diff --git a/CHANGELOG.md b/CHANGELOG.md index e1128d138..6097d2748 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * 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 ## [4.6.0] - 2024-12-20 diff --git a/includes/transformer/class-post.php b/includes/transformer/class-post.php index 894012320..f3cbcf960 100644 --- a/includes/transformer/class-post.php +++ b/includes/transformer/class-post.php @@ -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': diff --git a/readme.txt b/readme.txt index 19675da99..88bd189a3 100644 --- a/readme.txt +++ b/readme.txt @@ -138,6 +138,7 @@ For reasons of data protection, it is not possible to see the followers of other * 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 = 4.6.0 = diff --git a/tests/includes/transformer/class-test-post.php b/tests/includes/transformer/class-test-post.php index 6feb0fc22..a6a07202c 100644 --- a/tests/includes/transformer/class-test-post.php +++ b/tests/includes/transformer/class-test-post.php @@ -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' => '
Test alt text
', + ) + ); + $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' => '
Test alt text
', + ) ); + $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' => '
Test alt 1
Test alt 2
', + ) ); + $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'] ); } /** @@ -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 ); @@ -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; + } }