diff --git a/src/wp-includes/media.php b/src/wp-includes/media.php index 804a34f6ac..389be76f29 100644 --- a/src/wp-includes/media.php +++ b/src/wp-includes/media.php @@ -1023,7 +1023,8 @@ function wp_get_attachment_image_src( $attachment_id, $size = 'thumbnail', $icon * will result in the attribute being omitted for the image. * Defaults to 'lazy', depending on wp_lazy_loading_enabled(). * @type string $decoding The 'decoding' attribute value. Possible values are - * 'async' (default), 'sync', or 'auto'. + * 'async' (default), 'sync', or 'auto'. Passing false or an empty + * string will result in the attribute being omitted. * } * @return string HTML img element or empty string on failure. */ @@ -1056,6 +1057,11 @@ function wp_get_attachment_image( $attachment_id, $size = 'thumbnail', $icon = f $attr = wp_parse_args( $attr, $default_attr ); + // Omit the `decoding` attribute if the value is invalid according to the spec. + if ( empty( $attr['decoding'] ) || ! in_array( $attr['decoding'], array( 'async', 'sync', 'auto' ), true ) ) { + unset( $attr['decoding'] ); + } + // If the default value of `lazy` for the `loading` attribute is overridden // to omit the attribute for this image, ensure it is not included. if ( array_key_exists( 'loading', $attr ) && ! $attr['loading'] ) { diff --git a/tests/phpunit/tests/media.php b/tests/phpunit/tests/media.php index 5165e32b85..994b4b7c72 100644 --- a/tests/phpunit/tests/media.php +++ b/tests/phpunit/tests/media.php @@ -3278,6 +3278,81 @@ EOF; $this->assertStringNotContainsString( ' loading=', $img ); } + /** + * @ticket 57086 + * + * @dataProvider data_wp_get_attachment_image_decoding_attr + * + * @covers ::wp_get_attachment_image + */ + public function test_wp_get_attachment_image_decoding_attr( $decoding, $expected ) { + if ( 'no value' === $decoding ) { + $image = wp_get_attachment_image( self::$large_id, 'thumbnail', false, array() ); + } else { + $image = wp_get_attachment_image( self::$large_id, 'thumbnail', false, array( 'decoding' => $decoding ) ); + } + + if ( 'no value' === $expected ) { + $this->assertStringNotContainsString( ' decoding=', $image ); + } else { + $this->assertStringContainsString( ' decoding="' . esc_attr( $expected ) . '"', $image ); + } + } + + /** + * Data provider for test_wp_get_attachment_image_decoding_attr(). + * + * @return array[] + */ + public function data_wp_get_attachment_image_decoding_attr() { + return array( + 'default' => array( + 'decoding' => 'no value', + 'expected' => 'async', + ), + 'async' => array( + 'decoding' => 'async', + 'expected' => 'async', + ), + 'sync' => array( + 'decoding' => 'sync', + 'expected' => 'sync', + ), + 'auto' => array( + 'decoding' => 'auto', + 'expected' => 'auto', + ), + 'empty' => array( + 'decoding' => '', + 'expected' => 'no value', + ), + 'false' => array( + 'decoding' => false, + 'expected' => 'no value', + ), + 'null' => array( + 'decoding' => null, + 'expected' => 'no value', + ), + 'zero' => array( + 'decoding' => 0, + 'expected' => 'no value', + ), + 'zero string' => array( + 'decoding' => '0', + 'expected' => 'no value', + ), + 'zero float' => array( + 'decoding' => 0.0, + 'expected' => 'no value', + ), + 'invalid' => array( + 'decoding' => 'invalid', + 'expected' => 'no value', + ), + ); + } + /** * @ticket 44427 * @ticket 50425