WordPress.org

Make WordPress Core

Ticket #36982: 36982.2.diff

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

    diff --git src/wp-includes/media.php src/wp-includes/media.php
    index d29426213e..470a5e320d 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 ) { 
    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 tests/phpunit/tests/media.php tests/phpunit/tests/media.php
    index e7326fec65..cfd2eaba0c 100644
    EOF; 
    31593159                        array( 'trash-attachment', '/?attachment_id=%ID%', false ),
    31603160                );
    31613161        }
     3162
     3163        /**
     3164         * @ticket 36982
     3165         */
     3166        public function test_filter_image_srcset_and_sizes_by_image_attributes() {
     3167
     3168                $image_meta = wp_get_attachment_metadata( self::$large_id );
     3169                $class_attribute_string = 'test-class-string test-image-full';
     3170
     3171                // Add a filter to remove srcset and sizes from the generated image.
     3172                add_filter( 'wp_calculate_image_srcset', '__return_false' );
     3173                add_filter( 'wp_calculate_image_sizes', '__return_false' );
     3174
     3175                $image_with_class_attribute_no_srcset_sizes = wp_get_attachment_image( self::$large_id, 'full', false, array( 'class' => $class_attribute_string, 'alt' => 'Full size test image' ) );
     3176                $image_without_class_attribute_no_srcset_sizes = wp_get_attachment_image( self::$large_id, 'full', false, array( 'class' => '', 'alt' => 'Full size test image' ) );
     3177
     3178                // Remove the filter to restore srcset and sizes from the generated image.
     3179                remove_filter( 'wp_calculate_image_srcset', '__return_false' );
     3180                remove_filter( 'wp_calculate_image_sizes', '__return_false' );
     3181
     3182                $default_image_without_class_attribute = wp_get_attachment_image( self::$large_id, 'full', false, array( 'class' => '', 'alt' => 'Full size test image' ) );
     3183                $default_srcset_string_without_class_attribute = wp_get_attachment_image_srcset( self::$large_id, 'full', false, array( 'class' => '', 'alt' => 'Full size test image' ) );
     3184                $default_sizes_string_without_class_attribute = wp_get_attachment_image_sizes( self::$large_id, 'full', false, array( 'class' => '', 'alt' => 'Full size test image' ) );
     3185
     3186                // Filter the srcset and sizes values.
     3187                add_filter( 'wp_calculate_image_srcset', array( $this, '_filter_36982_srcset' ), 10, 6 );
     3188                add_filter( 'wp_calculate_image_sizes', array( $this, '_filter_36982_sizes' ), 10, 6 );
     3189
     3190                // Generate an image with srcset and sizes values that should match the filtered image.
     3191                $uploads_dir_url = 'http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/';
     3192                $image_file_date_dir = preg_replace( '/(\d{4}\/\d{2}\/).+/', '$1', $image_meta['file'] );
     3193
     3194                // Set sources that will match the filtered values.
     3195                $expected_sources = array(
     3196                        $image_meta['width'] => array(
     3197                                'url' => $uploads_dir_url . $image_meta['file'],
     3198                                'descriptor' => 'w',
     3199                                'value' => $image_meta['width'],
     3200                                'width' => $image_meta['width'],
     3201                                'height' => $image_meta['height'],
     3202                        ),
     3203                );
     3204
     3205                foreach( $image_meta['sizes'] as $size ) {
     3206                        $expected_sources[ $size['width'] ] = array(
     3207                                'url' => $uploads_dir_url . $image_file_date_dir . $size['file'],
     3208                                'descriptor' => 'w',
     3209                                'value' => $size['width'],
     3210                                'width' => $size['width'],
     3211                                'height' => $size['height'],
     3212                        );
     3213                }
     3214
     3215                $expected_sources = array_slice( array_filter( array_map( function( $source, $image_meta ) {
     3216                        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'] ) ) ) {
     3217                                return false;
     3218                        }
     3219                        return $source['url'] . ' ' . $source['value'] . $source['descriptor'];
     3220                }, $expected_sources, array_fill( 0, count( $expected_sources ), $image_meta ) ) ), 2 );
     3221
     3222                // Set a sizes sting value that will match the arbitrary value set in the filter.
     3223                $expected_sizes_string = sprintf( '(max-width: %1$dpx) 100vw, %1$dpx', 9999 );
     3224
     3225                $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 . '" />';
     3226
     3227                // Images without a class attribute that will match the test filter. Should match the default image with unfiltered srcset and sizes values.
     3228                $this->assertSame( $default_image_without_class_attribute, wp_get_attachment_image( self::$large_id, 'full', false, array( 'class' => '', 'alt' => 'Full size test image' ) ) );
     3229                $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 ) );
     3230
     3231                // Images with a class attribute that will match the test filter. Should match the expected image with filtered srcset and sizes values.
     3232                $this->assertSame( $expected_image, wp_image_add_srcset_and_sizes( $image_with_class_attribute_no_srcset_sizes, $image_meta, self::$large_id ) );
     3233                $this->assertSame( $expected_image, wp_get_attachment_image( self::$large_id, 'full', false, array( 'class' => $class_attribute_string, 'alt' => 'Full size test image' ) ) );
     3234
     3235                // Srcset and sizes strings with class attribute string. Should match the filtered string.
     3236                $this->assertSame( implode( ', ', $expected_sources ), wp_get_attachment_image_srcset( self::$large_id, 'full', false, array( 'class' => $class_attribute_string, 'alt' => 'Full size test image' ) ) );
     3237                $this->assertSame( $expected_sizes_string, wp_get_attachment_image_sizes( self::$large_id, 'full', false, array( 'class' => $class_attribute_string, 'alt' => 'Full size test image' ) ) );
     3238
     3239                // Srcset and sizes strings without class attribute string. Should match the unfiltered default string.
     3240                $this->assertSame( $default_srcset_string_without_class_attribute, wp_get_attachment_image_srcset( self::$large_id, 'full', false, array( 'class' => '', 'alt' => 'Full size test image' ) ) );
     3241                $this->assertSame( $default_sizes_string_without_class_attribute, wp_get_attachment_image_sizes( self::$large_id, 'full', false, array( 'class' => '', 'alt' => 'Full size test image' ) ) );
     3242
     3243
     3244        }
     3245
     3246        public function _filter_36982_srcset( $sources, $size_array, $image_src, $image_meta, $attachment_id, $image_attr ) {
     3247
     3248                if ( empty( $image_attr ) ) {
     3249                        return $sources;
     3250                }
     3251
     3252                if ( empty( $image_attr['class'] ) ) {
     3253                        return $sources;
     3254                }
     3255
     3256                $class_array = explode( ' ', $image_attr['class'] );
     3257
     3258                if ( in_array( 'test-image-full', $class_array, true ) ) {
     3259                        return array_slice( $sources, 2 );
     3260                }
     3261
     3262                return $sources;
     3263        }
     3264        public function _filter_36982_sizes( $sizes, $size_array, $image_src, $image_meta, $attachment_id, $image_attr ) {
     3265
     3266                if ( empty( $image_attr ) ) {
     3267                        return $sizes;
     3268                }
     3269
     3270                if ( empty( $image_attr['class'] ) ) {
     3271                        return $sizes;
     3272                }
     3273
     3274                $class_array = explode( ' ', $image_attr['class'] );
     3275
     3276                if ( in_array( 'test-image-full', $class_array, true ) ) {
     3277                        return sprintf( '(max-width: %1$dpx) 100vw, %1$dpx', 9999 );
     3278                }
     3279
     3280                return $sizes;
     3281        }
    31623282}
    31633283
    31643284/**