From 493b8ffad5925539511718c616e7ab0a1ddcbdba Mon Sep 17 00:00:00 2001 From: Matthias Pfefferle Date: Mon, 3 Jul 2023 17:59:42 +0200 Subject: [PATCH] use transformer instead of post-model --- includes/activity/class-activity.php | 38 ++ includes/activity/class-base-object.php | 15 + includes/class-activity-dispatcher.php | 96 ++-- includes/class-activitypub.php | 1 + includes/class-admin.php | 2 - includes/class-scheduler.php | 8 +- includes/collection/class-followers.php | 2 +- includes/model/class-activity.php | 244 ---------- includes/model/class-user.php | 1 - includes/rest/class-inbox.php | 2 +- includes/rest/class-outbox.php | 20 +- includes/rest/class-users.php | 4 +- .../{model => transformer}/class-post.php | 420 ++++++------------ includes/transformer/class-wp-user.php | 76 ---- templates/author-json.php | 2 +- templates/blog-json.php | 2 +- templates/post-json.php | 4 +- ...-class-activitypub-activity-dispatcher.php | 10 +- tests/test-class-activitypub-activity.php | 7 +- tests/test-class-activitypub-post.php | 4 +- ...typub-rest-post-signature-verification.php | 14 +- 21 files changed, 282 insertions(+), 690 deletions(-) delete mode 100644 includes/model/class-activity.php rename includes/{model => transformer}/class-post.php (55%) delete mode 100644 includes/transformer/class-wp-user.php diff --git a/includes/activity/class-activity.php b/includes/activity/class-activity.php index 592bbc1..a1bd3c5 100644 --- a/includes/activity/class-activity.php +++ b/includes/activity/class-activity.php @@ -7,6 +7,8 @@ namespace Activitypub\Activity; +use Activitypub\Activity\Base_Object; + /** * \Activitypub\Activity\Activity implements the common * attributes of an Activity. @@ -162,4 +164,40 @@ class Activity extends Base_Object { * | null */ protected $instrument; + + /** + * Set the object and copy Object properties to the Activity. + * + * Any to, bto, cc, bcc, and audience properties specified on the object + * MUST be copied over to the new Create activity by the server. + * + * @see https://www.w3.org/TR/activitypub/#object-without-create + * + * @param \Activitypub\Activity\Base_Object $object + * + * @return void + */ + public function set_object( Base_Object $object ) { + parent::set_object( $object ); + + foreach ( array( 'to', 'bto', 'cc', 'bcc', 'audience' ) as $i ) { + $this->set( $i, $object->get( $i ) ); + } + + if ( $object->get_published() && ! $this->get_published() ) { + $this->set( 'published', $object->get_published() ); + } + + if ( $object->get_updated() && ! $this->get_updated() ) { + $this->set( 'updated', $object->get_updated() ); + } + + if ( $object->attributed_to() && ! $this->get_actor() ) { + $this->set( 'actor', $object->attributed_to() ); + } + + if ( $object->get_id() && ! $this->get_id() ) { + $this->set( 'id', $object->get_id() . '#activity' ); + } + } } diff --git a/includes/activity/class-base-object.php b/includes/activity/class-base-object.php index 4343782..151ebf1 100644 --- a/includes/activity/class-base-object.php +++ b/includes/activity/class-base-object.php @@ -604,6 +604,10 @@ class Base_Object { $value = call_user_func( array( $this, 'get_' . $key ) ); } + if ( is_object( $value ) ) { + $value = $value->to_array(); + } + // if value is still empty, ignore it for the array and continue. if ( isset( $value ) ) { $array[ snake_to_camel_case( $key ) ] = $value; @@ -625,4 +629,15 @@ class Base_Object { return $array; } + + /** + * Convert Object to JSON. + * + * @return string The JSON string. + */ + public function to_json() { + $array = $this->to_array(); + + return \wp_json_encode( $array ); + } } diff --git a/includes/class-activity-dispatcher.php b/includes/class-activity-dispatcher.php index c7862c0..2a5444a 100644 --- a/includes/class-activity-dispatcher.php +++ b/includes/class-activity-dispatcher.php @@ -1,10 +1,11 @@ from_post( $activitypub_post ); + $object = Post::transform( $post )->to_object(); - $user_id = $activitypub_post->get_user_id(); + $activity = new Activity(); + $activity->set_type( $type ); + $activity->set_object( $object ); + + $user_id = $post->post_author; $follower_inboxes = Followers::get_inboxes( $user_id ); - $mentioned_inboxes = Mention::get_inboxes( $activitypub_activity->get_cc() ); + $mentioned_inboxes = Mention::get_inboxes( $activity->get_cc() ); $inboxes = array_merge( $follower_inboxes, $mentioned_inboxes ); $inboxes = array_unique( $inboxes ); - foreach ( $inboxes as $inbox ) { - $activity = $activitypub_activity->to_json(); + $array = $activity->to_json(); - safe_remote_post( $inbox, $activity, $user_id ); + foreach ( $inboxes as $inbox ) { + safe_remote_post( $inbox, $array, $user_id ); + } + } + + /** + * Send Activities to followers and mentioned users. + * + * @param WP_Post $post The ActivityPub Post. + * @param string $type The Activity-Type. + * + * @return void + */ + public static function send_blog_activity( WP_Post $post, $type ) { + // check if a migration is needed before sending new posts + Migration::maybe_migrate(); + + $user = Users::get_by_id( Users::BLOG_USER_ID ); + + $object = Post::transform( $post )->to_object(); + $object->set_attributed_to( $user->get_url() ); + + $activity = new Activity(); + $activity->set_type( $type ); + $activity->set_object( $object ); + + $follower_inboxes = Followers::get_inboxes( $user->get__id() ); + $mentioned_inboxes = Mention::get_inboxes( $activity->get_cc() ); + + $inboxes = array_merge( $follower_inboxes, $mentioned_inboxes ); + $inboxes = array_unique( $inboxes ); + + $array = $activity->to_array(); + + foreach ( $inboxes as $inbox ) { + safe_remote_post( $inbox, $array, $user_id ); } } } diff --git a/includes/class-activitypub.php b/includes/class-activitypub.php index 3b4d68a..507da58 100644 --- a/includes/class-activitypub.php +++ b/includes/class-activitypub.php @@ -2,6 +2,7 @@ namespace Activitypub; use Activitypub\Signature; +use Activitypub\Collection\Users; /** * ActivityPub Class diff --git a/includes/class-admin.php b/includes/class-admin.php index 1a94aa3..647805a 100644 --- a/includes/class-admin.php +++ b/includes/class-admin.php @@ -1,8 +1,6 @@ 'as:manuallyApprovesFollowers', - 'PropertyValue' => 'schema:PropertyValue', - 'schema' => 'http://schema.org#', - 'pt' => 'https://joinpeertube.org/ns#', - 'toot' => 'http://joinmastodon.org/ns#', - 'value' => 'schema:value', - 'Hashtag' => 'as:Hashtag', - 'featured' => array( - '@id' => 'toot:featured', - '@type' => '@id', - ), - 'featuredTags' => array( - '@id' => 'toot:featuredTags', - '@type' => '@id', - ), - ), - ); - - /** - * The JSON-LD context. - * - * @var array - */ - private $context = self::CONTEXT; - - /** - * The published date. - * - * @var string - */ - private $published = ''; - - /** - * The Activity-ID. - * - * @var string - */ - private $id = ''; - - /** - * The Activity-Type. - * - * @var string - */ - private $type = 'Create'; - - /** - * The Activity-Actor. - * - * @var string - */ - private $actor = ''; - - /** - * The Audience. - * - * @var array - */ - private $to = array( 'https://www.w3.org/ns/activitystreams#Public' ); - - /** - * The CC. - * - * @var array - */ - private $cc = array(); - - /** - * The Activity-Object. - * - * @var array - */ - private $object = null; - - /** - * The Class-Constructor. - * - * @param string $type The Activity-Type. - * @param boolean $context The JSON-LD context. - */ - public function __construct( $type = 'Create', $context = true ) { - if ( true !== $context ) { - $this->context = null; - } - - $this->type = \ucfirst( $type ); - $this->published = \gmdate( 'Y-m-d\TH:i:s\Z', \time() ); - } - - /** - * Magic Getter/Setter - * - * @param string $method The method name. - * @param string $params The method params. - * - * @return mixed The value. - */ - public function __call( $method, $params ) { - $var = \strtolower( \substr( $method, 4 ) ); - - if ( \strncasecmp( $method, 'get', 3 ) === 0 ) { - return $this->$var; - } - - if ( \strncasecmp( $method, 'set', 3 ) === 0 ) { - $this->$var = $params[0]; - } - - if ( \strncasecmp( $method, 'add', 3 ) === 0 ) { - if ( ! is_array( $this->$var ) ) { - $this->$var = $params[0]; - } - - if ( is_array( $params[0] ) ) { - $this->$var = array_merge( $this->$var, $params[0] ); - } else { - array_push( $this->$var, $params[0] ); - } - - $this->$var = array_unique( $this->$var ); - } - } - - /** - * Convert from a Post-Object. - * - * @param Post $post The Post-Object. - * - * @return void - */ - public function from_post( Post $post ) { - $this->object = $post->to_array(); - - if ( isset( $object['published'] ) ) { - $this->published = $object['published']; - } - - $path = sprintf( 'users/%d/followers', intval( $post->get_post_author() ) ); - $this->add_to( get_rest_url_by_path( $path ) ); - - if ( isset( $this->object['attributedTo'] ) ) { - $this->actor = $this->object['attributedTo']; - } - - foreach ( $post->get_tags() as $tag ) { - if ( 'Mention' === $tag['type'] ) { - $this->add_cc( $tag['href'] ); - } - } - - $type = \strtolower( $this->type ); - - if ( isset( $this->object['id'] ) ) { - $this->id = add_query_arg( 'activity', $type, $this->object['id'] ); - } - } - - public function from_comment( $object ) { - - } - - public function to_comment() { - - } - - public function from_remote_array( $array ) { - - } - - /** - * Convert to an Array. - * - * @return array The Array. - */ - public function to_array() { - $array = array_filter( \get_object_vars( $this ) ); - - if ( $this->context ) { - $array = array( '@context' => $this->context ) + $array; - } - - unset( $array['context'] ); - - return $array; - } - - /** - * Convert to JSON - * - * @return string The JSON. - */ - public function to_json() { - return \wp_json_encode( $this->to_array(), \JSON_HEX_TAG | \JSON_HEX_AMP | \JSON_HEX_QUOT ); - } - - /** - * Convert to a Simple Array. - * - * @return string The array. - */ - public function to_simple_array() { - $activity = array( - '@context' => $this->context, - 'type' => $this->type, - 'actor' => $this->actor, - 'object' => $this->object, - 'to' => $this->to, - 'cc' => $this->cc, - ); - - if ( $this->id ) { - $activity['id'] = $this->id; - } - - return $activity; - } - - /** - * Convert to a Simple JSON. - * - * @return string The JSON. - */ - public function to_simple_json() { - return \wp_json_encode( $this->to_simple_array(), \JSON_HEX_TAG | \JSON_HEX_AMP | \JSON_HEX_QUOT ); - } -} diff --git a/includes/model/class-user.php b/includes/model/class-user.php index c66e3d8..d641497 100644 --- a/includes/model/class-user.php +++ b/includes/model/class-user.php @@ -4,7 +4,6 @@ namespace Activitypub\Model; use WP_Query; use WP_Error; use Activitypub\Signature; -use Activitypub\Model\User; use Activitypub\Collection\Users; use Activitypub\Activity\Actor; diff --git a/includes/rest/class-inbox.php b/includes/rest/class-inbox.php index eee740c..4f0c3c3 100644 --- a/includes/rest/class-inbox.php +++ b/includes/rest/class-inbox.php @@ -5,7 +5,7 @@ use WP_Error; use WP_REST_Server; use WP_REST_Response; use Activitypub\Collection\Users; -use Activitypub\Model\Activity; +use Activitypub\Activity\Activity; use function Activitypub\get_context; use function Activitypub\url_to_authorid; diff --git a/includes/rest/class-outbox.php b/includes/rest/class-outbox.php index 3df982f..91af46d 100644 --- a/includes/rest/class-outbox.php +++ b/includes/rest/class-outbox.php @@ -5,9 +5,9 @@ use stdClass; use WP_Error; use WP_REST_Server; use WP_REST_Response; +use Activitypub\Activity\Activity; use Activitypub\Collection\Users; -use Activitypub\Model\Post; -use Activitypub\Model\Activity; +use Activitypub\Transformer\Post; use function Activitypub\get_context; use function Activitypub\get_rest_url_by_path; @@ -73,9 +73,9 @@ class Outbox { $json->{'@context'} = get_context(); $json->id = \home_url( \add_query_arg( null, null ) ); $json->generator = 'http://wordpress.org/?v=' . \get_bloginfo_rss( 'version' ); - $json->actor = $user->get_id(); + //$json->actor = $user->get_id(); $json->type = 'OrderedCollectionPage'; - $json->partOf = get_rest_url_by_path( sprintf( 'users/%d/outbox', $user->get__id() ) ); // phpcs:ignore + $json->partOf = get_rest_url_by_path( sprintf( 'users/%d/outbox', $user_id ) ); // phpcs:ignore $json->totalItems = 0; // phpcs:ignore // phpcs:ignore @@ -97,18 +97,20 @@ class Outbox { $posts = \get_posts( array( 'posts_per_page' => 10, - 'author' => $user->get__id(), + 'author' => $user_id, 'offset' => ( $page - 1 ) * 10, 'post_type' => $post_types, ) ); foreach ( $posts as $post ) { - $activitypub_post = new Post( $post ); - $activitypub_activity = new Activity( 'Create', false ); + $post = Post::transform( $post )->to_object(); + $activity = new Activity(); + $activity->set_type( 'Create' ); + $activity->set_context( null ); + $activity->set_object( $post ); - $activitypub_activity->from_post( $activitypub_post ); - $json->orderedItems[] = $activitypub_activity->to_array(); // phpcs:ignore + $json->orderedItems[] = $activity->to_array(); // phpcs:ignore } } diff --git a/includes/rest/class-users.php b/includes/rest/class-users.php index dac7792..2017036 100644 --- a/includes/rest/class-users.php +++ b/includes/rest/class-users.php @@ -4,8 +4,8 @@ namespace Activitypub\Rest; use WP_Error; use WP_REST_Server; use WP_REST_Response; -use \Activitypub\Model\Activity; -use Activitypub\Collection\User_Collection; +use \Activitypub\Activity\Activity; +use Activitypub\Collection\Users as User_Collection; use function Activitypub\is_activitypub_request; diff --git a/includes/model/class-post.php b/includes/transformer/class-post.php similarity index 55% rename from includes/model/class-post.php rename to includes/transformer/class-post.php index 1aa862a..ca35949 100644 --- a/includes/model/class-post.php +++ b/includes/transformer/class-post.php @@ -1,84 +1,37 @@ array( 'href' => array(), 'title' => array(), @@ -126,185 +79,70 @@ class Post { ); /** - * List of audience + * Static function to Transform a WP_Post Object. * - * Also used for visibility + * This helps to chain the output of the Transformer. * - * @var array - */ - private $to = array( 'https://www.w3.org/ns/activitystreams#Public' ); - - /** - * List of audience - * - * Also used for visibility - * - * @var array - */ - private $cc = array(); - - /** - * Constructor - * - * @param WP_Post $post - * @param int $post_author - */ - public function __construct( $post, $post_author = null ) { - $this->post = \get_post( $post ); - - if ( $post_author ) { - $this->post_author = $post_author; - } else { - $this->post_author = $this->post->post_author; - } - - $path = sprintf( 'users/%d/followers', intval( $this->get_post_author() ) ); - $this->add_to( get_rest_url_by_path( $path ) ); - } - - /** - * Magic function to implement getter and setter - * - * @param string $method - * @param string $params + * @param WP_Post $wp_post The WP_Post object * * @return void */ - public function __call( $method, $params ) { - $var = \strtolower( \substr( $method, 4 ) ); - - if ( \strncasecmp( $method, 'get', 3 ) === 0 ) { - if ( empty( $this->$var ) && ! empty( $this->post->$var ) ) { - return $this->post->$var; - } - return $this->$var; - } - - if ( \strncasecmp( $method, 'set', 3 ) === 0 ) { - $this->$var = $params[0]; - } - - if ( \strncasecmp( $method, 'add', 3 ) === 0 ) { - if ( ! is_array( $this->$var ) ) { - $this->$var = $params[0]; - } - - if ( is_array( $params[0] ) ) { - $this->$var = array_merge( $this->$var, $params[0] ); - } else { - array_push( $this->$var, $params[0] ); - } - - $this->$var = array_unique( $this->$var ); - } + public static function transform( WP_Post $wp_post ) { + return new self( $wp_post ); } /** - * Returns the User ID. * - * @return int the User ID. + * + * @param WP_Post $wp_post */ - public function get_user_id() { - return apply_filters( 'activitypub_post_user_id', $this->get_post_author(), $this->post ); + public function __construct( WP_Post $wp_post ) { + $this->wp_post = $wp_post; } /** - * Converts this Object into an Array. + * Transforms the WP_Post object to an ActivityPub Object * - * @return array the array representation of a Post. + * @see \Activitypub\Activity\Base_Object + * + * @return \Activitypub\Activity\Base_Object The ActivityPub Object */ - public function to_array() { - $post = $this->post; + public function to_object() { + $wp_post = $this->wp_post; + $object = new Base_Object(); - $array = array( - 'id' => $this->get_id(), - 'url' => $this->get_url(), - 'type' => $this->get_object_type(), - 'published' => \gmdate( 'Y-m-d\TH:i:s\Z', \strtotime( $post->post_date_gmt ) ), - 'attributedTo' => $this->get_actor(), - 'summary' => $this->get_summary(), - 'inReplyTo' => null, - 'content' => $this->get_content(), - 'contentMap' => array( + $object->set_id( \esc_url( \get_permalink( $wp_post->ID ) ) ); + $object->set_url( \esc_url( \get_permalink( $wp_post->ID ) ) ); + $object->set_type( $this->get_object_type() ); + $object->set_published( \gmdate( 'Y-m-d\TH:i:s\Z', \strtotime( $wp_post->post_date_gmt ) ) ); + $object->attributed_to( Users::get_by_id( $wp_post->post_author )->get_url() ); + $object->set_content( $this->get_content() ); + $object->set_content_map( + array( \strstr( \get_locale(), '_', true ) => $this->get_content(), - ), - 'to' => $this->get_to(), - 'cc' => $this->get_cc(), - 'attachment' => $this->get_attachments(), - 'tag' => $this->get_tags(), + ) ); + $path = sprintf( 'users/%d/followers', intval( $wp_post->post_author ) ); - return \apply_filters( 'activitypub_post', $array, $this->post ); + $object->set_to( + array( + 'https://www.w3.org/ns/activitystreams#Public', + get_rest_url_by_path( $path ), + ) + ); + $object->set_cc( $this->get_cc() ); + $object->set_attachment( $this->get_attachments() ); + $object->set_tag( $this->get_tags() ); + + return $object; } /** - * Returns the Actor of this Object. + * Generates all Image Attachments for a Post. * - * @return string The URL of the Actor. + * @return array The Image Attachments. */ - public function get_actor() { - $user = Users::get_by_id( $this->get_user_id() ); - - return $user->get_url(); - } - - /** - * Converts this Object into a JSON String - * - * @return string - */ - public function to_json() { - return \wp_json_encode( $this->to_array(), \JSON_HEX_TAG | \JSON_HEX_AMP | \JSON_HEX_QUOT ); - } - - /** - * Returns the URL of an Activity Object - * - * @return string - */ - public function get_url() { - if ( $this->url ) { - return $this->url; - } - - $post = $this->post; - - if ( 'trash' === get_post_status( $post ) ) { - $permalink = \get_post_meta( $post->ID, 'activitypub_canonical_url', true ); - } else { - $permalink = \get_permalink( $post ); - } - - $this->url = $permalink; - - return $permalink; - } - - /** - * Returns the ID of an Activity Object - * - * @return string - */ - public function get_id() { - if ( $this->id ) { - return $this->id; - } - - $this->id = $this->get_url(); - - return $this->id; - } - - /** - * Returns a list of Image Attachments - * - * @return array - */ - public function get_attachments() { - if ( $this->attachments ) { - return $this->attachments; - } - + protected function get_attachments() { $max_images = intval( \apply_filters( 'activitypub_max_image_attachments', \get_option( 'activitypub_max_image_attachments', ACTIVITYPUB_MAX_IMAGE_ATTACHMENTS ) ) ); $images = array(); @@ -314,7 +152,7 @@ class Post { return $images; } - $id = $this->post->ID; + $id = $this->wp_post->ID; $image_ids = array(); @@ -393,7 +231,7 @@ class Post { * * @return array|false Array of image data, or boolean false if no image is available. */ - public function get_image( $id, $image_size = 'full' ) { + protected function get_image( $id, $image_size = 'full' ) { /** * Hook into the image retrieval process. Before image retrieval. * @@ -416,64 +254,22 @@ class Post { } /** - * Returns a list of Tags, used in the Post + * Returns the ActivityStreams 2.0 Object-Type for a Post based on the + * settings and the Post-Type. * - * @return array - */ - public function get_tags() { - if ( $this->tags ) { - return $this->tags; - } - - $tags = array(); - - $post_tags = \get_the_tags( $this->post->ID ); - if ( $post_tags ) { - foreach ( $post_tags as $post_tag ) { - $tag = array( - 'type' => 'Hashtag', - 'href' => \get_tag_link( $post_tag->term_id ), - 'name' => '#' . $post_tag->slug, - ); - $tags[] = $tag; - } - } - - $mentions = apply_filters( 'activitypub_extract_mentions', array(), $this->post->post_content, $this ); - if ( $mentions ) { - foreach ( $mentions as $mention => $url ) { - $tag = array( - 'type' => 'Mention', - 'href' => $url, - 'name' => $mention, - ); - $tags[] = $tag; - } - } - - $this->tags = $tags; - - return $tags; - } - - /** - * Returns the as2 object-type for a given post + * @see https://www.w3.org/TR/activitystreams-vocabulary/#activity-types * - * @return string the object-type + * @return string The Object-Type. */ - public function get_object_type() { - if ( $this->object_type ) { - return $this->object_type; - } - + protected function get_object_type() { if ( 'wordpress-post-format' !== \get_option( 'activitypub_object_type', 'note' ) ) { return \ucfirst( \get_option( 'activitypub_object_type', 'note' ) ); } - $post_type = \get_post_type( $this->post ); + $post_type = \get_post_type( $this->wp_post ); switch ( $post_type ) { case 'post': - $post_format = \get_post_format( $this->post ); + $post_format = \get_post_format( $this->wp_post ); switch ( $post_format ) { case 'aside': case 'status': @@ -519,25 +315,78 @@ class Post { break; } - $this->object_type = $object_type; - return $object_type; } + /** + * Returns a list of Mentions, used in the Post. + * + * @see https://docs.joinmastodon.org/spec/activitypub/#Mention + * + * @return array The list of Mentions. + */ + protected function get_cc() { + $cc = array(); + + $mentions = $this->get_mentions(); + if ( $mentions ) { + foreach ( $mentions as $mention => $url ) { + $cc[] = $url; + } + } + + return $cc; + } + + /** + * Returns a list of Tags, used in the Post. + * + * This includes Hash-Tags and Mentions. + * + * @return array The list of Tags. + */ + protected function get_tags() { + $tags = array(); + + $post_tags = \get_the_tags( $this->wp_post->ID ); + if ( $post_tags ) { + foreach ( $post_tags as $post_tag ) { + $tag = array( + 'type' => 'Hashtag', + 'href' => esc_url( \get_tag_link( $post_tag->term_id ) ), + 'name' => '#' . \esc_attr( $post_tag->slug ), + ); + $tags[] = $tag; + } + } + + $mentions = $this->get_mentions(); + if ( $mentions ) { + foreach ( $mentions as $mention => $url ) { + $tag = array( + 'type' => 'Mention', + 'href' => \esc_url( $url ), + 'name' => \esc_html( $mention ), + ); + $tags[] = $tag; + } + } + + return $tags; + } + /** * Returns the content for the ActivityPub Item. * - * @return string the content + * The content will be generated based on the user settings. + * + * @return string The content. */ - public function get_content() { + protected function get_content() { global $post; - if ( $this->content ) { - return $this->content; - } - // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited - $post = $this->post; + $post = $this->wp_post; $content = $this->get_post_content_template(); // Fill in the shortcodes. @@ -553,17 +402,15 @@ class Post { $content = \apply_filters( 'activitypub_the_content', $content, $post ); $content = \html_entity_decode( $content, \ENT_QUOTES, 'UTF-8' ); - $this->content = $content; - return $content; } /** * Gets the template to use to generate the content of the activitypub item. * - * @return string the template + * @return string The Template. */ - public function get_post_content_template() { + protected function get_post_content_template() { if ( 'excerpt' === \get_option( 'activitypub_post_content_type', 'content' ) ) { return "[ap_excerpt]\n\n[ap_permalink type=\"html\"]"; } @@ -578,4 +425,13 @@ class Post { return \get_option( 'activitypub_custom_post_content', ACTIVITYPUB_CUSTOM_POST_CONTENT ); } + + /** + * Helper function to get the @-Mentions from the post content. + * + * @return array The list of @-Mentions. + */ + protected function get_mentions() { + return apply_filters( 'activitypub_extract_mentions', array(), $this->wp_post->post_content, $this->wp_post ); + } } diff --git a/includes/transformer/class-wp-user.php b/includes/transformer/class-wp-user.php deleted file mode 100644 index 083b119..0000000 --- a/includes/transformer/class-wp-user.php +++ /dev/null @@ -1,76 +0,0 @@ -wp_user = $wp_user; - } - - public function to_user() { - $wp_user = $this->wp_user; - if ( - is_user_disabled( $user->ID ) || - ! get_user_by( 'id', $user->ID ) - ) { - return new WP_Error( - 'activitypub_user_not_found', - \__( 'User not found', 'activitypub' ), - array( 'status' => 404 ) - ); - } - - $user = new User(); - - $user->setwp_user->ID( \esc_url( \get_author_posts_url( $wp_user->ID ) ) ); - $user->set_url( \esc_url( \get_author_posts_url( $wp_user->ID ) ) ); - $user->set_summary( $this->get_summary() ); - $user->set_name( \esc_attr( $wp_user->display_name ) ); - $user->set_preferred_username( \esc_attr( $wp_user->login ) ); - - $user->set_icon( $this->get_icon() ); - $user->set_image( $this->get_image() ); - - return $user; - } - - public function get_summary() { - $description = get_user_meta( $this->wp_user->ID, 'activitypub_user_description', true ); - if ( empty( $description ) ) { - $description = $this->wp_user->description; - } - return \wpautop( \wp_kses( $description, 'default' ) ); - } - - public function get_icon() { - $icon = \esc_url( - \get_avatar_url( - $this->wp_user->ID, - array( 'size' => 120 ) - ) - ); - - return array( - 'type' => 'Image', - 'url' => $icon, - ); - } - - public function get_image() { - if ( \has_header_image() ) { - $image = \esc_url( \get_header_image() ); - return array( - 'type' => 'Image', - 'url' => $image, - ); - } - - return null; - } -} diff --git a/templates/author-json.php b/templates/author-json.php index 6c5f8ad..70fb43b 100644 --- a/templates/author-json.php +++ b/templates/author-json.php @@ -2,7 +2,7 @@ $user = \Activitypub\Collection\Users::get_by_id( \get_the_author_meta( 'ID' ) ); $user->set_context( - \Activitypub\Model\Activity::CONTEXT + \Activitypub\Activity\Activity::CONTEXT ); /* diff --git a/templates/blog-json.php b/templates/blog-json.php index 635e7d5..7ce6a27 100644 --- a/templates/blog-json.php +++ b/templates/blog-json.php @@ -2,7 +2,7 @@ $user = new \Activitypub\Model\Blog_User(); $user->set_context( - \Activitypub\Model\Activity::CONTEXT + \Activitypub\Activity\Activity::CONTEXT ); /* diff --git a/templates/post-json.php b/templates/post-json.php index 4c597d6..89467c4 100644 --- a/templates/post-json.php +++ b/templates/post-json.php @@ -2,8 +2,8 @@ // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited $post = \get_post(); -$activitypub_post = new \Activitypub\Model\Post( $post ); -$json = \array_merge( array( '@context' => \Activitypub\get_context() ), $activitypub_post->to_array() ); +$object = new \Activitypub\Transformer\Post( $post ); +$json = \array_merge( array( '@context' => \Activitypub\get_context() ), $object->to_object()->to_array() ); // filter output $json = \apply_filters( 'activitypub_json_post_array', $json ); diff --git a/tests/test-class-activitypub-activity-dispatcher.php b/tests/test-class-activitypub-activity-dispatcher.php index 61f8c2b..f028798 100644 --- a/tests/test-class-activitypub-activity-dispatcher.php +++ b/tests/test-class-activitypub-activity-dispatcher.php @@ -34,10 +34,7 @@ class Test_Activitypub_Activity_Dispatcher extends ActivityPub_TestCase_Cache_HT $pre_http_request = new MockAction(); add_filter( 'pre_http_request', array( $pre_http_request, 'filter' ), 10, 3 ); - $activitypub_post = new \Activitypub\Model\Post( $post ); - \Activitypub\Activity_Dispatcher::send_create_activity( $activitypub_post ); - - $this->assertNotEmpty( $activitypub_post->get_content() ); + \Activitypub\Activity_Dispatcher::send_user_activity( get_post( $post ), 'Create' ); $this->assertSame( 2, $pre_http_request->get_call_count() ); $all_args = $pre_http_request->get_args(); @@ -77,10 +74,7 @@ class Test_Activitypub_Activity_Dispatcher extends ActivityPub_TestCase_Cache_HT $pre_http_request = new MockAction(); add_filter( 'pre_http_request', array( $pre_http_request, 'filter' ), 10, 3 ); - $activitypub_post = new \Activitypub\Model\Post( $post ); - \Activitypub\Activity_Dispatcher::send_create_activity( $activitypub_post ); - - $this->assertNotEmpty( $activitypub_post->get_content() ); + \Activitypub\Activity_Dispatcher::send_user_activity( get_post( $post ), 'Create' ); $this->assertSame( 1, $pre_http_request->get_call_count() ); $all_args = $pre_http_request->get_args(); diff --git a/tests/test-class-activitypub-activity.php b/tests/test-class-activitypub-activity.php index 8262f6c..b25545c 100644 --- a/tests/test-class-activitypub-activity.php +++ b/tests/test-class-activitypub-activity.php @@ -17,10 +17,11 @@ class Test_Activitypub_Activity extends WP_UnitTestCase { 10 ); - $activitypub_post = new \Activitypub\Model\Post( $post ); + $activitypub_post = \Activitypub\Transformer\Post::transform( get_post( $post ) )->to_object(); - $activitypub_activity = new \Activitypub\Model\Activity( 'Create' ); - $activitypub_activity->from_post( $activitypub_post ); + $activitypub_activity = new \Activitypub\Activity\Activity(); + $activitypub_activity->set_type( 'Create' ); + $activitypub_activity->set_object( $activitypub_post ); $this->assertContains( \Activitypub\get_rest_url_by_path( 'users/1/followers' ), $activitypub_activity->get_to() ); $this->assertContains( 'https://example.com/alex', $activitypub_activity->get_cc() ); diff --git a/tests/test-class-activitypub-post.php b/tests/test-class-activitypub-post.php index 4f1c74e..e995afa 100644 --- a/tests/test-class-activitypub-post.php +++ b/tests/test-class-activitypub-post.php @@ -10,13 +10,13 @@ class Test_Activitypub_Post extends WP_UnitTestCase { $permalink = \get_permalink( $post ); - $activitypub_post = new \Activitypub\Model\Post( $post ); + $activitypub_post = \Activitypub\Transformer\Post::transform( get_post( $post ) )->to_object(); $this->assertEquals( $permalink, $activitypub_post->get_id() ); \wp_trash_post( $post ); - $activitypub_post = new \Activitypub\Model\Post( $post ); + $activitypub_post = \Activitypub\Transformer\Post::transform( get_post( $post ) )->to_object(); $this->assertEquals( $permalink, $activitypub_post->get_id() ); } diff --git a/tests/test-class-activitypub-rest-post-signature-verification.php b/tests/test-class-activitypub-rest-post-signature-verification.php index f39927d..97f78f9 100644 --- a/tests/test-class-activitypub-rest-post-signature-verification.php +++ b/tests/test-class-activitypub-rest-post-signature-verification.php @@ -10,9 +10,10 @@ class Test_Activitypub_Signature_Verification extends WP_UnitTestCase { ) ); $remote_actor = \get_author_posts_url( 2 ); - $activitypub_post = new \Activitypub\Model\Post( $post ); - $activitypub_activity = new Activitypub\Model\Activity( 'Create' ); - $activitypub_activity->from_post( $activitypub_post ); + $activitypub_post = \Activitypub\Transformer\Post::transform( get_post( $post ) )->to_object(); + $activitypub_activity = new Activitypub\Activity\Activity( 'Create' ); + $activitypub_activity->set_type( 'Create' ); + $activitypub_activity->set_object( $activitypub_post ); $activitypub_activity->add_cc( $remote_actor ); $activity = $activitypub_activity->to_json(); @@ -81,9 +82,10 @@ class Test_Activitypub_Signature_Verification extends WP_UnitTestCase { ); $remote_actor = \get_author_posts_url( 2 ); $remote_actor_inbox = Activitypub\get_rest_url_by_path( '/inbox' ); - $activitypub_post = new \Activitypub\Model\Post( $post ); - $activitypub_activity = new Activitypub\Model\Activity( 'Create' ); - $activitypub_activity->from_post( $activitypub_post ); + $activitypub_post = \Activitypub\Transformer\Post::transform( \get_post( $post ) )->to_object(); + $activitypub_activity = new Activitypub\Activity\Activity(); + $activitypub_activity->set_type( 'Create' ); + $activitypub_activity->set_object( $activitypub_post ); $activitypub_activity->add_cc( $remote_actor_inbox ); $activity = $activitypub_activity->to_json();