WordPress Version: 6.4
/**
* Adds optimization attributes to an `img` HTML tag.
*
* @since 6.3.0
*
* @param string $image The HTML `img` tag where the attribute should be added.
* @param string $context Additional context to pass to the filters.
* @return string Converted `img` tag with optimization attributes added.
*/
function wp_img_tag_add_loading_optimization_attrs($image, $context)
{
$width = preg_match('/ width=["\']([0-9]+)["\']/', $image, $match_width) ? (int) $match_width[1] : null;
$height = preg_match('/ height=["\']([0-9]+)["\']/', $image, $match_height) ? (int) $match_height[1] : null;
$loading_val = preg_match('/ loading=["\']([A-Za-z]+)["\']/', $image, $match_loading) ? $match_loading[1] : null;
$fetchpriority_val = preg_match('/ fetchpriority=["\']([A-Za-z]+)["\']/', $image, $match_fetchpriority) ? $match_fetchpriority[1] : null;
$decoding_val = preg_match('/ decoding=["\']([A-Za-z]+)["\']/', $image, $match_decoding) ? $match_decoding[1] : null;
/*
* Get loading optimization attributes to use.
* This must occur before the conditional check below so that even images
* that are ineligible for being lazy-loaded are considered.
*/
$optimization_attrs = wp_get_loading_optimization_attributes('img', array('width' => $width, 'height' => $height, 'loading' => $loading_val, 'fetchpriority' => $fetchpriority_val, 'decoding' => $decoding_val), $context);
// Images should have source for the loading optimization attributes to be added.
if (!str_contains($image, ' src="')) {
return $image;
}
if (empty($decoding_val)) {
/**
* Filters the `decoding` attribute value to add to an image. Default `async`.
*
* Returning a falsey value will omit the attribute.
*
* @since 6.1.0
*
* @param string|false|null $value The `decoding` attribute value. Returning a falsey value
* will result in the attribute being omitted for the image.
* Otherwise, it may be: 'async', 'sync', or 'auto'. Defaults to false.
* @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.
*/
$filtered_decoding_attr = apply_filters('wp_img_tag_add_decoding_attr', isset($optimization_attrs['decoding']) ? $optimization_attrs['decoding'] : false, $image, $context);
// Validate the values after filtering.
if (isset($optimization_attrs['decoding']) && !$filtered_decoding_attr) {
// Unset `decoding` attribute if `$filtered_decoding_attr` is set to `false`.
unset($optimization_attrs['decoding']);
} elseif (in_array($filtered_decoding_attr, array('async', 'sync', 'auto'), true)) {
$optimization_attrs['decoding'] = $filtered_decoding_attr;
}
if (!empty($optimization_attrs['decoding'])) {
$image = str_replace('<img', '<img decoding="' . esc_attr($optimization_attrs['decoding']) . '"', $image);
}
}
// Images should have dimension attributes for the 'loading' and 'fetchpriority' attributes to be added.
if (!str_contains($image, ' width="') || !str_contains($image, ' height="')) {
return $image;
}
// Retained for backward compatibility.
$loading_attrs_enabled = wp_lazy_loading_enabled('img', $context);
if (empty($loading_val) && $loading_attrs_enabled) {
/**
* Filters the `loading` attribute value to add to an image. Default `lazy`.
*
* Returning `false` or an empty string will not add the attribute.
* Returning `true` will add the default value.
*
* @since 5.5.0
*
* @param string|bool $value The `loading` attribute value. Returning a falsey value will result in
* the attribute being omitted for the image.
* @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.
*/
$filtered_loading_attr = apply_filters('wp_img_tag_add_loading_attr', isset($optimization_attrs['loading']) ? $optimization_attrs['loading'] : false, $image, $context);
// Validate the values after filtering.
if (isset($optimization_attrs['loading']) && !$filtered_loading_attr) {
// Unset `loading` attributes if `$filtered_loading_attr` is set to `false`.
unset($optimization_attrs['loading']);
} elseif (in_array($filtered_loading_attr, array('lazy', 'eager'), true)) {
/*
* If the filter changed the loading attribute to "lazy" when a fetchpriority attribute
* with value "high" is already present, trigger a warning since those two attribute
* values should be mutually exclusive.
*
* The same warning is present in `wp_get_loading_optimization_attributes()`, and here it
* is only intended for the specific scenario where the above filtered caused the problem.
*/
if (isset($optimization_attrs['fetchpriority']) && 'high' === $optimization_attrs['fetchpriority'] && (isset($optimization_attrs['loading']) ? $optimization_attrs['loading'] : false) !== $filtered_loading_attr && 'lazy' === $filtered_loading_attr) {
_doing_it_wrong(__FUNCTION__, __('An image should not be lazy-loaded and marked as high priority at the same time.'), '6.3.0');
}
// The filtered value will still be respected.
$optimization_attrs['loading'] = $filtered_loading_attr;
}
if (!empty($optimization_attrs['loading'])) {
$image = str_replace('<img', '<img loading="' . esc_attr($optimization_attrs['loading']) . '"', $image);
}
}
if (empty($fetchpriority_val) && !empty($optimization_attrs['fetchpriority'])) {
$image = str_replace('<img', '<img fetchpriority="' . esc_attr($optimization_attrs['fetchpriority']) . '"', $image);
}
return $image;
}