From 22b71b755d5800d391873d7d955408f66d3fa29f Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Thu, 21 Sep 2023 16:35:30 +0000 Subject: [PATCH] Media: Introduce filters to customize the results from `wp_get_loading_optimization_attributes()`. This changeset introduces two filters that allow customizing the loading optimization attributes array returned from `wp_get_loading_optimization_attributes()` for individual HTML tags: * The `wp_get_loading_optimization_attributes` filter can be used to modify the results from the WordPress core logic. * The `pre_wp_get_loading_optimization_attributes` filter can be used to use entirely custom logic and effectively short-circuit the core function. Props pereirinha, mukesh27, spacedmonkey, joemcgill. Fixes #58893. git-svn-id: https://develop.svn.wordpress.org/trunk@56651 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-includes/media.php | 43 ++++++++++++-- tests/phpunit/tests/media.php | 103 ++++++++++++++++++++++++++++++++++ 2 files changed, 141 insertions(+), 5 deletions(-) diff --git a/src/wp-includes/media.php b/src/wp-includes/media.php index 335e415798..56624bdc6b 100644 --- a/src/wp-includes/media.php +++ b/src/wp-includes/media.php @@ -5625,6 +5625,25 @@ function wp_get_webp_info( $filename ) { function wp_get_loading_optimization_attributes( $tag_name, $attr, $context ) { global $wp_query; + /** + * Filters whether to short-circuit loading optimization attributes. + * + * Returning an array from the filter will effectively short-circuit the loading of optimization attributes, + * returning that value instead. + * + * @since 6.4.0 + * + * @param array|false $loading_attrs False by default, or array of loading optimization attributes to short-circuit. + * @param string $tag_name The tag name. + * @param array $attr Array of the attributes for the tag. + * @param string $context Context for the element for which the loading optimization attribute is requested. + */ + $loading_attrs = apply_filters( 'pre_wp_get_loading_optimization_attributes', false, $tag_name, $attr, $context ); + + if ( is_array( $loading_attrs ) ) { + return $loading_attrs; + } + $loading_attrs = array(); /* @@ -5632,17 +5651,20 @@ function wp_get_loading_optimization_attributes( $tag_name, $attr, $context ) { * The skip is also applicable for `fetchpriority`. */ if ( 'template' === $context ) { - return $loading_attrs; + /** This filter is documented in wp-includes/media.php */ + return apply_filters( 'wp_get_loading_optimization_attributes', $loading_attrs, $tag_name, $attr, $context ); } // For now this function only supports images and iframes. if ( 'img' !== $tag_name && 'iframe' !== $tag_name ) { - return $loading_attrs; + /** This filter is documented in wp-includes/media.php */ + return apply_filters( 'wp_get_loading_optimization_attributes', $loading_attrs, $tag_name, $attr, $context ); } // For any resources, width and height must be provided, to avoid layout shifts. if ( ! isset( $attr['width'], $attr['height'] ) ) { - return $loading_attrs; + /** This filter is documented in wp-includes/media.php */ + return apply_filters( 'wp_get_loading_optimization_attributes', $loading_attrs, $tag_name, $attr, $context ); } /* @@ -5654,7 +5676,8 @@ function wp_get_loading_optimization_attributes( $tag_name, $attr, $context ) { */ // TODO: Handle shortcode images together with the content (see https://core.trac.wordpress.org/ticket/58853). if ( 'the_content' !== $context && 'do_shortcode' !== $context && doing_filter( 'the_content' ) ) { - return $loading_attrs; + /** This filter is documented in wp-includes/media.php */ + return apply_filters( 'wp_get_loading_optimization_attributes', $loading_attrs, $tag_name, $attr, $context ); } /* @@ -5789,7 +5812,17 @@ function wp_get_loading_optimization_attributes( $tag_name, $attr, $context ) { } } - return $loading_attrs; + /** + * Filters the loading optimization attributes. + * + * @since 6.4.0 + * + * @param array $loading_attrs The loading optimization attributes. + * @param string $tag_name The tag name. + * @param array $attr Array of the attributes for the tag. + * @param string $context Context for the element for which the loading optimization attribute is requested. + */ + return apply_filters( 'wp_get_loading_optimization_attributes', $loading_attrs, $tag_name, $attr, $context ); } /** diff --git a/tests/phpunit/tests/media.php b/tests/phpunit/tests/media.php index 1ef1b93d4e..8ee5536b6d 100644 --- a/tests/phpunit/tests/media.php +++ b/tests/phpunit/tests/media.php @@ -5440,6 +5440,109 @@ EOF; $this->assertSame( 1, wp_increase_content_media_count( 0 ) ); } + /** + * Tests for pre_wp_get_loading_optimization_attributes filter. + * + * @ticket 58893 + */ + public function test_pre_wp_get_loading_optimization_attributes_filter() { + add_filter( + 'pre_wp_get_loading_optimization_attributes', + static function ( $loading_attrs ) { + if ( false === $loading_attrs ) { + // Initialize as an empty array. + $loading_attrs = array(); + } + $loading_attrs['fetchpriority'] = 'high'; + + return $loading_attrs; + }, + 10, + 1 + ); + + $attr = $this->get_width_height_for_high_priority(); + + $this->assertSame( + array( 'fetchpriority' => 'high' ), + wp_get_loading_optimization_attributes( 'img', $attr, 'the_content' ), + 'The filter did not return early fetchpriority attribute' + ); + + // Clean up the filter. + add_filter( 'pre_wp_get_loading_optimization_attributes', '__return_false' ); + + $this->assertSameSets( + array( 'loading' => 'lazy' ), + wp_get_loading_optimization_attributes( 'img', $attr, 'the_content' ), + 'The filter did not return the default attributes.' + ); + + // Return no loading attributes. + add_filter( 'pre_wp_get_loading_optimization_attributes', '__return_empty_array' ); + + $this->assertSameSets( + array(), + wp_get_loading_optimization_attributes( 'img', $attr, 'the_content' ), + 'The filter did not clean up all attributes.' + ); + + // Modify the loading attributes with any custom attributes. + add_filter( + 'pre_wp_get_loading_optimization_attributes', + static function ( $loading_attrs ) { + if ( false === $loading_attrs ) { + // Initialize as an empty array. + $loading_attrs = array(); + } + $loading_attrs['custom_attr'] = 'custom_value'; + + return $loading_attrs; + }, + 10, + 1 + ); + + $this->assertSameSets( + array( 'custom_attr' => 'custom_value' ), + wp_get_loading_optimization_attributes( 'img', $attr, 'the_content' ), + 'The filter did not return custom attributes.' + ); + } + + /** + * Tests for wp_get_loading_optimization_attributes filter. + * + * @ticket 58893 + */ + public function test_wp_get_loading_optimization_attributes_filter() { + $attr = $this->get_width_height_for_high_priority(); + + $this->assertSameSets( + array( 'loading' => 'lazy' ), + wp_get_loading_optimization_attributes( 'img', $attr, 'the_content' ), + 'Before the filter it will not return the loading attribute.' + ); + + add_filter( + 'wp_get_loading_optimization_attributes', + static function ( $loading_attrs ) { + unset( $loading_attrs['loading'] ); + $loading_attrs['fetchpriority'] = 'high'; + + return $loading_attrs; + }, + 10, + 1 + ); + + $this->assertSameSets( + array( 'fetchpriority' => 'high' ), + wp_get_loading_optimization_attributes( 'img', $attr, 'the_content' ), + 'After the filter it will not return the fetchpriority attribute.' + ); + } + /** * Helper method to keep track of the last context returned by the 'wp_get_attachment_image_context' filter. *