diff --git a/src/wp-includes/media.php b/src/wp-includes/media.php index 0dc67f7b86..74796210e2 100644 --- a/src/wp-includes/media.php +++ b/src/wp-includes/media.php @@ -1048,6 +1048,12 @@ function wp_get_attachment_image( $attachment_id, $size = 'thumbnail', $icon = f $attr = wp_parse_args( $attr, $default_attr ); + // If `loading` attribute default of `lazy` is overridden for this + // image to omit the attribute, ensure it is not included. + if ( array_key_exists( 'loading', $attr ) && ! $attr['loading'] ) { + unset( $attr['loading'] ); + } + // Generate 'srcset' and 'sizes' if not already present. if ( empty( $attr['srcset'] ) ) { $image_meta = wp_get_attachment_metadata( $attachment_id ); @@ -1725,9 +1731,10 @@ function wp_img_tag_add_loading_attr( $image, $context ) { * * @since 5.5.0 * - * @param string $value The `loading` attribute value, defaults to `lazy`. - * @param string $image The HTML `img` tag to be filtered. - * @param string $context Additional context about how the function was called or where the img tag is. + * @param string|bool $value The `loading` attribute value. Returning a false-y value will result in the + * attribute being omitted for the image. Default is `lazy`. + * @param string $image The HTML `img` tag to be filtered. + * @param string $context Additional context about how the function was called or where the img tag is. */ $value = apply_filters( 'wp_img_tag_add_loading_attr', 'lazy', $image, $context ); diff --git a/tests/phpunit/tests/media.php b/tests/phpunit/tests/media.php index 89b10be605..dbab853099 100644 --- a/tests/phpunit/tests/media.php +++ b/tests/phpunit/tests/media.php @@ -2675,24 +2675,139 @@ EOF; } /** + * @ticket 44427 + * @ticket 50367 + */ + function test_wp_img_tag_add_loading_attr() { + $img = ' width='; + $img = wp_img_tag_add_loading_attr( $img, 'test' ); + + $this->assertContains( ' loading="lazy"', $img ); + } + + /** + * @ticket 44427 * @ticket 50367 */ function test_wp_img_tag_add_loading_attr_without_src() { $img = ' width='; $img = wp_img_tag_add_loading_attr( $img, 'test' ); - $this->assertNotContains( ' loading="lazy"', $img ); + $this->assertNotContains( ' loading=', $img ); } /** + * @ticket 44427 * @ticket 50367 */ function test_wp_img_tag_add_loading_attr_with_single_quotes() { $img = " width="; $img = wp_img_tag_add_loading_attr( $img, 'test' ); + $this->assertNotContains( ' loading=', $img ); + + // Test specifically that the attribute is not there with double-quotes, + // to avoid regressions. $this->assertNotContains( ' loading="lazy"', $img ); } + + /** + * @ticket 44427 + * @ticket 50425 + */ + function test_wp_img_tag_add_loading_attr_opt_out() { + $img = ' width='; + add_filter( 'wp_img_tag_add_loading_attr', '__return_false' ); + + $this->assertNotContains( ' loading=', $img ); + } + + /** + * @ticket 44427 + * @ticket 50425 + */ + function test_wp_get_attachment_image_loading() { + $img = wp_get_attachment_image( self::$large_id ); + + $this->assertContains( ' loading="lazy"', $img ); + } + + /** + * @ticket 44427 + * @ticket 50425 + */ + function test_wp_get_attachment_image_loading_opt_out() { + add_filter( 'wp_lazy_loading_enabled', '__return_false' ); + $img = wp_get_attachment_image( self::$large_id ); + + // There should not be any loading attribute in this case. + $this->assertNotContains( ' loading=', $img ); + } + + /** + * @ticket 44427 + * @ticket 50425 + */ + function test_wp_get_attachment_image_loading_opt_out_individual() { + // The default is already tested above, the filter below ensures that + // lazy-loading is definitely enabled globally for images. + add_filter( 'wp_lazy_loading_enabled', '__return_true' ); + + $img = wp_get_attachment_image( self::$large_id, 'thumbnail', false, array( 'loading' => false ) ); + + // There should not be any loading attribute in this case. + $this->assertNotContains( ' loading=', $img ); + } + + /** + * @ticket 44427 + * @ticket 50425 + * @dataProvider data_wp_lazy_loading_enabled_tag_name_defaults + * + * @param string $tag_name Function context. + * @param bool $expected Expected return value. + */ + function test_wp_lazy_loading_enabled_tag_name_defaults( $tag_name, $expected ) { + if ( $expected ) { + $this->assertTrue( wp_lazy_loading_enabled( $tag_name, 'the_content' ) ); + } else { + $this->assertFalse( wp_lazy_loading_enabled( $tag_name, 'the_content' ) ); + } + } + + function data_wp_lazy_loading_enabled_tag_name_defaults() { + return array( + 'img => true' => array( 'img', true ), + 'iframe => false' => array( 'iframe', false ), + 'arbitrary tag => false' => array( 'blink', false ), + ); + } + + /** + * @ticket 50425 + * @dataProvider data_wp_lazy_loading_enabled_context_defaults + * + * @param string $context Function context. + * @param bool $expected Expected return value. + */ + function test_wp_lazy_loading_enabled_context_defaults( $context, $expected ) { + if ( $expected ) { + $this->assertTrue( wp_lazy_loading_enabled( 'img', $context ) ); + } else { + $this->assertFalse( wp_lazy_loading_enabled( 'img', $context ) ); + } + } + + function data_wp_lazy_loading_enabled_context_defaults() { + return array( + 'wp_get_attachment_image => true' => array( 'wp_get_attachment_image', true ), + 'the_content => true' => array( 'the_content', true ), + 'the_excerpt => true' => array( 'the_excerpt', true ), + 'widget_text_content => true' => array( 'widget_text_content', true ), + 'get_avatar => true' => array( 'get_avatar', true ), + 'arbitrary context => true' => array( 'something_completely_arbitrary', true ), + ); + } } /**