WordPress.org

Make WordPress Core

Ticket #44427: 44427.10.diff

File 44427.10.diff, 25.3 KB (added by azaozz, 7 months ago)
  • src/wp-includes/default-filters.php

     
    175175add_filter( 'the_content', 'wpautop' );
    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' );
    181181add_filter( 'the_excerpt', 'convert_smilies' );
     
    182182add_filter( 'the_excerpt', 'convert_chars' );
    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
    187188add_filter( 'the_post_thumbnail_caption', 'wptexturize' );
     
    207208add_filter( 'widget_text_content', 'convert_smilies', 20 );
    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
    212214// RSS filters.
  • src/wp-includes/deprecated.php

     
    25092509 * Determines whether the current admin page is generated by a plugin.
    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
    25192519 *
     
    37163716
    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
    37263726 *
     
    39503950                wp_send_json_error( array( 'errorMessage' => __( 'The Press This plugin is required.' ) ) );
    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}
  • src/wp-includes/media.php

     
    10211021function wp_get_attachment_image( $attachment_id, $size = 'thumbnail', $icon = false, $attr = '' ) {
    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,
    10341038                        'class' => "attachment-$size_class size-$size_class",
     
    10351039                        'alt'   => trim( strip_tags( get_post_meta( $attachment_id, '_wp_attachment_image_alt', true ) ) ),
    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
    10401049                // Generate 'srcset' and 'sizes' if not already present.
     
    10611070                 *
    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.
    10671076                 * @param string|array $size       Requested size. Image size or array of width and height values
     
    10681077                 *                                 (in that order). Default 'thumbnail'.
    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        }
    10781090
     
    14781490}
    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 *
    15331495 * @since 4.4.0
     
    16171579}
    16181580
    16191581/**
     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 existing `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' element 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                // Get the quote character used in the tag.
     1718                // Normally it will be a double quote but in some rare cases may be a single quote.
     1719                // This also checks if the `img` tag is not malformed, i.e. it has a `src` attribute.
     1720                if ( false !== strpos( $image, ' src="' ) ) {
     1721                        $quote = '"';
     1722                } elseif ( preg_match( '/\ssrc\s*=(["\'])/', $image, $matches ) ) {
     1723                        $quote = $matches[1];
     1724                }
     1725
     1726                if ( $quote ) {
     1727                        $loading = "loading={$quote}{$value}{$quote}";
     1728
     1729                        return str_replace( '<img', "<img {$loading}", $image );
     1730                }
     1731        }
     1732
     1733        return $image;
     1734}
     1735
     1736/**
     1737 * Adds `srcset` and `sizes` attributes to an existing `img` HTML tag.
     1738 *
     1739 * @since 5.5.0
     1740 *
     1741 * @param string $image         The HTML `img` tag where the attribute should be added.
     1742 * @param string $context       Additional context to pass to the filters.
     1743 * @param int    $attachment_id Image attachment ID.
     1744 * @return string Converted 'img' element with 'loading' attribute added.
     1745 */
     1746function wp_img_tag_add_srcset_and_sizes_attr( $image, $context, $attachment_id ) {
     1747        /**
     1748         * Filters whether to add the `srcset` and `sizes` HTML attributes to the img tag. Default `true`.
     1749         *
     1750         * Returning anything else than `true` will not add the attributes.
     1751         *
     1752         * @since 5.5.0
     1753         *
     1754         * @param bool   $value         The filtered value, defaults to `true`.
     1755         * @param string $image         The HTML `img` tag where the attribute should be added.
     1756         * @param string $context       Additional context about how the function was called or where the img tag is.
     1757         * @param int    $attachment_id The image attachment ID.
     1758         */
     1759        $add = apply_filters( 'wp_img_tag_add_srcset_and_sizes_attr', true, $image, $context, $attachment_id );
     1760
     1761        if ( true === $add ) {
     1762                $image_meta = wp_get_attachment_metadata( $attachment_id );
     1763                return wp_image_add_srcset_and_sizes( $image, $image_meta, $attachment_id );
     1764        }
     1765
     1766        return $image;
     1767}
     1768
     1769/**
    16201770 * Adds a 'wp-post-image' class to post thumbnails. Internal use only.
    16211771 *
    16221772 * Uses the {@see 'begin_fetch_post_thumbnail_html'} and {@see 'end_fetch_post_thumbnail_html'}
  • src/wp-includes/pluggable.php

     
    26012601         *                                       Default null.
    26022602         *     @type bool         $force_display Whether to always show the avatar - ignores the show_avatars option.
    26032603         *                                       Default false.
     2604         *     @type string       $loading       Value for the `loading` attribute.
     2605         *                                       Default null.
    26042606         *     @type string       $extra_attr    HTML attributes to insert in the IMG element. Is not sanitized. Default empty.
    26052607         * }
    26062608         * @return string|false `<img>` tag for the user's avatar. False on failure.
     
    26182620                        'alt'           => '',
    26192621                        'class'         => null,
    26202622                        'force_display' => false,
     2623                        'loading'       => null,
    26212624                        'extra_attr'    => '',
    26222625                );
    26232626
     2627                if ( wp_lazy_loading_enabled( 'img', 'get_avatar' ) ) {
     2628                        $defaults['loading'] = 'lazy';
     2629                }
     2630
    26242631                if ( empty( $args ) ) {
    26252632                        $args = array();
    26262633                }
     
    26902697                        }
    26912698                }
    26922699
     2700                // Add `loading` attribute.
     2701                $extra_attr = $args['extra_attr'];
     2702                $loading    = $args['loading'];
     2703
     2704                if ( in_array( $loading, array( 'lazy', 'eager' ), true ) && ! preg_match( '/\bloading\s*=/', $extra_attr ) ) {
     2705                        if ( ! empty( $extra_attr ) ) {
     2706                                $extra_attr .= ' ';
     2707                        }
     2708
     2709                        $extra_attr .= "loading='{$loading}'";
     2710                }
     2711
    26932712                $avatar = sprintf(
    26942713                        "<img alt='%s' src='%s' srcset='%s' class='%s' height='%d' width='%d' %s/>",
    26952714                        esc_attr( $args['alt'] ),
     
    26982717                        esc_attr( join( ' ', $class ) ),
    26992718                        (int) $args['height'],
    27002719                        (int) $args['width'],
    2701                         $args['extra_attr']
     2720                        $extra_attr
    27022721                );
    27032722
    27042723                /**
  • tests/phpunit/tests/avatar.php

     
    169169
    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
    175175        public function test_get_avatar_size() {
  • tests/phpunit/tests/media.php

     
    13321332         */
    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 ) );
    13381338        }
     
    13471347                update_post_meta( self::$large_id, '_wp_attachment_image_alt', 'Some very clever alt text', true );
    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 ) );
    13531353
     
    19641964        /**
    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' );
    19701970
     
    19731973
    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 );
    19781979                $img_no_width_height  = str_replace( ' height="' . $size_array[1] . '"', '', $img_no_width_height );
     
    20142015                $content_unfiltered = sprintf( $content, $img, $img_no_size_in_class, $img_no_width_height, $img_no_size_id, $img_with_sizes_attr, $img_xhtml, $img_html5 );
    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
    20202021        /**
     
    20282029         * @ticket 34898
    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 );
     2037                $image_wrong_src = preg_replace( '|src="[^"]+"|', 'src="http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/foo.jpg"', $img );
    20362038
    2037                 $this->assertSame( $image_wrong_src, wp_make_content_images_responsive( $image_wrong_src ) );
     2039                $this->assertSame( $image_wrong_src, wp_filter_content_tags( $image_wrong_src ) );
    20382040        }
    20392041
    20402042        /**
    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
    20522055        /**
     
    20972100         * @ticket 35045
    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' );
    21032106
     
    21062109
    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 );
    21112115
     
    21262130
    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 );
    21322136        }
     
    22602264                $month  = gmdate( 'm' );
    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"' .
    22662270                                ' sizes="(max-width: 999px) 100vw, 999px" />';
     
    25232527
    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
    25282628/**