Make WordPress Core

Ticket #36982: 36982.6.diff

File 36982.6.diff, 15.8 KB (added by adamsilverstein, 3 years ago)
  • src/wp-includes/media.php

    diff --git src/wp-includes/media.php src/wp-includes/media.php
    index 6e7f66760f..a45cc80ab1 100644
    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 ) { 
    11941194 * Retrieves the value for an image attachment's 'srcset' attribute.
    11951195 *
    11961196 * @since 4.4.0
     1197 * @since 5.7.0 Added the '$image_attr' parameter.
    11971198 *
    11981199 * @see wp_calculate_image_srcset()
    11991200 *
    function _wp_get_image_size_from_meta( $size_name, $image_meta ) { 
    12021203 *                                    width and height values in pixels (in that order). Default 'medium'.
    12031204 * @param array        $image_meta    Optional. The image meta data as returned by 'wp_get_attachment_metadata()'.
    12041205 *                                    Default null.
     1206 * @param array        $image_attr    Optional. An array of image attributes to be passed to 'wp_calculate_image_srcset()'.
    12051207 * @return string|false A 'srcset' value string or false.
    12061208 */
    1207 function wp_get_attachment_image_srcset( $attachment_id, $size = 'medium', $image_meta = null ) {
     1209function wp_get_attachment_image_srcset( $attachment_id, $size = 'medium', $image_meta = null, $image_attr = array() ) {
    12081210        $image = wp_get_attachment_image_src( $attachment_id, $size );
    12091211
    12101212        if ( ! $image ) {
    function wp_get_attachment_image_srcset( $attachment_id, $size = 'medium', $imag 
    12211223                absint( $image[2] ),
    12221224        );
    12231225
    1224         return wp_calculate_image_srcset( $size_array, $image_src, $image_meta, $attachment_id );
     1226        return wp_calculate_image_srcset( $size_array, $image_src, $image_meta, $attachment_id, $image_attr );
    12251227}
    12261228
    12271229/**
    12281230 * A helper function to calculate the image sources to include in a 'srcset' attribute.
    12291231 *
    12301232 * @since 4.4.0
     1233 * @since 5.7.0 Added the '$image_attr' parameter.
    12311234 *
    12321235 * @param int[]  $size_array    {
    12331236 *     An array of width and height values.
    function wp_get_attachment_image_srcset( $attachment_id, $size = 'medium', $imag 
    12381241 * @param string $image_src     The 'src' of the image.
    12391242 * @param array  $image_meta    The image meta data as returned by 'wp_get_attachment_metadata()'.
    12401243 * @param int    $attachment_id Optional. The image attachment ID. Default 0.
     1244 * @param array  $image_attr    Optional. Image attributes.
     1245
    12411246 * @return string|false The 'srcset' attribute value. False on error or when only one source exists.
    12421247 */
    1243 function wp_calculate_image_srcset( $size_array, $image_src, $image_meta, $attachment_id = 0 ) {
     1248function wp_calculate_image_srcset( $size_array, $image_src, $image_meta, $attachment_id = 0, $image_attr = array() ) {
    12441249        /**
    12451250         * Let plugins pre-filter the image meta to be able to fix inconsistencies in the stored data.
    12461251         *
    function wp_calculate_image_srcset( $size_array, $image_src, $image_meta, $attac 
    12551260         * }
    12561261         * @param string $image_src     The 'src' of the image.
    12571262         * @param int    $attachment_id The image attachment ID or 0 if not supplied.
     1263         * @param string $image_attr    The image attributes.
    12581264         */
    1259         $image_meta = apply_filters( 'wp_calculate_image_srcset_meta', $image_meta, $size_array, $image_src, $attachment_id );
     1265        $image_meta = apply_filters( 'wp_calculate_image_srcset_meta', $image_meta, $size_array, $image_src, $attachment_id, $image_attr );
    12601266
    12611267        if ( empty( $image_meta['sizes'] ) || ! isset( $image_meta['file'] ) || strlen( $image_meta['file'] ) < 4 ) {
    12621268                return false;
    function wp_calculate_image_srcset( $size_array, $image_src, $image_meta, $attac 
    14141420         * @param string $image_src     The 'src' of the image.
    14151421         * @param array  $image_meta    The image meta data as returned by 'wp_get_attachment_metadata()'.
    14161422         * @param int    $attachment_id Image attachment ID or 0.
     1423         * @param array  $image_attr    Image attributes.
    14171424         */
    1418         $sources = apply_filters( 'wp_calculate_image_srcset', $sources, $size_array, $image_src, $image_meta, $attachment_id );
     1425        $sources = apply_filters( 'wp_calculate_image_srcset', $sources, $size_array, $image_src, $image_meta, $attachment_id, $image_attr );
    14191426
    14201427        // Only return a 'srcset' value if there is more than one source.
    14211428        if ( ! $src_matched || ! is_array( $sources ) || count( $sources ) < 2 ) {
    function wp_calculate_image_srcset( $size_array, $image_src, $image_meta, $attac 
    14351442 * Retrieves the value for an image attachment's 'sizes' attribute.
    14361443 *
    14371444 * @since 4.4.0
     1445 * @since 5.7.0 Added the '$image_attr' parameter.
    14381446 *
    14391447 * @see wp_calculate_image_sizes()
    14401448 *
    function wp_calculate_image_srcset( $size_array, $image_src, $image_meta, $attac 
    14431451 *                                    width and height values in pixels (in that order). Default 'medium'.
    14441452 * @param array        $image_meta    Optional. The image meta data as returned by 'wp_get_attachment_metadata()'.
    14451453 *                                    Default null.
     1454 * @param array        $image_attr    Optional. Image attributes.
    14461455 * @return string|false A valid source size value for use in a 'sizes' attribute or false.
    14471456 */
    1448 function wp_get_attachment_image_sizes( $attachment_id, $size = 'medium', $image_meta = null ) {
     1457function wp_get_attachment_image_sizes( $attachment_id, $size = 'medium', $image_meta = null, $image_attr = array() ) {
    14491458        $image = wp_get_attachment_image_src( $attachment_id, $size );
    14501459
    14511460        if ( ! $image ) {
    function wp_get_attachment_image_sizes( $attachment_id, $size = 'medium', $image 
    14621471                absint( $image[2] ),
    14631472        );
    14641473
    1465         return wp_calculate_image_sizes( $size_array, $image_src, $image_meta, $attachment_id );
     1474        return wp_calculate_image_sizes( $size_array, $image_src, $image_meta, $attachment_id, $image_attr );
    14661475}
    14671476
    14681477/**
    14691478 * Creates a 'sizes' attribute value for an image.
    14701479 *
    14711480 * @since 4.4.0
     1481 * @since 5.7.0 Added the '$image_attr' parameter.
    14721482 *
    14731483 * @param string|int[] $size          Image size. Accepts any registered image size name, or an array of
    14741484 *                                    width and height values in pixels (in that order).
    function wp_get_attachment_image_sizes( $attachment_id, $size = 'medium', $image 
    14771487 *                                    Default null.
    14781488 * @param int          $attachment_id Optional. Image attachment ID. Either `$image_meta` or `$attachment_id`
    14791489 *                                    is needed when using the image size name as argument for `$size`. Default 0.
     1490 * @param array        $image_attr    Image attributes.
    14801491 * @return string|false A valid source size value for use in a 'sizes' attribute or false.
    14811492 */
    1482 function wp_calculate_image_sizes( $size, $image_src = null, $image_meta = null, $attachment_id = 0 ) {
     1493function wp_calculate_image_sizes( $size, $image_src = null, $image_meta = null, $attachment_id = 0, $image_attr = array() ) {
    14831494        $width = 0;
    14841495
    14851496        if ( is_array( $size ) ) {
    function wp_calculate_image_sizes( $size, $image_src = null, $image_meta = null, 
    15081519         * Filters the output of 'wp_calculate_image_sizes()'.
    15091520         *
    15101521         * @since 4.4.0
     1522         * @since 5.7.0 Added the '$image_attr' parameter.
    15111523         *
    15121524         * @param string       $sizes         A source size value for use in a 'sizes' attribute.
    15131525         * @param string|int[] $size          Requested image size. Can be any registered image size name, or
    function wp_calculate_image_sizes( $size, $image_src = null, $image_meta = null, 
    15151527         * @param string|null  $image_src     The URL to the image file or null.
    15161528         * @param array|null   $image_meta    The image meta data as returned by wp_get_attachment_metadata() or null.
    15171529         * @param int          $attachment_id Image attachment ID of the original image or 0.
     1530         * @param array        $image_attr    Image attributes.
    15181531         */
    1519         return apply_filters( 'wp_calculate_image_sizes', $sizes, $size, $image_src, $image_meta, $attachment_id );
     1532        return apply_filters( 'wp_calculate_image_sizes', $sizes, $size, $image_src, $image_meta, $attachment_id, $image_attr );
    15201533}
    15211534
    15221535/**
  • tests/phpunit/tests/media.php

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