Skip to content

Commit

Permalink
Merge branch 'trunk' into update/button-only-mode-for-follow-me
Browse files Browse the repository at this point in the history
  • Loading branch information
mattwiebe authored Jan 8, 2025
2 parents 3862d96 + 134dddb commit 4172cb7
Show file tree
Hide file tree
Showing 7 changed files with 201 additions and 61 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed

* Undefined array key warnings in various places
* Fetching replies from the same instance for Enable Mastodon Apps
* Image captions not being included in the ActivityPub representation when the image is attached to the post

### Changed

Expand Down
15 changes: 11 additions & 4 deletions includes/constants.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,13 @@
'ACTIVITYPUB_MASTODON_HTML_SANITIZER',
array(
'p' => array(),
'span' => array( 'class' ),
'span' => array( 'class' => true ),
'br' => array(),
'a' => array( 'href', 'rel', 'class' ),
'a' => array(
'href' => true,
'rel' => true,
'class' => true,
),
'del' => array(),
'pre' => array(),
'code' => array(),
Expand All @@ -46,8 +50,11 @@
'i' => array(),
'u' => array(),
'ul' => array(),
'ol' => array( 'start', 'reversed' ),
'li' => array( 'value' ),
'ol' => array(
'start' => true,
'reversed' => true,
),
'li' => array( 'value' => true ),
'blockquote' => array(),
'h1' => array(),
'h2' => array(),
Expand Down
4 changes: 2 additions & 2 deletions includes/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -620,7 +620,7 @@ function is_json( $data ) {
}

/**
* Check whther a blog is public based on the `blog_public` option.
* Check whether a blog is public based on the `blog_public` option.
*
* @return bool True if public, false if not
*/
Expand Down Expand Up @@ -1071,7 +1071,7 @@ function ( $enclosure ) {
*
* @param int|\WP_Comment $comment Comment ID or comment object.
*
* @return \WP_Comment[] Array of ancestor comments or empty array if there are none.
* @return int[] Array of ancestor IDs.
*/
function get_comment_ancestors( $comment ) {
$comment = \get_comment( $comment );
Expand Down
19 changes: 15 additions & 4 deletions includes/transformer/class-post.php
Original file line number Diff line number Diff line change
Expand Up @@ -454,10 +454,21 @@ protected function get_media_from_blocks( $blocks, $media ) {
$alt = $match[2];
}

$media['image'][] = array(
'id' => $block['attrs']['id'],
'alt' => $alt,
);
$found = false;
foreach ( $media['image'] as $i => $image ) {
if ( $image['id'] === $block['attrs']['id'] ) {
$media['image'][ $i ]['alt'] = $alt;
$found = true;
break;
}
}

if ( ! $found ) {
$media['image'][] = array(
'id' => $block['attrs']['id'],
'alt' => $alt,
);
}
}
break;
case 'core/audio':
Expand Down
41 changes: 29 additions & 12 deletions integration/class-enable-mastodon-apps.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public static function init() {
\add_filter( 'mastodon_api_search', array( self::class, 'api_search_by_url' ), 40, 2 );
\add_filter( 'mastodon_api_get_posts_query_args', array( self::class, 'api_get_posts_query_args' ) );
\add_filter( 'mastodon_api_statuses', array( self::class, 'api_statuses_external' ), 10, 2 );
\add_filter( 'mastodon_api_status_context', array( self::class, 'api_get_replies' ), 10, 23 );
\add_filter( 'mastodon_api_status_context', array( self::class, 'api_get_replies' ), 10, 3 );
\add_action( 'mastodon_api_update_credentials', array( self::class, 'api_update_credentials' ), 10, 2 );
}

Expand Down Expand Up @@ -800,20 +800,37 @@ public static function api_get_replies( $context, $post_id, $url ) {
return $context;
}

$replies_url = $meta['replies']['first']['next'];
$replies = Http::get_remote_object( $replies_url, true );
if ( is_wp_error( $replies ) || ! isset( $replies['items'] ) ) {
if ( ! empty( $meta['replies']['first']['items'] ) ) {
$replies = $meta['replies']['first'];
} elseif ( isset( $meta['replies']['first']['next'] ) ) {
$replies_url = $meta['replies']['first']['next'];
$replies = Http::get_remote_object( $replies_url, true );
if ( is_wp_error( $replies ) || ! isset( $replies['items'] ) ) {
return $context;
}
} else {
return $context;
}

foreach ( $replies['items'] as $url ) {
$response = Http::get( $url, true );
if ( is_wp_error( $response ) || wp_remote_retrieve_response_code( $response ) !== 200 ) {
continue;
}
$status = json_decode( wp_remote_retrieve_body( $response ), true );
if ( ! $status || is_wp_error( $status ) ) {
continue;
foreach ( $replies['items'] as $reply ) {
if ( isset( $reply['id'] ) && is_string( $reply['id'] ) && isset( $reply['content'] ) && is_string( $reply['content'] ) ) {
$status = $reply;
} else {
if ( is_string( $reply ) ) {
$url = $reply;
} elseif ( isset( $reply['url'] ) && is_string( $reply['url'] ) ) {
$url = $reply['url'];
} else {
continue;
}
$response = Http::get( $url, true );
if ( is_wp_error( $response ) || wp_remote_retrieve_response_code( $response ) !== 200 ) {
continue;
}
$status = json_decode( wp_remote_retrieve_body( $response ), true );
if ( ! $status || is_wp_error( $status ) ) {
continue;
}
}

$account = self::get_account_for_actor( $status['attributedTo'] );
Expand Down
2 changes: 2 additions & 0 deletions readme.txt
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@ For reasons of data protection, it is not possible to see the followers of other
* Added: A filter to make custom comment types manageable in WP.com Calypso
* Changed: Hide ActivityPub post meta keys from the custom Fields UI
* Fixed: Undefined array key warnings in various places
* Fixed: Fetching replies from the same instance for Enable Mastodon Apps
* Fixed: Image captions not being included in the ActivityPub representation when the image is attached to the post
* Changed: Button only mode for the "Follow Me" Block

= 4.6.0 =
Expand Down
179 changes: 140 additions & 39 deletions tests/includes/transformer/class-test-post.php
Original file line number Diff line number Diff line change
Expand Up @@ -387,56 +387,105 @@ public function test_block_attachments_with_fallback() {
}

/**
* Saves an attachment.
*
* @param string $file The file name to create attachment object for.
* @param int $parent_id ID of the post to attach the file to.
* Test get_media_from_blocks adds alt text to existing images.
*
* @return int|WP_Error The attachment ID on success. The value 0 or WP_Error on failure.
* @covers ::get_media_from_blocks
*/
public function create_upload_object( $file, $parent_id = 0 ) {
if ( ! class_exists( 'WP_Filesystem_Direct' ) ) {
require ABSPATH . 'wp-admin/includes/class-wp-filesystem-base.php';
require ABSPATH . 'wp-admin/includes/class-wp-filesystem-direct.php';
}
public function test_get_media_from_blocks_adds_alt_text_to_existing_images() {
$post_id = self::factory()->post->create(
array(
'post_content' => '<!-- wp:image {"id":123} --><figure class="wp-block-image"><img src="test.jpg" alt="Test alt text" /></figure><!-- /wp:image -->',
)
);
$post = get_post( $post_id );

$dest = dirname( $file ) . DIRECTORY_SEPARATOR . 'test-temp.jpg';
$fs = new \WP_Filesystem_Direct( array() );
$fs->copy( $file, $dest );
$transformer = new Post( $post );
$media = array(
'image' => array(
array(
'id' => 123,
'alt' => '',
),
),
'audio' => array(),
'video' => array(),
);

$file = $dest;
$reflection = new \ReflectionClass( Post::class );
$method = $reflection->getMethod( 'get_media_from_blocks' );
$method->setAccessible( true );

$file_array = array(
'name' => wp_basename( $file ),
'tmp_name' => $file,
$blocks = parse_blocks( $post->post_content );
$result = $method->invoke( $transformer, $blocks, $media );

$this->assertSame( 'Test alt text', $result['image'][0]['alt'] );
$this->assertSame( 123, $result['image'][0]['id'] );
}

/**
* Test get_media_from_blocks adds new image when none exist.
*
* @covers ::get_media_from_blocks
*/
public function test_get_media_from_blocks_adds_new_image() {
$post_id = self::factory()->post->create(
array(
'post_content' => '<!-- wp:image {"id":123} --><figure class="wp-block-image"><img src="test.jpg" alt="Test alt text" /></figure><!-- /wp:image -->',
)
);
$post = get_post( $post_id );

$upload = wp_handle_sideload( $file_array, array( 'test_form' => false ) );
$transformer = new Post( $post );
$media = array(
'image' => array(),
'audio' => array(),
'video' => array(),
);

$type = '';
if ( ! empty( $upload['type'] ) ) {
$type = $upload['type'];
} else {
$mime = wp_check_filetype( $upload['file'] );
if ( $mime ) {
$type = $mime['type'];
}
}
$reflection = new \ReflectionClass( Post::class );
$method = $reflection->getMethod( 'get_media_from_blocks' );
$method->setAccessible( true );

$attachment = array(
'post_title' => wp_basename( $upload['file'] ),
'post_content' => '',
'post_type' => 'attachment',
'post_parent' => $parent_id,
'post_mime_type' => $type,
'guid' => $upload['url'],
$blocks = parse_blocks( $post->post_content );
$result = $method->invoke( $transformer, $blocks, $media );

$this->assertCount( 1, $result['image'] );
$this->assertSame( 123, $result['image'][0]['id'] );
$this->assertSame( 'Test alt text', $result['image'][0]['alt'] );
}

/**
* Test get_media_from_blocks handles multiple blocks correctly.
*
* @covers ::get_media_from_blocks
*/
public function test_get_media_from_blocks_handles_multiple_blocks() {
$post_id = self::factory()->post->create(
array(
'post_content' => '<!-- wp:image {"id":123} --><figure class="wp-block-image"><img src="test1.jpg" alt="Test alt 1" /></figure><!-- /wp:image --><!-- wp:image {"id":456} --><figure class="wp-block-image"><img src="test2.jpg" alt="Test alt 2" /></figure><!-- /wp:image -->',
)
);
$post = get_post( $post_id );

// Save the data.
$id = wp_insert_attachment( $attachment, $upload['file'], $parent_id );
wp_update_attachment_metadata( $id, @wp_generate_attachment_metadata( $id, $upload['file'] ) ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
$transformer = new Post( $post );
$media = array(
'image' => array(),
'audio' => array(),
'video' => array(),
);

return $id;
$reflection = new \ReflectionClass( Post::class );
$method = $reflection->getMethod( 'get_media_from_blocks' );
$method->setAccessible( true );

$blocks = parse_blocks( $post->post_content );
$result = $method->invoke( $transformer, $blocks, $media );

$this->assertCount( 2, $result['image'] );
$this->assertSame( 123, $result['image'][0]['id'] );
$this->assertSame( 'Test alt 1', $result['image'][0]['alt'] );
$this->assertSame( 456, $result['image'][1]['id'] );
$this->assertSame( 'Test alt 2', $result['image'][1]['alt'] );
}

/**
Expand All @@ -457,7 +506,7 @@ public function test_get_icon() {
$attachment_id = $this->create_upload_object( dirname( __DIR__, 2 ) . '/assets/test.jpg' );

// Set up reflection method.
$reflection = new ReflectionClass( Post::class );
$reflection = new \ReflectionClass( Post::class );
$method = $reflection->getMethod( 'get_icon' );
$method->setAccessible( true );

Expand Down Expand Up @@ -513,4 +562,56 @@ public function test_get_icon() {
wp_delete_post( $post_id, true );
wp_delete_attachment( $attachment_id, true );
}

/**
* Saves an attachment.
*
* @param string $file The file name to create attachment object for.
* @param int $parent_id ID of the post to attach the file to.
* @return int|\WP_Error The attachment ID on success. The value 0 or WP_Error on failure.
*/
public function create_upload_object( $file, $parent_id = 0 ) {
if ( ! class_exists( 'WP_Filesystem_Direct' ) ) {
require ABSPATH . 'wp-admin/includes/class-wp-filesystem-base.php';
require ABSPATH . 'wp-admin/includes/class-wp-filesystem-direct.php';
}

$dest = dirname( $file ) . DIRECTORY_SEPARATOR . 'test-temp.jpg';
$fs = new \WP_Filesystem_Direct( array() );
$fs->copy( $file, $dest );

$file = $dest;

$file_array = array(
'name' => wp_basename( $file ),
'tmp_name' => $file,
);

$upload = wp_handle_sideload( $file_array, array( 'test_form' => false ) );

$type = '';
if ( ! empty( $upload['type'] ) ) {
$type = $upload['type'];
} else {
$mime = wp_check_filetype( $upload['file'] );
if ( $mime ) {
$type = $mime['type'];
}
}

$attachment = array(
'post_title' => wp_basename( $upload['file'] ),
'post_content' => '',
'post_type' => 'attachment',
'post_parent' => $parent_id,
'post_mime_type' => $type,
'guid' => $upload['url'],
);

// Save the data.
$id = wp_insert_attachment( $attachment, $upload['file'], $parent_id );
wp_update_attachment_metadata( $id, @wp_generate_attachment_metadata( $id, $upload['file'] ) ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged

return $id;
}
}

0 comments on commit 4172cb7

Please sign in to comment.