-
Notifications
You must be signed in to change notification settings - Fork 953
Fix inline image alt text not persisting in structured data blocks #23018
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
b0e0a5c
9300f8b
9d55c6c
bff59af
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -273,4 +273,242 @@ public function test_optimize_how_to_images( $expected, $attributes, $content, $ | |
| $message, | ||
| ); | ||
| } | ||
|
|
||
| /** | ||
| * Tests that custom inline alt text is preserved. | ||
| * | ||
| * @covers ::optimize_how_to_images | ||
| * | ||
| * @return void | ||
| */ | ||
| public function test_optimize_how_to_images_preserves_custom_inline_alt_text() { | ||
| global $post; | ||
| $post = (object) [ 'ID' => 42 ]; | ||
|
|
||
| $src = 'https://example.com/image.jpg'; | ||
| $content = '<p><img src="' . $src . '" alt="Custom inline alt text" /></p>'; | ||
|
|
||
| Monkey\Functions\expect( 'register_shutdown_function' ) | ||
| ->once() | ||
| ->withAnyArgs() | ||
| ->andReturn( true ); | ||
|
|
||
| Monkey\Functions\expect( 'apply_filters' ) | ||
| ->once() | ||
| ->with( 'wpseo_structured_data_blocks_image_size', 'full', 123, $src ) | ||
| ->andReturn( 'full' ); | ||
|
|
||
| Monkey\Functions\expect( 'wp_get_attachment_image' ) | ||
| ->once() | ||
| ->with( | ||
| 123, | ||
| 'full', | ||
| false, | ||
| [ | ||
| 'style' => 'max-width: 100%; height: auto;', | ||
| 'alt' => 'Custom inline alt text', | ||
| ], | ||
| ) | ||
| ->andReturn( '<img src="' . $src . '" alt="Custom inline alt text" />' ); | ||
|
|
||
| $attributes = [ | ||
| 'steps' => [ | ||
| [ | ||
| 'images' => [ | ||
| [ | ||
| 'type' => 'img', | ||
| 'key' => 123, | ||
| 'props' => [ | ||
| 'src' => $src, | ||
| ], | ||
| ], | ||
| ], | ||
| ], | ||
| ], | ||
| ]; | ||
|
|
||
| $this->assertSame( | ||
| '<p><img src="' . $src . '" alt="Custom inline alt text" /></p>', | ||
| $this->instance->optimize_how_to_images( $attributes, $content ), | ||
| ); | ||
| } | ||
|
|
||
| /** | ||
| * Tests that entities in alt text are decoded before image generation and re-encoded in output. | ||
| * | ||
| * @covers ::optimize_how_to_images | ||
| * | ||
| * @return void | ||
| */ | ||
| public function test_optimize_how_to_images_decodes_and_reencodes_alt_entities() { | ||
| global $post; | ||
| $post = (object) [ 'ID' => 43 ]; | ||
|
|
||
| $src = 'https://example.com/image.jpg'; | ||
| $encoded_alt = 'Tom & Jerry's "Guide"'; | ||
| $decoded_alt = 'Tom & Jerry\'s "Guide"'; | ||
| $re_encoded_alt = \htmlspecialchars( $decoded_alt, ( \ENT_QUOTES | \ENT_HTML5 ), 'UTF-8' ); | ||
| $content = '<p><img src="' . $src . '" alt="' . $encoded_alt . '" /></p>'; | ||
|
|
||
| Monkey\Functions\expect( 'register_shutdown_function' ) | ||
| ->once() | ||
| ->withAnyArgs() | ||
| ->andReturn( true ); | ||
|
|
||
| Monkey\Functions\expect( 'apply_filters' ) | ||
| ->once() | ||
| ->with( 'wpseo_structured_data_blocks_image_size', 'full', 123, $src ) | ||
| ->andReturn( 'full' ); | ||
|
|
||
| Monkey\Functions\expect( 'wp_get_attachment_image' ) | ||
| ->once() | ||
| ->with( | ||
| 123, | ||
| 'full', | ||
| false, | ||
| [ | ||
| 'style' => 'max-width: 100%; height: auto;', | ||
| 'alt' => $decoded_alt, | ||
| ], | ||
| ) | ||
| ->andReturn( '<img src="' . $src . '" alt="' . $re_encoded_alt . '" />' ); | ||
|
|
||
| $attributes = [ | ||
| 'steps' => [ | ||
| [ | ||
| 'images' => [ | ||
| [ | ||
| 'type' => 'img', | ||
| 'key' => 123, | ||
| 'props' => [ | ||
| 'src' => $src, | ||
| ], | ||
| ], | ||
| ], | ||
| ], | ||
| ], | ||
| ]; | ||
|
|
||
| $this->assertSame( | ||
| '<p><img src="' . $src . '" alt="' . $re_encoded_alt . '" /></p>', | ||
| $this->instance->optimize_how_to_images( $attributes, $content ), | ||
| ); | ||
| } | ||
|
|
||
| /** | ||
| * Tests that an empty alt attribute is preserved. | ||
| * | ||
| * @covers ::optimize_how_to_images | ||
| * | ||
| * @return void | ||
| */ | ||
| public function test_optimize_how_to_images_preserves_empty_alt_attribute() { | ||
| global $post; | ||
| $post = (object) [ 'ID' => 44 ]; | ||
|
|
||
| $src = 'https://example.com/image.jpg'; | ||
| $content = '<p><img src="' . $src . '" alt="" /></p>'; | ||
|
|
||
| Monkey\Functions\expect( 'register_shutdown_function' ) | ||
| ->once() | ||
| ->withAnyArgs() | ||
| ->andReturn( true ); | ||
|
|
||
| Monkey\Functions\expect( 'apply_filters' ) | ||
| ->once() | ||
| ->with( 'wpseo_structured_data_blocks_image_size', 'full', 123, $src ) | ||
| ->andReturn( 'full' ); | ||
|
|
||
| Monkey\Functions\expect( 'wp_get_attachment_image' ) | ||
| ->once() | ||
| ->with( | ||
| 123, | ||
| 'full', | ||
| false, | ||
| [ | ||
| 'style' => 'max-width: 100%; height: auto;', | ||
| 'alt' => '', | ||
| ], | ||
| ) | ||
| ->andReturn( '<img src="' . $src . '" alt="" />' ); | ||
|
|
||
| $attributes = [ | ||
| 'steps' => [ | ||
| [ | ||
| 'images' => [ | ||
| [ | ||
| 'type' => 'img', | ||
| 'key' => 123, | ||
| 'props' => [ | ||
| 'src' => $src, | ||
| ], | ||
| ], | ||
| ], | ||
| ], | ||
| ], | ||
| ]; | ||
|
|
||
| $this->assertSame( | ||
| '<p><img src="' . $src . '" alt="" /></p>', | ||
| $this->instance->optimize_how_to_images( $attributes, $content ), | ||
| ); | ||
| } | ||
|
|
||
| /** | ||
| * Tests that missing alt attribute falls back to media library alt text. | ||
| * | ||
| * @covers ::optimize_how_to_images | ||
| * | ||
| * @return void | ||
| */ | ||
| public function test_optimize_how_to_images_missing_alt_falls_back_to_media_library() { | ||
| global $post; | ||
| $post = (object) [ 'ID' => 45 ]; | ||
|
|
||
| $src = 'https://example.com/image.jpg'; | ||
| $content = '<p><img src="' . $src . '" /></p>'; | ||
|
|
||
| Monkey\Functions\expect( 'register_shutdown_function' ) | ||
| ->once() | ||
| ->withAnyArgs() | ||
| ->andReturn( true ); | ||
|
|
||
| Monkey\Functions\expect( 'apply_filters' ) | ||
| ->once() | ||
| ->with( 'wpseo_structured_data_blocks_image_size', 'full', 123, $src ) | ||
| ->andReturn( 'full' ); | ||
|
|
||
| Monkey\Functions\expect( 'wp_get_attachment_image' ) | ||
| ->once() | ||
| ->with( | ||
| 123, | ||
| 'full', | ||
| false, | ||
| [ | ||
| 'style' => 'max-width: 100%; height: auto;', | ||
| ], | ||
|
Comment on lines
+486
to
+489
|
||
| ) | ||
| ->andReturn( '<img src="' . $src . '" alt="Media library alt" />' ); | ||
|
|
||
| $attributes = [ | ||
| 'steps' => [ | ||
| [ | ||
| 'images' => [ | ||
| [ | ||
| 'type' => 'img', | ||
| 'key' => 123, | ||
| 'props' => [ | ||
| 'src' => $src, | ||
| ], | ||
| ], | ||
| ], | ||
| ], | ||
| ], | ||
| ]; | ||
|
|
||
| $this->assertSame( | ||
| '<p><img src="' . $src . '" alt="Media library alt" /></p>', | ||
| $this->instance->optimize_how_to_images( $attributes, $content ), | ||
| ); | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
$image_attrsalways includes an'alt'key, so when noaltis present in the original<img>this will passalt => ''intowp_get_attachment_image()and override the attachment’s stored alt text (previously WordPress would fall back to media-library alt whenaltisn’t provided). To keep backward compatibility, only add the'alt'attribute to$image_attrswhen the original HTML contains analtattribute (while still preserving an explicitly emptyalt="").