WordPress Version: 6.4
/**
* Saves image to post, along with enqueued changes
* in `$_REQUEST['history']`.
*
* @since 2.9.0
*
* @param int $post_id Attachment post ID.
* @return stdClass
*/
function wp_save_image($post_id)
{
$_wp_additional_image_sizes = wp_get_additional_image_sizes();
$return = new stdClass();
$success = false;
$delete = false;
$scaled = false;
$nocrop = false;
$post = get_post($post_id);
$img = wp_get_image_editor(_load_image_to_edit_path($post_id, 'full'));
if (is_wp_error($img)) {
$return->error = esc_js(__('Unable to create new image.'));
return $return;
}
$full_width = (!empty($_REQUEST['fwidth'])) ? (int) $_REQUEST['fwidth'] : 0;
$full_height = (!empty($_REQUEST['fheight'])) ? (int) $_REQUEST['fheight'] : 0;
$target = (!empty($_REQUEST['target'])) ? preg_replace('/[^a-z0-9_-]+/i', '', $_REQUEST['target']) : '';
$scale = !empty($_REQUEST['do']) && 'scale' === $_REQUEST['do'];
/** This filter is documented in wp-admin/includes/image-edit.php */
$edit_thumbnails_separately = (bool) apply_filters('image_edit_thumbnails_separately', false);
if ($scale) {
$size = $img->get_size();
$original_width = $size['width'];
$original_height = $size['height'];
if ($full_width > $original_width || $full_height > $original_height) {
$return->error = esc_js(__('Images cannot be scaled to a size larger than the original.'));
return $return;
}
if ($full_width > 0 && $full_height > 0) {
// Check if it has roughly the same w / h ratio.
$diff = round($original_width / $original_height, 2) - round($full_width / $full_height, 2);
if (-0.1 < $diff && $diff < 0.1) {
// Scale the full size image.
if ($img->resize($full_width, $full_height)) {
$scaled = true;
}
}
if (!$scaled) {
$return->error = esc_js(__('Error while saving the scaled image. Please reload the page and try again.'));
return $return;
}
}
} elseif (!empty($_REQUEST['history'])) {
$changes = json_decode(wp_unslash($_REQUEST['history']));
if ($changes) {
$img = image_edit_apply_changes($img, $changes);
}
} else {
$return->error = esc_js(__('Nothing to save, the image has not changed.'));
return $return;
}
$meta = wp_get_attachment_metadata($post_id);
$backup_sizes = get_post_meta($post->ID, '_wp_attachment_backup_sizes', true);
if (!is_array($meta)) {
$return->error = esc_js(__('Image data does not exist. Please re-upload the image.'));
return $return;
}
if (!is_array($backup_sizes)) {
$backup_sizes = array();
}
// Generate new filename.
$path = get_attached_file($post_id);
$basename = pathinfo($path, PATHINFO_BASENAME);
$dirname = pathinfo($path, PATHINFO_DIRNAME);
$ext = pathinfo($path, PATHINFO_EXTENSION);
$filename = pathinfo($path, PATHINFO_FILENAME);
$suffix = time() . rand(100, 999);
if (defined('IMAGE_EDIT_OVERWRITE') && IMAGE_EDIT_OVERWRITE && isset($backup_sizes['full-orig']) && $backup_sizes['full-orig']['file'] !== $basename) {
if ($edit_thumbnails_separately && 'thumbnail' === $target) {
$new_path = "{$dirname}/{$filename}-temp.{$ext}";
} else {
$new_path = $path;
}
} else {
while (true) {
$filename = preg_replace('/-e([0-9]+)$/', '', $filename);
$filename .= "-e{$suffix}";
$new_filename = "{$filename}.{$ext}";
$new_path = "{$dirname}/{$new_filename}";
if (file_exists($new_path)) {
++$suffix;
} else {
break;
}
}
}
// Save the full-size file, also needed to create sub-sizes.
if (!wp_save_image_file($new_path, $img, $post->post_mime_type, $post_id)) {
$return->error = esc_js(__('Unable to save the image.'));
return $return;
}
if ('nothumb' === $target || 'all' === $target || 'full' === $target || $scaled) {
$tag = false;
if (isset($backup_sizes['full-orig'])) {
if ((!defined('IMAGE_EDIT_OVERWRITE') || !IMAGE_EDIT_OVERWRITE) && $backup_sizes['full-orig']['file'] !== $basename) {
$tag = "full-{$suffix}";
}
} else {
$tag = 'full-orig';
}
if ($tag) {
$backup_sizes[$tag] = array('width' => $meta['width'], 'height' => $meta['height'], 'file' => $basename);
}
$success = $path === $new_path || update_attached_file($post_id, $new_path);
$meta['file'] = _wp_relative_upload_path($new_path);
$size = $img->get_size();
$meta['width'] = $size['width'];
$meta['height'] = $size['height'];
if ($success && ('nothumb' === $target || 'all' === $target)) {
$sizes = get_intermediate_image_sizes();
if ($edit_thumbnails_separately && 'nothumb' === $target) {
$sizes = array_diff($sizes, array('thumbnail'));
}
}
$return->fw = $meta['width'];
$return->fh = $meta['height'];
} elseif ($edit_thumbnails_separately && 'thumbnail' === $target) {
$sizes = array('thumbnail');
$success = true;
$delete = true;
$nocrop = true;
}
/*
* We need to remove any existing resized image files because
* a new crop or rotate could generate different sizes (and hence, filenames),
* keeping the new resized images from overwriting the existing image files.
* https://core.trac.wordpress.org/ticket/32171
*/
if (defined('IMAGE_EDIT_OVERWRITE') && IMAGE_EDIT_OVERWRITE && !empty($meta['sizes'])) {
foreach ($meta['sizes'] as $size) {
if (!empty($size['file']) && preg_match('/-e[0-9]{13}-/', $size['file'])) {
$delete_file = path_join($dirname, $size['file']);
wp_delete_file($delete_file);
}
}
}
if (isset($sizes)) {
$_sizes = array();
foreach ($sizes as $size) {
$tag = false;
if (isset($meta['sizes'][$size])) {
if (isset($backup_sizes["{$size}-orig"])) {
if ((!defined('IMAGE_EDIT_OVERWRITE') || !IMAGE_EDIT_OVERWRITE) && $backup_sizes["{$size}-orig"]['file'] !== $meta['sizes'][$size]['file']) {
$tag = "{$size}-{$suffix}";
}
} else {
$tag = "{$size}-orig";
}
if ($tag) {
$backup_sizes[$tag] = $meta['sizes'][$size];
}
}
if (isset($_wp_additional_image_sizes[$size])) {
$width = (int) $_wp_additional_image_sizes[$size]['width'];
$height = (int) $_wp_additional_image_sizes[$size]['height'];
$crop = $nocrop ? false : $_wp_additional_image_sizes[$size]['crop'];
} else {
$height = get_option("{$size}_size_h");
$width = get_option("{$size}_size_w");
$crop = $nocrop ? false : get_option("{$size}_crop");
}
$_sizes[$size] = array('width' => $width, 'height' => $height, 'crop' => $crop);
}
$meta['sizes'] = array_merge($meta['sizes'], $img->multi_resize($_sizes));
}
unset($img);
if ($success) {
wp_update_attachment_metadata($post_id, $meta);
update_post_meta($post_id, '_wp_attachment_backup_sizes', $backup_sizes);
if ('thumbnail' === $target || 'all' === $target || 'full' === $target) {
// Check if it's an image edit from attachment edit screen.
if (!empty($_REQUEST['context']) && 'edit-attachment' === $_REQUEST['context']) {
$thumb_url = wp_get_attachment_image_src($post_id, array(900, 600), true);
$return->thumbnail = $thumb_url[0];
} else {
$file_url = wp_get_attachment_url($post_id);
if (!empty($meta['sizes']['thumbnail'])) {
$thumb = $meta['sizes']['thumbnail'];
$return->thumbnail = path_join(dirname($file_url), $thumb['file']);
} else {
$return->thumbnail = "{$file_url}?w=128&h=128";
}
}
}
} else {
$delete = true;
}
if ($delete) {
wp_delete_file($new_path);
}
$return->msg = esc_js(__('Image saved'));
return $return;
}