WordPress.org

Make WordPress Core

Changeset 47554


Ignore:
Timestamp:
04/08/2020 12:53:18 AM (7 months ago)
Author:
azaozz
Message:

Media: Enable lazy-loading of images by automatically adding the new loading="lazy" attribute to image tags on the front-end.

  • Introduces wp_lazy_loading_enabled(), wp_filter_content_tags(), wp_img_tag_add_loading_attr(), and wp_img_tag_add_srcset_and_sizes_attr() functions.
  • Introduces wp_lazy_loading_enabled, wp_img_tag_add_loading_attr, and wp_img_tag_add_srcset_and_sizes_attr filters.

Props flixos90, addyosmani, mor10, swissspidy, pierlo, westonruter, spacedmonkey, mikeschroder, jonoaldersonwp, peterwilsoncc, narwen, jeffpaul, OptimizingMatters, futtta, mukeshpanchal27, azaozz.

Fixes #44427.

Location:
trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/default-filters.php

    r47455 r47554  
    176176add_filter( 'the_content', 'shortcode_unautop' );
    177177add_filter( 'the_content', 'prepend_attachment' );
    178 add_filter( 'the_content', 'wp_make_content_images_responsive' );
     178add_filter( 'the_content', 'wp_filter_content_tags' );
    179179
    180180add_filter( 'the_excerpt', 'wptexturize' );
     
    183183add_filter( 'the_excerpt', 'wpautop' );
    184184add_filter( 'the_excerpt', 'shortcode_unautop' );
     185add_filter( 'the_excerpt', 'wp_filter_content_tags' );
    185186add_filter( 'get_the_excerpt', 'wp_trim_excerpt', 10, 2 );
    186187
     
    208209add_filter( 'widget_text_content', 'wpautop' );
    209210add_filter( 'widget_text_content', 'shortcode_unautop' );
     211add_filter( 'widget_text_content', 'wp_filter_content_tags' );
    210212add_filter( 'widget_text_content', 'do_shortcode', 11 ); // Runs after wpautop(); note that $post global will be null when shortcodes run.
    211213
  • trunk/src/wp-includes/deprecated.php

    r47198 r47554  
    25102510 *
    25112511 * Use global $plugin_page and/or get_plugin_page_hookname() hooks.
    2512  * 
     2512 *
    25132513 * For more information on this and similar theme functions, check out
    2514  * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ 
     2514 * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/
    25152515 * Conditional Tags} article in the Theme Developer Handbook.
    2516  * 
     2516 *
    25172517 * @since 1.5.0
    25182518 * @deprecated 3.1.0
     
    37173717/**
    37183718 * Determines whether the current URL is within the comments popup window.
    3719  * 
     3719 *
    37203720 * For more information on this and similar theme functions, check out
    3721  * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ 
     3721 * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/
    37223722 * Conditional Tags} article in the Theme Developer Handbook.
    3723  * 
     3723 *
    37243724 * @since 1.5.0
    37253725 * @deprecated 4.5.0
     
    39513951    }
    39523952}
     3953
     3954/**
     3955 * Filters 'img' elements in post content to add 'srcset' and 'sizes' attributes.
     3956 *
     3957 * @since 4.4.0
     3958 * @deprecated 5.5.0
     3959 *
     3960 * @see wp_image_add_srcset_and_sizes()
     3961 *
     3962 * @param string $content The raw post content to be filtered.
     3963 * @return string Converted content with 'srcset' and 'sizes' attributes added to images.
     3964 */
     3965function wp_make_content_images_responsive( $content ) {
     3966    _deprecated_function( __FUNCTION__, '5.5.0', 'wp_filter_content_tags()' );
     3967
     3968    // This will also add the `loading` attribute to `img` tags, if enabled.
     3969    return wp_filter_content_tags( $content );
     3970}
  • trunk/src/wp-includes/media.php

    r47394 r47554  
    10221022    $html  = '';
    10231023    $image = wp_get_attachment_image_src( $attachment_id, $size, $icon );
     1024
    10241025    if ( $image ) {
    10251026        list( $src, $width, $height ) = $image;
    1026         $hwstring                     = image_hwstring( $width, $height );
    1027         $size_class                   = $size;
     1027
     1028        $attachment = get_post( $attachment_id );
     1029        $hwstring   = image_hwstring( $width, $height );
     1030        $size_class = $size;
     1031
    10281032        if ( is_array( $size_class ) ) {
    10291033            $size_class = join( 'x', $size_class );
    10301034        }
    1031         $attachment   = get_post( $attachment_id );
     1035
    10321036        $default_attr = array(
    10331037            'src'   => $src,
     
    10361040        );
    10371041
     1042        // Add `loading` attribute.
     1043        if ( wp_lazy_loading_enabled( 'img', 'wp_get_attachment_image' ) ) {
     1044            $default_attr['loading'] = 'lazy';
     1045        }
     1046
    10381047        $attr = wp_parse_args( $attr, $default_attr );
    10391048
     
    10621071         * @since 2.8.0
    10631072         *
    1064          * @param string[]     $attr       Array of attribute values for the image markup, keyed by attribute name.
     1073         * @param array        $attr       Array of attribute values for the image markup, keyed by attribute name.
    10651074         *                                 See wp_get_attachment_image().
    10661075         * @param WP_Post      $attachment Image attachment post.
     
    10691078         */
    10701079        $attr = apply_filters( 'wp_get_attachment_image_attributes', $attr, $attachment, $size );
     1080
    10711081        $attr = array_map( 'esc_attr', $attr );
    10721082        $html = rtrim( "<img $hwstring" );
     1083
    10731084        foreach ( $attr as $name => $value ) {
    10741085            $html .= " $name=" . '"' . $value . '"';
    10751086        }
     1087
    10761088        $html .= ' />';
    10771089    }
     
    14791491
    14801492/**
    1481  * Filters 'img' elements in post content to add 'srcset' and 'sizes' attributes.
    1482  *
    1483  * @since 4.4.0
    1484  *
    1485  * @see wp_image_add_srcset_and_sizes()
    1486  *
    1487  * @param string $content The raw post content to be filtered.
    1488  * @return string Converted content with 'srcset' and 'sizes' attributes added to images.
    1489  */
    1490 function wp_make_content_images_responsive( $content ) {
    1491     if ( ! preg_match_all( '/<img [^>]+>/', $content, $matches ) ) {
    1492         return $content;
    1493     }
    1494 
    1495     $selected_images = array();
    1496     $attachment_ids  = array();
    1497 
    1498     foreach ( $matches[0] as $image ) {
    1499         if ( false === strpos( $image, ' srcset=' ) && preg_match( '/wp-image-([0-9]+)/i', $image, $class_id ) ) {
    1500             $attachment_id = absint( $class_id[1] );
    1501 
    1502             if ( $attachment_id ) {
    1503                 /*
    1504                  * If exactly the same image tag is used more than once, overwrite it.
    1505                  * All identical tags will be replaced later with 'str_replace()'.
    1506                  */
    1507                 $selected_images[ $image ] = $attachment_id;
    1508                 // Overwrite the ID when the same image is included more than once.
    1509                 $attachment_ids[ $attachment_id ] = true;
    1510             }
    1511         }
    1512     }
    1513 
    1514     if ( count( $attachment_ids ) > 1 ) {
    1515         /*
    1516          * Warm the object cache with post and meta information for all found
    1517          * images to avoid making individual database calls.
    1518          */
    1519         _prime_post_caches( array_keys( $attachment_ids ), false, true );
    1520     }
    1521 
    1522     foreach ( $selected_images as $image => $attachment_id ) {
    1523         $image_meta = wp_get_attachment_metadata( $attachment_id );
    1524         $content    = str_replace( $image, wp_image_add_srcset_and_sizes( $image, $image_meta, $attachment_id ), $content );
    1525     }
    1526 
    1527     return $content;
    1528 }
    1529 
    1530 /**
    15311493 * Adds 'srcset' and 'sizes' attributes to an existing 'img' element.
    15321494 *
     
    16121574        // Add 'srcset' and 'sizes' attributes to the image markup.
    16131575        $image = preg_replace( '/<img ([^>]+?)[\/ ]*>/', '<img $1' . $attr . ' />', $image );
     1576    }
     1577
     1578    return $image;
     1579}
     1580
     1581/**
     1582 * Determine whether to add the `loading` attribute to the specified tag in the specified context.
     1583 *
     1584 * @since 5.5.0
     1585 *
     1586 * @param string $tag_name The tag name.
     1587 * @param string $context Additional context, like the current filter name or the function name from where this was called.
     1588 * @return bool Whether to add the attribute.
     1589 */
     1590function wp_lazy_loading_enabled( $tag_name, $context ) {
     1591    // By default add to all 'img' tags.
     1592    // See https://html.spec.whatwg.org/multipage/embedded-content.html#attr-img-loading
     1593    $default = ( 'img' === $tag_name );
     1594
     1595    /**
     1596     * Filters whether to add the `loading` attribute to the specified tag in the specified context.
     1597     *
     1598     * @since 5.5.0
     1599     *
     1600     * @param bool   $default Default value.
     1601     * @param string $tag_name The tag name.
     1602     * @param string $context Additional context, like the current filter name or the function name from where this was called.
     1603     */
     1604    return (bool) apply_filters( 'wp_lazy_loading_enabled', $default, $tag_name, $context );
     1605}
     1606
     1607/**
     1608 * Filters specific tags in post content and modifies their markup.
     1609 *
     1610 * This function adds `srcset`, `sizes`, and `loading` attributes to `img` HTML tags.
     1611 *
     1612 * @since 5.5.0
     1613 *
     1614 * @see wp_img_tag_add_loading_attr()
     1615 * @see wp_img_tag_add_srcset_and_sizes_attr()
     1616 *
     1617 * @param string $content The HTML content to be filtered.
     1618 * @param string $context Optional. Additional context to pass to the filters. Defaults to `current_filter()` when not set.
     1619 * @return string Converted content with images modified.
     1620 */
     1621function wp_filter_content_tags( $content, $context = null ) {
     1622    if ( null === $context ) {
     1623        $context = current_filter();
     1624    }
     1625
     1626    $add_loading_attr = wp_lazy_loading_enabled( 'img', $context );
     1627
     1628    if ( false === strpos( $content, '<img' ) ) {
     1629        return $content;
     1630    }
     1631
     1632    if ( ! preg_match_all( '/<img\s[^>]+>/', $content, $matches ) ) {
     1633        return $content;
     1634    }
     1635
     1636    // List of the unique `img` tags found in $content.
     1637    $images = array();
     1638
     1639    foreach ( $matches[0] as $image ) {
     1640        if ( preg_match( '/wp-image-([0-9]+)/i', $image, $class_id ) ) {
     1641            $attachment_id = absint( $class_id[1] );
     1642
     1643            if ( $attachment_id ) {
     1644                // If exactly the same image tag is used more than once, overwrite it.
     1645                // All identical tags will be replaced later with 'str_replace()'.
     1646                $images[ $image ] = $attachment_id;
     1647                continue;
     1648            }
     1649        }
     1650
     1651        $images[ $image ] = 0;
     1652    }
     1653
     1654    // Reduce the array to unique attachment IDs.
     1655    $attachment_ids = array_unique( array_filter( array_values( $images ) ) );
     1656
     1657    if ( count( $attachment_ids ) > 1 ) {
     1658        /*
     1659         * Warm the object cache with post and meta information for all found
     1660         * images to avoid making individual database calls.
     1661         */
     1662        _prime_post_caches( $attachment_ids, false, true );
     1663    }
     1664
     1665    foreach ( $images as $image => $attachment_id ) {
     1666        $filtered_image = $image;
     1667
     1668        // Add 'srcset' and 'sizes' attributes if applicable.
     1669        if ( $attachment_id > 0 && false === strpos( $filtered_image, ' srcset=' ) ) {
     1670            $filtered_image = wp_img_tag_add_srcset_and_sizes_attr( $filtered_image, $context, $attachment_id );
     1671        }
     1672
     1673        // Add 'loading' attribute if applicable.
     1674        if ( $add_loading_attr && false === strpos( $filtered_image, ' loading=' ) ) {
     1675            $filtered_image = wp_img_tag_add_loading_attr( $filtered_image, $context );
     1676        }
     1677
     1678        if ( $filtered_image !== $image ) {
     1679            $content = str_replace( $image, $filtered_image, $content );
     1680        }
     1681    }
     1682
     1683    return $content;
     1684}
     1685
     1686/**
     1687 * Adds `loading` attribute to an `img` HTML tag.
     1688 *
     1689 * @since 5.5.0
     1690 *
     1691 * @param string $image   The HTML `img` tag where the attribute should be added.
     1692 * @param string $context Additional context to pass to the filters.
     1693 * @return string Converted `img` tag with `loading` attribute added.
     1694 */
     1695function wp_img_tag_add_loading_attr( $image, $context ) {
     1696    /**
     1697     * Filters the `loading` attribute value. Default `lazy`.
     1698     *
     1699     * Returning `false` or an empty string will not add the attribute.
     1700     * Returning `true` will add the default value.
     1701     *
     1702     * @since 5.5.0
     1703     *
     1704     * @param string $value   The `loading` attribute value, defaults to `lazy`.
     1705     * @param string $image   The HTML `img` tag to be filtered.
     1706     * @param string $context Additional context about how the function was called or where the img tag is.
     1707     */
     1708    $value = apply_filters( 'wp_img_tag_add_loading_attr', 'lazy', $image, $context );
     1709
     1710    if ( $value ) {
     1711        if ( ! in_array( $value, array( 'lazy', 'eager' ), true ) ) {
     1712            $value = 'lazy';
     1713        }
     1714
     1715        $quote = null;
     1716
     1717        // Check if the img tag is valid (has `src` attribute) and get the quote character.
     1718        // In almost all cases it will have src and a double quote.
     1719        if ( false !== strpos( $image, ' src="' ) ) {
     1720            $quote = '"';
     1721        } elseif ( preg_match( '/\ssrc\s*=(["\'])/', $image, $matches ) ) {
     1722            $quote = $matches[1];
     1723        }
     1724
     1725        if ( $quote ) {
     1726            $loading = "loading={$quote}{$value}{$quote}";
     1727
     1728            return str_replace( '<img', "<img {$loading}", $image );
     1729        }
     1730    }
     1731
     1732    return $image;
     1733}
     1734
     1735/**
     1736 * Adds `srcset` and `sizes` attributes to an existing `img` HTML tag.
     1737 *
     1738 * @since 5.5.0
     1739 *
     1740 * @param string $image         The HTML `img` tag where the attribute should be added.
     1741 * @param string $context       Additional context to pass to the filters.
     1742 * @param int    $attachment_id Image attachment ID.
     1743 * @return string Converted 'img' element with 'loading' attribute added.
     1744 */
     1745function wp_img_tag_add_srcset_and_sizes_attr( $image, $context, $attachment_id ) {
     1746    /**
     1747     * Filters whether to add the `srcset` and `sizes` HTML attributes to the img tag. Default `true`.
     1748     *
     1749     * Returning anything else than `true` will not add the attributes.
     1750     *
     1751     * @since 5.5.0
     1752     *
     1753     * @param bool   $value         The filtered value, defaults to `true`.
     1754     * @param string $image         The HTML `img` tag where the attribute should be added.
     1755     * @param string $context       Additional context about how the function was called or where the img tag is.
     1756     * @param int    $attachment_id The image attachment ID.
     1757     */
     1758    $add = apply_filters( 'wp_img_tag_add_srcset_and_sizes_attr', true, $image, $context, $attachment_id );
     1759
     1760    if ( true === $add ) {
     1761        $image_meta = wp_get_attachment_metadata( $attachment_id );
     1762        return wp_image_add_srcset_and_sizes( $image, $image_meta, $attachment_id );
    16141763    }
    16151764
  • trunk/src/wp-includes/pluggable.php

    r47553 r47554  
    26072607     *     @type bool         $force_display Whether to always show the avatar - ignores the show_avatars option.
    26082608     *                                       Default false.
     2609     *     @type string       $loading       Value for the `loading` attribute.
     2610     *                                       Default null.
    26092611     *     @type string       $extra_attr    HTML attributes to insert in the IMG element. Is not sanitized. Default empty.
    26102612     * }
     
    26242626            'class'         => null,
    26252627            'force_display' => false,
     2628            'loading'       => null,
    26262629            'extra_attr'    => '',
    26272630        );
     2631
     2632        if ( wp_lazy_loading_enabled( 'img', 'get_avatar' ) ) {
     2633            $defaults['loading'] = 'lazy';
     2634        }
    26282635
    26292636        if ( empty( $args ) ) {
     
    26942701                $class[] = $args['class'];
    26952702            }
     2703        }
     2704
     2705        // Add `loading` attribute.
     2706        $extra_attr = $args['extra_attr'];
     2707        $loading    = $args['loading'];
     2708
     2709        if ( in_array( $loading, array( 'lazy', 'eager' ), true ) && ! preg_match( '/\bloading\s*=/', $extra_attr ) ) {
     2710            if ( ! empty( $extra_attr ) ) {
     2711                $extra_attr .= ' ';
     2712            }
     2713
     2714            $extra_attr .= "loading='{$loading}'";
    26962715        }
    26972716
     
    27042723            (int) $args['height'],
    27052724            (int) $args['width'],
    2706             $args['extra_attr']
     2725            $extra_attr
    27072726        );
    27082727
  • trunk/tests/phpunit/tests/avatar.php

    r46586 r47554  
    170170    public function test_get_avatar() {
    171171        $img = get_avatar( 1 );
    172         $this->assertEquals( preg_match( "|^<img alt='[^']*' src='[^']*' srcset='[^']*' class='[^']*' height='[^']*' width='[^']*' />$|", $img ), 1 );
     172        $this->assertEquals( preg_match( "|^<img alt='[^']*' src='[^']*' srcset='[^']*' class='[^']*' height='[^']*' width='[^']*' loading='lazy'/>$|", $img ), 1 );
    173173    }
    174174
  • trunk/tests/phpunit/tests/media.php

    r47122 r47554  
    13331333    function test_wp_get_attachment_image_defaults() {
    13341334        $image    = image_downsize( self::$large_id, 'thumbnail' );
    1335         $expected = sprintf( '<img width="%1$d" height="%2$d" src="%3$s" class="attachment-thumbnail size-thumbnail" alt="" />', $image[1], $image[2], $image[0] );
     1335        $expected = sprintf( '<img width="%1$d" height="%2$d" src="%3$s" class="attachment-thumbnail size-thumbnail" alt="" loading="lazy" />', $image[1], $image[2], $image[0] );
    13361336
    13371337        $this->assertEquals( $expected, wp_get_attachment_image( self::$large_id ) );
     
    13481348
    13491349        $image    = image_downsize( self::$large_id, 'thumbnail' );
    1350         $expected = sprintf( '<img width="%1$d" height="%2$d" src="%3$s" class="attachment-thumbnail size-thumbnail" alt="Some very clever alt text" />', $image[1], $image[2], $image[0] );
     1350        $expected = sprintf( '<img width="%1$d" height="%2$d" src="%3$s" class="attachment-thumbnail size-thumbnail" alt="Some very clever alt text" loading="lazy" />', $image[1], $image[2], $image[0] );
    13511351
    13521352        $this->assertEquals( $expected, wp_get_attachment_image( self::$large_id ) );
     
    19651965     * @ticket 33641
    19661966     */
    1967     function test_wp_make_content_images_responsive() {
     1967    function test_wp_filter_content_tags() {
    19681968        $image_meta = wp_get_attachment_metadata( self::$large_id );
    19691969        $size_array = $this->_get_image_size_array_from_meta( $image_meta, 'medium' );
     
    19741974        // Function used to build HTML for the editor.
    19751975        $img                  = get_image_tag( self::$large_id, '', '', '', 'medium' );
     1976        $img                  = wp_img_tag_add_loading_attr( $img, 'test' );
    19761977        $img_no_size_in_class = str_replace( 'size-', '', $img );
    19771978        $img_no_width_height  = str_replace( ' width="' . $size_array[0] . '"', '', $img );
     
    20152016        $content_filtered   = sprintf( $content, $respimg, $respimg_no_size_in_class, $respimg_no_width_height, $img_no_size_id, $respimg_with_sizes_attr, $respimg_xhtml, $respimg_html5 );
    20162017
    2017         $this->assertSame( $content_filtered, wp_make_content_images_responsive( $content_unfiltered ) );
     2018        $this->assertSame( $content_filtered, wp_filter_content_tags( $content_unfiltered ) );
    20182019    }
    20192020
     
    20292030     * @ticket 33641
    20302031     */
    2031     function test_wp_make_content_images_responsive_wrong() {
    2032         $image = get_image_tag( self::$large_id, '', '', '', 'medium' );
     2032    function test_wp_filter_content_tags_wrong() {
     2033        $img = get_image_tag( self::$large_id, '', '', '', 'medium' );
     2034        $img = wp_img_tag_add_loading_attr( $img, 'test' );
    20332035
    20342036        // Replace the src URL.
    2035         $image_wrong_src = preg_replace( '|src="[^"]+"|', 'src="http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/foo.jpg"', $image );
    2036 
    2037         $this->assertSame( $image_wrong_src, wp_make_content_images_responsive( $image_wrong_src ) );
     2037        $image_wrong_src = preg_replace( '|src="[^"]+"|', 'src="http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/foo.jpg"', $img );
     2038
     2039        $this->assertSame( $image_wrong_src, wp_filter_content_tags( $image_wrong_src ) );
    20382040    }
    20392041
     
    20412043     * @ticket 33641
    20422044     */
    2043     function test_wp_make_content_images_responsive_with_preexisting_srcset() {
     2045    function test_wp_filter_content_tags_with_preexisting_srcset() {
    20442046        // Generate HTML and add a dummy srcset attribute.
    2045         $image_html = get_image_tag( self::$large_id, '', '', '', 'medium' );
    2046         $image_html = preg_replace( '|<img ([^>]+) />|', '<img $1 ' . 'srcset="image2x.jpg 2x" />', $image_html );
     2047        $img = get_image_tag( self::$large_id, '', '', '', 'medium' );
     2048        $img = wp_img_tag_add_loading_attr( $img, 'test' );
     2049        $img = preg_replace( '|<img ([^>]+) />|', '<img $1 ' . 'srcset="image2x.jpg 2x" />', $img );
    20472050
    20482051        // The content filter should return the image unchanged.
    2049         $this->assertSame( $image_html, wp_make_content_images_responsive( $image_html ) );
     2052        $this->assertSame( $img, wp_filter_content_tags( $img ) );
    20502053    }
    20512054
     
    20982101     * @ticket 33641
    20992102     */
    2100     function test_wp_make_content_images_responsive_schemes() {
     2103    function test_wp_filter_content_tags_schemes() {
    21012104        $image_meta = wp_get_attachment_metadata( self::$large_id );
    21022105        $size_array = $this->_get_image_size_array_from_meta( $image_meta, 'medium' );
     
    21072110        // Build HTML for the editor.
    21082111        $img          = get_image_tag( self::$large_id, '', '', '', 'medium' );
     2112        $img          = wp_img_tag_add_loading_attr( $img, 'test' );
    21092113        $img_https    = str_replace( 'http://', 'https://', $img );
    21102114        $img_relative = str_replace( 'http://', '//', $img );
     
    21272131        $unfiltered = sprintf( $content, $img, $img_https, $img_relative );
    21282132        $expected   = sprintf( $content, $respimg, $respimg_https, $respimg_relative );
    2129         $actual     = wp_make_content_images_responsive( $unfiltered );
     2133        $actual     = wp_filter_content_tags( $unfiltered );
    21302134
    21312135        $this->assertSame( $expected, $actual );
     
    22612265
    22622266        $expected = '<img width="999" height="999" src="http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/' . $year . '/' . $month . '/test-image-testsize-999x999.png"' .
    2263             ' class="attachment-testsize size-testsize" alt=""' .
     2267            ' class="attachment-testsize size-testsize" alt="" loading="lazy"' .
    22642268            ' srcset="http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/' . $year . '/' . $month . '/test-image-testsize-999x999.png 999w,' .
    22652269                ' http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/' . $year . '/' . $month . '/test-image-large-150x150.png 150w"' .
     
    25242528        $this->assertSame( $expected, $url );
    25252529    }
     2530
     2531    /**
     2532     * @ticket 44427
     2533     */
     2534    function test_wp_lazy_load_content_media() {
     2535        $img       = get_image_tag( self::$large_id, '', '', '', 'medium' );
     2536        $img_xhtml = str_replace( ' />', '/>', $img );
     2537        $img_html5 = str_replace( ' />', '>', $img );
     2538        $iframe    = '<iframe src="https://www.example.com"></iframe>';
     2539
     2540        $lazy_img       = wp_img_tag_add_loading_attr( $img, 'test' );
     2541        $lazy_img_xhtml = wp_img_tag_add_loading_attr( $img_xhtml, 'test' );
     2542        $lazy_img_html5 = wp_img_tag_add_loading_attr( $img_html5, 'test' );
     2543
     2544        // The following should not be modified because there already is a 'loading' attribute.
     2545        $img_eager = str_replace( ' />', ' loading="eager" />', $img );
     2546
     2547        $content = '
     2548            <p>Image, standard.</p>
     2549            %1$s
     2550            <p>Image, XHTML 1.0 style (no space before the closing slash).</p>
     2551            %2$s
     2552            <p>Image, HTML 5.0 style.</p>
     2553            %3$s
     2554            <p>Image, with pre-existing "loading" attribute.</p>
     2555            %5$s
     2556            <p>Iframe, standard. Should not be modified.</p>
     2557            %4$s';
     2558
     2559        $content_unfiltered = sprintf( $content, $img, $img_xhtml, $img_html5, $iframe, $img_eager );
     2560        $content_filtered   = sprintf( $content, $lazy_img, $lazy_img_xhtml, $lazy_img_html5, $iframe, $img_eager );
     2561
     2562        // Do not add srcset and sizes.
     2563        add_filter( 'wp_img_tag_add_srcset_and_sizes_attr', '__return_false' );
     2564
     2565        $this->assertSame( $content_filtered, wp_filter_content_tags( $content_unfiltered ) );
     2566
     2567        remove_filter( 'wp_img_tag_add_srcset_and_sizes_attr', '__return_false' );
     2568    }
     2569
     2570    /**
     2571     * @ticket 44427
     2572     */
     2573    function test_wp_lazy_load_content_media_opted_in() {
     2574        $img      = get_image_tag( self::$large_id, '', '', '', 'medium' );
     2575        $lazy_img = wp_img_tag_add_loading_attr( $img, 'test' );
     2576
     2577        $content = '
     2578            <p>Image, standard.</p>
     2579            %1$s';
     2580
     2581        $content_unfiltered = sprintf( $content, $img );
     2582        $content_filtered   = sprintf( $content, $lazy_img );
     2583
     2584        // Do not add srcset and sizes while testing.
     2585        add_filter( 'wp_img_tag_add_srcset_and_sizes_attr', '__return_false' );
     2586
     2587        // Enable globally for all tags.
     2588        add_filter( 'wp_lazy_loading_enabled', '__return_true' );
     2589
     2590        $this->assertSame( $content_filtered, wp_filter_content_tags( $content_unfiltered ) );
     2591        remove_filter( 'wp_lazy_loading_enabled', '__return_true' );
     2592        remove_filter( 'wp_img_tag_add_srcset_and_sizes_attr', '__return_false' );
     2593    }
     2594
     2595    /**
     2596     * @ticket 44427
     2597     */
     2598    function test_wp_lazy_load_content_media_opted_out() {
     2599        $img = get_image_tag( self::$large_id, '', '', '', 'medium' );
     2600
     2601        $content = '
     2602            <p>Image, standard.</p>
     2603            %1$s';
     2604        $content = sprintf( $content, $img );
     2605
     2606        // Do not add srcset and sizes while testing.
     2607        add_filter( 'wp_img_tag_add_srcset_and_sizes_attr', '__return_false' );
     2608
     2609        // Disable globally for all tags.
     2610        add_filter( 'wp_lazy_loading_enabled', '__return_false' );
     2611
     2612        $this->assertSame( $content, wp_filter_content_tags( $content ) );
     2613        remove_filter( 'wp_lazy_loading_enabled', '__return_false' );
     2614        remove_filter( 'wp_img_tag_add_srcset_and_sizes_attr', '__return_false' );
     2615    }
     2616
     2617    /**
     2618     * @ticket 44427
     2619     */
     2620    function test_wp_img_tag_add_loading_attr_single_quote() {
     2621        $img = "<img src='example.png' alt='' width='300' height='225' />";
     2622        $img = wp_img_tag_add_loading_attr( $img, 'test' );
     2623
     2624        $this->assertContains( " loading='lazy'", $img );
     2625    }
    25262626}
    25272627
Note: See TracChangeset for help on using the changeset viewer.