diff --git a/.github/changelog/3168-from-description b/.github/changelog/3168-from-description new file mode 100644 index 0000000000..5976605a48 --- /dev/null +++ b/.github/changelog/3168-from-description @@ -0,0 +1,4 @@ +Significance: patch +Type: added + +Add support for importing Starter Packs in both the Pixelfed and Mastodon formats. diff --git a/includes/functions-activity.php b/includes/functions-activity.php index fbb2ceaab6..68f453c349 100644 --- a/includes/functions-activity.php +++ b/includes/functions-activity.php @@ -212,8 +212,20 @@ function object_to_uri( $data ) { $data = $data['href']; break; + case 'FeaturedItem': // See https://github.com/mastodon/featured_collections/pull/1. + $data = object_to_uri( $data['featuredObject'] ?? null ); + break; + default: - $data = $data['id']; + if ( isset( $data['id'] ) ) { + $data = $data['id']; + } elseif ( isset( $data['url'] ) ) { + $data = object_to_uri( $data['url'] ); + } elseif ( isset( $data['href'] ) ) { + $data = $data['href']; + } else { + $data = null; + } break; } diff --git a/includes/wp-admin/import/class-starter-kit.php b/includes/wp-admin/import/class-starter-kit.php index b965cbb68f..792925e807 100644 --- a/includes/wp-admin/import/class-starter-kit.php +++ b/includes/wp-admin/import/class-starter-kit.php @@ -378,12 +378,16 @@ private static function render_starter_kit_info() { echo '

' . \esc_html( $name ) . '

'; - if ( ! empty( self::$starter_kit['image']['url'] ) ) { - \printf( - '%s', - \esc_url( self::$starter_kit['image']['url'] ), - \esc_attr( self::$starter_kit['image']['summary'] ?? '' ) - ); + if ( ! empty( self::$starter_kit['image'] ) ) { + $image_url = object_to_uri( self::$starter_kit['image'] ); + + if ( $image_url ) { + \printf( + '%s', + \esc_url( $image_url ), + \esc_attr( $name ) + ); + } } if ( ! empty( self::$starter_kit['summary'] ) ) { @@ -440,11 +444,18 @@ private static function render_actor_selection( $actors ) { if ( ! self::is_valid_actor( $actor_uri ) ) { continue; } + + $actor_name = \is_array( $actor ) ? ( $actor['name'] ?? '' ) : ''; ?>
  • @@ -612,6 +623,18 @@ private static function get_actor_list() { return new \WP_Error( 'invalid_json', \esc_html__( 'Invalid JSON format in the uploaded file.', 'activitypub' ) ); } + /* + * Validate that the type is a Collection-like type. + * FeaturedCollection is from the Mastodon FEP draft: + * https://github.com/mastodon/featured_collections/pull/1 + */ + $type = (array) ( self::$starter_kit['type'] ?? array() ); + $valid_types = array( 'Collection', 'OrderedCollection', 'FeaturedCollection' ); + + if ( ! \array_intersect( $type, $valid_types ) ) { + return new \WP_Error( 'invalid_type', \esc_html__( 'The file does not contain a valid Starter Kit Collection.', 'activitypub' ) ); + } + $actors = self::$starter_kit['items'] ?? self::$starter_kit['orderedItems'] ?? array(); // Limit list to 150 actors. diff --git a/tests/phpunit/tests/includes/class-test-functions-activity.php b/tests/phpunit/tests/includes/class-test-functions-activity.php index 93bb8b10f0..1eca01a2c9 100644 --- a/tests/phpunit/tests/includes/class-test-functions-activity.php +++ b/tests/phpunit/tests/includes/class-test-functions-activity.php @@ -93,6 +93,43 @@ public function object_to_uri_provider() { ), 'https://example.com', ), + array( + array( + 'type' => 'FeaturedItem', + 'featuredObject' => 'https://example.com/users/alice', + 'featureAuthorization' => 'https://example.com/users/alice/stamps/1', + ), + 'https://example.com/users/alice', + ), + array( + array( + 'type' => 'FeaturedItem', + ), + null, + ), + // Default fallback: object with url but no id. + array( + array( + 'type' => 'Unknown', + 'url' => 'https://example.com/image.jpg', + ), + 'https://example.com/image.jpg', + ), + // Default fallback: object with href but no id or url. + array( + array( + 'type' => 'Unknown', + 'href' => 'https://example.com/link', + ), + 'https://example.com/link', + ), + // Default fallback: object with no id, url, or href. + array( + array( + 'type' => 'Unknown', + ), + null, + ), ); } diff --git a/tests/phpunit/tests/includes/class-test-moderation.php b/tests/phpunit/tests/includes/class-test-moderation.php index 0dc290ad2a..c9ac2bcbd8 100644 --- a/tests/phpunit/tests/includes/class-test-moderation.php +++ b/tests/phpunit/tests/includes/class-test-moderation.php @@ -507,23 +507,8 @@ public function test_activity_blocking_edge_cases() { ) ); - // phpcs:disable WordPress.PHP.DevelopmentFunctions.error_log_set_error_handler - \set_error_handler( - static function ( $errno, $errstr ) { - throw new \Exception( \esc_html( $errstr ), \esc_html( $errno ) ); - }, - E_NOTICE | E_WARNING - ); - - // PHP 7.x uses "Undefined index", PHP 8+ uses "Undefined array key". - if ( version_compare( PHP_VERSION, '8.0.0', '>=' ) ) { - $this->expectExceptionMessage( 'Undefined array key "id"' ); - } else { - $this->expectExceptionMessage( 'Undefined index: id' ); - } + // A malformed actor with no 'id' should gracefully return false, not trigger a PHP notice. $this->assertFalse( Moderation::activity_is_blocked( $activity ) ); - - \restore_error_handler(); } /**