WordPress.org

Make WordPress Core

Ticket #47873: 47873.diff

File 47873.diff, 14.0 KB (added by azaozz, 2 years ago)
  • src/wp-admin/includes/image.php

     
    141141                return $image_meta;
    142142        }
    143143
    144         $image_file = get_attached_file( $attachment_id );
     144        $image_file = wp_get_original_attachment_image( $attachment_id );
    145145
    146146        // This also updates the image meta.
    147147        return _wp_make_subsizes( $missing_sizes, $image_file, $image_meta, $attachment_id );
     
    156156 * @since 5.3.0
    157157 *
    158158 * @param string $file          Full path to the image file.
    159  * @param array  $image_meta    The attachment meta data array.
    160159 * @param int    $attachment_id Attachment Id to process.
    161160 * @return array The attachment metadata with updated `sizes` array. Includes an array of errors encountered while resizing.
    162161 */
    163 function wp_create_image_subsizes( $file, $image_meta, $attachment_id ) {
    164         if ( empty( $image_meta ) || ! isset( $image_meta['width'], $image_meta['height'] ) ) {
    165                 // New uploaded image.
    166                 $imagesize            = @getimagesize( $file );
    167                 $image_meta['width']  = $imagesize[0];
    168                 $image_meta['height'] = $imagesize[1];
     162function wp_create_image_subsizes( $file, $attachment_id ) {
     163        $imagesize  = @getimagesize( $file );
    169164
    170                 // Make the file path relative to the upload dir.
    171                 $image_meta['file'] = _wp_relative_upload_path( $file );
     165        // Default image meta
     166        $image_meta = array(
     167                'width'  => $imagesize[0],
     168                'height' => $imagesize[1],
     169                'file'   => _wp_relative_upload_path( $file ),
     170                'sizes'  => array(),
     171        );
    172172
    173                 // Fetch additional metadata from EXIF/IPTC.
    174                 $exif_meta = wp_read_image_metadata( $file );
     173        // Fetch additional metadata from EXIF/IPTC.
     174        $exif_meta = wp_read_image_metadata( $file );
    175175
    176                 if ( $exif_meta ) {
    177                         $image_meta['image_meta'] = $exif_meta;
     176        if ( $exif_meta ) {
     177                $image_meta['image_meta'] = $exif_meta;
     178        }
     179
     180        /**
     181         * Filters the "BIG image" threshold value.
     182         *
     183         * If the original image width or height is above the threshold, it will be scaled down. The threshold is
     184         * used as max width or height. The scaled down image will be used as the largest available size, including
     185         * the `_wp_attached_file` post meta value.
     186         *
     187         * Returning `false` from the filter callback will disable this behavior.
     188         *
     189         * @since 5.3.0
     190         *
     191         * @param array  $image_meta    The new image meta data array. Note that `sizes` is empty as sub-sizes
     192         *                              haven't been created yet.
     193         * @param string $file          Full path to the uploaded image file.
     194         * @param int    $attachment_id Attachment post ID.
     195         */
     196        $threshold = (int) apply_filters( 'big_image_size_threshold', 2560, $image_meta, $file, $attachment_id );
     197
     198        // If the original size is over the threshold, resize the image,
     199        // and use it as the "full" size.
     200        if ( $threshold && ( $image_meta['width'] > $threshold || $image_meta['height'] > $threshold ) ) {
     201                $editor = wp_get_image_editor( $file );
     202
     203                if ( is_wp_error( $editor ) ) {
     204                        // This image cannot be edited.
     205                        return $image_meta;
    178206                }
     207
     208                // Resize the image
     209                $resized = $editor->resize( $threshold, $threshold );
     210
     211                if ( ! is_wp_error( $resized ) ) {
     212                        // TODO: can EXIF rotate here.
     213                        // By default the editor will append `{width}x{height}` to the file name of the resized image.
     214                        // Perhaps append `-scaled` to the new image name to make it easy to recognize?.
     215                        $saved = $editor->save( $editor->generate_filename( 'scaled' ) );
     216
     217                        if ( ! is_wp_error( $saved ) ) {
     218                                $new_file = $saved['path'];
     219
     220                                // Update the attached file meta.
     221                                update_attached_file( $attachment_id, $new_file );
     222
     223                                // Width and height of the new image.
     224                                $image_meta['width']  = $saved['width'];
     225                                $image_meta['height'] = $saved['height'];
     226
     227                                // Make the file path relative to the upload dir.
     228                                $image_meta['file'] = _wp_relative_upload_path( $new_file );
     229
     230                                // Store the original image file name in image_meta.
     231                                $image_meta['original_image'] = wp_basename( $file );
     232                        }
     233                }
    179234        }
    180235
    181236        $new_sizes = wp_get_registered_image_subsizes();
     
    226281                $image_meta['sizes'] = array();
    227282        }
    228283
    229         if ( ! empty( $new_sizes ) ) {
    230                 // Sort the image sub-sizes in order of priority when creating them.
    231                 // This ensures there is an appropriate sub-size the user can access immediately
    232                 // even when there was an error and not all sub-sizes were created.
    233                 $priority = array(
    234                         'medium'       => null,
    235                         'large'        => null,
    236                         'thumbnail'    => null,
    237                         'medium_large' => null,
    238                 );
     284        if ( empty( $new_sizes ) ) {
     285                // Nothing to do...
     286                return $image_meta;
     287        }
    239288
    240                 $new_sizes = array_filter( array_merge( $priority, $new_sizes ) );
     289        // Sort the image sub-sizes in order of priority when creating them.
     290        // This ensures there is an appropriate sub-size the user can access immediately
     291        // even when there was an error and not all sub-sizes were created.
     292        $priority = array(
     293                'medium'       => null,
     294                'large'        => null,
     295                'thumbnail'    => null,
     296                'medium_large' => null,
     297        );
    241298
    242                 $editor = wp_get_image_editor( $file );
     299        $new_sizes = array_filter( array_merge( $priority, $new_sizes ) );
    243300
    244                 if ( ! is_wp_error( $editor ) ) {
    245                         if ( method_exists( $editor, 'make_subsize' ) ) {
    246                                 foreach ( $new_sizes as $new_size_name => $new_size_data ) {
    247                                         $new_size_meta = $editor->make_subsize( $new_size_data );
     301        $editor = wp_get_image_editor( $file );
    248302
    249                                         if ( is_wp_error( $new_size_meta ) ) {
    250                                                 $error_code = $new_size_meta->get_error_code();
     303        if ( is_wp_error( $editor ) ) {
     304                // The image cannot be edited.
     305                return $image_meta;
     306        }
    251307
    252                                                 if ( $error_code === 'error_getting_dimensions' ) {
    253                                                         // Ignore errors when `image_resize_dimensions()` returns false.
    254                                                         // They mean that the requested size is larger than the original image and should be skipped.
    255                                                         continue;
    256                                                 }
     308        if ( method_exists( $editor, 'make_subsize' ) ) {
     309                foreach ( $new_sizes as $new_size_name => $new_size_data ) {
     310                        $new_size_meta = $editor->make_subsize( $new_size_data );
    257311
    258                                                 if ( empty( $image_meta['subsize_errors'] ) ) {
    259                                                         $image_meta['subsize_errors'] = array();
    260                                                 }
     312                        if ( is_wp_error( $new_size_meta ) ) {
     313                                $error_code = $new_size_meta->get_error_code();
    261314
    262                                                 $error = array(
    263                                                         'error_code'    => $error_code,
    264                                                         'error_message' => $new_size_meta->get_error_message(),
    265                                                 );
     315                                if ( $error_code === 'error_getting_dimensions' ) {
     316                                        // Ignore errors when `image_resize_dimensions()` returns false.
     317                                        // They mean that the requested size is larger than the original image and should be skipped.
     318                                        continue;
     319                                }
    266320
    267                                                 // Store the error code and error message for displaying in the UI.
    268                                                 $image_meta['subsize_errors'][ $new_size_name ] = $error;
    269                                         } else {
    270                                                 // The sub-size was created successfully.
    271                                                 // Clear out previous errors in creating this subsize.
    272                                                 if ( ! empty( $image_meta['subsize_errors'][ $new_size_name ] ) ) {
    273                                                         unset( $image_meta['subsize_errors'][ $new_size_name ] );
    274                                                 }
     321                                if ( empty( $image_meta['subsize_errors'] ) ) {
     322                                        $image_meta['subsize_errors'] = array();
     323                                }
    275324
    276                                                 if ( empty( $image_meta['subsize_errors'] ) ) {
    277                                                         unset( $image_meta['subsize_errors'] );
    278                                                 }
     325                                $error = array(
     326                                        'error_code'    => $error_code,
     327                                        'error_message' => $new_size_meta->get_error_message(),
     328                                );
    279329
    280                                                 // Save the size meta value.
    281                                                 $image_meta['sizes'][ $new_size_name ] = $new_size_meta;
    282                                         }
    283 
    284                                         wp_update_attachment_metadata( $attachment_id, $image_meta );
     330                                // Store the error code and error message for displaying in the UI.
     331                                $image_meta['subsize_errors'][ $new_size_name ] = $error;
     332                        } else {
     333                                // The sub-size was created successfully.
     334                                // Clear out previous errors in creating this subsize.
     335                                if ( ! empty( $image_meta['subsize_errors'][ $new_size_name ] ) ) {
     336                                        unset( $image_meta['subsize_errors'][ $new_size_name ] );
    285337                                }
    286                         } else {
    287                                 // Fall back to `$editor->multi_resize()`.
    288                                 $created_sizes = $editor->multi_resize( $new_sizes );
    289338
    290                                 if ( ! empty( $created_sizes ) ) {
    291                                         $image_meta['sizes'] = array_merge( $image_meta['sizes'], $created_sizes );
     339                                if ( empty( $image_meta['subsize_errors'] ) ) {
    292340                                        unset( $image_meta['subsize_errors'] );
    293                                         wp_update_attachment_metadata( $attachment_id, $image_meta );
    294341                                }
     342
     343                                // Save the size meta value.
     344                                $image_meta['sizes'][ $new_size_name ] = $new_size_meta;
    295345                        }
     346
     347                        wp_update_attachment_metadata( $attachment_id, $image_meta );
    296348                }
     349        } else {
     350                // Fall back to `$editor->multi_resize()`.
     351                $created_sizes = $editor->multi_resize( $new_sizes );
     352
     353                if ( ! empty( $created_sizes ) ) {
     354                        $image_meta['sizes'] = array_merge( $image_meta['sizes'], $created_sizes );
     355                        unset( $image_meta['subsize_errors'] );
     356                        wp_update_attachment_metadata( $attachment_id, $image_meta );
     357                }
    297358        }
    298359
    299360        return $image_meta;
     
    317378
    318379        if ( preg_match( '!^image/!', $mime_type ) && file_is_displayable_image( $file ) ) {
    319380                // Make thumbnails and other intermediate sizes.
    320                 $metadata = wp_create_image_subsizes( $file, $metadata, $attachment_id );
     381                $metadata = wp_create_image_subsizes( $file, $attachment_id );
    321382        } elseif ( wp_attachment_is( 'video', $attachment ) ) {
    322383                $metadata = wp_read_video_metadata( $file );
    323384                $support  = current_theme_supports( 'post-thumbnails', 'attachment:video' ) || post_type_supports( 'attachment:video', 'thumbnail' );
  • src/wp-includes/post.php

     
    55745574                // Don't delete the thumb if another attachment uses it.
    55755575                if ( ! $wpdb->get_row( $wpdb->prepare( "SELECT meta_id FROM $wpdb->postmeta WHERE meta_key = '_wp_attachment_metadata' AND meta_value LIKE %s AND post_id <> %d", '%' . $wpdb->esc_like( $meta['thumb'] ) . '%', $post_id ) ) ) {
    55765576                        $thumbfile = str_replace( wp_basename( $file ), $meta['thumb'], $file );
     5577
    55775578                        if ( ! empty( $thumbfile ) ) {
    55785579                                $thumbfile = path_join( $uploadpath['basedir'], $thumbfile );
    55795580                                $thumbdir  = path_join( $uploadpath['basedir'], dirname( $file ) );
     
    55885589        // Remove intermediate and backup images if there are any.
    55895590        if ( isset( $meta['sizes'] ) && is_array( $meta['sizes'] ) ) {
    55905591                $intermediate_dir = path_join( $uploadpath['basedir'], dirname( $file ) );
     5592
    55915593                foreach ( $meta['sizes'] as $size => $sizeinfo ) {
    55925594                        $intermediate_file = str_replace( wp_basename( $file ), $sizeinfo['file'], $file );
     5595
    55935596                        if ( ! empty( $intermediate_file ) ) {
    55945597                                $intermediate_file = path_join( $uploadpath['basedir'], $intermediate_file );
    55955598
     
    56005603                }
    56015604        }
    56025605
     5606        if ( ! empty( $meta['original_image'] ) ) {
     5607                if ( empty( $intermediate_dir ) ) {
     5608                        $intermediate_dir = path_join( $uploadpath['basedir'], dirname( $file ) );
     5609                }
     5610
     5611                $original_image = str_replace( wp_basename( $file ), $meta['original_image'], $file );
     5612
     5613                if ( ! empty( $original_image ) ) {
     5614                        $original_image = path_join( $uploadpath['basedir'], $original_image );
     5615
     5616                        if ( ! wp_delete_file_from_directory( $original_image, $intermediate_dir ) ) {
     5617                                $deleted = false;
     5618                        }
     5619                }
     5620        }
     5621
    56035622        if ( is_array( $backup_sizes ) ) {
    56045623                $del_dir = path_join( $uploadpath['basedir'], dirname( $meta['file'] ) );
     5624
    56055625                foreach ( $backup_sizes as $size ) {
    56065626                        $del_file = path_join( dirname( $meta['file'] ), $size['file'] );
     5627
    56075628                        if ( ! empty( $del_file ) ) {
    56085629                                $del_file = path_join( $uploadpath['basedir'], $del_file );
    56095630
     
    58745895}
    58755896
    58765897/**
     5898 * Retrieves the path to an uploaded image.
     5899 *
     5900 * Similar to `get_attached_file()` however some images may have been
     5901 * processed after uploading. In this case this function returns the path
     5902 * to the originally uploaded image file.
     5903 *
     5904 * @since 5.3.0
     5905 *
     5906 * @param int $attachment_id Attachment ID.
     5907 * @return string|false Path to the original image file or false if the attachment is not an image.
     5908 */
     5909function wp_get_original_attachment_image( $attachment_id ) {
     5910        if ( ! wp_attachment_is_image( $attachment_id ) ) {
     5911                return false;
     5912        }
     5913
     5914        $image_meta = wp_get_attachment_metadata( $attachment_id );
     5915        $image_file = get_attached_file( $attachment_id );
     5916
     5917        if ( empty( $image_meta['original_image'] ) ) {
     5918                $original_image = $image_file;
     5919        } else {
     5920                $original_image = path_join( dirname( $image_file ), $image_meta['original_image'] );
     5921        }
     5922
     5923        /**
     5924         * Filters the path to the original attachment image.
     5925         *
     5926         * @since 5.3.0
     5927         *
     5928         * @param string $original_image Path to original image file.
     5929         * @param int    $attachment_id  Attachment ID.
     5930         */
     5931        return apply_filters( 'wp_get_original_attachment_image', $original_image, $attachment_id );
     5932}
     5933
     5934/**
     5935 * Retrieve the URL to an original attachment image.
     5936 *
     5937 * Similar to `wp_get_attachment_url()` however some images may have been
     5938 * processed after uploading. In this case this function returns the URL
     5939 * to the originally uploaded image file.
     5940 *
     5941 * @since 5.3.0
     5942 *
     5943 * @param int $attachment_id Attachment post ID.
     5944 * @return string|false Attachment image URL, false on error or if the attachment is not an image.
     5945 */
     5946function wp_get_original_attachment_image_url( $attachment_id ) {
     5947        if ( ! wp_attachment_is_image( $attachment_id ) ) {
     5948                return false;
     5949        }
     5950
     5951        $image_url = wp_get_attachment_url( $attachment_id );
     5952
     5953        if ( empty( $image_url ) ) {
     5954                return false;
     5955        }
     5956
     5957        $image_meta = wp_get_attachment_metadata( $attachment_id );
     5958
     5959        if ( empty( $image_meta['original_image'] ) ) {
     5960                $original_image_url = $image_url;
     5961        } else {
     5962                $original_image_url = path_join( dirname( $image_url ), $image_meta['original_image'] );
     5963        }
     5964
     5965        /**
     5966         * Filters the URL to the original attachment image.
     5967         *
     5968         * @since 5.3.0
     5969         *
     5970         * @param string $original_image_url URL to original image.
     5971         * @param int    $attachment_id      Attachment ID.
     5972         */
     5973        return apply_filters( 'wp_get_original_attachment_image_url', $original_image_url, $attachment_id );
     5974}
     5975
     5976/**
    58775977 * Verifies an attachment is of a given type.
    58785978 *
    58795979 * @since 4.2.0