decouple the adding/removing of follow relationships from adding/removing followers
Some checks are pending
PHP_CodeSniffer / phpcs (push) Waiting to run
Unit Testing / phpunit (5.6, 6.2) (push) Waiting to run
Unit Testing / phpunit (7.0) (push) Waiting to run
Unit Testing / phpunit (7.2) (push) Waiting to run
Unit Testing / phpunit (7.3) (push) Waiting to run
Unit Testing / phpunit (7.4) (push) Waiting to run
Unit Testing / phpunit (8.0) (push) Waiting to run
Unit Testing / phpunit (8.1) (push) Waiting to run
Unit Testing / phpunit (8.2) (push) Waiting to run
Unit Testing / phpunit (latest) (push) Waiting to run
Some checks are pending
PHP_CodeSniffer / phpcs (push) Waiting to run
Unit Testing / phpunit (5.6, 6.2) (push) Waiting to run
Unit Testing / phpunit (7.0) (push) Waiting to run
Unit Testing / phpunit (7.2) (push) Waiting to run
Unit Testing / phpunit (7.3) (push) Waiting to run
Unit Testing / phpunit (7.4) (push) Waiting to run
Unit Testing / phpunit (8.0) (push) Waiting to run
Unit Testing / phpunit (8.1) (push) Waiting to run
Unit Testing / phpunit (8.2) (push) Waiting to run
Unit Testing / phpunit (latest) (push) Waiting to run
also use post_content, and post_content_filtered to store the followers json object and inbox fix phpcs remove commented out code
This commit is contained in:
parent
32e08d7f68
commit
32acc511b1
8 changed files with 121 additions and 123 deletions
|
@ -572,7 +572,7 @@ class Base_Object {
|
|||
/**
|
||||
* Convert JSON input to an array.
|
||||
*
|
||||
* @return string The object array.
|
||||
* @param string The object array.
|
||||
*
|
||||
* @return \Activitypub\Activity\Base_Object An Object built from the JSON string.
|
||||
*/
|
||||
|
|
|
@ -444,18 +444,6 @@ class Activitypub {
|
|||
)
|
||||
);
|
||||
|
||||
register_post_meta(
|
||||
Followers::POST_TYPE,
|
||||
'activitypub_actor_json',
|
||||
array(
|
||||
'type' => 'string',
|
||||
'single' => true,
|
||||
'sanitize_callback' => function ( $value ) {
|
||||
return sanitize_text_field( $value );
|
||||
},
|
||||
)
|
||||
);
|
||||
|
||||
do_action( 'activitypub_after_register_post_type' );
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,9 @@ class Followers {
|
|||
const CACHE_KEY_INBOXES = 'follower_inboxes_%s';
|
||||
|
||||
/**
|
||||
* Add new Follower
|
||||
* Add new Follower.
|
||||
*
|
||||
* This does not add the follow relationship. It is added when the Accept respone is sent.
|
||||
*
|
||||
* @param int $user_id The ID of the WordPress User
|
||||
* @param string $actor The Actor URL
|
||||
|
@ -49,6 +51,16 @@ class Followers {
|
|||
return $follower_id;
|
||||
}
|
||||
|
||||
return $follower;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the follow relationship.
|
||||
*
|
||||
* @param int|string $user_id The internal id of the target WordPress user that gets followed.
|
||||
* @param int|string $follower_id The internal id of the follower actor.
|
||||
*/
|
||||
public static function add_follow_relationship( $user_id, $follower_id ) {
|
||||
$post_meta = get_post_meta( $follower_id, 'activitypub_user_id' );
|
||||
|
||||
// phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict
|
||||
|
@ -59,8 +71,6 @@ class Followers {
|
|||
// Reset the cached inboxes for the followed user
|
||||
wp_cache_delete( sprintf( self::CACHE_KEY_INBOXES, $user_id ), 'activitypub' );
|
||||
}
|
||||
|
||||
return $follower;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -71,7 +81,7 @@ class Followers {
|
|||
*
|
||||
* @return bool|WP_Error True on success, false or WP_Error on failure.
|
||||
*/
|
||||
public static function remove_follower( $user_id, $actor ) {
|
||||
public static function remove_follow_relationship( $user_id, $actor ) {
|
||||
wp_cache_delete( sprintf( self::CACHE_KEY_INBOXES, $user_id ), 'activitypub' );
|
||||
|
||||
$follower = self::get_follower( $user_id, $actor );
|
||||
|
@ -114,6 +124,18 @@ class Followers {
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a Follower by the internal ID.
|
||||
*
|
||||
* @param int $user_id The post ID of the WordPress Follower custom post type post.
|
||||
*
|
||||
* @return \Activitypub\Model\Follower|null The Follower object or null
|
||||
*/
|
||||
public static function get_follower_by_id( $follower_id ) {
|
||||
$post = get_post( $follower_id );
|
||||
return Follower::init_from_cpt( $post );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a Follower by Actor indepenent from the User.
|
||||
*
|
||||
|
@ -181,7 +203,7 @@ class Followers {
|
|||
),
|
||||
),
|
||||
);
|
||||
|
||||
// TODO: handle follower with empty post_content or inbox which is saved in post_content_filtered
|
||||
$args = wp_parse_args( $args, $defaults );
|
||||
$query = new WP_Query( $args );
|
||||
$total = $query->found_posts;
|
||||
|
@ -204,18 +226,6 @@ class Followers {
|
|||
public static function get_all_followers() {
|
||||
$args = array(
|
||||
'nopaging' => true,
|
||||
// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
|
||||
'meta_query' => array(
|
||||
'relation' => 'AND',
|
||||
array(
|
||||
'key' => 'activitypub_inbox',
|
||||
'compare' => 'EXISTS',
|
||||
),
|
||||
array(
|
||||
'key' => 'activitypub_actor_json',
|
||||
'compare' => 'EXISTS',
|
||||
),
|
||||
),
|
||||
);
|
||||
return self::get_followers( null, null, null, $args );
|
||||
}
|
||||
|
@ -239,18 +249,10 @@ class Followers {
|
|||
'key' => 'activitypub_user_id',
|
||||
'value' => $user_id,
|
||||
),
|
||||
array(
|
||||
'key' => 'activitypub_inbox',
|
||||
'compare' => 'EXISTS',
|
||||
),
|
||||
array(
|
||||
'key' => 'activitypub_actor_json',
|
||||
'compare' => 'EXISTS',
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
// TODO: handle follower with empty post_content or inbox which is saved in post_content_filtered
|
||||
return $query->found_posts;
|
||||
}
|
||||
|
||||
|
@ -263,6 +265,7 @@ class Followers {
|
|||
*/
|
||||
public static function get_inboxes( $user_id ) {
|
||||
$cache_key = sprintf( self::CACHE_KEY_INBOXES, $user_id );
|
||||
// TODO: enable caching of the inboxes: this is only for debugging purpose.
|
||||
// $inboxes = wp_cache_get( $cache_key, 'activitypub' );
|
||||
|
||||
// if ( $inboxes ) {
|
||||
|
@ -278,19 +281,10 @@ class Followers {
|
|||
// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
|
||||
'meta_query' => array(
|
||||
'relation' => 'AND',
|
||||
array(
|
||||
'key' => 'activitypub_inbox',
|
||||
'compare' => 'EXISTS',
|
||||
),
|
||||
array(
|
||||
'key' => 'activitypub_user_id',
|
||||
'value' => $user_id,
|
||||
),
|
||||
array(
|
||||
'key' => 'activitypub_inbox',
|
||||
'value' => '',
|
||||
'compare' => '!=',
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
@ -301,42 +295,16 @@ class Followers {
|
|||
return array();
|
||||
}
|
||||
|
||||
$user = Users::get_by_id( $user_id );
|
||||
|
||||
if ( $user->get_manually_approved_followers() ) {
|
||||
$accepted_follow_requests_query = new WP_Query(
|
||||
array(
|
||||
'nopaging' => true,
|
||||
'post_type' => 'ap_follow_request',
|
||||
'fields' => 'id=>parent',
|
||||
'post_status' => 'publish',
|
||||
'post_parent__in' => $follower_ids,
|
||||
// phpcs:ign ore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
|
||||
'meta_query' => array(
|
||||
'relation' => 'AND',
|
||||
array(
|
||||
'key' => 'activitypub_user_id',
|
||||
'value' => $user_id,
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
$accepted_follow_requests = $accepted_follow_requests_query->get_posts();
|
||||
|
||||
global $wpdb;
|
||||
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
|
||||
$results = $wpdb->get_col(
|
||||
$inboxes = $wpdb->get_col(
|
||||
$wpdb->prepare(
|
||||
"SELECT DISTINCT meta_value FROM {$wpdb->postmeta}
|
||||
WHERE post_id IN (" . implode( ', ', array_fill( 0, count( $follower_ids ), '%d' ) ) . ")
|
||||
AND meta_key = 'activitypub_inbox'
|
||||
AND meta_value IS NOT NULL",
|
||||
"SELECT DISTINCT post_content_filtered FROM {$wpdb->posts}
|
||||
WHERE ID IN (" . implode( ', ', array_fill( 0, count( $follower_ids ), '%d' ) ) . ')',
|
||||
$follower_ids
|
||||
)
|
||||
);
|
||||
|
||||
$inboxes = array_filter( $results );
|
||||
wp_cache_set( $cache_key, $inboxes, 'activitypub' );
|
||||
|
||||
return $inboxes;
|
||||
|
|
|
@ -75,17 +75,17 @@ class Follow {
|
|||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function send_follow_response( $user, $follower, $object, $type ) {
|
||||
public static function send_follow_response( $user, $inbox, $object, $type ) {
|
||||
// send activity
|
||||
$activity = new Activity();
|
||||
$activity->set_type( $type );
|
||||
$activity->set_object( $object );
|
||||
$activity->set_actor( $user->get_id() );
|
||||
$activity->set_to( $follower->get_id() );
|
||||
$activity->set_id( $user->get_id() . '#accept-' . \preg_replace( '~^https?://~', '', $follower->get_id() ) . '-' . \time() );
|
||||
$activity->set_to( $object['actor'] );
|
||||
$activity->set_id( $user->get_id() . '#accept-' . \preg_replace( '~^https?://~', '', $object['actor'] ) . '-' . \time() );
|
||||
|
||||
$activity = $activity->to_json();
|
||||
|
||||
Http::post( $follower->get_shared_inbox(), $activity, $user->get__id() );
|
||||
Http::post( $inbox, $activity, $user->get__id() );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,8 @@ class Undo {
|
|||
*
|
||||
* @param array $activity The JSON "Undo" Activity
|
||||
* @param int $user_id The ID of the ID of the WordPress User
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function handle_undo( $activity ) {
|
||||
if (
|
||||
|
|
|
@ -3,11 +3,11 @@ namespace Activitypub\Model;
|
|||
|
||||
use WP_Error;
|
||||
|
||||
use Activitypub\Activity\Activity;
|
||||
use Activitypub\Activity\Base_Object;
|
||||
use Activitypub\Collection\Followers;
|
||||
use Activitypub\Collection\Users;
|
||||
use Activitypub\Model\Follower;
|
||||
use Activitypub\Http;
|
||||
|
||||
|
||||
/**
|
||||
* ActivityPub Follow Class
|
||||
|
@ -21,6 +21,8 @@ use Activitypub\Http;
|
|||
*/
|
||||
class Follow_Request extends Base_Object {
|
||||
const FOLLOW_REQUEST_POST_TYPE = 'ap_follow_request';
|
||||
const FOLLOW_REQUEST_STATUS_APPROVED = 'approved';
|
||||
const FOLLOW_REQUEST_STATUS_REJECTED = 'rejected';
|
||||
|
||||
/**
|
||||
* Stores theinternal WordPress post id of the post of type ap_follow_request
|
||||
|
@ -113,6 +115,13 @@ class Follow_Request extends Base_Object {
|
|||
return $follow_request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the internal ID of the follower who issues the follow request.
|
||||
*/
|
||||
private function get_follower_id() {
|
||||
return wp_get_post_parent_id( $this->get__id() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the current Follower-Object.
|
||||
*
|
||||
|
@ -155,34 +164,62 @@ class Follow_Request extends Base_Object {
|
|||
}
|
||||
|
||||
/**
|
||||
* Reject the follow request
|
||||
* Get the URL/URI of the Follower that issued the follow request.
|
||||
*
|
||||
* @return string The url/uri of the follower.
|
||||
*/
|
||||
public function reject() {
|
||||
private function get_follower_actor() {
|
||||
$follower_id = wp_get_post_parent_id( $this->get__id() );
|
||||
$follower = Follower::init_from_cpt( get_post( $follower_id ) );
|
||||
return $follower->get_id();
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the status of the follow request.
|
||||
*
|
||||
* @param string $status The new status of the follow request.
|
||||
*/
|
||||
private function save_follow_request_status( $status ) {
|
||||
wp_update_post(
|
||||
array(
|
||||
'ID' => $this->get__id(),
|
||||
'post_status' => 'rejected',
|
||||
'post_status' => $status,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reject the follow request.
|
||||
*/
|
||||
public function reject() {
|
||||
$user_id = get_post_meta( $this->get__id(), 'activitypub_user_id', true );
|
||||
$actor = $this->get_follower_actor();
|
||||
|
||||
Followers::remove_follow_relationship( $user_id, $actor );
|
||||
|
||||
$this->save_follow_request_status( self::FOLLOW_REQUEST_STATUS_REJECTED );
|
||||
|
||||
$this->send_response( 'Reject' );
|
||||
|
||||
$this->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Approve the follow request
|
||||
* Approve the follow request.
|
||||
*/
|
||||
public function approve() {
|
||||
wp_update_post(
|
||||
array(
|
||||
'ID' => $this->get__id(),
|
||||
'post_status' => 'approved',
|
||||
)
|
||||
);
|
||||
$user_id = get_post_meta( $this->get__id(), 'activitypub_user_id', true );
|
||||
$follower_id = $this->get_follower_id();
|
||||
|
||||
Followers::add_follow_relationship( $user_id, $follower_id );
|
||||
|
||||
$this->save_follow_request_status( self::FOLLOW_REQUEST_STATUS_APPROVED );
|
||||
|
||||
$this->send_response( 'Accept' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the follow request
|
||||
* Delete the follow request.
|
||||
*
|
||||
* This should only be called after it has been rejected.
|
||||
*/
|
||||
|
@ -197,18 +234,17 @@ class Follow_Request extends Base_Object {
|
|||
$user_id = get_post_meta( $this->get__id(), 'activitypub_user_id', true );
|
||||
$user = Users::get_by_id( $user_id );
|
||||
|
||||
$follower_id = wp_get_post_parent_id( $this->get__id() );
|
||||
$follower = Follower::init_from_cpt( get_post( $follower_id ) );
|
||||
$follower_id = $this->get_follower_id();
|
||||
|
||||
$actor = $follower->get_id();
|
||||
$follower_inbox = get_post_field( 'post_content_filtered', $follower_id );
|
||||
|
||||
$object = array(
|
||||
// Reconstruct the follow_object.
|
||||
$follow_object = array(
|
||||
'id' => $this->get_id(),
|
||||
'type' => $this->get_type(),
|
||||
'actor' => $actor,
|
||||
'object' => $user,
|
||||
);
|
||||
|
||||
do_action( 'activitypub_send_follow_response', $user, $follower, $object, $type );
|
||||
do_action( 'activitypub_send_follow_response', $user, $follower_inbox, $follow_object, $type );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -178,7 +178,9 @@ class Follower extends Actor {
|
|||
'post_name' => esc_url_raw( $this->get_id() ),
|
||||
'post_excerpt' => sanitize_text_field( wp_kses( $this->get_summary(), 'user_description' ) ),
|
||||
'post_status' => 'publish',
|
||||
'meta_input' => $this->get_post_meta_input(),
|
||||
'post_content' => $this->to_json(),
|
||||
'post_mime_type' => 'application/json',
|
||||
'post_content_filtered' => $this->get_shared_inbox(),
|
||||
);
|
||||
|
||||
$post_id = wp_insert_post( $args );
|
||||
|
@ -202,7 +204,7 @@ class Follower extends Actor {
|
|||
* Beware that this os deleting a Follower for ALL users!!!
|
||||
*
|
||||
* To delete only the User connection (unfollow)
|
||||
* @see \Activitypub\Rest\Followers::remove_follower()
|
||||
* @see \Activitypub\Rest\Followers::remove_follow_relationship()
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
@ -210,18 +212,20 @@ class Follower extends Actor {
|
|||
wp_delete_post( $this->_id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the post meta.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function get_post_meta_input() {
|
||||
$meta_input = array();
|
||||
$meta_input['activitypub_inbox'] = $this->get_shared_inbox();
|
||||
$meta_input['activitypub_actor_json'] = $this->to_json();
|
||||
// /**
|
||||
// * Update the post meta.
|
||||
// *
|
||||
// * @return void
|
||||
// */
|
||||
// protected function get_post_meta_input() {
|
||||
// $meta_input = array();
|
||||
// // TODO: migrations - moved to post_content
|
||||
// $meta_input['activitypub_inbox'] = $this->get_shared_inbox();
|
||||
// // TODO: migrations - moved to post_content_filtered
|
||||
// $meta_input['activitypub_actor_json'] = $this->to_json();
|
||||
|
||||
return $meta_input;
|
||||
}
|
||||
// return $meta_input;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Get the icon.
|
||||
|
|
|
@ -185,7 +185,7 @@ class Test_Activitypub_Followers extends WP_UnitTestCase {
|
|||
$follower2 = \Activitypub\Collection\Followers::get_follower( 2, 'https://example.com/author/jon' );
|
||||
$this->assertEquals( 'https://example.com/author/jon', $follower2->get_url() );
|
||||
|
||||
\Activitypub\Collection\Followers::remove_follower( 1, 'https://example.com/author/jon' );
|
||||
\Activitypub\Collection\Followers::remove_follow_relationship( 1, 'https://example.com/author/jon' );
|
||||
|
||||
$follower = \Activitypub\Collection\Followers::get_follower( 1, 'https://example.com/author/jon' );
|
||||
$this->assertNull( $follower );
|
||||
|
|
Loading…
Reference in a new issue