mirror of
git://develop.git.wordpress.org/
synced 2025-02-24 08:33:35 +01:00
Media: Optimize images created in shortcodes.
This fixes an issue where images dynamically created during shortcode rendering (e.g., shortcode image galleries), were not getting image optimizations like `loading="lazy"` or `fetchpriority="hight"` applied. Note that even after this commit, shortcodes are processed after the main content images, which can affect the order in which optimizations are applied in content areas. Follow-up to [56037]. Props spacedmonkey, flixos90, thekt12, swissspidy, joemcgill. Fixes #58681. git-svn-id: https://develop.svn.wordpress.org/trunk@56214 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
parent
baec3f39c1
commit
ed174730d3
@ -5725,9 +5725,10 @@ function wp_get_loading_optimization_attributes( $tag_name, $attr, $context ) {
|
||||
|
||||
/*
|
||||
* The first elements in 'the_content' or 'the_post_thumbnail' should not be lazy-loaded,
|
||||
* as they are likely above the fold.
|
||||
* as they are likely above the fold. Shortcodes are processed after content images, so if
|
||||
* thresholds haven't already been met, apply the same logic to those as well.
|
||||
*/
|
||||
if ( 'the_content' === $context || 'the_post_thumbnail' === $context ) {
|
||||
if ( 'the_content' === $context || 'the_post_thumbnail' === $context || 'do_shortcode' === $context ) {
|
||||
// Only elements within the main query loop have special handling.
|
||||
if ( is_admin() || ! in_the_loop() || ! is_main_query() ) {
|
||||
$loading_attrs['loading'] = 'lazy';
|
||||
|
@ -221,6 +221,14 @@ function do_shortcode( $content, $ignore_html = false ) {
|
||||
return $content;
|
||||
}
|
||||
|
||||
// Ensure this context is only added once if shortcodes are nested.
|
||||
$has_filter = has_filter( 'wp_get_attachment_image_context', '_filter_do_shortcode_context' );
|
||||
$filter_added = false;
|
||||
|
||||
if ( ! $has_filter ) {
|
||||
$filter_added = add_filter( 'wp_get_attachment_image_context', '_filter_do_shortcode_context' );
|
||||
}
|
||||
|
||||
$content = do_shortcodes_in_html_tags( $content, $ignore_html, $tagnames );
|
||||
|
||||
$pattern = get_shortcode_regex( $tagnames );
|
||||
@ -229,9 +237,29 @@ function do_shortcode( $content, $ignore_html = false ) {
|
||||
// Always restore square braces so we don't break things like <!--[if IE ]>.
|
||||
$content = unescape_invalid_shortcodes( $content );
|
||||
|
||||
// Only remove the filter if it was added in this scope.
|
||||
if ( $filter_added ) {
|
||||
remove_filter( 'wp_get_attachment_image_context', '_filter_do_shortcode_context' );
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the `wp_get_attachment_image_context` hook during shortcode rendering.
|
||||
*
|
||||
* When wp_get_attachment_image() is called during shortcode rendering, we need to make clear
|
||||
* that the context is a shortcode and not part of the theme's template rendering logic.
|
||||
*
|
||||
* @since 6.3.0
|
||||
* @access private
|
||||
*
|
||||
* @return string The filtered context value for wp_get_attachment_images when doing shortcodes.
|
||||
*/
|
||||
function _filter_do_shortcode_context() {
|
||||
return 'do_shortcode';
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the shortcode regular expression for searching.
|
||||
*
|
||||
|
@ -78,8 +78,8 @@ CAP;
|
||||
/**
|
||||
* Ensures that the static content media count, fetchpriority element flag and related filter are reset between tests.
|
||||
*/
|
||||
public function set_up() {
|
||||
parent::set_up();
|
||||
public function tear_down() {
|
||||
parent::tear_down();
|
||||
|
||||
$this->reset_content_media_count();
|
||||
$this->reset_omit_loading_attr_filter();
|
||||
@ -5005,6 +5005,122 @@ EOF;
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 58681
|
||||
*
|
||||
* @dataProvider data_wp_get_loading_optimization_attributes_in_shortcodes
|
||||
*/
|
||||
public function test_wp_get_loading_optimization_attributes_in_shortcodes( $setup, $expected, $message ) {
|
||||
$attr = $this->get_width_height_for_high_priority();
|
||||
$setup();
|
||||
|
||||
// The first image processed in a shortcode should have fetchpriority set to high.
|
||||
$this->assertSame(
|
||||
$expected,
|
||||
wp_get_loading_optimization_attributes( 'img', $attr, 'do_shortcode' ),
|
||||
$message
|
||||
);
|
||||
}
|
||||
|
||||
public function data_wp_get_loading_optimization_attributes_in_shortcodes() {
|
||||
return array(
|
||||
'main_shortcode_image_should_have_fetchpriority_high' => array(
|
||||
'setup' => function () {
|
||||
global $wp_query;
|
||||
|
||||
// Set WP_Query to be in the loop and the main query.
|
||||
$wp_query->in_the_loop = true;
|
||||
$this->set_main_query( $wp_query );
|
||||
},
|
||||
'expected' => array(
|
||||
'fetchpriority' => 'high',
|
||||
),
|
||||
'message' => 'Fetch priority not applied to during shortcode rendering.',
|
||||
),
|
||||
'main_shortcode_image_after_threshold_is_loading_lazy' => array(
|
||||
'setup' => function () {
|
||||
global $wp_query;
|
||||
|
||||
// Set WP_Query to be in the loop and the main query.
|
||||
$wp_query->in_the_loop = true;
|
||||
$this->set_main_query( $wp_query );
|
||||
|
||||
// Set internal flags so lazy should be applied.
|
||||
wp_high_priority_element_flag( false );
|
||||
wp_increase_content_media_count( 3 );
|
||||
},
|
||||
'expected' => array(
|
||||
'loading' => 'lazy',
|
||||
),
|
||||
'message' => 'Lazy-loading not applied to during shortcode rendering.',
|
||||
),
|
||||
'shortcode_image_outside_of_the_loop_are_loaded_lazy' => array(
|
||||
'setup' => function () {
|
||||
// Avoid setting up the WP_Query object for the loop.
|
||||
return;
|
||||
},
|
||||
'expected' => array(
|
||||
'loading' => 'lazy',
|
||||
),
|
||||
'message' => 'Lazy-loading not applied to shortcodes outside the loop.',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 58681
|
||||
*/
|
||||
public function test_content_rendering_with_shortcodes() {
|
||||
// The gallery shortcode will dynamically create image markup that should be optimized.
|
||||
$content = "[gallery ids='" . self::$large_id . "' size='large']";
|
||||
$actual = apply_filters( 'the_content', $content );
|
||||
|
||||
$this->assertStringContainsString(
|
||||
// Since the main query and loop isn't set, this should be lazily loaded.
|
||||
'loading="lazy"',
|
||||
$actual,
|
||||
'Could not confirm shortcodes get optimizations applied.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 58681
|
||||
*/
|
||||
public function test_content_rendering_with_shortcodes_nested() {
|
||||
global $wp_query;
|
||||
|
||||
// Set WP_Query to be in the loop and the main query.
|
||||
$wp_query->in_the_loop = true;
|
||||
$this->set_main_query( $wp_query );
|
||||
|
||||
add_shortcode(
|
||||
'div',
|
||||
function ( $atts, $content = null ) {
|
||||
$parsed_atts = shortcode_atts(
|
||||
array(
|
||||
'class' => '',
|
||||
),
|
||||
$atts
|
||||
);
|
||||
|
||||
$class = ! empty( $parsed_atts['class'] ) ? sprintf( ' class="%s"', $parsed_atts['class'] ) : null;
|
||||
|
||||
return sprintf( '<div %s>%s</div>', $class, do_shortcode( $content ) );
|
||||
}
|
||||
);
|
||||
|
||||
// The gallery shortcode will dynamically create image markup that should be optimized.
|
||||
$content = "[div][gallery ids='" . self::$large_id . "' size='large'][div]";
|
||||
$actual = apply_filters( 'the_content', $content );
|
||||
|
||||
$this->assertStringContainsString(
|
||||
// Since this is in the loop, it should have a high fetchpriority.
|
||||
'fetchpriority="high"',
|
||||
$actual,
|
||||
'Could not confirm shortcodes get optimizations applied.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 58235
|
||||
*
|
||||
|
Loading…
x
Reference in New Issue
Block a user