Make WordPress Core

Ticket #55443: revert-53786-53848-r53847-r53845-r53751.diff

File revert-53786-53848-r53847-r53845-r53751.diff, 94.5 KB (added by adamsilverstein, 18 months ago)
  • src/js/_enqueues/vendor/plupload/handlers.js

    diff --git src/js/_enqueues/vendor/plupload/handlers.js src/js/_enqueues/vendor/plupload/handlers.js
    index c7e3c253d3..fa602daf43 100644
    jQuery( document ).ready( function( $ ) { 
    486486
    487487                times = tryAgainCount[ file.id ];
    488488
    489                 if ( times && times > 8 ) {
     489                if ( times && times > 4 ) {
    490490                        /*
    491491                         * The file may have been uploaded and attachment post created,
    492492                         * but post-processing and resizing failed...
  • src/js/_enqueues/vendor/plupload/wp-plupload.js

    diff --git src/js/_enqueues/vendor/plupload/wp-plupload.js src/js/_enqueues/vendor/plupload/wp-plupload.js
    index 217b3c09e2..0fdebf77d1 100644
    window.wp = window.wp || {}; 
    138138
    139139                        times = tryAgainCount[ file.id ];
    140140
    141                         if ( times && times > 8 ) {
     141                        if ( times && times > 4 ) {
    142142                                /*
    143143                                 * The file may have been uploaded and attachment post created,
    144144                                 * but post-processing and resizing failed...
  • src/wp-admin/includes/image.php

    diff --git src/wp-admin/includes/image.php src/wp-admin/includes/image.php
    index b0cffc504f..f937bdc2ff 100644
    function wp_crop_image( $src, $src_x, $src_y, $src_w, $src_h, $dst_w, $dst_h, $s 
    7171}
    7272
    7373/**
    74  * Compares the existing image sub-sizes (as saved in the attachment meta)
    75  * to the currently registered image sub-sizes, and returns the difference.
     74 * Compare the existing image sub-sizes (as saved in the attachment meta)
     75 * to the currently registered image sub-sizes, and return the difference.
    7676 *
    7777 * Registered sub-sizes that are larger than the image are skipped.
    7878 *
    7979 * @since 5.3.0
    80  * @since 6.1.0 The $mime_type parameter was added.
    8180 *
    82  * @param int    $attachment_id The image attachment post ID.
    83  * @param string $mime_type     Optional. The mime type to check for missing sizes. Default is the primary image mime.
     81 * @param int $attachment_id The image attachment post ID.
    8482 * @return array[] Associative array of arrays of image sub-size information for
    8583 *                 missing image sizes, keyed by image size name.
    8684 */
    87 function wp_get_missing_image_subsizes( $attachment_id, $mime_type = '' ) {
     85function wp_get_missing_image_subsizes( $attachment_id ) {
    8886        if ( ! wp_attachment_is_image( $attachment_id ) ) {
    8987                return array();
    9088        }
    9189
    92         $primary_mime_type = get_post_mime_type( get_post( $attachment_id ) );
    93         if ( ! $mime_type ) {
    94                 $mime_type = $primary_mime_type;
    95         }
    96 
    9790        $registered_sizes = wp_get_registered_image_subsizes();
    9891        $image_meta       = wp_get_attachment_metadata( $attachment_id );
    9992
    function wp_get_missing_image_subsizes( $attachment_id, $mime_type = '' ) { 
    136129         * However we keep the old sub-sizes with the previous dimensions
    137130         * as the image may have been used in an older post.
    138131         */
    139         $missing_sizes = array();
    140         foreach ( $possible_sizes as $size_name => $size_data ) {
    141                 if ( ! isset( $image_meta['sizes'][ $size_name ] ) ) {
    142                         $missing_sizes[ $size_name ] = $size_data;
    143                         continue;
    144                 }
    145 
    146                 if ( ( isset( $size_data['mime-type'] ) && $size_data['mime-type'] === $mime_type ) || isset( $size_data['sources'][ $mime_type ] ) ) {
    147                         continue;
    148                 }
    149 
    150                 $missing_sizes[ $size_name ] = $size_data;
    151         }
    152 
    153         // Filter secondary mime types to those sizes that are enabled.
    154         if ( $primary_mime_type !== $mime_type ) {
    155                 $missing_sizes = _wp_filter_image_sizes_additional_mime_type_support( $missing_sizes, $attachment_id );
    156         }
     132        $missing_sizes = array_diff_key( $possible_sizes, $image_meta['sizes'] );
    157133
    158134        /**
    159135         * Filters the array of missing image sub-sizes for an uploaded image.
    160136         *
    161137         * @since 5.3.0
    162          * @since 6.1.0 The $mime_type filter parameter was added.
    163138         *
    164139         * @param array[] $missing_sizes Associative array of arrays of image sub-size information for
    165140         *                               missing image sizes, keyed by image size name.
    166141         * @param array   $image_meta    The image meta data.
    167142         * @param int     $attachment_id The image attachment post ID.
    168          * @param string  $mime_type     The image mime type to get missing sizes for.
    169143         */
    170         return apply_filters( 'wp_get_missing_image_subsizes', $missing_sizes, $image_meta, $attachment_id, $mime_type );
     144        return apply_filters( 'wp_get_missing_image_subsizes', $missing_sizes, $image_meta, $attachment_id );
    171145}
    172146
    173147/**
    function wp_get_missing_image_subsizes( $attachment_id, $mime_type = '' ) { 
    175149 * create them and update the image meta data.
    176150 *
    177151 * @since 5.3.0
    178  * @since 6.1.0 Now supports additional mime types, creating the additional sub-sizes and 'full' sized images.
    179152 *
    180153 * @param int $attachment_id The image attachment post ID.
    181154 * @return array|WP_Error The updated image meta data array or WP_Error object
    function wp_update_image_subsizes( $attachment_id ) { 
    194167                        return new WP_Error( 'invalid_attachment', __( 'The attached file cannot be found.' ) );
    195168                }
    196169        } else {
    197                 // Get the primary and additional mime types to generate.
    198                 list( $primary_mime_type, $additional_mime_types ) = _wp_get_primary_and_additional_mime_types( $image_file, $attachment_id );
     170                $missing_sizes = wp_get_missing_image_subsizes( $attachment_id );
    199171
    200                 // Generate missing 'full' image files for additional mime types.
    201                 if ( ! empty( $additional_mime_types ) ) {
    202                         if ( isset( $image_meta['sources'] ) ) {
    203                                 $missing_mime_types = array_diff( $additional_mime_types, array_keys( $image_meta['sources'] ) );
    204                         } else {
    205                                 $missing_mime_types = $additional_mime_types;
    206                         }
    207                         if ( ! empty( $missing_mime_types ) ) {
    208                                 $image_meta = _wp_make_additional_mime_types( $missing_mime_types, $image_file, $image_meta, $attachment_id );
    209                         }
     172                if ( empty( $missing_sizes ) ) {
     173                        return $image_meta;
    210174                }
    211175
    212                 // Generate missing image sub-sizes for each mime type.
    213                 $all_mime_types = array_merge( array( $primary_mime_type ), $additional_mime_types );
    214                 foreach ( $all_mime_types as $mime_type ) {
    215                         $missing_sizes = wp_get_missing_image_subsizes( $attachment_id, $mime_type );
    216 
    217                         if ( empty( $missing_sizes ) ) {
    218                                 continue;
    219                         }
    220 
    221                         // This also updates the image meta.
    222                         $image_meta = _wp_make_subsizes( $missing_sizes, $image_file, $image_meta, $attachment_id, $mime_type );
    223                 }
     176                // This also updates the image meta.
     177                $image_meta = _wp_make_subsizes( $missing_sizes, $image_file, $image_meta, $attachment_id );
    224178        }
    225179
    226180        /** This filter is documented in wp-admin/includes/image.php */
    function _wp_image_meta_replace_original( $saved_data, $original_file, $image_me 
    268222}
    269223
    270224/**
    271  * Creates image mime variations and sub-sizes, adds the new data to the image meta `sizes` array, and updates the image metadata.
     225 * Creates image sub-sizes, adds the new data to the image meta `sizes` array, and updates the image metadata.
    272226 *
    273227 * Intended for use after an image is uploaded. Saves/updates the image metadata after each
    274228 * sub-size is created. If there was an error, it is added to the returned image metadata array.
    275229 *
    276230 * @since 5.3.0
    277  * @since 6.1.0 Generates sub-sizes in alternate mime types based on the `wp_image_mime_transforms` filter.
    278231 *
    279232 * @param string $file          Full path to the image file.
    280233 * @param int    $attachment_id Attachment ID to process.
    function wp_create_image_subsizes( $file, $attachment_id ) { 
    295248                'file'     => _wp_relative_upload_path( $file ),
    296249                'filesize' => wp_filesize( $file ),
    297250                'sizes'    => array(),
    298                 'sources'  => array(),
    299251        );
    300252
    301253        // Fetch additional metadata from EXIF/IPTC.
    function wp_create_image_subsizes( $file, $attachment_id ) { 
    305257                $image_meta['image_meta'] = $exif_meta;
    306258        }
    307259
    308         // Get the primary and additional mime types to generate.
    309         list( $primary_mime_type, $additional_mime_types ) = _wp_get_primary_and_additional_mime_types( $file, $attachment_id );
    310 
    311         list( $editor, $resized, $rotated ) = _wp_maybe_scale_and_rotate_image( $file, $attachment_id, $imagesize, $exif_meta, $primary_mime_type );
    312         if ( is_wp_error( $editor ) ) {
    313                 return $image_meta;
    314         }
    315         $suffix = _wp_get_image_suffix( $resized, $rotated );
    316 
    317         // Save image only if either it was modified or if the primary mime type is different from the original.
    318         if ( ! empty( $suffix ) || $primary_mime_type !== $imagesize['mime'] ) {
    319                 $saved = $editor->save( $editor->generate_filename( $suffix ) );
    320 
    321                 if ( ! is_wp_error( $saved ) ) {
    322                         $image_meta = _wp_image_meta_replace_original( $saved, $file, $image_meta, $attachment_id );
    323 
    324                         // If the image was rotated update the stored EXIF data.
    325                         if ( true === $rotated && ! empty( $image_meta['image_meta']['orientation'] ) ) {
    326                                 $image_meta['image_meta']['orientation'] = 1;
    327                         }
    328                 } else {
    329                         // TODO: Log errors.
    330                 }
    331         }
    332 
    333         // Set 'sources' for the primary mime type.
    334         $image_meta['sources'][ $primary_mime_type ] = _wp_get_sources_from_meta( $image_meta );
    335 
    336         /*
    337          * Initial save of the new metadata.
    338          * At this point the file was uploaded and moved to the uploads directory
    339          * but the image sub-sizes haven't been created yet and the `sizes` array is empty.
    340          */
    341         wp_update_attachment_metadata( $attachment_id, $image_meta );
    342 
    343         if ( ! empty( $additional_mime_types ) ) {
    344                 // Use the original file's exif_meta orientation and size information for secondary mime generation to ensure
    345                 // sub-sized images are correctly scaled and rotated.
    346 
    347                 // Save data.
    348                 $saved_meta                = array();
    349                 $saved_meta['orientation'] = $image_meta['image_meta']['orientation'];
    350                 $saved_meta['width']       = $image_meta['width'];
    351                 $saved_meta['height']      = $image_meta['height'];
    352 
    353                 // Temporarily set the image meta to the original file's meta.
    354                 $image_meta['image_meta']['orientation'] = $exif_meta['orientation'];
    355                 $image_meta['width']                     = $imagesize[0];
    356                 $image_meta['height']                    = $imagesize[1];
    357 
    358                 $image_meta = _wp_make_additional_mime_types( $additional_mime_types, $file, $image_meta, $attachment_id );
    359 
    360                 // Restore the saved meta data.
    361                 $image_meta['image_meta']['orientation'] = $saved_meta['orientation'];
    362                 $image_meta['width']                     = $saved_meta['width'];
    363                 $image_meta['height']                    = $saved_meta['height'];
    364 
    365         }
    366 
    367         $new_sizes = wp_get_registered_image_subsizes();
    368 
    369         /**
    370          * Filters the image sizes automatically generated when uploading an image.
    371          *
    372          * @since 2.9.0
    373          * @since 4.4.0 Added the `$image_meta` argument.
    374          * @since 5.3.0 Added the `$attachment_id` argument.
    375          *
    376          * @param array $new_sizes     Associative array of image sizes to be created.
    377          * @param array $image_meta    The image meta data: width, height, file, sizes, etc.
    378          * @param int   $attachment_id The attachment post ID for the image.
    379          */
    380         $new_sizes = apply_filters( 'intermediate_image_sizes_advanced', $new_sizes, $image_meta, $attachment_id );
    381 
    382         $image_meta = _wp_make_subsizes( $new_sizes, $file, $image_meta, $attachment_id, $primary_mime_type );
    383 
    384         // Filter secondary mime types to those sizes that are enabled.
    385         $new_sizes = _wp_filter_image_sizes_additional_mime_type_support( $new_sizes, $attachment_id );
    386 
    387         foreach ( $additional_mime_types as $additional_mime_type ) {
    388                 $image_meta = _wp_make_subsizes( $new_sizes, $file, $image_meta, $attachment_id, $additional_mime_type );
    389         }
    390 
    391         return $image_meta;
    392 }
    393 
    394 /**
    395  * Returns a WP_Image_Editor instance where the image file has been scaled and rotated as necessary.
    396  *
    397  * @since 6.1.0
    398  * @access private
    399  *
    400  * @param string     $file          Full path to the image file.
    401  * @param int        $attachment_id Attachment ID.
    402  * @param array      $imagesize     {
    403  *     Indexed array of the image width and height in pixels.
    404  *
    405  *     @type int $0 The image width.
    406  *     @type int $1 The image height.
    407  * }
    408  * @param array|null $exif_meta EXIF metadata if extracted from the image file.
    409  * @param string     $mime_type Output mime type.
    410  * @return array Array with three entries: The WP_Image_Editor instance, whether the image was resized, and whether the
    411  *               image was rotated (booleans). Each entry can alternatively be a WP_Error in case something went wrong.
    412  */
    413 function _wp_maybe_scale_and_rotate_image( $file, $attachment_id, $imagesize, $exif_meta, $mime_type ) {
    414         $resized = false;
    415         $rotated = false;
    416 
    417         $editor = wp_get_image_editor( $file, array( 'mime_type' => $mime_type ) );
    418         if ( is_wp_error( $editor ) ) {
    419                 // This image cannot be edited.
    420                 return array( $editor, $resized, $rotated );
    421         }
    422 
    423         if ( ! empty( $mime_type ) ) {
    424                 $editor->set_output_mime_type( $mime_type );
    425         }
    426 
    427260        // Do not scale (large) PNG images. May result in sub-sizes that have greater file size than the original. See #48736.
    428         if ( 'image/png' !== $mime_type ) {
     261        if ( 'image/png' !== $imagesize['mime'] ) {
     262
    429263                /**
    430264                 * Filters the "BIG image" threshold value.
    431265                 *
    function _wp_maybe_scale_and_rotate_image( $file, $attachment_id, $imagesize, $e 
    451285
    452286                // If the original image's dimensions are over the threshold,
    453287                // scale the image and use it as the "full" size.
    454                 if ( $threshold && ( $imagesize[0] > $threshold || $imagesize[1] > $threshold ) ) {
     288                if ( $threshold && ( $image_meta['width'] > $threshold || $image_meta['height'] > $threshold ) ) {
     289                        $editor = wp_get_image_editor( $file );
     290
     291                        if ( is_wp_error( $editor ) ) {
     292                                // This image cannot be edited.
     293                                return $image_meta;
     294                        }
     295
    455296                        // Resize the image.
    456297                        $resized = $editor->resize( $threshold, $threshold );
     298                        $rotated = null;
    457299
    458300                        // If there is EXIF data, rotate according to EXIF Orientation.
    459301                        if ( ! is_wp_error( $resized ) && is_array( $exif_meta ) ) {
    460                                 $rotated = $editor->maybe_exif_rotate();
     302                                $resized = $editor->maybe_exif_rotate();
     303                                $rotated = $resized;
     304                        }
     305
     306                        if ( ! is_wp_error( $resized ) ) {
     307                                // Append "-scaled" to the image file name. It will look like "my_image-scaled.jpg".
     308                                // This doesn't affect the sub-sizes names as they are generated from the original image (for best quality).
     309                                $saved = $editor->save( $editor->generate_filename( 'scaled' ) );
     310
     311                                if ( ! is_wp_error( $saved ) ) {
     312                                        $image_meta = _wp_image_meta_replace_original( $saved, $file, $image_meta, $attachment_id );
     313
     314                                        // If the image was rotated update the stored EXIF data.
     315                                        if ( true === $rotated && ! empty( $image_meta['image_meta']['orientation'] ) ) {
     316                                                $image_meta['image_meta']['orientation'] = 1;
     317                                        }
     318                                } else {
     319                                        // TODO: Log errors.
     320                                }
     321                        } else {
     322                                // TODO: Log errors.
    461323                        }
    462324                } elseif ( ! empty( $exif_meta['orientation'] ) && 1 !== (int) $exif_meta['orientation'] ) {
    463325                        // Rotate the whole original image if there is EXIF data and "orientation" is not 1.
     326
     327                        $editor = wp_get_image_editor( $file );
     328
     329                        if ( is_wp_error( $editor ) ) {
     330                                // This image cannot be edited.
     331                                return $image_meta;
     332                        }
     333
     334                        // Rotate the image.
    464335                        $rotated = $editor->maybe_exif_rotate();
    465                 }
    466         }
    467336
    468         return array( $editor, $resized, $rotated );
    469 }
     337                        if ( true === $rotated ) {
     338                                // Append `-rotated` to the image file name.
     339                                $saved = $editor->save( $editor->generate_filename( 'rotated' ) );
    470340
    471 /**
    472  * Gets the suffix to use for image files based on resizing and rotating.
    473  *
    474  * @since 6.1.0
    475  * @access private
    476  *
    477  * @param bool|WP_Error Whether the image was resized, or an error if resizing failed.
    478  * @param bool|WP_Error Whether the image was rotated, or an error if rotating failed.
    479  * @return string The suffix to use for the file name, or empty string if none.
    480  */
    481 function _wp_get_image_suffix( $resized, $rotated ) {
    482         if ( $resized && ! is_wp_error( $resized ) ) {
    483                 // Append "-scaled" to the image file name. It will look like "my_image-scaled.jpg".
    484                 // This doesn't affect the sub-sizes names as they are generated from the original image (for best quality).
    485                 return 'scaled';
    486         }
     341                                if ( ! is_wp_error( $saved ) ) {
     342                                        $image_meta = _wp_image_meta_replace_original( $saved, $file, $image_meta, $attachment_id );
    487343
    488         if ( true === $rotated ) {
    489                 // Append `-rotated` to the image file name.
    490                 return 'rotated';
     344                                        // Update the stored EXIF data.
     345                                        if ( ! empty( $image_meta['image_meta']['orientation'] ) ) {
     346                                                $image_meta['image_meta']['orientation'] = 1;
     347                                        }
     348                                } else {
     349                                        // TODO: Log errors.
     350                                }
     351                        }
     352                }
    491353        }
    492354
    493         if ( is_wp_error( $resized ) || is_wp_error( $rotated ) ) {
    494                 // TODO: Log errors.
    495         }
    496         return '';
    497 }
     355        /*
     356         * Initial save of the new metadata.
     357         * At this point the file was uploaded and moved to the uploads directory
     358         * but the image sub-sizes haven't been created yet and the `sizes` array is empty.
     359         */
     360        wp_update_attachment_metadata( $attachment_id, $image_meta );
    498361
    499 /**
    500  * Gets a sources array element from a meta.
    501  *
    502  * @since 6.1.0
    503  * @access private
    504  *
    505  * @param array $meta The meta to get the source from.
    506  * @return array The source array element.
    507  */
    508 function _wp_get_sources_from_meta( $meta ) {
    509         return array(
    510                 'file'     => isset( $meta['file'] ) ? wp_basename( $meta['file'] ) : '',
    511                 'filesize' => isset( $meta['filesize'] ) ? $meta['filesize'] : wp_filesize( $meta['path'] ),
    512         );
     362        $new_sizes = wp_get_registered_image_subsizes();
     363
     364        /**
     365         * Filters the image sizes automatically generated when uploading an image.
     366         *
     367         * @since 2.9.0
     368         * @since 4.4.0 Added the `$image_meta` argument.
     369         * @since 5.3.0 Added the `$attachment_id` argument.
     370         *
     371         * @param array $new_sizes     Associative array of image sizes to be created.
     372         * @param array $image_meta    The image meta data: width, height, file, sizes, etc.
     373         * @param int   $attachment_id The attachment post ID for the image.
     374         */
     375        $new_sizes = apply_filters( 'intermediate_image_sizes_advanced', $new_sizes, $image_meta, $attachment_id );
     376
     377        return _wp_make_subsizes( $new_sizes, $file, $image_meta, $attachment_id );
    513378}
    514379
    515380/**
    function _wp_get_sources_from_meta( $meta ) { 
    519384 * Errors are stored in the returned image metadata array.
    520385 *
    521386 * @since 5.3.0
    522  * @since 6.1.0 The $mime_type parameter was added.
    523387 * @access private
    524388 *
    525  * @param array  $new_sizes       Array defining what sizes to create.
    526  * @param string $file            Full path to the image file.
    527  * @param array  $image_meta      The attachment meta data array.
    528  * @param int    $attachment_id   Attachment ID to process.
    529  * @param string $mime_type       Optional. The mime type to check for missing sizes. Default is the image mime of $file.
     389 * @param array  $new_sizes     Array defining what sizes to create.
     390 * @param string $file          Full path to the image file.
     391 * @param array  $image_meta    The attachment meta data array.
     392 * @param int    $attachment_id Attachment ID to process.
    530393 * @return array The attachment meta data with updated `sizes` array. Includes an array of errors encountered while resizing.
    531394 */
    532 function _wp_make_subsizes( $new_sizes, $file, $image_meta, $attachment_id, $mime_type = '' ) {
     395function _wp_make_subsizes( $new_sizes, $file, $image_meta, $attachment_id ) {
    533396        if ( empty( $image_meta ) || ! is_array( $image_meta ) ) {
    534397                // Not an image attachment.
    535398                return array();
    536399        }
    537400
    538         if ( ! $mime_type ) {
    539                 $mime_type = wp_get_image_mime( $file );
    540         }
    541 
    542401        // Check if any of the new sizes already exist.
    543402        if ( isset( $image_meta['sizes'] ) && is_array( $image_meta['sizes'] ) ) {
    544403                foreach ( $image_meta['sizes'] as $size_name => $size_meta ) {
    function _wp_make_subsizes( $new_sizes, $file, $image_meta, $attachment_id, $mim 
    548407                         * To change the behavior, unset changed/mismatched sizes in the `sizes` array in image meta.
    549408                         */
    550409                        if ( array_key_exists( $size_name, $new_sizes ) ) {
    551                                 // Unset the size if it is either the required mime type already exists either as main mime type or
    552                                 // within sources.
    553                                 if ( $size_meta['mime-type'] === $mime_type || isset( $size_meta['sources'][ $mime_type ] ) ) {
    554                                         unset( $new_sizes[ $size_name ] );
    555                                 }
     410                                unset( $new_sizes[ $size_name ] );
    556411                        }
    557412                }
    558413        } else {
    function _wp_make_subsizes( $new_sizes, $file, $image_meta, $attachment_id, $mim 
    578433
    579434        $new_sizes = array_filter( array_merge( $priority, $new_sizes ) );
    580435
    581         $editor = wp_get_image_editor( $file, array( 'mime_type' => $mime_type ) );
     436        $editor = wp_get_image_editor( $file );
    582437
    583438        if ( is_wp_error( $editor ) ) {
    584439                // The image cannot be edited.
    585440                return $image_meta;
    586441        }
    587442
    588         $editor->set_output_mime_type( $mime_type );
    589 
    590443        // If stored EXIF data exists, rotate the source image before creating sub-sizes.
    591444        if ( ! empty( $image_meta['image_meta'] ) ) {
    592445                $rotated = $editor->maybe_exif_rotate();
    function _wp_make_subsizes( $new_sizes, $file, $image_meta, $attachment_id, $mim 
    604457                                // TODO: Log errors.
    605458                        } else {
    606459                                // Save the size meta value.
    607                                 if ( ! isset( $image_meta['sizes'][ $new_size_name ] ) ) {
    608                                         $image_meta['sizes'][ $new_size_name ] = $new_size_meta;
    609                                 } else {
    610                                         // Remove any newly generated images that are larger than the primary mime type.
    611                                         $new_size     = isset( $new_size_meta['filesize'] ) ? $new_size_meta['filesize'] : 0;
    612                                         $primary_size = isset( $image_meta['sizes'][ $new_size_name ]['filesize'] ) ? $image_meta['sizes'][ $new_size_name ]['filesize'] : 0;
    613 
    614                                         if ( $new_size && $primary_size && $new_size >= $primary_size ) {
    615                                                 wp_delete_file( dirname( $file ) . '/' . $new_size_meta['file'] );
    616                                                 continue;
    617                                         }
    618                                 }
    619                                 if ( ! isset( $image_meta['sizes'][ $new_size_name ]['sources'] ) ) {
    620                                         $image_meta['sizes'][ $new_size_name ]['sources'] = array();
    621                                 }
    622                                 $image_meta['sizes'][ $new_size_name ]['sources'][ $mime_type ] = _wp_get_sources_from_meta( $new_size_meta );
     460                                $image_meta['sizes'][ $new_size_name ] = $new_size_meta;
    623461                                wp_update_attachment_metadata( $attachment_id, $image_meta );
    624462                        }
    625463                }
    function _wp_make_subsizes( $new_sizes, $file, $image_meta, $attachment_id, $mim 
    628466                $created_sizes = $editor->multi_resize( $new_sizes );
    629467
    630468                if ( ! empty( $created_sizes ) ) {
    631                         foreach ( $created_sizes as $created_size_name => $created_size_meta ) {
    632 
    633                                 // Primary mime type is set in 'sizes' array.
    634                                 if ( ! isset( $image_meta['sizes'][ $created_size_name ] ) ) {
    635                                         $image_meta['sizes'][ $created_size_name ] = $created_size_meta;
    636                                 } else {
    637                                         // Remove any newly generated images that are larger than the primary mime type.
    638                                         $new_size     = isset( $created_size_meta['filesize'] ) ? $created_size_meta['filesize'] : 0;
    639                                         $primary_size = isset( $image_meta['sizes'][ $created_size_name ]['filesize'] ) ? $image_meta['sizes'][ $created_size_name ]['filesize'] : 0;
    640 
    641                                         if ( $new_size && $primary_size && $new_size >= $primary_size ) {
    642                                                 wp_delete_file( dirname( $file ) . '/' . $created_size_meta['file'] );
    643                                                 continue;
    644                                         }
    645                                 }
    646                                 if ( ! isset( $image_meta['sizes'][ $created_size_name ]['sources'] ) ) {
    647                                         $image_meta['sizes'][ $created_size_name ]['sources'] = array();
    648                                 }
    649                                 $image_meta['sizes'][ $created_size_name ]['sources'][ $mime_type ] = _wp_get_sources_from_meta( $created_size_meta );
    650                         }
    651                         wp_update_attachment_metadata( $attachment_id, $image_meta );
    652                 }
    653         }
    654 
    655         return $image_meta;
    656 }
    657 
    658 /**
    659  * Filters the list of image size objects that support secondary mime type output.
    660  *
    661  * @since 6.1.0
    662  *
    663  * @param array $sizes         Associative array of image sizes.
    664  * @param int   $attachment_id Attachment ID.
    665  * @return array $sizes Filtered $sizes with only those that support secondary mime type output.
    666  */
    667 function _wp_filter_image_sizes_additional_mime_type_support( $sizes, $attachment_id ) {
    668 
    669         // Include only the core sizes that do not rely on add_image_size(). Additional image sizes are opt-in.
    670         $enabled_sizes = array(
    671                 'thumbnail'      => true,
    672                 'medium'         => true,
    673                 'medium_large'   => true,
    674                 'large'          => true,
    675                 'post-thumbnail' => true,
    676         );
    677 
    678         /**
    679          * Filter the sizes that support secondary mime type output. Developers can use this
    680          * to control the output of additional mime type sub-sized images.
    681          *
    682          * @since 6.1.0
    683          *
    684          * @param array $enabled_sizes Map of size names and whether they support secondary mime type output.
    685          * @param int   $attachment_id Attachment ID.
    686          */
    687         $enabled_sizes = apply_filters( 'wp_image_sizes_with_additional_mime_type_support', $enabled_sizes, $attachment_id );
    688 
    689         // Filter supported sizes to only include enabled sizes.
    690         return array_intersect_key( $sizes, array_filter( $enabled_sizes ) );
    691 }
    692 
    693 /**
    694  * Low-level function to create full-size images in additional mime types.
    695  *
    696  * Updates the image meta after each mime type image is created.
    697  *
    698  * @since 6.1.0
    699  * @access private
    700  *
    701  * @param array  $new_mime_types Array defining what mime types to create.
    702  * @param string $file           Full path to the image file.
    703  * @param array  $image_meta     The attachment meta data array.
    704  * @param int    $attachment_id  Attachment ID to process.
    705  * @return array The attachment meta data with updated `sizes` array. Includes an array of errors encountered while resizing.
    706  */
    707 function _wp_make_additional_mime_types( $new_mime_types, $file, $image_meta, $attachment_id ) {
    708         $imagesize          = array(
    709                 $image_meta['width'],
    710                 $image_meta['height'],
    711         );
    712         $exif_meta          = isset( $image_meta['image_meta'] ) ? $image_meta['image_meta'] : null;
    713         $original_file_size = isset( $image_meta['filesize'] ) ? $image_meta['filesize'] : wp_filesize( $file );
    714 
    715         foreach ( $new_mime_types as $mime_type ) {
    716                 list( $editor, $resized, $rotated ) = _wp_maybe_scale_and_rotate_image( $file, $attachment_id, $imagesize, $exif_meta, $mime_type );
    717                 if ( is_wp_error( $editor ) ) {
    718                         // The image cannot be edited.
    719                         continue;
    720                 }
    721 
    722                 $suffix    = _wp_get_image_suffix( $resized, $rotated );
    723                 $extension = wp_get_default_extension_for_mime_type( $mime_type );
    724 
    725                 $saved = $editor->save( $editor->generate_filename( $suffix, null, $extension ) );
    726 
    727                 if ( is_wp_error( $saved ) ) {
    728                         // TODO: Log errors.
    729                 } else {
    730                         // If the saved image is larger than the original, discard it.
    731                         $filesize = isset( $saved['filesize'] ) ? $saved['filesize'] : wp_filesize( $saved['path'] );
    732                         if ( $filesize && $original_file_size && $filesize > $original_file_size ) {
    733                                 wp_delete_file( $saved['path'] );
    734                                 continue;
    735                         }
    736                         $image_meta['sources'][ $mime_type ] = _wp_get_sources_from_meta( $saved );
     469                        $image_meta['sizes'] = array_merge( $image_meta['sizes'], $created_sizes );
    737470                        wp_update_attachment_metadata( $attachment_id, $image_meta );
    738471                }
    739472        }
    function wp_generate_attachment_metadata( $attachment_id, $file ) { 
    827560                                 * @param array $uploaded         {
    828561                                 *     Information about the newly-uploaded file.
    829562                                 *
    830                                  *     @type string $file Filename of the newly-uploaded file.
    831                                  *     @type string $url  URL of the uploaded file.
    832                                  *     @type string $type File type.
     563                                 *     @type string $file  Filename of the newly-uploaded file.
     564                                 *     @type string $url   URL of the uploaded file.
     565                                 *     @type string $type  File type.
    833566                                 * }
    834567                                 */
    835568                                $image_attachment = apply_filters( 'attachment_thumbnail_args', $image_attachment, $metadata, $uploaded );
    function wp_generate_attachment_metadata( $attachment_id, $file ) { 
    897630                                        wp_update_attachment_metadata( $attachment_id, $metadata );
    898631
    899632                                        // Create sub-sizes saving the image meta after each.
    900                                         $metadata = _wp_make_subsizes( $merged_sizes, $image_file, $metadata, $attachment_id, '' );
     633                                        $metadata = _wp_make_subsizes( $merged_sizes, $image_file, $metadata, $attachment_id );
    901634                                }
    902635                        }
    903636                }
    function _copy_image_file( $attachment_id ) { 
    14241157
    14251158        return $dst_file;
    14261159}
    1427 
    1428 /**
    1429  * Returns an array with the list of valid mime types that a specific mime type should be converted into.
    1430  * For example an `image/jpeg` should be converted into an `image/jpeg` and `image/webp`. The first type
    1431  * is considered the primary output type for this image.
    1432  *
    1433  * Called for each uploaded image to determine the list of mime types that should be converted into. Then,
    1434  * called again for each image size as they are generated to check if the image should be converted into the mime type
    1435  * for that size.
    1436  *
    1437  * @since 6.1.0
    1438  *
    1439  * @param int    $attachment_id The attachment ID.
    1440  * @return array An array of valid mime types, where the key is the source file mime type and the list of mime types to
    1441  *               generate.
    1442  */
    1443 function wp_upload_image_mime_transforms( $attachment_id ) {
    1444         $default_image_mime_transforms = array(
    1445                 'image/jpeg' => array( 'image/jpeg', 'image/webp' ),
    1446                 'image/webp' => array( 'image/webp', 'image/jpeg' ),
    1447         );
    1448         $image_mime_transforms         = $default_image_mime_transforms;
    1449 
    1450         /**
    1451          * Filters the output mime types for a given input mime type and image size.
    1452          *
    1453          * @since 6.1.0
    1454          *
    1455          * @param array $image_mime_transforms A map with the valid mime transforms where the key is the source file mime type
    1456          *                                      and the value is one or more mime file types to generate.
    1457          * @param int   $attachment_id         The ID of the attachment where the hook was dispatched.
    1458          */
    1459         $image_mime_transforms = apply_filters( 'wp_upload_image_mime_transforms', $image_mime_transforms, $attachment_id );
    1460 
    1461         if ( ! is_array( $image_mime_transforms ) ) {
    1462                 return $default_image_mime_transforms;
    1463         }
    1464 
    1465         return array_map(
    1466                 function( $transforms_list ) {
    1467                         return (array) $transforms_list;
    1468                 },
    1469                 $image_mime_transforms
    1470         );
    1471 }
    1472 
    1473 /**
    1474  * Extracts the primary and additional mime output types for an image from the $image_mime_transforms.
    1475  *
    1476  * @since 6.1.0
    1477  * @access private
    1478  *
    1479  * @param string $file          Full path to the image file.
    1480  * @param int    $attachment_id Attachment ID to process.
    1481  * @return array An array with two entries, the primary mime type and the list of additional mime types.
    1482  */
    1483 function _wp_get_primary_and_additional_mime_types( $file, $attachment_id ) {
    1484         $image_mime_transforms = wp_upload_image_mime_transforms( $attachment_id );
    1485         $original_mime_type    = wp_get_image_mime( $file );
    1486         $output_mime_types     = isset( $image_mime_transforms[ $original_mime_type ] ) ? $image_mime_transforms[ $original_mime_type ] : array( $original_mime_type );
    1487 
    1488         // Exclude any output mime types that the system doesn't support.
    1489         $output_mime_types = array_values(
    1490                 array_filter(
    1491                         $output_mime_types,
    1492                         function( $mime_type ) {
    1493                                 return wp_image_editor_supports(
    1494                                         array(
    1495                                                 'mime_type' => $mime_type,
    1496                                         )
    1497                                 );
    1498                         }
    1499                 )
    1500         );
    1501 
    1502         // Handle an empty value for $output_mime_types: only output the original type.
    1503         if ( empty( $output_mime_types ) ) {
    1504                 return array( $original_mime_type, array() );
    1505         }
    1506 
    1507         // Use original mime type as primary mime type, or alternatively the first one.
    1508         $primary_mime_type_key = array_search( $original_mime_type, $output_mime_types, true );
    1509         if ( false === $primary_mime_type_key ) {
    1510                 $primary_mime_type_key = 0;
    1511         }
    1512         // Split output mime types into primary mime type and additional mime types.
    1513         $additional_mime_types     = $output_mime_types;
    1514         list( $primary_mime_type ) = array_splice( $additional_mime_types, $primary_mime_type_key, 1 );
    1515 
    1516         return array(
    1517                 $primary_mime_type,
    1518                 $additional_mime_types,
    1519         );
    1520 }
  • src/wp-includes/class-wp-image-editor.php

    diff --git src/wp-includes/class-wp-image-editor.php src/wp-includes/class-wp-image-editor.php
    index ccf43402a6..caa3092d36 100644
    abstract class WP_Image_Editor { 
    334334        protected function get_output_format( $filename = null, $mime_type = null ) {
    335335                $new_ext = null;
    336336
    337                 // If no mime type is passed but output mime type is set, use that.
    338                 if ( ! $mime_type && ! empty( $this->output_mime_type ) ) {
    339                         $mime_type = $this->output_mime_type;
    340                 }
    341 
    342337                // By default, assume specified type takes priority.
    343338                if ( $mime_type ) {
    344339                        $new_ext = $this->get_extension( $mime_type );
    abstract class WP_Image_Editor { 
    430425        }
    431426
    432427        /**
    433          * Builds an output filename based on current file, and adding proper suffix.
     428         * Builds an output filename based on current file, and adding proper suffix
    434429         *
    435430         * @since 3.5.0
    436          * @since 6.1.0 Skips adding a suffix when set to an empty string. When the
    437          *              file extension being generated doesn't match the image file extension,
    438          *              add the extension to the suffix
    439          *
    440          * @param string $suffix    Optional. Suffix to add to the filename. The default null
    441          *                          will result in a 'widthxheight' suffix. Passing
    442          *                          an empty string will result in no suffix.
    443          * @param string $dest_path Optional. The path to save the file to. The default null
    444          *                          will use the image file path.
    445          * @param string $extension Optional. The file extension to use. The default null
    446          *                          will use the image file extension.
    447          * @return string filename The generated file name.
     431         *
     432         * @param string $suffix
     433         * @param string $dest_path
     434         * @param string $extension
     435         * @return string filename
    448436         */
    449437        public function generate_filename( $suffix = null, $dest_path = null, $extension = null ) {
    450438                // $suffix will be appended to the destination filename, just before the extension.
    451                 if ( null === $suffix ) {
     439                if ( ! $suffix ) {
    452440                        $suffix = $this->get_suffix();
    453441                }
    454442
    abstract class WP_Image_Editor { 
    469457                        }
    470458                }
    471459
    472                 if ( empty( $suffix ) ) {
    473                         $suffix = '';
    474                 } else {
    475                         $suffix = "-{$suffix}";
    476                 }
    477 
    478                 // When the file extension being generated doesn't match the image file extension,
    479                 // add the extension to the suffix to ensure a unique file name. Prevents
    480                 // name conflicts when a single image type can have multiple extensions,
    481                 // eg. .jpg, .jpeg and .jpe are all valid JPEG extensions.
    482                 if ( ! empty( $extension ) && $extension !== $ext ) {
    483                         $suffix .= "-{$ext}";
    484                 }
    485 
    486                 return trailingslashit( $dir ) . "{$name}{$suffix}.{$new_ext}";
     460                return trailingslashit( $dir ) . "{$name}-{$suffix}.{$new_ext}";
    487461        }
    488462
    489463        /**
    abstract class WP_Image_Editor { 
    663637
    664638                return wp_get_default_extension_for_mime_type( $mime_type );
    665639        }
    666 
    667         /**
    668          * Set the editor output mime type, useful when outputting alternate mime types.
    669          *
    670          * Track that the mime type is set with the mime type set flag.
    671          *
    672          * @since 6.1.0
    673          *
    674          * @param string $output_mime_type The mime type to set.
    675          */
    676         public function set_output_mime_type( $output_mime_type ) {
    677                 $this->output_mime_type = $output_mime_type;
    678         }
    679 
    680         /**
    681          * Reset the mime type to the original file mime type.
    682          *
    683          * Reset the mime type set flag.
    684          *
    685          * @since 6.1.0
    686          */
    687         public function reset_output_mime_type() {
    688                 $this->output_mime_type = $this->mime_type;
    689         }
    690640}
     641
  • src/wp-includes/media.php

    diff --git src/wp-includes/media.php src/wp-includes/media.php
    index 456cd7c988..e398644178 100644
    function wp_filter_content_tags( $content, $context = null ) { 
    18521852                                $filtered_image = wp_img_tag_add_decoding_attr( $filtered_image, $context );
    18531853                        }
    18541854
    1855                         // Use alternate mime types when specified and available.
    1856                         if ( $attachment_id > 0 && _wp_in_front_end_context() ) {
    1857                                 $filtered_image = wp_image_use_alternate_mime_types( $filtered_image, $context, $attachment_id );
    1858                         }
    1859 
    18601855                        /**
    18611856                         * Filters an img tag within the content for a given context.
    18621857                         *
    function wp_filter_content_tags( $content, $context = null ) { 
    19031898        return $content;
    19041899}
    19051900
    1906 /**
    1907  * Use alternate mime type images in the front end content output when available.
    1908  *
    1909  * @since 6.1.0
    1910  *
    1911  * @param string $image         The HTML `img` tag where the attribute should be added.
    1912  * @param string $context       Additional context to pass to the filters.
    1913  * @param int    $attachment_id The attachment ID.
    1914  * @return string Converted `img` tag with `loading` attribute added.
    1915  */
    1916 function wp_image_use_alternate_mime_types( $image, $context, $attachment_id ) {
    1917         $metadata = wp_get_attachment_metadata( $attachment_id );
    1918         if ( empty( $metadata['file'] ) ) {
    1919                 return $image;
    1920         }
    1921 
    1922         // Only alter images with a `sources` attribute
    1923         if ( empty( $metadata['sources'] ) ) {
    1924                 return $image;
    1925         };
    1926 
    1927         $target_mimes = array( 'image/webp', 'image/jpeg' );
    1928 
    1929         /**
    1930          * Filter the content image mime type output selection and order.
    1931          *
    1932          * When outputting images in the content, the first mime type available will be used.
    1933          *
    1934          * @since 6.1.0
    1935          *
    1936          * @param array  $target_mimes  The image output mime type and order. Default is array( 'image/webp', 'image/jpeg' ).
    1937          * @param int    $attachment_id The attachment ID.
    1938          * @param string $context       Additional context to pass to the filters.
    1939          * @return array The filtered output mime type and order. Return an empty array to skip mime type substitution.
    1940          */
    1941         $target_mimes = apply_filters( 'wp_content_image_mimes', $target_mimes, $attachment_id, $context );
    1942 
    1943         if ( false === $target_mimes ) {
    1944                 return $image;
    1945         }
    1946 
    1947         // Find the appropriate size for the provided URL in the first available mime type.
    1948         foreach ( $target_mimes as $target_mime ) {
    1949                 // Handle full size image replacement.
    1950                 if ( ! empty( $metadata['sources'][ $target_mime ]['file'] ) ) {
    1951                         $src_filename = wp_basename( $metadata['file'] );
    1952 
    1953                         // This is the same MIME type as the original, so the entire $target_mime can be skipped.
    1954                         // Since it is already the preferred MIME type, the entire loop can be cancelled.
    1955                         if ( $metadata['sources'][ $target_mime ]['file'] === $src_filename ) {
    1956                                 break;
    1957                         }
    1958 
    1959                         $image = str_replace( $src_filename, $metadata['sources'][ $target_mime ]['file'], $image );
    1960 
    1961                         // The full size was replaced, so unset this entirely here so that in the next iteration it is no longer
    1962                         // considered, simply for a small performance optimization.
    1963                         unset( $metadata['sources'] );
    1964                 }
    1965 
    1966                 // Go through each image size and replace with the first available mime type version.
    1967                 foreach ( $metadata['sizes'] as $name => $size_data ) {
    1968                         // Check if size has an original file.
    1969                         if ( empty( $size_data['file'] ) ) {
    1970                                 continue;
    1971                         }
    1972 
    1973                         // Check if size has a source in the desired mime type.
    1974                         if ( empty( $size_data['sources'][ $target_mime ]['file'] ) ) {
    1975                                 continue;
    1976                         }
    1977 
    1978                         $src_filename = wp_basename( $size_data['file'] );
    1979 
    1980                         // This is the same MIME type as the original, so the entire $target_mime can be skipped.
    1981                         // Since it is already the preferred MIME type, the entire loop can be cancelled.
    1982                         if ( $size_data['sources'][ $target_mime ]['file'] === $src_filename ) {
    1983                                 break 2;
    1984                         }
    1985 
    1986                         // Found a match, replace with the new filename.
    1987                         $image = str_replace( $src_filename, $size_data['sources'][ $target_mime ]['file'], $image );
    1988 
    1989                         // This size was replaced, so unset this entirely here so that in the next iteration it is no longer
    1990                         // considered, simply for a small performance optimization.
    1991                         unset( $metadata['sizes'][ $name ] );
    1992                 }
    1993         }
    1994         return $image;
    1995 }
    1996 
    1997 /**
    1998  * Check if execution is currently in the front end content context, outside of <head>.
    1999  *
    2000  * @since 6.1.0
    2001  * @access private
    2002  *
    2003  * @return bool True if in the front end content context, false otherwise.
    2004  */
    2005 function _wp_in_front_end_context() {
    2006         global $wp_query;
    2007 
    2008         // Check if this request is generally outside (or before) any frontend context.
    2009         if ( ! isset( $wp_query ) || defined( 'XMLRPC_REQUEST' ) || defined( 'REST_REQUEST' ) || is_feed() ) {
    2010                 return false;
    2011         }
    2012 
    2013         // Check if we're anywhere before the 'wp_head' action has completed.
    2014         return did_action( 'template_redirect' ) && ! doing_action( 'wp_head' );
    2015 }
    2016 
    20171901/**
    20181902 * Adds `loading` attribute to an `img` HTML tag.
    20191903 *
  • src/wp-includes/post.php

    diff --git src/wp-includes/post.php src/wp-includes/post.php
    index 244047659d..6a0af16a8b 100644
    function wp_delete_attachment_files( $post_id, $meta, $backup_sizes, $file ) { 
    64866486                $intermediate_dir = path_join( $uploadpath['basedir'], dirname( $file ) );
    64876487
    64886488                foreach ( $meta['sizes'] as $size => $sizeinfo ) {
     6489                        $intermediate_file = str_replace( wp_basename( $file ), $sizeinfo['file'], $file );
    64896490
    6490                         // Check for alternate size mime types in the sizeinfo['sources'] array to delete.
    6491                         if ( isset( $sizeinfo['sources'] ) && is_array( $sizeinfo['sources'] ) ) {
    6492                                 foreach ( $sizeinfo['sources'] as $mime => $properties ) {
    6493                                         $intermediate_file = str_replace( wp_basename( $file ), $properties['file'], $file );
    6494                                         if ( ! empty( $intermediate_file ) ) {
    6495                                                 $intermediate_file = path_join( $uploadpath['basedir'], $intermediate_file );
    6496                                                 if ( ! wp_delete_file_from_directory( $intermediate_file, $intermediate_dir ) ) {
    6497                                                         $deleted = false;
    6498                                                 }
    6499                                         }
    6500                                 }
    6501                         } else {
    6502                                 // Otherwise, delete files from the sizeinfo data.
    6503                                 $intermediate_file = str_replace( wp_basename( $file ), $sizeinfo['file'], $file );
     6491                        if ( ! empty( $intermediate_file ) ) {
     6492                                $intermediate_file = path_join( $uploadpath['basedir'], $intermediate_file );
    65046493
    6505                                 if ( ! empty( $intermediate_file ) ) {
    6506                                         $intermediate_file = path_join( $uploadpath['basedir'], $intermediate_file );
    6507 
    6508                                         if ( ! wp_delete_file_from_directory( $intermediate_file, $intermediate_dir ) ) {
    6509                                                 $deleted = false;
    6510                                         }
     6494                                if ( ! wp_delete_file_from_directory( $intermediate_file, $intermediate_dir ) ) {
     6495                                        $deleted = false;
    65116496                                }
    65126497                        }
    65136498                }
    function wp_delete_attachment_files( $post_id, $meta, $backup_sizes, $file ) { 
    65296514                }
    65306515        }
    65316516
    6532         // Delete the full size images from 'sources' if available, or the root file.
    6533         if ( isset( $meta['sources'] ) && is_array( $meta['sources'] ) ) {
    6534                 $sources          = $meta['sources'];
    6535                 $intermediate_dir = path_join( $uploadpath['basedir'], dirname( $file ) );
    6536                 foreach ( $sources as $mime => $properties ) {
    6537                         if ( ! is_array( $properties ) || empty( $properties['file'] ) ) {
    6538                                 continue;
    6539                         }
    6540                         $intermediate_file = str_replace( wp_basename( $file ), $properties['file'], $file );
    6541                         if ( ! wp_delete_file_from_directory( $intermediate_file, $intermediate_dir ) ) {
    6542                                 $deleted = false;
    6543                         }
    6544                 }
    6545         } else {
    6546                 if ( ! wp_delete_file_from_directory( $file, $uploadpath['basedir'] ) ) {
    6547                         $deleted = false;
    6548                 }
    6549         }
    6550 
    65516517        if ( is_array( $backup_sizes ) ) {
    6552 
    65536518                $del_dir = path_join( $uploadpath['basedir'], dirname( $meta['file'] ) );
    6554                 // Delete the root (edited) file which was not deleted above.
    6555                 if ( ! wp_delete_file_from_directory( $file, $uploadpath['basedir'] ) ) {
    6556                         $deleted = false;
    6557                 }
     6519
    65586520                foreach ( $backup_sizes as $size ) {
    6559                         // Delete files from 'sources' data if available, otherwise from 'sizes' data.
    6560                         if ( isset( $meta['sources'] ) && is_array( $meta['sources'] ) ) {
    6561                                 // Delete any backup images stored in the 'sources' array.
    6562                                 if ( isset( $size['sources'] ) && is_array( $size['sources'] ) ) {
    6563                                         foreach ( $size['sources'] as $mime => $properties ) {
    6564                                                 $del_file = path_join( dirname( $meta['file'] ), $properties['file'] );
    6565                                                 if ( ! empty( $del_file ) ) {
    6566                                                         $del_file = path_join( $uploadpath['basedir'], $del_file );
    6567                                                         if ( ! wp_delete_file_from_directory( $del_file, $del_dir ) ) {
    6568                                                                 $deleted = false;
    6569                                                         }
    6570                                                 }
    6571                                         }
    6572                                 }
    6573                         } else {
    6574                                 $del_file = path_join( dirname( $meta['file'] ), $size['file'] );
     6521                        $del_file = path_join( dirname( $meta['file'] ), $size['file'] );
    65756522
    6576                                 if ( ! empty( $del_file ) ) {
    6577                                         $del_file = path_join( $uploadpath['basedir'], $del_file );
    6578                                         if ( ! wp_delete_file_from_directory( $del_file, $del_dir ) ) {
    6579                                                 $deleted = false;
    6580                                         }
     6523                        if ( ! empty( $del_file ) ) {
     6524                                $del_file = path_join( $uploadpath['basedir'], $del_file );
     6525
     6526                                if ( ! wp_delete_file_from_directory( $del_file, $del_dir ) ) {
     6527                                        $deleted = false;
    65816528                                }
    65826529                        }
    65836530                }
    65846531        }
    65856532
     6533        if ( ! wp_delete_file_from_directory( $file, $uploadpath['basedir'] ) ) {
     6534                $deleted = false;
     6535        }
     6536
    65866537        return $deleted;
    65876538}
    65886539
  • src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php

    diff --git src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php
    index fdb08e78bb..423347a721 100644
    class WP_REST_Attachments_Controller extends WP_REST_Posts_Controller { 
    783783                                        }
    784784
    785785                                        $size_data['source_url'] = $image_src[0];
    786 
    787                                         if ( empty( $size_data['sources'] ) || ! is_array( $size_data['sources'] ) ) {
    788                                                 continue;
    789                                         }
    790 
    791                                         $image_url_basename = wp_basename( $image_src[0] );
    792                                         foreach ( $size_data['sources'] as $mime => &$mime_details ) {
    793                                                 $mime_details['source_url'] = str_replace( $image_url_basename, $mime_details['file'], $image_src[0] );
    794                                         }
    795786                                }
    796787
    797788                                $full_src = wp_get_attachment_image_src( $post->ID, 'full' );
    class WP_REST_Attachments_Controller extends WP_REST_Posts_Controller { 
    804795                                                'mime_type'  => $post->post_mime_type,
    805796                                                'source_url' => $full_src[0],
    806797                                        );
    807 
    808                                         if ( ! empty( $data['media_details']['sources'] ) ) {
    809                                                 $full_url_basename = wp_basename( $full_src[0] );
    810                                                 foreach ( $data['media_details']['sources'] as $mime => &$mime_details ) {
    811                                                         $mime_details['source_url'] = str_replace( $full_url_basename, $mime_details['file'], $full_src[0] );
    812                                                 }
    813                                                 $data['media_details']['sizes']['full']['sources'] = $data['media_details']['sources'];
    814                                                 unset( $data['media_details']['sources'] );
    815                                         }
    816798                                }
    817799                        } else {
    818800                                $data['media_details']['sizes'] = new stdClass;
  • tests/phpunit/tests/image/editor.php

    diff --git tests/phpunit/tests/image/editor.php tests/phpunit/tests/image/editor.php
    index c051ffec2b..487dad0664 100644
    class Tests_Image_Editor extends WP_Image_UnitTestCase { 
    131131                $this->assertSame( 86, $editor->get_quality(), 'Output image format is WEBP. Quality setting for it should be 86.' );
    132132
    133133                // Removing PNG to WEBP conversion on save. Quality setting should reset to the default.
    134                 $editor->reset_output_mime_type();
    135134                remove_filter( 'image_editor_output_format', array( $this, 'image_editor_output_formats' ) );
    136135                $editor->save();
    137136                $this->assertSame( 82, $editor->get_quality(), 'After removing image conversion quality setting should reset to the default of 82.' );
    class Tests_Image_Editor extends WP_Image_UnitTestCase { 
    155154                $this->assertSame( 42, $editor->get_quality(), 'Image conversion from JPEG to WEBP. Filtered WEBP quality shoild be 42.' );
    156155
    157156                // After removing the conversion the quality setting should reset to the filtered value for the original image type, JPEG.
    158                 $editor->reset_output_mime_type();
    159157                remove_filter( 'image_editor_output_format', array( $this, 'image_editor_output_formats' ) );
    160158                $editor->save();
    161159                $this->assertSame(
    class Tests_Image_Editor extends WP_Image_UnitTestCase { 
    228226                $this->assertSame( trailingslashit( realpath( get_temp_dir() ) ), trailingslashit( realpath( dirname( $editor->generate_filename( null, get_temp_dir() ) ) ) ) );
    229227
    230228                // Test with a suffix only.
    231                 $this->assertSame( 'canola-100x50-jpg.png', wp_basename( $editor->generate_filename( null, null, 'png' ) ) );
     229                $this->assertSame( 'canola-100x50.png', wp_basename( $editor->generate_filename( null, null, 'png' ) ) );
    232230
    233231                // Combo!
    234                 $this->assertSame( trailingslashit( realpath( get_temp_dir() ) ) . 'canola-new-jpg.png', $editor->generate_filename( 'new', realpath( get_temp_dir() ), 'png' ) );
     232                $this->assertSame( trailingslashit( realpath( get_temp_dir() ) ) . 'canola-new.png', $editor->generate_filename( 'new', realpath( get_temp_dir() ), 'png' ) );
    235233
    236234                // Test with a stream destination.
    237235                $this->assertSame( 'file://testing/path/canola-100x50.jpg', $editor->generate_filename( null, 'file://testing/path' ) );
    class Tests_Image_Editor extends WP_Image_UnitTestCase { 
    364362                );
    365363        }
    366364
    367         /**
    368          * Test creating  the original image mime type when the image is uploaded.
    369          *
    370          * @ticket 55443
    371          *
    372          * @dataProvider provider_image_with_default_behaviors_during_upload
    373          */
    374         public function it_should_create_the_original_image_mime_type_when_the_image_is_uploaded( $file_location, $expected_mime, $targeted_mime ) {
    375                 $attachment_id = $this->factory->attachment->create_upload_object( $file_location );
    376 
    377                 $metadata = wp_get_attachment_metadata( $attachment_id );
    378 
    379                 $this->assertIsArray( $metadata );
    380                 foreach ( $metadata['sizes'] as $size_name => $properties ) {
    381                         $this->assertArrayHasKey( 'sources', $properties );
    382                         $this->assertIsArray( $properties['sources'] );
    383                         $this->assertArrayHasKey( $expected_mime, $properties['sources'] );
    384                         $this->assertArrayHasKey( 'filesize', $properties['sources'][ $expected_mime ] );
    385                         $this->assertArrayHasKey( 'file', $properties['sources'][ $expected_mime ] );
    386                         $this->assertArrayHasKey( $targeted_mime, $properties['sources'] );
    387                         $this->assertArrayHasKey( 'filesize', $properties['sources'][ $targeted_mime ] );
    388                         $this->assertArrayHasKey( 'file', $properties['sources'][ $targeted_mime ] );
    389                 }
    390         }
    391 
    392         /**
    393          * Data provider for it_should_create_the_original_image_mime_type_when_the_image_is_uploaded.
    394          */
    395         public function provider_image_with_default_behaviors_during_upload() {
    396                 yield 'JPEG image' => array(
    397                         DIR_TESTDATA . '/images/test-image.jpg',
    398                         'image/jpeg',
    399                         'image/webp',
    400                 );
    401 
    402                 yield 'WebP image' => array(
    403                         DIR_TESTDATA . '/images/webp-lossy.webp',
    404                         'image/webp',
    405                         'image/jpeg',
    406                 );
    407         }
    408 
    409         /**
    410          * Test Do not create the sources property if no transform is provided.
    411          *
    412          * @ticket 55443
    413          */
    414         public function it_should_not_create_the_sources_property_if_no_transform_is_provided() {
    415                 add_filter( 'wp_upload_image_mime_transforms', '__return_empty_array' );
    416 
    417                 $attachment_id = $this->factory->attachment->create_upload_object(
    418                         DIR_TESTDATA . '/images/test-image.jpg'
    419                 );
    420 
    421                 $metadata = wp_get_attachment_metadata( $attachment_id );
    422 
    423                 $this->assertIsArray( $metadata );
    424                 foreach ( $metadata['sizes'] as $size_name => $properties ) {
    425                         $this->assertArrayNotHasKey( 'sources', $properties );
    426                 }
    427         }
    428 
    429         /**
    430          * Test creating the sources property when no transform is available.
    431          *
    432          * @ticket 55443
    433          */
    434         public function it_should_create_the_sources_property_when_no_transform_is_available() {
    435                 add_filter(
    436                         'wp_upload_image_mime_transforms',
    437                         function () {
    438                                 return array( 'image/jpeg' => array() );
    439                         }
    440                 );
    441 
    442                 $attachment_id = $this->factory->attachment->create_upload_object(
    443                         DIR_TESTDATA . '/images/test-image.jpg'
    444                 );
    445 
    446                 $metadata = wp_get_attachment_metadata( $attachment_id );
    447 
    448                 $this->assertIsArray( $metadata );
    449                 foreach ( $metadata['sizes'] as $size_name => $properties ) {
    450                         $this->assertArrayHasKey( 'sources', $properties );
    451                         $this->assertIsArray( $properties['sources'] );
    452                         $this->assertArrayHasKey( 'image/jpeg', $properties['sources'] );
    453                         $this->assertArrayHasKey( 'filesize', $properties['sources']['image/jpeg'] );
    454                         $this->assertArrayHasKey( 'file', $properties['sources']['image/jpeg'] );
    455                         $this->assertArrayNotHasKey( 'image/webp', $properties['sources'] );
    456                 }
    457         }
    458 
    459         /**
    460          * Test not creating the sources property if the mime is not specified on the transforms images.
    461          *
    462          * @ticket 55443
    463          */
    464         public function it_should_not_create_the_sources_property_if_the_mime_is_not_specified_on_the_transforms_images() {
    465                 add_filter(
    466                         'wp_upload_image_mime_transforms',
    467                         function () {
    468                                 return array( 'image/jpeg' => array() );
    469                         }
    470                 );
    471 
    472                 $attachment_id = $this->factory->attachment->create_upload_object(
    473                         DIR_TESTDATA . '/images/webp-lossy.webp'
    474                 );
    475 
    476                 $metadata = wp_get_attachment_metadata( $attachment_id );
    477 
    478                 $this->assertIsArray( $metadata );
    479                 foreach ( $metadata['sizes'] as $size_name => $properties ) {
    480                         $this->assertArrayNotHasKey( 'sources', $properties );
    481                 }
    482         }
    483 
    484 
    485         /**
    486          * Test creating a WebP version with all the required properties.
    487          *
    488          * @ticket 55443
    489          */
    490         public function it_should_create_a_webp_version_with_all_the_required_properties() {
    491                 $attachment_id = $this->factory->attachment->create_upload_object(
    492                         DIR_TESTDATA . '/images/test-image.jpg'
    493                 );
    494 
    495                 $metadata = wp_get_attachment_metadata( $attachment_id );
    496                 $this->assertArrayHasKey( 'sources', $metadata['sizes']['thumbnail'] );
    497                 $this->assertArrayHasKey( 'image/jpeg', $metadata['sizes']['thumbnail']['sources'] );
    498                 $this->assertArrayHasKey( 'filesize', $metadata['sizes']['thumbnail']['sources']['image/jpeg'] );
    499                 $this->assertArrayHasKey( 'file', $metadata['sizes']['thumbnail']['sources']['image/jpeg'] );
    500                 $this->assertArrayHasKey( 'image/webp', $metadata['sizes']['thumbnail']['sources'] );
    501                 $this->assertArrayHasKey( 'filesize', $metadata['sizes']['thumbnail']['sources']['image/webp'] );
    502                 $this->assertArrayHasKey( 'file', $metadata['sizes']['thumbnail']['sources']['image/webp'] );
    503                 $this->assertStringEndsNotWith( '.jpeg', $metadata['sizes']['thumbnail']['sources']['image/webp']['file'] );
    504                 $this->assertStringEndsWith( '.webp', $metadata['sizes']['thumbnail']['sources']['image/webp']['file'] );
    505         }
    506 
    507         /**
    508          * Test removing `scaled` suffix from the generated filename.
    509          *
    510          * @ticket 55443
    511          */
    512         public function it_should_remove_scaled_suffix_from_the_generated_filename() {
    513                 // The leafs image is 1080 pixels wide with this filter we ensure a -scaled version is created.
    514                 add_filter(
    515                         'big_image_size_threshold',
    516                         function () {
    517                                 return 850;
    518                         }
    519                 );
    520 
    521                 $attachment_id = $this->factory->attachment->create_upload_object(
    522                         DIR_TESTDATA . '/images/test-image.jpg'
    523                 );
    524                 $metadata      = wp_get_attachment_metadata( $attachment_id );
    525                 $this->assertStringEndsWith( '-scaled.jpg', get_attached_file( $attachment_id ) );
    526                 $this->assertArrayHasKey( 'image/webp', $metadata['sizes']['medium']['sources'] );
    527                 $this->assertStringEndsNotWith( '-scaled.webp', $metadata['sizes']['medium']['sources']['image/webp']['file'] );
    528                 $this->assertStringEndsWith( '-300x200.webp', $metadata['sizes']['medium']['sources']['image/webp']['file'] );
    529         }
    530 
    531         /**
    532          * Test removing the generated webp images when the attachment is deleted.
    533          *
    534          * @ticket 55443
    535          */
    536         public function it_should_remove_the_generated_webp_images_when_the_attachment_is_deleted() {
    537                 // Make sure no editor is available.
    538                 $attachment_id = $this->factory->attachment->create_upload_object(
    539                         DIR_TESTDATA . '/images/test-image.jpg'
    540                 );
    541 
    542                 $file    = get_attached_file( $attachment_id, true );
    543                 $dirname = pathinfo( $file, PATHINFO_DIRNAME );
    544 
    545                 $this->assertIsString( $file );
    546                 $this->assertFileExists( $file );
    547 
    548                 $metadata = wp_get_attachment_metadata( $attachment_id );
    549                 $sizes    = array( 'thumbnail', 'medium' );
    550 
    551                 foreach ( $sizes as $size_name ) {
    552                         $this->assertArrayHasKey( 'image/webp', $metadata['sizes'][ $size_name ]['sources'] );
    553                         $this->assertArrayHasKey( 'file', $metadata['sizes'][ $size_name ]['sources']['image/webp'] );
    554                         $this->assertFileExists(
    555                                 path_join( $dirname, $metadata['sizes'][ $size_name ]['sources']['image/webp']['file'] )
    556                         );
    557                 }
    558 
    559                 wp_delete_attachment( $attachment_id );
    560 
    561                 foreach ( $sizes as $size_name ) {
    562                         $this->assertFileDoesNotExist(
    563                                 path_join( $dirname, $metadata['sizes'][ $size_name ]['sources']['image/webp']['file'] )
    564                         );
    565                 }
    566         }
    567 
    568         /**
    569          * Test removing the attached WebP version if the attachment is force deleted but empty trash day is not defined.
    570          *
    571          * @ticket 55443
    572          */
    573         public function it_should_remove_the_attached_webp_version_if_the_attachment_is_force_deleted_but_empty_trash_day_is_not_defined() {
    574                 // Make sure no editor is available.
    575                 $attachment_id = $this->factory->attachment->create_upload_object(
    576                         DIR_TESTDATA . '/images/test-image.jpg'
    577                 );
    578 
    579                 $file    = get_attached_file( $attachment_id, true );
    580                 $dirname = pathinfo( $file, PATHINFO_DIRNAME );
    581 
    582                 $this->assertIsString( $file );
    583                 $this->assertFileExists( $file );
    584 
    585                 $metadata = wp_get_attachment_metadata( $attachment_id );
    586 
    587                 $this->assertFileExists(
    588                         path_join( $dirname, $metadata['sizes']['thumbnail']['sources']['image/webp']['file'] )
    589                 );
    590 
    591                 wp_delete_attachment( $attachment_id, true );
    592 
    593                 $this->assertFileDoesNotExist(
    594                         path_join( $dirname, $metadata['sizes']['thumbnail']['sources']['image/webp']['file'] )
    595                 );
    596         }
    597 
    598         /**
    599          * Test removing the WebP version of the image if the image is force deleted and empty trash days is set to zero.
    600          *
    601          * @ticket 55443
    602          */
    603         public function it_should_remove_the_webp_version_of_the_image_if_the_image_is_force_deleted_and_empty_trash_days_is_set_to_zero() {
    604                 // Make sure no editor is available.
    605                 $attachment_id = $this->factory->attachment->create_upload_object(
    606                         DIR_TESTDATA . '/images/test-image.jpg'
    607                 );
    608 
    609                 $file    = get_attached_file( $attachment_id, true );
    610                 $dirname = pathinfo( $file, PATHINFO_DIRNAME );
    611 
    612                 $this->assertIsString( $file );
    613                 $this->assertFileExists( $file );
    614 
    615                 $metadata = wp_get_attachment_metadata( $attachment_id );
    616 
    617                 $this->assertFileExists(
    618                         path_join( $dirname, $metadata['sizes']['thumbnail']['sources']['image/webp']['file'] )
    619                 );
    620 
    621                 define( 'EMPTY_TRASH_DAYS', 0 );
    622 
    623                 wp_delete_attachment( $attachment_id, true );
    624 
    625                 $this->assertFileDoesNotExist(
    626                         path_join( $dirname, $metadata['sizes']['thumbnail']['sources']['image/webp']['file'] )
    627                 );
    628         }
    629 
    630         /**
    631          * Test avoiding the change of URLs of images that are not part of the media library.
    632          *
    633          * @ticket 55443
    634          */
    635         public function it_should_avoid_the_change_of_urls_of_images_that_are_not_part_of_the_media_library() {
    636                 $paragraph = '<p>Donec accumsan, sapien et <img src="https://ia600200.us.archive.org/16/items/SPD-SLRSY-1867/hubblesite_2001_06.jpg">, id commodo nisi sapien et est. Mauris nisl odio, iaculis vitae pellentesque nec.</p>';
    637 
    638                 $this->assertSame( $paragraph, webp_uploads_update_image_references( $paragraph ) );
    639         }
    640 
    641         /**
    642          * Test avoiding replacing not existing attachment IDs.
    643          *
    644          * @ticket 55443
    645          */
    646         public function it_should_avoid_replacing_not_existing_attachment_i_ds() {
    647                 $paragraph = '<p>Donec accumsan, sapien et <img class="wp-image-0" src="https://ia600200.us.archive.org/16/items/SPD-SLRSY-1867/hubblesite_2001_06.jpg">, id commodo nisi sapien et est. Mauris nisl odio, iaculis vitae pellentesque nec.</p>';
    648 
    649                 $this->assertSame( $paragraph, webp_uploads_update_image_references( $paragraph ) );
    650         }
    651 
    652         /**
    653          * Test preventing replacing a WebP image.
    654          *
    655          * @ticket 55443
    656          */
    657         public function it_should_test_preventing_replacing_a_webp_image() {
    658                 $attachment_id = $this->factory->attachment->create_upload_object(
    659                         DIR_TESTDATA . '/images/webp-lossy.webp'
    660                 );
    661 
    662                 $tag = wp_get_attachment_image( $attachment_id, 'medium', false, array( 'class' => "wp-image-{$attachment_id}" ) );
    663 
    664                 $this->assertSame( $tag, webp_uploads_img_tag_update_mime_type( $tag, 'the_content', $attachment_id ) );
    665         }
    666 
    667         /**
    668          * Test preventing replacing a jpg image if the image does not have the target class name.
    669          *
    670          * @ticket 55443
    671          */
    672         public function it_should_test_preventing_replacing_a_jpg_image_if_the_image_does_not_have_the_target_class_name() {
    673                 $attachment_id = $this->factory->attachment->create_upload_object(
    674                         DIR_TESTDATA . '/images/test-image.jpg'
    675                 );
    676 
    677                 $tag = wp_get_attachment_image( $attachment_id, 'medium' );
    678 
    679                 $this->assertSame( $tag, webp_uploads_update_image_references( $tag ) );
    680         }
    681 
    682         /**
    683          * Test replacing the references to a JPG image to a WebP version.
    684          *
    685          * @dataProvider provider_replace_images_with_different_extensions
    686          *
    687          * @ticket 55443
    688          */
    689         public function it_should_replace_the_references_to_a_jpg_image_to_a_webp_version( $image_path ) {
    690                 $attachment_id = $this->factory->attachment->create_upload_object( $image_path );
    691 
    692                 $tag          = wp_get_attachment_image( $attachment_id, 'medium', false, array( 'class' => "wp-image-{$attachment_id}" ) );
    693                 $expected_tag = $tag;
    694                 $metadata     = wp_get_attachment_metadata( $attachment_id );
    695                 foreach ( $metadata['sizes'] as $size => $properties ) {
    696                         $expected_tag = str_replace( $properties['sources']['image/jpeg']['file'], $properties['sources']['image/webp']['file'], $expected_tag );
    697                 }
    698 
    699                 $this->assertNotEmpty( $expected_tag );
    700                 $this->assertNotSame( $tag, $expected_tag );
    701                 $this->assertSame( $expected_tag, webp_uploads_img_tag_update_mime_type( $tag, 'the_content', $attachment_id ) );
    702         }
    703 
    704         public function provider_replace_images_with_different_extensions() {
    705                 yield 'An image with a .jpg extension' => array( DIR_TESTDATA . '/images/test-image.jpg' );
    706                 yield 'An image with a .jpeg extension' => array( DIR_TESTDATA . '/images/test-image.jpeg' );
    707         }
    708 
    709         /**
    710          * Test the full image size from the original mime type.
    711          *
    712          * @ticket 55443
    713          */
    714         public function it_should_contain_the_full_image_size_from_the_original_mime() {
    715                 $attachment_id = $this->factory->attachment->create_upload_object(
    716                         DIR_TESTDATA . '/images/test-image.jpg'
    717                 );
    718 
    719                 $tag = wp_get_attachment_image( $attachment_id, 'full', false, array( 'class' => "wp-image-{$attachment_id}" ) );
    720 
    721                 $expected = array(
    722                         'ext'  => 'jpg',
    723                         'type' => 'image/jpeg',
    724                 );
    725                 $this->assertSame( $expected, wp_check_filetype( get_attached_file( $attachment_id ) ) );
    726                 $this->assertContains( wp_basename( get_attached_file( $attachment_id ) ), webp_uploads_img_tag_update_mime_type( $tag, 'the_content', $attachment_id ) );
    727         }
    728 
    729         /**
    730          * Test preventing replacing an image with no available sources.
    731          *
    732          * @ticket 55443
    733          */
    734         public function it_should_prevent_replacing_an_image_with_no_available_sources() {
    735                 add_filter( 'wp_upload_image_mime_transforms', '__return_empty_array' );
    736 
    737                 $attachment_id = $this->factory->attachment->create_upload_object( DIR_TESTDATA . '/images/test-image.jpg' );
    738 
    739                 $tag = wp_get_attachment_image( $attachment_id, 'full', false, array( 'class' => "wp-image-{$attachment_id}" ) );
    740                 $this->assertSame( $tag, webp_uploads_img_tag_update_mime_type( $tag, 'the_content', $attachment_id ) );
    741         }
    742 
    743         /**
    744          * Test preventing update not supported images with no available sources.
    745          *
    746          * @dataProvider provider_it_should_prevent_update_not_supported_images_with_no_available_sources
    747          *
    748          * @ticket 55443
    749          */
    750         public function it_should_prevent_update_not_supported_images_with_no_available_sources( $image_path ) {
    751                 $attachment_id = $this->factory->attachment->create_upload_object( $image_path );
    752 
    753                 $this->assertIsNumeric( $attachment_id );
    754                 $tag = wp_get_attachment_image( $attachment_id, 'full', false, array( 'class' => "wp-image-{$attachment_id}" ) );
    755 
    756                 $this->assertSame( $tag, webp_uploads_img_tag_update_mime_type( $tag, 'the_content', $attachment_id ) );
    757         }
    758 
    759         /**
    760          * Data provider for it_should_prevent_update_not_supported_images_with_no_available_sources.
    761          */
    762         public function provider_it_should_prevent_update_not_supported_images_with_no_available_sources() {
    763                 yield 'PNG image' => array( DIR_TESTDATA . '/images/test-image.png' );
    764                 yield 'GIFT image' => array( DIR_TESTDATA . '/images/test-image.gif' );
    765         }
    766 
    767365}
  • tests/phpunit/tests/image/functions.php

    diff --git tests/phpunit/tests/image/functions.php tests/phpunit/tests/image/functions.php
    index cb5a7971c9..86d559145e 100644
    class Tests_Image_Functions extends WP_UnitTestCase { 
    639639                        $this->markTestSkipped( 'Rendering PDFs is not supported on this system.' );
    640640                }
    641641
    642                 // Use legacy JPEG output.
    643                 add_filter( 'wp_upload_image_mime_transforms', '__return_empty_array' );
    644 
    645642                $orig_file = DIR_TESTDATA . '/images/wordpress-gsoc-flyer.pdf';
    646643                $test_file = get_temp_dir() . 'wordpress-gsoc-flyer.pdf';
    647644                copy( $orig_file, $test_file );
    class Tests_Image_Functions extends WP_UnitTestCase { 
    680677                                        'height'    => 300,
    681678                                        'mime-type' => 'image/jpeg',
    682679                                        'filesize'  => wp_filesize( $temp_dir . 'wordpress-gsoc-flyer-pdf-232x300.jpg' ),
    683                                         'sources'   => array(
    684                                                 'image/jpeg' => array(
    685                                                         'file'     => 'wordpress-gsoc-flyer-pdf-232x300.jpg',
    686                                                         'filesize' => wp_filesize( $temp_dir . 'wordpress-gsoc-flyer-pdf-232x300.jpg' ),
    687                                                 ),
    688                                         ),
    689680                                ),
    690681                                'large'     => array(
    691682                                        'file'      => 'wordpress-gsoc-flyer-pdf-791x1024.jpg',
    class Tests_Image_Functions extends WP_UnitTestCase { 
    693684                                        'height'    => 1024,
    694685                                        'mime-type' => 'image/jpeg',
    695686                                        'filesize'  => wp_filesize( $temp_dir . 'wordpress-gsoc-flyer-pdf-791x1024.jpg' ),
    696                                         'sources'   => array(
    697                                                 'image/jpeg' => array(
    698                                                         'file'     => 'wordpress-gsoc-flyer-pdf-791x1024.jpg',
    699                                                         'filesize' => wp_filesize( $temp_dir . 'wordpress-gsoc-flyer-pdf-791x1024.jpg' ),
    700                                                 ),
    701                                         ),
    702687                                ),
    703688                                'thumbnail' => array(
    704689                                        'file'      => 'wordpress-gsoc-flyer-pdf-116x150.jpg',
    class Tests_Image_Functions extends WP_UnitTestCase { 
    706691                                        'height'    => 150,
    707692                                        'mime-type' => 'image/jpeg',
    708693                                        'filesize'  => wp_filesize( $temp_dir . 'wordpress-gsoc-flyer-pdf-116x150.jpg' ),
    709                                         'sources'   => array(
    710                                                 'image/jpeg' => array(
    711                                                         'file'     => 'wordpress-gsoc-flyer-pdf-116x150.jpg',
    712                                                         'filesize' => wp_filesize( $temp_dir . 'wordpress-gsoc-flyer-pdf-116x150.jpg' ),
    713                                                 ),
    714                                         ),
    715694                                ),
    716695                        ),
    717696                        'filesize' => wp_filesize( $test_file ),
    class Tests_Image_Functions extends WP_UnitTestCase { 
    723702                foreach ( $metadata['sizes'] as $size ) {
    724703                        unlink( $temp_dir . $size['file'] );
    725704                }
    726                 remove_filter( 'wp_upload_image_mime_transforms', '__return_empty_array' );
    727705        }
    728706
    729707        /**
    class Tests_Image_Functions extends WP_UnitTestCase { 
    738716
    739717                update_option( 'medium_crop', 1 );
    740718
    741                 // Use legacy JPEG output.
    742                 add_filter( 'wp_upload_image_mime_transforms', '__return_empty_array' );
    743 
    744719                $orig_file = DIR_TESTDATA . '/images/wordpress-gsoc-flyer.pdf';
    745720                $test_file = get_temp_dir() . 'wordpress-gsoc-flyer.pdf';
    746721                copy( $orig_file, $test_file );
    class Tests_Image_Functions extends WP_UnitTestCase { 
    779754                                        'height'    => 300,
    780755                                        'mime-type' => 'image/jpeg',
    781756                                        'filesize'  => wp_filesize( $temp_dir . 'wordpress-gsoc-flyer-pdf-300x300.jpg' ),
    782                                         'sources'   => array(
    783                                                 'image/jpeg' => array(
    784                                                         'file'     => 'wordpress-gsoc-flyer-pdf-300x300.jpg',
    785                                                         'filesize' => wp_filesize( $temp_dir . 'wordpress-gsoc-flyer-pdf-300x300.jpg' ),
    786                                                 ),
    787                                         ),
    788757                                ),
    789758                                'large'     => array(
    790759                                        'file'      => 'wordpress-gsoc-flyer-pdf-791x1024.jpg',
    class Tests_Image_Functions extends WP_UnitTestCase { 
    792761                                        'height'    => 1024,
    793762                                        'mime-type' => 'image/jpeg',
    794763                                        'filesize'  => wp_filesize( $temp_dir . 'wordpress-gsoc-flyer-pdf-791x1024.jpg' ),
    795                                         'sources'   => array(
    796                                                 'image/jpeg' => array(
    797                                                         'file'     => 'wordpress-gsoc-flyer-pdf-791x1024.jpg',
    798                                                         'filesize' => wp_filesize( $temp_dir . 'wordpress-gsoc-flyer-pdf-791x1024.jpg' ),
    799                                                 ),
    800                                         ),
    801 
    802764                                ),
    803765                                'thumbnail' => array(
    804766                                        'file'      => 'wordpress-gsoc-flyer-pdf-116x150.jpg',
    class Tests_Image_Functions extends WP_UnitTestCase { 
    806768                                        'height'    => 150,
    807769                                        'mime-type' => 'image/jpeg',
    808770                                        'filesize'  => wp_filesize( $temp_dir . 'wordpress-gsoc-flyer-pdf-116x150.jpg' ),
    809                                         'sources'   => array(
    810                                                 'image/jpeg' => array(
    811                                                         'file'     => 'wordpress-gsoc-flyer-pdf-116x150.jpg',
    812                                                         'filesize' => wp_filesize( $temp_dir . 'wordpress-gsoc-flyer-pdf-116x150.jpg' ),
    813                                                 ),
    814                                         ),
    815771                                ),
    816772                        ),
    817773                        'filesize' => wp_filesize( $test_file ),
    class Tests_Image_Functions extends WP_UnitTestCase { 
    823779                foreach ( $metadata['sizes'] as $size ) {
    824780                        unlink( $temp_dir . $size['file'] );
    825781                }
    826                 remove_filter( 'wp_upload_image_mime_transforms', '__return_empty_array' );
    827 
    828782        }
    829783
    830784        /**
    class Tests_Image_Functions extends WP_UnitTestCase { 
    835789                        $this->markTestSkipped( 'Rendering PDFs is not supported on this system.' );
    836790                }
    837791
    838                 // Use legacy JPEG output.
    839                 add_filter( 'wp_upload_image_mime_transforms', '__return_empty_array' );
    840 
    841792                $orig_file = DIR_TESTDATA . '/images/wordpress-gsoc-flyer.pdf';
    842793                $test_file = get_temp_dir() . 'wordpress-gsoc-flyer.pdf';
    843794                copy( $orig_file, $test_file );
    class Tests_Image_Functions extends WP_UnitTestCase { 
    870821                        'height'    => 100,
    871822                        'mime-type' => 'image/jpeg',
    872823                        'filesize'  => wp_filesize( $temp_dir . 'wordpress-gsoc-flyer-pdf-77x100.jpg' ),
    873                         'sources'   => array(
    874                                 'image/jpeg' => array(
    875                                         'file'     => 'wordpress-gsoc-flyer-pdf-77x100.jpg',
    876                                         'filesize' => wp_filesize( $temp_dir . 'wordpress-gsoc-flyer-pdf-77x100.jpg' ),
    877                                 ),
    878                         ),
    879824                );
    880825
    881826                // Different environments produce slightly different filesize results.
    class Tests_Image_Functions extends WP_UnitTestCase { 
    891836                foreach ( $metadata['sizes'] as $size ) {
    892837                        unlink( $temp_dir . $size['file'] );
    893838                }
    894                 remove_filter( 'wp_upload_image_mime_transforms', '__return_empty_array' );
    895839        }
    896840
    897841        public function filter_fallback_intermediate_image_sizes( $fallback_sizes, $metadata ) {
    class Tests_Image_Functions extends WP_UnitTestCase { 
    10821026                        ),
    10831027                );
    10841028        }
    1085 
    1086         /**
    1087          * @ticket 55443
    1088          */
    1089         public function test_wp_upload_image_mime_transforms_generates_webp_and_jpeg_for_both_by_default() {
    1090                 $result = wp_upload_image_mime_transforms( 42 );
    1091                 $this->assertArrayHasKey( 'image/jpeg', $result );
    1092                 $this->assertArrayHasKey( 'image/webp', $result );
    1093                 $this->assertSameSets( array( 'image/jpeg', 'image/webp' ), $result['image/jpeg'] );
    1094                 $this->assertSameSets( array( 'image/jpeg', 'image/webp' ), $result['image/webp'] );
    1095         }
    1096 
    1097         /**
    1098          * @ticket 55443
    1099          */
    1100         public function test_wp_upload_image_mime_transforms_filter_always_use_webp_instead_of_jpeg() {
    1101                 add_filter(
    1102                         'wp_upload_image_mime_transforms',
    1103                         function( $transforms ) {
    1104                                 // Ensure JPG only results in WebP files.
    1105                                 $transforms['image/jpeg'] = array( 'image/webp' );
    1106                                 // Unset WebP since it does not need any transformation in that case.
    1107                                 unset( $transforms['image/webp'] );
    1108                                 return $transforms;
    1109                         }
    1110                 );
    1111 
    1112                 $result = wp_upload_image_mime_transforms( 42 );
    1113                 $this->assertArrayHasKey( 'image/jpeg', $result );
    1114                 $this->assertArrayNotHasKey( 'image/webp', $result );
    1115                 $this->assertSameSets( array( 'image/webp' ), $result['image/jpeg'] );
    1116         }
    1117 
    1118         /**
    1119          * @ticket 55443
    1120          */
    1121         public function test_wp_upload_image_mime_transforms_filter_receives_parameters() {
    1122                 $attachment_id = null;
    1123                 add_filter(
    1124                         'wp_upload_image_mime_transforms',
    1125                         function( $transforms, $param1 ) use ( &$attachment_id ) {
    1126                                 $attachment_id = $param1;
    1127                                 return $transforms;
    1128                         },
    1129                         10,
    1130                         2
    1131                 );
    1132 
    1133                 wp_upload_image_mime_transforms( 23 );
    1134                 $this->assertSame( 23, $attachment_id );
    1135         }
    1136 
    1137         /**
    1138          * @ticket 55443
    1139          */
    1140         public function test_wp_upload_image_mime_transforms_filter_with_empty_array() {
    1141                 add_filter( 'wp_upload_image_mime_transforms', '__return_empty_array' );
    1142                 $result = wp_upload_image_mime_transforms( 42 );
    1143                 $this->assertSame( array(), $result );
    1144         }
    1145 
    1146         /**
    1147          * @ticket 55443
    1148          */
    1149         public function test_wp_upload_image_mime_transforms_filter_with_invalid_usage() {
    1150                 $default = wp_upload_image_mime_transforms( 42 );
    1151 
    1152                 add_filter( 'wp_upload_image_mime_transforms', '__return_false' );
    1153                 $result = wp_upload_image_mime_transforms( 42 );
    1154                 $this->assertSame( $default, $result );
    1155         }
    1156 
    1157         /**
    1158          * @ticket 55443
    1159          */
    1160         public function test__wp_get_primary_and_additional_mime_types_default() {
    1161                 $jpeg_file = DIR_TESTDATA . '/images/test-image-large.jpg';
    1162 
    1163                 list( $primary_mime_type, $additional_mime_types ) = _wp_get_primary_and_additional_mime_types( $jpeg_file, 42 );
    1164                 $this->assertSame( 'image/jpeg', $primary_mime_type );
    1165 
    1166                 // WebP may not be supported by the server, in which case it will be stripped from the results.
    1167                 if ( wp_image_editor_supports( array( 'mime_type' => 'image/webp' ) ) ) {
    1168                         $this->assertSame( array( 'image/webp' ), $additional_mime_types );
    1169                 } else {
    1170                         $this->assertSame( array(), $additional_mime_types );
    1171                 }
    1172         }
    1173 
    1174         /**
    1175          * @ticket 55443
    1176          */
    1177         public function test__wp_get_primary_and_additional_mime_types_prefer_original_mime() {
    1178                 $jpeg_file = DIR_TESTDATA . '/images/test-image-large.jpg';
    1179 
    1180                 // Set 'image/jpeg' only as secondary output MIME type.
    1181                 // Still, because it is the original, it should be chosen as primary over 'image/webp'.
    1182                 add_filter(
    1183                         'wp_upload_image_mime_transforms',
    1184                         function( $transforms ) {
    1185                                 $transforms['image/jpeg'] = array( 'image/webp', 'image/jpeg' );
    1186                                 return $transforms;
    1187                         }
    1188                 );
    1189 
    1190                 list( $primary_mime_type, $additional_mime_types ) = _wp_get_primary_and_additional_mime_types( $jpeg_file, 42 );
    1191                 $this->assertSame( 'image/jpeg', $primary_mime_type );
    1192 
    1193                 // WebP may not be supported by the server, in which case it will be stripped from the results.
    1194                 if ( wp_image_editor_supports( array( 'mime_type' => 'image/webp' ) ) ) {
    1195                         $this->assertSame( array( 'image/webp' ), $additional_mime_types );
    1196                 } else {
    1197                         $this->assertSame( array(), $additional_mime_types );
    1198                 }
    1199         }
    1200 
    1201         /**
    1202          * @ticket 55443
    1203          */
    1204         public function test__wp_get_primary_and_additional_mime_types_use_original_mime_when_no_transformation_rules() {
    1205                 $jpeg_file = DIR_TESTDATA . '/images/test-image-large.jpg';
    1206 
    1207                 // Strip all transformation rules.
    1208                 add_filter( 'wp_upload_image_mime_transforms', '__return_empty_array' );
    1209 
    1210                 list( $primary_mime_type, $additional_mime_types ) = _wp_get_primary_and_additional_mime_types( $jpeg_file, 42 );
    1211                 $this->assertSame( 'image/jpeg', $primary_mime_type );
    1212                 $this->assertSame( array(), $additional_mime_types );
    1213         }
    1214 
    1215         /**
    1216          * @ticket 55443
    1217          */
    1218         public function test__wp_get_primary_and_additional_mime_types_different_output_mime() {
    1219                 $jpeg_file = DIR_TESTDATA . '/images/test-image-large.jpg';
    1220 
    1221                 // Set 'image/webp' as the only output MIME type.
    1222                 // In that case, JPEG is not generated at all, so WebP becomes the primary MIME type.
    1223                 add_filter(
    1224                         'wp_upload_image_mime_transforms',
    1225                         function( $transforms ) {
    1226                                 $transforms['image/jpeg'] = array( 'image/webp' );
    1227                                 return $transforms;
    1228                         }
    1229                 );
    1230 
    1231                 list( $primary_mime_type, $additional_mime_types ) = _wp_get_primary_and_additional_mime_types( $jpeg_file, 42 );
    1232 
    1233                 // WebP may not be supported by the server, in which case it will fall back to the original MIME type.
    1234                 if ( wp_image_editor_supports( array( 'mime_type' => 'image/webp' ) ) ) {
    1235                         $this->assertSame( 'image/webp', $primary_mime_type );
    1236                 } else {
    1237                         $this->assertSame( 'image/jpeg', $primary_mime_type );
    1238                 }
    1239 
    1240                 $this->assertSame( array(), $additional_mime_types );
    1241         }
    1242 
    1243         /**
    1244          * @ticket 55443
    1245          */
    1246         public function test__wp_get_primary_and_additional_mime_types_different_output_mimes() {
    1247                 $jpeg_file = DIR_TESTDATA . '/images/test-image-large.jpg';
    1248 
    1249                 // Set 'image/webp' and 'image/avif' as output MIME types.
    1250                 // In that case, JPEG is not generated at all, with WebP being the primary MIME type and AVIF the secondary.
    1251                 add_filter(
    1252                         'wp_upload_image_mime_transforms',
    1253                         function( $transforms ) {
    1254                                 $transforms['image/jpeg'] = array( 'image/webp', 'image/avif' );
    1255                                 return $transforms;
    1256                         }
    1257                 );
    1258 
    1259                 list( $primary_mime_type, $additional_mime_types ) = _wp_get_primary_and_additional_mime_types( $jpeg_file, 42 );
    1260 
    1261                 // WebP may not be supported by the server, in which case it will fall back to the original MIME type.
    1262                 if ( wp_image_editor_supports( array( 'mime_type' => 'image/webp' ) ) ) {
    1263                         $this->assertSame( 'image/webp', $primary_mime_type );
    1264                 } else {
    1265                         $this->assertSame( 'image/jpeg', $primary_mime_type );
    1266                 }
    1267 
    1268                 // AVIF may not be supported by the server, in which case it will be stripped from the results.
    1269                 if ( wp_image_editor_supports( array( 'mime_type' => 'image/avif' ) ) ) {
    1270                         $this->assertSame( array( 'image/avif' ), $additional_mime_types );
    1271                 } else {
    1272                         $this->assertSame( array(), $additional_mime_types );
    1273                 }
    1274         }
    1275 
    1276         /**
    1277          * @ticket 55443
    1278          * @dataProvider data__wp_filter_image_sizes_additional_mime_type_support
    1279          */
    1280         public function test__wp_filter_image_sizes_additional_mime_type_support( $input_size_data, $filter_callback, $expected_size_names ) {
    1281                 remove_all_filters( 'wp_image_sizes_with_additional_mime_type_support' );
    1282                 if ( $filter_callback ) {
    1283                         add_filter( 'wp_image_sizes_with_additional_mime_type_support', $filter_callback );
    1284                 }
    1285 
    1286                 $expected_size_data = array_intersect_key( $input_size_data, array_flip( $expected_size_names ) );
    1287 
    1288                 $output_size_data = _wp_filter_image_sizes_additional_mime_type_support( $input_size_data, 42 );
    1289                 $this->assertEqualSetsWithIndex( $expected_size_data, $output_size_data );
    1290         }
    1291 
    1292         public function data__wp_filter_image_sizes_additional_mime_type_support() {
    1293                 $thumbnail_data    = array(
    1294                         'width'  => 150,
    1295                         'height' => 150,
    1296                         'crop'   => true,
    1297                 );
    1298                 $medium_data       = array(
    1299                         'width'  => 300,
    1300                         'height' => 300,
    1301                         'crop'   => false,
    1302                 );
    1303                 $medium_large_data = array(
    1304                         'width'  => 768,
    1305                         'height' => 0,
    1306                         'crop'   => false,
    1307                 );
    1308                 $large_data        = array(
    1309                         'width'  => 1024,
    1310                         'height' => 1024,
    1311                         'crop'   => false,
    1312                 );
    1313                 $custom_data       = array(
    1314                         'width'  => 512,
    1315                         'height' => 512,
    1316                         'crop'   => true,
    1317                 );
    1318 
    1319                 return array(
    1320                         array(
    1321                                 array(
    1322                                         'thumbnail'    => $thumbnail_data,
    1323                                         'medium'       => $medium_data,
    1324                                         'medium_large' => $medium_large_data,
    1325                                         'large'        => $large_data,
    1326                                 ),
    1327                                 null,
    1328                                 array( 'thumbnail', 'medium', 'medium_large', 'large' ),
    1329                         ),
    1330                         array(
    1331                                 array(
    1332                                         'thumbnail' => $thumbnail_data,
    1333                                         'medium'    => $medium_data,
    1334                                         'custom'    => $custom_data,
    1335                                 ),
    1336                                 null,
    1337                                 array( 'thumbnail', 'medium' ),
    1338                         ),
    1339                         array(
    1340                                 array(
    1341                                         'thumbnail'    => $thumbnail_data,
    1342                                         'medium'       => $medium_data,
    1343                                         'medium_large' => $medium_large_data,
    1344                                         'large'        => $large_data,
    1345                                 ),
    1346                                 function( $enabled_sizes ) {
    1347                                         unset( $enabled_sizes['medium_large'], $enabled_sizes['large'] );
    1348                                         return $enabled_sizes;
    1349                                 },
    1350                                 array( 'thumbnail', 'medium' ),
    1351                         ),
    1352                         array(
    1353                                 array(
    1354                                         'thumbnail'    => $thumbnail_data,
    1355                                         'medium'       => $medium_data,
    1356                                         'medium_large' => $medium_large_data,
    1357                                         'large'        => $large_data,
    1358                                 ),
    1359                                 function( $enabled_sizes ) {
    1360                                         $enabled_sizes['medium_large'] = false;
    1361                                         $enabled_sizes['large']        = false;
    1362                                         return $enabled_sizes;
    1363                                 },
    1364                                 array( 'thumbnail', 'medium' ),
    1365                         ),
    1366                         array(
    1367                                 array(
    1368                                         'thumbnail' => $thumbnail_data,
    1369                                         'medium'    => $medium_data,
    1370                                         'custom'    => $custom_data,
    1371                                 ),
    1372                                 function( $enabled_sizes ) {
    1373                                         unset( $enabled_sizes['medium'] );
    1374                                         $enabled_sizes['custom'] = true;
    1375                                         return $enabled_sizes;
    1376                                 },
    1377                                 array( 'thumbnail', 'custom' ),
    1378                         ),
    1379                 );
    1380         }
    1381 
    1382         /**
    1383          * Test the `_wp_maybe_scale_and_rotate_image()` function.
    1384          *
    1385          * @dataProvider data_test__wp_maybe_scale_and_rotate_image
    1386          *
    1387          * @ticket 55443
    1388          */
    1389         public function test__wp_maybe_scale_and_rotate_image( $file, $imagesize, $mime_type, $expected ) {
    1390                 if ( ! wp_image_editor_supports( array( 'mime_type' => $mime_type ) ) ) {
    1391                         $this->markTestSkipped( sprintf( 'This test requires %s support.', $mime_type ) );
    1392                 }
    1393 
    1394                 $attributes    = array( 'post_mime_type' => $mime_type );
    1395                 $attachment_id = $this->factory->attachment->create_object( $file, 0, $attributes );
    1396                 $exif_meta     = wp_read_image_metadata( $file );
    1397 
    1398                 list( $editor, $resized, $rotated ) = _wp_maybe_scale_and_rotate_image( $file, $attachment_id, $imagesize, $exif_meta, $mime_type );
    1399 
    1400                 $this->assertSame( $expected['rotated'], $rotated );
    1401                 $this->assertSame( $expected['resized'], $resized );
    1402                 $this->assertSame( $expected['size'], $editor->get_size() );
    1403         }
    1404 
    1405         /**
    1406          * Data provider for the `test__wp_maybe_scale_and_rotate_image()` test.
    1407          *
    1408          * @return array
    1409          */
    1410         public function data_test__wp_maybe_scale_and_rotate_image() {
    1411                 return array(
    1412 
    1413                         // Image that will be scaled.
    1414                         array(
    1415                                 DIR_TESTDATA . '/images/test-image-large.jpg',
    1416                                 array( 3000, 2250 ),
    1417                                 'image/jpeg',
    1418                                 array(
    1419                                         'rotated' => false,
    1420                                         'resized' => true,
    1421                                         'size'    => array(
    1422                                                 'width'  => 2560,
    1423                                                 'height' => 1920,
    1424                                         ),
    1425                                 ),
    1426                         ),
    1427 
    1428                         // Image that will not be scaled.
    1429                         array(
    1430                                 DIR_TESTDATA . '/images/canola.jpg',
    1431                                 array( 640, 480 ),
    1432                                 'image/jpeg',
    1433                                 array(
    1434                                         'rotated' => false,
    1435                                         'resized' => false,
    1436                                         'size'    => array(
    1437                                                 'width'  => 640,
    1438                                                 'height' => 480,
    1439                                         ),
    1440                                 ),
    1441                         ),
    1442 
    1443                         // Image that will be flipped.
    1444                         array(
    1445                                 DIR_TESTDATA . '/images/test-image-upside-down.jpg',
    1446                                 array( 600, 450 ),
    1447                                 'image/jpeg',
    1448                                 array(
    1449                                         'rotated' => true,
    1450                                         'resized' => false,
    1451                                         'size'    => array(
    1452                                                 'width'  => 600,
    1453                                                 'height' => 450,
    1454                                         ),
    1455                                 ),
    1456                         ),
    1457 
    1458                         // Image that will be rotated.
    1459                         array(
    1460                                 DIR_TESTDATA . '/images/test-image-rotated-90ccw.jpg',
    1461                                 array( 1200, 1800 ),
    1462                                 'image/jpeg',
    1463                                 array(
    1464                                         'rotated' => true,
    1465                                         'resized' => false,
    1466                                         'size'    => array(
    1467                                                 'width'  => 1800,
    1468                                                 'height' => 1200,
    1469                                         ),
    1470                                 ),
    1471                         ),
    1472 
    1473                         // Image that will not be rotated - WebP Exif is not supported in PHP.
    1474                         array(
    1475                                 DIR_TESTDATA . '/images/test-image-rotated-90cw.webp',
    1476                                 array( 1024, 768 ),
    1477                                 'image/webp',
    1478                                 array(
    1479                                         'rotated' => false,
    1480                                         'resized' => false,
    1481                                         'size'    => array(
    1482                                                 'width'  => 1024,
    1483                                                 'height' => 768,
    1484                                         ),
    1485                                 ),
    1486                         ),
    1487 
    1488                 );
    1489         }
    1490 
    1491         /**
    1492          * Test the `_wp_get_image_suffix()` function.
    1493          * @dataProvider data_test__wp_get_image_suffix
    1494          *
    1495          * @ticket 55443
    1496          */
    1497         public function test__wp_get_image_suffix( $resized, $rotated, $expected ) {
    1498                 $this->assertSame( $expected, _wp_get_image_suffix( $resized, $rotated ) );
    1499         }
    1500 
    1501         /**
    1502          * Data provider for the `test__wp_get_image_suffix()` test.
    1503          */
    1504         public function data_test__wp_get_image_suffix() {
    1505                 return array(
    1506                         array( false, false, '' ),
    1507                         array( true, false, 'scaled' ),
    1508                         array( false, true, 'rotated' ),
    1509                         array( true, true, 'scaled' ),
    1510                 );
    1511         }
    15121029}
  • tests/phpunit/tests/media.php

    diff --git tests/phpunit/tests/media.php tests/phpunit/tests/media.php
    index 7a1723af12..ba4bedf51e 100644
    EOF; 
    22552255                // Do not add width, height, and loading.
    22562256                add_filter( 'wp_img_tag_add_width_and_height_attr', '__return_false' );
    22572257                add_filter( 'wp_img_tag_add_loading_attr', '__return_false' );
    2258                 add_filter( 'wp_content_image_mimes', '__return_empty_array' );
    22592258
    22602259                $this->assertSame( $content_filtered, wp_filter_content_tags( $content_unfiltered ) );
    22612260
    22622261                remove_filter( 'wp_img_tag_add_width_and_height_attr', '__return_false' );
    22632262                remove_filter( 'wp_img_tag_add_loading_attr', '__return_false' );
    2264                 remove_filter( 'wp_content_image_mimes', '__return_empty_array' );
    2265 
    22662263        }
    22672264
    22682265        /**
    EOF; 
    22962293                $img = wp_img_tag_add_loading_attr( $img, 'test' );
    22972294                $img = wp_img_tag_add_decoding_attr( $img, 'the_content' );
    22982295                $img = preg_replace( '|<img ([^>]+) />|', '<img $1 ' . 'srcset="image2x.jpg 2x" />', $img );
    2299                 add_filter( 'wp_content_image_mimes', '__return_empty_array' );
    23002296
    23012297                // The content filter should return the image unchanged.
    23022298                $this->assertSame( $img, wp_filter_content_tags( $img ) );
    2303 
    2304                 remove_filter( 'wp_content_image_mimes', '__return_empty_array' );
    23052299        }
    23062300
    23072301        /**
    EOF; 
    23712365                add_filter( 'wp_img_tag_add_width_and_height_attr', '__return_false' );
    23722366                add_filter( 'wp_img_tag_add_srcset_and_sizes_attr', '__return_false' );
    23732367                add_filter( 'wp_img_tag_add_decoding_attr', '__return_false' );
    2374                 add_filter( 'wp_content_image_mimes', '__return_empty_array' );
    23752368
    23762369                add_filter(
    23772370                        'wp_content_img_tag',
    EOF; 
    24342427         * @requires function imagejpeg
    24352428         */
    24362429        public function test_wp_filter_content_tags_schemes() {
    2437                 add_filter( 'wp_content_image_mimes', '__return_empty_array' );
    24382430                $image_meta = wp_get_attachment_metadata( self::$large_id );
    24392431                $size_array = $this->get_image_size_array_from_meta( $image_meta, 'medium' );
    24402432
    EOF; 
    24802472                $actual = wp_filter_content_tags( $unfiltered );
    24812473
    24822474                $this->assertSame( $expected, $actual );
    2483                 remove_filter( 'wp_content_image_mimes', '__return_empty_array' );
    24842475        }
    24852476
    24862477        /**
    EOF; 
    29742965                // Do not add loading, srcset, and sizes.
    29752966                add_filter( 'wp_img_tag_add_loading_attr', '__return_false' );
    29762967                add_filter( 'wp_img_tag_add_srcset_and_sizes_attr', '__return_false' );
    2977                 add_filter( 'wp_content_image_mimes', '__return_empty_array' );
    29782968
    29792969                $this->assertSame( $content_filtered, wp_filter_content_tags( $content_unfiltered ) );
    29802970
    29812971                remove_filter( 'wp_img_tag_add_loading_attr', '__return_false' );
    29822972                remove_filter( 'wp_img_tag_add_srcset_and_sizes_attr', '__return_false' );
    2983                 remove_filter( 'wp_content_image_mimes', '__return_empty_array' );
    29842973        }
    29852974
    29862975        /**
    EOF; 
    30563045                // Do not add width, height, srcset, and sizes.
    30573046                add_filter( 'wp_img_tag_add_width_and_height_attr', '__return_false' );
    30583047                add_filter( 'wp_img_tag_add_srcset_and_sizes_attr', '__return_false' );
    3059                 add_filter( 'wp_content_image_mimes', '__return_empty_array' );
    30603048
    30613049                $this->assertSame( $content_filtered, wp_filter_content_tags( $content_unfiltered ) );
    30623050
    30633051                remove_filter( 'wp_img_tag_add_width_and_height_attr', '__return_false' );
    30643052                remove_filter( 'wp_img_tag_add_srcset_and_sizes_attr', '__return_false' );
    3065                 remove_filter( 'wp_content_image_mimes', '__return_empty_array' );
    30663053        }
    30673054
    30683055        /**
    EOF; 
    30913078                // Enable globally for all tags.
    30923079                add_filter( 'wp_lazy_loading_enabled', '__return_true' );
    30933080
    3094                 add_filter( 'wp_content_image_mimes', '__return_empty_array' );
    3095 
    30963081                $this->assertSame( $content_filtered, wp_filter_content_tags( $content_unfiltered ) );
    30973082                remove_filter( 'wp_lazy_loading_enabled', '__return_true' );
    30983083                remove_filter( 'wp_img_tag_add_srcset_and_sizes_attr', '__return_false' );
    3099                 remove_filter( 'wp_content_image_mimes', '__return_empty_array' );
    3100 
    31013084        }
    31023085
    31033086        /**
    EOF; 
    31223105                // Disable globally for all tags.
    31233106                add_filter( 'wp_lazy_loading_enabled', '__return_false' );
    31243107
    3125                 add_filter( 'wp_content_image_mimes', '__return_empty_array' );
    3126 
    31273108                $this->assertSame( $content, wp_filter_content_tags( $content ) );
    31283109                remove_filter( 'wp_lazy_loading_enabled', '__return_false' );
    31293110                remove_filter( 'wp_img_tag_add_srcset_and_sizes_attr', '__return_false' );
    3130                 remove_filter( 'wp_content_image_mimes', '__return_empty_array' );
    31313111        }
    31323112
    31333113        /**
    EOF; 
    35533533         */
    35543534        function test_wp_filter_content_tags_with_wp_get_loading_attr_default() {
    35553535                global $wp_query, $wp_the_query;
    3556                 add_filter( 'wp_content_image_mimes', '__return_empty_array' );
    35573536
    35583537                $img1         = get_image_tag( self::$large_id, '', '', '', 'large' );
    35593538                $iframe1      = '<iframe src="https://www.example.com" width="640" height="360"></iframe>';
    EOF; 
    35893568                        $content_filtered = wp_filter_content_tags( $content_unfiltered, 'the_content' );
    35903569                        remove_filter( 'wp_img_tag_add_srcset_and_sizes_attr', '__return_false' );
    35913570                }
    3592                 remove_filter( 'wp_content_image_mimes', '__return_empty_array' );
    35933571
    35943572                // After filtering, the first image should not be lazy-loaded while the other ones should be.
    35953573                $this->assertSame( $content_expected, $content_filtered );
    EOF; 
    36393617                // Clean up the above filter.
    36403618                remove_filter( 'wp_omit_loading_attr_threshold', '__return_null', 100 );
    36413619        }
    3642 
    3643         /**
    3644          * @ticket 55443
    3645          */
    3646         public function test_wp_image_use_alternate_mime_types_replaces_jpg_with_webp_where_available() {
    3647                 if ( ! wp_image_editor_supports( array( 'mime_type' => 'image/webp' ) ) ) {
    3648                         $this->markTestSkipped( 'This test requires WebP support.' );
    3649                 }
    3650 
    3651                 // The attachment $large_id is a JPEG image, so it gets WebP files generated by default.
    3652                 $tag          = wp_get_attachment_image( self::$large_id, 'full' );
    3653                 $expected_tag = $tag;
    3654 
    3655                 $metadata = wp_get_attachment_metadata( self::$large_id );
    3656                 foreach ( $metadata['sizes'] as $size => $properties ) {
    3657                         // Some sizes may not have WebP if the WebP file is larger than the JPEG for the size.
    3658                         if ( ! isset( $properties['sources']['image/webp'] ) ) {
    3659                                 continue;
    3660                         }
    3661                         $expected_tag = str_replace( $properties['sources']['image/jpeg']['file'], $properties['sources']['image/webp']['file'], $expected_tag );
    3662                 }
    3663                 // Same applies to the full size.
    3664                 if ( isset( $metadata['sources']['image/webp'] ) ) {
    3665                         $expected_tag = str_replace( $metadata['sources']['image/jpeg']['file'], $metadata['sources']['image/webp']['file'], $expected_tag );
    3666                 }
    3667 
    3668                 $this->assertNotSame( $tag, $expected_tag );
    3669                 $this->assertSame( $expected_tag, wp_image_use_alternate_mime_types( $tag, 'the_content', self::$large_id ) );
    3670         }
    3671 
    3672         /**
    3673          * @ticket 55443
    3674          */
    3675         public function test_wp_image_use_alternate_mime_types_does_not_replace_jpg_when_webp_is_not_available() {
    3676                 if ( ! wp_image_editor_supports( array( 'mime_type' => 'image/webp' ) ) ) {
    3677                         $this->markTestSkipped( 'This test requires WebP support.' );
    3678                 }
    3679 
    3680                 // The attachment $large_id is a JPEG image, so it gets WebP files generated by default.
    3681                 $tag = wp_get_attachment_image( self::$large_id, 'full' );
    3682 
    3683                 // Update attachment metadata as if the image had no WebP available for any sub-sizes and the full size.
    3684                 $metadata = wp_get_attachment_metadata( self::$large_id );
    3685                 foreach ( $metadata['sizes'] as $size => $properties ) {
    3686                         unset( $metadata['sizes'][ $size ]['sources']['image/webp'] );
    3687                 }
    3688                 unset( $metadata['sources']['image/webp'] );
    3689                 wp_update_attachment_metadata( self::$large_id, $metadata );
    3690 
    3691                 $this->assertSame( $tag, wp_image_use_alternate_mime_types( $tag, 'the_content', self::$large_id ) );
    3692         }
    3693 
    3694         /**
    3695          * @ticket 55443
    3696          */
    3697         public function test_wp_image_use_alternate_mime_types_still_replaces_jpg_subsizes_when_webp_is_not_available_for_full_size() {
    3698                 if ( ! wp_image_editor_supports( array( 'mime_type' => 'image/webp' ) ) ) {
    3699                         $this->markTestSkipped( 'This test requires WebP support.' );
    3700                 }
    3701 
    3702                 // The attachment $large_id is a JPEG image, so it gets WebP files generated by default.
    3703                 $tag          = wp_get_attachment_image( self::$large_id, 'full' );
    3704                 $expected_tag = $tag;
    3705 
    3706                 // Update attachment metadata as if the image had no WebP available for the full size.
    3707                 $metadata = wp_get_attachment_metadata( self::$large_id );
    3708                 unset( $metadata['sources']['image/webp'] );
    3709                 wp_update_attachment_metadata( self::$large_id, $metadata );
    3710 
    3711                 foreach ( $metadata['sizes'] as $size => $properties ) {
    3712                         // Some sizes may not have WebP if the WebP file is larger than the JPEG for the size.
    3713                         if ( ! isset( $properties['sources']['image/webp'] ) ) {
    3714                                 continue;
    3715                         }
    3716                         $expected_tag = str_replace( $properties['sources']['image/jpeg']['file'], $properties['sources']['image/webp']['file'], $expected_tag );
    3717                 }
    3718 
    3719                 $this->assertNotSame( $tag, $expected_tag );
    3720                 $this->assertSame( $expected_tag, wp_image_use_alternate_mime_types( $tag, 'the_content', self::$large_id ) );
    3721         }
    3722 
    3723         /**
    3724          * @ticket 55443
    3725          */
    3726         public function test_wp_image_use_alternate_mime_types_respects_wp_content_image_mimes_filter() {
    3727                 if ( ! wp_image_editor_supports( array( 'mime_type' => 'image/webp' ) ) ) {
    3728                         $this->markTestSkipped( 'This test requires WebP support.' );
    3729                 }
    3730 
    3731                 // The attachment $large_id is a JPEG image, so it gets WebP files generated by default.
    3732                 $tag = wp_get_attachment_image( self::$large_id, 'full' );
    3733 
    3734                 // Invalid filter value results in no changes to content.
    3735                 add_filter( 'wp_content_image_mimes', '__return_false' );
    3736                 $this->assertSame( $tag, wp_image_use_alternate_mime_types( $tag, 'the_content', self::$large_id ) );
    3737 
    3738                 // Empty array results in no changes to content.
    3739                 add_filter( 'wp_content_image_mimes', '__return_empty_array' );
    3740                 $this->assertSame( $tag, wp_image_use_alternate_mime_types( $tag, 'the_content', self::$large_id ) );
    3741 
    3742                 // Preferring JPEG over WebP results in no changes to content.
    3743                 add_filter(
    3744                         'wp_content_image_mimes',
    3745                         function() {
    3746                                 return array( 'image/jpeg', 'image/webp' );
    3747                         }
    3748                 );
    3749                 $this->assertSame( $tag, wp_image_use_alternate_mime_types( $tag, 'the_content', self::$large_id ) );
    3750         }
    3751 
    3752         /**
    3753          * @ticket 55443
    3754          */
    3755         public function test__wp_in_front_end_context_without_wp_query() {
    3756                 unset( $GLOBALS['wp_query'] );
    3757 
    3758                 $this->assertFalse( _wp_in_front_end_context() );
    3759         }
    3760 
    3761         /**
    3762          * @ticket 55443
    3763          */
    3764         public function test__wp_in_front_end_context_with_feed() {
    3765                 remove_all_actions( 'template_redirect' );
    3766                 do_action( 'template_redirect' );
    3767                 $GLOBALS['wp_query']->is_feed = true;
    3768 
    3769                 $this->assertFalse( _wp_in_front_end_context() );
    3770         }
    3771 
    3772         /**
    3773          * @ticket 55443
    3774          */
    3775         public function test__wp_in_front_end_context_before_and_after_template_redirect() {
    3776                 $result = _wp_in_front_end_context();
    3777 
    3778                 remove_all_actions( 'template_redirect' );
    3779                 do_action( 'template_redirect' );
    3780 
    3781                 $this->assertFalse( $result );
    3782                 $this->assertTrue( _wp_in_front_end_context() );
    3783         }
    3784 
    3785         /**
    3786          * @ticket 55443
    3787          */
    3788         public function test__wp_in_front_end_context_within_wp_head() {
    3789                 remove_all_actions( 'template_redirect' );
    3790                 do_action( 'template_redirect' );
    3791 
    3792                 // Call function within a 'wp_head' callback.
    3793                 remove_all_actions( 'wp_head' );
    3794                 $result = null;
    3795                 add_action(
    3796                         'wp_head',
    3797                         function() use ( &$result ) {
    3798                                 $result = _wp_in_front_end_context();
    3799                         }
    3800                 );
    3801                 do_action( 'wp_head' );
    3802 
    3803                 $this->assertFalse( $result );
    3804         }
    38053620}
    38063621
    38073622/**
  • tests/phpunit/tests/rest-api/rest-attachments-controller.php

    diff --git tests/phpunit/tests/rest-api/rest-attachments-controller.php tests/phpunit/tests/rest-api/rest-attachments-controller.php
    index 585b2b5b4f..106906ee2b 100644
    class WP_Test_REST_Attachments_Controller extends WP_Test_REST_Post_Type_Control 
    22622262                        }
    22632263                );
    22642264        }
    2265 
    2266         /**
    2267          * @ticket 55443
    2268          */
    2269         public function test_image_sources_to_rest_response() {
    2270 
    2271                 $attachment_id = self::factory()->attachment->create_upload_object( $this->test_file );
    2272                 $metadata      = wp_get_attachment_metadata( $attachment_id );
    2273                 $request       = new WP_REST_Request();
    2274                 $request['id'] = $attachment_id;
    2275                 $controller    = new WP_REST_Attachments_Controller( 'attachment' );
    2276                 $response      = $controller->get_item( $request );
    2277 
    2278                 $this->assertNotWPError( $response );
    2279 
    2280                 $data       = $response->get_data();
    2281                 $mime_types = array(
    2282                         'image/jpeg',
    2283                 );
    2284 
    2285                 if ( wp_image_editor_supports( array( 'mime_type' => 'image/webp' ) ) ) {
    2286                         array_push( $mime_types, 'image/webp' );
    2287                 }
    2288 
    2289                 foreach ( $data['media_details']['sizes'] as $size_name => $properties ) {
    2290                         if ( ! isset( $metadata['sizes'][ $size_name ]['sources'] ) ) {
    2291                                 continue;
    2292                         }
    2293 
    2294                         $this->assertArrayHasKey( 'sources', $properties );
    2295                         $this->assertIsArray( $properties['sources'] );
    2296 
    2297                         foreach ( $mime_types as $mime_type ) {
    2298                                 $this->assertArrayHasKey( $mime_type, $properties['sources'] );
    2299                                 $this->assertArrayHasKey( 'filesize', $properties['sources'][ $mime_type ] );
    2300                                 $this->assertArrayHasKey( 'file', $properties['sources'][ $mime_type ] );
    2301                                 $this->assertArrayHasKey( 'source_url', $properties['sources'][ $mime_type ] );
    2302                                 $this->assertNotFalse( filter_var( $properties['sources'][ $mime_type ]['source_url'], FILTER_VALIDATE_URL ) );
    2303                         }
    2304                 }
    2305                 $this->assertArrayNotHasKey( 'sources', $data['media_details'] );
    2306         }
    23072265}