Changeset 56037 for trunk/src/wp-includes/media.php
- Timestamp:
- 06/26/2023 04:15:12 PM (22 months ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-includes/media.php
r56031 r56037 1059 1059 */ 1060 1060 $context = apply_filters( 'wp_get_attachment_image_context', 'wp_get_attachment_image' ); 1061 1062 // Add `loading` attribute. 1063 if ( wp_lazy_loading_enabled( 'img', $context ) ) { 1064 $default_attr['loading'] = wp_get_loading_attr_default( $context ); 1065 } 1066 1067 $attr = wp_parse_args( $attr, $default_attr ); 1061 $attr = wp_parse_args( $attr, $default_attr ); 1062 1063 $loading_attr = $attr; 1064 $loading_attr['width'] = $width; 1065 $loading_attr['height'] = $height; 1066 $loading_optimization_attr = wp_get_loading_optimization_attributes( 1067 'img', 1068 $loading_attr, 1069 $context 1070 ); 1071 1072 // Add loading optimization attributes if not available. 1073 $attr = array_merge( $attr, $loading_optimization_attr ); 1068 1074 1069 1075 // Omit the `decoding` attribute if the value is invalid according to the spec. … … 1074 1080 // If the default value of `lazy` for the `loading` attribute is overridden 1075 1081 // to omit the attribute for this image, ensure it is not included. 1076 if ( array_key_exists( 'loading', $attr) && ! $attr['loading'] ) {1082 if ( isset( $attr['loading'] ) && ! $attr['loading'] ) { 1077 1083 unset( $attr['loading'] ); 1084 } 1085 1086 // If the `fetchpriority` attribute is overridden and set to false or an empty string. 1087 if ( isset( $attr['fetchpriority'] ) && ! $attr['fetchpriority'] ) { 1088 unset( $attr['fetchpriority'] ); 1078 1089 } 1079 1090 … … 1781 1792 * @see wp_img_tag_add_width_and_height_attr() 1782 1793 * @see wp_img_tag_add_srcset_and_sizes_attr() 1783 * @see wp_img_tag_add_loading_ attr()1794 * @see wp_img_tag_add_loading_optimization_attrs() 1784 1795 * @see wp_iframe_tag_add_loading_attr() 1785 1796 * … … 1794 1805 } 1795 1806 1796 $add_img_loading_attr = wp_lazy_loading_enabled( 'img', $context );1797 1807 $add_iframe_loading_attr = wp_lazy_loading_enabled( 'iframe', $context ); 1798 1808 … … 1858 1868 } 1859 1869 1860 // Add 'loading' attribute if applicable. 1861 if ( $add_img_loading_attr && ! str_contains( $filtered_image, ' loading=' ) ) { 1862 $filtered_image = wp_img_tag_add_loading_attr( $filtered_image, $context ); 1863 } 1870 // Add loading optimization attributes if applicable. 1871 $filtered_image = wp_img_tag_add_loading_optimization_attrs( $filtered_image, $context ); 1864 1872 1865 1873 // Add 'decoding=async' attribute unless a 'decoding' attribute is already present. … … 1915 1923 1916 1924 /** 1917 * Adds `loading` attributeto an `img` HTML tag.1918 * 1919 * @since 5.5.01925 * Adds optimization attributes to an `img` HTML tag. 1926 * 1927 * @since 6.3.0 1920 1928 * 1921 1929 * @param string $image The HTML `img` tag where the attribute should be added. 1922 1930 * @param string $context Additional context to pass to the filters. 1923 * @return string Converted `img` tag with `loading` attribute added. 1924 */ 1925 function wp_img_tag_add_loading_attr( $image, $context ) { 1926 // Get loading attribute value to use. This must occur before the conditional check below so that even images that 1927 // are ineligible for being lazy-loaded are considered. 1928 $value = wp_get_loading_attr_default( $context ); 1929 1930 // Images should have source and dimension attributes for the `loading` attribute to be added. 1931 * @return string Converted `img` tag with optimization attributes added. 1932 */ 1933 function wp_img_tag_add_loading_optimization_attrs( $image, $context ) { 1934 $width = preg_match( '/ width=["\']([0-9]+)["\']/', $image, $match_width ) ? (int) $match_width[1] : null; 1935 $height = preg_match( '/ height=["\']([0-9]+)["\']/', $image, $match_height ) ? (int) $match_height[1] : null; 1936 $loading_val = preg_match( '/ loading=["\']([A-Za-z]+)["\']/', $image, $match_loading ) ? $match_loading[1] : null; 1937 $fetchpriority_val = preg_match( '/ fetchpriority=["\']([A-Za-z]+)["\']/', $image, $match_fetchpriority ) ? $match_fetchpriority[1] : null; 1938 1939 /* 1940 * Get loading optimization attributes to use. 1941 * This must occur before the conditional check below so that even images 1942 * that are ineligible for being lazy-loaded are considered. 1943 */ 1944 $optimization_attrs = wp_get_loading_optimization_attributes( 1945 'img', 1946 array( 1947 'width' => $width, 1948 'height' => $height, 1949 'loading' => $loading_val, 1950 'fetchpriority' => $fetchpriority_val, 1951 ), 1952 $context 1953 ); 1954 1955 // Images should have source and dimension attributes for the loading optimization attributes to be added. 1931 1956 if ( ! str_contains( $image, ' src="' ) || ! str_contains( $image, ' width="' ) || ! str_contains( $image, ' height="' ) ) { 1932 1957 return $image; 1933 1958 } 1934 1959 1935 /** 1936 * Filters the `loading` attribute value to add to an image. Default `lazy`. 1937 * 1938 * Returning `false` or an empty string will not add the attribute. 1939 * Returning `true` will add the default value. 1940 * 1941 * @since 5.5.0 1942 * 1943 * @param string|bool $value The `loading` attribute value. Returning a falsey value will result in 1944 * the attribute being omitted for the image. 1945 * @param string $image The HTML `img` tag to be filtered. 1946 * @param string $context Additional context about how the function was called or where the img tag is. 1947 */ 1948 $value = apply_filters( 'wp_img_tag_add_loading_attr', $value, $image, $context ); 1949 1950 if ( $value ) { 1951 if ( ! in_array( $value, array( 'lazy', 'eager' ), true ) ) { 1952 $value = 'lazy'; 1953 } 1954 1955 return str_replace( '<img', '<img loading="' . esc_attr( $value ) . '"', $image ); 1960 // Retained for backward compatibility. 1961 $loading_attrs_enabled = wp_lazy_loading_enabled( 'img', $context ); 1962 1963 if ( empty( $loading_val ) && $loading_attrs_enabled ) { 1964 /** 1965 * Filters the `loading` attribute value to add to an image. Default `lazy`. 1966 * This filter is added in for backward compatibility. 1967 * 1968 * Returning `false` or an empty string will not add the attribute. 1969 * Returning `true` will add the default value. 1970 * `true` and `false` usage supported for backward compatibility. 1971 * 1972 * @since 5.5.0 1973 * 1974 * @param string|bool $loading Current value for `loading` attribute for the image. 1975 * @param string $image The HTML `img` tag to be filtered. 1976 * @param string $context Additional context about how the function was called or where the img tag is. 1977 */ 1978 $filtered_loading_attr = apply_filters( 1979 'wp_img_tag_add_loading_attr', 1980 isset( $optimization_attrs['loading'] ) ? $optimization_attrs['loading'] : false, 1981 $image, 1982 $context 1983 ); 1984 1985 // Validate the values after filtering. 1986 if ( isset( $optimization_attrs['loading'] ) && ! $filtered_loading_attr ) { 1987 // Unset `loading` attributes if `$filtered_loading_attr` is set to `false`. 1988 unset( $optimization_attrs['loading'] ); 1989 } elseif ( in_array( $filtered_loading_attr, array( 'lazy', 'eager' ), true ) ) { 1990 /* 1991 * If the filter changed the loading attribute to "lazy" when a fetchpriority attribute 1992 * with value "high" is already present, trigger a warning since those two attribute 1993 * values should be mutually exclusive. 1994 * 1995 * The same warning is present in `wp_get_loading_optimization_attributes()`, and here it 1996 * is only intended for the specific scenario where the above filtered caused the problem. 1997 */ 1998 if ( isset( $optimization_attrs['fetchpriority'] ) && 'high' === $optimization_attrs['fetchpriority'] && 1999 ( isset( $optimization_attrs['loading'] ) ? $optimization_attrs['loading'] : false ) !== $filtered_loading_attr && 2000 'lazy' === $filtered_loading_attr 2001 ) { 2002 _doing_it_wrong( 2003 __FUNCTION__, 2004 __( 'An image should not be lazy-loaded and marked as high priority at the same time.' ), 2005 '6.3.0' 2006 ); 2007 } 2008 2009 // The filtered value will still be respected. 2010 $optimization_attrs['loading'] = $filtered_loading_attr; 2011 } 2012 2013 if ( ! empty( $optimization_attrs['loading'] ) ) { 2014 $image = str_replace( '<img', '<img loading="' . esc_attr( $optimization_attrs['loading'] ) . '"', $image ); 2015 } 2016 } 2017 2018 if ( empty( $fetchpriority_val ) && ! empty( $optimization_attrs['fetchpriority'] ) ) { 2019 $image = str_replace( '<img', '<img fetchpriority="' . esc_attr( $optimization_attrs['fetchpriority'] ) . '"', $image ); 1956 2020 } 1957 2021 … … 2104 2168 // Get loading attribute value to use. This must occur before the conditional check below so that even iframes that 2105 2169 // are ineligible for being lazy-loaded are considered. 2106 $value = wp_get_loading_attr_default( $context ); 2170 $optimization_attrs = wp_get_loading_optimization_attributes( 2171 'iframe', 2172 array( 2173 /* 2174 * The concrete values for width and height are not important here for now 2175 * since fetchpriority is not yet supported for iframes. 2176 * TODO: Use WP_HTML_Tag_Processor to extract actual values once support is 2177 * added. 2178 */ 2179 'width' => str_contains( $iframe, ' width="' ) ? 100 : null, 2180 'height' => str_contains( $iframe, ' height="' ) ? 100 : null, 2181 // This function is never called when a 'loading' attribute is already present. 2182 'loading' => null, 2183 ), 2184 $context 2185 ); 2107 2186 2108 2187 // Iframes should have source and dimension attributes for the `loading` attribute to be added. … … 2110 2189 return $iframe; 2111 2190 } 2191 2192 $value = isset( $optimization_attrs['loading'] ) ? $optimization_attrs['loading'] : false; 2112 2193 2113 2194 /** … … 5470 5551 5471 5552 /** 5472 * Gets the default value to use for a `loading` attribute on an element. 5473 * 5474 * This function should only be called for a tag and context if lazy-loading is generally enabled. 5475 * 5476 * The function usually returns 'lazy', but uses certain heuristics to guess whether the current element is likely to 5477 * appear above the fold, in which case it returns a boolean `false`, which will lead to the `loading` attribute being 5478 * omitted on the element. The purpose of this refinement is to avoid lazy-loading elements that are within the initial 5479 * viewport, which can have a negative performance impact. 5480 * 5481 * Under the hood, the function uses {@see wp_increase_content_media_count()} every time it is called for an element 5482 * within the main content. If the element is the very first content element, the `loading` attribute will be omitted. 5483 * This default threshold of 3 content elements to omit the `loading` attribute for can be customized using the 5484 * {@see 'wp_omit_loading_attr_threshold'} filter. 5485 * 5486 * @since 5.9.0 5553 * Gets loading optimization attributes. 5554 * 5555 * This function returns an array of attributes that should be merged into the given attributes array to optimize 5556 * loading performance. Potential attributes returned by this function are: 5557 * - `loading` attribute with a value of "lazy" 5558 * - `fetchpriority` attribute with a value of "high" 5559 * 5560 * If any of these attributes are already present in the given attributes, they will not be modified. Note that no 5561 * element should have both `loading="lazy"` and `fetchpriority="high"`, so the function will trigger a warning in case 5562 * both attributes are present with those values. 5563 * 5564 * @since 6.3.0 5487 5565 * 5488 5566 * @global WP_Query $wp_query WordPress Query object. 5489 5567 * 5490 * @param string $context Context for the element for which the `loading` attribute value is requested. 5491 * @return string|bool The default `loading` attribute value. Either 'lazy', 'eager', or a boolean `false`, to indicate 5492 * that the `loading` attribute should be skipped. 5493 */ 5494 function wp_get_loading_attr_default( $context ) { 5568 * @param string $tag_name The tag name. 5569 * @param array $attr Array of the attributes for the tag. 5570 * @param string $context Context for the element for which the loading optimization attribute is requested. 5571 * @return array Loading optimization attributes. 5572 */ 5573 function wp_get_loading_optimization_attributes( $tag_name, $attr, $context ) { 5495 5574 global $wp_query; 5496 5575 5497 // Skip lazy-loading for the overall block template, as it is handled more granularly. 5576 /* 5577 * Closure for postprocessing logic. 5578 * It is here to avoid duplicate logic in many places below, without having 5579 * to introduce a very specific private global function. 5580 */ 5581 $postprocess = static function( $loading_attributes, $with_fetchpriority = false ) use ( $tag_name, $attr, $context ) { 5582 // Potentially add `fetchpriority="high"`. 5583 if ( $with_fetchpriority ) { 5584 $loading_attributes = wp_maybe_add_fetchpriority_high_attr( $loading_attributes, $tag_name, $attr ); 5585 } 5586 // Potentially strip `loading="lazy"` if the feature is disabled. 5587 if ( isset( $loading_attributes['loading'] ) && ! wp_lazy_loading_enabled( $tag_name, $context ) ) { 5588 unset( $loading_attributes['loading'] ); 5589 } 5590 return $loading_attributes; 5591 }; 5592 5593 $loading_attrs = array(); 5594 5595 /* 5596 * Skip lazy-loading for the overall block template, as it is handled more granularly. 5597 * The skip is also applicable for `fetchpriority`. 5598 */ 5498 5599 if ( 'template' === $context ) { 5499 return false; 5500 } 5501 5502 // Do not lazy-load images in the header block template part, as they are likely above the fold. 5503 // For classic themes, this is handled in the condition below using the 'get_header' action. 5600 return $loading_attrs; 5601 } 5602 5603 // For now this function only supports images and iframes. 5604 if ( 'img' !== $tag_name && 'iframe' !== $tag_name ) { 5605 return $loading_attrs; 5606 } 5607 5608 // For any resources, width and height must be provided, to avoid layout shifts. 5609 if ( ! isset( $attr['width'], $attr['height'] ) ) { 5610 return $loading_attrs; 5611 } 5612 5613 if ( isset( $attr['loading'] ) ) { 5614 /* 5615 * While any `loading` value could be set in `$loading_attrs`, for 5616 * consistency we only do it for `loading="lazy"` since that is the 5617 * only possible value that WordPress core would apply on its own. 5618 */ 5619 if ( 'lazy' === $attr['loading'] ) { 5620 $loading_attrs['loading'] = 'lazy'; 5621 if ( isset( $attr['fetchpriority'] ) && 'high' === $attr['fetchpriority'] ) { 5622 _doing_it_wrong( 5623 __FUNCTION__, 5624 __( 'An image should not be lazy-loaded and marked as high priority at the same time.' ), 5625 '6.3.0' 5626 ); 5627 } 5628 } 5629 5630 return $postprocess( $loading_attrs, true ); 5631 } 5632 5633 // An image with `fetchpriority="high"` cannot be assigned `loading="lazy"` at the same time. 5634 if ( isset( $attr['fetchpriority'] ) && 'high' === $attr['fetchpriority'] ) { 5635 return $postprocess( $loading_attrs, true ); 5636 } 5637 5638 /* 5639 * Do not lazy-load images in the header block template part, as they are likely above the fold. 5640 * For classic themes, this is handled in the condition below using the 'get_header' action. 5641 */ 5504 5642 $header_area = WP_TEMPLATE_PART_AREA_HEADER; 5505 5643 if ( "template_part_{$header_area}" === $context ) { 5506 return false;5644 return $postprocess( $loading_attrs, true ); 5507 5645 } 5508 5646 5509 5647 // Special handling for programmatically created image tags. 5510 if ( ( 'the_post_thumbnail' === $context || 'wp_get_attachment_image' === $context )) {5648 if ( 'the_post_thumbnail' === $context || 'wp_get_attachment_image' === $context ) { 5511 5649 /* 5512 5650 * Skip programmatically created images within post content as they need to be handled together with the other … … 5516 5654 */ 5517 5655 if ( doing_filter( 'the_content' ) ) { 5518 return false;5656 return $postprocess( $loading_attrs, true ); 5519 5657 } 5520 5658 … … 5530 5668 && did_action( 'get_header' ) && ! did_action( 'get_footer' ) 5531 5669 ) { 5532 return false;5670 return $postprocess( $loading_attrs, true ); 5533 5671 } 5534 5672 } … … 5541 5679 // Only elements within the main query loop have special handling. 5542 5680 if ( is_admin() || ! in_the_loop() || ! is_main_query() ) { 5543 return 'lazy'; 5681 $loading_attrs['loading'] = 'lazy'; 5682 return $postprocess( $loading_attrs, false ); 5544 5683 } 5545 5684 … … 5547 5686 $content_media_count = wp_increase_content_media_count(); 5548 5687 5549 // If the count so far is below the threshold, return `false` so that the`loading` attribute is omitted.5688 // If the count so far is below the threshold, `loading` attribute is omitted. 5550 5689 if ( $content_media_count <= wp_omit_loading_attr_threshold() ) { 5551 return false; 5552 } 5553 5554 // For elements after the threshold, lazy-load them as usual. 5555 return 'lazy'; 5690 // The first largest image will still get `fetchpriority='high'`. 5691 return $postprocess( $loading_attrs, true ); 5692 } 5556 5693 } 5557 5694 5558 5695 // Lazy-load by default for any unknown context. 5559 return 'lazy'; 5696 $loading_attrs['loading'] = 'lazy'; 5697 return $postprocess( $loading_attrs, false ); 5560 5698 } 5561 5699 … … 5610 5748 return $content_media_count; 5611 5749 } 5750 5751 /** 5752 * Determines whether to add `fetchpriority='high'` to loading attributes. 5753 * 5754 * @since 6.3.0 5755 * @access private 5756 * 5757 * @param array $loading_attrs Array of the loading optimization attributes for the element. 5758 * @param string $tag_name The tag name. 5759 * @param array $attr Array of the attributes for the element. 5760 * @return array Updated loading optimization attributes for the element. 5761 */ 5762 function wp_maybe_add_fetchpriority_high_attr( $loading_attrs, $tag_name, $attr ) { 5763 // For now, adding `fetchpriority="high"` is only supported for images. 5764 if ( 'img' !== $tag_name ) { 5765 return $loading_attrs; 5766 } 5767 5768 if ( isset( $attr['fetchpriority'] ) ) { 5769 /* 5770 * While any `fetchpriority` value could be set in `$loading_attrs`, 5771 * for consistency we only do it for `fetchpriority="high"` since that 5772 * is the only possible value that WordPress core would apply on its 5773 * own. 5774 */ 5775 if ( 'high' === $attr['fetchpriority'] ) { 5776 $loading_attrs['fetchpriority'] = 'high'; 5777 wp_high_priority_element_flag( false ); 5778 } 5779 return $loading_attrs; 5780 } 5781 5782 // Lazy-loading and `fetchpriority="high"` are mutually exclusive. 5783 if ( isset( $loading_attrs['loading'] ) && 'lazy' === $loading_attrs['loading'] ) { 5784 return $loading_attrs; 5785 } 5786 5787 if ( ! wp_high_priority_element_flag() ) { 5788 return $loading_attrs; 5789 } 5790 5791 /** 5792 * Filters the minimum square-pixels threshold for an image to be eligible as the high-priority image. 5793 * 5794 * @since 6.3.0 5795 * 5796 * @param int $threshold Minimum square-pixels threshold. Default 50000. 5797 */ 5798 $wp_min_priority_img_pixels = apply_filters( 'wp_min_priority_img_pixels', 50000 ); 5799 if ( $wp_min_priority_img_pixels <= $attr['width'] * $attr['height'] ) { 5800 $loading_attrs['fetchpriority'] = 'high'; 5801 wp_high_priority_element_flag( false ); 5802 } 5803 return $loading_attrs; 5804 } 5805 5806 /** 5807 * Accesses a flag that indicates if an element is a possible candidate for `fetchpriority='high'`. 5808 * 5809 * @since 6.3.0 5810 * @access private 5811 * 5812 * @param bool $value Optional. Used to change the static variable. Default null. 5813 * @return bool Returns true if high-priority element was marked already, otherwise false. 5814 */ 5815 function wp_high_priority_element_flag( $value = null ) { 5816 static $high_priority_element = true; 5817 5818 if ( is_bool( $value ) ) { 5819 $high_priority_element = $value; 5820 } 5821 return $high_priority_element; 5822 }
Note: See TracChangeset
for help on using the changeset viewer.