WordPress.org

Make WordPress Core

Ticket #47873: 47873.2.diff

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

     
    136136 */
    137137function wp_update_image_subsizes( $attachment_id ) {
    138138        $image_meta = wp_get_attachment_metadata( $attachment_id );
    139         $image_file = get_attached_file( $attachment_id );
     139        $image_file = wp_get_original_image_path( $attachment_id );
    140140
    141141        if ( empty( $image_meta ) || ! is_array( $image_meta ) ) {
    142142                // Previously failed upload?
    143143                // If there is an uploaded file, make all sub-sizes and generate all of the attachment meta.
    144144                if ( ! empty( $image_file ) ) {
    145                         return wp_create_image_subsizes( $image_file, array(), $attachment_id );
     145                        return wp_create_image_subsizes( $image_file, $attachment_id );
    146146                } else {
    147147                        return new WP_Error( 'invalid_attachment', __( 'The attached file cannot be found.' ) );
    148148                }
     
    167167 * @since 5.3.0
    168168 *
    169169 * @param string $file          Full path to the image file.
    170  * @param array  $image_meta    The attachment meta data array.
    171170 * @param int    $attachment_id Attachment Id to process.
    172  * @return array The attachment metadata with updated `sizes` array. Includes an array of errors encountered while resizing.
     171 * @return array The image attachment meta data.
    173172 */
    174 function wp_create_image_subsizes( $file, $image_meta, $attachment_id ) {
    175         if ( empty( $image_meta ) || ! isset( $image_meta['width'], $image_meta['height'] ) ) {
    176                 // New uploaded image.
    177                 $imagesize            = @getimagesize( $file );
    178                 $image_meta['width']  = $imagesize[0];
    179                 $image_meta['height'] = $imagesize[1];
     173function wp_create_image_subsizes( $file, $attachment_id ) {
     174        $imagesize = @getimagesize( $file );
    180175
    181                 // Make the file path relative to the upload dir.
    182                 $image_meta['file'] = _wp_relative_upload_path( $file );
     176        if ( empty( $imagesize ) ) {
     177                // File is not an image.
     178                return array();
     179        }
    183180
    184                 // Fetch additional metadata from EXIF/IPTC.
    185                 $exif_meta = wp_read_image_metadata( $file );
     181        // Default image meta
     182        $image_meta = array(
     183                'width'  => $imagesize[0],
     184                'height' => $imagesize[1],
     185                'file'   => _wp_relative_upload_path( $file ),
     186                'sizes'  => array(),
     187        );
    186188
    187                 if ( $exif_meta ) {
    188                         $image_meta['image_meta'] = $exif_meta;
     189        // Fetch additional metadata from EXIF/IPTC.
     190        $exif_meta = wp_read_image_metadata( $file );
     191
     192        if ( $exif_meta ) {
     193                $image_meta['image_meta'] = $exif_meta;
     194        }
     195
     196        /**
     197         * Filters the "BIG image" threshold value.
     198         *
     199         * If the original image width or height is above the threshold, it will be scaled down. The threshold is
     200         * used as max width and max height. The scaled down image will be used as the largest available size, including
     201         * the `_wp_attached_file` post meta value.
     202         *
     203         * Returning `false` from the filter callback will disable the scaling.
     204         *
     205         * @since 5.3.0
     206         *
     207         * @param array  $imagesize     Indexed array of the image width and height (in that order).
     208         * @param string $file          Full path to the uploaded image file.
     209         * @param int    $attachment_id Attachment post ID.
     210         */
     211        $threshold = (int) apply_filters( 'big_image_size_threshold', 2560, $imagesize, $file, $attachment_id );
     212
     213        // If the original image's dimensions are over the threshold, scale the image
     214        // and use it as the "full" size.
     215        if ( $threshold && ( $image_meta['width'] > $threshold || $image_meta['height'] > $threshold ) ) {
     216                $editor = wp_get_image_editor( $file );
     217
     218                if ( is_wp_error( $editor ) ) {
     219                        // This image cannot be edited.
     220                        return $image_meta;
    189221                }
     222
     223                // Resize the image
     224                $resized = $editor->resize( $threshold, $threshold );
     225
     226                if ( ! is_wp_error( $resized ) ) {
     227                        // TODO: EXIF rotate here.
     228                        // By default the editor will append `{width}x{height}` to the file name of the resized image.
     229                        // Better to append the threshold size instead so the image file name would be like "my-image-2560.jpg"
     230                        // and not look like a "regular" sub-size.
     231                        // This doesn't affect the sub-sizes names as they are generated from the original image (for best quality).
     232                        $saved = $editor->save( $editor->generate_filename( $threshold ) );
     233
     234                        if ( ! is_wp_error( $saved ) ) {
     235                                $new_file = $saved['path'];
     236
     237                                // Update the attached file meta.
     238                                update_attached_file( $attachment_id, $new_file );
     239
     240                                // Width and height of the new image.
     241                                $image_meta['width']  = $saved['width'];
     242                                $image_meta['height'] = $saved['height'];
     243
     244                                // Make the file path relative to the upload dir.
     245                                $image_meta['file'] = _wp_relative_upload_path( $new_file );
     246
     247                                // Store the original image file name in image_meta.
     248                                $image_meta['original_image'] = wp_basename( $file );
     249                        }
     250                }
    190251        }
    191252
    192253        $new_sizes = wp_get_registered_image_subsizes();
     
    223284 * @return array The attachment meta data with updated `sizes` array. Includes an array of errors encountered while resizing.
    224285 */
    225286function _wp_make_subsizes( $new_sizes, $file, $image_meta, $attachment_id ) {
     287        if ( empty( $image_meta ) || ! is_array( $image_meta ) ) {
     288                // Not an image attachment.
     289                return array();
     290        }
     291
    226292        // Check if any of the new sizes already exist.
    227293        if ( isset( $image_meta['sizes'] ) && is_array( $image_meta['sizes'] ) ) {
    228294                foreach ( $image_meta['sizes'] as $size_name => $size_meta ) {
     
    237303                $image_meta['sizes'] = array();
    238304        }
    239305
    240         if ( ! empty( $new_sizes ) ) {
    241                 // Sort the image sub-sizes in order of priority when creating them.
    242                 // This ensures there is an appropriate sub-size the user can access immediately
    243                 // even when there was an error and not all sub-sizes were created.
    244                 $priority = array(
    245                         'medium'       => null,
    246                         'large'        => null,
    247                         'thumbnail'    => null,
    248                         'medium_large' => null,
    249                 );
     306        if ( empty( $new_sizes ) ) {
     307                // Nothing to do...
     308                return $image_meta;
     309        }
    250310
    251                 $new_sizes = array_filter( array_merge( $priority, $new_sizes ) );
     311        // Sort the image sub-sizes in order of priority when creating them.
     312        // This ensures there is an appropriate sub-size the user can access immediately
     313        // even when there was an error and not all sub-sizes were created.
     314        $priority = array(
     315                'medium'       => null,
     316                'large'        => null,
     317                'thumbnail'    => null,
     318                'medium_large' => null,
     319        );
    252320
    253                 $editor = wp_get_image_editor( $file );
     321        $new_sizes = array_filter( array_merge( $priority, $new_sizes ) );
    254322
    255                 if ( ! is_wp_error( $editor ) ) {
    256                         if ( method_exists( $editor, 'make_subsize' ) ) {
    257                                 foreach ( $new_sizes as $new_size_name => $new_size_data ) {
    258                                         $new_size_meta = $editor->make_subsize( $new_size_data );
     323        $editor = wp_get_image_editor( $file );
    259324
    260                                         if ( is_wp_error( $new_size_meta ) ) {
    261                                                 $error_code = $new_size_meta->get_error_code();
     325        if ( is_wp_error( $editor ) ) {
     326                // The image cannot be edited.
     327                return $image_meta;
     328        }
    262329
    263                                                 if ( $error_code === 'error_getting_dimensions' ) {
    264                                                         // Ignore errors when `image_resize_dimensions()` returns false.
    265                                                         // They mean that the requested size is larger than the original image and should be skipped.
    266                                                         continue;
    267                                                 }
     330        if ( method_exists( $editor, 'make_subsize' ) ) {
     331                foreach ( $new_sizes as $new_size_name => $new_size_data ) {
     332                        $new_size_meta = $editor->make_subsize( $new_size_data );
    268333
    269                                                 if ( empty( $image_meta['subsize_errors'] ) ) {
    270                                                         $image_meta['subsize_errors'] = array();
    271                                                 }
     334                        if ( is_wp_error( $new_size_meta ) ) {
     335                                $error_code = $new_size_meta->get_error_code();
    272336
    273                                                 $error = array(
    274                                                         'error_code'    => $error_code,
    275                                                         'error_message' => $new_size_meta->get_error_message(),
    276                                                 );
     337                                if ( $error_code === 'error_getting_dimensions' ) {
     338                                        // Ignore errors when `image_resize_dimensions()` returns false.
     339                                        // They mean that the requested size is larger than the original image and should be skipped.
     340                                        continue;
     341                                }
    277342
    278                                                 // Store the error code and error message for displaying in the UI.
    279                                                 $image_meta['subsize_errors'][ $new_size_name ] = $error;
    280                                         } else {
    281                                                 // The sub-size was created successfully.
    282                                                 // Clear out previous errors in creating this subsize.
    283                                                 if ( ! empty( $image_meta['subsize_errors'][ $new_size_name ] ) ) {
    284                                                         unset( $image_meta['subsize_errors'][ $new_size_name ] );
    285                                                 }
     343                                if ( empty( $image_meta['subsize_errors'] ) ) {
     344                                        $image_meta['subsize_errors'] = array();
     345                                }
    286346
    287                                                 if ( empty( $image_meta['subsize_errors'] ) ) {
    288                                                         unset( $image_meta['subsize_errors'] );
    289                                                 }
     347                                $error = array(
     348                                        'error_code'    => $error_code,
     349                                        'error_message' => $new_size_meta->get_error_message(),
     350                                );
    290351
    291                                                 // Save the size meta value.
    292                                                 $image_meta['sizes'][ $new_size_name ] = $new_size_meta;
    293                                         }
    294 
    295                                         wp_update_attachment_metadata( $attachment_id, $image_meta );
     352                                // Store the error code and error message for displaying in the UI.
     353                                $image_meta['subsize_errors'][ $new_size_name ] = $error;
     354                        } else {
     355                                // The sub-size was created successfully.
     356                                // Clear out previous errors in creating this subsize.
     357                                if ( ! empty( $image_meta['subsize_errors'][ $new_size_name ] ) ) {
     358                                        unset( $image_meta['subsize_errors'][ $new_size_name ] );
    296359                                }
    297                         } else {
    298                                 // Fall back to `$editor->multi_resize()`.
    299                                 $created_sizes = $editor->multi_resize( $new_sizes );
    300360
    301                                 if ( ! empty( $created_sizes ) ) {
    302                                         $image_meta['sizes'] = array_merge( $image_meta['sizes'], $created_sizes );
     361                                if ( empty( $image_meta['subsize_errors'] ) ) {
    303362                                        unset( $image_meta['subsize_errors'] );
    304                                         wp_update_attachment_metadata( $attachment_id, $image_meta );
    305363                                }
     364
     365                                // Save the size meta value.
     366                                $image_meta['sizes'][ $new_size_name ] = $new_size_meta;
    306367                        }
     368
     369                        wp_update_attachment_metadata( $attachment_id, $image_meta );
    307370                }
     371        } else {
     372                // Fall back to `$editor->multi_resize()`.
     373                $created_sizes = $editor->multi_resize( $new_sizes );
     374
     375                if ( ! empty( $created_sizes ) ) {
     376                        $image_meta['sizes'] = array_merge( $image_meta['sizes'], $created_sizes );
     377                        unset( $image_meta['subsize_errors'] );
     378                        wp_update_attachment_metadata( $attachment_id, $image_meta );
     379                }
    308380        }
    309381
    310382        return $image_meta;
     
    328400
    329401        if ( preg_match( '!^image/!', $mime_type ) && file_is_displayable_image( $file ) ) {
    330402                // Make thumbnails and other intermediate sizes.
    331                 $metadata = wp_create_image_subsizes( $file, $metadata, $attachment_id );
     403                $metadata = wp_create_image_subsizes( $file, $attachment_id );
    332404        } elseif ( wp_attachment_is( 'video', $attachment ) ) {
    333405                $metadata = wp_read_video_metadata( $file );
    334406                $support  = current_theme_supports( 'post-thumbnails', 'attachment:video' ) || post_type_supports( 'attachment:video', 'thumbnail' );
     
    899971
    900972        return $dst_file;
    901973}
     974
     975/**
     976 * Retrieves the path to an uploaded image.
     977 *
     978 * Similar to `get_attached_file()` however some images may have been
     979 * processed after uploading to make them "web ready".
     980 * In this case this function returns the path to the originally uploaded image file.
     981 *
     982 * @since 5.3.0
     983 *
     984 * @param int $attachment_id Attachment ID.
     985 * @return string|false Path to the original image file or false if the attachment is not an image.
     986 */
     987function wp_get_original_image_path( $attachment_id ) {
     988        if ( ! wp_attachment_is_image( $attachment_id ) ) {
     989                return false;
     990        }
     991
     992        $image_meta = wp_get_attachment_metadata( $attachment_id );
     993        $image_file = get_attached_file( $attachment_id );
     994
     995        if ( empty( $image_meta['original_image'] ) ) {
     996                $original_image = $image_file;
     997        } else {
     998                $original_image = path_join( dirname( $image_file ), $image_meta['original_image'] );
     999        }
     1000
     1001        /**
     1002         * Filters the path to the original image.
     1003         *
     1004         * @since 5.3.0
     1005         *
     1006         * @param string $original_image Path to original image file.
     1007         * @param int    $attachment_id  Attachment ID.
     1008         */
     1009        return apply_filters( 'wp_get_original_image_path', $original_image, $attachment_id );
     1010}
  • src/wp-includes/post.php

     
    56385638                // Don't delete the thumb if another attachment uses it.
    56395639                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 ) ) ) {
    56405640                        $thumbfile = str_replace( wp_basename( $file ), $meta['thumb'], $file );
     5641
    56415642                        if ( ! empty( $thumbfile ) ) {
    56425643                                $thumbfile = path_join( $uploadpath['basedir'], $thumbfile );
    56435644                                $thumbdir  = path_join( $uploadpath['basedir'], dirname( $file ) );
     
    56525653        // Remove intermediate and backup images if there are any.
    56535654        if ( isset( $meta['sizes'] ) && is_array( $meta['sizes'] ) ) {
    56545655                $intermediate_dir = path_join( $uploadpath['basedir'], dirname( $file ) );
     5656
    56555657                foreach ( $meta['sizes'] as $size => $sizeinfo ) {
    56565658                        $intermediate_file = str_replace( wp_basename( $file ), $sizeinfo['file'], $file );
     5659
    56575660                        if ( ! empty( $intermediate_file ) ) {
    56585661                                $intermediate_file = path_join( $uploadpath['basedir'], $intermediate_file );
    56595662
     
    56645667                }
    56655668        }
    56665669
     5670        if ( ! empty( $meta['original_image'] ) ) {
     5671                if ( empty( $intermediate_dir ) ) {
     5672                        $intermediate_dir = path_join( $uploadpath['basedir'], dirname( $file ) );
     5673                }
     5674
     5675                $original_image = str_replace( wp_basename( $file ), $meta['original_image'], $file );
     5676
     5677                if ( ! empty( $original_image ) ) {
     5678                        $original_image = path_join( $uploadpath['basedir'], $original_image );
     5679
     5680                        if ( ! wp_delete_file_from_directory( $original_image, $intermediate_dir ) ) {
     5681                                $deleted = false;
     5682                        }
     5683                }
     5684        }
     5685
    56675686        if ( is_array( $backup_sizes ) ) {
    56685687                $del_dir = path_join( $uploadpath['basedir'], dirname( $meta['file'] ) );
     5688
    56695689                foreach ( $backup_sizes as $size ) {
    56705690                        $del_file = path_join( dirname( $meta['file'] ), $size['file'] );
     5691
    56715692                        if ( ! empty( $del_file ) ) {
    56725693                                $del_file = path_join( $uploadpath['basedir'], $del_file );
    56735694