Make WordPress Core

Changeset 55821


Ignore:
Timestamp:
05/17/2023 06:29:41 PM (19 months 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.