WordPress.org

Make WordPress Core

Ticket #36982: 36982.diff

File 36982.diff, 13.2 KB (added by adamsilverstein, 11 months ago)
  • src/wp-includes/media.php

    diff --git src/wp-includes/media.php src/wp-includes/media.php
    index 561cdf3d4c..fbc433315b 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 ) { 
    12011201 *                                    width and height values in pixels (in that order). Default 'medium'.
    12021202 * @param array        $image_meta    Optional. The image meta data as returned by 'wp_get_attachment_metadata()'.
    12031203 *                                    Default null.
     1204 * @param array        $image_attr    Optional. An array of image attributes to be passed to 'wp_calculate_image_srcset()'.
    12041205 * @return string|bool A 'srcset' value string or false.
    12051206 */
    1206 function wp_get_attachment_image_srcset( $attachment_id, $size = 'medium', $image_meta = null ) {
     1207function wp_get_attachment_image_srcset( $attachment_id, $size = 'medium', $image_meta = null, $image_attr = array() ) {
    12071208        $image = wp_get_attachment_image_src( $attachment_id, $size );
    12081209
    12091210        if ( ! $image ) {
    function wp_get_attachment_image_srcset( $attachment_id, $size = 'medium', $imag 
    12201221                absint( $image[2] ),
    12211222        );
    12221223
    1223         return wp_calculate_image_srcset( $size_array, $image_src, $image_meta, $attachment_id );
     1224        return wp_calculate_image_srcset( $size_array, $image_src, $image_meta, $attachment_id, $image_attr );
    12241225}
    12251226
    12261227/**
    function wp_get_attachment_image_srcset( $attachment_id, $size = 'medium', $imag 
    12371238 * @param string $image_src     The 'src' of the image.
    12381239 * @param array  $image_meta    The image meta data as returned by 'wp_get_attachment_metadata()'.
    12391240 * @param int    $attachment_id Optional. The image attachment ID. Default 0.
     1241 * @param array  $image_attr    Optional. Image attributes.
     1242
    12401243 * @return string|false The 'srcset' attribute value. False on error or when only one source exists.
    12411244 */
    1242 function wp_calculate_image_srcset( $size_array, $image_src, $image_meta, $attachment_id = 0 ) {
     1245function wp_calculate_image_srcset( $size_array, $image_src, $image_meta, $attachment_id = 0, $image_attr = array() ) {
    12431246        /**
    12441247         * Let plugins pre-filter the image meta to be able to fix inconsistencies in the stored data.
    12451248         *
    function wp_calculate_image_srcset( $size_array, $image_src, $image_meta, $attac 
    12541257         * }
    12551258         * @param string $image_src     The 'src' of the image.
    12561259         * @param int    $attachment_id The image attachment ID or 0 if not supplied.
     1260         * @param string $image_attr    The image attributes.
    12571261         */
    1258         $image_meta = apply_filters( 'wp_calculate_image_srcset_meta', $image_meta, $size_array, $image_src, $attachment_id );
     1262        $image_meta = apply_filters( 'wp_calculate_image_srcset_meta', $image_meta, $size_array, $image_src, $attachment_id, $image_attr );
    12591263
    12601264        if ( empty( $image_meta['sizes'] ) || ! isset( $image_meta['file'] ) || strlen( $image_meta['file'] ) < 4 ) {
    12611265                return false;
    function wp_calculate_image_srcset( $size_array, $image_src, $image_meta, $attac 
    14131417         * @param string $image_src     The 'src' of the image.
    14141418         * @param array  $image_meta    The image meta data as returned by 'wp_get_attachment_metadata()'.
    14151419         * @param int    $attachment_id Image attachment ID or 0.
     1420         * @param array  $image_attr    Image attributes.
    14161421         */
    1417         $sources = apply_filters( 'wp_calculate_image_srcset', $sources, $size_array, $image_src, $image_meta, $attachment_id );
     1422        $sources = apply_filters( 'wp_calculate_image_srcset', $sources, $size_array, $image_src, $image_meta, $attachment_id, $image_attr );
    14181423
    14191424        // Only return a 'srcset' value if there is more than one source.
    14201425        if ( ! $src_matched || ! is_array( $sources ) || count( $sources ) < 2 ) {
    function wp_calculate_image_srcset( $size_array, $image_src, $image_meta, $attac 
    14421447 *                                    width and height values in pixels (in that order). Default 'medium'.
    14431448 * @param array        $image_meta    Optional. The image meta data as returned by 'wp_get_attachment_metadata()'.
    14441449 *                                    Default null.
     1450 * @param array        $image_attr    Optional. Image attributes.
    14451451 * @return string|bool A valid source size value for use in a 'sizes' attribute or false.
    14461452 */
    1447 function wp_get_attachment_image_sizes( $attachment_id, $size = 'medium', $image_meta = null ) {
     1453function wp_get_attachment_image_sizes( $attachment_id, $size = 'medium', $image_meta = null, $image_attr = array() ) {
    14481454        $image = wp_get_attachment_image_src( $attachment_id, $size );
    14491455
    14501456        if ( ! $image ) {
    function wp_get_attachment_image_sizes( $attachment_id, $size = 'medium', $image 
    14611467                absint( $image[2] ),
    14621468        );
    14631469
    1464         return wp_calculate_image_sizes( $size_array, $image_src, $image_meta, $attachment_id );
     1470        return wp_calculate_image_sizes( $size_array, $image_src, $image_meta, $attachment_id, $image_attr );
    14651471}
    14661472
    14671473/**
    function wp_calculate_image_sizes( $size, $image_src = null, $image_meta = null, 
    15131519         *                                    an array of width and height values in pixels (in that order).
    15141520         * @param string|null  $image_src     The URL to the image file or null.
    15151521         * @param array|null   $image_meta    The image meta data as returned by wp_get_attachment_metadata() or null.
     1522         * @param array        $image_attr    Image attributes.
    15161523         * @param int          $attachment_id Image attachment ID of the original image or 0.
    15171524         */
    1518         return apply_filters( 'wp_calculate_image_sizes', $sizes, $size, $image_src, $image_meta, $attachment_id );
     1525        return apply_filters( 'wp_calculate_image_sizes', $sizes, $size, $image_src, $image_meta, $attachment_id, $image_attr );
    15191526}
    15201527
    15211528/**
    function wp_image_add_srcset_and_sizes( $image, $image_meta, $attachment_id ) { 
    16731680                }
    16741681        }
    16751682
    1676         $srcset = wp_calculate_image_srcset( $size_array, $image_src, $image_meta, $attachment_id );
    1677 
    16781683        if ( $srcset ) {
    16791684                // Check if there is already a 'sizes' attribute.
    16801685                $sizes = strpos( $image, ' sizes=' );
  • tests/phpunit/tests/media.php

    diff --git tests/phpunit/tests/media.php tests/phpunit/tests/media.php
    index b968b95a51..c836d6a10e 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/**