Media: Add handling for "BIG" images. When the users upload a big image, typically a photo, scale it down to make it suitable for web use. Then use the scaled image as the "full" size, and keep the originally uploaded image for creating high quality sub-sizes in the future and in case the users want to download it later.
Introduces `wp_get_original_image_path()` that retrieves the path to the originally uploaded image in all cases, and `big_image_size_threshold` filter to set the pixel value above which images will be scaled. The same value is used as max-width and max-height when scaling. See #47873. Built from https://develop.svn.wordpress.org/trunk@46076 git-svn-id: http://core.svn.wordpress.org/trunk@45888 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
parent
630bad3a4f
commit
dc8349ba0a
|
@ -136,13 +136,13 @@ function wp_get_missing_image_subsizes( $attachment_id ) {
|
||||||
*/
|
*/
|
||||||
function wp_update_image_subsizes( $attachment_id ) {
|
function wp_update_image_subsizes( $attachment_id ) {
|
||||||
$image_meta = wp_get_attachment_metadata( $attachment_id );
|
$image_meta = wp_get_attachment_metadata( $attachment_id );
|
||||||
$image_file = get_attached_file( $attachment_id );
|
$image_file = wp_get_original_image_path( $attachment_id );
|
||||||
|
|
||||||
if ( empty( $image_meta ) || ! is_array( $image_meta ) ) {
|
if ( empty( $image_meta ) || ! is_array( $image_meta ) ) {
|
||||||
// Previously failed upload?
|
// Previously failed upload?
|
||||||
// If there is an uploaded file, make all sub-sizes and generate all of the attachment meta.
|
// If there is an uploaded file, make all sub-sizes and generate all of the attachment meta.
|
||||||
if ( ! empty( $image_file ) ) {
|
if ( ! empty( $image_file ) ) {
|
||||||
return wp_create_image_subsizes( $image_file, array(), $attachment_id );
|
return wp_create_image_subsizes( $image_file, $attachment_id );
|
||||||
} else {
|
} else {
|
||||||
return new WP_Error( 'invalid_attachment', __( 'The attached file cannot be found.' ) );
|
return new WP_Error( 'invalid_attachment', __( 'The attached file cannot be found.' ) );
|
||||||
}
|
}
|
||||||
|
@ -167,25 +167,86 @@ function wp_update_image_subsizes( $attachment_id ) {
|
||||||
* @since 5.3.0
|
* @since 5.3.0
|
||||||
*
|
*
|
||||||
* @param string $file Full path to the image file.
|
* @param string $file Full path to the image file.
|
||||||
* @param array $image_meta The attachment meta data array.
|
|
||||||
* @param int $attachment_id Attachment Id to process.
|
* @param int $attachment_id Attachment Id to process.
|
||||||
* @return array The attachment metadata with updated `sizes` array. Includes an array of errors encountered while resizing.
|
* @return array The image attachment meta data.
|
||||||
*/
|
*/
|
||||||
function wp_create_image_subsizes( $file, $image_meta, $attachment_id ) {
|
function wp_create_image_subsizes( $file, $attachment_id ) {
|
||||||
if ( empty( $image_meta ) || ! isset( $image_meta['width'], $image_meta['height'] ) ) {
|
$imagesize = @getimagesize( $file );
|
||||||
// New uploaded image.
|
|
||||||
$imagesize = @getimagesize( $file );
|
|
||||||
$image_meta['width'] = $imagesize[0];
|
|
||||||
$image_meta['height'] = $imagesize[1];
|
|
||||||
|
|
||||||
// Make the file path relative to the upload dir.
|
if ( empty( $imagesize ) ) {
|
||||||
$image_meta['file'] = _wp_relative_upload_path( $file );
|
// File is not an image.
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
// Fetch additional metadata from EXIF/IPTC.
|
// Default image meta
|
||||||
$exif_meta = wp_read_image_metadata( $file );
|
$image_meta = array(
|
||||||
|
'width' => $imagesize[0],
|
||||||
|
'height' => $imagesize[1],
|
||||||
|
'file' => _wp_relative_upload_path( $file ),
|
||||||
|
'sizes' => array(),
|
||||||
|
);
|
||||||
|
|
||||||
if ( $exif_meta ) {
|
// Fetch additional metadata from EXIF/IPTC.
|
||||||
$image_meta['image_meta'] = $exif_meta;
|
$exif_meta = wp_read_image_metadata( $file );
|
||||||
|
|
||||||
|
if ( $exif_meta ) {
|
||||||
|
$image_meta['image_meta'] = $exif_meta;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters the "BIG image" threshold value.
|
||||||
|
*
|
||||||
|
* If the original image width or height is above the threshold, it will be scaled down. The threshold is
|
||||||
|
* used as max width and max height. The scaled down image will be used as the largest available size, including
|
||||||
|
* the `_wp_attached_file` post meta value.
|
||||||
|
*
|
||||||
|
* Returning `false` from the filter callback will disable the scaling.
|
||||||
|
*
|
||||||
|
* @since 5.3.0
|
||||||
|
*
|
||||||
|
* @param array $imagesize Indexed array of the image width and height (in that order).
|
||||||
|
* @param string $file Full path to the uploaded image file.
|
||||||
|
* @param int $attachment_id Attachment post ID.
|
||||||
|
*/
|
||||||
|
$threshold = (int) apply_filters( 'big_image_size_threshold', 2560, $imagesize, $file, $attachment_id );
|
||||||
|
|
||||||
|
// If the original image's dimensions are over the threshold, scale the image
|
||||||
|
// and use it as the "full" size.
|
||||||
|
if ( $threshold && ( $image_meta['width'] > $threshold || $image_meta['height'] > $threshold ) ) {
|
||||||
|
$editor = wp_get_image_editor( $file );
|
||||||
|
|
||||||
|
if ( is_wp_error( $editor ) ) {
|
||||||
|
// This image cannot be edited.
|
||||||
|
return $image_meta;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resize the image
|
||||||
|
$resized = $editor->resize( $threshold, $threshold );
|
||||||
|
|
||||||
|
if ( ! is_wp_error( $resized ) ) {
|
||||||
|
// TODO: EXIF rotate here.
|
||||||
|
// By default the editor will append `{width}x{height}` to the file name of the resized image.
|
||||||
|
// Better to append the threshold size instead so the image file name would be like "my-image-2560.jpg"
|
||||||
|
// and not look like a "regular" sub-size.
|
||||||
|
// This doesn't affect the sub-sizes names as they are generated from the original image (for best quality).
|
||||||
|
$saved = $editor->save( $editor->generate_filename( $threshold ) );
|
||||||
|
|
||||||
|
if ( ! is_wp_error( $saved ) ) {
|
||||||
|
$new_file = $saved['path'];
|
||||||
|
|
||||||
|
// Update the attached file meta.
|
||||||
|
update_attached_file( $attachment_id, $new_file );
|
||||||
|
|
||||||
|
// Width and height of the new image.
|
||||||
|
$image_meta['width'] = $saved['width'];
|
||||||
|
$image_meta['height'] = $saved['height'];
|
||||||
|
|
||||||
|
// Make the file path relative to the upload dir.
|
||||||
|
$image_meta['file'] = _wp_relative_upload_path( $new_file );
|
||||||
|
|
||||||
|
// Store the original image file name in image_meta.
|
||||||
|
$image_meta['original_image'] = wp_basename( $file );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,6 +284,11 @@ function wp_create_image_subsizes( $file, $image_meta, $attachment_id ) {
|
||||||
* @return array The attachment meta data with updated `sizes` array. Includes an array of errors encountered while resizing.
|
* @return array The attachment meta data with updated `sizes` array. Includes an array of errors encountered while resizing.
|
||||||
*/
|
*/
|
||||||
function _wp_make_subsizes( $new_sizes, $file, $image_meta, $attachment_id ) {
|
function _wp_make_subsizes( $new_sizes, $file, $image_meta, $attachment_id ) {
|
||||||
|
if ( empty( $image_meta ) || ! is_array( $image_meta ) ) {
|
||||||
|
// Not an image attachment.
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
// Check if any of the new sizes already exist.
|
// Check if any of the new sizes already exist.
|
||||||
if ( isset( $image_meta['sizes'] ) && is_array( $image_meta['sizes'] ) ) {
|
if ( isset( $image_meta['sizes'] ) && is_array( $image_meta['sizes'] ) ) {
|
||||||
foreach ( $image_meta['sizes'] as $size_name => $size_meta ) {
|
foreach ( $image_meta['sizes'] as $size_name => $size_meta ) {
|
||||||
|
@ -237,73 +303,79 @@ function _wp_make_subsizes( $new_sizes, $file, $image_meta, $attachment_id ) {
|
||||||
$image_meta['sizes'] = array();
|
$image_meta['sizes'] = array();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ! empty( $new_sizes ) ) {
|
if ( empty( $new_sizes ) ) {
|
||||||
// Sort the image sub-sizes in order of priority when creating them.
|
// Nothing to do...
|
||||||
// This ensures there is an appropriate sub-size the user can access immediately
|
return $image_meta;
|
||||||
// even when there was an error and not all sub-sizes were created.
|
}
|
||||||
$priority = array(
|
|
||||||
'medium' => null,
|
|
||||||
'large' => null,
|
|
||||||
'thumbnail' => null,
|
|
||||||
'medium_large' => null,
|
|
||||||
);
|
|
||||||
|
|
||||||
$new_sizes = array_filter( array_merge( $priority, $new_sizes ) );
|
// Sort the image sub-sizes in order of priority when creating them.
|
||||||
|
// This ensures there is an appropriate sub-size the user can access immediately
|
||||||
|
// even when there was an error and not all sub-sizes were created.
|
||||||
|
$priority = array(
|
||||||
|
'medium' => null,
|
||||||
|
'large' => null,
|
||||||
|
'thumbnail' => null,
|
||||||
|
'medium_large' => null,
|
||||||
|
);
|
||||||
|
|
||||||
$editor = wp_get_image_editor( $file );
|
$new_sizes = array_filter( array_merge( $priority, $new_sizes ) );
|
||||||
|
|
||||||
if ( ! is_wp_error( $editor ) ) {
|
$editor = wp_get_image_editor( $file );
|
||||||
if ( method_exists( $editor, 'make_subsize' ) ) {
|
|
||||||
foreach ( $new_sizes as $new_size_name => $new_size_data ) {
|
|
||||||
$new_size_meta = $editor->make_subsize( $new_size_data );
|
|
||||||
|
|
||||||
if ( is_wp_error( $new_size_meta ) ) {
|
if ( is_wp_error( $editor ) ) {
|
||||||
$error_code = $new_size_meta->get_error_code();
|
// The image cannot be edited.
|
||||||
|
return $image_meta;
|
||||||
|
}
|
||||||
|
|
||||||
if ( $error_code === 'error_getting_dimensions' ) {
|
if ( method_exists( $editor, 'make_subsize' ) ) {
|
||||||
// Ignore errors when `image_resize_dimensions()` returns false.
|
foreach ( $new_sizes as $new_size_name => $new_size_data ) {
|
||||||
// They mean that the requested size is larger than the original image and should be skipped.
|
$new_size_meta = $editor->make_subsize( $new_size_data );
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( empty( $image_meta['subsize_errors'] ) ) {
|
if ( is_wp_error( $new_size_meta ) ) {
|
||||||
$image_meta['subsize_errors'] = array();
|
$error_code = $new_size_meta->get_error_code();
|
||||||
}
|
|
||||||
|
|
||||||
$error = array(
|
if ( $error_code === 'error_getting_dimensions' ) {
|
||||||
'error_code' => $error_code,
|
// Ignore errors when `image_resize_dimensions()` returns false.
|
||||||
'error_message' => $new_size_meta->get_error_message(),
|
// They mean that the requested size is larger than the original image and should be skipped.
|
||||||
);
|
continue;
|
||||||
|
|
||||||
// Store the error code and error message for displaying in the UI.
|
|
||||||
$image_meta['subsize_errors'][ $new_size_name ] = $error;
|
|
||||||
} else {
|
|
||||||
// The sub-size was created successfully.
|
|
||||||
// Clear out previous errors in creating this subsize.
|
|
||||||
if ( ! empty( $image_meta['subsize_errors'][ $new_size_name ] ) ) {
|
|
||||||
unset( $image_meta['subsize_errors'][ $new_size_name ] );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( empty( $image_meta['subsize_errors'] ) ) {
|
|
||||||
unset( $image_meta['subsize_errors'] );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save the size meta value.
|
|
||||||
$image_meta['sizes'][ $new_size_name ] = $new_size_meta;
|
|
||||||
}
|
|
||||||
|
|
||||||
wp_update_attachment_metadata( $attachment_id, $image_meta );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( empty( $image_meta['subsize_errors'] ) ) {
|
||||||
|
$image_meta['subsize_errors'] = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
$error = array(
|
||||||
|
'error_code' => $error_code,
|
||||||
|
'error_message' => $new_size_meta->get_error_message(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Store the error code and error message for displaying in the UI.
|
||||||
|
$image_meta['subsize_errors'][ $new_size_name ] = $error;
|
||||||
} else {
|
} else {
|
||||||
// Fall back to `$editor->multi_resize()`.
|
// The sub-size was created successfully.
|
||||||
$created_sizes = $editor->multi_resize( $new_sizes );
|
// Clear out previous errors in creating this subsize.
|
||||||
|
if ( ! empty( $image_meta['subsize_errors'][ $new_size_name ] ) ) {
|
||||||
if ( ! empty( $created_sizes ) ) {
|
unset( $image_meta['subsize_errors'][ $new_size_name ] );
|
||||||
$image_meta['sizes'] = array_merge( $image_meta['sizes'], $created_sizes );
|
|
||||||
unset( $image_meta['subsize_errors'] );
|
|
||||||
wp_update_attachment_metadata( $attachment_id, $image_meta );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( empty( $image_meta['subsize_errors'] ) ) {
|
||||||
|
unset( $image_meta['subsize_errors'] );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the size meta value.
|
||||||
|
$image_meta['sizes'][ $new_size_name ] = $new_size_meta;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wp_update_attachment_metadata( $attachment_id, $image_meta );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Fall back to `$editor->multi_resize()`.
|
||||||
|
$created_sizes = $editor->multi_resize( $new_sizes );
|
||||||
|
|
||||||
|
if ( ! empty( $created_sizes ) ) {
|
||||||
|
$image_meta['sizes'] = array_merge( $image_meta['sizes'], $created_sizes );
|
||||||
|
unset( $image_meta['subsize_errors'] );
|
||||||
|
wp_update_attachment_metadata( $attachment_id, $image_meta );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -328,7 +400,7 @@ function wp_generate_attachment_metadata( $attachment_id, $file ) {
|
||||||
|
|
||||||
if ( preg_match( '!^image/!', $mime_type ) && file_is_displayable_image( $file ) ) {
|
if ( preg_match( '!^image/!', $mime_type ) && file_is_displayable_image( $file ) ) {
|
||||||
// Make thumbnails and other intermediate sizes.
|
// Make thumbnails and other intermediate sizes.
|
||||||
$metadata = wp_create_image_subsizes( $file, $metadata, $attachment_id );
|
$metadata = wp_create_image_subsizes( $file, $attachment_id );
|
||||||
} elseif ( wp_attachment_is( 'video', $attachment ) ) {
|
} elseif ( wp_attachment_is( 'video', $attachment ) ) {
|
||||||
$metadata = wp_read_video_metadata( $file );
|
$metadata = wp_read_video_metadata( $file );
|
||||||
$support = current_theme_supports( 'post-thumbnails', 'attachment:video' ) || post_type_supports( 'attachment:video', 'thumbnail' );
|
$support = current_theme_supports( 'post-thumbnails', 'attachment:video' ) || post_type_supports( 'attachment:video', 'thumbnail' );
|
||||||
|
@ -899,3 +971,40 @@ function _copy_image_file( $attachment_id ) {
|
||||||
|
|
||||||
return $dst_file;
|
return $dst_file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the path to an uploaded image.
|
||||||
|
*
|
||||||
|
* Similar to `get_attached_file()` however some images may have been
|
||||||
|
* processed after uploading to make them "web ready".
|
||||||
|
* In this case this function returns the path to the originally uploaded image file.
|
||||||
|
*
|
||||||
|
* @since 5.3.0
|
||||||
|
*
|
||||||
|
* @param int $attachment_id Attachment ID.
|
||||||
|
* @return string|false Path to the original image file or false if the attachment is not an image.
|
||||||
|
*/
|
||||||
|
function wp_get_original_image_path( $attachment_id ) {
|
||||||
|
if ( ! wp_attachment_is_image( $attachment_id ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$image_meta = wp_get_attachment_metadata( $attachment_id );
|
||||||
|
$image_file = get_attached_file( $attachment_id );
|
||||||
|
|
||||||
|
if ( empty( $image_meta['original_image'] ) ) {
|
||||||
|
$original_image = $image_file;
|
||||||
|
} else {
|
||||||
|
$original_image = path_join( dirname( $image_file ), $image_meta['original_image'] );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters the path to the original image.
|
||||||
|
*
|
||||||
|
* @since 5.3.0
|
||||||
|
*
|
||||||
|
* @param string $original_image Path to original image file.
|
||||||
|
* @param int $attachment_id Attachment ID.
|
||||||
|
*/
|
||||||
|
return apply_filters( 'wp_get_original_image_path', $original_image, $attachment_id );
|
||||||
|
}
|
||||||
|
|
|
@ -5638,6 +5638,7 @@ function wp_delete_attachment_files( $post_id, $meta, $backup_sizes, $file ) {
|
||||||
// Don't delete the thumb if another attachment uses it.
|
// Don't delete the thumb if another attachment uses it.
|
||||||
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 ) ) ) {
|
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 ) ) ) {
|
||||||
$thumbfile = str_replace( wp_basename( $file ), $meta['thumb'], $file );
|
$thumbfile = str_replace( wp_basename( $file ), $meta['thumb'], $file );
|
||||||
|
|
||||||
if ( ! empty( $thumbfile ) ) {
|
if ( ! empty( $thumbfile ) ) {
|
||||||
$thumbfile = path_join( $uploadpath['basedir'], $thumbfile );
|
$thumbfile = path_join( $uploadpath['basedir'], $thumbfile );
|
||||||
$thumbdir = path_join( $uploadpath['basedir'], dirname( $file ) );
|
$thumbdir = path_join( $uploadpath['basedir'], dirname( $file ) );
|
||||||
|
@ -5652,8 +5653,10 @@ function wp_delete_attachment_files( $post_id, $meta, $backup_sizes, $file ) {
|
||||||
// Remove intermediate and backup images if there are any.
|
// Remove intermediate and backup images if there are any.
|
||||||
if ( isset( $meta['sizes'] ) && is_array( $meta['sizes'] ) ) {
|
if ( isset( $meta['sizes'] ) && is_array( $meta['sizes'] ) ) {
|
||||||
$intermediate_dir = path_join( $uploadpath['basedir'], dirname( $file ) );
|
$intermediate_dir = path_join( $uploadpath['basedir'], dirname( $file ) );
|
||||||
|
|
||||||
foreach ( $meta['sizes'] as $size => $sizeinfo ) {
|
foreach ( $meta['sizes'] as $size => $sizeinfo ) {
|
||||||
$intermediate_file = str_replace( wp_basename( $file ), $sizeinfo['file'], $file );
|
$intermediate_file = str_replace( wp_basename( $file ), $sizeinfo['file'], $file );
|
||||||
|
|
||||||
if ( ! empty( $intermediate_file ) ) {
|
if ( ! empty( $intermediate_file ) ) {
|
||||||
$intermediate_file = path_join( $uploadpath['basedir'], $intermediate_file );
|
$intermediate_file = path_join( $uploadpath['basedir'], $intermediate_file );
|
||||||
|
|
||||||
|
@ -5664,10 +5667,28 @@ function wp_delete_attachment_files( $post_id, $meta, $backup_sizes, $file ) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( ! empty( $meta['original_image'] ) ) {
|
||||||
|
if ( empty( $intermediate_dir ) ) {
|
||||||
|
$intermediate_dir = path_join( $uploadpath['basedir'], dirname( $file ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
$original_image = str_replace( wp_basename( $file ), $meta['original_image'], $file );
|
||||||
|
|
||||||
|
if ( ! empty( $original_image ) ) {
|
||||||
|
$original_image = path_join( $uploadpath['basedir'], $original_image );
|
||||||
|
|
||||||
|
if ( ! wp_delete_file_from_directory( $original_image, $intermediate_dir ) ) {
|
||||||
|
$deleted = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ( is_array( $backup_sizes ) ) {
|
if ( is_array( $backup_sizes ) ) {
|
||||||
$del_dir = path_join( $uploadpath['basedir'], dirname( $meta['file'] ) );
|
$del_dir = path_join( $uploadpath['basedir'], dirname( $meta['file'] ) );
|
||||||
|
|
||||||
foreach ( $backup_sizes as $size ) {
|
foreach ( $backup_sizes as $size ) {
|
||||||
$del_file = path_join( dirname( $meta['file'] ), $size['file'] );
|
$del_file = path_join( dirname( $meta['file'] ), $size['file'] );
|
||||||
|
|
||||||
if ( ! empty( $del_file ) ) {
|
if ( ! empty( $del_file ) ) {
|
||||||
$del_file = path_join( $uploadpath['basedir'], $del_file );
|
$del_file = path_join( $uploadpath['basedir'], $del_file );
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
*
|
*
|
||||||
* @global string $wp_version
|
* @global string $wp_version
|
||||||
*/
|
*/
|
||||||
$wp_version = '5.3-alpha-46075';
|
$wp_version = '5.3-alpha-46076';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.
|
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.
|
||||||
|
|
Loading…
Reference in New Issue