Make WordPress Core

Changeset 54097


Ignore:
Timestamp:
09/07/2022 09:43:28 PM (21 months 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.