Make WordPress Core

Changeset 55821


Ignore:
Timestamp:
05/17/2023 06:29:41 PM (3 years ago)
Author:
flixos90
Message:

Media: Introduce wp_get_attachment_image_context filter.

Since WordPress 5.9, a "context" value of "wp_get_attachment_image" has been used in the wp_get_attachment_image() function to provide context to underlying functions where that is relevant, e.g. wp_get_loading_attr_default(). Since that value used to be not customizable, it required a workaround in get_the_post_thumbnail() to avoid calling those functions in wp_get_attachment_image(), which resulted in unnecessary complexity and was prone to errors.

This changeset introduces a wp_get_attachment_image_context filter and leverages it with private filter callback functions that are leveraged by default when get_the_post_thumbnail() is called. This avoids the need for the previous workaround and furthermore provides flexibility for other callers of wp_get_attachment_image() to provide their own contexts.

Props flixos90, costdev, thekt12, westonruter, spacedmonkey.
Fixes #58212.

Location:
trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/default-filters.php

    r55695 r55821  
    445445add_action( 'delete_post', '_wp_delete_customize_changeset_dependent_auto_drafts' );
    446446
    447 // Post Thumbnail CSS class filtering.
     447// Post Thumbnail specific image filtering.
    448448add_action( 'begin_fetch_post_thumbnail_html', '_wp_post_thumbnail_class_filter_add' );
    449449add_action( 'end_fetch_post_thumbnail_html', '_wp_post_thumbnail_class_filter_remove' );
     450add_action( 'begin_fetch_post_thumbnail_html', '_wp_post_thumbnail_context_filter_add' );
     451add_action( 'end_fetch_post_thumbnail_html', '_wp_post_thumbnail_context_filter_remove' );
    450452
    451453// Redirect old slugs.
  • trunk/src/wp-includes/media.php

    r55816 r55821  
    10511051                );
    10521052
     1053                /**
     1054                 * Filters the context in which wp_get_attachment_image() is used.
     1055                 *
     1056                 * @since 6.3.0
     1057                 *
     1058                 * @param string $context The context. Default 'wp_get_attachment_image'.
     1059                 */
     1060                $context = apply_filters( 'wp_get_attachment_image_context', 'wp_get_attachment_image' );
     1061
    10531062                // Add `loading` attribute.
    1054                 if ( wp_lazy_loading_enabled( 'img', 'wp_get_attachment_image' ) ) {
    1055                         $default_attr['loading'] = wp_get_loading_attr_default( 'wp_get_attachment_image' );
     1063                if ( wp_lazy_loading_enabled( 'img', $context ) ) {
     1064                        $default_attr['loading'] = wp_get_loading_attr_default( $context );
    10561065                }
    10571066
     
    21692178function _wp_post_thumbnail_class_filter_remove( $attr ) {
    21702179        remove_filter( 'wp_get_attachment_image_attributes', '_wp_post_thumbnail_class_filter' );
     2180}
     2181
     2182/**
     2183 * Overrides the context used in {@see wp_get_attachment_image()}. Internal use only.
     2184 *
     2185 * Uses the {@see 'begin_fetch_post_thumbnail_html'} and {@see 'end_fetch_post_thumbnail_html'}
     2186 * action hooks to dynamically add/remove itself so as to only filter post thumbnails.
     2187 *
     2188 * @ignore
     2189 * @since 6.3.0
     2190 * @access private
     2191 *
     2192 * @param string $context The context for rendering an attachment image.
     2193 * @return string Modified context set to 'the_post_thumbnail'.
     2194 */
     2195function _wp_post_thumbnail_context_filter( $context ) {
     2196        return 'the_post_thumbnail';
     2197}
     2198
     2199/**
     2200 * Adds the '_wp_post_thumbnail_context_filter' callback to the 'wp_get_attachment_image_context'
     2201 * filter hook. Internal use only.
     2202 *
     2203 * @ignore
     2204 * @since 6.3.0
     2205 * @access private
     2206 */
     2207function _wp_post_thumbnail_context_filter_add() {
     2208        add_filter( 'wp_get_attachment_image_context', '_wp_post_thumbnail_context_filter' );
     2209}
     2210
     2211/**
     2212 * Removes the '_wp_post_thumbnail_context_filter' callback from the 'wp_get_attachment_image_context'
     2213 * filter hook. Internal use only.
     2214 *
     2215 * @ignore
     2216 * @since 6.3.0
     2217 * @access private
     2218 */
     2219function _wp_post_thumbnail_context_filter_remove() {
     2220        remove_filter( 'wp_get_attachment_image_context', '_wp_post_thumbnail_context_filter' );
    21712221}
    21722222
  • trunk/src/wp-includes/post-thumbnail-template.php

    r55093 r55821  
    187187                }
    188188
    189                 // Add `loading` attribute.
    190                 if ( wp_lazy_loading_enabled( 'img', 'the_post_thumbnail' ) ) {
    191                         // Get the 'loading' attribute value to use as default, taking precedence over the default from
    192                         // `wp_get_attachment_image()`.
    193                         $loading = wp_get_loading_attr_default( 'the_post_thumbnail' );
    194 
    195                         // Add the default to the given attributes unless they already include a 'loading' directive.
    196                         if ( empty( $attr ) ) {
    197                                 $attr = array( 'loading' => $loading );
    198                         } elseif ( is_array( $attr ) && ! array_key_exists( 'loading', $attr ) ) {
    199                                 $attr['loading'] = $loading;
    200                         } elseif ( is_string( $attr ) && ! preg_match( '/(^|&)loading=/', $attr ) ) {
    201                                 $attr .= '&loading=' . $loading;
    202                         }
    203                 }
    204 
    205189                $html = wp_get_attachment_image( $post_thumbnail_id, $size, false, $attr );
    206190
  • trunk/tests/phpunit/tests/media.php

    r55816 r55821  
    39653965
    39663966        /**
     3967         * Tests that `wp_get_attachment_image()` uses the correct default context.
     3968         *
     3969         * @ticket 58212
     3970         *
     3971         * @covers ::wp_get_attachment_image()
     3972         */
     3973        public function test_wp_get_attachment_image_context_filter_default() {
     3974                $last_context = '';
     3975                $this->track_last_attachment_image_context( $last_context );
     3976
     3977                wp_get_attachment_image( self::$large_id );
     3978                $this->assertSame( 'wp_get_attachment_image', $last_context );
     3979        }
     3980
     3981        /**
     3982         * Tests that `wp_get_attachment_image()` allows overriding the context via filter.
     3983         *
     3984         * @ticket 58212
     3985         *
     3986         * @covers ::wp_get_attachment_image()
     3987         */
     3988        public function test_wp_get_attachment_image_context_filter_value_is_passed_correctly() {
     3989                $last_context = '';
     3990                $this->track_last_attachment_image_context( $last_context );
     3991
     3992                // Add a filter that modifies the context.
     3993                add_filter(
     3994                        'wp_get_attachment_image_context',
     3995                        static function() {
     3996                                return 'my_custom_context';
     3997                        }
     3998                );
     3999
     4000                wp_get_attachment_image( self::$large_id );
     4001                $this->assertSame( 'my_custom_context', $last_context );
     4002        }
     4003
     4004        /**
     4005         * Helper method to keep track of the last context returned by the 'wp_get_attachment_image_context' filter.
     4006         *
     4007         * The method parameter is passed by reference and therefore will always contain the last context value.
     4008         *
     4009         * @param mixed $last_context Variable to track last context. Passed by reference.
     4010         */
     4011        private function track_last_attachment_image_context( &$last_context ) {
     4012                add_filter(
     4013                        'wp_get_attachment_image_context',
     4014                        static function( $context ) use ( &$last_context ) {
     4015                                $last_context = $context;
     4016                                return $context;
     4017                        },
     4018                        11
     4019                );
     4020        }
     4021
     4022        /**
    39674023         * Add threshold to create a `-scaled` output image for testing.
    39684024         */
  • trunk/tests/phpunit/tests/post/thumbnails.php

    r55093 r55821  
    451451        }
    452452
     453        /**
     454         * Tests that `_wp_post_thumbnail_context_filter()` returns 'the_post_thumbnail'.
     455         *
     456         * @ticket 58212
     457         *
     458         * @covers::_wp_post_thumbnail_context_filter
     459         */
     460        public function test_wp_post_thumbnail_context_filter_should_return_the_post_thumbnail() {
     461                $this->assertSame( 'the_post_thumbnail', _wp_post_thumbnail_context_filter( 'wp_get_attachment_image' ) );
     462        }
     463
     464        /**
     465         * Tests that `::_wp_post_thumbnail_context_filter_add` adds a filter to override the context
     466         * used in `wp_get_attachment_image()`.
     467         *
     468         * @ticket 58212
     469         *
     470         * @covers ::_wp_post_thumbnail_context_filter_add
     471         */
     472        public function test_wp_post_thumbnail_context_filter_add_should_add_the_filter() {
     473                $last_context = '';
     474                $this->track_last_attachment_image_context( $last_context );
     475
     476                _wp_post_thumbnail_context_filter_add();
     477                wp_get_attachment_image( self::$attachment_id );
     478
     479                $this->assertSame( 'the_post_thumbnail', $last_context );
     480        }
     481
     482        /**
     483         * Tests that `_wp_post_thumbnail_context_filter_remove()` removes a filter to override the context
     484         * used in `wp_get_attachment_image()`.
     485         *
     486         * @ticket 58212
     487         *
     488         * @covers ::_wp_post_thumbnail_context_filter_remove
     489         */
     490        public function test_wp_post_thumbnail_context_filter_remove_should_remove_the_filter() {
     491                $last_context = '';
     492                $this->track_last_attachment_image_context( $last_context );
     493
     494                _wp_post_thumbnail_context_filter_add();
     495                wp_get_attachment_image( self::$attachment_id );
     496
     497                // Verify that the filter has been added before testing that it has been removed.
     498                $this->assertSame(
     499                        'the_post_thumbnail',
     500                        $last_context,
     501                        'The filter was not added.'
     502                );
     503
     504                _wp_post_thumbnail_context_filter_remove();
     505
     506                // The context should no longer be modified by the filter.
     507                wp_get_attachment_image( self::$attachment_id );
     508
     509                $this->assertSame(
     510                        'wp_get_attachment_image',
     511                        $last_context,
     512                        'The filter was not removed.'
     513                );
     514        }
     515
     516        /**
     517         * Tests that `get_the_post_thumbnail()` uses the 'the_post_thumbnail' context.
     518         *
     519         * @ticket 58212
     520         *
     521         * @covers ::get_the_post_thumbnail
     522         */
     523        public function test_get_the_post_thumbnail_should_use_the_post_thumbnail_context() {
     524                $last_context = '';
     525                $this->track_last_attachment_image_context( $last_context );
     526
     527                set_post_thumbnail( self::$post, self::$attachment_id );
     528                get_the_post_thumbnail( self::$post );
     529
     530                $this->assertSame( 'the_post_thumbnail', $last_context );
     531        }
     532
     533        /**
     534         * Tests that `get_the_post_thumbnail()` restores the context afterwards.
     535         *
     536         * @ticket 58212
     537         *
     538         * @covers ::get_the_post_thumbnail
     539         */
     540        public function test_get_the_post_thumbnail_should_remove_the_post_thumbnail_context_afterwards() {
     541                $last_context = '';
     542                $this->track_last_attachment_image_context( $last_context );
     543
     544                set_post_thumbnail( self::$post, self::$attachment_id );
     545                get_the_post_thumbnail( self::$post );
     546
     547                // Verify that the context was overridden before testing that it has been restored.
     548                $this->assertSame(
     549                        'the_post_thumbnail',
     550                        $last_context,
     551                        'The context was not overridden.'
     552                );
     553
     554                // The context should no longer be overridden.
     555                wp_get_attachment_image( self::$attachment_id );
     556
     557                $this->assertSame(
     558                        'wp_get_attachment_image',
     559                        $last_context,
     560                        'The context was not restored.'
     561                );
     562        }
     563
     564        /**
     565         * Helper method to keep track of the last context returned by the 'wp_get_attachment_image_context' filter.
     566         *
     567         * The method parameter is passed by reference and therefore will always contain the last context value.
     568         *
     569         * @param mixed $last_context Variable to track last context. Passed by reference.
     570         */
     571        private function track_last_attachment_image_context( &$last_context ) {
     572                add_filter(
     573                        'wp_get_attachment_image_context',
     574                        static function( $context ) use ( &$last_context ) {
     575                                $last_context = $context;
     576                                return $context;
     577                        },
     578                        11
     579                );
     580        }
     581
    453582        public function filter_post_thumbnail_size( $size, $post_id ) {
    454583                if ( is_array( $this->current_size_filter_data ) && isset( $this->current_size_filter_data[ $post_id ] ) ) {
Note: See TracChangeset for help on using the changeset viewer.