wp_save_image()
云策文档标注
概述
wp_save_image() 函数用于保存图像到文章,处理通过 $_REQUEST['history'] 传递的编辑更改。它支持缩放图像和应用历史更改,并更新附件元数据和备份尺寸。
关键要点
- 函数参数:$post_id(整数,必需),表示附件文章 ID。
- 返回值:stdClass 对象,包含成功状态、错误信息或缩略图 URL 等属性。
- 核心功能:基于 $_REQUEST 参数(如 'do'、'target'、'history')执行图像缩放或应用编辑更改。
- 文件处理:生成新文件名,保存图像文件,并更新附件文件路径和元数据。
- 备份机制:使用 _wp_attachment_backup_sizes 元数据备份原始尺寸,支持 IMAGE_EDIT_OVERWRITE 常量控制覆盖行为。
- 缩略图处理:根据 target 参数(如 'thumbnail'、'all'、'nothumb')生成或跳过特定尺寸的缩略图。
- 错误处理:返回错误信息,如无法创建图像、无更改或保存失败。
代码示例
function wp_save_image( $post_id ) {
// 函数实现代码,包括参数处理、图像编辑、文件保存和元数据更新
}注意事项
- 依赖 $_REQUEST 参数传递编辑数据,需确保在 AJAX 或表单提交中正确设置。
- 使用 filter 'image_edit_thumbnails_separately' 控制是否单独编辑缩略图。
- 图像缩放时,新尺寸不能大于原始尺寸,否则会返回错误。
- 如果定义了 IMAGE_EDIT_OVERWRITE 常量且为真,可能会覆盖现有编辑文件。
- 函数内部调用多个辅助函数,如 wp_get_image_editor() 和 image_edit_apply_changes(),需确保这些函数可用。
原文内容
Saves image to post, along with enqueued changes in $_REQUEST['history'].
Parameters
$post_idintrequired-
Attachment post ID.
Source
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;
}
}
}
$saved_image = wp_save_image_file( $new_path, $img, $post->post_mime_type, $post_id );
// Save the full-size file, also needed to create sub-sizes.
if ( ! $saved_image ) {
$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'],
'filesize' => $meta['filesize'],
'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'];
$meta['filesize'] = $saved_image['filesize'];
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;
}
Hooks
- apply_filters( ‘image_edit_thumbnails_separately’, bool $show )
-
Shows the settings in the Image Editor that allow selecting to edit only the thumbnail of an image.
Changelog
| Version | Description |
|---|---|
| 2.9.0 | Introduced. |