Make WordPress Core

Changeset 54097


Ignore:
Timestamp:
09/07/2022 09:43:28 PM (4 years ago)
Author:
flixos90
Message:

Media: Generate WebP only for certain registered image sizes.

The existing filter image_editor_output_format receives an additional parameter $size_name which is populated whenever it controls the output format for a specific registered image size to create. Otherwise, it remains empty. In order to achieve this, a low level change has been added in bringing a new $size_name class property to the WP_Image_Editor base class, which is introduced in a backward compatible way that will not cause conflicts with custom implementations.

This parameter is then used in new logic inside the wp_default_image_output_mapping() callback function for the filter, controlling whether image/jpeg should map to image/webp output or not. By default, this is enabled for all WordPress core image sizes by default, and this list can be modified using a new wp_image_sizes_with_additional_mime_type_support filter, e.g. to remove core sizes or add custom sizes.

The customization per image size may be further enhanced by providing a more declarative API via a new parameter on the add_image_size() function.

Props eugenemanuilov, flixos90, adamsilverstein, joegrainger.

Fixes #56526.
See #55443, #56288.

Location:
trunk
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/includes/image.php

    r54085 r54097  
    452452        if ( method_exists( $editor, 'make_subsize' ) ) {
    453453                foreach ( $new_sizes as $new_size_name => $new_size_data ) {
     454                        // Include size name in the data.
     455                        $new_size_data['name'] = $new_size_name;
     456
    454457                        $new_size_meta = $editor->make_subsize( $new_size_data );
    455458
  • trunk/src/wp-includes/class-wp-image-editor-gd.php

    r53547 r54097  
    228228         *
    229229         * @param array $sizes {
    230          *     An array of image size data arrays.
     230         *     Associative array of image size names and their data.
    231231         *
    232232         *     Either a height or width must be provided.
     
    248248
    249249                foreach ( $sizes as $size => $size_data ) {
     250                        // Include size name in the data.
     251                        $size_data['name'] = $size;
     252
    250253                        $meta = $this->make_subsize( $size_data );
    251254
     
    262265         *
    263266         * @since 5.3.0
     267         * @since 6.1.0 The $sizes parameter may now include a $name key for each entry.
    264268         *
    265269         * @param array $size_data {
    266270         *     Array of size data.
    267271         *
    268          *     @type int  $width  The maximum width in pixels.
    269          *     @type int  $height The maximum height in pixels.
    270          *     @type bool $crop   Whether to crop the image to exact dimensions.
     272         *     @type int    $width  The maximum width in pixels.
     273         *     @type int    $height The maximum height in pixels.
     274         *     @type bool   $crop   Whether to crop the image to exact dimensions.
     275         *     @type string $name   Image size name.
    271276         * }
    272277         * @return array|WP_Error The image data array for inclusion in the `sizes` array in the image meta,
     
    278283                }
    279284
    280                 $orig_size = $this->size;
     285                $orig_size      = $this->size;
     286                $orig_size_name = $this->size_name;
    281287
    282288                if ( ! isset( $size_data['width'] ) ) {
     
    290296                if ( ! isset( $size_data['crop'] ) ) {
    291297                        $size_data['crop'] = false;
     298                }
     299
     300                if ( isset( $size_data['name'] ) ) {
     301                        $this->update_size_name( $size_data['name'] );
    292302                }
    293303
     
    302312
    303313                $this->size = $orig_size;
     314                $this->size_name = $orig_size_name;
    304315
    305316                if ( ! is_wp_error( $saved ) ) {
  • trunk/src/wp-includes/class-wp-image-editor-imagick.php

    r53547 r54097  
    439439         *
    440440         * @param array $sizes {
    441          *     An array of image size data arrays.
     441         *     Associative array of image size names and their data.
    442442         *
    443443         *     Either a height or width must be provided.
     
    459459
    460460                foreach ( $sizes as $size => $size_data ) {
     461                        // Include size name in the data.
     462                        $size_data['name'] = $size;
     463
    461464                        $meta = $this->make_subsize( $size_data );
    462465
     
    473476         *
    474477         * @since 5.3.0
     478         * @since 6.1.0 The $sizes parameter may now include a $name key for each entry.
    475479         *
    476480         * @param array $size_data {
    477481         *     Array of size data.
    478482         *
    479          *     @type int  $width  The maximum width in pixels.
    480          *     @type int  $height The maximum height in pixels.
    481          *     @type bool $crop   Whether to crop the image to exact dimensions.
     483         *     @type int    $width  The maximum width in pixels.
     484         *     @type int    $height The maximum height in pixels.
     485         *     @type bool   $crop   Whether to crop the image to exact dimensions.
     486         *     @type string $name   Image size name.
    482487         * }
    483488         * @return array|WP_Error The image data array for inclusion in the `sizes` array in the image meta,
     
    489494                }
    490495
    491                 $orig_size  = $this->size;
    492                 $orig_image = $this->image->getImage();
     496                $orig_size      = $this->size;
     497                $orig_size_name = $this->size_name;
     498                $orig_image     = $this->image->getImage();
    493499
    494500                if ( ! isset( $size_data['width'] ) ) {
     
    502508                if ( ! isset( $size_data['crop'] ) ) {
    503509                        $size_data['crop'] = false;
     510                }
     511
     512                if ( isset( $size_data['name'] ) ) {
     513                        $this->update_size_name( $size_data['name'] );
    504514                }
    505515
     
    516526                }
    517527
    518                 $this->size  = $orig_size;
    519                 $this->image = $orig_image;
     528                $this->size      = $orig_size;
     529                $this->size_name = $orig_size_name;
     530                $this->image     = $orig_image;
    520531
    521532                if ( ! is_wp_error( $saved ) ) {
  • trunk/src/wp-includes/class-wp-image-editor.php

    r54086 r54097  
    1515        protected $file              = null;
    1616        protected $size              = null;
     17        protected $size_name         = '';
    1718        protected $mime_type         = null;
    1819        protected $output_mime_type  = null;
     
    118119         *
    119120         * @param array $sizes {
    120          *     An array of image size arrays. Default sizes are 'small', 'medium', 'large'.
     121         *     Associative array of image size names and their data. Default sizes are 'small', 'medium', 'large'.
    121122         *
    122123         *     @type array ...$0 {
     
    186187         * @since 3.5.0
    187188         *
    188          * @return int[] {
     189         * @return array {
    189190         *     Dimensions of the image.
    190191         *
     
    202203         * @since 3.5.0
    203204         *
    204          * @param int $width
    205          * @param int $height
    206          * @return true
     205         * @param int $width  The image width.
     206         * @param int $height The image height.
     207         * @return true True on success, false on failure.
    207208         */
    208209        protected function update_size( $width = null, $height = null ) {
     
    212213                );
    213214                return true;
     215        }
     216
     217        /**
     218         * Gets the current image size name.
     219         *
     220         * @since 6.1.0
     221         *
     222         * @return string Image size name, or empty string if none set.
     223         */
     224        public function get_size_name() {
     225                return $this->size_name;
     226        }
     227
     228        /**
     229         * Sets the current image size name.
     230         *
     231         * @since 6.1.0
     232         *
     233         * @param string $size_name The image size name.
     234         */
     235        protected function update_size_name( $size_name ) {
     236                $this->size_name = (string) $size_name;
    214237        }
    215238
     
    365388                 *
    366389                 * @since 5.8.0
     390                 * @since 6.1.0 The $size_name parameter was added.
    367391                 *
    368392                 * @param string[] $output_format {
     
    374398                 * @param string $filename  Path to the image.
    375399                 * @param string $mime_type The source image mime type.
     400                 * @param string $size_name The image size name to create, or empty string if not set.
    376401                 */
    377                 $output_format = apply_filters( 'image_editor_output_format', array(), $filename, $mime_type );
     402                $output_format = apply_filters( 'image_editor_output_format', array(), $filename, $mime_type, $this->size_name );
    378403
    379404                if ( isset( $output_format[ $mime_type ] )
  • trunk/src/wp-includes/default-filters.php

    r54094 r54097  
    633633add_filter( 'media_send_to_editor', 'image_media_send_to_editor', 10, 3 );
    634634
    635 add_filter( 'image_editor_output_format', 'wp_default_image_output_mapping' );
     635add_filter( 'image_editor_output_format', 'wp_default_image_output_mapping', 10, 4 );
    636636
    637637// Embeds.
  • trunk/src/wp-includes/functions.php

    r53946 r54097  
    26912691                if ( $is_image ) {
    26922692                        /** This filter is documented in wp-includes/class-wp-image-editor.php */
    2693                         $output_formats = apply_filters( 'image_editor_output_format', array(), $_dir . $filename, $mime_type );
     2693                        $output_formats = apply_filters( 'image_editor_output_format', array(), $_dir . $filename, $mime_type, '' );
    26942694                        $alt_types      = array();
    26952695
  • trunk/src/wp-includes/media.php

    r54094 r54097  
    39133913 *
    39143914 * @param array $output_mapping Map of mime type to output format.
    3915  * @retun array The adjusted default output mapping.
    3916  */
    3917 function wp_default_image_output_mapping( $output_mapping ) {
     3915 * @param string $filename  Path to the image.
     3916 * @param string $mime_type The source image mime type.
     3917 * @param string $size_name Optional. The image size name to create, or empty string if not set. Default empty string.
     3918 * @return array The adjusted default output mapping.
     3919 */
     3920function wp_default_image_output_mapping( $output_mapping, $filename, $mime_type, $size_name = '' ) {
     3921        // If size name is specified, check whether the size supports additional MIME types like WebP.
     3922        if ( $size_name ) {
     3923                // Include only the core sizes that do not rely on add_image_size(). Additional image sizes are opt-in.
     3924                $enabled_sizes = array(
     3925                        'thumbnail'      => true,
     3926                        'medium'         => true,
     3927                        'medium_large'   => true,
     3928                        'large'          => true,
     3929                        'post-thumbnail' => true,
     3930                );
     3931
     3932                /**
     3933                 * Filters the sizes that support secondary mime type output. Developers can use this
     3934                 * to control the generation of additional mime type sub-sized images.
     3935                 *
     3936                 * @since 6.1.0
     3937                 *
     3938                 * @param array $enabled_sizes Map of size names and whether they support secondary mime type output.
     3939                 */
     3940                $enabled_sizes = apply_filters( 'wp_image_sizes_with_additional_mime_type_support', $enabled_sizes );
     3941
     3942                // Bail early if the size does not support additional MIME types.
     3943                if ( empty( $enabled_sizes[ $size_name ] ) ) {
     3944                        return $output_mapping;
     3945                }
     3946        }
     3947
    39183948        $output_mapping['image/jpeg'] = 'image/webp';
    39193949        return $output_mapping;
  • trunk/tests/phpunit/tests/media.php

    r54086 r54097  
    36273627         */
    36283628        public function test_wp_default_image_output_mapping() {
    3629                 $mapping = wp_default_image_output_mapping( array() );
     3629                $mapping = wp_default_image_output_mapping( array(), 'test.jpg', 'image/jpeg', '' );
    36303630                $this->assertSame( array( 'image/jpeg' => 'image/webp' ), $mapping );
    36313631        }
     
    36383638        public function test_wp_default_image_output_mapping_existing() {
    36393639                $mapping = array( 'mime/png' => 'mime/webp' );
    3640                 $mapping = wp_default_image_output_mapping( $mapping );
     3640                $mapping = wp_default_image_output_mapping( $mapping, 'test.jpg', 'image/jpeg', '' );
    36413641                $this->assertSame(
    36423642                        array(
     
    36733673                }
    36743674        }
     3675
     3676        /**
     3677         * @ticket 56526
     3678         * @dataProvider data_wp_default_image_output_mapping_size_filter
     3679         */
     3680        public function test_wp_default_image_output_mapping_size_filter( $size_name, $filter_callback, $expects_webp ) {
     3681                remove_all_filters( 'wp_image_sizes_with_additional_mime_type_support' );
     3682                if ( $filter_callback ) {
     3683                        add_filter( 'wp_image_sizes_with_additional_mime_type_support', $filter_callback );
     3684                }
     3685
     3686                $mapping = wp_default_image_output_mapping( array(), 'test.jpg', 'image/jpeg', $size_name );
     3687                if ( $expects_webp ) {
     3688                        $this->assertSame( array( 'image/jpeg' => 'image/webp' ), $mapping );
     3689                } else {
     3690                        $this->assertSame( array(), $mapping );
     3691                }
     3692        }
     3693
     3694        public function data_wp_default_image_output_mapping_size_filter() {
     3695                return array(
     3696                        'default size thumbnail'    => array(
     3697                                'thumbnail',
     3698                                null,
     3699                                true,
     3700                        ),
     3701                        'default size medium'       => array(
     3702                                'medium',
     3703                                null,
     3704                                true,
     3705                        ),
     3706                        'default size medium_large' => array(
     3707                                'medium_large',
     3708                                null,
     3709                                true,
     3710                        ),
     3711                        'default size large'        => array(
     3712                                'large',
     3713                                null,
     3714                                true,
     3715                        ),
     3716                        'default size unset'        => array(
     3717                                'medium',
     3718                                function( $enabled_sizes ) {
     3719                                        unset( $enabled_sizes['medium'] );
     3720                                        return $enabled_sizes;
     3721                                },
     3722                                false,
     3723                        ),
     3724                        'default size set to false' => array(
     3725                                'medium',
     3726                                function( $enabled_sizes ) {
     3727                                        $enabled_sizes['medium'] = false;
     3728                                        return $enabled_sizes;
     3729                                },
     3730                                false,
     3731                        ),
     3732                        'custom size'               => array(
     3733                                'custom',
     3734                                null,
     3735                                false,
     3736                        ),
     3737                        'custom size opted in'      => array(
     3738                                'custom',
     3739                                function( $enabled_sizes ) {
     3740                                        $enabled_sizes['custom'] = true;
     3741                                        return $enabled_sizes;
     3742                                },
     3743                                true,
     3744                        ),
     3745                );
     3746        }
    36753747}
    36763748
Note: See TracChangeset for help on using the changeset viewer.