mirror of
https://github.com/Automattic/wordpress-activitypub
synced 2024-10-18 14:23:31 +00:00
Add replies collection (#876)
* typo in phpdoc * add first draft for adding replies collections to posts and comments * refactoring * Fix php CodeSniffer violations * fix typo in php comment * add draft for testing replies * replies: test with own comment * fix basic test for replies collection * Restrict 'type' parameter for replies to 'post' or 'comment' in REST API * some cleanups * prefer ID over URL * rename to `reply_id` to make clear that it is not the WordPress comment_id * modularize retrieving of comment link via comment meta * fix phpcs * I think we should be more precise with this and maybe there are other fallbacks coming --------- Co-authored-by: Matthias Pfefferle <pfefferle@users.noreply.github.com>
This commit is contained in:
parent
d361a6954d
commit
7370e97b5a
12 changed files with 446 additions and 32 deletions
|
@ -39,7 +39,7 @@ require_once __DIR__ . '/includes/functions.php';
|
|||
\defined( 'ACTIVITYPUB_AUTHORIZED_FETCH' ) || \define( 'ACTIVITYPUB_AUTHORIZED_FETCH', false );
|
||||
\defined( 'ACTIVITYPUB_DISABLE_REWRITES' ) || \define( 'ACTIVITYPUB_DISABLE_REWRITES', false );
|
||||
\defined( 'ACTIVITYPUB_DISABLE_INCOMING_INTERACTIONS' ) || \define( 'ACTIVITYPUB_DISABLE_INCOMING_INTERACTIONS', false );
|
||||
// Disable reactions like `Like` and `Accounce` by default
|
||||
// Disable reactions like `Like` and `Announce` by default
|
||||
\defined( 'ACTIVITYPUB_DISABLE_REACTIONS' ) || \define( 'ACTIVITYPUB_DISABLE_REACTIONS', true );
|
||||
\defined( 'ACTIVITYPUB_DISABLE_OUTGOING_INTERACTIONS' ) || \define( 'ACTIVITYPUB_DISABLE_OUTGOING_INTERACTIONS', false );
|
||||
\defined( 'ACTIVITYPUB_SHARED_INBOX_FEATURE' ) || \define( 'ACTIVITYPUB_SHARED_INBOX_FEATURE', false );
|
||||
|
|
|
@ -90,6 +90,21 @@ class Activity extends Base_Object {
|
|||
*/
|
||||
protected $result;
|
||||
|
||||
/**
|
||||
* Identifies a Collection containing objects considered to be responses
|
||||
* to this object.
|
||||
* WordPress has a strong core system of approving replies. We only include
|
||||
* approved replies here.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-replies
|
||||
*
|
||||
* @var array
|
||||
* | ObjectType
|
||||
* | Link
|
||||
* | null
|
||||
*/
|
||||
protected $replies;
|
||||
|
||||
/**
|
||||
* An indirect object of the activity from which the
|
||||
* activity is directed.
|
||||
|
|
|
@ -340,6 +340,46 @@ class Comment {
|
|||
return $classes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the public comment id via the WordPress comments meta.
|
||||
*
|
||||
* @param int $wp_comment_id The internal WordPress comment ID.
|
||||
* @param bool $fallback Whether the code should fall back to `source_url` if `source_id` is not set.
|
||||
*
|
||||
* @return string|null The ActivityPub id/url of the comment.
|
||||
*/
|
||||
public static function get_source_id( $wp_comment_id, $fallback = true ) {
|
||||
$comment_meta = \get_comment_meta( $wp_comment_id );
|
||||
|
||||
if ( ! empty( $comment_meta['source_id'][0] ) ) {
|
||||
return $comment_meta['source_id'][0];
|
||||
} elseif ( ! empty( $comment_meta['source_url'][0] && $fallback ) ) {
|
||||
return $comment_meta['source_url'][0];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the public comment url via the WordPress comments meta.
|
||||
*
|
||||
* @param int $wp_comment_id The internal WordPress comment ID.
|
||||
* @param bool $fallback Whether the code should fall back to `source_id` if `source_url` is not set.
|
||||
*
|
||||
* @return string|null The ActivityPub id/url of the comment.
|
||||
*/
|
||||
public static function get_source_url( $wp_comment_id, $fallback = true ) {
|
||||
$comment_meta = \get_comment_meta( $wp_comment_id );
|
||||
|
||||
if ( ! empty( $comment_meta['source_url'][0] ) ) {
|
||||
return $comment_meta['source_url'][0];
|
||||
} elseif ( ! empty( $comment_meta['source_id'][0] && $fallback ) ) {
|
||||
return $comment_meta['source_id'][0];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Link remote comments to source url.
|
||||
*
|
||||
|
@ -353,15 +393,9 @@ class Comment {
|
|||
return $comment_link;
|
||||
}
|
||||
|
||||
$comment_meta = \get_comment_meta( $comment->comment_ID );
|
||||
$public_comment_link = self::get_source_url( $comment->comment_ID );
|
||||
|
||||
if ( ! empty( $comment_meta['source_url'][0] ) ) {
|
||||
return $comment_meta['source_url'][0];
|
||||
} elseif ( ! empty( $comment_meta['source_id'][0] ) ) {
|
||||
return $comment_meta['source_id'][0];
|
||||
}
|
||||
|
||||
return $comment_link;
|
||||
return $public_comment_link ?? $comment_link;
|
||||
}
|
||||
|
||||
|
||||
|
@ -374,13 +408,12 @@ class Comment {
|
|||
*/
|
||||
public static function generate_id( $comment ) {
|
||||
$comment = \get_comment( $comment );
|
||||
$comment_meta = \get_comment_meta( $comment->comment_ID );
|
||||
|
||||
// show external comment ID if it exists
|
||||
if ( ! empty( $comment_meta['source_id'][0] ) ) {
|
||||
return $comment_meta['source_id'][0];
|
||||
} elseif ( ! empty( $comment_meta['source_url'][0] ) ) {
|
||||
return $comment_meta['source_url'][0];
|
||||
$public_comment_link = self::get_source_id( $comment->comment_ID );
|
||||
|
||||
if ( $public_comment_link ) {
|
||||
return $public_comment_link;
|
||||
}
|
||||
|
||||
// generate URI based on comment ID
|
||||
|
|
|
@ -111,7 +111,7 @@ class Followers {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get a Follower by Actor indepenent from the User.
|
||||
* Get a Follower by Actor independent from the User.
|
||||
*
|
||||
* @param string $actor The Actor URL.
|
||||
*
|
||||
|
|
176
includes/collection/class-replies.php
Normal file
176
includes/collection/class-replies.php
Normal file
|
@ -0,0 +1,176 @@
|
|||
<?php
|
||||
namespace Activitypub\Collection;
|
||||
|
||||
use WP_Post;
|
||||
use WP_Comment;
|
||||
use WP_Error;
|
||||
|
||||
use Activitypub\Comment;
|
||||
|
||||
use function Activitypub\is_local_comment;
|
||||
use function Activitypub\get_rest_url_by_path;
|
||||
|
||||
/**
|
||||
* Class containing code for getting replies Collections and CollectionPages of posts and comments.
|
||||
*/
|
||||
class Replies {
|
||||
/**
|
||||
* Build base arguments for fetching the comments of either a WordPress post or comment.
|
||||
*
|
||||
* @param WP_Post|WP_Comment $wp_object
|
||||
*/
|
||||
private static function build_args( $wp_object ) {
|
||||
$args = array(
|
||||
'status' => 'approve',
|
||||
'orderby' => 'comment_date_gmt',
|
||||
'order' => 'ASC',
|
||||
);
|
||||
|
||||
if ( $wp_object instanceof WP_Post ) {
|
||||
$args['parent'] = 0; // TODO: maybe this is unnecessary.
|
||||
$args['post_id'] = $wp_object->ID;
|
||||
} elseif ( $wp_object instanceof WP_Comment ) {
|
||||
$args['parent'] = $wp_object->comment_ID;
|
||||
} else {
|
||||
return new WP_Error();
|
||||
}
|
||||
|
||||
return $args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds pagination args comments query.
|
||||
*
|
||||
* @param array $args Query args built by self::build_args.
|
||||
* @param int $page The current pagination page.
|
||||
* @param int $comments_per_page The number of comments per page.
|
||||
*/
|
||||
private static function add_pagination_args( $args, $page, $comments_per_page ) {
|
||||
$args['number'] = $comments_per_page;
|
||||
|
||||
$offset = intval( $page ) * $comments_per_page;
|
||||
$args['offset'] = $offset;
|
||||
|
||||
return $args;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the replies collections ID.
|
||||
*
|
||||
* @param WP_Post|WP_Comment $wp_object
|
||||
*
|
||||
* @return string The rest URL of the replies collection.
|
||||
*/
|
||||
private static function get_id( $wp_object ) {
|
||||
if ( $wp_object instanceof WP_Post ) {
|
||||
return get_rest_url_by_path( sprintf( 'posts/%d/replies', $wp_object->ID ) );
|
||||
} elseif ( $wp_object instanceof WP_Comment ) {
|
||||
return get_rest_url_by_path( sprintf( 'comments/%d/replies', $wp_object->comment_ID ) );
|
||||
} else {
|
||||
return new WP_Error();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the replies collection.
|
||||
*
|
||||
* @param WP_Post|WP_Comment $wp_object
|
||||
* @param int $page
|
||||
*
|
||||
* @return array An associative array containing the replies collection without JSON-LD context.
|
||||
*/
|
||||
public static function get_collection( $wp_object ) {
|
||||
$id = self::get_id( $wp_object );
|
||||
|
||||
if ( ! $id ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$replies = array(
|
||||
'id' => $id,
|
||||
'type' => 'Collection',
|
||||
);
|
||||
|
||||
$replies['first'] = self::get_collection_page( $wp_object, 0, $replies['id'] );
|
||||
|
||||
return $replies;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ActivityPub ID's from a list of comments.
|
||||
*
|
||||
* It takes only federated/non-local comments into account, others also do not have an
|
||||
* ActivityPub ID available.
|
||||
*
|
||||
* @param WP_Comment[] $comments The comments to retrieve the ActivityPub ids from.
|
||||
*
|
||||
* @return string[] A list of the ActivityPub ID's.
|
||||
*/
|
||||
private static function get_reply_ids( $comments ) {
|
||||
$comment_ids = array();
|
||||
// Only add external comments from the fediverse.
|
||||
// Maybe use the Comment class more and the function is_local_comment etc.
|
||||
foreach ( $comments as $comment ) {
|
||||
if ( is_local_comment( $comment ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$public_comment_id = Comment::get_source_id( $comment->comment_ID );
|
||||
if ( $public_comment_id ) {
|
||||
$comment_ids[] = $public_comment_id;
|
||||
}
|
||||
}
|
||||
return $comment_ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a replies collection page as an associative array.
|
||||
*
|
||||
* @link https://www.w3.org/TR/activitystreams-vocabulary/#dfn-collectionpage
|
||||
*
|
||||
* @param WP_Post|WP_Comment $wp_object The post of comment the replies are for.
|
||||
* @param int $page The current pagination page.
|
||||
* @param string $part_of The collection id/url the returned CollectionPage belongs to.
|
||||
*
|
||||
* @return array A CollectionPage as an associative array.
|
||||
*/
|
||||
public static function get_collection_page( $wp_object, $page, $part_of = null ) {
|
||||
// Build initial arguments for fetching approved comments.
|
||||
$args = self::build_args( $wp_object );
|
||||
|
||||
// Retrieve the partOf if not already given.
|
||||
$part_of = $part_of ?? self::get_id( $wp_object );
|
||||
|
||||
// If the collection page does not exist.
|
||||
if ( is_wp_error( $args ) || is_wp_error( $part_of ) ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Get to total replies count.
|
||||
$total_replies = \get_comments( array_merge( $args, array( 'count' => true ) ) );
|
||||
|
||||
// Modify query args to retrieve paginated results.
|
||||
$comments_per_page = \get_option( 'comments_per_page' );
|
||||
|
||||
// Fetch internal and external comments for current page.
|
||||
$comments = get_comments( self::add_pagination_args( $args, $page, $comments_per_page ) );
|
||||
|
||||
// Get the ActivityPub ID's of the comments, without out local-only comments.
|
||||
$comment_ids = self::get_reply_ids( $comments );
|
||||
|
||||
// Build the associative CollectionPage array.
|
||||
$collection_page = array(
|
||||
'id' => \add_query_arg( 'page', $page, $part_of ),
|
||||
'type' => 'CollectionPage',
|
||||
'partOf' => $part_of,
|
||||
'items' => $comment_ids,
|
||||
);
|
||||
|
||||
if ( $total_replies / $comments_per_page > $page + 1 ) {
|
||||
$collection_page['next'] = \add_query_arg( 'page', $page + 1, $part_of );
|
||||
}
|
||||
|
||||
return $collection_page;
|
||||
}
|
||||
}
|
|
@ -6,7 +6,10 @@ use WP_REST_Response;
|
|||
use Activitypub\Activity\Actor;
|
||||
use Activitypub\Activity\Base_Object;
|
||||
use Activitypub\Collection\Users as User_Collection;
|
||||
use Activitypub\Collection\Replies;
|
||||
|
||||
use Activitypub\Transformer\Factory;
|
||||
use WP_Error;
|
||||
|
||||
use function Activitypub\esc_hashtag;
|
||||
use function Activitypub\is_single_user;
|
||||
|
@ -69,6 +72,73 @@ class Collection {
|
|||
),
|
||||
)
|
||||
);
|
||||
|
||||
\register_rest_route(
|
||||
ACTIVITYPUB_REST_NAMESPACE,
|
||||
'/(?P<type>[\w\-\.]+)s/(?P<id>[\w\-\.]+)/replies',
|
||||
array(
|
||||
array(
|
||||
'methods' => WP_REST_Server::READABLE,
|
||||
'callback' => array( self::class, 'replies_get' ),
|
||||
'args' => self::request_parameters_for_replies(),
|
||||
'permission_callback' => '__return_true',
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The endpoint for replies collections
|
||||
*
|
||||
* @param WP_REST_Request $request The request object.
|
||||
*
|
||||
* @return WP_REST_Response The response object.
|
||||
*/
|
||||
public static function replies_get( $request ) {
|
||||
$type = $request->get_param( 'type' );
|
||||
|
||||
// Get the WordPress object of that "owns" the requested replies.
|
||||
switch ( $type ) {
|
||||
case 'comment':
|
||||
$wp_object = \get_comment( $request->get_param( 'id' ) );
|
||||
break;
|
||||
case 'post':
|
||||
default:
|
||||
$wp_object = \get_post( $request->get_param( 'id' ) );
|
||||
break;
|
||||
}
|
||||
|
||||
if ( ! isset( $wp_object ) || is_wp_error( $wp_object ) ) {
|
||||
return new WP_Error(
|
||||
'activitypub_replies_collection_does_not_exist',
|
||||
\sprintf(
|
||||
// translators: %s: The type (post, comment, etc.) for which no replies collection exists.
|
||||
\__( 'No reply collection exists for the type %s.', 'activitypub' ),
|
||||
$type
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$page = intval( $request->get_param( 'page' ) );
|
||||
|
||||
// If the request parameter page is present get the CollectionPage otherwise the replies collection.
|
||||
if ( isset( $page ) ) {
|
||||
$response = Replies::get_collection_page( $wp_object, $page );
|
||||
} else {
|
||||
$response = Replies::get_collection( $wp_object );
|
||||
}
|
||||
|
||||
if ( is_wp_error( $response ) ) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
// Add ActivityPub Context.
|
||||
$response = array_merge(
|
||||
array( '@context' => Base_Object::JSON_LD_CONTEXT ),
|
||||
$response
|
||||
);
|
||||
|
||||
return new WP_REST_Response( $response, 200 );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -225,4 +295,26 @@ class Collection {
|
|||
|
||||
return $params;
|
||||
}
|
||||
|
||||
/**
|
||||
* The supported parameters
|
||||
*
|
||||
* @return array list of parameters
|
||||
*/
|
||||
public static function request_parameters_for_replies() {
|
||||
$params = array();
|
||||
|
||||
$params['type'] = array(
|
||||
'required' => true,
|
||||
'type' => 'string',
|
||||
'enum' => array( 'post', 'comment' ),
|
||||
);
|
||||
|
||||
$params['id'] = array(
|
||||
'required' => true,
|
||||
'type' => 'string',
|
||||
);
|
||||
|
||||
return $params;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -75,13 +75,9 @@ class Comment {
|
|||
return $template;
|
||||
}
|
||||
|
||||
$comment_meta = \get_comment_meta( $comment_id );
|
||||
$resource = Comment_Utils::get_source_id( $comment_id );
|
||||
|
||||
if ( ! empty( $comment_meta['source_id'][0] ) ) {
|
||||
$resource = $comment_meta['source_id'][0];
|
||||
} elseif ( ! empty( $comment_meta['source_url'][0] ) ) {
|
||||
$resource = $comment_meta['source_url'][0];
|
||||
} else {
|
||||
if ( ! $resource ) {
|
||||
$resource = Comment_Utils::generate_id( $comment );
|
||||
}
|
||||
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
<?php
|
||||
namespace Activitypub\Transformer;
|
||||
|
||||
use WP_Error;
|
||||
use WP_Post;
|
||||
use WP_Comment;
|
||||
|
||||
use Activitypub\Activity\Activity;
|
||||
use Activitypub\Activity\Base_Object;
|
||||
use Activitypub\Collection\Replies;
|
||||
|
||||
|
||||
/**
|
||||
* WordPress Base Transformer
|
||||
|
@ -108,6 +109,16 @@ abstract class Base {
|
|||
return $activity;
|
||||
}
|
||||
|
||||
abstract protected function get_id();
|
||||
|
||||
/**
|
||||
* Get the replies Collection.
|
||||
*/
|
||||
public function get_replies() {
|
||||
$replies = Replies::get_collection( $this->wp_object, $this->get_id() );
|
||||
return $replies;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ID of the WordPress Object.
|
||||
*
|
||||
|
|
|
@ -134,13 +134,8 @@ class Comment extends Base {
|
|||
}
|
||||
|
||||
if ( $parent_comment ) {
|
||||
$comment_meta = \get_comment_meta( $parent_comment->comment_ID );
|
||||
|
||||
if ( ! empty( $comment_meta['source_id'][0] ) ) {
|
||||
$in_reply_to = $comment_meta['source_id'][0];
|
||||
} elseif ( ! empty( $comment_meta['source_url'][0] ) ) {
|
||||
$in_reply_to = $comment_meta['source_url'][0];
|
||||
} elseif ( ! empty( $parent_comment->user_id ) ) {
|
||||
$in_reply_to = Comment_Utils::get_source_id( $parent_comment->comment_ID );
|
||||
if ( ! $in_reply_to && ! empty( $parent_comment->user_id ) ) {
|
||||
$in_reply_to = Comment_Utils::generate_id( $parent_comment );
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -124,7 +124,7 @@ class Post extends Base {
|
|||
*
|
||||
* @return string The Posts ID.
|
||||
*/
|
||||
public function get_id() {
|
||||
protected function get_id() {
|
||||
return $this->get_url();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,62 @@
|
|||
<?php
|
||||
class Test_Activitypub_Comment extends WP_UnitTestCase {
|
||||
public function test_get_source_id_or_url() {
|
||||
$comment_id = wp_insert_comment(
|
||||
array(
|
||||
'comment_type' => 'comment id',
|
||||
'comment_content' => 'This is a comment id test',
|
||||
'comment_author_url' => 'https://example.com',
|
||||
'comment_author_email' => '',
|
||||
'comment_meta' => array(
|
||||
'protocol' => 'activitypub',
|
||||
'source_id' => 'https://example.com/id',
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
$this->assertEquals( 'https://example.com/id', \Activitypub\Comment::get_source_url( $comment_id ) );
|
||||
$this->assertEquals( 'https://example.com/id', \Activitypub\Comment::get_source_id( $comment_id ) );
|
||||
$this->assertEquals( 'https://example.com/id', \Activitypub\Comment::get_source_id( $comment_id, false ) );
|
||||
$this->assertEquals( null, \Activitypub\Comment::get_source_url( $comment_id, false ) );
|
||||
|
||||
$comment_id = wp_insert_comment(
|
||||
array(
|
||||
'comment_type' => 'comment url',
|
||||
'comment_content' => 'This is a comment url test',
|
||||
'comment_author_url' => 'https://example.com',
|
||||
'comment_author_email' => '',
|
||||
'comment_meta' => array(
|
||||
'protocol' => 'activitypub',
|
||||
'source_url' => 'https://example.com/url',
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
$this->assertEquals( 'https://example.com/url', \Activitypub\Comment::get_source_id( $comment_id ) );
|
||||
$this->assertEquals( 'https://example.com/url', \Activitypub\Comment::get_source_url( $comment_id ) );
|
||||
$this->assertEquals( 'https://example.com/url', \Activitypub\Comment::get_source_url( $comment_id, false ) );
|
||||
$this->assertEquals( null, \Activitypub\Comment::get_source_id( $comment_id, false ) );
|
||||
|
||||
$comment_id = wp_insert_comment(
|
||||
array(
|
||||
'comment_type' => 'comment url and id',
|
||||
'comment_content' => 'This is a comment url and id test',
|
||||
'comment_author_url' => 'https://example.com',
|
||||
'comment_author_email' => '',
|
||||
'comment_meta' => array(
|
||||
'protocol' => 'activitypub',
|
||||
'source_url' => 'https://example.com/url',
|
||||
'source_id' => 'https://example.com/id',
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
$this->assertEquals( 'https://example.com/id', \Activitypub\Comment::get_source_id( $comment_id ) );
|
||||
$this->assertEquals( 'https://example.com/id', \Activitypub\Comment::get_source_id( $comment_id, false ) );
|
||||
$this->assertEquals( 'https://example.com/url', \Activitypub\Comment::get_source_url( $comment_id ) );
|
||||
$this->assertEquals( 'https://example.com/url', \Activitypub\Comment::get_source_url( $comment_id, false ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider ability_to_federate_comment
|
||||
*/
|
||||
|
|
39
tests/test-class-activitypub-replies.php
Normal file
39
tests/test-class-activitypub-replies.php
Normal file
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
class Test_Activitypub_Replies extends WP_UnitTestCase {
|
||||
|
||||
public function test_replies_collection_of_post_with_federated_comments() {
|
||||
$post_id = \wp_insert_post(
|
||||
array(
|
||||
'post_author' => 1,
|
||||
'post_content' => 'test',
|
||||
)
|
||||
);
|
||||
|
||||
$source_id = 'https://example.instance/notes/123';
|
||||
|
||||
$comment = array(
|
||||
'user_id' => 1,
|
||||
'comment_type' => 'comment',
|
||||
'comment_content' => 'This is a comment.',
|
||||
'comment_author_url' => 'https://example.com',
|
||||
'comment_author_email' => '',
|
||||
'comment_meta' => array(
|
||||
'protocol' => 'activitypub',
|
||||
'source_id' => $source_id,
|
||||
),
|
||||
'comment_post_ID' => $post_id,
|
||||
);
|
||||
|
||||
$comment_id = wp_insert_comment( $comment );
|
||||
|
||||
wp_set_comment_status( $comment_id, 'hold' );
|
||||
$replies = Activitypub\Collection\Replies::get_collection( get_post( $post_id ) );
|
||||
$this->assertEquals( $replies['id'], sprintf( 'http://example.org/index.php?rest_route=/activitypub/1.0/posts/%d/replies', $post_id ) );
|
||||
$this->assertCount( 0, $replies['first']['items'] );
|
||||
|
||||
wp_set_comment_status( $comment_id, 'approve' );
|
||||
$replies = Activitypub\Collection\Replies::get_collection( get_post( $post_id ) );
|
||||
$this->assertCount( 1, $replies['first']['items'] );
|
||||
$this->assertEquals( $replies['first']['items'][0], $source_id );
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue