From bc5f5871897919211b87adda6fb762148cdd831f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Menrath?= Date: Tue, 4 Feb 2025 22:46:44 +0100 Subject: [PATCH 01/18] Fix outbox not using object types other than Base_Object --- CHANGELOG.md | 1 + includes/activity/class-activity.php | 8 +++++--- includes/class-activitypub.php | 22 ++++++++++++++++++++++ includes/class-dispatcher.php | 7 ++++--- includes/collection/class-outbox.php | 8 ++++++++ readme.txt | 1 + 6 files changed, 41 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a9d51495f..4f717eff8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Negotiation of ActivityPub requests for custom post types when queried by the ActivityPub ID. * Avoid PHP warnings when using Debug mode and when the `actor` is not set. * No longer creates Outbox items when importing content/users. +* Outbox is now capable of sending other object types that are not Base_Object. ## [5.0.0] - 2025-02-03 diff --git a/includes/activity/class-activity.php b/includes/activity/class-activity.php index 3fa8669f1..80b297038 100644 --- a/includes/activity/class-activity.php +++ b/includes/activity/class-activity.php @@ -151,14 +151,16 @@ class Activity extends Base_Object { * @see https://www.w3.org/TR/activitypub/#object-without-create * * @param array|string|Base_Object|Link|null $data Activity object. + * @param string|null $object_class The full class path to a child of Base_Object. * * @return void */ - public function set_object( $data ) { + public function set_object( $data, $object_class = null ) { // Convert array to object. if ( is_array( $data ) ) { - // Check if the item is an Activity or an Object. - if ( is_activity( $data ) ) { + if ( $object_class && class_exists( $object_class ) ) { + $data = $object_class::init_from_array( $data ); + } elseif ( is_activity( $data ) ) { // Check if the item is an Activity or an Object. $data = self::init_from_array( $data ); } elseif ( is_actor( $data ) ) { $data = Actor::init_from_array( $data ); diff --git a/includes/class-activitypub.php b/includes/class-activitypub.php index c3aa89616..47be3d704 100644 --- a/includes/class-activitypub.php +++ b/includes/class-activitypub.php @@ -594,6 +594,28 @@ private static function register_post_types() { ) ); + /** + * Register ActivityPub object class for Outbox items. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#object-types + */ + \register_post_meta( + Outbox::POST_TYPE, + '_activitypub_object_class', + array( + 'type' => 'string', + 'description' => 'The full class name of the object class', + 'single' => true, + 'sanitize_callback' => function ( $value ) { + if ( class_exists( $value ) ) { + return $value; + } + + return \Activitypub\Activity\Base_Object::class; + }, + ) + ); + \register_post_meta( Outbox::POST_TYPE, '_activitypub_activity_actor', diff --git a/includes/class-dispatcher.php b/includes/class-dispatcher.php index b98d867a7..547a34061 100644 --- a/includes/class-dispatcher.php +++ b/includes/class-dispatcher.php @@ -60,12 +60,13 @@ public static function process_outbox( $id ) { break; } - $type = \get_post_meta( $outbox_item->ID, '_activitypub_activity_type', true ); - $activity = new Activity(); + $type = \get_post_meta( $outbox_item->ID, '_activitypub_activity_type', true ); + $object_class = \get_post_meta( $outbox_item->ID, '_activitypub_object_class', true ); + $activity = new Activity(); $activity->set_type( $type ); $activity->set_id( $outbox_item->guid ); // Pre-fill the Activity with data (for example cc and to). - $activity->set_object( \json_decode( $outbox_item->post_content, true ) ); + $activity->set_object( \json_decode( $outbox_item->post_content, true ), $object_class ); $activity->set_actor( Actors::get_by_id( $outbox_item->post_author )->get_id() ); // Use simple Object (only ID-URI) for Like and Announce. diff --git a/includes/collection/class-outbox.php b/includes/collection/class-outbox.php index b0d762455..f194768ad 100644 --- a/includes/collection/class-outbox.php +++ b/includes/collection/class-outbox.php @@ -7,6 +7,8 @@ namespace Activitypub\Collection; +use Activitypub\Activity\Base_Object; + /** * ActivityPub Outbox Collection * @@ -52,6 +54,12 @@ public static function add( $activity_object, $activity_type, $user_id, $content ), ); + $object_class = get_class( $activity_object ); + + if ( Base_Object::class !== $object_class ) { + $outbox_item['meta_input']['_activitypub_object_class'] = str_replace( '\\', '\\\\', $object_class ); + } + $has_kses = false !== \has_filter( 'content_save_pre', 'wp_filter_post_kses' ); if ( $has_kses ) { // Prevent KSES from corrupting JSON in post_content. diff --git a/readme.txt b/readme.txt index 96ed9180b..f3e8c07e7 100644 --- a/readme.txt +++ b/readme.txt @@ -140,6 +140,7 @@ For reasons of data protection, it is not possible to see the followers of other * Fixed: Negotiation of ActivityPub requests for custom post types when queried by the ActivityPub ID. * Fixed: Avoid PHP warnings when using Debug mode and when the `actor` is not set. * Fixed: No longer creates Outbox items when importing content/users. +* Fixed: Outbox is now capable of sending other object types that are not Base_Object. = 5.0.0 = From 700272aac3a74f2b1594171e62a256c535239ad8 Mon Sep 17 00:00:00 2001 From: Konstantin Obenland Date: Wed, 5 Feb 2025 11:16:20 +0100 Subject: [PATCH 02/18] Update Following endpoint to extend WP_REST_Controller (#1267) * Move file * Update following endpoint to extend WP_REST_Controller * Inherit from Actor --------- Co-authored-by: Matthias Pfefferle --- activitypub.php | 2 +- includes/rest/class-following-controller.php | 209 ++++++++++++++++++ includes/rest/class-following.php | 139 ------------ .../rest/class-test-following-controller.php | 134 +++++++++++ 4 files changed, 344 insertions(+), 140 deletions(-) create mode 100644 includes/rest/class-following-controller.php delete mode 100644 includes/rest/class-following.php create mode 100644 tests/includes/rest/class-test-following-controller.php diff --git a/activitypub.php b/activitypub.php index 4ef9f260d..5a61475de 100644 --- a/activitypub.php +++ b/activitypub.php @@ -41,13 +41,13 @@ function rest_init() { Rest\Inbox::init(); Rest\Followers::init(); - Rest\Following::init(); Rest\Comment::init(); Rest\Server::init(); Rest\Collection::init(); Rest\Post::init(); ( new Rest\Actors_Controller() )->register_routes(); ( new Rest\Application_Controller() )->register_routes(); + ( new Rest\Following_Controller() )->register_routes(); ( new Rest\Interaction_Controller() )->register_routes(); ( new Rest\Outbox_Controller() )->register_routes(); ( new Rest\Webfinger_Controller() )->register_routes(); diff --git a/includes/rest/class-following-controller.php b/includes/rest/class-following-controller.php new file mode 100644 index 000000000..f44c2e67e --- /dev/null +++ b/includes/rest/class-following-controller.php @@ -0,0 +1,209 @@ +namespace, + '/' . $this->rest_base . '/following', + array( + 'args' => array( + 'user_id' => array( + 'description' => 'The ID or username of the actor.', + 'type' => 'string', + 'required' => true, + 'pattern' => '[\w\-\.]+', + ), + ), + array( + 'methods' => \WP_REST_Server::READABLE, + 'callback' => array( $this, 'get_items' ), + 'permission_callback' => array( 'Activitypub\Rest\Server', 'verify_signature' ), + 'args' => array( + 'page' => array( + 'description' => 'Current page of the collection.', + 'type' => 'integer', + 'default' => 1, + 'minimum' => 1, + ), + ), + ), + 'schema' => array( $this, 'get_public_item_schema' ), + ) + ); + } + + /** + * Retrieves following list. + * + * @param \WP_REST_Request $request Full details about the request. + * @return \WP_REST_Response|\WP_Error Response object on success, or WP_Error object on failure. + */ + public function get_items( $request ) { + $user_id = $request->get_param( 'user_id' ); + $user = Actors::get_by_various( $user_id ); + + if ( \is_wp_error( $user ) ) { + return $user; + } + + /** + * Action triggered prior to the ActivityPub profile being created and sent to the client. + */ + \do_action( 'activitypub_rest_following_pre' ); + + $response = array( + '@context' => \Activitypub\get_context(), + 'id' => get_rest_url_by_path( \sprintf( 'actors/%d/following', $user->get__id() ) ), + 'generator' => 'https://wordpress.org/?v=' . get_masked_wp_version(), + 'actor' => $user->get_id(), + 'type' => 'OrderedCollectionPage', + 'partOf' => get_rest_url_by_path( \sprintf( 'actors/%d/following', $user->get__id() ) ), + ); + + /** + * Filter the list of following urls. + * + * @param array $items The array of following urls. + * @param \Activitypub\Model\User $user The user object. + */ + $items = \apply_filters( 'activitypub_rest_following', array(), $user ); + + $response['totalItems'] = \is_countable( $items ) ? \count( $items ) : 0; + $response['orderedItems'] = $items; + $response['first'] = $response['partOf']; + + $response = \rest_ensure_response( $response ); + $response->header( 'Content-Type', 'application/activity+json; charset=' . \get_option( 'blog_charset' ) ); + + return $response; + } + + /** + * Add the Blog Authors to the following list of the Blog Actor + * if Blog not in single mode. + * + * @param array $follow_list The array of following urls. + * @param \Activitypub\Model\User $user The user object. + * + * @return array The array of following urls. + */ + public static function default_following( $follow_list, $user ) { + if ( 0 !== $user->get__id() || is_single_user() ) { + return $follow_list; + } + + $users = Actors::get_collection(); + + foreach ( $users as $user ) { + $follow_list[] = $user->get_id(); + } + + return $follow_list; + } + + /** + * Retrieves the following schema, conforming to JSON Schema. + * + * @return array Item schema data. + */ + public function get_item_schema() { + if ( $this->schema ) { + return $this->add_additional_fields_schema( $this->schema ); + } + + $this->schema = array( + '$schema' => 'http://json-schema.org/draft-04/schema#', + 'title' => 'following', + 'type' => 'object', + 'properties' => array( + '@context' => array( + 'description' => 'The JSON-LD context for the response.', + 'type' => array( 'array', 'object' ), + 'readonly' => true, + ), + 'id' => array( + 'description' => 'The unique identifier for the following collection.', + 'type' => 'string', + 'format' => 'uri', + 'readonly' => true, + ), + 'generator' => array( + 'description' => 'The generator of the following collection.', + 'type' => 'string', + 'format' => 'uri', + 'readonly' => true, + ), + 'actor' => array( + 'description' => 'The actor who owns the following collection.', + 'type' => 'string', + 'format' => 'uri', + 'readonly' => true, + ), + 'type' => array( + 'description' => 'The type of the following collection.', + 'type' => 'string', + 'enum' => array( 'OrderedCollectionPage' ), + 'readonly' => true, + ), + 'totalItems' => array( + 'description' => 'The total number of items in the following collection.', + 'type' => 'integer', + 'readonly' => true, + ), + 'partOf' => array( + 'description' => 'The collection this page is part of.', + 'type' => 'string', + 'format' => 'uri', + 'readonly' => true, + ), + 'orderedItems' => array( + 'description' => 'The items in the following collection.', + 'type' => 'array', + 'items' => array( + 'type' => 'string', + 'format' => 'uri', + ), + 'readonly' => true, + ), + 'first' => array( + 'description' => 'The first page in the collection.', + 'type' => 'string', + 'format' => 'uri', + 'readonly' => true, + ), + ), + ); + + return $this->add_additional_fields_schema( $this->schema ); + } +} diff --git a/includes/rest/class-following.php b/includes/rest/class-following.php deleted file mode 100644 index 79cba650f..000000000 --- a/includes/rest/class-following.php +++ /dev/null @@ -1,139 +0,0 @@ -[\w\-\.]+)/following', - array( - array( - 'methods' => \WP_REST_Server::READABLE, - 'callback' => array( self::class, 'get' ), - 'args' => self::request_parameters(), - 'permission_callback' => array( 'Activitypub\Rest\Server', 'verify_signature' ), - ), - ) - ); - } - - /** - * Handle GET request - * - * @param \WP_REST_Request $request The request object. - * - * @return WP_REST_Response|\WP_Error The response object or WP_Error. - */ - public static function get( $request ) { - $user_id = $request->get_param( 'user_id' ); - $user = Actors::get_by_various( $user_id ); - - if ( is_wp_error( $user ) ) { - return $user; - } - - /** - * Action triggered prior to the ActivityPub profile being created and sent to the client. - */ - \do_action( 'activitypub_rest_following_pre' ); - - $json = new \stdClass(); - - $json->{'@context'} = \Activitypub\get_context(); - - // phpcs:disable WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase - $json->id = get_rest_url_by_path( sprintf( 'actors/%d/following', $user->get__id() ) ); - $json->generator = 'http://wordpress.org/?v=' . get_masked_wp_version(); - $json->actor = $user->get_id(); - $json->type = 'OrderedCollectionPage'; - $json->partOf = get_rest_url_by_path( sprintf( 'actors/%d/following', $user->get__id() ) ); - - /** - * Filter the list of following urls. - * - * @param array $items The array of following urls. - * @param \Activitypub\Model\User $user The user object. - */ - $items = apply_filters( 'activitypub_rest_following', array(), $user ); - - $json->totalItems = is_countable( $items ) ? count( $items ) : 0; - $json->orderedItems = $items; - $json->first = $json->partOf; - // phpcs:enable WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase - - $rest_response = new WP_REST_Response( $json, 200 ); - $rest_response->header( 'Content-Type', 'application/activity+json; charset=' . get_option( 'blog_charset' ) ); - - return $rest_response; - } - - /** - * The supported parameters. - * - * @return array List of parameters. - */ - public static function request_parameters() { - $params = array(); - - $params['page'] = array( - 'type' => 'integer', - ); - - return $params; - } - - /** - * Add the Blog Authors to the following list of the Blog Actor - * if Blog not in single mode. - * - * @param array $follow_list The array of following urls. - * @param \Activitypub\Model\User $user The user object. - * - * @return array The array of following urls. - */ - public static function default_following( $follow_list, $user ) { - if ( 0 !== $user->get__id() || is_single_user() ) { - return $follow_list; - } - - $users = Actors::get_collection(); - - foreach ( $users as $user ) { - $follow_list[] = $user->get_id(); - } - - return $follow_list; - } -} diff --git a/tests/includes/rest/class-test-following-controller.php b/tests/includes/rest/class-test-following-controller.php new file mode 100644 index 000000000..a48baea16 --- /dev/null +++ b/tests/includes/rest/class-test-following-controller.php @@ -0,0 +1,134 @@ +get_id(); + } + + return $follow_list; + } + ); + } + + /** + * Tear down. + */ + public function tear_down() { + remove_all_filters( 'activitypub_rest_following' ); + + parent::tear_down(); + } + /** + * Test route registration. + * + * @covers ::register_routes + */ + public function test_register_routes() { + $routes = rest_get_server()->get_routes(); + $this->assertArrayHasKey( '/' . ACTIVITYPUB_REST_NAMESPACE . '/(?:users|actors)\/(?P[\w\-\.]+)/following', $routes ); + } + + /** + * Test schema. + * + * @covers ::get_item_schema + */ + public function test_get_item_schema() { + $request = new \WP_REST_Request( 'OPTIONS', '/' . ACTIVITYPUB_REST_NAMESPACE . '/actors/0/following' ); + $response = rest_get_server()->dispatch( $request )->get_data(); + + $this->assertArrayHasKey( 'schema', $response ); + $schema = $response['schema']; + + // Test specific property types. + $this->assertEquals( array( 'array', 'object' ), $schema['properties']['@context']['type'] ); + $this->assertEquals( 'string', $schema['properties']['id']['type'] ); + $this->assertEquals( 'uri', $schema['properties']['id']['format'] ); + $this->assertEquals( array( 'OrderedCollectionPage' ), $schema['properties']['type']['enum'] ); + $this->assertEquals( 'array', $schema['properties']['orderedItems']['type'] ); + $this->assertEquals( 'string', $schema['properties']['orderedItems']['items']['type'] ); + $this->assertEquals( 'string', $schema['properties']['generator']['type'] ); + $this->assertEquals( 'uri', $schema['properties']['generator']['format'] ); + } + + /** + * Test get_items response. + * + * @covers ::get_items + */ + public function test_get_items() { + $request = new \WP_REST_Request( 'GET', '/' . ACTIVITYPUB_REST_NAMESPACE . '/actors/0/following' ); + $response = rest_get_server()->dispatch( $request ); + + $this->assertEquals( 200, $response->get_status() ); + $this->assertStringContainsString( 'application/activity+json', $response->get_headers()['Content-Type'] ); + + $data = $response->get_data(); + + // Test required properties. + $this->assertArrayHasKey( '@context', $data ); + $this->assertArrayHasKey( 'id', $data ); + $this->assertArrayHasKey( 'type', $data ); + $this->assertArrayHasKey( 'generator', $data ); + $this->assertArrayHasKey( 'actor', $data ); + $this->assertArrayHasKey( 'totalItems', $data ); + $this->assertArrayHasKey( 'orderedItems', $data ); + $this->assertArrayHasKey( 'partOf', $data ); + $this->assertArrayHasKey( 'first', $data ); + + // Test property values. + $this->assertEquals( 'OrderedCollectionPage', $data['type'] ); + $this->assertStringContainsString( 'wordpress.org', $data['generator'] ); + $this->assertEquals( $data['partOf'], $data['first'] ); + $this->assertIsArray( $data['orderedItems'] ); + } + + /** + * Test that the Following response matches its schema. + * + * @covers ::get_item + * @covers ::get_item_schema + */ + public function test_response_matches_schema() { + $request = new \WP_REST_Request( 'GET', '/' . ACTIVITYPUB_REST_NAMESPACE . '/actors/0/following' ); + $response = rest_get_server()->dispatch( $request ); + $data = $response->get_data(); + $schema = ( new \Activitypub\Rest\Following_Controller() )->get_item_schema(); + + $valid = \rest_validate_value_from_schema( $data, $schema ); + $this->assertNotWPError( $valid, 'Response failed schema validation: ' . ( \is_wp_error( $valid ) ? $valid->get_error_message() : '' ) ); + } + + /** + * Test get_item method. + * + * @doesNotPerformAssertions + */ + public function test_get_item() { + // Controller does not implement get_item(). + } +} From 6155f4b5ecd567bebe7d99f193ce510fac7cd9fb Mon Sep 17 00:00:00 2001 From: Matthias Pfefferle Date: Wed, 5 Feb 2025 12:56:12 +0100 Subject: [PATCH 03/18] Change usage of fediverse symbol (#1239) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Move "⁂" to the end of a line otherwise the links look a bit disorganized * this one mimics the logo --- build/editor-plugin/plugin.asset.php | 2 +- build/editor-plugin/plugin.js | 2 +- build/follow-me/index.asset.php | 2 +- build/follow-me/index.js | 4 ++-- build/follow-me/view.asset.php | 2 +- build/follow-me/view.js | 2 +- build/followers/index.asset.php | 2 +- build/followers/index.js | 8 ++++---- build/followers/view.asset.php | 2 +- build/followers/view.js | 6 +++--- build/reactions/index.asset.php | 2 +- build/reactions/index.js | 2 +- build/remote-reply/index.asset.php | 2 +- build/remote-reply/index.js | 2 +- build/reply/index.asset.php | 2 +- build/reply/index.js | 2 +- includes/class-admin.php | 12 ++++++------ src/editor-plugin/plugin.js | 4 ++-- templates/toolbox.php | 2 +- 19 files changed, 31 insertions(+), 31 deletions(-) diff --git a/build/editor-plugin/plugin.asset.php b/build/editor-plugin/plugin.asset.php index 548126f53..cb21393ca 100644 --- a/build/editor-plugin/plugin.asset.php +++ b/build/editor-plugin/plugin.asset.php @@ -1 +1 @@ - array('react', 'wp-components', 'wp-core-data', 'wp-data', 'wp-editor', 'wp-element', 'wp-i18n', 'wp-plugins', 'wp-primitives', 'wp-url'), 'version' => '6b15195803d2f5a2c116'); + array('react', 'wp-components', 'wp-core-data', 'wp-data', 'wp-editor', 'wp-element', 'wp-i18n', 'wp-plugins', 'wp-primitives', 'wp-url'), 'version' => '1c8a8b8b83b4690c70b6'); diff --git a/build/editor-plugin/plugin.js b/build/editor-plugin/plugin.js index 1d75171bd..590e355e1 100644 --- a/build/editor-plugin/plugin.js +++ b/build/editor-plugin/plugin.js @@ -1 +1 @@ -(()=>{"use strict";const e=window.React,t=window.wp.editor,i=window.wp.plugins,n=window.wp.components,a=window.wp.element,l=(0,a.forwardRef)((function({icon:e,size:t=24,...i},n){return(0,a.cloneElement)(e,{width:t,height:t,...i,ref:n})})),c=window.wp.primitives,o=(0,e.createElement)(c.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},(0,e.createElement)(c.Path,{d:"M12 3.3c-4.8 0-8.8 3.9-8.8 8.8 0 4.8 3.9 8.8 8.8 8.8 4.8 0 8.8-3.9 8.8-8.8s-4-8.8-8.8-8.8zm6.5 5.5h-2.6C15.4 7.3 14.8 6 14 5c2 .6 3.6 2 4.5 3.8zm.7 3.2c0 .6-.1 1.2-.2 1.8h-2.9c.1-.6.1-1.2.1-1.8s-.1-1.2-.1-1.8H19c.2.6.2 1.2.2 1.8zM12 18.7c-1-.7-1.8-1.9-2.3-3.5h4.6c-.5 1.6-1.3 2.9-2.3 3.5zm-2.6-4.9c-.1-.6-.1-1.1-.1-1.8 0-.6.1-1.2.1-1.8h5.2c.1.6.1 1.1.1 1.8s-.1 1.2-.1 1.8H9.4zM4.8 12c0-.6.1-1.2.2-1.8h2.9c-.1.6-.1 1.2-.1 1.8 0 .6.1 1.2.1 1.8H5c-.2-.6-.2-1.2-.2-1.8zM12 5.3c1 .7 1.8 1.9 2.3 3.5H9.7c.5-1.6 1.3-2.9 2.3-3.5zM10 5c-.8 1-1.4 2.3-1.8 3.8H5.5C6.4 7 8 5.6 10 5zM5.5 15.3h2.6c.4 1.5 1 2.8 1.8 3.7-1.8-.6-3.5-2-4.4-3.7zM14 19c.8-1 1.4-2.2 1.8-3.7h2.6C17.6 17 16 18.4 14 19z"})),r=(0,e.createElement)(c.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},(0,e.createElement)(c.Path,{d:"M15.5 9.5a1 1 0 100-2 1 1 0 000 2zm0 1.5a2.5 2.5 0 100-5 2.5 2.5 0 000 5zm-2.25 6v-2a2.75 2.75 0 00-2.75-2.75h-4A2.75 2.75 0 003.75 15v2h1.5v-2c0-.69.56-1.25 1.25-1.25h4c.69 0 1.25.56 1.25 1.25v2h1.5zm7-2v2h-1.5v-2c0-.69-.56-1.25-1.25-1.25H15v-1.5h2.5A2.75 2.75 0 0120.25 15zM9.5 8.5a1 1 0 11-2 0 1 1 0 012 0zm1.5 0a2.5 2.5 0 11-5 0 2.5 2.5 0 015 0z",fillRule:"evenodd"})),u=(0,e.createElement)(c.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},(0,e.createElement)(c.Path,{d:"M19.5 4.5h-7V6h4.44l-5.97 5.97 1.06 1.06L18 7.06v4.44h1.5v-7Zm-13 1a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-3H17v3a.5.5 0 0 1-.5.5h-10a.5.5 0 0 1-.5-.5v-10a.5.5 0 0 1 .5-.5h3V5.5h-3Z"})),w=window.wp.data,p=window.wp.coreData,v=window.wp.url,s=window.wp.i18n,d=(0,e.createElement)(c.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},(0,e.createElement)(c.Path,{fillRule:"evenodd",clipRule:"evenodd",d:"M12 18.5A6.5 6.5 0 0 1 6.93 7.931l9.139 9.138A6.473 6.473 0 0 1 12 18.5Zm5.123-2.498a6.5 6.5 0 0 0-9.124-9.124l9.124 9.124ZM4 12a8 8 0 1 1 16 0 8 8 0 0 1-16 0Z"}));(0,i.registerPlugin)("activitypub-editor-plugin",{render:()=>{const i=(0,w.useSelect)((e=>e("core/editor").getCurrentPostType()),[]),[a,c]=(0,p.useEntityProp)("postType",i,"meta"),u={verticalAlign:"middle",gap:"4px",justifyContent:"start",display:"inline-flex",alignItems:"center"},v=(t,i)=>(0,e.createElement)(n.__experimentalText,{style:u},(0,e.createElement)(l,{icon:i}),t);return"wp_block"===i?null:(0,e.createElement)(t.PluginDocumentSettingPanel,{name:"activitypub",title:(0,s.__)("⁂ Fediverse","activitypub")},(0,e.createElement)(n.TextControl,{label:(0,s.__)("Content Warning","activitypub"),value:a?.activitypub_content_warning,onChange:e=>{c({...a,activitypub_content_warning:e})},placeholder:(0,s.__)("Optional content warning","activitypub"),help:(0,s.__)("Content warnings do not change the content on your site, only in the fediverse.","activitypub")}),(0,e.createElement)(n.RadioControl,{label:(0,s.__)("Visibility","activitypub"),help:(0,s.__)("This adjusts the visibility of a post in the fediverse, but note that it won't affect how the post appears on the blog.","activitypub"),selected:a?.activitypub_content_visibility||"public",options:[{label:v((0,s.__)("Public","activitypub"),o),value:"public"},{label:v((0,s.__)("Quiet public","activitypub"),r),value:"quiet_public"},{label:v((0,s.__)("Do not federate","activitypub"),d),value:"local"}],onChange:e=>{c({...a,activitypub_content_visibility:e})},className:"activitypub-visibility"}))}}),(0,i.registerPlugin)("activitypub-editor-preview",{render:()=>{const i=(0,w.useSelect)((e=>e("core/editor").getCurrentPost().status));return(0,e.createElement)(e.Fragment,null,t.PluginPreviewMenuItem?(0,e.createElement)(t.PluginPreviewMenuItem,{onClick:()=>function(){const e=(0,w.select)("core/editor").getEditedPostPreviewLink(),t=(0,v.addQueryArgs)(e,{activitypub:"true"});window.open(t,"_blank")}(),icon:u,disabled:"auto-draft"===i},(0,s.__)("⁂ Fediverse preview","activitypub")):null)}})})(); \ No newline at end of file +(()=>{"use strict";var e={20:(e,t,i)=>{var n=i(609),r=Symbol.for("react.element"),o=(Symbol.for("react.fragment"),Object.prototype.hasOwnProperty),a=n.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,l={key:!0,ref:!0,__self:!0,__source:!0};t.jsx=function(e,t,i){var n,c={},s=null,p=null;for(n in void 0!==i&&(s=""+i),void 0!==t.key&&(s=""+t.key),void 0!==t.ref&&(p=t.ref),t)o.call(t,n)&&!l.hasOwnProperty(n)&&(c[n]=t[n]);if(e&&e.defaultProps)for(n in t=e.defaultProps)void 0===c[n]&&(c[n]=t[n]);return{$$typeof:r,type:e,key:s,ref:p,props:c,_owner:a.current}}},848:(e,t,i)=>{e.exports=i(20)},609:e=>{e.exports=window.React}},t={};function i(n){var r=t[n];if(void 0!==r)return r.exports;var o=t[n]={exports:{}};return e[n](o,o.exports,i),o.exports}var n=i(609);const r=window.wp.editor,o=window.wp.plugins,a=window.wp.components,l=window.wp.element,c=(0,l.forwardRef)((function({icon:e,size:t=24,...i},n){return(0,l.cloneElement)(e,{width:t,height:t,...i,ref:n})})),s=window.wp.primitives;var p=i(848);const u=(0,p.jsx)(s.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,p.jsx)(s.Path,{d:"M12 3.3c-4.8 0-8.8 3.9-8.8 8.8 0 4.8 3.9 8.8 8.8 8.8 4.8 0 8.8-3.9 8.8-8.8s-4-8.8-8.8-8.8zm6.5 5.5h-2.6C15.4 7.3 14.8 6 14 5c2 .6 3.6 2 4.5 3.8zm.7 3.2c0 .6-.1 1.2-.2 1.8h-2.9c.1-.6.1-1.2.1-1.8s-.1-1.2-.1-1.8H19c.2.6.2 1.2.2 1.8zM12 18.7c-1-.7-1.8-1.9-2.3-3.5h4.6c-.5 1.6-1.3 2.9-2.3 3.5zm-2.6-4.9c-.1-.6-.1-1.1-.1-1.8 0-.6.1-1.2.1-1.8h5.2c.1.6.1 1.1.1 1.8s-.1 1.2-.1 1.8H9.4zM4.8 12c0-.6.1-1.2.2-1.8h2.9c-.1.6-.1 1.2-.1 1.8 0 .6.1 1.2.1 1.8H5c-.2-.6-.2-1.2-.2-1.8zM12 5.3c1 .7 1.8 1.9 2.3 3.5H9.7c.5-1.6 1.3-2.9 2.3-3.5zM10 5c-.8 1-1.4 2.3-1.8 3.8H5.5C6.4 7 8 5.6 10 5zM5.5 15.3h2.6c.4 1.5 1 2.8 1.8 3.7-1.8-.6-3.5-2-4.4-3.7zM14 19c.8-1 1.4-2.2 1.8-3.7h2.6C17.6 17 16 18.4 14 19z"})}),v=(0,p.jsx)(s.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,p.jsx)(s.Path,{d:"M15.5 9.5a1 1 0 100-2 1 1 0 000 2zm0 1.5a2.5 2.5 0 100-5 2.5 2.5 0 000 5zm-2.25 6v-2a2.75 2.75 0 00-2.75-2.75h-4A2.75 2.75 0 003.75 15v2h1.5v-2c0-.69.56-1.25 1.25-1.25h4c.69 0 1.25.56 1.25 1.25v2h1.5zm7-2v2h-1.5v-2c0-.69-.56-1.25-1.25-1.25H15v-1.5h2.5A2.75 2.75 0 0120.25 15zM9.5 8.5a1 1 0 11-2 0 1 1 0 012 0zm1.5 0a2.5 2.5 0 11-5 0 2.5 2.5 0 015 0z",fillRule:"evenodd"})}),w=(0,p.jsx)(s.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,p.jsx)(s.Path,{d:"M19.5 4.5h-7V6h4.44l-5.97 5.97 1.06 1.06L18 7.06v4.44h1.5v-7Zm-13 1a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-3H17v3a.5.5 0 0 1-.5.5h-10a.5.5 0 0 1-.5-.5v-10a.5.5 0 0 1 .5-.5h3V5.5h-3Z"})}),d=window.wp.data,h=window.wp.coreData,_=window.wp.url,y=window.wp.i18n,b=(0,n.createElement)(s.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},(0,n.createElement)(s.Path,{fillRule:"evenodd",clipRule:"evenodd",d:"M12 18.5A6.5 6.5 0 0 1 6.93 7.931l9.139 9.138A6.473 6.473 0 0 1 12 18.5Zm5.123-2.498a6.5 6.5 0 0 0-9.124-9.124l9.124 9.124ZM4 12a8 8 0 1 1 16 0 8 8 0 0 1-16 0Z"}));(0,o.registerPlugin)("activitypub-editor-plugin",{render:()=>{const e=(0,d.useSelect)((e=>e("core/editor").getCurrentPostType()),[]),[t,i]=(0,h.useEntityProp)("postType",e,"meta"),o={verticalAlign:"middle",gap:"4px",justifyContent:"start",display:"inline-flex",alignItems:"center"},l=(e,t)=>(0,n.createElement)(a.__experimentalText,{style:o},(0,n.createElement)(c,{icon:t}),e);return"wp_block"===e?null:(0,n.createElement)(r.PluginDocumentSettingPanel,{name:"activitypub",title:(0,y.__)("Fediverse ⁂","activitypub")},(0,n.createElement)(a.TextControl,{label:(0,y.__)("Content Warning","activitypub"),value:t?.activitypub_content_warning,onChange:e=>{i({...t,activitypub_content_warning:e})},placeholder:(0,y.__)("Optional content warning","activitypub"),help:(0,y.__)("Content warnings do not change the content on your site, only in the fediverse.","activitypub")}),(0,n.createElement)(a.RadioControl,{label:(0,y.__)("Visibility","activitypub"),help:(0,y.__)("This adjusts the visibility of a post in the fediverse, but note that it won't affect how the post appears on the blog.","activitypub"),selected:t?.activitypub_content_visibility||"public",options:[{label:l((0,y.__)("Public","activitypub"),u),value:"public"},{label:l((0,y.__)("Quiet public","activitypub"),v),value:"quiet_public"},{label:l((0,y.__)("Do not federate","activitypub"),b),value:"local"}],onChange:e=>{i({...t,activitypub_content_visibility:e})},className:"activitypub-visibility"}))}}),(0,o.registerPlugin)("activitypub-editor-preview",{render:()=>{const e=(0,d.useSelect)((e=>e("core/editor").getCurrentPost().status));return(0,n.createElement)(n.Fragment,null,r.PluginPreviewMenuItem?(0,n.createElement)(r.PluginPreviewMenuItem,{onClick:()=>function(){const e=(0,d.select)("core/editor").getEditedPostPreviewLink(),t=(0,_.addQueryArgs)(e,{activitypub:"true"});window.open(t,"_blank")}(),icon:w,disabled:"auto-draft"===e},(0,y.__)("Fediverse preview ⁂","activitypub")):null)}})})(); \ No newline at end of file diff --git a/build/follow-me/index.asset.php b/build/follow-me/index.asset.php index c9a909a3e..a1d132c3c 100644 --- a/build/follow-me/index.asset.php +++ b/build/follow-me/index.asset.php @@ -1 +1 @@ - array('react', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-element', 'wp-i18n', 'wp-primitives'), 'version' => '83f77c18c3da9f51d14b'); + array('react', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-element', 'wp-i18n', 'wp-primitives'), 'version' => '37fe71b93359e27fe42a'); diff --git a/build/follow-me/index.js b/build/follow-me/index.js index cf75e0f09..3e7e3a5f4 100644 --- a/build/follow-me/index.js +++ b/build/follow-me/index.js @@ -1,2 +1,2 @@ -(()=>{"use strict";var e,t={60:(e,t,r)=>{const o=window.wp.blocks,a=window.React,n=window.wp.primitives,i=(0,a.createElement)(n.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},(0,a.createElement)(n.Path,{d:"M15.5 9.5a1 1 0 100-2 1 1 0 000 2zm0 1.5a2.5 2.5 0 100-5 2.5 2.5 0 000 5zm-2.25 6v-2a2.75 2.75 0 00-2.75-2.75h-4A2.75 2.75 0 003.75 15v2h1.5v-2c0-.69.56-1.25 1.25-1.25h4c.69 0 1.25.56 1.25 1.25v2h1.5zm7-2v2h-1.5v-2c0-.69-.56-1.25-1.25-1.25H15v-1.5h2.5A2.75 2.75 0 0120.25 15zM9.5 8.5a1 1 0 11-2 0 1 1 0 012 0zm1.5 0a2.5 2.5 0 11-5 0 2.5 2.5 0 015 0z",fillRule:"evenodd"})),l=window.wp.blockEditor,c=window.wp.i18n,s=window.wp.data,u=window.wp.coreData,p=window.wp.components,m=window.wp.element;function d(){return window._activityPubOptions||{}}const v=window.wp.apiFetch;var f=r.n(v);function b(e){return`var(--wp--preset--color--${e})`}function y(e){if("string"!=typeof e)return null;if(e.match(/^#/))return e.substring(0,7);const[,,t]=e.split("|");return b(t)}function h(e,t,r=null,o=""){return r?`${e}${o} { ${t}: ${r}; }\n`:""}function _(e,t,r,o){return h(e,"background-color",t)+h(e,"color",r)+h(e,"background-color",o,":hover")+h(e,"background-color",o,":focus")}function w({selector:e,style:t,backgroundColor:r}){const o=function(e,t,r){const o=`${e} .components-button`,a=("string"==typeof(n=r)?b(n):n?.color?.background||null)||t?.color?.background;var n;return _(o,y(t?.elements?.link?.color?.text),a,y(t?.elements?.link?.[":hover"]?.color?.text))}(e,t,r);return(0,a.createElement)("style",null,o)}const g=(0,a.createElement)(n.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},(0,a.createElement)(n.Path,{fillRule:"evenodd",clipRule:"evenodd",d:"M5 4.5h11a.5.5 0 0 1 .5.5v11a.5.5 0 0 1-.5.5H5a.5.5 0 0 1-.5-.5V5a.5.5 0 0 1 .5-.5ZM3 5a2 2 0 0 1 2-2h11a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5Zm17 3v10.75c0 .69-.56 1.25-1.25 1.25H6v1.5h12.75a2.75 2.75 0 0 0 2.75-2.75V8H20Z"})),E=(0,a.createElement)(n.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},(0,a.createElement)(n.Path,{d:"M16.7 7.1l-6.3 8.5-3.3-2.5-.9 1.2 4.5 3.4L17.9 8z"})),k=(0,m.forwardRef)((function({icon:e,size:t=24,...r},o){return(0,m.cloneElement)(e,{width:t,height:t,...r,ref:o})})),x=window.wp.compose,C="fediverse-remote-user";function S(e){try{return new URL(e),!0}catch(e){return!1}}function N({actionText:e,copyDescription:t,handle:r,resourceUrl:o,myProfile:n=!1,rememberProfile:l=!1}){const s=(0,c.__)("Loading...","activitypub"),u=(0,c.__)("Opening...","activitypub"),d=(0,c.__)("Error","activitypub"),v=(0,c.__)("Invalid","activitypub"),b=n||(0,c.__)("My Profile","activitypub"),[y,h]=(0,m.useState)(e),[_,w]=(0,m.useState)(g),N=(0,x.useCopyToClipboard)(r,(()=>{w(E),setTimeout((()=>w(g)),1e3)})),[I,O]=(0,m.useState)(""),[U,$]=(0,m.useState)(!0),{setRemoteUser:R}=function(){const[e,t]=(0,m.useState)(function(){const e=localStorage.getItem(C);return e?JSON.parse(e):{}}()),r=(0,m.useCallback)((e=>{!function(e){localStorage.setItem(C,JSON.stringify(e))}(e),t(e)}),[]),o=(0,m.useCallback)((()=>{localStorage.removeItem(C),t({})}),[]);return{template:e?.template||!1,profileURL:e?.profileURL||!1,setRemoteUser:r,deleteRemoteUser:o}}(),T=(0,m.useCallback)((()=>{let t;if(!S(I)&&!function(e){const t=e.replace(/^@/,"").split("@");return 2===t.length&&S(`https://${t[1]}`)}(I))return h(v),t=setTimeout((()=>h(e)),2e3),()=>clearTimeout(t);const r=o+I;h(s),f()({path:r}).then((({url:t,template:r})=>{U&&R({profileURL:I,template:r}),h(u),setTimeout((()=>{window.open(t,"_blank"),h(e)}),200)})).catch((()=>{h(d),setTimeout((()=>h(e)),2e3)}))}),[I]);return(0,a.createElement)("div",{className:"activitypub__dialog",role:"dialog","aria-labelledby":"dialog-title"},(0,a.createElement)("div",{className:"activitypub-dialog__section"},(0,a.createElement)("h4",{id:"dialog-title"},b),(0,a.createElement)("div",{className:"activitypub-dialog__description",id:"copy-description"},t),(0,a.createElement)("div",{className:"activitypub-dialog__button-group"},(0,a.createElement)("label",{htmlFor:"profile-handle",className:"screen-reader-text"},t),(0,a.createElement)("input",{type:"text",id:"profile-handle",value:r,readOnly:!0}),(0,a.createElement)(p.Button,{ref:N,"aria-label":(0,c.__)("Copy handle to clipboard","activitypub")},(0,a.createElement)(k,{icon:_}),(0,c.__)("Copy","activitypub")))),(0,a.createElement)("div",{className:"activitypub-dialog__section"},(0,a.createElement)("h4",{id:"remote-profile-title"},(0,c.__)("Your Profile","activitypub")),(0,a.createElement)("div",{className:"activitypub-dialog__description",id:"remote-profile-description"},(0,m.createInterpolateElement)((0,c.__)("Or, if you know your own profile, we can start things that way! (eg @yourusername@example.com)","activitypub"),{code:(0,a.createElement)("code",null)})),(0,a.createElement)("div",{className:"activitypub-dialog__button-group"},(0,a.createElement)("label",{htmlFor:"remote-profile",className:"screen-reader-text"},(0,c.__)("Enter your ActivityPub profile","activitypub")),(0,a.createElement)("input",{type:"text",id:"remote-profile",value:I,onKeyDown:e=>{"Enter"===e?.code&&T()},onChange:e=>O(e.target.value),"aria-invalid":y===v}),(0,a.createElement)(p.Button,{onClick:T,"aria-label":(0,c.__)("Submit profile","activitypub")},(0,a.createElement)(k,{icon:i}),y)),l&&(0,a.createElement)("div",{className:"activitypub-dialog__remember"},(0,a.createElement)(p.CheckboxControl,{checked:U,label:(0,c.__)("Remember me for easier comments","activitypub"),onChange:()=>{$(!U)}}))))}const I={avatar:"",webfinger:"@well@hello.dolly",name:(0,c.__)("Hello Dolly Fan Account","activitypub"),url:"#"};function O(e){if(!e)return I;const t={...I,...e};return t.avatar=t?.icon?.url,t}function U({profile:e,popupStyles:t,userId:r}){const{webfinger:o,avatar:n,name:i}=e,l=o.startsWith("@")?o:`@${o}`;return(0,a.createElement)("div",{className:"activitypub-profile"},(0,a.createElement)("img",{className:"activitypub-profile__avatar",src:n,alt:i}),(0,a.createElement)("div",{className:"activitypub-profile__content"},(0,a.createElement)("div",{className:"activitypub-profile__name"},i),(0,a.createElement)("div",{className:"activitypub-profile__handle",title:l},l)),(0,a.createElement)($,{profile:e,popupStyles:t,userId:r}))}function $({profile:e,popupStyles:t,userId:r}){const[o,n]=(0,m.useState)(!1),i=(0,c.sprintf)((0,c.__)("Follow %s","activitypub"),e?.name);return(0,a.createElement)(a.Fragment,null,(0,a.createElement)(p.Button,{className:"activitypub-profile__follow",onClick:()=>n(!0),"aria-haspopup":"dialog","aria-expanded":o,"aria-label":(0,c.__)("Follow me on the Fediverse","activitypub")},(0,c.__)("Follow","activitypub")),o&&(0,a.createElement)(p.Modal,{className:"activitypub-profile__confirm activitypub__modal",onRequestClose:()=>n(!1),title:i,"aria-label":i,role:"dialog"},(0,a.createElement)(R,{profile:e,userId:r}),(0,a.createElement)("style",null,t)))}function R({profile:e,userId:t}){const{namespace:r}=d(),{webfinger:o}=e,n=(0,c.__)("Follow","activitypub"),i=`/${r}/actors/${t}/remote-follow?resource=`,l=(0,c.__)("Copy and paste my profile into the search field of your favorite fediverse app or server.","activitypub"),s=o.startsWith("@")?o:`@${o}`;return(0,a.createElement)(N,{actionText:n,copyDescription:l,handle:s,resourceUrl:i})}function T({selectedUser:e,style:t,backgroundColor:r,id:o,useId:n=!1,profileData:i=!1}){const[l,c]=(0,m.useState)(O()),s="site"===e?0:e,u=function(e){return _(".apfmd__button-group .components-button",y(e?.elements?.link?.color?.text)||"#111","#fff",y(e?.elements?.link?.[":hover"]?.color?.text)||"#333")}(t),p=n?{id:o}:{};function v(e){c(O(e))}return(0,m.useEffect)((()=>{if(i)return v(i);(function(e){const{namespace:t}=d(),r={headers:{Accept:"application/activity+json"},path:`/${t}/actors/${e}`};return f()(r)})(s).then(v)}),[s,i]),(0,a.createElement)("div",{...p},(0,a.createElement)(w,{selector:`#${o}`,style:t,backgroundColor:r}),(0,a.createElement)(U,{profile:l,userId:s,popupStyles:u}))}function P({name:e}){const{enabled:t}=d(),r=t?.site?"":(0,c.__)("It will be empty in other non-author contexts.","activitypub"),o=(0,c.sprintf)(/* translators: %1$s: block name, %2$s: extra information for non-author context */ /* translators: %1$s: block name, %2$s: extra information for non-author context */ -(0,c.__)("This %1$s block will adapt to the page it is on, displaying the user profile associated with a post author (in a loop) or a user archive. %2$s","activitypub"),e,r).trim();return(0,a.createElement)(p.Card,null,(0,a.createElement)(p.CardBody,null,(0,m.createInterpolateElement)(o,{strong:(0,a.createElement)("strong",null)})))}(0,o.registerBlockType)("activitypub/follow-me",{edit:function({attributes:e,setAttributes:t,context:{postType:r,postId:o}}){const n=(0,l.useBlockProps)({className:"activitypub-follow-me-block-wrapper"}),i=function({withInherit:e=!1}){const{enabled:t}=d(),r=t?.users?(0,s.useSelect)((e=>e("core").getUsers({who:"authors"}))):[];return(0,m.useMemo)((()=>{if(!r)return[];const o=[];return t?.site&&o.push({label:(0,c.__)("Site","activitypub"),value:"site"}),e&&t?.users&&o.push({label:(0,c.__)("Dynamic User","activitypub"),value:"inherit"}),r.reduce(((e,t)=>(e.push({label:t.name,value:`${t.id}`}),e)),o)}),[r])}({withInherit:!0}),{selectedUser:v}=e,f="inherit"===v,b=(0,s.useSelect)((e=>{const{getEditedEntityRecord:t}=e(u.store),a=t("postType",r,o)?.author;return null!=a?a:null}),[r,o]);return(0,m.useEffect)((()=>{i.length&&(i.find((({value:e})=>e===v))||t({selectedUser:i[0].value}))}),[v,i]),(0,a.createElement)("div",{...n},i.length>1&&(0,a.createElement)(l.InspectorControls,{key:"setting"},(0,a.createElement)(p.PanelBody,{title:(0,c.__)("Followers Options","activitypub")},(0,a.createElement)(p.SelectControl,{label:(0,c.__)("Select User","activitypub"),value:e.selectedUser,options:i,onChange:e=>t({selectedUser:e})}))),f?b?(0,a.createElement)(T,{...e,id:n.id,selectedUser:b}):(0,a.createElement)(P,{name:(0,c.__)("Follow Me","activitypub")}):(0,a.createElement)(T,{...e,id:n.id}))},save:()=>null,icon:i})}},r={};function o(e){var a=r[e];if(void 0!==a)return a.exports;var n=r[e]={exports:{}};return t[e](n,n.exports,o),n.exports}o.m=t,e=[],o.O=(t,r,a,n)=>{if(!r){var i=1/0;for(u=0;u=n)&&Object.keys(o.O).every((e=>o.O[e](r[c])))?r.splice(c--,1):(l=!1,n0&&e[u-1][2]>n;u--)e[u]=e[u-1];e[u]=[r,a,n]},o.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return o.d(t,{a:t}),t},o.d=(e,t)=>{for(var r in t)o.o(t,r)&&!o.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},o.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{var e={338:0,301:0};o.O.j=t=>0===e[t];var t=(t,r)=>{var a,n,[i,l,c]=r,s=0;if(i.some((t=>0!==e[t]))){for(a in l)o.o(l,a)&&(o.m[a]=l[a]);if(c)var u=c(o)}for(t&&t(r);so(60)));a=o.O(a)})(); \ No newline at end of file +(()=>{"use strict";var e,t={919:(e,t,r)=>{const o=window.wp.blocks,n=window.wp.primitives;var a=r(848);const i=(0,a.jsx)(n.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,a.jsx)(n.Path,{d:"M15.5 9.5a1 1 0 100-2 1 1 0 000 2zm0 1.5a2.5 2.5 0 100-5 2.5 2.5 0 000 5zm-2.25 6v-2a2.75 2.75 0 00-2.75-2.75h-4A2.75 2.75 0 003.75 15v2h1.5v-2c0-.69.56-1.25 1.25-1.25h4c.69 0 1.25.56 1.25 1.25v2h1.5zm7-2v2h-1.5v-2c0-.69-.56-1.25-1.25-1.25H15v-1.5h2.5A2.75 2.75 0 0120.25 15zM9.5 8.5a1 1 0 11-2 0 1 1 0 012 0zm1.5 0a2.5 2.5 0 11-5 0 2.5 2.5 0 015 0z",fillRule:"evenodd"})});var l=r(609);const c=window.wp.blockEditor,s=window.wp.i18n,u=window.wp.data,p=window.wp.coreData,d=window.wp.components,m=window.wp.element;function v(){return window._activityPubOptions||{}}const f=window.wp.apiFetch;var y=r.n(f);function b(e){return`var(--wp--preset--color--${e})`}function _(e){if("string"!=typeof e)return null;if(e.match(/^#/))return e.substring(0,7);const[,,t]=e.split("|");return b(t)}function h(e,t,r=null,o=""){return r?`${e}${o} { ${t}: ${r}; }\n`:""}function w(e,t,r,o){return h(e,"background-color",t)+h(e,"color",r)+h(e,"background-color",o,":hover")+h(e,"background-color",o,":focus")}function g({selector:e,style:t,backgroundColor:r}){const o=function(e,t,r){const o=`${e} .components-button`,n=("string"==typeof(a=r)?b(a):a?.color?.background||null)||t?.color?.background;var a;return w(o,_(t?.elements?.link?.color?.text),n,_(t?.elements?.link?.[":hover"]?.color?.text))}(e,t,r);return(0,l.createElement)("style",null,o)}const E=(0,a.jsx)(n.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,a.jsx)(n.Path,{fillRule:"evenodd",clipRule:"evenodd",d:"M5 4.5h11a.5.5 0 0 1 .5.5v11a.5.5 0 0 1-.5.5H5a.5.5 0 0 1-.5-.5V5a.5.5 0 0 1 .5-.5ZM3 5a2 2 0 0 1 2-2h11a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5Zm17 3v10.75c0 .69-.56 1.25-1.25 1.25H6v1.5h12.75a2.75 2.75 0 0 0 2.75-2.75V8H20Z"})}),k=(0,a.jsx)(n.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,a.jsx)(n.Path,{d:"M16.7 7.1l-6.3 8.5-3.3-2.5-.9 1.2 4.5 3.4L17.9 8z"})}),x=(0,m.forwardRef)((function({icon:e,size:t=24,...r},o){return(0,m.cloneElement)(e,{width:t,height:t,...r,ref:o})})),S=window.wp.compose,C="fediverse-remote-user";function O(e){try{return new URL(e),!0}catch(e){return!1}}function N({actionText:e,copyDescription:t,handle:r,resourceUrl:o,myProfile:n=!1,rememberProfile:a=!1}){const c=(0,s.__)("Loading...","activitypub"),u=(0,s.__)("Opening...","activitypub"),p=(0,s.__)("Error","activitypub"),v=(0,s.__)("Invalid","activitypub"),f=n||(0,s.__)("My Profile","activitypub"),[b,_]=(0,m.useState)(e),[h,w]=(0,m.useState)(E),g=(0,S.useCopyToClipboard)(r,(()=>{w(k),setTimeout((()=>w(E)),1e3)})),[N,I]=(0,m.useState)(""),[R,U]=(0,m.useState)(!0),{setRemoteUser:$}=function(){const[e,t]=(0,m.useState)(function(){const e=localStorage.getItem(C);return e?JSON.parse(e):{}}()),r=(0,m.useCallback)((e=>{!function(e){localStorage.setItem(C,JSON.stringify(e))}(e),t(e)}),[]),o=(0,m.useCallback)((()=>{localStorage.removeItem(C),t({})}),[]);return{template:e?.template||!1,profileURL:e?.profileURL||!1,setRemoteUser:r,deleteRemoteUser:o}}(),P=(0,m.useCallback)((()=>{let t;if(!O(N)&&!function(e){const t=e.replace(/^@/,"").split("@");return 2===t.length&&O(`https://${t[1]}`)}(N))return _(v),t=setTimeout((()=>_(e)),2e3),()=>clearTimeout(t);const r=o+N;_(c),y()({path:r}).then((({url:t,template:r})=>{R&&$({profileURL:N,template:r}),_(u),setTimeout((()=>{window.open(t,"_blank"),_(e)}),200)})).catch((()=>{_(p),setTimeout((()=>_(e)),2e3)}))}),[N]);return(0,l.createElement)("div",{className:"activitypub__dialog",role:"dialog","aria-labelledby":"dialog-title"},(0,l.createElement)("div",{className:"activitypub-dialog__section"},(0,l.createElement)("h4",{id:"dialog-title"},f),(0,l.createElement)("div",{className:"activitypub-dialog__description",id:"copy-description"},t),(0,l.createElement)("div",{className:"activitypub-dialog__button-group"},(0,l.createElement)("label",{htmlFor:"profile-handle",className:"screen-reader-text"},t),(0,l.createElement)("input",{type:"text",id:"profile-handle",value:r,readOnly:!0}),(0,l.createElement)(d.Button,{ref:g,"aria-label":(0,s.__)("Copy handle to clipboard","activitypub")},(0,l.createElement)(x,{icon:h}),(0,s.__)("Copy","activitypub")))),(0,l.createElement)("div",{className:"activitypub-dialog__section"},(0,l.createElement)("h4",{id:"remote-profile-title"},(0,s.__)("Your Profile","activitypub")),(0,l.createElement)("div",{className:"activitypub-dialog__description",id:"remote-profile-description"},(0,m.createInterpolateElement)((0,s.__)("Or, if you know your own profile, we can start things that way! (eg @yourusername@example.com)","activitypub"),{code:(0,l.createElement)("code",null)})),(0,l.createElement)("div",{className:"activitypub-dialog__button-group"},(0,l.createElement)("label",{htmlFor:"remote-profile",className:"screen-reader-text"},(0,s.__)("Enter your ActivityPub profile","activitypub")),(0,l.createElement)("input",{type:"text",id:"remote-profile",value:N,onKeyDown:e=>{"Enter"===e?.code&&P()},onChange:e=>I(e.target.value),"aria-invalid":b===v}),(0,l.createElement)(d.Button,{onClick:P,"aria-label":(0,s.__)("Submit profile","activitypub")},(0,l.createElement)(x,{icon:i}),b)),a&&(0,l.createElement)("div",{className:"activitypub-dialog__remember"},(0,l.createElement)(d.CheckboxControl,{checked:R,label:(0,s.__)("Remember me for easier comments","activitypub"),onChange:()=>{U(!R)}}))))}const I={avatar:"",webfinger:"@well@hello.dolly",name:(0,s.__)("Hello Dolly Fan Account","activitypub"),url:"#"};function R(e){if(!e)return I;const t={...I,...e};return t.avatar=t?.icon?.url,t}function U({profile:e,popupStyles:t,userId:r}){const{webfinger:o,avatar:n,name:a}=e,i=o.startsWith("@")?o:`@${o}`;return(0,l.createElement)("div",{className:"activitypub-profile"},(0,l.createElement)("img",{className:"activitypub-profile__avatar",src:n,alt:a}),(0,l.createElement)("div",{className:"activitypub-profile__content"},(0,l.createElement)("div",{className:"activitypub-profile__name"},a),(0,l.createElement)("div",{className:"activitypub-profile__handle",title:i},i)),(0,l.createElement)($,{profile:e,popupStyles:t,userId:r}))}function $({profile:e,popupStyles:t,userId:r}){const[o,n]=(0,m.useState)(!1),a=(0,s.sprintf)((0,s.__)("Follow %s","activitypub"),e?.name);return(0,l.createElement)(l.Fragment,null,(0,l.createElement)(d.Button,{className:"activitypub-profile__follow",onClick:()=>n(!0),"aria-haspopup":"dialog","aria-expanded":o,"aria-label":(0,s.__)("Follow me on the Fediverse","activitypub")},(0,s.__)("Follow","activitypub")),o&&(0,l.createElement)(d.Modal,{className:"activitypub-profile__confirm activitypub__modal",onRequestClose:()=>n(!1),title:a,"aria-label":a,role:"dialog"},(0,l.createElement)(P,{profile:e,userId:r}),(0,l.createElement)("style",null,t)))}function P({profile:e,userId:t}){const{namespace:r}=v(),{webfinger:o}=e,n=(0,s.__)("Follow","activitypub"),a=`/${r}/actors/${t}/remote-follow?resource=`,i=(0,s.__)("Copy and paste my profile into the search field of your favorite fediverse app or server.","activitypub"),c=o.startsWith("@")?o:`@${o}`;return(0,l.createElement)(N,{actionText:n,copyDescription:i,handle:c,resourceUrl:a})}function T({selectedUser:e,style:t,backgroundColor:r,id:o,useId:n=!1,profileData:a=!1}){const[i,c]=(0,m.useState)(R()),s="site"===e?0:e,u=function(e){return w(".apfmd__button-group .components-button",_(e?.elements?.link?.color?.text)||"#111","#fff",_(e?.elements?.link?.[":hover"]?.color?.text)||"#333")}(t),p=n?{id:o}:{};function d(e){c(R(e))}return(0,m.useEffect)((()=>{if(a)return d(a);(function(e){const{namespace:t}=v(),r={headers:{Accept:"application/activity+json"},path:`/${t}/actors/${e}`};return y()(r)})(s).then(d)}),[s,a]),(0,l.createElement)("div",{...p},(0,l.createElement)(g,{selector:`#${o}`,style:t,backgroundColor:r}),(0,l.createElement)(U,{profile:i,userId:s,popupStyles:u}))}function j({name:e}){const{enabled:t}=v(),r=t?.site?"":(0,s.__)("It will be empty in other non-author contexts.","activitypub"),o=(0,s.sprintf)(/* translators: %1$s: block name, %2$s: extra information for non-author context */ /* translators: %1$s: block name, %2$s: extra information for non-author context */ +(0,s.__)("This %1$s block will adapt to the page it is on, displaying the user profile associated with a post author (in a loop) or a user archive. %2$s","activitypub"),e,r).trim();return(0,l.createElement)(d.Card,null,(0,l.createElement)(d.CardBody,null,(0,m.createInterpolateElement)(o,{strong:(0,l.createElement)("strong",null)})))}(0,o.registerBlockType)("activitypub/follow-me",{edit:function({attributes:e,setAttributes:t,context:{postType:r,postId:o}}){const n=(0,c.useBlockProps)({className:"activitypub-follow-me-block-wrapper"}),a=function({withInherit:e=!1}){const{enabled:t}=v(),r=t?.users?(0,u.useSelect)((e=>e("core").getUsers({who:"authors"}))):[];return(0,m.useMemo)((()=>{if(!r)return[];const o=[];return t?.site&&o.push({label:(0,s.__)("Site","activitypub"),value:"site"}),e&&t?.users&&o.push({label:(0,s.__)("Dynamic User","activitypub"),value:"inherit"}),r.reduce(((e,t)=>(e.push({label:t.name,value:`${t.id}`}),e)),o)}),[r])}({withInherit:!0}),{selectedUser:i}=e,f="inherit"===i,y=(0,u.useSelect)((e=>{const{getEditedEntityRecord:t}=e(p.store),n=t("postType",r,o)?.author;return null!=n?n:null}),[r,o]);return(0,m.useEffect)((()=>{a.length&&(a.find((({value:e})=>e===i))||t({selectedUser:a[0].value}))}),[i,a]),(0,l.createElement)("div",{...n},a.length>1&&(0,l.createElement)(c.InspectorControls,{key:"setting"},(0,l.createElement)(d.PanelBody,{title:(0,s.__)("Followers Options","activitypub")},(0,l.createElement)(d.SelectControl,{label:(0,s.__)("Select User","activitypub"),value:e.selectedUser,options:a,onChange:e=>t({selectedUser:e})}))),f?y?(0,l.createElement)(T,{...e,id:n.id,selectedUser:y}):(0,l.createElement)(j,{name:(0,s.__)("Follow Me","activitypub")}):(0,l.createElement)(T,{...e,id:n.id}))},save:()=>null,icon:i})},20:(e,t,r)=>{var o=r(609),n=Symbol.for("react.element"),a=(Symbol.for("react.fragment"),Object.prototype.hasOwnProperty),i=o.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,l={key:!0,ref:!0,__self:!0,__source:!0};t.jsx=function(e,t,r){var o,c={},s=null,u=null;for(o in void 0!==r&&(s=""+r),void 0!==t.key&&(s=""+t.key),void 0!==t.ref&&(u=t.ref),t)a.call(t,o)&&!l.hasOwnProperty(o)&&(c[o]=t[o]);if(e&&e.defaultProps)for(o in t=e.defaultProps)void 0===c[o]&&(c[o]=t[o]);return{$$typeof:n,type:e,key:s,ref:u,props:c,_owner:i.current}}},848:(e,t,r)=>{e.exports=r(20)},609:e=>{e.exports=window.React}},r={};function o(e){var n=r[e];if(void 0!==n)return n.exports;var a=r[e]={exports:{}};return t[e](a,a.exports,o),a.exports}o.m=t,e=[],o.O=(t,r,n,a)=>{if(!r){var i=1/0;for(u=0;u=a)&&Object.keys(o.O).every((e=>o.O[e](r[c])))?r.splice(c--,1):(l=!1,a0&&e[u-1][2]>a;u--)e[u]=e[u-1];e[u]=[r,n,a]},o.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return o.d(t,{a:t}),t},o.d=(e,t)=>{for(var r in t)o.o(t,r)&&!o.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},o.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{var e={338:0,301:0};o.O.j=t=>0===e[t];var t=(t,r)=>{var n,a,i=r[0],l=r[1],c=r[2],s=0;if(i.some((t=>0!==e[t]))){for(n in l)o.o(l,n)&&(o.m[n]=l[n]);if(c)var u=c(o)}for(t&&t(r);so(919)));n=o.O(n)})(); \ No newline at end of file diff --git a/build/follow-me/view.asset.php b/build/follow-me/view.asset.php index 94ce6bf25..eec19f8e9 100644 --- a/build/follow-me/view.asset.php +++ b/build/follow-me/view.asset.php @@ -1 +1 @@ - array('react', 'wp-api-fetch', 'wp-components', 'wp-compose', 'wp-dom-ready', 'wp-element', 'wp-i18n', 'wp-primitives'), 'version' => 'e73363caa1732d86861b'); + array('react', 'wp-api-fetch', 'wp-components', 'wp-compose', 'wp-dom-ready', 'wp-element', 'wp-i18n', 'wp-primitives'), 'version' => '91c0e513a192990d783c'); diff --git a/build/follow-me/view.js b/build/follow-me/view.js index 73933188e..8f2141f1c 100644 --- a/build/follow-me/view.js +++ b/build/follow-me/view.js @@ -1 +1 @@ -(()=>{"use strict";var e,t={300:(e,t,r)=>{const o=window.React,a=window.wp.element,n=window.wp.domReady;var i=r.n(n);const l=window.wp.apiFetch;var c=r.n(l);const s=window.wp.components,u=window.wp.i18n;function p(e){return`var(--wp--preset--color--${e})`}function m(e){if("string"!=typeof e)return null;if(e.match(/^#/))return e.substring(0,7);const[,,t]=e.split("|");return p(t)}function d(e,t,r=null,o=""){return r?`${e}${o} { ${t}: ${r}; }\n`:""}function v(e,t,r,o){return d(e,"background-color",t)+d(e,"color",r)+d(e,"background-color",o,":hover")+d(e,"background-color",o,":focus")}function f({selector:e,style:t,backgroundColor:r}){const a=function(e,t,r){const o=`${e} .components-button`,a=("string"==typeof(n=r)?p(n):n?.color?.background||null)||t?.color?.background;var n;return v(o,m(t?.elements?.link?.color?.text),a,m(t?.elements?.link?.[":hover"]?.color?.text))}(e,t,r);return(0,o.createElement)("style",null,a)}const b=window.wp.primitives,y=(0,o.createElement)(b.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},(0,o.createElement)(b.Path,{fillRule:"evenodd",clipRule:"evenodd",d:"M5 4.5h11a.5.5 0 0 1 .5.5v11a.5.5 0 0 1-.5.5H5a.5.5 0 0 1-.5-.5V5a.5.5 0 0 1 .5-.5ZM3 5a2 2 0 0 1 2-2h11a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5Zm17 3v10.75c0 .69-.56 1.25-1.25 1.25H6v1.5h12.75a2.75 2.75 0 0 0 2.75-2.75V8H20Z"})),_=(0,o.createElement)(b.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},(0,o.createElement)(b.Path,{d:"M16.7 7.1l-6.3 8.5-3.3-2.5-.9 1.2 4.5 3.4L17.9 8z"})),w=(0,a.forwardRef)((function({icon:e,size:t=24,...r},o){return(0,a.cloneElement)(e,{width:t,height:t,...r,ref:o})})),h=(0,o.createElement)(b.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},(0,o.createElement)(b.Path,{d:"M15.5 9.5a1 1 0 100-2 1 1 0 000 2zm0 1.5a2.5 2.5 0 100-5 2.5 2.5 0 000 5zm-2.25 6v-2a2.75 2.75 0 00-2.75-2.75h-4A2.75 2.75 0 003.75 15v2h1.5v-2c0-.69.56-1.25 1.25-1.25h4c.69 0 1.25.56 1.25 1.25v2h1.5zm7-2v2h-1.5v-2c0-.69-.56-1.25-1.25-1.25H15v-1.5h2.5A2.75 2.75 0 0120.25 15zM9.5 8.5a1 1 0 11-2 0 1 1 0 012 0zm1.5 0a2.5 2.5 0 11-5 0 2.5 2.5 0 015 0z",fillRule:"evenodd"})),g=window.wp.compose,E="fediverse-remote-user";function k(e){try{return new URL(e),!0}catch(e){return!1}}function x({actionText:e,copyDescription:t,handle:r,resourceUrl:n,myProfile:i=!1,rememberProfile:l=!1}){const p=(0,u.__)("Loading...","activitypub"),m=(0,u.__)("Opening...","activitypub"),d=(0,u.__)("Error","activitypub"),v=(0,u.__)("Invalid","activitypub"),f=i||(0,u.__)("My Profile","activitypub"),[b,x]=(0,a.useState)(e),[S,C]=(0,a.useState)(y),N=(0,g.useCopyToClipboard)(r,(()=>{C(_),setTimeout((()=>C(y)),1e3)})),[O,R]=(0,a.useState)(""),[$,I]=(0,a.useState)(!0),{setRemoteUser:P}=function(){const[e,t]=(0,a.useState)(function(){const e=localStorage.getItem(E);return e?JSON.parse(e):{}}()),r=(0,a.useCallback)((e=>{!function(e){localStorage.setItem(E,JSON.stringify(e))}(e),t(e)}),[]),o=(0,a.useCallback)((()=>{localStorage.removeItem(E),t({})}),[]);return{template:e?.template||!1,profileURL:e?.profileURL||!1,setRemoteUser:r,deleteRemoteUser:o}}(),F=(0,a.useCallback)((()=>{let t;if(!k(O)&&!function(e){const t=e.replace(/^@/,"").split("@");return 2===t.length&&k(`https://${t[1]}`)}(O))return x(v),t=setTimeout((()=>x(e)),2e3),()=>clearTimeout(t);const r=n+O;x(p),c()({path:r}).then((({url:t,template:r})=>{$&&P({profileURL:O,template:r}),x(m),setTimeout((()=>{window.open(t,"_blank"),x(e)}),200)})).catch((()=>{x(d),setTimeout((()=>x(e)),2e3)}))}),[O]);return(0,o.createElement)("div",{className:"activitypub__dialog",role:"dialog","aria-labelledby":"dialog-title"},(0,o.createElement)("div",{className:"activitypub-dialog__section"},(0,o.createElement)("h4",{id:"dialog-title"},f),(0,o.createElement)("div",{className:"activitypub-dialog__description",id:"copy-description"},t),(0,o.createElement)("div",{className:"activitypub-dialog__button-group"},(0,o.createElement)("label",{htmlFor:"profile-handle",className:"screen-reader-text"},t),(0,o.createElement)("input",{type:"text",id:"profile-handle",value:r,readOnly:!0}),(0,o.createElement)(s.Button,{ref:N,"aria-label":(0,u.__)("Copy handle to clipboard","activitypub")},(0,o.createElement)(w,{icon:S}),(0,u.__)("Copy","activitypub")))),(0,o.createElement)("div",{className:"activitypub-dialog__section"},(0,o.createElement)("h4",{id:"remote-profile-title"},(0,u.__)("Your Profile","activitypub")),(0,o.createElement)("div",{className:"activitypub-dialog__description",id:"remote-profile-description"},(0,a.createInterpolateElement)((0,u.__)("Or, if you know your own profile, we can start things that way! (eg @yourusername@example.com)","activitypub"),{code:(0,o.createElement)("code",null)})),(0,o.createElement)("div",{className:"activitypub-dialog__button-group"},(0,o.createElement)("label",{htmlFor:"remote-profile",className:"screen-reader-text"},(0,u.__)("Enter your ActivityPub profile","activitypub")),(0,o.createElement)("input",{type:"text",id:"remote-profile",value:O,onKeyDown:e=>{"Enter"===e?.code&&F()},onChange:e=>R(e.target.value),"aria-invalid":b===v}),(0,o.createElement)(s.Button,{onClick:F,"aria-label":(0,u.__)("Submit profile","activitypub")},(0,o.createElement)(w,{icon:h}),b)),l&&(0,o.createElement)("div",{className:"activitypub-dialog__remember"},(0,o.createElement)(s.CheckboxControl,{checked:$,label:(0,u.__)("Remember me for easier comments","activitypub"),onChange:()=>{I(!$)}}))))}function S(){return window._activityPubOptions||{}}const C={avatar:"",webfinger:"@well@hello.dolly",name:(0,u.__)("Hello Dolly Fan Account","activitypub"),url:"#"};function N(e){if(!e)return C;const t={...C,...e};return t.avatar=t?.icon?.url,t}function O({profile:e,popupStyles:t,userId:r}){const{webfinger:a,avatar:n,name:i}=e,l=a.startsWith("@")?a:`@${a}`;return(0,o.createElement)("div",{className:"activitypub-profile"},(0,o.createElement)("img",{className:"activitypub-profile__avatar",src:n,alt:i}),(0,o.createElement)("div",{className:"activitypub-profile__content"},(0,o.createElement)("div",{className:"activitypub-profile__name"},i),(0,o.createElement)("div",{className:"activitypub-profile__handle",title:l},l)),(0,o.createElement)(R,{profile:e,popupStyles:t,userId:r}))}function R({profile:e,popupStyles:t,userId:r}){const[n,i]=(0,a.useState)(!1),l=(0,u.sprintf)((0,u.__)("Follow %s","activitypub"),e?.name);return(0,o.createElement)(o.Fragment,null,(0,o.createElement)(s.Button,{className:"activitypub-profile__follow",onClick:()=>i(!0),"aria-haspopup":"dialog","aria-expanded":n,"aria-label":(0,u.__)("Follow me on the Fediverse","activitypub")},(0,u.__)("Follow","activitypub")),n&&(0,o.createElement)(s.Modal,{className:"activitypub-profile__confirm activitypub__modal",onRequestClose:()=>i(!1),title:l,"aria-label":l,role:"dialog"},(0,o.createElement)($,{profile:e,userId:r}),(0,o.createElement)("style",null,t)))}function $({profile:e,userId:t}){const{namespace:r}=S(),{webfinger:a}=e,n=(0,u.__)("Follow","activitypub"),i=`/${r}/actors/${t}/remote-follow?resource=`,l=(0,u.__)("Copy and paste my profile into the search field of your favorite fediverse app or server.","activitypub"),c=a.startsWith("@")?a:`@${a}`;return(0,o.createElement)(x,{actionText:n,copyDescription:l,handle:c,resourceUrl:i})}function I({selectedUser:e,style:t,backgroundColor:r,id:n,useId:i=!1,profileData:l=!1}){const[s,u]=(0,a.useState)(N()),p="site"===e?0:e,d=function(e){return v(".apfmd__button-group .components-button",m(e?.elements?.link?.color?.text)||"#111","#fff",m(e?.elements?.link?.[":hover"]?.color?.text)||"#333")}(t),b=i?{id:n}:{};function y(e){u(N(e))}return(0,a.useEffect)((()=>{if(l)return y(l);(function(e){const{namespace:t}=S(),r={headers:{Accept:"application/activity+json"},path:`/${t}/actors/${e}`};return c()(r)})(p).then(y)}),[p,l]),(0,o.createElement)("div",{...b},(0,o.createElement)(f,{selector:`#${n}`,style:t,backgroundColor:r}),(0,o.createElement)(O,{profile:s,userId:p,popupStyles:d}))}let P=1;i()((()=>{[].forEach.call(document.querySelectorAll(".activitypub-follow-me-block-wrapper"),(e=>{const t=JSON.parse(e.dataset.attrs);(0,a.createRoot)(e).render((0,o.createElement)(I,{...t,id:"activitypub-follow-me-block-"+P++,useId:!0}))}))}))}},r={};function o(e){var a=r[e];if(void 0!==a)return a.exports;var n=r[e]={exports:{}};return t[e](n,n.exports,o),n.exports}o.m=t,e=[],o.O=(t,r,a,n)=>{if(!r){var i=1/0;for(u=0;u=n)&&Object.keys(o.O).every((e=>o.O[e](r[c])))?r.splice(c--,1):(l=!1,n0&&e[u-1][2]>n;u--)e[u]=e[u-1];e[u]=[r,a,n]},o.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return o.d(t,{a:t}),t},o.d=(e,t)=>{for(var r in t)o.o(t,r)&&!o.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},o.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{var e={41:0,301:0};o.O.j=t=>0===e[t];var t=(t,r)=>{var a,n,[i,l,c]=r,s=0;if(i.some((t=>0!==e[t]))){for(a in l)o.o(l,a)&&(o.m[a]=l[a]);if(c)var u=c(o)}for(t&&t(r);so(300)));a=o.O(a)})(); \ No newline at end of file +(()=>{"use strict";var e,t={5:(e,t,r)=>{var o=r(609);const a=window.wp.element,n=window.wp.domReady;var i=r.n(n);const l=window.wp.apiFetch;var c=r.n(l);const s=window.wp.components,u=window.wp.i18n;function p(e){return`var(--wp--preset--color--${e})`}function d(e){if("string"!=typeof e)return null;if(e.match(/^#/))return e.substring(0,7);const[,,t]=e.split("|");return p(t)}function m(e,t,r=null,o=""){return r?`${e}${o} { ${t}: ${r}; }\n`:""}function f(e,t,r,o){return m(e,"background-color",t)+m(e,"color",r)+m(e,"background-color",o,":hover")+m(e,"background-color",o,":focus")}function v({selector:e,style:t,backgroundColor:r}){const a=function(e,t,r){const o=`${e} .components-button`,a=("string"==typeof(n=r)?p(n):n?.color?.background||null)||t?.color?.background;var n;return f(o,d(t?.elements?.link?.color?.text),a,d(t?.elements?.link?.[":hover"]?.color?.text))}(e,t,r);return(0,o.createElement)("style",null,a)}const y=window.wp.primitives;var b=r(848);const _=(0,b.jsx)(y.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,b.jsx)(y.Path,{fillRule:"evenodd",clipRule:"evenodd",d:"M5 4.5h11a.5.5 0 0 1 .5.5v11a.5.5 0 0 1-.5.5H5a.5.5 0 0 1-.5-.5V5a.5.5 0 0 1 .5-.5ZM3 5a2 2 0 0 1 2-2h11a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5Zm17 3v10.75c0 .69-.56 1.25-1.25 1.25H6v1.5h12.75a2.75 2.75 0 0 0 2.75-2.75V8H20Z"})}),w=(0,b.jsx)(y.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,b.jsx)(y.Path,{d:"M16.7 7.1l-6.3 8.5-3.3-2.5-.9 1.2 4.5 3.4L17.9 8z"})}),h=(0,a.forwardRef)((function({icon:e,size:t=24,...r},o){return(0,a.cloneElement)(e,{width:t,height:t,...r,ref:o})})),g=(0,b.jsx)(y.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,b.jsx)(y.Path,{d:"M15.5 9.5a1 1 0 100-2 1 1 0 000 2zm0 1.5a2.5 2.5 0 100-5 2.5 2.5 0 000 5zm-2.25 6v-2a2.75 2.75 0 00-2.75-2.75h-4A2.75 2.75 0 003.75 15v2h1.5v-2c0-.69.56-1.25 1.25-1.25h4c.69 0 1.25.56 1.25 1.25v2h1.5zm7-2v2h-1.5v-2c0-.69-.56-1.25-1.25-1.25H15v-1.5h2.5A2.75 2.75 0 0120.25 15zM9.5 8.5a1 1 0 11-2 0 1 1 0 012 0zm1.5 0a2.5 2.5 0 11-5 0 2.5 2.5 0 015 0z",fillRule:"evenodd"})}),E=window.wp.compose,k="fediverse-remote-user";function x(e){try{return new URL(e),!0}catch(e){return!1}}function S({actionText:e,copyDescription:t,handle:r,resourceUrl:n,myProfile:i=!1,rememberProfile:l=!1}){const p=(0,u.__)("Loading...","activitypub"),d=(0,u.__)("Opening...","activitypub"),m=(0,u.__)("Error","activitypub"),f=(0,u.__)("Invalid","activitypub"),v=i||(0,u.__)("My Profile","activitypub"),[y,b]=(0,a.useState)(e),[S,O]=(0,a.useState)(_),N=(0,E.useCopyToClipboard)(r,(()=>{O(w),setTimeout((()=>O(_)),1e3)})),[C,R]=(0,a.useState)(""),[I,$]=(0,a.useState)(!0),{setRemoteUser:P}=function(){const[e,t]=(0,a.useState)(function(){const e=localStorage.getItem(k);return e?JSON.parse(e):{}}()),r=(0,a.useCallback)((e=>{!function(e){localStorage.setItem(k,JSON.stringify(e))}(e),t(e)}),[]),o=(0,a.useCallback)((()=>{localStorage.removeItem(k),t({})}),[]);return{template:e?.template||!1,profileURL:e?.profileURL||!1,setRemoteUser:r,deleteRemoteUser:o}}(),j=(0,a.useCallback)((()=>{let t;if(!x(C)&&!function(e){const t=e.replace(/^@/,"").split("@");return 2===t.length&&x(`https://${t[1]}`)}(C))return b(f),t=setTimeout((()=>b(e)),2e3),()=>clearTimeout(t);const r=n+C;b(p),c()({path:r}).then((({url:t,template:r})=>{I&&P({profileURL:C,template:r}),b(d),setTimeout((()=>{window.open(t,"_blank"),b(e)}),200)})).catch((()=>{b(m),setTimeout((()=>b(e)),2e3)}))}),[C]);return(0,o.createElement)("div",{className:"activitypub__dialog",role:"dialog","aria-labelledby":"dialog-title"},(0,o.createElement)("div",{className:"activitypub-dialog__section"},(0,o.createElement)("h4",{id:"dialog-title"},v),(0,o.createElement)("div",{className:"activitypub-dialog__description",id:"copy-description"},t),(0,o.createElement)("div",{className:"activitypub-dialog__button-group"},(0,o.createElement)("label",{htmlFor:"profile-handle",className:"screen-reader-text"},t),(0,o.createElement)("input",{type:"text",id:"profile-handle",value:r,readOnly:!0}),(0,o.createElement)(s.Button,{ref:N,"aria-label":(0,u.__)("Copy handle to clipboard","activitypub")},(0,o.createElement)(h,{icon:S}),(0,u.__)("Copy","activitypub")))),(0,o.createElement)("div",{className:"activitypub-dialog__section"},(0,o.createElement)("h4",{id:"remote-profile-title"},(0,u.__)("Your Profile","activitypub")),(0,o.createElement)("div",{className:"activitypub-dialog__description",id:"remote-profile-description"},(0,a.createInterpolateElement)((0,u.__)("Or, if you know your own profile, we can start things that way! (eg @yourusername@example.com)","activitypub"),{code:(0,o.createElement)("code",null)})),(0,o.createElement)("div",{className:"activitypub-dialog__button-group"},(0,o.createElement)("label",{htmlFor:"remote-profile",className:"screen-reader-text"},(0,u.__)("Enter your ActivityPub profile","activitypub")),(0,o.createElement)("input",{type:"text",id:"remote-profile",value:C,onKeyDown:e=>{"Enter"===e?.code&&j()},onChange:e=>R(e.target.value),"aria-invalid":y===f}),(0,o.createElement)(s.Button,{onClick:j,"aria-label":(0,u.__)("Submit profile","activitypub")},(0,o.createElement)(h,{icon:g}),y)),l&&(0,o.createElement)("div",{className:"activitypub-dialog__remember"},(0,o.createElement)(s.CheckboxControl,{checked:I,label:(0,u.__)("Remember me for easier comments","activitypub"),onChange:()=>{$(!I)}}))))}function O(){return window._activityPubOptions||{}}const N={avatar:"",webfinger:"@well@hello.dolly",name:(0,u.__)("Hello Dolly Fan Account","activitypub"),url:"#"};function C(e){if(!e)return N;const t={...N,...e};return t.avatar=t?.icon?.url,t}function R({profile:e,popupStyles:t,userId:r}){const{webfinger:a,avatar:n,name:i}=e,l=a.startsWith("@")?a:`@${a}`;return(0,o.createElement)("div",{className:"activitypub-profile"},(0,o.createElement)("img",{className:"activitypub-profile__avatar",src:n,alt:i}),(0,o.createElement)("div",{className:"activitypub-profile__content"},(0,o.createElement)("div",{className:"activitypub-profile__name"},i),(0,o.createElement)("div",{className:"activitypub-profile__handle",title:l},l)),(0,o.createElement)(I,{profile:e,popupStyles:t,userId:r}))}function I({profile:e,popupStyles:t,userId:r}){const[n,i]=(0,a.useState)(!1),l=(0,u.sprintf)((0,u.__)("Follow %s","activitypub"),e?.name);return(0,o.createElement)(o.Fragment,null,(0,o.createElement)(s.Button,{className:"activitypub-profile__follow",onClick:()=>i(!0),"aria-haspopup":"dialog","aria-expanded":n,"aria-label":(0,u.__)("Follow me on the Fediverse","activitypub")},(0,u.__)("Follow","activitypub")),n&&(0,o.createElement)(s.Modal,{className:"activitypub-profile__confirm activitypub__modal",onRequestClose:()=>i(!1),title:l,"aria-label":l,role:"dialog"},(0,o.createElement)($,{profile:e,userId:r}),(0,o.createElement)("style",null,t)))}function $({profile:e,userId:t}){const{namespace:r}=O(),{webfinger:a}=e,n=(0,u.__)("Follow","activitypub"),i=`/${r}/actors/${t}/remote-follow?resource=`,l=(0,u.__)("Copy and paste my profile into the search field of your favorite fediverse app or server.","activitypub"),c=a.startsWith("@")?a:`@${a}`;return(0,o.createElement)(S,{actionText:n,copyDescription:l,handle:c,resourceUrl:i})}function P({selectedUser:e,style:t,backgroundColor:r,id:n,useId:i=!1,profileData:l=!1}){const[s,u]=(0,a.useState)(C()),p="site"===e?0:e,m=function(e){return f(".apfmd__button-group .components-button",d(e?.elements?.link?.color?.text)||"#111","#fff",d(e?.elements?.link?.[":hover"]?.color?.text)||"#333")}(t),y=i?{id:n}:{};function b(e){u(C(e))}return(0,a.useEffect)((()=>{if(l)return b(l);(function(e){const{namespace:t}=O(),r={headers:{Accept:"application/activity+json"},path:`/${t}/actors/${e}`};return c()(r)})(p).then(b)}),[p,l]),(0,o.createElement)("div",{...y},(0,o.createElement)(v,{selector:`#${n}`,style:t,backgroundColor:r}),(0,o.createElement)(R,{profile:s,userId:p,popupStyles:m}))}let j=1;i()((()=>{[].forEach.call(document.querySelectorAll(".activitypub-follow-me-block-wrapper"),(e=>{const t=JSON.parse(e.dataset.attrs);(0,a.createRoot)(e).render((0,o.createElement)(P,{...t,id:"activitypub-follow-me-block-"+j++,useId:!0}))}))}))},20:(e,t,r)=>{var o=r(609),a=Symbol.for("react.element"),n=(Symbol.for("react.fragment"),Object.prototype.hasOwnProperty),i=o.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,l={key:!0,ref:!0,__self:!0,__source:!0};t.jsx=function(e,t,r){var o,c={},s=null,u=null;for(o in void 0!==r&&(s=""+r),void 0!==t.key&&(s=""+t.key),void 0!==t.ref&&(u=t.ref),t)n.call(t,o)&&!l.hasOwnProperty(o)&&(c[o]=t[o]);if(e&&e.defaultProps)for(o in t=e.defaultProps)void 0===c[o]&&(c[o]=t[o]);return{$$typeof:a,type:e,key:s,ref:u,props:c,_owner:i.current}}},848:(e,t,r)=>{e.exports=r(20)},609:e=>{e.exports=window.React}},r={};function o(e){var a=r[e];if(void 0!==a)return a.exports;var n=r[e]={exports:{}};return t[e](n,n.exports,o),n.exports}o.m=t,e=[],o.O=(t,r,a,n)=>{if(!r){var i=1/0;for(u=0;u=n)&&Object.keys(o.O).every((e=>o.O[e](r[c])))?r.splice(c--,1):(l=!1,n0&&e[u-1][2]>n;u--)e[u]=e[u-1];e[u]=[r,a,n]},o.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return o.d(t,{a:t}),t},o.d=(e,t)=>{for(var r in t)o.o(t,r)&&!o.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},o.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{var e={41:0,301:0};o.O.j=t=>0===e[t];var t=(t,r)=>{var a,n,i=r[0],l=r[1],c=r[2],s=0;if(i.some((t=>0!==e[t]))){for(a in l)o.o(l,a)&&(o.m[a]=l[a]);if(c)var u=c(o)}for(t&&t(r);so(5)));a=o.O(a)})(); \ No newline at end of file diff --git a/build/followers/index.asset.php b/build/followers/index.asset.php index f9f1a3443..9b0afcfac 100644 --- a/build/followers/index.asset.php +++ b/build/followers/index.asset.php @@ -1 +1 @@ - array('react', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-element', 'wp-i18n', 'wp-primitives', 'wp-url'), 'version' => '5c45aaa8f57f7b4b3f8f'); + array('react', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-element', 'wp-i18n', 'wp-primitives', 'wp-url'), 'version' => 'e98a40c18060cbb88187'); diff --git a/build/followers/index.js b/build/followers/index.js index a2f2300c2..9bec7474c 100644 --- a/build/followers/index.js +++ b/build/followers/index.js @@ -1,4 +1,4 @@ -(()=>{var e={942:(e,t)=>{var a;!function(){"use strict";var n={}.hasOwnProperty;function r(){for(var e="",t=0;t{var t=e&&e.__esModule?()=>e.default:()=>e;return a.d(t,{a:t}),t},a.d=(e,t)=>{for(var n in t)a.o(t,n)&&!a.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},a.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{"use strict";const e=window.wp.blocks,t=window.React,n=window.wp.primitives,r=(0,t.createElement)(n.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},(0,t.createElement)(n.Path,{d:"M15.5 9.5a1 1 0 100-2 1 1 0 000 2zm0 1.5a2.5 2.5 0 100-5 2.5 2.5 0 000 5zm-2.25 6v-2a2.75 2.75 0 00-2.75-2.75h-4A2.75 2.75 0 003.75 15v2h1.5v-2c0-.69.56-1.25 1.25-1.25h4c.69 0 1.25.56 1.25 1.25v2h1.5zm7-2v2h-1.5v-2c0-.69-.56-1.25-1.25-1.25H15v-1.5h2.5A2.75 2.75 0 0120.25 15zM9.5 8.5a1 1 0 11-2 0 1 1 0 012 0zm1.5 0a2.5 2.5 0 11-5 0 2.5 2.5 0 015 0z",fillRule:"evenodd"})),l=window.wp.components,o=window.wp.element,i=window.wp.blockEditor,c=window.wp.data,s=window.wp.coreData,p=window.wp.i18n,u=window.wp.apiFetch;var m=a.n(u);const v=window.wp.url;var w=a(942),d=a.n(w);function b({active:e,children:a,page:n,pageClick:r,className:l}){const o=d()("wp-block activitypub-pager",l,{current:e});return(0,t.createElement)("a",{className:o,onClick:t=>{t.preventDefault(),!e&&r(n)}},a)}const g={outlined:"outlined",minimal:"minimal"};function f({compact:e,nextLabel:a,page:n,pageClick:r,perPage:l,prevLabel:o,total:i,variant:c=g.outlined}){const s=((e,t)=>{let a=[1,e-2,e-1,e,e+1,e+2,t];a.sort(((e,t)=>e-t)),a=a.filter(((e,a,n)=>e>=1&&e<=t&&n.lastIndexOf(e)===a));for(let e=a.length-2;e>=0;e--)a[e]===a[e+1]&&a.splice(e+1,1);return a})(n,Math.ceil(i/l)),p=d()("alignwide wp-block-query-pagination is-content-justification-space-between is-layout-flex wp-block-query-pagination-is-layout-flex",`is-${c}`,{"is-compact":e});return(0,t.createElement)("nav",{className:p},o&&(0,t.createElement)(b,{key:"prev",page:n-1,pageClick:r,active:1===n,"aria-label":o,className:"wp-block-query-pagination-previous block-editor-block-list__block"},o),!e&&(0,t.createElement)("div",{className:"block-editor-block-list__block wp-block wp-block-query-pagination-numbers"},s.map((e=>(0,t.createElement)(b,{key:e,page:e,pageClick:r,active:e===n,className:"page-numbers"},e)))),a&&(0,t.createElement)(b,{key:"next",page:n+1,pageClick:r,active:n===Math.ceil(i/l),"aria-label":a,className:"wp-block-query-pagination-next block-editor-block-list__block"},a))}function y(){return window._activityPubOptions||{}}function h({selectedUser:e,per_page:a,order:n,title:r,page:l,setPage:i,className:c="",followLinks:s=!0,followerData:u=!1}){const w="site"===e?0:e,[d,b]=(0,t.useState)([]),[g,h]=(0,t.useState)(0),[E,_]=(0,t.useState)(0),[x,C]=function(){const[e,a]=(0,t.useState)(1);return[e,a]}(),N=l||x,S=i||C,P=(0,o.createInterpolateElement)(/* translators: arrow for previous followers link */ /* translators: arrow for previous followers link */ -(0,p.__)(" Less","activitypub"),{span:(0,t.createElement)("span",{className:"wp-block-query-pagination-previous-arrow is-arrow-arrow","aria-hidden":"true"})}),I=(0,o.createInterpolateElement)(/* translators: arrow for next followers link */ /* translators: arrow for next followers link */ -(0,p.__)("More ","activitypub"),{span:(0,t.createElement)("span",{className:"wp-block-query-pagination-next-arrow is-arrow-arrow","aria-hidden":"true"})}),L=(e,t)=>{b(e),_(t),h(Math.ceil(t/a))};return(0,t.useEffect)((()=>{if(u&&1===N)return L(u.followers,u.total);const e=function(e,t,a,n){const{namespace:r}=y(),l=`/${r}/actors/${e}/followers`,o={per_page:t,order:a,page:n,context:"full"};return(0,v.addQueryArgs)(l,o)}(w,a,n,N);m()({path:e}).then((e=>L(e.orderedItems,e.totalItems))).catch((()=>{}))}),[w,a,n,N,u]),(0,t.createElement)("div",{className:"activitypub-follower-block "+c},(0,t.createElement)("h3",null,r),(0,t.createElement)("ul",null,d&&d.map((e=>(0,t.createElement)("li",{key:e.url},(0,t.createElement)(k,{...e,followLinks:s}))))),g>1&&(0,t.createElement)(f,{page:N,perPage:a,total:E,pageClick:S,nextLabel:I,prevLabel:P,compact:"is-style-compact"===c}))}function k({name:e,icon:a,url:n,preferredUsername:r,followLinks:o=!0}){const i=`@${r}`,c={};return o||(c.onClick=e=>e.preventDefault()),(0,t.createElement)(l.ExternalLink,{className:"activitypub-link",href:n,title:i,...c},(0,t.createElement)("img",{width:"40",height:"40",src:a.url,className:"avatar activitypub-avatar",alt:e}),(0,t.createElement)("span",{className:"activitypub-actor"},(0,t.createElement)("strong",{className:"activitypub-name"},e),(0,t.createElement)("span",{className:"sep"},"/"),(0,t.createElement)("span",{className:"activitypub-handle"},i)))}function E({name:e}){const{enabled:a}=y(),n=a?.site?"":(0,p.__)("It will be empty in other non-author contexts.","activitypub"),r=(0,p.sprintf)(/* translators: %1$s: block name, %2$s: extra information for non-author context */ /* translators: %1$s: block name, %2$s: extra information for non-author context */ -(0,p.__)("This %1$s block will adapt to the page it is on, displaying the user profile associated with a post author (in a loop) or a user archive. %2$s","activitypub"),e,n).trim();return(0,t.createElement)(l.Card,null,(0,t.createElement)(l.CardBody,null,(0,o.createInterpolateElement)(r,{strong:(0,t.createElement)("strong",null)})))}(0,e.registerBlockType)("activitypub/followers",{edit:function({attributes:e,setAttributes:a,context:{postType:n,postId:r}}){const{order:u,per_page:m,selectedUser:v,title:w}=e,d=(0,i.useBlockProps)(),[b,g]=(0,o.useState)(1),f=[{label:(0,p.__)("New to old","activitypub"),value:"desc"},{label:(0,p.__)("Old to new","activitypub"),value:"asc"}],k=function({withInherit:e=!1}){const{enabled:t}=y(),a=t?.users?(0,c.useSelect)((e=>e("core").getUsers({who:"authors"}))):[];return(0,o.useMemo)((()=>{if(!a)return[];const n=[];return t?.site&&n.push({label:(0,p.__)("Site","activitypub"),value:"site"}),e&&t?.users&&n.push({label:(0,p.__)("Dynamic User","activitypub"),value:"inherit"}),a.reduce(((e,t)=>(e.push({label:t.name,value:`${t.id}`}),e)),n)}),[a])}({withInherit:!0}),_=e=>t=>{g(1),a({[e]:t})},x=(0,c.useSelect)((e=>{const{getEditedEntityRecord:t}=e(s.store),a=t("postType",n,r)?.author;return null!=a?a:null}),[n,r]);return(0,o.useEffect)((()=>{k.length&&(k.find((({value:e})=>e===v))||a({selectedUser:k[0].value}))}),[v,k]),(0,t.createElement)("div",{...d},(0,t.createElement)(i.InspectorControls,{key:"setting"},(0,t.createElement)(l.PanelBody,{title:(0,p.__)("Followers Options","activitypub")},(0,t.createElement)(l.TextControl,{label:(0,p.__)("Title","activitypub"),help:(0,p.__)("Title to display above the list of followers. Blank for none.","activitypub"),value:w,onChange:e=>a({title:e})}),k.length>1&&(0,t.createElement)(l.SelectControl,{label:(0,p.__)("Select User","activitypub"),value:v,options:k,onChange:_("selectedUser")}),(0,t.createElement)(l.SelectControl,{label:(0,p.__)("Sort","activitypub"),value:u,options:f,onChange:_("order")}),(0,t.createElement)(l.RangeControl,{label:(0,p.__)("Number of Followers","activitypub"),value:m,onChange:_("per_page"),min:1,max:10}))),"inherit"===v?x?(0,t.createElement)(h,{...e,page:b,setPage:g,followLinks:!1,selectedUser:x}):(0,t.createElement)(E,{name:(0,p.__)("Followers","activitypub")}):(0,t.createElement)(h,{...e,page:b,setPage:g,followLinks:!1}))},save:()=>null,icon:r})})()})(); \ No newline at end of file +(()=>{var e={20:(e,t,a)=>{"use strict";var r=a(609),n=Symbol.for("react.element"),l=(Symbol.for("react.fragment"),Object.prototype.hasOwnProperty),o=r.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,i={key:!0,ref:!0,__self:!0,__source:!0};t.jsx=function(e,t,a){var r,c={},s=null,p=null;for(r in void 0!==a&&(s=""+a),void 0!==t.key&&(s=""+t.key),void 0!==t.ref&&(p=t.ref),t)l.call(t,r)&&!i.hasOwnProperty(r)&&(c[r]=t[r]);if(e&&e.defaultProps)for(r in t=e.defaultProps)void 0===c[r]&&(c[r]=t[r]);return{$$typeof:n,type:e,key:s,ref:p,props:c,_owner:o.current}}},848:(e,t,a)=>{"use strict";e.exports=a(20)},609:e=>{"use strict";e.exports=window.React},942:(e,t)=>{var a;!function(){"use strict";var r={}.hasOwnProperty;function n(){for(var e="",t=0;t{var t=e&&e.__esModule?()=>e.default:()=>e;return a.d(t,{a:t}),t},a.d=(e,t)=>{for(var r in t)a.o(t,r)&&!a.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},a.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{"use strict";const e=window.wp.blocks,t=window.wp.primitives;var r=a(848);const n=(0,r.jsx)(t.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,r.jsx)(t.Path,{d:"M15.5 9.5a1 1 0 100-2 1 1 0 000 2zm0 1.5a2.5 2.5 0 100-5 2.5 2.5 0 000 5zm-2.25 6v-2a2.75 2.75 0 00-2.75-2.75h-4A2.75 2.75 0 003.75 15v2h1.5v-2c0-.69.56-1.25 1.25-1.25h4c.69 0 1.25.56 1.25 1.25v2h1.5zm7-2v2h-1.5v-2c0-.69-.56-1.25-1.25-1.25H15v-1.5h2.5A2.75 2.75 0 0120.25 15zM9.5 8.5a1 1 0 11-2 0 1 1 0 012 0zm1.5 0a2.5 2.5 0 11-5 0 2.5 2.5 0 015 0z",fillRule:"evenodd"})});var l=a(609);const o=window.wp.components,i=window.wp.element,c=window.wp.blockEditor,s=window.wp.data,p=window.wp.coreData,u=window.wp.i18n,m=window.wp.apiFetch;var v=a.n(m);const d=window.wp.url;var w=a(942),b=a.n(w);function f({active:e,children:t,page:a,pageClick:r,className:n}){const o=b()("wp-block activitypub-pager",n,{current:e});return(0,l.createElement)("a",{className:o,onClick:t=>{t.preventDefault(),!e&&r(a)}},t)}function y({compact:e,nextLabel:t,page:a,pageClick:r,perPage:n,prevLabel:o,total:i,variant:c="outlined"}){const s=((e,t)=>{let a=[1,e-2,e-1,e,e+1,e+2,t];a.sort(((e,t)=>e-t)),a=a.filter(((e,a,r)=>e>=1&&e<=t&&r.lastIndexOf(e)===a));for(let e=a.length-2;e>=0;e--)a[e]===a[e+1]&&a.splice(e+1,1);return a})(a,Math.ceil(i/n)),p=b()("alignwide wp-block-query-pagination is-content-justification-space-between is-layout-flex wp-block-query-pagination-is-layout-flex",`is-${c}`,{"is-compact":e});return(0,l.createElement)("nav",{className:p},o&&(0,l.createElement)(f,{key:"prev",page:a-1,pageClick:r,active:1===a,"aria-label":o,className:"wp-block-query-pagination-previous block-editor-block-list__block"},o),!e&&(0,l.createElement)("div",{className:"block-editor-block-list__block wp-block wp-block-query-pagination-numbers"},s.map((e=>(0,l.createElement)(f,{key:e,page:e,pageClick:r,active:e===a,className:"page-numbers"},e)))),t&&(0,l.createElement)(f,{key:"next",page:a+1,pageClick:r,active:a===Math.ceil(i/n),"aria-label":t,className:"wp-block-query-pagination-next block-editor-block-list__block"},t))}function g(){return window._activityPubOptions||{}}function h({selectedUser:e,per_page:t,order:a,title:r,page:n,setPage:o,className:c="",followLinks:s=!0,followerData:p=!1}){const m="site"===e?0:e,[w,b]=(0,l.useState)([]),[f,h]=(0,l.useState)(0),[k,E]=(0,l.useState)(0),[x,S]=function(){const[e,t]=(0,l.useState)(1);return[e,t]}(),N=n||x,C=o||S,O=(0,i.createInterpolateElement)(/* translators: arrow for previous followers link */ /* translators: arrow for previous followers link */ +(0,u.__)(" Less","activitypub"),{span:(0,l.createElement)("span",{className:"wp-block-query-pagination-previous-arrow is-arrow-arrow","aria-hidden":"true"})}),P=(0,i.createInterpolateElement)(/* translators: arrow for next followers link */ /* translators: arrow for next followers link */ +(0,u.__)("More ","activitypub"),{span:(0,l.createElement)("span",{className:"wp-block-query-pagination-next-arrow is-arrow-arrow","aria-hidden":"true"})}),I=(e,a)=>{b(e),E(a),h(Math.ceil(a/t))};return(0,l.useEffect)((()=>{if(p&&1===N)return I(p.followers,p.total);const e=function(e,t,a,r){const{namespace:n}=g(),l=`/${n}/actors/${e}/followers`,o={per_page:t,order:a,page:r,context:"full"};return(0,d.addQueryArgs)(l,o)}(m,t,a,N);v()({path:e}).then((e=>I(e.orderedItems,e.totalItems))).catch((()=>{}))}),[m,t,a,N,p]),(0,l.createElement)("div",{className:"activitypub-follower-block "+c},(0,l.createElement)("h3",null,r),(0,l.createElement)("ul",null,w&&w.map((e=>(0,l.createElement)("li",{key:e.url},(0,l.createElement)(_,{...e,followLinks:s}))))),f>1&&(0,l.createElement)(y,{page:N,perPage:t,total:k,pageClick:C,nextLabel:P,prevLabel:O,compact:"is-style-compact"===c}))}function _({name:e,icon:t,url:a,preferredUsername:r,followLinks:n=!0}){const i=`@${r}`,c={};return n||(c.onClick=e=>e.preventDefault()),(0,l.createElement)(o.ExternalLink,{className:"activitypub-link",href:a,title:i,...c},(0,l.createElement)("img",{width:"40",height:"40",src:t.url,className:"avatar activitypub-avatar",alt:e}),(0,l.createElement)("span",{className:"activitypub-actor"},(0,l.createElement)("strong",{className:"activitypub-name"},e),(0,l.createElement)("span",{className:"sep"},"/"),(0,l.createElement)("span",{className:"activitypub-handle"},i)))}function k({name:e}){const{enabled:t}=g(),a=t?.site?"":(0,u.__)("It will be empty in other non-author contexts.","activitypub"),r=(0,u.sprintf)(/* translators: %1$s: block name, %2$s: extra information for non-author context */ /* translators: %1$s: block name, %2$s: extra information for non-author context */ +(0,u.__)("This %1$s block will adapt to the page it is on, displaying the user profile associated with a post author (in a loop) or a user archive. %2$s","activitypub"),e,a).trim();return(0,l.createElement)(o.Card,null,(0,l.createElement)(o.CardBody,null,(0,i.createInterpolateElement)(r,{strong:(0,l.createElement)("strong",null)})))}(0,e.registerBlockType)("activitypub/followers",{edit:function({attributes:e,setAttributes:t,context:{postType:a,postId:r}}){const{order:n,per_page:m,selectedUser:v,title:d}=e,w=(0,c.useBlockProps)(),[b,f]=(0,i.useState)(1),y=[{label:(0,u.__)("New to old","activitypub"),value:"desc"},{label:(0,u.__)("Old to new","activitypub"),value:"asc"}],_=function({withInherit:e=!1}){const{enabled:t}=g(),a=t?.users?(0,s.useSelect)((e=>e("core").getUsers({who:"authors"}))):[];return(0,i.useMemo)((()=>{if(!a)return[];const r=[];return t?.site&&r.push({label:(0,u.__)("Site","activitypub"),value:"site"}),e&&t?.users&&r.push({label:(0,u.__)("Dynamic User","activitypub"),value:"inherit"}),a.reduce(((e,t)=>(e.push({label:t.name,value:`${t.id}`}),e)),r)}),[a])}({withInherit:!0}),E=e=>a=>{f(1),t({[e]:a})},x=(0,s.useSelect)((e=>{const{getEditedEntityRecord:t}=e(p.store),n=t("postType",a,r)?.author;return null!=n?n:null}),[a,r]);return(0,i.useEffect)((()=>{_.length&&(_.find((({value:e})=>e===v))||t({selectedUser:_[0].value}))}),[v,_]),(0,l.createElement)("div",{...w},(0,l.createElement)(c.InspectorControls,{key:"setting"},(0,l.createElement)(o.PanelBody,{title:(0,u.__)("Followers Options","activitypub")},(0,l.createElement)(o.TextControl,{label:(0,u.__)("Title","activitypub"),help:(0,u.__)("Title to display above the list of followers. Blank for none.","activitypub"),value:d,onChange:e=>t({title:e})}),_.length>1&&(0,l.createElement)(o.SelectControl,{label:(0,u.__)("Select User","activitypub"),value:v,options:_,onChange:E("selectedUser")}),(0,l.createElement)(o.SelectControl,{label:(0,u.__)("Sort","activitypub"),value:n,options:y,onChange:E("order")}),(0,l.createElement)(o.RangeControl,{label:(0,u.__)("Number of Followers","activitypub"),value:m,onChange:E("per_page"),min:1,max:10}))),"inherit"===v?x?(0,l.createElement)(h,{...e,page:b,setPage:f,followLinks:!1,selectedUser:x}):(0,l.createElement)(k,{name:(0,u.__)("Followers","activitypub")}):(0,l.createElement)(h,{...e,page:b,setPage:f,followLinks:!1}))},save:()=>null,icon:n})})()})(); \ No newline at end of file diff --git a/build/followers/view.asset.php b/build/followers/view.asset.php index 8ee28c028..88e182175 100644 --- a/build/followers/view.asset.php +++ b/build/followers/view.asset.php @@ -1 +1 @@ - array('react', 'wp-api-fetch', 'wp-components', 'wp-dom-ready', 'wp-element', 'wp-i18n', 'wp-url'), 'version' => '20f96df73527c3bf094a'); + array('react', 'wp-api-fetch', 'wp-components', 'wp-dom-ready', 'wp-element', 'wp-i18n', 'wp-url'), 'version' => '34299fc181d49292ada0'); diff --git a/build/followers/view.js b/build/followers/view.js index a94fcf18d..227bb0122 100644 --- a/build/followers/view.js +++ b/build/followers/view.js @@ -1,3 +1,3 @@ -(()=>{var e,t={73:(e,t,a)=>{"use strict";const r=window.React,n=window.wp.apiFetch;var l=a.n(n);const o=window.wp.url,i=window.wp.element,c=window.wp.i18n;var s=a(942),p=a.n(s);function u({active:e,children:t,page:a,pageClick:n,className:l}){const o=p()("wp-block activitypub-pager",l,{current:e});return(0,r.createElement)("a",{className:o,onClick:t=>{t.preventDefault(),!e&&n(a)}},t)}const m={outlined:"outlined",minimal:"minimal"};function f({compact:e,nextLabel:t,page:a,pageClick:n,perPage:l,prevLabel:o,total:i,variant:c=m.outlined}){const s=((e,t)=>{let a=[1,e-2,e-1,e,e+1,e+2,t];a.sort(((e,t)=>e-t)),a=a.filter(((e,a,r)=>e>=1&&e<=t&&r.lastIndexOf(e)===a));for(let e=a.length-2;e>=0;e--)a[e]===a[e+1]&&a.splice(e+1,1);return a})(a,Math.ceil(i/l)),f=p()("alignwide wp-block-query-pagination is-content-justification-space-between is-layout-flex wp-block-query-pagination-is-layout-flex",`is-${c}`,{"is-compact":e});return(0,r.createElement)("nav",{className:f},o&&(0,r.createElement)(u,{key:"prev",page:a-1,pageClick:n,active:1===a,"aria-label":o,className:"wp-block-query-pagination-previous block-editor-block-list__block"},o),!e&&(0,r.createElement)("div",{className:"block-editor-block-list__block wp-block wp-block-query-pagination-numbers"},s.map((e=>(0,r.createElement)(u,{key:e,page:e,pageClick:n,active:e===a,className:"page-numbers"},e)))),t&&(0,r.createElement)(u,{key:"next",page:a+1,pageClick:n,active:a===Math.ceil(i/l),"aria-label":t,className:"wp-block-query-pagination-next block-editor-block-list__block"},t))}const v=window.wp.components;function b({selectedUser:e,per_page:t,order:a,title:n,page:s,setPage:p,className:u="",followLinks:m=!0,followerData:v=!1}){const b="site"===e?0:e,[w,g]=(0,r.useState)([]),[y,k]=(0,r.useState)(0),[h,E]=(0,r.useState)(0),[N,x]=function(){const[e,t]=(0,r.useState)(1);return[e,t]}(),_=s||N,O=p||x,S=(0,i.createInterpolateElement)(/* translators: arrow for previous followers link */ /* translators: arrow for previous followers link */ -(0,c.__)(" Less","activitypub"),{span:(0,r.createElement)("span",{className:"wp-block-query-pagination-previous-arrow is-arrow-arrow","aria-hidden":"true"})}),C=(0,i.createInterpolateElement)(/* translators: arrow for next followers link */ /* translators: arrow for next followers link */ -(0,c.__)("More ","activitypub"),{span:(0,r.createElement)("span",{className:"wp-block-query-pagination-next-arrow is-arrow-arrow","aria-hidden":"true"})}),L=(e,a)=>{g(e),E(a),k(Math.ceil(a/t))};return(0,r.useEffect)((()=>{if(v&&1===_)return L(v.followers,v.total);const e=function(e,t,a,r){const{namespace:n}=window._activityPubOptions||{},l=`/${n}/actors/${e}/followers`,i={per_page:t,order:a,page:r,context:"full"};return(0,o.addQueryArgs)(l,i)}(b,t,a,_);l()({path:e}).then((e=>L(e.orderedItems,e.totalItems))).catch((()=>{}))}),[b,t,a,_,v]),(0,r.createElement)("div",{className:"activitypub-follower-block "+u},(0,r.createElement)("h3",null,n),(0,r.createElement)("ul",null,w&&w.map((e=>(0,r.createElement)("li",{key:e.url},(0,r.createElement)(d,{...e,followLinks:m}))))),y>1&&(0,r.createElement)(f,{page:_,perPage:t,total:h,pageClick:O,nextLabel:C,prevLabel:S,compact:"is-style-compact"===u}))}function d({name:e,icon:t,url:a,preferredUsername:n,followLinks:l=!0}){const o=`@${n}`,i={};return l||(i.onClick=e=>e.preventDefault()),(0,r.createElement)(v.ExternalLink,{className:"activitypub-link",href:a,title:o,...i},(0,r.createElement)("img",{width:"40",height:"40",src:t.url,className:"avatar activitypub-avatar",alt:e}),(0,r.createElement)("span",{className:"activitypub-actor"},(0,r.createElement)("strong",{className:"activitypub-name"},e),(0,r.createElement)("span",{className:"sep"},"/"),(0,r.createElement)("span",{className:"activitypub-handle"},o)))}const w=window.wp.domReady;a.n(w)()((()=>{[].forEach.call(document.querySelectorAll(".activitypub-follower-block"),(e=>{const t=JSON.parse(e.dataset.attrs);(0,i.createRoot)(e).render((0,r.createElement)(b,{...t}))}))}))},942:(e,t)=>{var a;!function(){"use strict";var r={}.hasOwnProperty;function n(){for(var e="",t=0;t{if(!a){var o=1/0;for(p=0;p=l)&&Object.keys(r.O).every((e=>r.O[e](a[c])))?a.splice(c--,1):(i=!1,l0&&e[p-1][2]>l;p--)e[p]=e[p-1];e[p]=[a,n,l]},r.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return r.d(t,{a:t}),t},r.d=(e,t)=>{for(var a in t)r.o(t,a)&&!r.o(e,a)&&Object.defineProperty(e,a,{enumerable:!0,get:t[a]})},r.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{var e={996:0,528:0};r.O.j=t=>0===e[t];var t=(t,a)=>{var n,l,[o,i,c]=a,s=0;if(o.some((t=>0!==e[t]))){for(n in i)r.o(i,n)&&(r.m[n]=i[n]);if(c)var p=c(r)}for(t&&t(a);sr(73)));n=r.O(n)})(); \ No newline at end of file +(()=>{var e,t={73:(e,t,a)=>{"use strict";const r=window.React,n=window.wp.apiFetch;var l=a.n(n);const o=window.wp.url,c=window.wp.element,i=window.wp.i18n;var s=a(942),p=a.n(s);function u({active:e,children:t,page:a,pageClick:n,className:l}){const o=p()("wp-block activitypub-pager",l,{current:e});return(0,r.createElement)("a",{className:o,onClick:t=>{t.preventDefault(),!e&&n(a)}},t)}function m({compact:e,nextLabel:t,page:a,pageClick:n,perPage:l,prevLabel:o,total:c,variant:i="outlined"}){const s=((e,t)=>{let a=[1,e-2,e-1,e,e+1,e+2,t];a.sort(((e,t)=>e-t)),a=a.filter(((e,a,r)=>e>=1&&e<=t&&r.lastIndexOf(e)===a));for(let e=a.length-2;e>=0;e--)a[e]===a[e+1]&&a.splice(e+1,1);return a})(a,Math.ceil(c/l)),m=p()("alignwide wp-block-query-pagination is-content-justification-space-between is-layout-flex wp-block-query-pagination-is-layout-flex",`is-${i}`,{"is-compact":e});return(0,r.createElement)("nav",{className:m},o&&(0,r.createElement)(u,{key:"prev",page:a-1,pageClick:n,active:1===a,"aria-label":o,className:"wp-block-query-pagination-previous block-editor-block-list__block"},o),!e&&(0,r.createElement)("div",{className:"block-editor-block-list__block wp-block wp-block-query-pagination-numbers"},s.map((e=>(0,r.createElement)(u,{key:e,page:e,pageClick:n,active:e===a,className:"page-numbers"},e)))),t&&(0,r.createElement)(u,{key:"next",page:a+1,pageClick:n,active:a===Math.ceil(c/l),"aria-label":t,className:"wp-block-query-pagination-next block-editor-block-list__block"},t))}const f=window.wp.components;function v({selectedUser:e,per_page:t,order:a,title:n,page:s,setPage:p,className:u="",followLinks:f=!0,followerData:v=!1}){const w="site"===e?0:e,[d,g]=(0,r.useState)([]),[y,k]=(0,r.useState)(0),[h,E]=(0,r.useState)(0),[N,x]=function(){const[e,t]=(0,r.useState)(1);return[e,t]}(),_=s||N,O=p||x,S=(0,c.createInterpolateElement)(/* translators: arrow for previous followers link */ /* translators: arrow for previous followers link */ +(0,i.__)(" Less","activitypub"),{span:(0,r.createElement)("span",{className:"wp-block-query-pagination-previous-arrow is-arrow-arrow","aria-hidden":"true"})}),C=(0,c.createInterpolateElement)(/* translators: arrow for next followers link */ /* translators: arrow for next followers link */ +(0,i.__)("More ","activitypub"),{span:(0,r.createElement)("span",{className:"wp-block-query-pagination-next-arrow is-arrow-arrow","aria-hidden":"true"})}),L=(e,a)=>{g(e),E(a),k(Math.ceil(a/t))};return(0,r.useEffect)((()=>{if(v&&1===_)return L(v.followers,v.total);const e=function(e,t,a,r){const{namespace:n}=window._activityPubOptions||{},l=`/${n}/actors/${e}/followers`,c={per_page:t,order:a,page:r,context:"full"};return(0,o.addQueryArgs)(l,c)}(w,t,a,_);l()({path:e}).then((e=>L(e.orderedItems,e.totalItems))).catch((()=>{}))}),[w,t,a,_,v]),(0,r.createElement)("div",{className:"activitypub-follower-block "+u},(0,r.createElement)("h3",null,n),(0,r.createElement)("ul",null,d&&d.map((e=>(0,r.createElement)("li",{key:e.url},(0,r.createElement)(b,{...e,followLinks:f}))))),y>1&&(0,r.createElement)(m,{page:_,perPage:t,total:h,pageClick:O,nextLabel:C,prevLabel:S,compact:"is-style-compact"===u}))}function b({name:e,icon:t,url:a,preferredUsername:n,followLinks:l=!0}){const o=`@${n}`,c={};return l||(c.onClick=e=>e.preventDefault()),(0,r.createElement)(f.ExternalLink,{className:"activitypub-link",href:a,title:o,...c},(0,r.createElement)("img",{width:"40",height:"40",src:t.url,className:"avatar activitypub-avatar",alt:e}),(0,r.createElement)("span",{className:"activitypub-actor"},(0,r.createElement)("strong",{className:"activitypub-name"},e),(0,r.createElement)("span",{className:"sep"},"/"),(0,r.createElement)("span",{className:"activitypub-handle"},o)))}const w=window.wp.domReady;a.n(w)()((()=>{[].forEach.call(document.querySelectorAll(".activitypub-follower-block"),(e=>{const t=JSON.parse(e.dataset.attrs);(0,c.createRoot)(e).render((0,r.createElement)(v,{...t}))}))}))},942:(e,t)=>{var a;!function(){"use strict";var r={}.hasOwnProperty;function n(){for(var e="",t=0;t{if(!a){var o=1/0;for(p=0;p=l)&&Object.keys(r.O).every((e=>r.O[e](a[i])))?a.splice(i--,1):(c=!1,l0&&e[p-1][2]>l;p--)e[p]=e[p-1];e[p]=[a,n,l]},r.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return r.d(t,{a:t}),t},r.d=(e,t)=>{for(var a in t)r.o(t,a)&&!r.o(e,a)&&Object.defineProperty(e,a,{enumerable:!0,get:t[a]})},r.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{var e={996:0,528:0};r.O.j=t=>0===e[t];var t=(t,a)=>{var n,l,o=a[0],c=a[1],i=a[2],s=0;if(o.some((t=>0!==e[t]))){for(n in c)r.o(c,n)&&(r.m[n]=c[n]);if(i)var p=i(r)}for(t&&t(a);sr(73)));n=r.O(n)})(); \ No newline at end of file diff --git a/build/reactions/index.asset.php b/build/reactions/index.asset.php index 6d9642e29..426d76aee 100644 --- a/build/reactions/index.asset.php +++ b/build/reactions/index.asset.php @@ -1 +1 @@ - array('react', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-element', 'wp-i18n'), 'version' => 'af8b65b2e9159308a4b0'); + array('react', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-element', 'wp-i18n'), 'version' => '2ff24f7290aed1fc43f8'); diff --git a/build/reactions/index.js b/build/reactions/index.js index 613ec78c7..6628493f6 100644 --- a/build/reactions/index.js +++ b/build/reactions/index.js @@ -1 +1 @@ -(()=>{"use strict";var e,t={373:(e,t,a)=>{const n=window.wp.blocks,r=window.React,l=window.wp.blockEditor,o=window.wp.element,s=window.wp.i18n,i=window.wp.components,c=window.wp.apiFetch;var u=a.n(c);function m(){return window._activityPubOptions||{}}const h=({reactions:e})=>{const{defaultAvatarUrl:t}=m(),[a,n]=(0,o.useState)(new Set),[l,s]=(0,o.useState)(new Map),i=(0,o.useRef)([]),c=()=>{i.current.forEach((e=>clearTimeout(e))),i.current=[]},u=(t,a)=>{c();const r=100,l=e.length;a&&s((e=>{const a=new Map(e);return a.set(t,"clockwise"),a}));const o=e=>{const o="right"===e,c=o?l-1:0,u=o?1:-1;for(let e=o?t:t-1;o?e<=c:e>=c;e+=u){const l=Math.abs(e-t),o=setTimeout((()=>{n((t=>{const n=new Set(t);return a?n.add(e):n.delete(e),n})),a&&e!==t&&s((t=>{const a=new Map(t),n=e-u,r=a.get(n);return a.set(e,"clockwise"===r?"counter":"clockwise"),a}))}),l*r);i.current.push(o)}};if(o("right"),o("left"),!a){const e=Math.max((l-t)*r,t*r),a=setTimeout((()=>{s(new Map)}),e+r);i.current.push(a)}};return(0,o.useEffect)((()=>()=>c()),[]),(0,r.createElement)("ul",{className:"reaction-avatars"},e.map(((e,n)=>{const o=l.get(n),s=["reaction-avatar",a.has(n)?"wave-active":"",o?`rotate-${o}`:""].filter(Boolean).join(" "),i=e.avatar||t;return(0,r.createElement)("li",{key:n},(0,r.createElement)("a",{href:e.url,target:"_blank",rel:"noopener noreferrer",onMouseEnter:()=>u(n,!0),onMouseLeave:()=>u(n,!1)},(0,r.createElement)("img",{src:i,alt:e.name,className:s,width:"32",height:"32"})))})))},p=({reactions:e,type:t})=>(0,r.createElement)("ul",{className:"activitypub-reaction-list"},e.map(((e,t)=>(0,r.createElement)("li",{key:t},(0,r.createElement)("a",{href:e.url,className:"reaction-item",target:"_blank",rel:"noopener noreferrer"},(0,r.createElement)("img",{src:e.avatar,alt:e.name,width:"32",height:"32"}),(0,r.createElement)("span",null,e.name)))))),f=({items:e,label:t})=>{const[a,n]=(0,o.useState)(!1),[l,s]=(0,o.useState)(null),[c,u]=(0,o.useState)(e.length),m=(0,o.useRef)(null);(0,o.useEffect)((()=>{if(!m.current)return;const t=()=>{const t=m.current;if(!t)return;const a=t.offsetWidth-(l?.offsetWidth||0)-12,n=Math.max(1,Math.floor((a-32)/22));u(Math.min(n,e.length))};t();const a=new ResizeObserver(t);return a.observe(m.current),()=>{a.disconnect()}}),[l,e.length]);const f=e.slice(0,c);return(0,r.createElement)("div",{className:"reaction-group",ref:m},(0,r.createElement)(h,{reactions:f}),(0,r.createElement)(i.Button,{ref:s,className:"reaction-label is-link",onClick:()=>n(!a),"aria-expanded":a},t),a&&l&&(0,r.createElement)(i.Popover,{anchor:l,onClose:()=>n(!1)},(0,r.createElement)(p,{reactions:e})))};function d({title:e="",postId:t=null,reactions:a=null,titleComponent:n=null}){const{namespace:l}=m(),[s,i]=(0,o.useState)(a),[c,h]=(0,o.useState)(!a);return(0,o.useEffect)((()=>{if(a)return i(a),void h(!1);t?(h(!0),u()({path:`/${l}/posts/${t}/reactions`}).then((e=>{i(e),h(!1)})).catch((()=>h(!1)))):h(!1)}),[t,a]),c?null:s&&Object.values(s).some((e=>e.items?.length>0))?(0,r.createElement)("div",{className:"activitypub-reactions"},n||e&&(0,r.createElement)("h6",null,e),Object.entries(s).map((([e,t])=>t.items?.length?(0,r.createElement)(f,{key:e,items:t.items,label:t.label}):null))):null}const g=e=>{const t=["#FF6B6B","#4ECDC4","#45B7D1","#96CEB4","#FFEEAD","#D4A5A5","#9B59B6","#3498DB","#E67E22"],a=(()=>{const e=["Bouncy","Cosmic","Dancing","Fluffy","Giggly","Hoppy","Jazzy","Magical","Nifty","Perky","Quirky","Sparkly","Twirly","Wiggly","Zippy"],t=["Badger","Capybara","Dolphin","Echidna","Flamingo","Giraffe","Hedgehog","Iguana","Jellyfish","Koala","Lemur","Manatee","Narwhal","Octopus","Penguin"];return`${e[Math.floor(Math.random()*e.length)]} ${t[Math.floor(Math.random()*t.length)]}`})(),n=t[Math.floor(Math.random()*t.length)],r=a.charAt(0),l=document.createElement("canvas");l.width=64,l.height=64;const o=l.getContext("2d");return o.fillStyle=n,o.beginPath(),o.arc(32,32,32,0,2*Math.PI),o.fill(),o.fillStyle="#FFFFFF",o.font="32px sans-serif",o.textAlign="center",o.textBaseline="middle",o.fillText(r,32,32),{name:a,url:"#",avatar:l.toDataURL()}},v=JSON.parse('{"UU":"activitypub/reactions"}');(0,n.registerBlockType)(v.UU,{edit:function({attributes:e,setAttributes:t,__unstableLayoutClassNames:a}){const n=(0,l.useBlockProps)({className:a}),[i]=(0,o.useState)({likes:{label:"9 likes",items:Array.from({length:9},((e,t)=>g()))},reposts:{label:"6 reposts",items:Array.from({length:6},((e,t)=>g()))}}),c=(0,r.createElement)(l.RichText,{tagName:"h6",value:e.title,onChange:e=>t({title:e}),placeholder:(0,s.__)("Fediverse reactions","activitypub"),disableLineBreaks:!0,allowedFormats:[]});return(0,r.createElement)("div",{...n},(0,r.createElement)(d,{titleComponent:c,reactions:i}))}})}},a={};function n(e){var r=a[e];if(void 0!==r)return r.exports;var l=a[e]={exports:{}};return t[e](l,l.exports,n),l.exports}n.m=t,e=[],n.O=(t,a,r,l)=>{if(!a){var o=1/0;for(u=0;u=l)&&Object.keys(n.O).every((e=>n.O[e](a[i])))?a.splice(i--,1):(s=!1,l0&&e[u-1][2]>l;u--)e[u]=e[u-1];e[u]=[a,r,l]},n.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return n.d(t,{a:t}),t},n.d=(e,t)=>{for(var a in t)n.o(t,a)&&!n.o(e,a)&&Object.defineProperty(e,a,{enumerable:!0,get:t[a]})},n.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{var e={608:0,104:0};n.O.j=t=>0===e[t];var t=(t,a)=>{var r,l,[o,s,i]=a,c=0;if(o.some((t=>0!==e[t]))){for(r in s)n.o(s,r)&&(n.m[r]=s[r]);if(i)var u=i(n)}for(t&&t(a);cn(373)));r=n.O(r)})(); \ No newline at end of file +(()=>{"use strict";var e,t={373:(e,t,a)=>{const n=window.wp.blocks,r=window.React,l=window.wp.blockEditor,o=window.wp.element,s=window.wp.i18n,i=window.wp.components,c=window.wp.apiFetch;var u=a.n(c);function m(){return window._activityPubOptions||{}}const h=({reactions:e})=>{const{defaultAvatarUrl:t}=m(),[a,n]=(0,o.useState)(new Set),[l,s]=(0,o.useState)(new Map),i=(0,o.useRef)([]),c=()=>{i.current.forEach((e=>clearTimeout(e))),i.current=[]},u=(t,a)=>{c();const r=100,l=e.length;a&&s((e=>{const a=new Map(e);return a.set(t,"clockwise"),a}));const o=e=>{const o="right"===e,c=o?l-1:0,u=o?1:-1;for(let e=o?t:t-1;o?e<=c:e>=c;e+=u){const l=Math.abs(e-t),o=setTimeout((()=>{n((t=>{const n=new Set(t);return a?n.add(e):n.delete(e),n})),a&&e!==t&&s((t=>{const a=new Map(t),n=e-u,r=a.get(n);return a.set(e,"clockwise"===r?"counter":"clockwise"),a}))}),l*r);i.current.push(o)}};if(o("right"),o("left"),!a){const e=Math.max((l-t)*r,t*r),a=setTimeout((()=>{s(new Map)}),e+r);i.current.push(a)}};return(0,o.useEffect)((()=>()=>c()),[]),(0,r.createElement)("ul",{className:"reaction-avatars"},e.map(((e,n)=>{const o=l.get(n),s=["reaction-avatar",a.has(n)?"wave-active":"",o?`rotate-${o}`:""].filter(Boolean).join(" "),i=e.avatar||t;return(0,r.createElement)("li",{key:n},(0,r.createElement)("a",{href:e.url,target:"_blank",rel:"noopener noreferrer",onMouseEnter:()=>u(n,!0),onMouseLeave:()=>u(n,!1)},(0,r.createElement)("img",{src:i,alt:e.name,className:s,width:"32",height:"32"})))})))},p=({reactions:e,type:t})=>(0,r.createElement)("ul",{className:"activitypub-reaction-list"},e.map(((e,t)=>(0,r.createElement)("li",{key:t},(0,r.createElement)("a",{href:e.url,className:"reaction-item",target:"_blank",rel:"noopener noreferrer"},(0,r.createElement)("img",{src:e.avatar,alt:e.name,width:"32",height:"32"}),(0,r.createElement)("span",null,e.name)))))),f=({items:e,label:t})=>{const[a,n]=(0,o.useState)(!1),[l,s]=(0,o.useState)(null),[c,u]=(0,o.useState)(e.length),m=(0,o.useRef)(null);(0,o.useEffect)((()=>{if(!m.current)return;const t=()=>{const t=m.current;if(!t)return;const a=t.offsetWidth-(l?.offsetWidth||0)-12,n=Math.max(1,Math.floor((a-32)/22));u(Math.min(n,e.length))};t();const a=new ResizeObserver(t);return a.observe(m.current),()=>{a.disconnect()}}),[l,e.length]);const f=e.slice(0,c);return(0,r.createElement)("div",{className:"reaction-group",ref:m},(0,r.createElement)(h,{reactions:f}),(0,r.createElement)(i.Button,{ref:s,className:"reaction-label is-link",onClick:()=>n(!a),"aria-expanded":a},t),a&&l&&(0,r.createElement)(i.Popover,{anchor:l,onClose:()=>n(!1)},(0,r.createElement)(p,{reactions:e})))};function d({title:e="",postId:t=null,reactions:a=null,titleComponent:n=null}){const{namespace:l}=m(),[s,i]=(0,o.useState)(a),[c,h]=(0,o.useState)(!a);return(0,o.useEffect)((()=>{if(a)return i(a),void h(!1);t?(h(!0),u()({path:`/${l}/posts/${t}/reactions`}).then((e=>{i(e),h(!1)})).catch((()=>h(!1)))):h(!1)}),[t,a]),c?null:s&&Object.values(s).some((e=>e.items?.length>0))?(0,r.createElement)("div",{className:"activitypub-reactions"},n||e&&(0,r.createElement)("h6",null,e),Object.entries(s).map((([e,t])=>t.items?.length?(0,r.createElement)(f,{key:e,items:t.items,label:t.label}):null))):null}const g=e=>{const t=["#FF6B6B","#4ECDC4","#45B7D1","#96CEB4","#FFEEAD","#D4A5A5","#9B59B6","#3498DB","#E67E22"],a=(()=>{const e=["Bouncy","Cosmic","Dancing","Fluffy","Giggly","Hoppy","Jazzy","Magical","Nifty","Perky","Quirky","Sparkly","Twirly","Wiggly","Zippy"],t=["Badger","Capybara","Dolphin","Echidna","Flamingo","Giraffe","Hedgehog","Iguana","Jellyfish","Koala","Lemur","Manatee","Narwhal","Octopus","Penguin"];return`${e[Math.floor(Math.random()*e.length)]} ${t[Math.floor(Math.random()*t.length)]}`})(),n=t[Math.floor(Math.random()*t.length)],r=a.charAt(0),l=document.createElement("canvas");l.width=64,l.height=64;const o=l.getContext("2d");return o.fillStyle=n,o.beginPath(),o.arc(32,32,32,0,2*Math.PI),o.fill(),o.fillStyle="#FFFFFF",o.font="32px sans-serif",o.textAlign="center",o.textBaseline="middle",o.fillText(r,32,32),{name:a,url:"#",avatar:l.toDataURL()}},v=JSON.parse('{"UU":"activitypub/reactions"}');(0,n.registerBlockType)(v.UU,{edit:function({attributes:e,setAttributes:t,__unstableLayoutClassNames:a}){const n=(0,l.useBlockProps)({className:a}),[i]=(0,o.useState)({likes:{label:"9 likes",items:Array.from({length:9},((e,t)=>g()))},reposts:{label:"6 reposts",items:Array.from({length:6},((e,t)=>g()))}}),c=(0,r.createElement)(l.RichText,{tagName:"h6",value:e.title,onChange:e=>t({title:e}),placeholder:(0,s.__)("Fediverse reactions","activitypub"),disableLineBreaks:!0,allowedFormats:[]});return(0,r.createElement)("div",{...n},(0,r.createElement)(d,{titleComponent:c,reactions:i}))}})}},a={};function n(e){var r=a[e];if(void 0!==r)return r.exports;var l=a[e]={exports:{}};return t[e](l,l.exports,n),l.exports}n.m=t,e=[],n.O=(t,a,r,l)=>{if(!a){var o=1/0;for(u=0;u=l)&&Object.keys(n.O).every((e=>n.O[e](a[i])))?a.splice(i--,1):(s=!1,l0&&e[u-1][2]>l;u--)e[u]=e[u-1];e[u]=[a,r,l]},n.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return n.d(t,{a:t}),t},n.d=(e,t)=>{for(var a in t)n.o(t,a)&&!n.o(e,a)&&Object.defineProperty(e,a,{enumerable:!0,get:t[a]})},n.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{var e={608:0,104:0};n.O.j=t=>0===e[t];var t=(t,a)=>{var r,l,o=a[0],s=a[1],i=a[2],c=0;if(o.some((t=>0!==e[t]))){for(r in s)n.o(s,r)&&(n.m[r]=s[r]);if(i)var u=i(n)}for(t&&t(a);cn(373)));r=n.O(r)})(); \ No newline at end of file diff --git a/build/remote-reply/index.asset.php b/build/remote-reply/index.asset.php index 332746df0..888cb8380 100644 --- a/build/remote-reply/index.asset.php +++ b/build/remote-reply/index.asset.php @@ -1 +1 @@ - array('react', 'wp-api-fetch', 'wp-components', 'wp-compose', 'wp-dom-ready', 'wp-element', 'wp-i18n', 'wp-primitives'), 'version' => 'dbc9c5826a8c3e7e33ca'); + array('react', 'wp-api-fetch', 'wp-components', 'wp-compose', 'wp-dom-ready', 'wp-element', 'wp-i18n', 'wp-primitives'), 'version' => 'd6faa1422ba0d444a9d3'); diff --git a/build/remote-reply/index.js b/build/remote-reply/index.js index 270d4a4a9..69e42b268 100644 --- a/build/remote-reply/index.js +++ b/build/remote-reply/index.js @@ -1 +1 @@ -(()=>{"use strict";var e,t={786:(e,t,a)=>{const r=window.React,i=window.wp.element,o=window.wp.domReady;var l=a.n(o);const n=window.wp.components,c=window.wp.i18n,m=(0,i.forwardRef)((function({icon:e,size:t=24,...a},r){return(0,i.cloneElement)(e,{width:t,height:t,...a,ref:r})})),p=window.wp.primitives,s=(0,r.createElement)(p.SVG,{viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg"},(0,r.createElement)(p.Path,{d:"M12 21C16.9706 21 21 16.9706 21 12C21 7.02944 16.9706 3 12 3C7.02944 3 3 7.02944 3 12C3 16.9706 7.02944 21 12 21ZM15.5303 8.46967C15.8232 8.76256 15.8232 9.23744 15.5303 9.53033L13.0607 12L15.5303 14.4697C15.8232 14.7626 15.8232 15.2374 15.5303 15.5303C15.2374 15.8232 14.7626 15.8232 14.4697 15.5303L12 13.0607L9.53033 15.5303C9.23744 15.8232 8.76256 15.8232 8.46967 15.5303C8.17678 15.2374 8.17678 14.7626 8.46967 14.4697L10.9393 12L8.46967 9.53033C8.17678 9.23744 8.17678 8.76256 8.46967 8.46967C8.76256 8.17678 9.23744 8.17678 9.53033 8.46967L12 10.9393L14.4697 8.46967C14.7626 8.17678 15.2374 8.17678 15.5303 8.46967Z"})),u=window.wp.apiFetch;var d=a.n(u);const v=(0,r.createElement)(p.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},(0,r.createElement)(p.Path,{fillRule:"evenodd",clipRule:"evenodd",d:"M5 4.5h11a.5.5 0 0 1 .5.5v11a.5.5 0 0 1-.5.5H5a.5.5 0 0 1-.5-.5V5a.5.5 0 0 1 .5-.5ZM3 5a2 2 0 0 1 2-2h11a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5Zm17 3v10.75c0 .69-.56 1.25-1.25 1.25H6v1.5h12.75a2.75 2.75 0 0 0 2.75-2.75V8H20Z"})),y=(0,r.createElement)(p.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},(0,r.createElement)(p.Path,{d:"M16.7 7.1l-6.3 8.5-3.3-2.5-.9 1.2 4.5 3.4L17.9 8z"})),b=(0,r.createElement)(p.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},(0,r.createElement)(p.Path,{d:"M15.5 9.5a1 1 0 100-2 1 1 0 000 2zm0 1.5a2.5 2.5 0 100-5 2.5 2.5 0 000 5zm-2.25 6v-2a2.75 2.75 0 00-2.75-2.75h-4A2.75 2.75 0 003.75 15v2h1.5v-2c0-.69.56-1.25 1.25-1.25h4c.69 0 1.25.56 1.25 1.25v2h1.5zm7-2v2h-1.5v-2c0-.69-.56-1.25-1.25-1.25H15v-1.5h2.5A2.75 2.75 0 0120.25 15zM9.5 8.5a1 1 0 11-2 0 1 1 0 012 0zm1.5 0a2.5 2.5 0 11-5 0 2.5 2.5 0 015 0z",fillRule:"evenodd"})),_=window.wp.compose,f="fediverse-remote-user";function w(){const[e,t]=(0,i.useState)(function(){const e=localStorage.getItem(f);return e?JSON.parse(e):{}}()),a=(0,i.useCallback)((e=>{!function(e){localStorage.setItem(f,JSON.stringify(e))}(e),t(e)}),[]),r=(0,i.useCallback)((()=>{localStorage.removeItem(f),t({})}),[]);return{template:e?.template||!1,profileURL:e?.profileURL||!1,setRemoteUser:a,deleteRemoteUser:r}}function h(e){try{return new URL(e),!0}catch(e){return!1}}function E({actionText:e,copyDescription:t,handle:a,resourceUrl:o,myProfile:l=!1,rememberProfile:p=!1}){const s=(0,c.__)("Loading...","activitypub"),u=(0,c.__)("Opening...","activitypub"),f=(0,c.__)("Error","activitypub"),E=(0,c.__)("Invalid","activitypub"),g=l||(0,c.__)("My Profile","activitypub"),[C,R]=(0,i.useState)(e),[k,L]=(0,i.useState)(v),x=(0,_.useCopyToClipboard)(a,(()=>{L(y),setTimeout((()=>L(v)),1e3)})),[O,U]=(0,i.useState)(""),[S,N]=(0,i.useState)(!0),{setRemoteUser:P}=w(),M=(0,i.useCallback)((()=>{let t;if(!h(O)&&!function(e){const t=e.replace(/^@/,"").split("@");return 2===t.length&&h(`https://${t[1]}`)}(O))return R(E),t=setTimeout((()=>R(e)),2e3),()=>clearTimeout(t);const a=o+O;R(s),d()({path:a}).then((({url:t,template:a})=>{S&&P({profileURL:O,template:a}),R(u),setTimeout((()=>{window.open(t,"_blank"),R(e)}),200)})).catch((()=>{R(f),setTimeout((()=>R(e)),2e3)}))}),[O]);return(0,r.createElement)("div",{className:"activitypub__dialog",role:"dialog","aria-labelledby":"dialog-title"},(0,r.createElement)("div",{className:"activitypub-dialog__section"},(0,r.createElement)("h4",{id:"dialog-title"},g),(0,r.createElement)("div",{className:"activitypub-dialog__description",id:"copy-description"},t),(0,r.createElement)("div",{className:"activitypub-dialog__button-group"},(0,r.createElement)("label",{htmlFor:"profile-handle",className:"screen-reader-text"},t),(0,r.createElement)("input",{type:"text",id:"profile-handle",value:a,readOnly:!0}),(0,r.createElement)(n.Button,{ref:x,"aria-label":(0,c.__)("Copy handle to clipboard","activitypub")},(0,r.createElement)(m,{icon:k}),(0,c.__)("Copy","activitypub")))),(0,r.createElement)("div",{className:"activitypub-dialog__section"},(0,r.createElement)("h4",{id:"remote-profile-title"},(0,c.__)("Your Profile","activitypub")),(0,r.createElement)("div",{className:"activitypub-dialog__description",id:"remote-profile-description"},(0,i.createInterpolateElement)((0,c.__)("Or, if you know your own profile, we can start things that way! (eg @yourusername@example.com)","activitypub"),{code:(0,r.createElement)("code",null)})),(0,r.createElement)("div",{className:"activitypub-dialog__button-group"},(0,r.createElement)("label",{htmlFor:"remote-profile",className:"screen-reader-text"},(0,c.__)("Enter your ActivityPub profile","activitypub")),(0,r.createElement)("input",{type:"text",id:"remote-profile",value:O,onKeyDown:e=>{"Enter"===e?.code&&M()},onChange:e=>U(e.target.value),"aria-invalid":C===E}),(0,r.createElement)(n.Button,{onClick:M,"aria-label":(0,c.__)("Submit profile","activitypub")},(0,r.createElement)(m,{icon:b}),C)),p&&(0,r.createElement)("div",{className:"activitypub-dialog__remember"},(0,r.createElement)(n.CheckboxControl,{checked:S,label:(0,c.__)("Remember me for easier comments","activitypub"),onChange:()=>{N(!S)}}))))}function g({selectedComment:e,commentId:t}){const{namespace:a}=window._activityPubOptions||{},i=(0,c.__)("Reply","activitypub"),o=`/${a}/comments/${t}/remote-reply?resource=`,l=(0,c.__)("Copy and paste the Comment URL into the search field of your favorite fediverse app or server.","activitypub");return(0,r.createElement)(E,{actionText:i,copyDescription:l,handle:e,resourceUrl:o,myProfile:(0,c.__)("Original Comment URL","activitypub"),rememberProfile:!0})}function C({profileURL:e,template:t,commentURL:a,deleteRemoteUser:i}){return(0,r.createElement)(r.Fragment,null,(0,r.createElement)(n.Button,{variant:"link",className:"comment-reply-link activitypub-remote-reply__button",onClick:()=>{const e=t.replace("{uri}",a);window.open(e,"_blank")}},(0,c.sprintf)((0,c.__)("Reply as %s","activitypub"),e)),(0,r.createElement)(n.Button,{className:"activitypub-remote-profile-delete",onClick:i,title:(0,c.__)("Delete Remote Profile","activitypub")},(0,r.createElement)(m,{icon:s,size:18})))}function R({selectedComment:e,commentId:t}){const[a,o]=(0,i.useState)(!1),l=(0,c.__)("Remote Reply","activitypub"),{profileURL:m,template:p,deleteRemoteUser:s}=w(),u=m&&p;return(0,r.createElement)(r.Fragment,null,u?(0,r.createElement)(C,{profileURL:m,template:p,commentURL:e,deleteRemoteUser:s}):(0,r.createElement)(n.Button,{variant:"link",className:"comment-reply-link activitypub-remote-reply__button",onClick:()=>o(!0)},(0,c.__)("Reply on the Fediverse","activitypub")),a&&(0,r.createElement)(n.Modal,{className:"activitypub-remote-reply__modal activitypub__modal",onRequestClose:()=>o(!1),title:l},(0,r.createElement)(g,{selectedComment:e,commentId:t})))}let k=1;l()((()=>{[].forEach.call(document.querySelectorAll(".activitypub-remote-reply"),(e=>{const t=JSON.parse(e.dataset.attrs);(0,i.createRoot)(e).render((0,r.createElement)(R,{...t,id:"activitypub-remote-reply-link-"+k++,useId:!0}))}))}))}},a={};function r(e){var i=a[e];if(void 0!==i)return i.exports;var o=a[e]={exports:{}};return t[e](o,o.exports,r),o.exports}r.m=t,e=[],r.O=(t,a,i,o)=>{if(!a){var l=1/0;for(p=0;p=o)&&Object.keys(r.O).every((e=>r.O[e](a[c])))?a.splice(c--,1):(n=!1,o0&&e[p-1][2]>o;p--)e[p]=e[p-1];e[p]=[a,i,o]},r.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return r.d(t,{a:t}),t},r.d=(e,t)=>{for(var a in t)r.o(t,a)&&!r.o(e,a)&&Object.defineProperty(e,a,{enumerable:!0,get:t[a]})},r.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{var e={227:0,739:0};r.O.j=t=>0===e[t];var t=(t,a)=>{var i,o,[l,n,c]=a,m=0;if(l.some((t=>0!==e[t]))){for(i in n)r.o(n,i)&&(r.m[i]=n[i]);if(c)var p=c(r)}for(t&&t(a);mr(786)));i=r.O(i)})(); \ No newline at end of file +(()=>{"use strict";var e,t={170:(e,t,r)=>{var o=r(609);const a=window.wp.element,i=window.wp.domReady;var n=r.n(i);const l=window.wp.components,c=window.wp.i18n,s=(0,a.forwardRef)((function({icon:e,size:t=24,...r},o){return(0,a.cloneElement)(e,{width:t,height:t,...r,ref:o})})),m=window.wp.primitives;var p=r(848);const u=(0,p.jsx)(m.SVG,{viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",children:(0,p.jsx)(m.Path,{d:"M12 21C16.9706 21 21 16.9706 21 12C21 7.02944 16.9706 3 12 3C7.02944 3 3 7.02944 3 12C3 16.9706 7.02944 21 12 21ZM15.5303 8.46967C15.8232 8.76256 15.8232 9.23744 15.5303 9.53033L13.0607 12L15.5303 14.4697C15.8232 14.7626 15.8232 15.2374 15.5303 15.5303C15.2374 15.8232 14.7626 15.8232 14.4697 15.5303L12 13.0607L9.53033 15.5303C9.23744 15.8232 8.76256 15.8232 8.46967 15.5303C8.17678 15.2374 8.17678 14.7626 8.46967 14.4697L10.9393 12L8.46967 9.53033C8.17678 9.23744 8.17678 8.76256 8.46967 8.46967C8.76256 8.17678 9.23744 8.17678 9.53033 8.46967L12 10.9393L14.4697 8.46967C14.7626 8.17678 15.2374 8.17678 15.5303 8.46967Z"})}),d=window.wp.apiFetch;var v=r.n(d);const y=(0,p.jsx)(m.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,p.jsx)(m.Path,{fillRule:"evenodd",clipRule:"evenodd",d:"M5 4.5h11a.5.5 0 0 1 .5.5v11a.5.5 0 0 1-.5.5H5a.5.5 0 0 1-.5-.5V5a.5.5 0 0 1 .5-.5ZM3 5a2 2 0 0 1 2-2h11a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5Zm17 3v10.75c0 .69-.56 1.25-1.25 1.25H6v1.5h12.75a2.75 2.75 0 0 0 2.75-2.75V8H20Z"})}),_=(0,p.jsx)(m.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,p.jsx)(m.Path,{d:"M16.7 7.1l-6.3 8.5-3.3-2.5-.9 1.2 4.5 3.4L17.9 8z"})}),f=(0,p.jsx)(m.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,p.jsx)(m.Path,{d:"M15.5 9.5a1 1 0 100-2 1 1 0 000 2zm0 1.5a2.5 2.5 0 100-5 2.5 2.5 0 000 5zm-2.25 6v-2a2.75 2.75 0 00-2.75-2.75h-4A2.75 2.75 0 003.75 15v2h1.5v-2c0-.69.56-1.25 1.25-1.25h4c.69 0 1.25.56 1.25 1.25v2h1.5zm7-2v2h-1.5v-2c0-.69-.56-1.25-1.25-1.25H15v-1.5h2.5A2.75 2.75 0 0120.25 15zM9.5 8.5a1 1 0 11-2 0 1 1 0 012 0zm1.5 0a2.5 2.5 0 11-5 0 2.5 2.5 0 015 0z",fillRule:"evenodd"})}),b=window.wp.compose,w="fediverse-remote-user";function h(){const[e,t]=(0,a.useState)(function(){const e=localStorage.getItem(w);return e?JSON.parse(e):{}}()),r=(0,a.useCallback)((e=>{!function(e){localStorage.setItem(w,JSON.stringify(e))}(e),t(e)}),[]),o=(0,a.useCallback)((()=>{localStorage.removeItem(w),t({})}),[]);return{template:e?.template||!1,profileURL:e?.profileURL||!1,setRemoteUser:r,deleteRemoteUser:o}}function g(e){try{return new URL(e),!0}catch(e){return!1}}function E({actionText:e,copyDescription:t,handle:r,resourceUrl:i,myProfile:n=!1,rememberProfile:m=!1}){const p=(0,c.__)("Loading...","activitypub"),u=(0,c.__)("Opening...","activitypub"),d=(0,c.__)("Error","activitypub"),w=(0,c.__)("Invalid","activitypub"),E=n||(0,c.__)("My Profile","activitypub"),[C,R]=(0,a.useState)(e),[x,O]=(0,a.useState)(y),k=(0,b.useCopyToClipboard)(r,(()=>{O(_),setTimeout((()=>O(y)),1e3)})),[L,S]=(0,a.useState)(""),[U,N]=(0,a.useState)(!0),{setRemoteUser:P}=h(),j=(0,a.useCallback)((()=>{let t;if(!g(L)&&!function(e){const t=e.replace(/^@/,"").split("@");return 2===t.length&&g(`https://${t[1]}`)}(L))return R(w),t=setTimeout((()=>R(e)),2e3),()=>clearTimeout(t);const r=i+L;R(p),v()({path:r}).then((({url:t,template:r})=>{U&&P({profileURL:L,template:r}),R(u),setTimeout((()=>{window.open(t,"_blank"),R(e)}),200)})).catch((()=>{R(d),setTimeout((()=>R(e)),2e3)}))}),[L]);return(0,o.createElement)("div",{className:"activitypub__dialog",role:"dialog","aria-labelledby":"dialog-title"},(0,o.createElement)("div",{className:"activitypub-dialog__section"},(0,o.createElement)("h4",{id:"dialog-title"},E),(0,o.createElement)("div",{className:"activitypub-dialog__description",id:"copy-description"},t),(0,o.createElement)("div",{className:"activitypub-dialog__button-group"},(0,o.createElement)("label",{htmlFor:"profile-handle",className:"screen-reader-text"},t),(0,o.createElement)("input",{type:"text",id:"profile-handle",value:r,readOnly:!0}),(0,o.createElement)(l.Button,{ref:k,"aria-label":(0,c.__)("Copy handle to clipboard","activitypub")},(0,o.createElement)(s,{icon:x}),(0,c.__)("Copy","activitypub")))),(0,o.createElement)("div",{className:"activitypub-dialog__section"},(0,o.createElement)("h4",{id:"remote-profile-title"},(0,c.__)("Your Profile","activitypub")),(0,o.createElement)("div",{className:"activitypub-dialog__description",id:"remote-profile-description"},(0,a.createInterpolateElement)((0,c.__)("Or, if you know your own profile, we can start things that way! (eg @yourusername@example.com)","activitypub"),{code:(0,o.createElement)("code",null)})),(0,o.createElement)("div",{className:"activitypub-dialog__button-group"},(0,o.createElement)("label",{htmlFor:"remote-profile",className:"screen-reader-text"},(0,c.__)("Enter your ActivityPub profile","activitypub")),(0,o.createElement)("input",{type:"text",id:"remote-profile",value:L,onKeyDown:e=>{"Enter"===e?.code&&j()},onChange:e=>S(e.target.value),"aria-invalid":C===w}),(0,o.createElement)(l.Button,{onClick:j,"aria-label":(0,c.__)("Submit profile","activitypub")},(0,o.createElement)(s,{icon:f}),C)),m&&(0,o.createElement)("div",{className:"activitypub-dialog__remember"},(0,o.createElement)(l.CheckboxControl,{checked:U,label:(0,c.__)("Remember me for easier comments","activitypub"),onChange:()=>{N(!U)}}))))}function C({selectedComment:e,commentId:t}){const{namespace:r}=window._activityPubOptions||{},a=(0,c.__)("Reply","activitypub"),i=`/${r}/comments/${t}/remote-reply?resource=`,n=(0,c.__)("Copy and paste the Comment URL into the search field of your favorite fediverse app or server.","activitypub");return(0,o.createElement)(E,{actionText:a,copyDescription:n,handle:e,resourceUrl:i,myProfile:(0,c.__)("Original Comment URL","activitypub"),rememberProfile:!0})}function R({profileURL:e,template:t,commentURL:r,deleteRemoteUser:a}){return(0,o.createElement)(o.Fragment,null,(0,o.createElement)(l.Button,{variant:"link",className:"comment-reply-link activitypub-remote-reply__button",onClick:()=>{const e=t.replace("{uri}",r);window.open(e,"_blank")}},(0,c.sprintf)((0,c.__)("Reply as %s","activitypub"),e)),(0,o.createElement)(l.Button,{className:"activitypub-remote-profile-delete",onClick:a,title:(0,c.__)("Delete Remote Profile","activitypub")},(0,o.createElement)(s,{icon:u,size:18})))}function x({selectedComment:e,commentId:t}){const[r,i]=(0,a.useState)(!1),n=(0,c.__)("Remote Reply","activitypub"),{profileURL:s,template:m,deleteRemoteUser:p}=h(),u=s&&m;return(0,o.createElement)(o.Fragment,null,u?(0,o.createElement)(R,{profileURL:s,template:m,commentURL:e,deleteRemoteUser:p}):(0,o.createElement)(l.Button,{variant:"link",className:"comment-reply-link activitypub-remote-reply__button",onClick:()=>i(!0)},(0,c.__)("Reply on the Fediverse","activitypub")),r&&(0,o.createElement)(l.Modal,{className:"activitypub-remote-reply__modal activitypub__modal",onRequestClose:()=>i(!1),title:n},(0,o.createElement)(C,{selectedComment:e,commentId:t})))}let O=1;n()((()=>{[].forEach.call(document.querySelectorAll(".activitypub-remote-reply"),(e=>{const t=JSON.parse(e.dataset.attrs);(0,a.createRoot)(e).render((0,o.createElement)(x,{...t,id:"activitypub-remote-reply-link-"+O++,useId:!0}))}))}))},20:(e,t,r)=>{var o=r(609),a=Symbol.for("react.element"),i=(Symbol.for("react.fragment"),Object.prototype.hasOwnProperty),n=o.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,l={key:!0,ref:!0,__self:!0,__source:!0};t.jsx=function(e,t,r){var o,c={},s=null,m=null;for(o in void 0!==r&&(s=""+r),void 0!==t.key&&(s=""+t.key),void 0!==t.ref&&(m=t.ref),t)i.call(t,o)&&!l.hasOwnProperty(o)&&(c[o]=t[o]);if(e&&e.defaultProps)for(o in t=e.defaultProps)void 0===c[o]&&(c[o]=t[o]);return{$$typeof:a,type:e,key:s,ref:m,props:c,_owner:n.current}}},848:(e,t,r)=>{e.exports=r(20)},609:e=>{e.exports=window.React}},r={};function o(e){var a=r[e];if(void 0!==a)return a.exports;var i=r[e]={exports:{}};return t[e](i,i.exports,o),i.exports}o.m=t,e=[],o.O=(t,r,a,i)=>{if(!r){var n=1/0;for(m=0;m=i)&&Object.keys(o.O).every((e=>o.O[e](r[c])))?r.splice(c--,1):(l=!1,i0&&e[m-1][2]>i;m--)e[m]=e[m-1];e[m]=[r,a,i]},o.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return o.d(t,{a:t}),t},o.d=(e,t)=>{for(var r in t)o.o(t,r)&&!o.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},o.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{var e={227:0,739:0};o.O.j=t=>0===e[t];var t=(t,r)=>{var a,i,n=r[0],l=r[1],c=r[2],s=0;if(n.some((t=>0!==e[t]))){for(a in l)o.o(l,a)&&(o.m[a]=l[a]);if(c)var m=c(o)}for(t&&t(r);so(170)));a=o.O(a)})(); \ No newline at end of file diff --git a/build/reply/index.asset.php b/build/reply/index.asset.php index 76928c260..2e7cd8438 100644 --- a/build/reply/index.asset.php +++ b/build/reply/index.asset.php @@ -1 +1 @@ - array('react', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-element', 'wp-i18n', 'wp-primitives'), 'version' => '6e4203d933b0e0349c2a'); + array('react', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-element', 'wp-i18n', 'wp-primitives'), 'version' => '808c98599517db815fc5'); diff --git a/build/reply/index.js b/build/reply/index.js index 58c6c7202..9cabdce19 100644 --- a/build/reply/index.js +++ b/build/reply/index.js @@ -1 +1 @@ -(()=>{"use strict";const e=window.wp.blocks,t=window.React,o=window.wp.primitives,i=(0,t.createElement)(o.SVG,{width:"24",height:"24",viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg"},(0,t.createElement)(o.Path,{d:"M6.68822 10.625L6.24878 11.0649L5.5 11.8145L5.5 5.5L12.5 5.5V8L14 6.5V5C14 4.44772 13.5523 4 13 4H5C4.44772 4 4 4.44771 4 5V13.5247C4 13.8173 4.16123 14.086 4.41935 14.2237C4.72711 14.3878 5.10601 14.3313 5.35252 14.0845L7.31 12.125H8.375L9.875 10.625H7.31H6.68822ZM14.5605 10.4983L11.6701 13.75H16.9975C17.9963 13.75 18.7796 14.1104 19.3553 14.7048C19.9095 15.2771 20.2299 16.0224 20.4224 16.7443C20.7645 18.0276 20.7543 19.4618 20.7487 20.2544C20.7481 20.345 20.7475 20.4272 20.7475 20.4999L19.2475 20.5001C19.2475 20.4191 19.248 20.3319 19.2484 20.2394V20.2394C19.2526 19.4274 19.259 18.2035 18.973 17.1307C18.8156 16.5401 18.586 16.0666 18.2778 15.7483C17.9909 15.4521 17.5991 15.25 16.9975 15.25H11.8106L14.5303 17.9697L13.4696 19.0303L8.96956 14.5303L13.4394 9.50171L14.5605 10.4983Z"})),n=window.wp.i18n,r=window.wp.blockEditor,a=window.wp.components,l=window.wp.element,s=window.wp.data;(0,e.registerBlockType)("activitypub/reply",{edit:function({attributes:e,setAttributes:o,clientId:i,isSelected:c}){const[w,p]=(0,l.useState)(""),{insertAfterBlock:u,removeBlock:d}=(0,s.useDispatch)(r.store),L=(0,n.__)("For example: Paste a URL from a Mastodon post or note into the field above to leave a comment.","activitypub"),[h,m]=(0,l.useState)(L);return(0,t.createElement)("div",{...(0,r.useBlockProps)()},(0,t.createElement)(a.TextControl,{label:(0,n.__)("This post is a reply to the following URL","activitypub"),value:e.url,onChange:e=>{!function(e){try{return new URL(e),!0}catch(e){return!1}}(e)?(p("error"),m((0,n.__)("Please enter a valid URL.","activitypub"))):(p(""),m(L)),o({url:e})},onKeyDown:t=>{"Enter"===t.key&&u(i),!e.url&&["Backspace","Delete"].includes(t.key)&&d(i)},type:"url",placeholder:"https://example.org/path",className:w,help:c?h:""}))},save:()=>null,icon:i})})(); \ No newline at end of file +(()=>{"use strict";var e={20:(e,t,r)=>{var o=r(609),n=Symbol.for("react.element"),i=(Symbol.for("react.fragment"),Object.prototype.hasOwnProperty),a=o.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,s={key:!0,ref:!0,__self:!0,__source:!0};t.jsx=function(e,t,r){var o,l={},p=null,c=null;for(o in void 0!==r&&(p=""+r),void 0!==t.key&&(p=""+t.key),void 0!==t.ref&&(c=t.ref),t)i.call(t,o)&&!s.hasOwnProperty(o)&&(l[o]=t[o]);if(e&&e.defaultProps)for(o in t=e.defaultProps)void 0===l[o]&&(l[o]=t[o]);return{$$typeof:n,type:e,key:p,ref:c,props:l,_owner:a.current}}},848:(e,t,r)=>{e.exports=r(20)},609:e=>{e.exports=window.React}},t={};function r(o){var n=t[o];if(void 0!==n)return n.exports;var i=t[o]={exports:{}};return e[o](i,i.exports,r),i.exports}const o=window.wp.blocks,n=window.wp.primitives;var i=r(848);const a=(0,i.jsx)(n.SVG,{width:"24",height:"24",viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",children:(0,i.jsx)(n.Path,{d:"M6.68822 10.625L6.24878 11.0649L5.5 11.8145L5.5 5.5L12.5 5.5V8L14 6.5V5C14 4.44772 13.5523 4 13 4H5C4.44772 4 4 4.44771 4 5V13.5247C4 13.8173 4.16123 14.086 4.41935 14.2237C4.72711 14.3878 5.10601 14.3313 5.35252 14.0845L7.31 12.125H8.375L9.875 10.625H7.31H6.68822ZM14.5605 10.4983L11.6701 13.75H16.9975C17.9963 13.75 18.7796 14.1104 19.3553 14.7048C19.9095 15.2771 20.2299 16.0224 20.4224 16.7443C20.7645 18.0276 20.7543 19.4618 20.7487 20.2544C20.7481 20.345 20.7475 20.4272 20.7475 20.4999L19.2475 20.5001C19.2475 20.4191 19.248 20.3319 19.2484 20.2394V20.2394C19.2526 19.4274 19.259 18.2035 18.973 17.1307C18.8156 16.5401 18.586 16.0666 18.2778 15.7483C17.9909 15.4521 17.5991 15.25 16.9975 15.25H11.8106L14.5303 17.9697L13.4696 19.0303L8.96956 14.5303L13.4394 9.50171L14.5605 10.4983Z"})});var s=r(609);const l=window.wp.i18n,p=window.wp.blockEditor,c=window.wp.components,w=window.wp.element,u=window.wp.data;(0,o.registerBlockType)("activitypub/reply",{edit:function({attributes:e,setAttributes:t,clientId:r,isSelected:o}){const[n,i]=(0,w.useState)(""),{insertAfterBlock:a,removeBlock:d}=(0,u.useDispatch)(p.store),v=(0,l.__)("For example: Paste a URL from a Mastodon post or note into the field above to leave a comment.","activitypub"),[f,y]=(0,w.useState)(v);return(0,s.createElement)("div",{...(0,p.useBlockProps)()},(0,s.createElement)(c.TextControl,{label:(0,l.__)("This post is a reply to the following URL","activitypub"),value:e.url,onChange:e=>{!function(e){try{return new URL(e),!0}catch(e){return!1}}(e)?(i("error"),y((0,l.__)("Please enter a valid URL.","activitypub"))):(i(""),y(v)),t({url:e})},onKeyDown:t=>{"Enter"===t.key&&a(r),!e.url&&["Backspace","Delete"].includes(t.key)&&d(r)},type:"url",placeholder:"https://example.org/path",className:n,help:o?f:""}))},save:()=>null,icon:a})})(); \ No newline at end of file diff --git a/includes/class-admin.php b/includes/class-admin.php index c5b67bebc..e9f9b9898 100644 --- a/includes/class-admin.php +++ b/includes/class-admin.php @@ -74,8 +74,8 @@ public static function admin_menu() { // User has to be able to publish posts. if ( ! is_user_disabled( get_current_user_id() ) ) { $followers_list_page = \add_users_page( - \__( '⁂ Followers', 'activitypub' ), - \__( '⁂ Followers', 'activitypub' ), + \__( 'Followers ⁂', 'activitypub' ), + \__( 'Followers ⁂', 'activitypub' ), 'activitypub', 'activitypub-followers-list', array( @@ -90,8 +90,8 @@ public static function admin_menu() { ); \add_users_page( - \__( '⁂ Extra Fields', 'activitypub' ), - \__( '⁂ Extra Fields', 'activitypub' ), + \__( 'Extra Fields ⁂', 'activitypub' ), + \__( 'Extra Fields ⁂', 'activitypub' ), 'activitypub', \esc_url( \admin_url( '/edit.php?post_type=ap_extrafield' ) ) ); @@ -866,7 +866,7 @@ public static function dashboard_glance_items( $items ) { } /** - * Add a "⁂ Preview" link to the row actions. + * Add a "Fediverse Preview ⁂" link to the row actions. * * @param array $actions The existing actions. * @param \WP_Post $post The post object. @@ -890,7 +890,7 @@ public static function row_actions( $actions, $post ) { $actions['activitypub'] = sprintf( '%s', \esc_url( $preview_url ), - \esc_html__( '⁂ Fediverse Preview', 'activitypub' ) + \esc_html__( 'Fediverse Preview ⁂', 'activitypub' ) ); return $actions; diff --git a/src/editor-plugin/plugin.js b/src/editor-plugin/plugin.js index f15921f82..71126674b 100644 --- a/src/editor-plugin/plugin.js +++ b/src/editor-plugin/plugin.js @@ -51,7 +51,7 @@ const EditorPlugin = () => { return ( { icon={ external } disabled={ post_status === 'auto-draft' } > - { __( '⁂ Fediverse preview', 'activitypub' ) } + { __( 'Fediverse preview ⁂', 'activitypub' ) } ) : null } diff --git a/templates/toolbox.php b/templates/toolbox.php index 21d786e38..19fa797df 100644 --- a/templates/toolbox.php +++ b/templates/toolbox.php @@ -8,7 +8,7 @@ ?>
-

+

From 1e35c38355fdabf6f33af4c6b9775bcfccf9ebb9 Mon Sep 17 00:00:00 2001 From: Konstantin Obenland Date: Wed, 5 Feb 2025 13:15:31 +0100 Subject: [PATCH 04/18] Update Followers endpoint to extend WP_REST_Controller (#1266) * Move file * Update followers endpoint to extend WP_REST_Controlelr * Inherit from Actors_Controller * update schema * Remove debug * Adopt pagination from Outbox Controller Props @pfefferle * Prevent requests that go beyond what's available Props @pfefferle --------- Co-authored-by: Matthias Pfefferle --- activitypub.php | 2 +- includes/rest/class-followers-controller.php | 300 ++++++++++++++++++ includes/rest/class-followers.php | 149 --------- .../rest/class-test-followers-controller.php | 192 +++++++++++ 4 files changed, 493 insertions(+), 150 deletions(-) create mode 100644 includes/rest/class-followers-controller.php delete mode 100644 includes/rest/class-followers.php create mode 100644 tests/includes/rest/class-test-followers-controller.php diff --git a/activitypub.php b/activitypub.php index 5a61475de..f75eb2f06 100644 --- a/activitypub.php +++ b/activitypub.php @@ -40,13 +40,13 @@ */ function rest_init() { Rest\Inbox::init(); - Rest\Followers::init(); Rest\Comment::init(); Rest\Server::init(); Rest\Collection::init(); Rest\Post::init(); ( new Rest\Actors_Controller() )->register_routes(); ( new Rest\Application_Controller() )->register_routes(); + ( new Rest\Followers_Controller() )->register_routes(); ( new Rest\Following_Controller() )->register_routes(); ( new Rest\Interaction_Controller() )->register_routes(); ( new Rest\Outbox_Controller() )->register_routes(); diff --git a/includes/rest/class-followers-controller.php b/includes/rest/class-followers-controller.php new file mode 100644 index 000000000..dfa02510d --- /dev/null +++ b/includes/rest/class-followers-controller.php @@ -0,0 +1,300 @@ +namespace, + '/' . $this->rest_base . '/followers', + array( + 'args' => array( + 'user_id' => array( + 'description' => 'The ID or username of the actor.', + 'type' => 'string', + 'required' => true, + 'pattern' => '[\w\-\.]+', + ), + ), + array( + 'methods' => \WP_REST_Server::READABLE, + 'callback' => array( $this, 'get_items' ), + 'permission_callback' => array( 'Activitypub\Rest\Server', 'verify_signature' ), + 'args' => array( + 'page' => array( + 'description' => 'Current page of the collection.', + 'type' => 'integer', + 'default' => 1, + 'minimum' => 1, + ), + 'per_page' => array( + 'description' => 'Maximum number of items to be returned in result set.', + 'type' => 'integer', + 'default' => 20, + 'minimum' => 1, + ), + 'order' => array( + 'description' => 'Order sort attribute ascending or descending.', + 'type' => 'string', + 'default' => 'desc', + 'enum' => array( 'asc', 'desc' ), + ), + 'context' => array( + 'description' => 'The context in which the request is made.', + 'type' => 'string', + 'default' => 'simple', + 'enum' => array( 'simple', 'full' ), + ), + ), + ), + 'schema' => array( $this, 'get_item_schema' ), + ) + ); + } + + /** + * Retrieves followers list. + * + * @param \WP_REST_Request $request Full details about the request. + * @return \WP_REST_Response|\WP_Error Response object on success, or WP_Error object on failure. + */ + public function get_items( $request ) { + $user_id = $request->get_param( 'user_id' ); + $user = Actors::get_by_various( $user_id ); + + if ( \is_wp_error( $user ) ) { + return $user; + } + + /** + * Action triggered prior to the ActivityPub profile being created and sent to the client. + */ + \do_action( 'activitypub_rest_followers_pre' ); + + $order = $request->get_param( 'order' ); + $per_page = $request->get_param( 'per_page' ); + $page = $request->get_param( 'page' ); + $context = $request->get_param( 'context' ); + + $data = Follower_Collection::get_followers_with_count( $user_id, $per_page, $page, array( 'order' => \ucwords( $order ) ) ); + + $response = array( + '@context' => \Activitypub\get_context(), + 'id' => get_rest_url_by_path( \sprintf( 'actors/%d/followers', $user->get__id() ) ), + 'generator' => 'https://wordpress.org/?v=' . get_masked_wp_version(), + 'actor' => $user->get_id(), + 'type' => 'OrderedCollectionPage', + 'totalItems' => $data['total'], + 'partOf' => get_rest_url_by_path( \sprintf( 'actors/%d/followers', $user->get__id() ) ), + 'orderedItems' => array_map( + function ( $item ) use ( $context ) { + if ( 'full' === $context ) { + return $item->to_array( false ); + } + return $item->get_id(); + }, + $data['followers'] + ), + ); + + $max_pages = \ceil( $response['totalItems'] / $per_page ); + + if ( $page > $max_pages ) { + return new \WP_Error( + 'rest_post_invalid_page_number', + 'The page number requested is larger than the number of pages available.', + array( 'status' => 400 ) + ); + } + + $response['first'] = \add_query_arg( 'page', 1, $response['partOf'] ); + $response['last'] = \add_query_arg( 'page', \max( $max_pages, 1 ), $response['partOf'] ); + + if ( $max_pages > $page ) { + $response['next'] = \add_query_arg( 'page', $page + 1, $response['partOf'] ); + } + + if ( $page > 1 ) { + $response['prev'] = \add_query_arg( 'page', $page - 1, $response['partOf'] ); + } + + $response = \rest_ensure_response( $response ); + $response->header( 'Content-Type', 'application/activity+json; charset=' . \get_option( 'blog_charset' ) ); + + return $response; + } + + /** + * Retrieves the followers schema, conforming to JSON Schema. + * + * @return array Item schema data. + */ + public function get_item_schema() { + if ( $this->schema ) { + return $this->add_additional_fields_schema( $this->schema ); + } + + $this->schema = array( + '$schema' => 'http://json-schema.org/draft-04/schema#', + 'title' => 'followers', + 'type' => 'object', + 'properties' => array( + '@context' => array( + 'description' => 'The JSON-LD context for the response.', + 'type' => array( 'array', 'object' ), + 'readonly' => true, + ), + 'id' => array( + 'description' => 'The unique identifier for the followers collection.', + 'type' => 'string', + 'format' => 'uri', + 'readonly' => true, + ), + 'generator' => array( + 'description' => 'The generator of the followers collection.', + 'type' => 'string', + 'format' => 'uri', + 'readonly' => true, + ), + 'actor' => array( + 'description' => 'The actor who owns the followers collection.', + 'type' => 'string', + 'format' => 'uri', + 'readonly' => true, + ), + 'type' => array( + 'description' => 'The type of the followers collection.', + 'type' => 'string', + 'enum' => array( 'OrderedCollectionPage' ), + 'readonly' => true, + ), + 'totalItems' => array( + 'description' => 'The total number of items in the followers collection.', + 'type' => 'integer', + 'readonly' => true, + ), + 'partOf' => array( + 'description' => 'The collection this page is part of.', + 'type' => 'string', + 'format' => 'uri', + 'readonly' => true, + ), + 'orderedItems' => array( + 'description' => 'The items in the followers collection.', + 'type' => 'array', + 'items' => array( + 'oneOf' => array( + array( + 'type' => 'string', + 'format' => 'uri', + ), + array( + 'type' => 'object', + 'properties' => array( + 'id' => array( + 'type' => 'string', + 'format' => 'uri', + ), + 'type' => array( + 'type' => 'string', + ), + 'name' => array( + 'type' => 'string', + ), + 'icon' => array( + 'type' => 'object', + 'properties' => array( + 'type' => array( + 'type' => 'string', + ), + 'mediaType' => array( + 'type' => 'string', + ), + 'url' => array( + 'type' => 'string', + 'format' => 'uri', + ), + ), + ), + 'published' => array( + 'type' => 'string', + 'format' => 'date-time', + ), + 'summary' => array( + 'type' => 'string', + ), + 'updated' => array( + 'type' => 'string', + 'format' => 'date-time', + ), + 'url' => array( + 'type' => 'string', + 'format' => 'uri', + ), + 'streams' => array( + 'type' => 'array', + ), + 'preferredUsername' => array( + 'type' => 'string', + ), + 'manuallyApprovesFollowers' => array( + 'type' => 'boolean', + ), + ), + ), + ), + ), + 'readonly' => true, + ), + 'next' => array( + 'description' => 'The next page in the collection.', + 'type' => 'string', + 'format' => 'uri', + 'readonly' => true, + ), + 'prev' => array( + 'description' => 'The previous page in the collection.', + 'type' => 'string', + 'format' => 'uri', + 'readonly' => true, + ), + 'first' => array( + 'description' => 'The first page in the collection.', + 'type' => 'string', + 'format' => 'uri', + 'readonly' => true, + ), + 'last' => array( + 'description' => 'The last page in the collection.', + 'type' => 'string', + 'format' => 'uri', + 'readonly' => true, + ), + ), + ); + + return $this->add_additional_fields_schema( $this->schema ); + } +} diff --git a/includes/rest/class-followers.php b/includes/rest/class-followers.php deleted file mode 100644 index ee25ecc98..000000000 --- a/includes/rest/class-followers.php +++ /dev/null @@ -1,149 +0,0 @@ -[\w\-\.]+)/followers', - array( - array( - 'methods' => WP_REST_Server::READABLE, - 'callback' => array( self::class, 'get' ), - 'args' => self::request_parameters(), - 'permission_callback' => array( 'Activitypub\Rest\Server', 'verify_signature' ), - ), - ) - ); - } - - /** - * Handle GET request - * - * @param \WP_REST_Request $request The request object. - * - * @return WP_REST_Response|\WP_Error The response object or WP_Error. - */ - public static function get( $request ) { - $user_id = $request->get_param( 'user_id' ); - $user = Actors::get_by_various( $user_id ); - - if ( is_wp_error( $user ) ) { - return $user; - } - - $order = $request->get_param( 'order' ); - $per_page = (int) $request->get_param( 'per_page' ); - $page = (int) $request->get_param( 'page' ); - $context = $request->get_param( 'context' ); - - /** - * Action triggered prior to the ActivityPub profile being created and sent to the client - */ - \do_action( 'activitypub_rest_followers_pre' ); - - $data = Follower_Collection::get_followers_with_count( $user_id, $per_page, $page, array( 'order' => ucwords( $order ) ) ); - $json = new stdClass(); - - // phpcs:disable WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase - $json->{'@context'} = \Activitypub\get_context(); - $json->id = get_rest_url_by_path( sprintf( 'actors/%d/followers', $user->get__id() ) ); - $json->generator = 'http://wordpress.org/?v=' . get_masked_wp_version(); - $json->actor = $user->get_id(); - $json->type = 'OrderedCollectionPage'; - $json->totalItems = $data['total']; - $json->partOf = get_rest_url_by_path( sprintf( 'actors/%d/followers', $user->get__id() ) ); - - $json->first = \add_query_arg( 'page', 1, $json->partOf ); - $json->last = \add_query_arg( 'page', \ceil( $json->totalItems / $per_page ), $json->partOf ); - - if ( $page && ( ( \ceil( $json->totalItems / $per_page ) ) > $page ) ) { - $json->next = \add_query_arg( 'page', $page + 1, $json->partOf ); - } - - if ( $page && ( $page > 1 ) ) { - $json->prev = \add_query_arg( 'page', $page - 1, $json->partOf ); - } - - $json->orderedItems = array_map( - function ( $item ) use ( $context ) { - if ( 'full' === $context ) { - return $item->to_array( false ); - } - return $item->get_id(); - }, - $data['followers'] - ); - // phpcs:enable WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase - - $rest_response = new WP_REST_Response( $json, 200 ); - $rest_response->header( 'Content-Type', 'application/activity+json; charset=' . get_option( 'blog_charset' ) ); - - return $rest_response; - } - - /** - * The supported parameters. - * - * @return array List of parameters. - */ - public static function request_parameters() { - $params = array(); - - $params['page'] = array( - 'type' => 'integer', - 'default' => 1, - ); - - $params['per_page'] = array( - 'type' => 'integer', - 'default' => 20, - ); - - $params['order'] = array( - 'type' => 'string', - 'default' => 'desc', - 'enum' => array( 'asc', 'desc' ), - ); - - $params['context'] = array( - 'type' => 'string', - 'default' => 'simple', - 'enum' => array( 'simple', 'full' ), - ); - - return $params; - } -} diff --git a/tests/includes/rest/class-test-followers-controller.php b/tests/includes/rest/class-test-followers-controller.php new file mode 100644 index 000000000..1efa6b10b --- /dev/null +++ b/tests/includes/rest/class-test-followers-controller.php @@ -0,0 +1,192 @@ +post->create_many( + 25, + array( + 'post_type' => Followers::POST_TYPE, + 'meta_input' => array( + '_activitypub_user_id' => '0', + '_activitypub_actor_json' => wp_json_encode( + array( + 'id' => 'https://example.org/actor/1', + 'type' => 'Person', + 'preferredUsername' => 'user1', + 'name' => 'User 1', + ) + ), + ), + ) + ); + } + + /** + * Test route registration. + * + * @covers ::register_routes + */ + public function test_register_routes() { + $routes = rest_get_server()->get_routes(); + $this->assertArrayHasKey( '/' . ACTIVITYPUB_REST_NAMESPACE . '/(?:users|actors)\/(?P[\w\-\.]+)/followers', $routes ); + } + + /** + * Test schema. + * + * @covers ::get_item_schema + */ + public function test_get_item_schema() { + $request = new \WP_REST_Request( 'OPTIONS', '/' . ACTIVITYPUB_REST_NAMESPACE . '/actors/0/followers' ); + $response = rest_get_server()->dispatch( $request )->get_data(); + + $this->assertArrayHasKey( 'schema', $response ); + $schema = $response['schema']; + + // Test specific property types. + $this->assertContains( 'array', (array) $schema['properties']['@context']['type'] ); + $this->assertContains( 'object', (array) $schema['properties']['@context']['type'] ); + $this->assertEquals( 'string', $schema['properties']['id']['type'] ); + $this->assertEquals( 'uri', $schema['properties']['id']['format'] ); + $this->assertEquals( 'string', $schema['properties']['generator']['type'] ); + $this->assertEquals( 'uri', $schema['properties']['generator']['format'] ); + $this->assertEquals( 'string', $schema['properties']['actor']['type'] ); + $this->assertEquals( 'uri', $schema['properties']['actor']['format'] ); + $this->assertEquals( array( 'OrderedCollectionPage' ), $schema['properties']['type']['enum'] ); + $this->assertEquals( 'integer', $schema['properties']['totalItems']['type'] ); + $this->assertEquals( 'string', $schema['properties']['partOf']['type'] ); + $this->assertEquals( 'uri', $schema['properties']['partOf']['format'] ); + $this->assertEquals( 'array', $schema['properties']['orderedItems']['type'] ); + } + + /** + * Test get_items response. + * + * @covers ::get_items + */ + public function test_get_items() { + $request = new \WP_REST_Request( 'GET', '/' . ACTIVITYPUB_REST_NAMESPACE . '/actors/0/followers' ); + $request->set_param( 'context', 'simple' ); + $response = rest_get_server()->dispatch( $request ); + + $this->assertEquals( 200, $response->get_status() ); + $this->assertStringContainsString( 'application/activity+json', $response->get_headers()['Content-Type'] ); + + $data = $response->get_data(); + + // Test required properties. + $this->assertArrayHasKey( '@context', $data ); + $this->assertArrayHasKey( 'id', $data ); + $this->assertArrayHasKey( 'type', $data ); + $this->assertArrayHasKey( 'generator', $data ); + $this->assertArrayHasKey( 'actor', $data ); + $this->assertArrayHasKey( 'totalItems', $data ); + $this->assertArrayHasKey( 'partOf', $data ); + $this->assertArrayHasKey( 'orderedItems', $data ); + + // Test property values. + $this->assertEquals( 'OrderedCollectionPage', $data['type'] ); + $this->assertStringContainsString( 'wordpress.org', $data['generator'] ); + $this->assertNotEmpty( $data['orderedItems'] ); + } + + /** + * Test get_items response with full context. + * + * @covers ::get_items + */ + public function test_get_items_full_context() { + $request = new \WP_REST_Request( 'GET', '/' . ACTIVITYPUB_REST_NAMESPACE . '/actors/0/followers' ); + $request->set_param( 'context', 'full' ); + $response = rest_get_server()->dispatch( $request ); + + $data = $response->get_data(); + $this->assertIsArray( $data['orderedItems'] ); + + // In full context, orderedItems should contain full actor objects. + foreach ( $data['orderedItems'] as $item ) { + $this->assertIsArray( $item ); + } + } + + /** + * Test get_items with pagination. + * + * @covers ::get_items + */ + public function test_get_items_pagination() { + $request = new \WP_REST_Request( 'GET', '/' . ACTIVITYPUB_REST_NAMESPACE . '/actors/0/followers' ); + $request->set_param( 'page', 2 ); + $request->set_param( 'per_page', 10 ); + $response = rest_get_server()->dispatch( $request ); + + $data = $response->get_data(); + + // Test pagination properties. + $this->assertArrayHasKey( 'first', $data ); + $this->assertArrayHasKey( 'last', $data ); + $this->assertStringContainsString( 'page=1', $data['first'] ); + $this->assertIsString( $data['last'] ); + + $request = new \WP_REST_Request( 'GET', '/' . ACTIVITYPUB_REST_NAMESPACE . '/actors/0/followers' ); + $request->set_param( 'page', 100 ); + $response = rest_get_server()->dispatch( $request ); + + $this->assertErrorResponse( 'rest_post_invalid_page_number', $response, 400 ); + } + + /** + * Test get_items with invalid user. + * + * @covers ::get_items + */ + public function test_get_items_invalid_user() { + $request = new \WP_REST_Request( 'GET', '/' . ACTIVITYPUB_REST_NAMESPACE . '/actors/999999/followers' ); + $response = rest_get_server()->dispatch( $request ); + + $this->assertErrorResponse( 'activitypub_user_not_found', $response, 404 ); + } + + /** + * Test that the Followers response matches its schema. + * + * @covers ::get_items + * @covers ::get_item_schema + */ + public function test_response_matches_schema() { + $request = new \WP_REST_Request( 'GET', '/' . ACTIVITYPUB_REST_NAMESPACE . '/actors/0/followers' ); + $response = rest_get_server()->dispatch( $request ); + $data = $response->get_data(); + $schema = ( new \Activitypub\Rest\Followers_Controller() )->get_item_schema(); + + $valid = \rest_validate_value_from_schema( $data, $schema ); + $this->assertNotWPError( $valid, 'Response failed schema validation: ' . ( \is_wp_error( $valid ) ? $valid->get_error_message() : '' ) ); + } + + /** + * Test get_item method. + * + * @doesNotPerformAssertions + */ + public function test_get_item() { + // Controller does not implement get_item(). + } +} From d0ea2efa41223432c61a0476c5f08bbc9ceb2ba6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Menrath?= <99024746+Menrath@users.noreply.github.com> Date: Wed, 5 Feb 2025 14:49:06 +0100 Subject: [PATCH 05/18] Add: Show ActivityPub preview in row actions, when block editor enabled but is not used for post type. (#1273) * Fix outbox not using object types other than Base_Object * Show ActivityPub preview in row actions, when block editor is not used for post type. * Revert "Fix outbox not using object types other than Base_Object" This reverts commit bc5f5871897919211b87adda6fb762148cdd831f. * Improve changelog --- CHANGELOG.md | 3 ++- includes/class-admin.php | 4 ++-- readme.txt | 1 + 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fe21f4eda..7022aa4d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Cleanup of option values when the plugin is uninstalled. * Third-party plugins can filter settings tabs to add their own settings pages for ActivityPub. - +* Show ActivityPub preview in row actions when Block Editor is enabled but not used for the post type. +* ### Changed * Manually granting `activitypub` cap no longer requires the receiving user to have `publish_post`. diff --git a/includes/class-admin.php b/includes/class-admin.php index e9f9b9898..45152f5c2 100644 --- a/includes/class-admin.php +++ b/includes/class-admin.php @@ -879,8 +879,8 @@ public static function row_actions( $actions, $post ) { ! \post_type_supports( \get_post_type( $post ), 'activitypub' ) || ! in_array( $post->post_status, array( 'pending', 'draft', 'future', 'publish' ), true ) || ! \current_user_can( 'edit_post', $post->ID ) || - ACTIVITYPUB_CONTENT_VISIBILITY_LOCAL === get_content_visibility( $post ) || - site_supports_blocks() + ACTIVITYPUB_CONTENT_VISIBILITY_LOCAL === get_content_visibility( $post->ID ) || + ( site_supports_blocks() && \use_block_editor_for_post_type( $post->post_type ) ) ) { return $actions; } diff --git a/readme.txt b/readme.txt index afe00afdc..2c108c219 100644 --- a/readme.txt +++ b/readme.txt @@ -135,6 +135,7 @@ For reasons of data protection, it is not possible to see the followers of other * Added: Cleanup of option values when the plugin is uninstalled. * Added: Third-party plugins can filter settings tabs to add their own settings pages for ActivityPub. +* Added: Show ActivityPub preview in row actions when Block Editor is enabled but not used for the post type. * Changed: Manually granting `activitypub` cap no longer requires the receiving user to have `publish_post`. * Changed: Allow Base Transformer to handle WP_Term objects for transformation. * Changed: Allow omitting replies in ActivityPub representations instead of setting them as empty. From 7ee2180b64b07c466307146c3c31ee4659ee37fb Mon Sep 17 00:00:00 2001 From: Matthias Pfefferle Date: Wed, 5 Feb 2025 14:49:33 +0100 Subject: [PATCH 06/18] ActivityPub Query: Improve third party plugin support (#1272) * check `$activitypub_object` before returning it * make queried object filterable * add phpdoc * added changelog * Fix phpcs issues * allow access to `author` --------- Co-authored-by: Konstantin Obenland --- CHANGELOG.md | 1 + includes/class-activitypub.php | 1 + includes/class-query.php | 46 +++++++++++++++++++++------------- readme.txt | 1 + 4 files changed, 32 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7022aa4d8..c1cc6bdd0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Manually granting `activitypub` cap no longer requires the receiving user to have `publish_post`. * Allow omitting replies in ActivityPub representations instead of setting them as empty. * Allow Base Transformer to handle WP_Term objects for transformation. +* Improved Query extensibility for third party plugins. ### Fixed diff --git a/includes/class-activitypub.php b/includes/class-activitypub.php index 47be3d704..9a9184f47 100644 --- a/includes/class-activitypub.php +++ b/includes/class-activitypub.php @@ -281,6 +281,7 @@ public static function template_redirect() { public static function add_query_vars( $vars ) { $vars[] = 'activitypub'; $vars[] = 'preview'; + $vars[] = 'author'; $vars[] = 'c'; $vars[] = 'p'; diff --git a/includes/class-query.php b/includes/class-query.php index e1562e869..622a1eede 100644 --- a/includes/class-query.php +++ b/includes/class-query.php @@ -88,8 +88,13 @@ public function get_activitypub_object() { if ( ! $queried_object ) { // If the object is not a valid ActivityPub object, try to get a virtual object. - $this->activitypub_object = $this->maybe_get_virtual_object(); - return $this->activitypub_object; + $activitypub_object = $this->maybe_get_virtual_object(); + + if ( $activitypub_object ) { + $this->activitypub_object = $activitypub_object; + + return $this->activitypub_object; + } } $transformer = Factory::get_transformer( $queried_object ); @@ -144,30 +149,37 @@ public function get_activitypub_object_id() { public function get_queried_object() { $queried_object = \get_queried_object(); - if ( $queried_object ) { - return $queried_object; - } - // Check Comment by ID. - $comment_id = \get_query_var( 'c' ); - if ( $comment_id ) { - return \get_comment( $comment_id ); + if ( ! $queried_object ) { + $comment_id = \get_query_var( 'c' ); + if ( $comment_id ) { + $queried_object = \get_comment( $comment_id ); + } } // Check Post by ID (works for custom post types). - $post_id = \get_query_var( 'p' ); - if ( $post_id ) { - return \get_post( $post_id ); + if ( ! $queried_object ) { + $post_id = \get_query_var( 'p' ); + if ( $post_id ) { + $queried_object = \get_post( $post_id ); + } } // Try to get Author by ID. - $url = $this->get_request_url(); - $author_id = url_to_authorid( $url ); - if ( $author_id ) { - return \get_user_by( 'id', $author_id ); + if ( ! $queried_object ) { + $url = $this->get_request_url(); + $author_id = url_to_authorid( $url ); + if ( $author_id ) { + $queried_object = \get_user_by( 'id', $author_id ); + } } - return null; + /** + * Filters the queried object. + * + * @param \WP_Term|\WP_Post_Type|\WP_Post|\WP_User|\WP_Comment|null $queried_object The queried object. + */ + return apply_filters( 'activitypub_queried_object', $queried_object ); } /** diff --git a/readme.txt b/readme.txt index 2c108c219..24338ddc3 100644 --- a/readme.txt +++ b/readme.txt @@ -139,6 +139,7 @@ For reasons of data protection, it is not possible to see the followers of other * Changed: Manually granting `activitypub` cap no longer requires the receiving user to have `publish_post`. * Changed: Allow Base Transformer to handle WP_Term objects for transformation. * Changed: Allow omitting replies in ActivityPub representations instead of setting them as empty. +* Changed: Improved Query extensibility for third party plugins. * Fixed: Negotiation of ActivityPub requests for custom post types when queried by the ActivityPub ID. * Fixed: Avoid PHP warnings when using Debug mode and when the `actor` is not set. * Fixed: No longer creates Outbox items when importing content/users. From cda0a7f7d785b76be6bd3ea2c10ed3de75831218 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Menrath?= Date: Thu, 6 Feb 2025 07:30:44 +0100 Subject: [PATCH 07/18] Add assertions for php unit test of Oubox:add --- .../includes/collection/class-test-outbox.php | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/tests/includes/collection/class-test-outbox.php b/tests/includes/collection/class-test-outbox.php index 36fa1c537..8d37e19b4 100644 --- a/tests/includes/collection/class-test-outbox.php +++ b/tests/includes/collection/class-test-outbox.php @@ -7,6 +7,8 @@ namespace Activitypub\Tests\Collection; +use Activitypub\Activity\Extended_Object\Event; + /** * Test class for Outbox collection. * @@ -46,6 +48,13 @@ public function test_add( $data, $type, $user_id, $json ) { // Fall back to blog if user does not have the activitypub capability. $actor_type = \user_can( $user_id, 'activitypub' ) ? 'user' : 'blog'; $this->assertEquals( $actor_type, \get_post_meta( $id, '_activitypub_activity_actor', true ) ); + + if ( $data instanceof Event ) { + $this->assertEquals( Event::class, \get_post_meta( $id, '_activitypub_object_class', true ) ); + $this->assertEquals( $data->get_timezone(), $activity->timezone ); + $this->assertCount( count( $data->get_location() ), $activity->location ); + $this->assertIsArray( $data->get_location()[0]['address'] ); + } } /** @@ -77,6 +86,42 @@ public function activity_object_provider() { 2, '{"@context":["https:\/\/www.w3.org\/ns\/activitystreams",{"Hashtag":"as:Hashtag","sensitive":"as:sensitive"}],"id":"https:\/\/example.com\/2","type":"Note","content":"\u003Cp\u003EThis is another note\u003C\/p\u003E","contentMap":{"en":"\u003Cp\u003EThis is another note\u003C\/p\u003E"},"tag":[],"to":["https:\/\/www.w3.org\/ns\/activitystreams#Public"],"cc":[],"mediaType":"text\/html","sensitive":false}', ), + array( + Event::init_from_array( + array( + 'id' => 'https://example.com/3', + 'name' => 'WP Test Event', + 'type' => 'Event', + 'location' => array( + array( + 'id' => 'https://example.com/place/1', + 'type' => 'Place', + 'attributedTo' => 'https://wp-test.event-federation.eu/@test', + 'name' => 'Fediverse Place', + 'address' => array( + 'type' => 'PostalAddress', + 'addressCountry' => 'FediCountry', + 'addressLocality' => 'FediTown', + 'postalCode' => '1337', + 'streetAddress' => 'FediStreet', + ), + ), + array( + 'type' => 'VirtualLocation', + 'url' => 'https://example.com/VirtualMeetingRoom', + ), + ), + 'startTime' => '2030-02-29T16:00:00+01:00', + 'endTime' => '2030-02-29T17:00:00+01:00', + 'timezone' => 'Europe/Vienna', + 'joinMode' => 'external', + 'category' => 'MOVEMENTS_POLITICS', + ) + ), + 'Create', + 1, + '{"id":"https://example.com/3","name":"WP Test Event","type":"Event","location":[{"id":"https://example.com/place/1","type":"Place","attributedTo":"https://wp-test.event-federation.eu/@test","name":"Fediverse Place","address":{"type":"PostalAddress","addressCountry":"FediCountry","addressLocality":"FediTown","postalCode":"1337","streetAddress":"FediStreet"}},{"type":"VirtualLocation","url":"https://example.com/VirtualMeetingRoom"}],"startTime":"2030-02-29T16:00:00+01:00","endTime":"2030-02-29T17:00:00+01:00","timezone":"Europe/Vienna","joinMode":"external","category":"MOVEMENTS_POLITICS"}', + ), ); } From eecf9086098f0838f066dab83ef9f93ff454e2e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Menrath?= Date: Thu, 6 Feb 2025 07:43:20 +0100 Subject: [PATCH 08/18] Add context to test object --- tests/includes/collection/class-test-outbox.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/includes/collection/class-test-outbox.php b/tests/includes/collection/class-test-outbox.php index 8d37e19b4..52fba166c 100644 --- a/tests/includes/collection/class-test-outbox.php +++ b/tests/includes/collection/class-test-outbox.php @@ -120,7 +120,7 @@ public function activity_object_provider() { ), 'Create', 1, - '{"id":"https://example.com/3","name":"WP Test Event","type":"Event","location":[{"id":"https://example.com/place/1","type":"Place","attributedTo":"https://wp-test.event-federation.eu/@test","name":"Fediverse Place","address":{"type":"PostalAddress","addressCountry":"FediCountry","addressLocality":"FediTown","postalCode":"1337","streetAddress":"FediStreet"}},{"type":"VirtualLocation","url":"https://example.com/VirtualMeetingRoom"}],"startTime":"2030-02-29T16:00:00+01:00","endTime":"2030-02-29T17:00:00+01:00","timezone":"Europe/Vienna","joinMode":"external","category":"MOVEMENTS_POLITICS"}', + '{"@context":["https:\/\/schema.org\/","https:\/\/www.w3.org\/ns\/activitystreams",{"pt":"https:\/\/joinpeertube.org\/ns#","mz":"https:\/\/joinmobilizon.org\/ns#","status":"http:\/\/www.w3.org\/2002\/12\/cal\/ical#status","commentsEnabled":"pt:commentsEnabled","isOnline":"mz:isOnline","timezone":"mz:timezone","participantCount":"mz:participantCount","anonymousParticipationEnabled":"mz:anonymousParticipationEnabled","joinMode":{"@id":"mz:joinMode","@type":"mz:joinModeType"},"externalParticipationUrl":{"@id":"mz:externalParticipationUrl","@type":"schema:URL"},"repliesModerationOption":{"@id":"mz:repliesModerationOption","@type":"@vocab"},"contacts":{"@id":"mz:contacts","@type":"@id"}}],"id":"https://example.com/3","name":"WP Test Event","type":"Event","location":[{"id":"https://example.com/place/1","type":"Place","attributedTo":"https://wp-test.event-federation.eu/@test","name":"Fediverse Place","address":{"type":"PostalAddress","addressCountry":"FediCountry","addressLocality":"FediTown","postalCode":"1337","streetAddress":"FediStreet"}},{"type":"VirtualLocation","url":"https://example.com/VirtualMeetingRoom"}],"startTime":"2030-02-29T16:00:00+01:00","endTime":"2030-02-29T17:00:00+01:00","timezone":"Europe/Vienna","joinMode":"external","category":"MOVEMENTS_POLITICS"}', ), ); } From aac315cf41ca4feb494b6b6fd7cbf755097c374f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Menrath?= Date: Thu, 6 Feb 2025 07:48:28 +0100 Subject: [PATCH 09/18] Fix test data --- tests/includes/collection/class-test-outbox.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/includes/collection/class-test-outbox.php b/tests/includes/collection/class-test-outbox.php index 52fba166c..7f4497830 100644 --- a/tests/includes/collection/class-test-outbox.php +++ b/tests/includes/collection/class-test-outbox.php @@ -120,7 +120,7 @@ public function activity_object_provider() { ), 'Create', 1, - '{"@context":["https:\/\/schema.org\/","https:\/\/www.w3.org\/ns\/activitystreams",{"pt":"https:\/\/joinpeertube.org\/ns#","mz":"https:\/\/joinmobilizon.org\/ns#","status":"http:\/\/www.w3.org\/2002\/12\/cal\/ical#status","commentsEnabled":"pt:commentsEnabled","isOnline":"mz:isOnline","timezone":"mz:timezone","participantCount":"mz:participantCount","anonymousParticipationEnabled":"mz:anonymousParticipationEnabled","joinMode":{"@id":"mz:joinMode","@type":"mz:joinModeType"},"externalParticipationUrl":{"@id":"mz:externalParticipationUrl","@type":"schema:URL"},"repliesModerationOption":{"@id":"mz:repliesModerationOption","@type":"@vocab"},"contacts":{"@id":"mz:contacts","@type":"@id"}}],"id":"https://example.com/3","name":"WP Test Event","type":"Event","location":[{"id":"https://example.com/place/1","type":"Place","attributedTo":"https://wp-test.event-federation.eu/@test","name":"Fediverse Place","address":{"type":"PostalAddress","addressCountry":"FediCountry","addressLocality":"FediTown","postalCode":"1337","streetAddress":"FediStreet"}},{"type":"VirtualLocation","url":"https://example.com/VirtualMeetingRoom"}],"startTime":"2030-02-29T16:00:00+01:00","endTime":"2030-02-29T17:00:00+01:00","timezone":"Europe/Vienna","joinMode":"external","category":"MOVEMENTS_POLITICS"}', + '{"@context":["https:\/\/schema.org\/","https:\/\/www.w3.org\/ns\/activitystreams",{"pt":"https:\/\/joinpeertube.org\/ns#","mz":"https:\/\/joinmobilizon.org\/ns#","status":"http:\/\/www.w3.org\/2002\/12\/cal\/ical#status","commentsEnabled":"pt:commentsEnabled","isOnline":"mz:isOnline","timezone":"mz:timezone","participantCount":"mz:participantCount","anonymousParticipationEnabled":"mz:anonymousParticipationEnabled","joinMode":{"@id":"mz:joinMode","@type":"mz:joinModeType"},"externalParticipationUrl":{"@id":"mz:externalParticipationUrl","@type":"schema:URL"},"repliesModerationOption":{"@id":"mz:repliesModerationOption","@type":"@vocab"},"contacts":{"@id":"mz:contacts","@type":"@id"}}],"type":"Event","name":"WP Test Event","timezone":"Europe\/Vienna","category":"MOVEMENTS_POLITICS","joinMode":"external","id":"https:\/\/example.com\/3","nameMap":{"en":"WP Test Event"},"endTime":"2030-02-29T17:00:00+01:00","location":[{"id":"https:\/\/example.com\/place\/1","type":"Place","attributedTo":"https:\/\/wp-test.event-federation.eu\/@test","name":"Fediverse Place","address":{"type":"PostalAddress","addressCountry":"FediCountry","addressLocality":"FediTown","postalCode":"1337","streetAddress":"FediStreet"}},{"type":"VirtualLocation","url":"https:\/\/example.com\/VirtualMeetingRoom"}],"startTime":"2030-02-29T16:00:00+01:00","tag":[],"to":["https:\/\/www.w3.org\/ns\/activitystreams#Public"],"cc":[],"mediaType":"text\/html","sensitive":false}', ), ); } From 43a1d24284c25e7a7cff18bdd17257edb9f18c8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Menrath?= Date: Thu, 6 Feb 2025 13:47:53 +0100 Subject: [PATCH 10/18] Use assertJsonStringEqualsJsonString for comparing two JSON strings. --- .../includes/collection/class-test-outbox.php | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/tests/includes/collection/class-test-outbox.php b/tests/includes/collection/class-test-outbox.php index 7f4497830..7a13b72a7 100644 --- a/tests/includes/collection/class-test-outbox.php +++ b/tests/includes/collection/class-test-outbox.php @@ -7,6 +7,7 @@ namespace Activitypub\Tests\Collection; +use Activitypub\Activity\Base_Object; use Activitypub\Activity\Extended_Object\Event; /** @@ -38,22 +39,23 @@ public function test_add( $data, $type, $user_id, $json ) { $this->assertInstanceOf( 'WP_Post', $post ); $this->assertEquals( 'pending', $post->post_status ); - $this->assertEquals( $json, $post->post_content ); + $this->assertJsonStringEqualsJsonString( $json, $post->post_content ); $activity = json_decode( $post->post_content ); - $this->assertSame( $data['content'], $activity->content ); + if ( is_array( $data) ) { + $this->assertSame( $data['content'], $activity->content ); + } elseif ( $data instanceof Base_Object) { + $this->assertSame( $data->get_content(), $activity->content ); + } $this->assertEquals( $type, \get_post_meta( $id, '_activitypub_activity_type', true ) ); // Fall back to blog if user does not have the activitypub capability. $actor_type = \user_can( $user_id, 'activitypub' ) ? 'user' : 'blog'; $this->assertEquals( $actor_type, \get_post_meta( $id, '_activitypub_activity_actor', true ) ); - if ( $data instanceof Event ) { - $this->assertEquals( Event::class, \get_post_meta( $id, '_activitypub_object_class', true ) ); - $this->assertEquals( $data->get_timezone(), $activity->timezone ); - $this->assertCount( count( $data->get_location() ), $activity->location ); - $this->assertIsArray( $data->get_location()[0]['address'] ); + if ( $data instanceof Base_Object && get_class( $data ) !== Event::class ) { + $this->assertEquals( get_class( $data ), \get_post_meta( $id, '_activitypub_object_class', true ) ); } } @@ -116,11 +118,12 @@ public function activity_object_provider() { 'timezone' => 'Europe/Vienna', 'joinMode' => 'external', 'category' => 'MOVEMENTS_POLITICS', + 'content' => '

You should not miss this Event!

', ) ), 'Create', 1, - '{"@context":["https:\/\/schema.org\/","https:\/\/www.w3.org\/ns\/activitystreams",{"pt":"https:\/\/joinpeertube.org\/ns#","mz":"https:\/\/joinmobilizon.org\/ns#","status":"http:\/\/www.w3.org\/2002\/12\/cal\/ical#status","commentsEnabled":"pt:commentsEnabled","isOnline":"mz:isOnline","timezone":"mz:timezone","participantCount":"mz:participantCount","anonymousParticipationEnabled":"mz:anonymousParticipationEnabled","joinMode":{"@id":"mz:joinMode","@type":"mz:joinModeType"},"externalParticipationUrl":{"@id":"mz:externalParticipationUrl","@type":"schema:URL"},"repliesModerationOption":{"@id":"mz:repliesModerationOption","@type":"@vocab"},"contacts":{"@id":"mz:contacts","@type":"@id"}}],"type":"Event","name":"WP Test Event","timezone":"Europe\/Vienna","category":"MOVEMENTS_POLITICS","joinMode":"external","id":"https:\/\/example.com\/3","nameMap":{"en":"WP Test Event"},"endTime":"2030-02-29T17:00:00+01:00","location":[{"id":"https:\/\/example.com\/place\/1","type":"Place","attributedTo":"https:\/\/wp-test.event-federation.eu\/@test","name":"Fediverse Place","address":{"type":"PostalAddress","addressCountry":"FediCountry","addressLocality":"FediTown","postalCode":"1337","streetAddress":"FediStreet"}},{"type":"VirtualLocation","url":"https:\/\/example.com\/VirtualMeetingRoom"}],"startTime":"2030-02-29T16:00:00+01:00","tag":[],"to":["https:\/\/www.w3.org\/ns\/activitystreams#Public"],"cc":[],"mediaType":"text\/html","sensitive":false}', + '{"@context":["https:\/\/schema.org\/","https:\/\/www.w3.org\/ns\/activitystreams",{"pt":"https:\/\/joinpeertube.org\/ns#","mz":"https:\/\/joinmobilizon.org\/ns#","status":"http:\/\/www.w3.org\/2002\/12\/cal\/ical#status","commentsEnabled":"pt:commentsEnabled","isOnline":"mz:isOnline","timezone":"mz:timezone","participantCount":"mz:participantCount","anonymousParticipationEnabled":"mz:anonymousParticipationEnabled","joinMode":{"@id":"mz:joinMode","@type":"mz:joinModeType"},"externalParticipationUrl":{"@id":"mz:externalParticipationUrl","@type":"schema:URL"},"repliesModerationOption":{"@id":"mz:repliesModerationOption","@type":"@vocab"},"contacts":{"@id":"mz:contacts","@type":"@id"}}],"type":"Event","name":"WP Test Event","timezone":"Europe\/Vienna","category":"MOVEMENTS_POLITICS","joinMode":"external","id":"https:\/\/example.com\/3","nameMap":{"en":"WP Test Event"},"endTime":"2030-02-29T17:00:00+01:00","location":[{"id":"https:\/\/example.com\/place\/1","type":"Place","attributedTo":"https:\/\/wp-test.event-federation.eu\/@test","name":"Fediverse Place","address":{"type":"PostalAddress","addressCountry":"FediCountry","addressLocality":"FediTown","postalCode":"1337","streetAddress":"FediStreet"}},{"type":"VirtualLocation","url":"https:\/\/example.com\/VirtualMeetingRoom"}],"startTime":"2030-02-29T16:00:00+01:00","tag":[],"to":["https:\/\/www.w3.org\/ns\/activitystreams#Public"],"cc":[],"mediaType":"text\/html","sensitive":false,"content":"\u003Cp\u003EYou should not miss this Event!\u003C\/p\u003E","contentMap":{"en":"\u003Cp\u003EYou should not miss this Event!\u003C\/p\u003E"}}', ), ); } From b27d8c5355e06fc4e1c708e5680eec56a30768f0 Mon Sep 17 00:00:00 2001 From: Matthias Pfefferle Date: Thu, 6 Feb 2025 09:32:00 +0100 Subject: [PATCH 11/18] Fix NodeInfo rel (#1275) * Fix NodeInfo rel * fix tests --- tests/includes/collection/class-test-outbox.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/includes/collection/class-test-outbox.php b/tests/includes/collection/class-test-outbox.php index 7a13b72a7..fb66bf6ae 100644 --- a/tests/includes/collection/class-test-outbox.php +++ b/tests/includes/collection/class-test-outbox.php @@ -43,9 +43,9 @@ public function test_add( $data, $type, $user_id, $json ) { $activity = json_decode( $post->post_content ); - if ( is_array( $data) ) { + if ( is_array( $data ) ) { $this->assertSame( $data['content'], $activity->content ); - } elseif ( $data instanceof Base_Object) { + } elseif ( $data instanceof Base_Object ) { $this->assertSame( $data->get_content(), $activity->content ); } $this->assertEquals( $type, \get_post_meta( $id, '_activitypub_activity_type', true ) ); @@ -118,7 +118,7 @@ public function activity_object_provider() { 'timezone' => 'Europe/Vienna', 'joinMode' => 'external', 'category' => 'MOVEMENTS_POLITICS', - 'content' => '

You should not miss this Event!

', + 'content' => '

You should not miss this Event!

', ) ), 'Create', From 96671473729f99cf61714a296c9210e47d93af6a Mon Sep 17 00:00:00 2001 From: Matthias Pfefferle Date: Thu, 6 Feb 2025 09:39:42 +0100 Subject: [PATCH 12/18] Release 5.1.0 (#1276) --- CHANGELOG.md | 2 +- readme.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 675396ba6..0388e22f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [Unreleased] +## [5.1.0] - 2025-02-06 ### Fixed diff --git a/readme.txt b/readme.txt index cc7171bce..39335e5e8 100644 --- a/readme.txt +++ b/readme.txt @@ -129,7 +129,7 @@ For reasons of data protection, it is not possible to see the followers of other == Changelog == -= Unreleased = += 5.1.0 = * Fixed an issue where the outbox could not send object types other than `Base_Object` (introduced in 5.0.0). From 57f3d303c7fc2bec79852e760412ab9971a884b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Menrath?= Date: Thu, 6 Feb 2025 14:08:53 +0100 Subject: [PATCH 13/18] No need to set default object class in post meta. --- includes/class-activitypub.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/class-activitypub.php b/includes/class-activitypub.php index 9a9184f47..118ca10c0 100644 --- a/includes/class-activitypub.php +++ b/includes/class-activitypub.php @@ -612,7 +612,7 @@ private static function register_post_types() { return $value; } - return \Activitypub\Activity\Base_Object::class; + return ''; }, ) ); From 4ae24568bbad389c2320eb294c02721299ecf5e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Menrath?= Date: Thu, 6 Feb 2025 14:13:28 +0100 Subject: [PATCH 14/18] Fix Changelog. --- CHANGELOG.md | 2 +- readme.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0388e22f8..675396ba6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [5.1.0] - 2025-02-06 +## [Unreleased] ### Fixed diff --git a/readme.txt b/readme.txt index 39335e5e8..cc7171bce 100644 --- a/readme.txt +++ b/readme.txt @@ -129,7 +129,7 @@ For reasons of data protection, it is not possible to see the followers of other == Changelog == -= 5.1.0 = += Unreleased = * Fixed an issue where the outbox could not send object types other than `Base_Object` (introduced in 5.0.0). From 279f556bb6497509a00e89dda54cf7374bbd8608 Mon Sep 17 00:00:00 2001 From: Matthias Pfefferle Date: Thu, 13 Feb 2025 16:46:13 +0100 Subject: [PATCH 15/18] Use an Arbitrary_Object as default --- includes/activity/class-activity.php | 15 +- includes/activity/class-arbitrary-object.php | 321 ++++++++++++++++++ includes/activity/class-base-object.php | 280 +-------------- includes/collection/class-outbox.php | 6 - .../activity/class-test-arbitrary-object.php | 120 +++++++ .../activity/class-test-base-object.php | 41 +++ 6 files changed, 497 insertions(+), 286 deletions(-) create mode 100644 includes/activity/class-arbitrary-object.php create mode 100644 tests/includes/activity/class-test-arbitrary-object.php diff --git a/includes/activity/class-activity.php b/includes/activity/class-activity.php index a773de846..1fc01e246 100644 --- a/includes/activity/class-activity.php +++ b/includes/activity/class-activity.php @@ -159,21 +159,12 @@ class Activity extends Base_Object { * * @see https://www.w3.org/TR/activitypub/#object-without-create * - * @param array|string|Base_Object|Link|null $data Activity object. - * @param string|null $object_class The full class path to a child of Base_Object. + * @param array|string|Base_Object|Link|null $data Activity object. */ - public function set_object( $data, $object_class = null ) { + public function set_object( $data ) { // Convert array to object. if ( is_array( $data ) ) { - if ( $object_class && class_exists( $object_class ) ) { - $data = $object_class::init_from_array( $data ); - } elseif ( is_activity( $data ) ) { // Check if the item is an Activity or an Object. - $data = self::init_from_array( $data ); - } elseif ( is_actor( $data ) ) { - $data = Actor::init_from_array( $data ); - } else { - $data = Base_Object::init_from_array( $data ); - } + $data = Arbitrary_Object::init_from_array( $data ); } // Set object. diff --git a/includes/activity/class-arbitrary-object.php b/includes/activity/class-arbitrary-object.php new file mode 100644 index 000000000..792eaf399 --- /dev/null +++ b/includes/activity/class-arbitrary-object.php @@ -0,0 +1,321 @@ +to_string(); + } + + /** + * Function to transform the object to string. + * + * @return string The object id. + */ + public function to_string() { + return $this->get_id(); + } + + /** + * Magic function to implement getter and setter. + * + * @param string $method The method name. + * @param string $params The method params. + */ + public function __call( $method, $params ) { + $var = \strtolower( \substr( $method, 4 ) ); + + if ( \strncasecmp( $method, 'get', 3 ) === 0 ) { + if ( ! $this->has( $var ) ) { + return null; + } + + return $this->$var; + } + + if ( \strncasecmp( $method, 'set', 3 ) === 0 ) { + return $this->set( $var, $params[0] ); + } + + if ( \strncasecmp( $method, 'add', 3 ) === 0 ) { + return $this->add( $var, $params[0] ); + } + } + + /** + * Generic getter. + * + * @param string $key The key to get. + * + * @return mixed The value. + */ + public function get( $key ) { + return call_user_func( array( $this, 'get_' . $key ) ); + } + + /** + * Generic setter. + * + * @param string $key The key to set. + * @param string $value The value to set. + * + * @return mixed The value. + */ + public function set( $key, $value ) { + $this->$key = $value; + + return $this; + } + + /** + * Generic adder. + * + * @param string $key The key to set. + * @param mixed $value The value to add. + * + * @return mixed The value. + */ + public function add( $key, $value ) { + if ( ! isset( $this->$key ) ) { + $this->$key = array(); + } + + if ( is_string( $this->$key ) ) { + $this->$key = array( $this->$key ); + } + + $attributes = $this->$key; + + if ( is_array( $value ) ) { + $attributes = array_merge( $attributes, $value ); + } else { + $attributes[] = $value; + } + + $this->$key = array_unique( $attributes ); + + return $this->$key; + } + + /** + * Check if the object has a key + * + * @param string $key The key to check. + * + * @return boolean True if the object has the key. + */ + public function has( $key ) { + return property_exists( $this, $key ); + } + + /** + * Convert JSON input to an array. + * + * @param string $json The JSON string. + * + * @return Base_Object|\WP_Error An Object built from the JSON string or WP_Error when it's not a JSON string. + */ + public static function init_from_json( $json ) { + $array = \json_decode( $json, true ); + + if ( ! is_array( $array ) ) { + return new \WP_Error( 'invalid_json', __( 'Invalid JSON', 'activitypub' ), array( 'status' => 400 ) ); + } + + return self::init_from_array( $array ); + } + + /** + * Convert input array to a Base_Object. + * + * @param array $data The object array. + * + * @return Base_Object|\WP_Error An Object built from the input array or WP_Error when it's not an array. + */ + public static function init_from_array( $data ) { + if ( ! is_array( $data ) ) { + return new \WP_Error( 'invalid_array', __( 'Invalid array', 'activitypub' ), array( 'status' => 400 ) ); + } + + $object = new static(); + $object->from_array( $data ); + + return $object; + } + + /** + * Convert JSON input to an array and pre-fill the object. + * + * @param array $data The array. + */ + public function from_array( $data ) { + foreach ( $data as $key => $value ) { + if ( $value ) { + $key = camel_to_snake_case( $key ); + call_user_func( array( $this, 'set_' . $key ), $value ); + } + } + } + + /** + * Convert JSON input to an array and pre-fill the object. + * + * @param string $json The JSON string. + */ + public function from_json( $json ) { + $array = \json_decode( $json, true ); + + $this->from_array( $array ); + } + + /** + * Convert Object to an array. + * + * It tries to get the object attributes if they exist + * and falls back to the getters. Empty values are ignored. + * + * @param bool $include_json_ld_context Whether to include the JSON-LD context. Default true. + * + * @return array An array built from the Object. + */ + public function to_array( $include_json_ld_context = true ) { + $array = array(); + $vars = get_object_vars( $this ); + + foreach ( $vars as $key => $value ) { + if ( \is_wp_error( $value ) ) { + continue; + } + + // Ignore all _prefixed keys. + if ( '_' === substr( $key, 0, 1 ) ) { + continue; + } + + // If value is empty, try to get it from a getter. + if ( ! $value ) { + $value = call_user_func( array( $this, 'get_' . $key ) ); + } + + if ( is_object( $value ) ) { + $value = $value->to_array( false ); + } + + // If value is still empty, ignore it for the array and continue. + if ( isset( $value ) ) { + $array[ snake_to_camel_case( $key ) ] = $value; + } + } + + if ( $include_json_ld_context ) { + // Get JsonLD context and move it to '@context' at the top. + $array = array_merge( array( '@context' => $this->get_json_ld_context() ), $array ); + } + + $class = new \ReflectionClass( $this ); + $class = strtolower( $class->getShortName() ); + + /** + * Filter the array of the ActivityPub object. + * + * @param array $array The array of the ActivityPub object. + * @param string $class The class of the ActivityPub object. + * @param int $id The ID of the ActivityPub object. + * @param Base_Object $object The ActivityPub object. + * + * @return array The filtered array of the ActivityPub object. + */ + $array = \apply_filters( 'activitypub_activity_object_array', $array, $class, $this->id, $this ); + + /** + * Filter the array of the ActivityPub object by class. + * + * @param array $array The array of the ActivityPub object. + * @param int $id The ID of the ActivityPub object. + * @param Base_Object $object The ActivityPub object. + * + * @return array The filtered array of the ActivityPub object. + */ + return \apply_filters( "activitypub_activity_{$class}_object_array", $array, $this->id, $this ); + } + + /** + * Convert Object to JSON. + * + * @param bool $include_json_ld_context Whether to include the JSON-LD context. Default true. + * + * @return string The JSON string. + */ + public function to_json( $include_json_ld_context = true ) { + $array = $this->to_array( $include_json_ld_context ); + $options = \JSON_HEX_TAG | \JSON_HEX_AMP | \JSON_HEX_QUOT; + + /** + * Options to be passed to json_encode() + * + * @param int $options The current options flags. + */ + $options = \apply_filters( 'activitypub_json_encode_options', $options ); + + return \wp_json_encode( $array, $options ); + } + + /** + * Returns the keys of the object vars. + * + * @return array The keys of the object vars. + */ + public function get_object_var_keys() { + return \array_keys( \get_object_vars( $this ) ); + } + + /** + * Returns the JSON-LD context of this object. + * + * @return array $context A compacted JSON-LD context for the ActivityPub object. + */ + public function get_json_ld_context() { + return static::JSON_LD_CONTEXT; + } +} diff --git a/includes/activity/class-base-object.php b/includes/activity/class-base-object.php index 4e6f12fb6..b5e130f70 100644 --- a/includes/activity/class-base-object.php +++ b/includes/activity/class-base-object.php @@ -9,13 +9,6 @@ namespace Activitypub\Activity; -use WP_Error; -use ReflectionClass; -use DateTime; - -use function Activitypub\camel_to_snake_case; -use function Activitypub\snake_to_camel_case; - /** * Base_Object is an implementation of one of the * Activity Streams Core Types. @@ -28,7 +21,12 @@ * * @see https://www.w3.org/TR/activitystreams-core/#object */ -class Base_Object { +class Base_Object extends Arbitrary_Object { + /** + * The JSON-LD context for the object. + * + * @var array + */ const JSON_LD_CONTEXT = array( 'https://www.w3.org/ns/activitystreams', array( @@ -37,15 +35,6 @@ class Base_Object { ), ); - /** - * The object's unique global identifier - * - * @see https://www.w3.org/TR/activitypub/#obj-id - * - * @var string - */ - protected $id; - /** * The type of the object. * @@ -405,50 +394,6 @@ class Base_Object { */ protected $sensitive = false; - /** - * Magic function to implement getter and setter. - * - * @param string $method The method name. - * @param string $params The method params. - */ - public function __call( $method, $params ) { - $var = \strtolower( \substr( $method, 4 ) ); - - if ( \strncasecmp( $method, 'get', 3 ) === 0 ) { - if ( ! $this->has( $var ) ) { - return new WP_Error( 'invalid_key', __( 'Invalid key', 'activitypub' ), array( 'status' => 404 ) ); - } - - return $this->$var; - } - - if ( \strncasecmp( $method, 'set', 3 ) === 0 ) { - return $this->set( $var, $params[0] ); - } - - if ( \strncasecmp( $method, 'add', 3 ) === 0 ) { - return $this->add( $var, $params[0] ); - } - } - - /** - * Magic function, to transform the object to string. - * - * @return string The object id. - */ - public function __toString() { - return $this->to_string(); - } - - /** - * Function to transform the object to string. - * - * @return string The object id. - */ - public function to_string() { - return $this->get_id(); - } - /** * Generic getter. * @@ -458,21 +403,10 @@ public function to_string() { */ public function get( $key ) { if ( ! $this->has( $key ) ) { - return new WP_Error( 'invalid_key', __( 'Invalid key', 'activitypub' ), array( 'status' => 404 ) ); + return new \WP_Error( 'invalid_key', __( 'Invalid key', 'activitypub' ), array( 'status' => 404 ) ); } - return call_user_func( array( $this, 'get_' . $key ) ); - } - - /** - * Check if the object has a key - * - * @param string $key The key to check. - * - * @return boolean True if the object has the key. - */ - public function has( $key ) { - return property_exists( $this, $key ); + return parent::get( $key ); } /** @@ -485,12 +419,10 @@ public function has( $key ) { */ public function set( $key, $value ) { if ( ! $this->has( $key ) ) { - return new WP_Error( 'invalid_key', __( 'Invalid key', 'activitypub' ), array( 'status' => 404 ) ); + return new \WP_Error( 'invalid_key', __( 'Invalid key', 'activitypub' ), array( 'status' => 404 ) ); } - $this->$key = $value; - - return $this; + return parent::set( $key, $value ); } /** @@ -503,197 +435,9 @@ public function set( $key, $value ) { */ public function add( $key, $value ) { if ( ! $this->has( $key ) ) { - return new WP_Error( 'invalid_key', __( 'Invalid key', 'activitypub' ), array( 'status' => 404 ) ); - } - - if ( ! isset( $this->$key ) ) { - $this->$key = array(); + return new \WP_Error( 'invalid_key', __( 'Invalid key', 'activitypub' ), array( 'status' => 404 ) ); } - if ( is_string( $this->$key ) ) { - $this->$key = array( $this->$key ); - } - - $attributes = $this->$key; - - if ( is_array( $value ) ) { - $attributes = array_merge( $attributes, $value ); - } else { - $attributes[] = $value; - } - - $this->$key = array_unique( $attributes ); - - return $this->$key; - } - - /** - * Convert JSON input to an array. - * - * @param string $json The JSON string. - * - * @return Base_Object|WP_Error An Object built from the JSON string or WP_Error when it's not a JSON string. - */ - public static function init_from_json( $json ) { - $array = \json_decode( $json, true ); - - if ( ! is_array( $array ) ) { - return new WP_Error( 'invalid_json', __( 'Invalid JSON', 'activitypub' ), array( 'status' => 400 ) ); - } - - return self::init_from_array( $array ); - } - - /** - * Convert input array to a Base_Object. - * - * @param array $data The object array. - * - * @return Base_Object|WP_Error An Object built from the input array or WP_Error when it's not an array. - */ - public static function init_from_array( $data ) { - if ( ! is_array( $data ) ) { - return new WP_Error( 'invalid_array', __( 'Invalid array', 'activitypub' ), array( 'status' => 400 ) ); - } - - $object = new static(); - $object->from_array( $data ); - - return $object; - } - - /** - * Convert JSON input to an array and pre-fill the object. - * - * @param string $json The JSON string. - */ - public function from_json( $json ) { - $array = \json_decode( $json, true ); - - $this->from_array( $array ); - } - - /** - * Convert JSON input to an array and pre-fill the object. - * - * @param array $data The array. - */ - public function from_array( $data ) { - foreach ( $data as $key => $value ) { - if ( $value ) { - $key = camel_to_snake_case( $key ); - call_user_func( array( $this, 'set_' . $key ), $value ); - } - } - } - - /** - * Convert Object to an array. - * - * It tries to get the object attributes if they exist - * and falls back to the getters. Empty values are ignored. - * - * @param bool $include_json_ld_context Whether to include the JSON-LD context. Default true. - * - * @return array An array built from the Object. - */ - public function to_array( $include_json_ld_context = true ) { - $array = array(); - $vars = get_object_vars( $this ); - - foreach ( $vars as $key => $value ) { - if ( \is_wp_error( $value ) ) { - continue; - } - - // Ignore all _prefixed keys. - if ( '_' === substr( $key, 0, 1 ) ) { - continue; - } - - // If value is empty, try to get it from a getter. - if ( ! $value ) { - $value = call_user_func( array( $this, 'get_' . $key ) ); - } - - if ( is_object( $value ) ) { - $value = $value->to_array( false ); - } - - // If value is still empty, ignore it for the array and continue. - if ( isset( $value ) ) { - $array[ snake_to_camel_case( $key ) ] = $value; - } - } - - if ( $include_json_ld_context ) { - // Get JsonLD context and move it to '@context' at the top. - $array = array_merge( array( '@context' => $this->get_json_ld_context() ), $array ); - } - - $class = new ReflectionClass( $this ); - $class = strtolower( $class->getShortName() ); - - /** - * Filter the array of the ActivityPub object. - * - * @param array $array The array of the ActivityPub object. - * @param string $class The class of the ActivityPub object. - * @param int $id The ID of the ActivityPub object. - * @param Base_Object $object The ActivityPub object. - * - * @return array The filtered array of the ActivityPub object. - */ - $array = \apply_filters( 'activitypub_activity_object_array', $array, $class, $this->id, $this ); - - /** - * Filter the array of the ActivityPub object by class. - * - * @param array $array The array of the ActivityPub object. - * @param int $id The ID of the ActivityPub object. - * @param Base_Object $object The ActivityPub object. - * - * @return array The filtered array of the ActivityPub object. - */ - return \apply_filters( "activitypub_activity_{$class}_object_array", $array, $this->id, $this ); - } - - /** - * Convert Object to JSON. - * - * @param bool $include_json_ld_context Whether to include the JSON-LD context. Default true. - * - * @return string The JSON string. - */ - public function to_json( $include_json_ld_context = true ) { - $array = $this->to_array( $include_json_ld_context ); - $options = \JSON_HEX_TAG | \JSON_HEX_AMP | \JSON_HEX_QUOT; - - /** - * Options to be passed to json_encode() - * - * @param int $options The current options flags. - */ - $options = \apply_filters( 'activitypub_json_encode_options', $options ); - - return \wp_json_encode( $array, $options ); - } - - /** - * Returns the keys of the object vars. - * - * @return array The keys of the object vars. - */ - public function get_object_var_keys() { - return \array_keys( \get_object_vars( $this ) ); - } - - /** - * Returns the JSON-LD context of this object. - * - * @return array $context A compacted JSON-LD context for the ActivityPub object. - */ - public function get_json_ld_context() { - return static::JSON_LD_CONTEXT; + return parent::add( $key, $value ); } } diff --git a/includes/collection/class-outbox.php b/includes/collection/class-outbox.php index 1ac0b0987..dc18ba73c 100644 --- a/includes/collection/class-outbox.php +++ b/includes/collection/class-outbox.php @@ -73,12 +73,6 @@ public static function add( $activity_object, $activity_type, $user_id, $content ), ); - $object_class = get_class( $activity_object ); - - if ( Base_Object::class !== $object_class ) { - $outbox_item['meta_input']['_activitypub_object_class'] = str_replace( '\\', '\\\\', $object_class ); - } - $has_kses = false !== \has_filter( 'content_save_pre', 'wp_filter_post_kses' ); if ( $has_kses ) { // Prevent KSES from corrupting JSON in post_content. diff --git a/tests/includes/activity/class-test-arbitrary-object.php b/tests/includes/activity/class-test-arbitrary-object.php new file mode 100644 index 000000000..3ce6637b9 --- /dev/null +++ b/tests/includes/activity/class-test-arbitrary-object.php @@ -0,0 +1,120 @@ + 'https://example.com/test', + 'type' => 'Test', + 'name' => 'Test Name', + 'summary' => 'Test Summary', + 'content' => 'Test Content', + 'published' => '2024-03-20T12:00:00Z', + 'to' => array( 'https://example.com/user1' ), + 'cc' => array( 'https://example.com/user2' ), + 'attachment' => array( + array( + 'type' => 'Image', + 'url' => 'https://example.com/image.jpg', + ), + ), + 'attributedTo' => 'https://example.com/author', + 'unsupported' => 'unsupported', + ); + + $object = Arbitrary_Object::init_from_array( $test_data ); + + // Test if all attributes are set correctly + $this->assertEquals( $test_data['id'], $object->get_id() ); + $this->assertEquals( $test_data['type'], $object->get_type() ); + $this->assertEquals( $test_data['name'], $object->get_name() ); + $this->assertEquals( $test_data['summary'], $object->get_summary() ); + $this->assertEquals( $test_data['content'], $object->get_content() ); + $this->assertEquals( $test_data['published'], $object->get_published() ); + $this->assertEquals( $test_data['to'], $object->get_to() ); + $this->assertEquals( $test_data['cc'], $object->get_cc() ); + $this->assertEquals( $test_data['attachment'], $object->get_attachment() ); + $this->assertEquals( $test_data['attributedTo'], $object->get_attributed_to() ); + $this->assertEquals( $test_data['unsupported'], $object->get_unsupported() ); + } + + /** + * Test if init_from_array handles invalid input correctly. + */ + public function test_init_from_array_invalid_input() { + $result = Arbitrary_Object::init_from_array( 'not an array' ); + $this->assertWPError( $result ); + $this->assertEquals( 'invalid_array', $result->get_error_code() ); + } + + /** + * Test if init_from_array handles empty values correctly. + */ + public function test_init_from_array_empty_values() { + $test_data = array( + 'id' => 'https://example.com/test', + 'type' => 'Test', + 'name' => '', + 'summary' => null, + 'content' => false, + ); + + $object = Arbitrary_Object::init_from_array( $test_data ); + + $this->assertEquals( $test_data['id'], $object->get_id() ); + $this->assertEquals( $test_data['type'], $object->get_type() ); + $this->assertNull( $object->get_name() ); + $this->assertNull( $object->get_summary() ); + $this->assertNull( $object->get_content() ); + } + + /** + * Test if init_from_array correctly handles camelCase to snake_case conversion. + */ + public function test_init_from_array_case_conversion() { + $test_data = array( + 'attributedTo' => 'https://example.com/author', + 'inReplyTo' => 'https://example.com/post/1', + 'mediaType' => 'text/html', + ); + + $object = Arbitrary_Object::init_from_array( $test_data ); + + $this->assertEquals( $test_data['attributedTo'], $object->get_attributed_to() ); + $this->assertEquals( $test_data['inReplyTo'], $object->get_in_reply_to() ); + $this->assertEquals( $test_data['mediaType'], $object->get_media_type() ); + } + + /** + * Test if init_from_array correctly handles camelCase to snake_case conversion. + */ + public function test_to_array() { + $test_data = array( + 'attributedTo' => 'https://example.com/author', + 'inReplyTo' => 'https://example.com/post/1', + 'mediaType' => 'text/html', + ); + + $object = Arbitrary_Object::init_from_array( $test_data ); + + $array = $object->to_array(); + + $this->assertEquals( $test_data['attributedTo'], $array['attributedTo'] ); + $this->assertEquals( $test_data['inReplyTo'], $array['inReplyTo'] ); + $this->assertEquals( $test_data['mediaType'], $array['mediaType'] ); + } +} diff --git a/tests/includes/activity/class-test-base-object.php b/tests/includes/activity/class-test-base-object.php index f8da047bc..476cc1c1b 100644 --- a/tests/includes/activity/class-test-base-object.php +++ b/tests/includes/activity/class-test-base-object.php @@ -70,4 +70,45 @@ public function test_init_from_json() { $this->assertInstanceOf( 'WP_Error', $base_object ); } + + /** + * Test init_from_array method. + * + * @covers ::init_from_array + */ + public function test_init_from_array() { + $test_data = array( + 'id' => 'https://example.com/test', + 'type' => 'Test', + 'name' => 'Test Name', + 'summary' => 'Test Summary', + 'content' => 'Test Content', + 'published' => '2024-03-20T12:00:00Z', + 'to' => array( 'https://example.com/user1' ), + 'cc' => array( 'https://example.com/user2' ), + 'attachment' => array( + array( + 'type' => 'Image', + 'url' => 'https://example.com/image.jpg', + ), + ), + 'attributedTo' => 'https://example.com/author', + 'unsupported' => 'unsupported', + ); + + $object = Base_Object::init_from_array( $test_data ); + + // Test if all attributes are set correctly + $this->assertEquals( $test_data['id'], $object->get_id() ); + $this->assertEquals( $test_data['type'], $object->get_type() ); + $this->assertEquals( $test_data['name'], $object->get_name() ); + $this->assertEquals( $test_data['summary'], $object->get_summary() ); + $this->assertEquals( $test_data['content'], $object->get_content() ); + $this->assertEquals( $test_data['published'], $object->get_published() ); + $this->assertEquals( $test_data['to'], $object->get_to() ); + $this->assertEquals( $test_data['cc'], $object->get_cc() ); + $this->assertEquals( $test_data['attachment'], $object->get_attachment() ); + $this->assertEquals( $test_data['attributedTo'], $object->get_attributed_to() ); + $this->assertNull( $object->get_unsupported() ); + } } From efaaac7878fe73b38abacf0b9a10e6a8b4cdb314 Mon Sep 17 00:00:00 2001 From: Matthias Pfefferle Date: Thu, 13 Feb 2025 16:48:36 +0100 Subject: [PATCH 16/18] remove post-meta --- includes/class-activitypub.php | 22 ------------------- includes/collection/class-outbox.php | 1 - .../includes/collection/class-test-outbox.php | 4 ---- 3 files changed, 27 deletions(-) diff --git a/includes/class-activitypub.php b/includes/class-activitypub.php index 11bcf73e9..52f00f551 100644 --- a/includes/class-activitypub.php +++ b/includes/class-activitypub.php @@ -607,28 +607,6 @@ private static function register_post_types() { ) ); - /** - * Register ActivityPub object class for Outbox items. - * - * @see https://www.w3.org/TR/activitystreams-vocabulary/#object-types - */ - \register_post_meta( - Outbox::POST_TYPE, - '_activitypub_object_class', - array( - 'type' => 'string', - 'description' => 'The full class name of the object class', - 'single' => true, - 'sanitize_callback' => function ( $value ) { - if ( class_exists( $value ) ) { - return $value; - } - - return ''; - }, - ) - ); - \register_post_meta( Outbox::POST_TYPE, '_activitypub_activity_actor', diff --git a/includes/collection/class-outbox.php b/includes/collection/class-outbox.php index dc18ba73c..81e438366 100644 --- a/includes/collection/class-outbox.php +++ b/includes/collection/class-outbox.php @@ -7,7 +7,6 @@ namespace Activitypub\Collection; -use Activitypub\Activity\Base_Object; use Activitypub\Dispatcher; use function Activitypub\is_activity; diff --git a/tests/includes/collection/class-test-outbox.php b/tests/includes/collection/class-test-outbox.php index 596dd2794..87f0c2fd6 100644 --- a/tests/includes/collection/class-test-outbox.php +++ b/tests/includes/collection/class-test-outbox.php @@ -53,10 +53,6 @@ public function test_add( $data, $type, $user_id, $json ) { // Fall back to blog if user does not have the activitypub capability. $actor_type = \user_can( $user_id, 'activitypub' ) ? 'user' : 'blog'; $this->assertEquals( $actor_type, \get_post_meta( $id, '_activitypub_activity_actor', true ) ); - - if ( $data instanceof Base_Object && get_class( $data ) !== Event::class ) { - $this->assertEquals( get_class( $data ), \get_post_meta( $id, '_activitypub_object_class', true ) ); - } } /** From ef2e515c368a5a9d8ed4c99db968e6f6909aacdb Mon Sep 17 00:00:00 2001 From: Matthias Pfefferle Date: Thu, 13 Feb 2025 16:49:04 +0100 Subject: [PATCH 17/18] remove whitespace --- includes/collection/class-outbox.php | 1 - 1 file changed, 1 deletion(-) diff --git a/includes/collection/class-outbox.php b/includes/collection/class-outbox.php index 81e438366..9a91587cb 100644 --- a/includes/collection/class-outbox.php +++ b/includes/collection/class-outbox.php @@ -11,7 +11,6 @@ use function Activitypub\is_activity; - /** * ActivityPub Outbox Collection * From e4a0a9fce11b0496c9434fd0f1935c8e85699e41 Mon Sep 17 00:00:00 2001 From: Matthias Pfefferle Date: Thu, 13 Feb 2025 16:51:13 +0100 Subject: [PATCH 18/18] Fix PHPCS --- includes/activity/class-arbitrary-object.php | 2 +- .../activity/class-test-arbitrary-object.php | 20 +++++++++---------- .../activity/class-test-base-object.php | 20 +++++++++---------- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/includes/activity/class-arbitrary-object.php b/includes/activity/class-arbitrary-object.php index 792eaf399..23cf14b28 100644 --- a/includes/activity/class-arbitrary-object.php +++ b/includes/activity/class-arbitrary-object.php @@ -27,7 +27,7 @@ class Arbitrary_Object { * @var array */ const JSON_LD_CONTEXT = array( - 'https://www.w3.org/ns/activitystreams' + 'https://www.w3.org/ns/activitystreams', ); /** diff --git a/tests/includes/activity/class-test-arbitrary-object.php b/tests/includes/activity/class-test-arbitrary-object.php index 3ce6637b9..4247e14ed 100644 --- a/tests/includes/activity/class-test-arbitrary-object.php +++ b/tests/includes/activity/class-test-arbitrary-object.php @@ -18,15 +18,15 @@ class Test_Arbitrary_Object extends WP_UnitTestCase { */ public function test_init_from_array() { $test_data = array( - 'id' => 'https://example.com/test', - 'type' => 'Test', - 'name' => 'Test Name', - 'summary' => 'Test Summary', - 'content' => 'Test Content', - 'published' => '2024-03-20T12:00:00Z', - 'to' => array( 'https://example.com/user1' ), - 'cc' => array( 'https://example.com/user2' ), - 'attachment' => array( + 'id' => 'https://example.com/test', + 'type' => 'Test', + 'name' => 'Test Name', + 'summary' => 'Test Summary', + 'content' => 'Test Content', + 'published' => '2024-03-20T12:00:00Z', + 'to' => array( 'https://example.com/user1' ), + 'cc' => array( 'https://example.com/user2' ), + 'attachment' => array( array( 'type' => 'Image', 'url' => 'https://example.com/image.jpg', @@ -38,7 +38,7 @@ public function test_init_from_array() { $object = Arbitrary_Object::init_from_array( $test_data ); - // Test if all attributes are set correctly + // Test if all attributes are set correctly. $this->assertEquals( $test_data['id'], $object->get_id() ); $this->assertEquals( $test_data['type'], $object->get_type() ); $this->assertEquals( $test_data['name'], $object->get_name() ); diff --git a/tests/includes/activity/class-test-base-object.php b/tests/includes/activity/class-test-base-object.php index 476cc1c1b..5af6d1004 100644 --- a/tests/includes/activity/class-test-base-object.php +++ b/tests/includes/activity/class-test-base-object.php @@ -78,15 +78,15 @@ public function test_init_from_json() { */ public function test_init_from_array() { $test_data = array( - 'id' => 'https://example.com/test', - 'type' => 'Test', - 'name' => 'Test Name', - 'summary' => 'Test Summary', - 'content' => 'Test Content', - 'published' => '2024-03-20T12:00:00Z', - 'to' => array( 'https://example.com/user1' ), - 'cc' => array( 'https://example.com/user2' ), - 'attachment' => array( + 'id' => 'https://example.com/test', + 'type' => 'Test', + 'name' => 'Test Name', + 'summary' => 'Test Summary', + 'content' => 'Test Content', + 'published' => '2024-03-20T12:00:00Z', + 'to' => array( 'https://example.com/user1' ), + 'cc' => array( 'https://example.com/user2' ), + 'attachment' => array( array( 'type' => 'Image', 'url' => 'https://example.com/image.jpg', @@ -98,7 +98,7 @@ public function test_init_from_array() { $object = Base_Object::init_from_array( $test_data ); - // Test if all attributes are set correctly + // Test if all attributes are set correctly. $this->assertEquals( $test_data['id'], $object->get_id() ); $this->assertEquals( $test_data['type'], $object->get_type() ); $this->assertEquals( $test_data['name'], $object->get_name() );