WordPress.org

Make WordPress Core

Ticket #36982: 36982.4.diff

File 36982.4.diff, 14.7 KB (added by adamsilverstein, 10 months ago)
  • src/wp-includes/media.php

    diff --git a/src/wp-includes/media.php b/src/wp-includes/media.php
    index 088e6868c7..b2fef3c0de 100644
    a b function wp_get_attachment_image( $attachment_id, $size = 'thumbnail', $icon = f 
    10631063
    10641064                        if ( is_array( $image_meta ) ) {
    10651065                                $size_array = array( absint( $width ), absint( $height ) );
    1066                                 $srcset     = wp_calculate_image_srcset( $size_array, $src, $image_meta, $attachment_id );
    1067                                 $sizes      = wp_calculate_image_sizes( $size_array, $src, $image_meta, $attachment_id );
     1066                                $srcset     = wp_calculate_image_srcset( $size_array, $src, $image_meta, $attachment_id, $attr );
     1067                                $sizes      = wp_calculate_image_sizes( $size_array, $src, $image_meta, $attachment_id, $attr );
    10681068
    10691069                                if ( $srcset && ( $sizes || ! empty( $attr['sizes'] ) ) ) {
    10701070                                        $attr['srcset'] = $srcset;
    function _wp_get_image_size_from_meta( $size_name, $image_meta ) { 
    11931193 * Retrieves the value for an image attachment's 'srcset' attribute.
    11941194 *
    11951195 * @since 4.4.0
     1196 * @since 5.7.0 Added the '$image_attr' parameter.
    11961197 *
    11971198 * @see wp_calculate_image_srcset()
    11981199 *
    function _wp_get_image_size_from_meta( $size_name, $image_meta ) { 
    12011202 *                                    width and height values in pixels (in that order). Default 'medium'.
    12021203 * @param array        $image_meta    Optional. The image meta data as returned by 'wp_get_attachment_metadata()'.
    12031204 *                                    Default null.
     1205 * @param array        $image_attr    Optional. An array of image attributes to be passed to 'wp_calculate_image_srcset()'.
    12041206 * @return string|false A 'srcset' value string or false.
    12051207 */
    1206 function wp_get_attachment_image_srcset( $attachment_id, $size = 'medium', $image_meta = null ) {
     1208function wp_get_attachment_image_srcset( $attachment_id, $size = 'medium', $image_meta = null, $image_attr = array() ) {
    12071209        $image = wp_get_attachment_image_src( $attachment_id, $size );
    12081210
    12091211        if ( ! $image ) {
    function wp_get_attachment_image_srcset( $attachment_id, $size = 'medium', $imag 
    12201222                absint( $image[2] ),
    12211223        );
    12221224
    1223         return wp_calculate_image_srcset( $size_array, $image_src, $image_meta, $attachment_id );
     1225        return wp_calculate_image_srcset( $size_array, $image_src, $image_meta, $attachment_id, $image_attr );
    12241226}
    12251227
    12261228/**
    12271229 * A helper function to calculate the image sources to include in a 'srcset' attribute.
    12281230 *
    12291231 * @since 4.4.0
     1232 * @since 5.7.0 Added the '$image_attr' parameter.
    12301233 *
    12311234 * @param int[]  $size_array    {
    12321235 *     An array of width and height values.
    function wp_get_attachment_image_srcset( $attachment_id, $size = 'medium', $imag 
    12371240 * @param string $image_src     The 'src' of the image.
    12381241 * @param array  $image_meta    The image meta data as returned by 'wp_get_attachment_metadata()'.
    12391242 * @param int    $attachment_id Optional. The image attachment ID. Default 0.
     1243 * @param array  $image_attr    Optional. Image attributes.
     1244
    12401245 * @return string|false The 'srcset' attribute value. False on error or when only one source exists.
    12411246 */
    1242 function wp_calculate_image_srcset( $size_array, $image_src, $image_meta, $attachment_id = 0 ) {
     1247function wp_calculate_image_srcset( $size_array, $image_src, $image_meta, $attachment_id = 0, $image_attr = array() ) {
    12431248        /**
    12441249         * Let plugins pre-filter the image meta to be able to fix inconsistencies in the stored data.
    12451250         *
    function wp_calculate_image_srcset( $size_array, $image_src, $image_meta, $attac 
    12541259         * }
    12551260         * @param string $image_src     The 'src' of the image.
    12561261         * @param int    $attachment_id The image attachment ID or 0 if not supplied.
     1262         * @param string $image_attr    The image attributes.
    12571263         */
    1258         $image_meta = apply_filters( 'wp_calculate_image_srcset_meta', $image_meta, $size_array, $image_src, $attachment_id );
     1264        $image_meta = apply_filters( 'wp_calculate_image_srcset_meta', $image_meta, $size_array, $image_src, $attachment_id, $image_attr );
    12591265
    12601266        if ( empty( $image_meta['sizes'] ) || ! isset( $image_meta['file'] ) || strlen( $image_meta['file'] ) < 4 ) {
    12611267                return false;
    function wp_calculate_image_srcset( $size_array, $image_src, $image_meta, $attac 
    14131419         * @param string $image_src     The 'src' of the image.
    14141420         * @param array  $image_meta    The image meta data as returned by 'wp_get_attachment_metadata()'.
    14151421         * @param int    $attachment_id Image attachment ID or 0.
     1422         * @param array  $image_attr    Image attributes.
    14161423         */
    1417         $sources = apply_filters( 'wp_calculate_image_srcset', $sources, $size_array, $image_src, $image_meta, $attachment_id );
     1424        $sources = apply_filters( 'wp_calculate_image_srcset', $sources, $size_array, $image_src, $image_meta, $attachment_id, $image_attr );
    14181425
    14191426        // Only return a 'srcset' value if there is more than one source.
    14201427        if ( ! $src_matched || ! is_array( $sources ) || count( $sources ) < 2 ) {
    function wp_calculate_image_srcset( $size_array, $image_src, $image_meta, $attac 
    14341441 * Retrieves the value for an image attachment's 'sizes' attribute.
    14351442 *
    14361443 * @since 4.4.0
     1444 * @since 5.7.0 Added the '$image_attr' parameter.
    14371445 *
    14381446 * @see wp_calculate_image_sizes()
    14391447 *
    function wp_calculate_image_srcset( $size_array, $image_src, $image_meta, $attac 
    14421450 *                                    width and height values in pixels (in that order). Default 'medium'.
    14431451 * @param array        $image_meta    Optional. The image meta data as returned by 'wp_get_attachment_metadata()'.
    14441452 *                                    Default null.
     1453 * @param array        $image_attr    Optional. Image attributes.
    14451454 * @return string|false A valid source size value for use in a 'sizes' attribute or false.
    14461455 */
    1447 function wp_get_attachment_image_sizes( $attachment_id, $size = 'medium', $image_meta = null ) {
     1456function wp_get_attachment_image_sizes( $attachment_id, $size = 'medium', $image_meta = null, $image_attr = array() ) {
    14481457        $image = wp_get_attachment_image_src( $attachment_id, $size );
    14491458
    14501459        if ( ! $image ) {
    function wp_get_attachment_image_sizes( $attachment_id, $size = 'medium', $image 
    14611470                absint( $image[2] ),
    14621471        );
    14631472
    1464         return wp_calculate_image_sizes( $size_array, $image_src, $image_meta, $attachment_id );
     1473        return wp_calculate_image_sizes( $size_array, $image_src, $image_meta, $attachment_id, $image_attr );
    14651474}
    14661475
    14671476/**
    function wp_calculate_image_sizes( $size, $image_src = null, $image_meta = null, 
    15071516         * Filters the output of 'wp_calculate_image_sizes()'.
    15081517         *
    15091518         * @since 4.4.0
     1519         * @since 5.7.0 Added the '$image_attr' parameter.
    15101520         *
    15111521         * @param string       $sizes         A source size value for use in a 'sizes' attribute.
    15121522         * @param string|int[] $size          Requested image size. Can be any registered image size name, or
    15131523         *                                    an array of width and height values in pixels (in that order).
    15141524         * @param string|null  $image_src     The URL to the image file or null.
    15151525         * @param array|null   $image_meta    The image meta data as returned by wp_get_attachment_metadata() or null.
     1526         * @param array        $image_attr    Image attributes.
    15161527         * @param int          $attachment_id Image attachment ID of the original image or 0.
    15171528         */
    1518         return apply_filters( 'wp_calculate_image_sizes', $sizes, $size, $image_src, $image_meta, $attachment_id );
     1529        return apply_filters( 'wp_calculate_image_sizes', $sizes, $size, $image_src, $image_meta, $attachment_id, $image_attr );
    15191530}
    15201531
    15211532/**
  • tests/phpunit/tests/media.php

    diff --git a/tests/phpunit/tests/media.php b/tests/phpunit/tests/media.php
    index 055618f620..f5daa8090f 100644
    a b EOF; 
    31643164                        array( 'trash-attachment', '/?attachment_id=%ID%', false ),
    31653165                );
    31663166        }
     3167
     3168        /**
     3169         * @ticket 36982
     3170         */
     3171        public function test_filter_image_srcset_and_sizes_by_image_attributes() {
     3172
     3173                $image_meta             = wp_get_attachment_metadata( self::$large_id );
     3174                $class_attribute_string = 'test-class-string test-image-full';
     3175
     3176                // Add a filter to remove srcset and sizes from the generated image.
     3177                add_filter( 'wp_calculate_image_srcset', '__return_false' );
     3178                add_filter( 'wp_calculate_image_sizes', '__return_false' );
     3179
     3180                $image_with_class_attribute_no_srcset_sizes    = wp_get_attachment_image(
     3181                        self::$large_id,
     3182                        'full',
     3183                        false,
     3184                        array(
     3185                                'class' => $class_attribute_string,
     3186                                'alt'   => 'Full size test image',
     3187                        )
     3188                );
     3189                $image_without_class_attribute_no_srcset_sizes = wp_get_attachment_image(
     3190                        self::$large_id,
     3191                        'full',
     3192                        false,
     3193                        array(
     3194                                'class' => '',
     3195                                'alt'   => 'Full size test image',
     3196                        )
     3197                );
     3198
     3199                // Remove the filter to restore srcset and sizes from the generated image.
     3200                remove_filter( 'wp_calculate_image_srcset', '__return_false' );
     3201                remove_filter( 'wp_calculate_image_sizes', '__return_false' );
     3202
     3203                $default_image_without_class_attribute         = wp_get_attachment_image(
     3204                        self::$large_id,
     3205                        'full',
     3206                        false,
     3207                        array(
     3208                                'class' => '',
     3209                                'alt'   => 'Full size test image',
     3210                        )
     3211                );
     3212                $default_srcset_string_without_class_attribute = wp_get_attachment_image_srcset(
     3213                        self::$large_id,
     3214                        'full',
     3215                        false,
     3216                        array(
     3217                                'class' => '',
     3218                                'alt'   => 'Full size test image',
     3219                        )
     3220                );
     3221                $default_sizes_string_without_class_attribute  = wp_get_attachment_image_sizes(
     3222                        self::$large_id,
     3223                        'full',
     3224                        false,
     3225                        array(
     3226                                'class' => '',
     3227                                'alt'   => 'Full size test image',
     3228                        )
     3229                );
     3230
     3231                // Filter the srcset and sizes values.
     3232                add_filter( 'wp_calculate_image_srcset', array( $this, '_filter_36982_srcset' ), 10, 6 );
     3233                add_filter( 'wp_calculate_image_sizes', array( $this, '_filter_36982_sizes' ), 10, 6 );
     3234
     3235                // Generate an image with srcset and sizes values that should match the filtered image.
     3236                $uploads_dir_url     = 'http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/';
     3237                $image_file_date_dir = preg_replace( '/(\d{4}\/\d{2}\/).+/', '$1', $image_meta['file'] );
     3238
     3239                // Set sources that will match the filtered values.
     3240                $expected_sources = array(
     3241                        $image_meta['width'] => array(
     3242                                'url'        => $uploads_dir_url . $image_meta['file'],
     3243                                'descriptor' => 'w',
     3244                                'value'      => $image_meta['width'],
     3245                                'width'      => $image_meta['width'],
     3246                                'height'     => $image_meta['height'],
     3247                        ),
     3248                );
     3249
     3250                foreach ( $image_meta['sizes'] as $size ) {
     3251                        $expected_sources[ $size['width'] ] = array(
     3252                                'url'        => $uploads_dir_url . $image_file_date_dir . $size['file'],
     3253                                'descriptor' => 'w',
     3254                                'value'      => $size['width'],
     3255                                'width'      => $size['width'],
     3256                                'height'     => $size['height'],
     3257                        );
     3258                }
     3259
     3260                $expected_sources = array_slice(
     3261                        array_filter(
     3262                                array_map(
     3263                                        function( $source, $image_meta ) {
     3264                                                if ( ! wp_image_matches_ratio( $image_meta['width'], $image_meta['height'], $source['width'], $source['height'] ) || $source['value'] > apply_filters( 'max_srcset_image_width', 1600, array( $image_meta['width'], $image_meta['height'] ) ) ) {
     3265                                                          return false;
     3266                                                }
     3267                                                return $source['url'] . ' ' . $source['value'] . $source['descriptor'];
     3268                                        },
     3269                                        $expected_sources,
     3270                                        array_fill( 0, count( $expected_sources ), $image_meta )
     3271                                )
     3272                        ),
     3273                        2
     3274                );
     3275
     3276                // Set a sizes sting value that will match the arbitrary value set in the filter.
     3277                $expected_sizes_string = sprintf( '(max-width: %1$dpx) 100vw, %1$dpx', 9999 );
     3278
     3279                $expected_image = '<img width="' . $image_meta['width'] . '" height="' . $image_meta['height'] . '" src="' . $uploads_dir_url . $image_meta['file'] . '" class="' . $class_attribute_string . '" alt="Full size test image" srcset="' . implode( ', ', $expected_sources ) . '" sizes="' . $expected_sizes_string . '" />';
     3280
     3281                // Images without a class attribute that will match the test filter. Should match the default image with unfiltered srcset and sizes values.
     3282                $this->assertSame(
     3283                        $default_image_without_class_attribute,
     3284                        wp_get_attachment_image(
     3285                                self::$large_id,
     3286                                'full',
     3287                                false,
     3288                                array(
     3289                                        'class' => '',
     3290                                        'alt'   => 'Full size test image',
     3291                                )
     3292                        )
     3293                );
     3294                $this->assertSame( $default_image_without_class_attribute, wp_image_add_srcset_and_sizes( $image_without_class_attribute_no_srcset_sizes, $image_meta, self::$large_id ) );
     3295
     3296                // Images with a class attribute that will match the test filter. Should match the expected image with filtered srcset and sizes values.
     3297                $this->assertSame( $expected_image, wp_image_add_srcset_and_sizes( $image_with_class_attribute_no_srcset_sizes, $image_meta, self::$large_id ) );
     3298                $this->assertSame(
     3299                        $expected_image,
     3300                        wp_get_attachment_image(
     3301                                self::$large_id,
     3302                                'full',
     3303                                false,
     3304                                array(
     3305                                        'class' => $class_attribute_string,
     3306                                        'alt'   => 'Full size test image',
     3307                                )
     3308                        )
     3309                );
     3310
     3311                // Srcset and sizes strings with class attribute string. Should match the filtered string.
     3312                $this->assertSame(
     3313                        implode( ', ', $expected_sources ),
     3314                        wp_get_attachment_image_srcset(
     3315                                self::$large_id,
     3316                                'full',
     3317                                false,
     3318                                array(
     3319                                        'class' => $class_attribute_string,
     3320                                        'alt'   => 'Full size test image',
     3321                                )
     3322                        )
     3323                );
     3324                $this->assertSame(
     3325                        $expected_sizes_string,
     3326                        wp_get_attachment_image_sizes(
     3327                                self::$large_id,
     3328                                'full',
     3329                                false,
     3330                                array(
     3331                                        'class' => $class_attribute_string,
     3332                                        'alt'   => 'Full size test image',
     3333                                )
     3334                        )
     3335                );
     3336
     3337                // Srcset and sizes strings without class attribute string. Should match the unfiltered default string.
     3338                $this->assertSame(
     3339                        $default_srcset_string_without_class_attribute,
     3340                        wp_get_attachment_image_srcset(
     3341                                self::$large_id,
     3342                                'full',
     3343                                false,
     3344                                array(
     3345                                        'class' => '',
     3346                                        'alt'   => 'Full size test image',
     3347                                )
     3348                        )
     3349                );
     3350                $this->assertSame(
     3351                        $default_sizes_string_without_class_attribute,
     3352                        wp_get_attachment_image_sizes(
     3353                                self::$large_id,
     3354                                'full',
     3355                                false,
     3356                                array(
     3357                                        'class' => '',
     3358                                        'alt'   => 'Full size test image',
     3359                                )
     3360                        )
     3361                );
     3362
     3363        }
     3364
     3365        public function _filter_36982_srcset( $sources, $size_array, $image_src, $image_meta, $attachment_id, $image_attr ) {
     3366
     3367                if ( empty( $image_attr ) ) {
     3368                        return $sources;
     3369                }
     3370
     3371                if ( empty( $image_attr['class'] ) ) {
     3372                        return $sources;
     3373                }
     3374
     3375                $class_array = explode( ' ', $image_attr['class'] );
     3376
     3377                if ( in_array( 'test-image-full', $class_array, true ) ) {
     3378                        return array_slice( $sources, 2 );
     3379                }
     3380
     3381                return $sources;
     3382        }
     3383        public function _filter_36982_sizes( $sizes, $size_array, $image_src, $image_meta, $attachment_id, $image_attr ) {
     3384
     3385                if ( empty( $image_attr ) ) {
     3386                        return $sizes;
     3387                }
     3388
     3389                if ( empty( $image_attr['class'] ) ) {
     3390                        return $sizes;
     3391                }
     3392
     3393                $class_array = explode( ' ', $image_attr['class'] );
     3394
     3395                if ( in_array( 'test-image-full', $class_array, true ) ) {
     3396                        return sprintf( '(max-width: %1$dpx) 100vw, %1$dpx', 9999 );
     3397                }
     3398
     3399                return $sizes;
     3400        }
    31673401}
    31683402
    31693403/**