Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/changelog/3168-from-description
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: added

Add support for importing Starter Packs in both the Pixelfed and Mastodon formats.
14 changes: 13 additions & 1 deletion includes/functions-activity.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Comment thread
pfefferle marked this conversation as resolved.

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;
}

Expand Down
37 changes: 30 additions & 7 deletions includes/wp-admin/import/class-starter-kit.php
Original file line number Diff line number Diff line change
Expand Up @@ -378,12 +378,16 @@ private static function render_starter_kit_info() {

echo '<h3>' . \esc_html( $name ) . '</h3>';

if ( ! empty( self::$starter_kit['image']['url'] ) ) {
\printf(
'<img src="%s" style="max-width: 500px;" alt="%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(
'<img src="%s" style="max-width: 500px;" alt="%s" />',
\esc_url( $image_url ),
\esc_attr( $name )
);
}
}

if ( ! empty( self::$starter_kit['summary'] ) ) {
Expand Down Expand Up @@ -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'] ?? '' ) : '';
?>
<li>
<label>
<input type="checkbox" name="actors[]" value="<?php echo \esc_attr( $actor_uri ); ?>" checked />
<?php echo \esc_html( $actor_uri ); ?>
<?php if ( $actor_name ) : ?>
<strong><?php echo \esc_html( $actor_name ); ?></strong>
(<?php echo \esc_html( $actor_uri ); ?>)
<?php else : ?>
<?php echo \esc_html( $actor_uri ); ?>
<?php endif; ?>
</label>
</li>
<?php endforeach; ?>
Expand Down Expand Up @@ -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.
Expand Down
37 changes: 37 additions & 0 deletions tests/phpunit/tests/includes/class-test-functions-activity.php
Original file line number Diff line number Diff line change
Expand Up @@ -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,
),
);
}

Expand Down
17 changes: 1 addition & 16 deletions tests/phpunit/tests/includes/class-test-moderation.php
Original file line number Diff line number Diff line change
Expand Up @@ -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 &quot;id&quot;' );
} 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();
}

/**
Expand Down
Loading