run:R W Run
7.85 KB
2026-03-11 16:18:51
R W Run
3.54 KB
2026-03-11 16:18:51
R W Run
148.33 KB
2026-03-11 16:18:51
R W Run
11.45 KB
2026-03-11 16:18:51
R W Run
3.58 KB
2026-03-11 16:18:51
R W Run
2.53 KB
2026-03-11 16:18:51
R W Run
2.6 KB
2026-03-11 16:18:51
R W Run
6.59 KB
2026-03-11 16:18:51
R W Run
14.83 KB
2026-03-11 16:18:51
R W Run
21.18 KB
2026-03-11 16:18:51
R W Run
48.13 KB
2026-03-11 16:18:51
R W Run
4.07 KB
2026-03-11 16:18:51
R W Run
5.3 KB
2026-03-11 16:18:51
R W Run
8.28 KB
2026-03-11 16:18:51
R W Run
26.73 KB
2026-03-11 16:18:51
R W Run
2.8 KB
2026-03-11 16:18:51
R W Run
15.2 KB
2026-03-11 16:18:51
R W Run
192.08 KB
2026-03-11 16:18:51
R W Run
11.77 KB
2026-03-11 16:18:51
R W Run
3.2 KB
2026-03-11 16:18:51
R W Run
22.89 KB
2026-03-11 16:18:51
R W Run
12.77 KB
2026-03-11 16:18:51
R W Run
4.08 KB
2026-03-11 16:18:51
R W Run
26.27 KB
2026-03-11 16:18:51
R W Run
4.97 KB
2026-03-11 16:18:51
R W Run
5.57 KB
2026-03-11 16:18:51
R W Run
13.93 KB
2026-03-11 16:18:51
R W Run
4.09 KB
2026-03-11 16:18:51
R W Run
6.79 KB
2026-03-11 16:18:51
R W Run
60.45 KB
2026-03-11 16:18:51
R W Run
32.4 KB
2026-03-11 16:18:51
R W Run
18.24 KB
2026-03-11 16:18:51
R W Run
66.01 KB
2026-03-11 16:18:51
R W Run
23.84 KB
2026-03-11 16:18:51
R W Run
17.72 KB
2026-03-11 16:18:51
R W Run
22.71 KB
2026-03-11 16:18:51
R W Run
18.05 KB
2026-03-11 16:18:51
R W Run
22.76 KB
2026-03-11 16:18:51
R W Run
7.34 KB
2026-03-11 16:18:51
R W Run
4.51 KB
2026-03-11 16:18:51
R W Run
9.02 KB
2026-03-11 16:18:51
R W Run
1.46 KB
2026-03-11 16:18:51
R W Run
51.76 KB
2026-03-11 16:18:51
R W Run
25.29 KB
2026-03-11 16:18:51
R W Run
21.61 KB
2026-03-11 16:18:51
R W Run
27.77 KB
2026-03-11 16:18:51
R W Run
15.35 KB
2026-03-11 16:18:51
R W Run
24.54 KB
2026-03-11 16:18:51
R W Run
56.44 KB
2026-03-11 16:18:51
R W Run
1.42 KB
2026-03-11 16:18:51
R W Run
63.66 KB
2026-03-11 16:18:51
R W Run
31.9 KB
2026-03-11 16:18:51
R W Run
14.44 KB
2026-03-11 16:18:51
R W Run
36.47 KB
2026-03-11 16:18:51
R W Run
14 KB
2026-03-11 16:18:51
R W Run
121.89 KB
2026-03-11 16:18:51
R W Run
6.26 KB
2026-03-11 16:18:51
R W Run
20.73 KB
2026-03-11 16:18:51
R W Run
15.23 KB
2026-03-11 16:18:51
R W Run
10.14 KB
2026-03-11 16:18:51
R W Run
6.94 KB
2026-03-11 16:18:51
R W Run
1.44 KB
2026-03-11 16:18:51
R W Run
46.85 KB
2026-03-11 16:18:51
R W Run
18.61 KB
2026-03-11 16:18:51
R W Run
6.08 KB
2026-03-11 16:18:51
R W Run
20.06 KB
2026-03-11 16:18:51
R W Run
5.73 KB
2026-03-11 16:18:51
R W Run
68.18 KB
2026-03-11 16:18:51
R W Run
40.8 KB
2026-03-11 16:18:51
R W Run
1.44 KB
2026-03-11 16:18:51
R W Run
25.26 KB
2026-03-11 16:18:51
R W Run
95.94 KB
2026-03-11 16:18:51
R W Run
43.12 KB
2026-03-11 16:18:51
R W Run
41.73 KB
2026-03-11 16:18:51
R W Run
6.46 KB
2026-03-11 16:18:51
R W Run
3.71 KB
2026-03-11 16:18:51
R W Run
116.31 KB
2026-03-11 16:18:51
R W Run
9.39 KB
2026-03-11 16:18:51
R W Run
64.34 KB
2026-03-11 16:18:51
R W Run
44.73 KB
2026-03-11 16:18:51
R W Run
1.27 KB
2026-03-11 16:18:51
R W Run
3.68 KB
2026-03-11 16:18:51
R W Run
33.53 KB
2026-03-11 16:18:51
R W Run
48.84 KB
2026-03-11 16:18:51
R W Run
26.35 KB
2026-03-11 16:18:51
R W Run
1.12 KB
2026-03-11 16:18:51
R W Run
4.19 KB
2026-03-11 16:18:51
R W Run
38.19 KB
2026-03-11 16:18:51
R W Run
91.33 KB
2026-03-11 16:18:51
R W Run
80.39 KB
2026-03-11 16:18:51
R W Run
32.67 KB
2026-03-11 16:18:51
R W Run
16.18 KB
2026-03-11 16:18:51
R W Run
44.46 KB
2026-03-11 16:18:51
R W Run
6.23 KB
2026-03-11 16:18:51
R W Run
8.23 KB
2026-03-11 16:18:51
R W Run
96.96 KB
2026-03-11 16:18:51
R W Run
6.83 KB
2026-03-11 16:18:51
R W Run
46.62 KB
2026-03-11 16:18:51
R W Run
10.82 KB
2026-03-11 16:18:51
R W Run
68.86 KB
2026-03-11 16:18:51
R W Run
33.63 KB
2026-03-11 16:18:51
R W Run
113.3 KB
2026-03-11 16:18:51
R W Run
22.98 KB
2026-03-11 16:18:51
R W Run
10.66 KB
2026-03-11 16:18:51
R W Run
error_log
📄image.php
1<?php
2/**
3 * File contains all the administration image manipulation functions.
4 *
5 * @package WordPress
6 * @subpackage Administration
7 */
8
9/**
10 * Crops an image to a given size.
11 *
12 * @since 2.1.0
13 *
14 * @param string|int $src The source file or Attachment ID.
15 * @param int $src_x The start x position to crop from.
16 * @param int $src_y The start y position to crop from.
17 * @param int $src_w The width to crop.
18 * @param int $src_h The height to crop.
19 * @param int $dst_w The destination width.
20 * @param int $dst_h The destination height.
21 * @param bool|false $src_abs Optional. If the source crop points are absolute.
22 * @param string|false $dst_file Optional. The destination file to write to.
23 * @return string|WP_Error New filepath on success, WP_Error on failure.
24 */
25function wp_crop_image( $src, $src_x, $src_y, $src_w, $src_h, $dst_w, $dst_h, $src_abs = false, $dst_file = false ) {
26 $src_file = $src;
27 if ( is_numeric( $src ) ) { // Handle int as attachment ID.
28 $src_file = get_attached_file( $src );
29
30 if ( ! file_exists( $src_file ) ) {
31 /*
32 * If the file doesn't exist, attempt a URL fopen on the src link.
33 * This can occur with certain file replication plugins.
34 */
35 $src = _load_image_to_edit_path( $src, 'full' );
36 } else {
37 $src = $src_file;
38 }
39 }
40
41 $editor = wp_get_image_editor( $src );
42 if ( is_wp_error( $editor ) ) {
43 return $editor;
44 }
45
46 $src = $editor->crop( $src_x, $src_y, $src_w, $src_h, $dst_w, $dst_h, $src_abs );
47 if ( is_wp_error( $src ) ) {
48 return $src;
49 }
50
51 if ( ! $dst_file ) {
52 $dst_file = str_replace( wp_basename( $src_file ), 'cropped-' . wp_basename( $src_file ), $src_file );
53 }
54
55 /*
56 * The directory containing the original file may no longer exist when
57 * using a replication plugin.
58 */
59 wp_mkdir_p( dirname( $dst_file ) );
60
61 $dst_file = dirname( $dst_file ) . '/' . wp_unique_filename( dirname( $dst_file ), wp_basename( $dst_file ) );
62
63 $result = $editor->save( $dst_file );
64 if ( is_wp_error( $result ) ) {
65 return $result;
66 }
67
68 if ( ! empty( $result['path'] ) ) {
69 return $result['path'];
70 }
71
72 return $dst_file;
73}
74
75/**
76 * Compare the existing image sub-sizes (as saved in the attachment meta)
77 * to the currently registered image sub-sizes, and return the difference.
78 *
79 * Registered sub-sizes that are larger than the image are skipped.
80 *
81 * @since 5.3.0
82 *
83 * @param int $attachment_id The image attachment post ID.
84 * @return array[] Associative array of arrays of image sub-size information for
85 * missing image sizes, keyed by image size name.
86 */
87function wp_get_missing_image_subsizes( $attachment_id ) {
88 if ( ! wp_attachment_is_image( $attachment_id ) ) {
89 return array();
90 }
91
92 $registered_sizes = wp_get_registered_image_subsizes();
93 $image_meta = wp_get_attachment_metadata( $attachment_id );
94
95 // Meta error?
96 if ( empty( $image_meta ) ) {
97 return $registered_sizes;
98 }
99
100 // Use the originally uploaded image dimensions as full_width and full_height.
101 if ( ! empty( $image_meta['original_image'] ) ) {
102 $image_file = wp_get_original_image_path( $attachment_id );
103 $imagesize = wp_getimagesize( $image_file );
104 }
105
106 if ( ! empty( $imagesize ) ) {
107 $full_width = $imagesize[0];
108 $full_height = $imagesize[1];
109 } else {
110 $full_width = (int) $image_meta['width'];
111 $full_height = (int) $image_meta['height'];
112 }
113
114 $possible_sizes = array();
115
116 // Skip registered sizes that are too large for the uploaded image.
117 foreach ( $registered_sizes as $size_name => $size_data ) {
118 if ( image_resize_dimensions( $full_width, $full_height, $size_data['width'], $size_data['height'], $size_data['crop'] ) ) {
119 $possible_sizes[ $size_name ] = $size_data;
120 }
121 }
122
123 if ( empty( $image_meta['sizes'] ) ) {
124 $image_meta['sizes'] = array();
125 }
126
127 /*
128 * Remove sizes that already exist. Only checks for matching "size names".
129 * It is possible that the dimensions for a particular size name have changed.
130 * For example the user has changed the values on the Settings -> Media screen.
131 * However we keep the old sub-sizes with the previous dimensions
132 * as the image may have been used in an older post.
133 */
134 $missing_sizes = array_diff_key( $possible_sizes, $image_meta['sizes'] );
135
136 /**
137 * Filters the array of missing image sub-sizes for an uploaded image.
138 *
139 * @since 5.3.0
140 *
141 * @param array[] $missing_sizes Associative array of arrays of image sub-size information for
142 * missing image sizes, keyed by image size name.
143 * @param array $image_meta The image meta data.
144 * @param int $attachment_id The image attachment post ID.
145 */
146 return apply_filters( 'wp_get_missing_image_subsizes', $missing_sizes, $image_meta, $attachment_id );
147}
148
149/**
150 * If any of the currently registered image sub-sizes are missing,
151 * create them and update the image meta data.
152 *
153 * @since 5.3.0
154 *
155 * @param int $attachment_id The image attachment post ID.
156 * @return array|WP_Error The updated image meta data array or WP_Error object
157 * if both the image meta and the attached file are missing.
158 */
159function wp_update_image_subsizes( $attachment_id ) {
160 $image_meta = wp_get_attachment_metadata( $attachment_id );
161 $image_file = wp_get_original_image_path( $attachment_id );
162
163 if ( empty( $image_meta ) || ! is_array( $image_meta ) ) {
164 /*
165 * Previously failed upload?
166 * If there is an uploaded file, make all sub-sizes and generate all of the attachment meta.
167 */
168 if ( ! empty( $image_file ) ) {
169 $image_meta = wp_create_image_subsizes( $image_file, $attachment_id );
170 } else {
171 return new WP_Error( 'invalid_attachment', __( 'The attached file cannot be found.' ) );
172 }
173 } else {
174 $missing_sizes = wp_get_missing_image_subsizes( $attachment_id );
175
176 if ( empty( $missing_sizes ) ) {
177 return $image_meta;
178 }
179
180 // This also updates the image meta.
181 $image_meta = _wp_make_subsizes( $missing_sizes, $image_file, $image_meta, $attachment_id );
182 }
183
184 /** This filter is documented in wp-admin/includes/image.php */
185 $image_meta = apply_filters( 'wp_generate_attachment_metadata', $image_meta, $attachment_id, 'update' );
186
187 // Save the updated metadata.
188 wp_update_attachment_metadata( $attachment_id, $image_meta );
189
190 return $image_meta;
191}
192
193/**
194 * Updates the attached file and image meta data when the original image was edited.
195 *
196 * @since 5.3.0
197 * @since 6.0.0 The `$filesize` value was added to the returned array.
198 * @access private
199 *
200 * @param array $saved_data The data returned from WP_Image_Editor after successfully saving an image.
201 * @param string $original_file Path to the original file.
202 * @param array $image_meta The image meta data.
203 * @param int $attachment_id The attachment post ID.
204 * @return array The updated image meta data.
205 */
206function _wp_image_meta_replace_original( $saved_data, $original_file, $image_meta, $attachment_id ) {
207 $new_file = $saved_data['path'];
208
209 // Update the attached file meta.
210 update_attached_file( $attachment_id, $new_file );
211
212 // Width and height of the new image.
213 $image_meta['width'] = $saved_data['width'];
214 $image_meta['height'] = $saved_data['height'];
215
216 // Make the file path relative to the upload dir.
217 $image_meta['file'] = _wp_relative_upload_path( $new_file );
218
219 // Add image file size.
220 $image_meta['filesize'] = wp_filesize( $new_file );
221
222 // Store the original image file name in image_meta.
223 $image_meta['original_image'] = wp_basename( $original_file );
224
225 return $image_meta;
226}
227
228/**
229 * Creates image sub-sizes, adds the new data to the image meta `sizes` array, and updates the image metadata.
230 *
231 * Intended for use after an image is uploaded. Saves/updates the image metadata after each
232 * sub-size is created. If there was an error, it is added to the returned image metadata array.
233 *
234 * @since 5.3.0
235 *
236 * @param string $file Full path to the image file.
237 * @param int $attachment_id Attachment ID to process.
238 * @return array The image attachment meta data.
239 */
240function wp_create_image_subsizes( $file, $attachment_id ) {
241 $imagesize = wp_getimagesize( $file );
242
243 if ( empty( $imagesize ) ) {
244 // File is not an image.
245 return array();
246 }
247
248 // Default image meta.
249 $image_meta = array(
250 'width' => $imagesize[0],
251 'height' => $imagesize[1],
252 'file' => _wp_relative_upload_path( $file ),
253 'filesize' => wp_filesize( $file ),
254 'sizes' => array(),
255 );
256
257 // Fetch additional metadata from EXIF/IPTC.
258 $exif_meta = wp_read_image_metadata( $file );
259
260 if ( $exif_meta ) {
261 $image_meta['image_meta'] = $exif_meta;
262 }
263
264 /**
265 * Filters the "BIG image" threshold value.
266 *
267 * If the original image width or height is above the threshold, it will be scaled down. The threshold is
268 * used as max width and max height. The scaled down image will be used as the largest available size, including
269 * the `_wp_attached_file` post meta value.
270 *
271 * Returning `false` from the filter callback will disable the scaling.
272 *
273 * @since 5.3.0
274 *
275 * @param int $threshold The threshold value in pixels. Default 2560.
276 * @param array $imagesize {
277 * Indexed array of the image width and height in pixels.
278 *
279 * @type int $0 The image width.
280 * @type int $1 The image height.
281 * }
282 * @param string $file Full path to the uploaded image file.
283 * @param int $attachment_id Attachment post ID.
284 */
285 $threshold = (int) apply_filters( 'big_image_size_threshold', 2560, $imagesize, $file, $attachment_id );
286
287 /*
288 * If the original image's dimensions are over the threshold,
289 * scale the image and use it as the "full" size.
290 */
291 $scale_down = false;
292 $convert = false;
293
294 if ( $threshold && ( $image_meta['width'] > $threshold || $image_meta['height'] > $threshold ) ) {
295 // The image will be converted if needed on saving.
296 $scale_down = true;
297 } else {
298 // The image may need to be converted regardless of its dimensions.
299 $output_format = wp_get_image_editor_output_format( $file, $imagesize['mime'] );
300
301 if (
302 is_array( $output_format ) &&
303 array_key_exists( $imagesize['mime'], $output_format ) &&
304 $output_format[ $imagesize['mime'] ] !== $imagesize['mime']
305 ) {
306 $convert = true;
307 }
308 }
309
310 if ( $scale_down || $convert ) {
311 $editor = wp_get_image_editor( $file );
312
313 if ( is_wp_error( $editor ) ) {
314 // This image cannot be edited.
315 return $image_meta;
316 }
317
318 if ( $scale_down ) {
319 // Resize the image. This will also convet it if needed.
320 $resized = $editor->resize( $threshold, $threshold );
321 } elseif ( $convert ) {
322 // The image will be converted (if possible) when saved.
323 $resized = true;
324 }
325
326 $rotated = null;
327
328 // If there is EXIF data, rotate according to EXIF Orientation.
329 if ( ! is_wp_error( $resized ) && is_array( $exif_meta ) ) {
330 $resized = $editor->maybe_exif_rotate();
331 $rotated = $resized; // bool true or WP_Error
332 }
333
334 if ( ! is_wp_error( $resized ) ) {
335 /*
336 * Append "-scaled" to the image file name. It will look like "my_image-scaled.jpg".
337 * This doesn't affect the sub-sizes names as they are generated from the original image (for best quality).
338 */
339 if ( $scale_down ) {
340 $saved = $editor->save( $editor->generate_filename( 'scaled' ) );
341 } elseif ( $convert ) {
342 // Pass an empty string to avoid adding a suffix to converted file names.
343 $saved = $editor->save( $editor->generate_filename( '' ) );
344 } else {
345 $saved = $editor->save();
346 }
347
348 if ( ! is_wp_error( $saved ) ) {
349 $image_meta = _wp_image_meta_replace_original( $saved, $file, $image_meta, $attachment_id );
350
351 // If the image was rotated update the stored EXIF data.
352 if ( true === $rotated && ! empty( $image_meta['image_meta']['orientation'] ) ) {
353 $image_meta['image_meta']['orientation'] = 1;
354 }
355 } else {
356 // TODO: Log errors.
357 }
358 } else {
359 // TODO: Log errors.
360 }
361 } elseif ( ! empty( $exif_meta['orientation'] ) && 1 !== (int) $exif_meta['orientation'] ) {
362 // Rotate the whole original image if there is EXIF data and "orientation" is not 1.
363 $editor = wp_get_image_editor( $file );
364
365 if ( is_wp_error( $editor ) ) {
366 // This image cannot be edited.
367 return $image_meta;
368 }
369
370 // Rotate the image.
371 $rotated = $editor->maybe_exif_rotate();
372
373 if ( true === $rotated ) {
374 // Append `-rotated` to the image file name.
375 $saved = $editor->save( $editor->generate_filename( 'rotated' ) );
376
377 if ( ! is_wp_error( $saved ) ) {
378 $image_meta = _wp_image_meta_replace_original( $saved, $file, $image_meta, $attachment_id );
379
380 // Update the stored EXIF data.
381 if ( ! empty( $image_meta['image_meta']['orientation'] ) ) {
382 $image_meta['image_meta']['orientation'] = 1;
383 }
384 } else {
385 // TODO: Log errors.
386 }
387 }
388 }
389
390 /*
391 * Initial save of the new metadata.
392 * At this point the file was uploaded and moved to the uploads directory
393 * but the image sub-sizes haven't been created yet and the `sizes` array is empty.
394 */
395 wp_update_attachment_metadata( $attachment_id, $image_meta );
396
397 $new_sizes = wp_get_registered_image_subsizes();
398
399 /**
400 * Filters the image sizes automatically generated when uploading an image.
401 *
402 * @since 2.9.0
403 * @since 4.4.0 Added the `$image_meta` argument.
404 * @since 5.3.0 Added the `$attachment_id` argument.
405 *
406 * @param array $new_sizes Associative array of image sizes to be created.
407 * @param array $image_meta The image meta data: width, height, file, sizes, etc.
408 * @param int $attachment_id The attachment post ID for the image.
409 */
410 $new_sizes = apply_filters( 'intermediate_image_sizes_advanced', $new_sizes, $image_meta, $attachment_id );
411
412 return _wp_make_subsizes( $new_sizes, $file, $image_meta, $attachment_id );
413}
414
415/**
416 * Low-level function to create image sub-sizes.
417 *
418 * Updates the image meta after each sub-size is created.
419 * Errors are stored in the returned image metadata array.
420 *
421 * @since 5.3.0
422 * @access private
423 *
424 * @param array $new_sizes Array defining what sizes to create.
425 * @param string $file Full path to the image file.
426 * @param array $image_meta The attachment meta data array.
427 * @param int $attachment_id Attachment ID to process.
428 * @return array The attachment meta data with updated `sizes` array. Includes an array of errors encountered while resizing.
429 */
430function _wp_make_subsizes( $new_sizes, $file, $image_meta, $attachment_id ) {
431 if ( empty( $image_meta ) || ! is_array( $image_meta ) ) {
432 // Not an image attachment.
433 return array();
434 }
435
436 // Check if any of the new sizes already exist.
437 if ( isset( $image_meta['sizes'] ) && is_array( $image_meta['sizes'] ) ) {
438 foreach ( $image_meta['sizes'] as $size_name => $size_meta ) {
439 /*
440 * Only checks "size name" so we don't override existing images even if the dimensions
441 * don't match the currently defined size with the same name.
442 * To change the behavior, unset changed/mismatched sizes in the `sizes` array in image meta.
443 */
444 if ( array_key_exists( $size_name, $new_sizes ) ) {
445 unset( $new_sizes[ $size_name ] );
446 }
447 }
448 } else {
449 $image_meta['sizes'] = array();
450 }
451
452 if ( empty( $new_sizes ) ) {
453 // Nothing to do...
454 return $image_meta;
455 }
456
457 /*
458 * Sort the image sub-sizes in order of priority when creating them.
459 * This ensures there is an appropriate sub-size the user can access immediately
460 * even when there was an error and not all sub-sizes were created.
461 */
462 $priority = array(
463 'medium' => null,
464 'large' => null,
465 'thumbnail' => null,
466 'medium_large' => null,
467 );
468
469 $new_sizes = array_filter( array_merge( $priority, $new_sizes ) );
470
471 $editor = wp_get_image_editor( $file );
472
473 if ( is_wp_error( $editor ) ) {
474 // The image cannot be edited.
475 return $image_meta;
476 }
477
478 // If stored EXIF data exists, rotate the source image before creating sub-sizes.
479 if ( ! empty( $image_meta['image_meta'] ) ) {
480 $rotated = $editor->maybe_exif_rotate();
481
482 if ( is_wp_error( $rotated ) ) {
483 // TODO: Log errors.
484 }
485 }
486
487 if ( method_exists( $editor, 'make_subsize' ) ) {
488 foreach ( $new_sizes as $new_size_name => $new_size_data ) {
489 $new_size_meta = $editor->make_subsize( $new_size_data );
490
491 if ( is_wp_error( $new_size_meta ) ) {
492 // TODO: Log errors.
493 } else {
494 // Save the size meta value.
495 $image_meta['sizes'][ $new_size_name ] = $new_size_meta;
496 wp_update_attachment_metadata( $attachment_id, $image_meta );
497 }
498 }
499 } else {
500 // Fall back to `$editor->multi_resize()`.
501 $created_sizes = $editor->multi_resize( $new_sizes );
502
503 if ( ! empty( $created_sizes ) ) {
504 $image_meta['sizes'] = array_merge( $image_meta['sizes'], $created_sizes );
505 wp_update_attachment_metadata( $attachment_id, $image_meta );
506 }
507 }
508
509 return $image_meta;
510}
511
512/**
513 * Copy parent attachment properties to newly cropped image.
514 *
515 * @since 6.5.0
516 *
517 * @param string $cropped Path to the cropped image file.
518 * @param int $parent_attachment_id Parent file Attachment ID.
519 * @param string $context Control calling the function.
520 * @return array Properties of attachment.
521 */
522function wp_copy_parent_attachment_properties( $cropped, $parent_attachment_id, $context = '' ) {
523 $parent = get_post( $parent_attachment_id );
524 $parent_url = wp_get_attachment_url( $parent->ID );
525 $parent_basename = wp_basename( $parent_url );
526 $url = str_replace( wp_basename( $parent_url ), wp_basename( $cropped ), $parent_url );
527
528 $size = wp_getimagesize( $cropped );
529 $image_type = $size ? $size['mime'] : 'image/jpeg';
530
531 $sanitized_post_title = sanitize_file_name( $parent->post_title );
532 $use_original_title = (
533 ( '' !== trim( $parent->post_title ) ) &&
534 /*
535 * Check if the original image has a title other than the "filename" default,
536 * meaning the image had a title when originally uploaded or its title was edited.
537 */
538 ( $parent_basename !== $sanitized_post_title ) &&
539 ( pathinfo( $parent_basename, PATHINFO_FILENAME ) !== $sanitized_post_title )
540 );
541 $use_original_description = ( '' !== trim( $parent->post_content ) );
542
543 $attachment = array(
544 'post_title' => $use_original_title ? $parent->post_title : wp_basename( $cropped ),
545 'post_content' => $use_original_description ? $parent->post_content : $url,
546 'post_mime_type' => $image_type,
547 'guid' => $url,
548 'context' => $context,
549 );
550
551 // Copy the image caption attribute (post_excerpt field) from the original image.
552 if ( '' !== trim( $parent->post_excerpt ) ) {
553 $attachment['post_excerpt'] = $parent->post_excerpt;
554 }
555
556 // Copy the image alt text attribute from the original image.
557 if ( '' !== trim( $parent->_wp_attachment_image_alt ) ) {
558 $attachment['meta_input'] = array(
559 '_wp_attachment_image_alt' => wp_slash( $parent->_wp_attachment_image_alt ),
560 );
561 }
562
563 $attachment['post_parent'] = $parent_attachment_id;
564
565 return $attachment;
566}
567
568/**
569 * Generates attachment meta data and create image sub-sizes for images.
570 *
571 * @since 2.1.0
572 * @since 6.0.0 The `$filesize` value was added to the returned array.
573 * @since 6.7.0 The 'image/heic' mime type is supported.
574 *
575 * @param int $attachment_id Attachment ID to process.
576 * @param string $file Filepath of the attached image.
577 * @return array Metadata for attachment.
578 */
579function wp_generate_attachment_metadata( $attachment_id, $file ) {
580 $attachment = get_post( $attachment_id );
581
582 $metadata = array();
583 $support = false;
584 $mime_type = get_post_mime_type( $attachment );
585
586 if ( 'image/heic' === $mime_type || ( preg_match( '!^image/!', $mime_type ) && file_is_displayable_image( $file ) ) ) {
587 // Make thumbnails and other intermediate sizes.
588 $metadata = wp_create_image_subsizes( $file, $attachment_id );
589 } elseif ( wp_attachment_is( 'video', $attachment ) ) {
590 $metadata = wp_read_video_metadata( $file );
591 $support = current_theme_supports( 'post-thumbnails', 'attachment:video' ) || post_type_supports( 'attachment:video', 'thumbnail' );
592 } elseif ( wp_attachment_is( 'audio', $attachment ) ) {
593 $metadata = wp_read_audio_metadata( $file );
594 $support = current_theme_supports( 'post-thumbnails', 'attachment:audio' ) || post_type_supports( 'attachment:audio', 'thumbnail' );
595 }
596
597 /*
598 * wp_read_video_metadata() and wp_read_audio_metadata() return `false`
599 * if the attachment does not exist in the local filesystem,
600 * so make sure to convert the value to an array.
601 */
602 if ( ! is_array( $metadata ) ) {
603 $metadata = array();
604 }
605
606 if ( $support && ! empty( $metadata['image']['data'] ) ) {
607 // Check for existing cover.
608 $hash = md5( $metadata['image']['data'] );
609 $posts = get_posts(
610 array(
611 'fields' => 'ids',
612 'post_type' => 'attachment',
613 'post_mime_type' => $metadata['image']['mime'],
614 'post_status' => 'inherit',
615 'posts_per_page' => 1,
616 'meta_key' => '_cover_hash',
617 'meta_value' => $hash,
618 )
619 );
620 $exists = reset( $posts );
621
622 if ( ! empty( $exists ) ) {
623 update_post_meta( $attachment_id, '_thumbnail_id', $exists );
624 } else {
625 $ext = '.jpg';
626 switch ( $metadata['image']['mime'] ) {
627 case 'image/gif':
628 $ext = '.gif';
629 break;
630 case 'image/png':
631 $ext = '.png';
632 break;
633 case 'image/webp':
634 $ext = '.webp';
635 break;
636 }
637 $basename = str_replace( '.', '-', wp_basename( $file ) ) . '-image' . $ext;
638 $uploaded = wp_upload_bits( $basename, '', $metadata['image']['data'] );
639 if ( false === $uploaded['error'] ) {
640 $image_attachment = array(
641 'post_mime_type' => $metadata['image']['mime'],
642 'post_type' => 'attachment',
643 'post_content' => '',
644 );
645 /**
646 * Filters the parameters for the attachment thumbnail creation.
647 *
648 * @since 3.9.0
649 *
650 * @param array $image_attachment An array of parameters to create the thumbnail.
651 * @param array $metadata Current attachment metadata.
652 * @param array $uploaded {
653 * Information about the newly-uploaded file.
654 *
655 * @type string $file Filename of the newly-uploaded file.
656 * @type string $url URL of the uploaded file.
657 * @type string $type File type.
658 * }
659 */
660 $image_attachment = apply_filters( 'attachment_thumbnail_args', $image_attachment, $metadata, $uploaded );
661
662 $sub_attachment_id = wp_insert_attachment( $image_attachment, $uploaded['file'] );
663 add_post_meta( $sub_attachment_id, '_cover_hash', $hash );
664 $attach_data = wp_generate_attachment_metadata( $sub_attachment_id, $uploaded['file'] );
665 wp_update_attachment_metadata( $sub_attachment_id, $attach_data );
666 update_post_meta( $attachment_id, '_thumbnail_id', $sub_attachment_id );
667 }
668 }
669 } elseif ( 'application/pdf' === $mime_type ) {
670 // Try to create image thumbnails for PDFs.
671
672 $fallback_sizes = array(
673 'thumbnail',
674 'medium',
675 'large',
676 );
677
678 /**
679 * Filters the image sizes generated for non-image mime types.
680 *
681 * @since 4.7.0
682 *
683 * @param string[] $fallback_sizes An array of image size names.
684 * @param array $metadata Current attachment metadata.
685 */
686 $fallback_sizes = apply_filters( 'fallback_intermediate_image_sizes', $fallback_sizes, $metadata );
687
688 $registered_sizes = wp_get_registered_image_subsizes();
689 $merged_sizes = array_intersect_key( $registered_sizes, array_flip( $fallback_sizes ) );
690
691 // Force thumbnails to be soft crops.
692 if ( isset( $merged_sizes['thumbnail'] ) && is_array( $merged_sizes['thumbnail'] ) ) {
693 $merged_sizes['thumbnail']['crop'] = false;
694 }
695
696 // Only load PDFs in an image editor if we're processing sizes.
697 if ( ! empty( $merged_sizes ) ) {
698 $editor = wp_get_image_editor( $file );
699
700 if ( ! is_wp_error( $editor ) ) { // No support for this type of file.
701 /*
702 * PDFs may have the same file filename as JPEGs.
703 * Ensure the PDF preview image does not overwrite any JPEG images that already exist.
704 */
705 $dirname = dirname( $file ) . '/';
706 $ext = '.' . pathinfo( $file, PATHINFO_EXTENSION );
707 $preview_file = $dirname . wp_unique_filename( $dirname, wp_basename( $file, $ext ) . '-pdf.jpg' );
708
709 $uploaded = $editor->save( $preview_file, 'image/jpeg' );
710 unset( $editor );
711
712 // Resize based on the full size image, rather than the source.
713 if ( ! is_wp_error( $uploaded ) ) {
714 $image_file = $uploaded['path'];
715 unset( $uploaded['path'] );
716
717 $metadata['sizes'] = array(
718 'full' => $uploaded,
719 );
720
721 // Save the meta data before any image post-processing errors could happen.
722 wp_update_attachment_metadata( $attachment_id, $metadata );
723
724 // Create sub-sizes saving the image meta after each.
725 $metadata = _wp_make_subsizes( $merged_sizes, $image_file, $metadata, $attachment_id );
726 }
727 }
728 }
729 }
730
731 // Remove the blob of binary data from the array.
732 unset( $metadata['image']['data'] );
733
734 // Capture file size for cases where it has not been captured yet, such as PDFs.
735 if ( ! isset( $metadata['filesize'] ) && file_exists( $file ) ) {
736 $metadata['filesize'] = wp_filesize( $file );
737 }
738
739 /**
740 * Filters the generated attachment meta data.
741 *
742 * @since 2.1.0
743 * @since 5.3.0 The `$context` parameter was added.
744 *
745 * @param array $metadata An array of attachment meta data.
746 * @param int $attachment_id Current attachment ID.
747 * @param string $context Additional context. Can be 'create' when metadata was initially created for new attachment
748 * or 'update' when the metadata was updated.
749 */
750 return apply_filters( 'wp_generate_attachment_metadata', $metadata, $attachment_id, 'create' );
751}
752
753/**
754 * Converts a fraction string to a decimal.
755 *
756 * @since 2.5.0
757 *
758 * @param string $str Fraction string.
759 * @return int|float Returns calculated fraction or integer 0 on invalid input.
760 */
761function wp_exif_frac2dec( $str ) {
762 if ( ! is_scalar( $str ) || is_bool( $str ) ) {
763 return 0;
764 }
765
766 if ( ! is_string( $str ) ) {
767 return $str; // This can only be an integer or float, so this is fine.
768 }
769
770 // Fractions passed as a string must contain a single `/`.
771 if ( substr_count( $str, '/' ) !== 1 ) {
772 if ( is_numeric( $str ) ) {
773 return (float) $str;
774 }
775
776 return 0;
777 }
778
779 list( $numerator, $denominator ) = explode( '/', $str );
780
781 // Both the numerator and the denominator must be numbers.
782 if ( ! is_numeric( $numerator ) || ! is_numeric( $denominator ) ) {
783 return 0;
784 }
785
786 // The denominator must not be zero.
787 if ( 0 == $denominator ) { // phpcs:ignore Universal.Operators.StrictComparisons.LooseEqual -- Deliberate loose comparison.
788 return 0;
789 }
790
791 return $numerator / $denominator;
792}
793
794/**
795 * Converts the exif date format to a unix timestamp.
796 *
797 * @since 2.5.0
798 *
799 * @param string $str A date string expected to be in Exif format (Y:m:d H:i:s).
800 * @return int|false The unix timestamp, or false on failure.
801 */
802function wp_exif_date2ts( $str ) {
803 list( $date, $time ) = explode( ' ', trim( $str ) );
804 list( $y, $m, $d ) = explode( ':', $date );
805
806 return strtotime( "{$y}-{$m}-{$d} {$time}" );
807}
808
809/**
810 * Gets extended image metadata, exif or iptc as available.
811 *
812 * Retrieves the EXIF metadata aperture, credit, camera, caption, copyright, iso
813 * created_timestamp, focal_length, shutter_speed, and title.
814 *
815 * The IPTC metadata that is retrieved is APP13, credit, byline, created date
816 * and time, caption, copyright, and title. Also includes FNumber, Model,
817 * DateTimeDigitized, FocalLength, ISOSpeedRatings, and ExposureTime.
818 *
819 * @todo Try other exif libraries if available.
820 * @since 2.5.0
821 *
822 * @param string $file
823 * @return array|false Image metadata array on success, false on failure.
824 */
825function wp_read_image_metadata( $file ) {
826 if ( ! file_exists( $file ) ) {
827 return false;
828 }
829
830 $image_size = wp_getimagesize( $file );
831
832 if ( false === $image_size ) {
833 return false;
834 }
835
836 list( , , $image_type ) = $image_size;
837
838 /*
839 * EXIF contains a bunch of data we'll probably never need formatted in ways
840 * that are difficult to use. We'll normalize it and just extract the fields
841 * that are likely to be useful. Fractions and numbers are converted to
842 * floats, dates to unix timestamps, and everything else to strings.
843 */
844 $meta = array(
845 'aperture' => 0,
846 'credit' => '',
847 'camera' => '',
848 'caption' => '',
849 'created_timestamp' => 0,
850 'copyright' => '',
851 'focal_length' => 0,
852 'iso' => 0,
853 'shutter_speed' => 0,
854 'title' => '',
855 'orientation' => 0,
856 'keywords' => array(),
857 );
858
859 $iptc = array();
860 $info = array();
861 /*
862 * Read IPTC first, since it might contain data not available in exif such
863 * as caption, description etc.
864 */
865 if ( is_callable( 'iptcparse' ) ) {
866 wp_getimagesize( $file, $info );
867
868 if ( ! empty( $info['APP13'] ) ) {
869 // Don't silence errors when in debug mode, unless running unit tests.
870 if ( defined( 'WP_DEBUG' ) && WP_DEBUG
871 && ! defined( 'WP_RUN_CORE_TESTS' )
872 ) {
873 $iptc = iptcparse( $info['APP13'] );
874 } else {
875 // Silencing notice and warning is intentional. See https://core.trac.wordpress.org/ticket/42480
876 $iptc = @iptcparse( $info['APP13'] );
877 }
878
879 if ( ! is_array( $iptc ) ) {
880 $iptc = array();
881 }
882
883 // Headline, "A brief synopsis of the caption".
884 if ( ! empty( $iptc['2#105'][0] ) ) {
885 $meta['title'] = trim( $iptc['2#105'][0] );
886 /*
887 * Title, "Many use the Title field to store the filename of the image,
888 * though the field may be used in many ways".
889 */
890 } elseif ( ! empty( $iptc['2#005'][0] ) ) {
891 $meta['title'] = trim( $iptc['2#005'][0] );
892 }
893
894 if ( ! empty( $iptc['2#120'][0] ) ) { // Description / legacy caption.
895 $caption = trim( $iptc['2#120'][0] );
896
897 mbstring_binary_safe_encoding();
898 $caption_length = strlen( $caption );
899 reset_mbstring_encoding();
900
901 if ( empty( $meta['title'] ) && $caption_length < 80 ) {
902 // Assume the title is stored in 2:120 if it's short.
903 $meta['title'] = $caption;
904 }
905
906 $meta['caption'] = $caption;
907 }
908
909 if ( ! empty( $iptc['2#110'][0] ) ) { // Credit.
910 $meta['credit'] = trim( $iptc['2#110'][0] );
911 } elseif ( ! empty( $iptc['2#080'][0] ) ) { // Creator / legacy byline.
912 $meta['credit'] = trim( $iptc['2#080'][0] );
913 }
914
915 if ( ! empty( $iptc['2#055'][0] ) && ! empty( $iptc['2#060'][0] ) ) { // Created date and time.
916 $meta['created_timestamp'] = strtotime( $iptc['2#055'][0] . ' ' . $iptc['2#060'][0] );
917 }
918
919 if ( ! empty( $iptc['2#116'][0] ) ) { // Copyright.
920 $meta['copyright'] = trim( $iptc['2#116'][0] );
921 }
922
923 if ( ! empty( $iptc['2#025'][0] ) ) { // Keywords array.
924 $meta['keywords'] = array_values( $iptc['2#025'] );
925 }
926 }
927 }
928
929 $exif = array();
930
931 /**
932 * Filters the image types to check for exif data.
933 *
934 * @since 2.5.0
935 *
936 * @param int[] $image_types Array of image types to check for exif data. Each value
937 * is usually one of the `IMAGETYPE_*` constants.
938 */
939 $exif_image_types = apply_filters( 'wp_read_image_metadata_types', array( IMAGETYPE_JPEG, IMAGETYPE_TIFF_II, IMAGETYPE_TIFF_MM ) );
940
941 if ( is_callable( 'exif_read_data' ) && in_array( $image_type, $exif_image_types, true ) ) {
942 // Don't silence errors when in debug mode, unless running unit tests.
943 if ( defined( 'WP_DEBUG' ) && WP_DEBUG
944 && ! defined( 'WP_RUN_CORE_TESTS' )
945 ) {
946 $exif = exif_read_data( $file );
947 } else {
948 // Silencing notice and warning is intentional. See https://core.trac.wordpress.org/ticket/42480
949 $exif = @exif_read_data( $file );
950 }
951
952 if ( ! is_array( $exif ) ) {
953 $exif = array();
954 }
955
956 $exif_description = '';
957 $exif_usercomment = '';
958 if ( ! empty( $exif['ImageDescription'] ) ) {
959 $exif_description = trim( $exif['ImageDescription'] );
960 }
961
962 if ( ! empty( $exif['COMPUTED']['UserComment'] ) ) {
963 $exif_usercomment = trim( $exif['COMPUTED']['UserComment'] );
964 }
965
966 if ( $exif_description ) {
967 mbstring_binary_safe_encoding();
968 $description_length = strlen( $exif_description );
969 reset_mbstring_encoding();
970 if ( empty( $meta['title'] ) && $description_length < 80 ) {
971 // Assume the title is stored in ImageDescription.
972 $meta['title'] = $exif_description;
973 }
974
975 // If both user comments and description are present.
976 if ( empty( $meta['caption'] ) && $exif_usercomment ) {
977 if ( ! empty( $meta['title'] ) && $exif_description === $meta['title'] ) {
978 $caption = $exif_usercomment;
979 } else {
980 if ( $exif_description === $exif_usercomment ) {
981 $caption = $exif_description;
982 } else {
983 $caption = trim( $exif_description . ' ' . $exif_usercomment );
984 }
985 }
986 $meta['caption'] = $caption;
987 }
988
989 if ( empty( $meta['caption'] ) && $exif_usercomment ) {
990 $meta['caption'] = $exif_usercomment;
991 }
992
993 if ( empty( $meta['caption'] ) ) {
994 $meta['caption'] = $exif_description;
995 }
996 } elseif ( empty( $meta['caption'] ) && $exif_usercomment ) {
997 $meta['caption'] = $exif_usercomment;
998 $description_length = strlen( $exif_usercomment );
999 if ( empty( $meta['title'] ) && $description_length < 80 ) {
1000 $meta['title'] = trim( $exif_usercomment );
1001 }
1002 } elseif ( empty( $meta['caption'] ) && ! empty( $exif['Comments'] ) ) {
1003 $meta['caption'] = trim( $exif['Comments'] );
1004 }
1005
1006 if ( empty( $meta['credit'] ) ) {
1007 if ( ! empty( $exif['Artist'] ) ) {
1008 $meta['credit'] = trim( $exif['Artist'] );
1009 } elseif ( ! empty( $exif['Author'] ) ) {
1010 $meta['credit'] = trim( $exif['Author'] );
1011 }
1012 }
1013
1014 if ( empty( $meta['copyright'] ) && ! empty( $exif['Copyright'] ) ) {
1015 $meta['copyright'] = trim( $exif['Copyright'] );
1016 }
1017 if ( ! empty( $exif['FNumber'] ) && is_scalar( $exif['FNumber'] ) ) {
1018 $meta['aperture'] = round( wp_exif_frac2dec( $exif['FNumber'] ), 2 );
1019 }
1020 if ( ! empty( $exif['Model'] ) ) {
1021 $meta['camera'] = trim( $exif['Model'] );
1022 }
1023 if ( empty( $meta['created_timestamp'] ) && ! empty( $exif['DateTimeDigitized'] ) ) {
1024 $meta['created_timestamp'] = wp_exif_date2ts( $exif['DateTimeDigitized'] );
1025 }
1026 if ( ! empty( $exif['FocalLength'] ) ) {
1027 $meta['focal_length'] = (string) $exif['FocalLength'];
1028 if ( is_scalar( $exif['FocalLength'] ) ) {
1029 $meta['focal_length'] = (string) wp_exif_frac2dec( $exif['FocalLength'] );
1030 }
1031 }
1032 if ( ! empty( $exif['ISOSpeedRatings'] ) ) {
1033 $meta['iso'] = is_array( $exif['ISOSpeedRatings'] ) ? reset( $exif['ISOSpeedRatings'] ) : $exif['ISOSpeedRatings'];
1034 $meta['iso'] = trim( $meta['iso'] );
1035 }
1036 if ( ! empty( $exif['ExposureTime'] ) ) {
1037 $meta['shutter_speed'] = (string) $exif['ExposureTime'];
1038 if ( is_scalar( $exif['ExposureTime'] ) ) {
1039 $meta['shutter_speed'] = (string) wp_exif_frac2dec( $exif['ExposureTime'] );
1040 }
1041 }
1042 if ( ! empty( $exif['Orientation'] ) ) {
1043 $meta['orientation'] = $exif['Orientation'];
1044 }
1045 }
1046
1047 foreach ( array( 'title', 'caption', 'credit', 'copyright', 'camera', 'iso' ) as $key ) {
1048 if ( $meta[ $key ] && ! wp_is_valid_utf8( $meta[ $key ] ) ) {
1049 $meta[ $key ] = utf8_encode( $meta[ $key ] );
1050 }
1051 }
1052
1053 foreach ( $meta['keywords'] as $key => $keyword ) {
1054 if ( ! wp_is_valid_utf8( $keyword ) ) {
1055 $meta['keywords'][ $key ] = utf8_encode( $keyword );
1056 }
1057 }
1058
1059 $meta = wp_kses_post_deep( $meta );
1060
1061 /**
1062 * Filters the array of meta data read from an image's exif data.
1063 *
1064 * @since 2.5.0
1065 * @since 4.4.0 The `$iptc` parameter was added.
1066 * @since 5.0.0 The `$exif` parameter was added.
1067 *
1068 * @param array $meta Image meta data.
1069 * @param string $file Path to image file.
1070 * @param int $image_type Type of image, one of the `IMAGETYPE_XXX` constants.
1071 * @param array $iptc IPTC data.
1072 * @param array $exif EXIF data.
1073 */
1074 return apply_filters( 'wp_read_image_metadata', $meta, $file, $image_type, $iptc, $exif );
1075}
1076
1077/**
1078 * Validates that file is an image.
1079 *
1080 * @since 2.5.0
1081 *
1082 * @param string $path File path to test if valid image.
1083 * @return bool True if valid image, false if not valid image.
1084 */
1085function file_is_valid_image( $path ) {
1086 $size = wp_getimagesize( $path );
1087 return ! empty( $size );
1088}
1089
1090/**
1091 * Validates that file is suitable for displaying within a web page.
1092 *
1093 * @since 2.5.0
1094 *
1095 * @param string $path File path to test.
1096 * @return bool True if suitable, false if not suitable.
1097 */
1098function file_is_displayable_image( $path ) {
1099 $displayable_image_types = array( IMAGETYPE_GIF, IMAGETYPE_JPEG, IMAGETYPE_PNG, IMAGETYPE_BMP, IMAGETYPE_ICO, IMAGETYPE_WEBP, IMAGETYPE_AVIF );
1100
1101 $info = wp_getimagesize( $path );
1102 if ( empty( $info ) ) {
1103 $result = false;
1104 } elseif ( ! in_array( $info[2], $displayable_image_types, true ) ) {
1105 $result = false;
1106 } else {
1107 $result = true;
1108 }
1109
1110 /**
1111 * Filters whether the current image is displayable in the browser.
1112 *
1113 * @since 2.5.0
1114 *
1115 * @param bool $result Whether the image can be displayed. Default true.
1116 * @param string $path Path to the image.
1117 */
1118 return apply_filters( 'file_is_displayable_image', $result, $path );
1119}
1120
1121/**
1122 * Loads an image resource for editing.
1123 *
1124 * @since 2.9.0
1125 *
1126 * @param int $attachment_id Attachment ID.
1127 * @param string $mime_type Image mime type.
1128 * @param string|int[] $size Optional. Image size. Accepts any registered image size name, or an array
1129 * of width and height values in pixels (in that order). Default 'full'.
1130 * @return resource|GdImage|false The resulting image resource or GdImage instance on success,
1131 * false on failure.
1132 */
1133function load_image_to_edit( $attachment_id, $mime_type, $size = 'full' ) {
1134 $filepath = _load_image_to_edit_path( $attachment_id, $size );
1135 if ( empty( $filepath ) ) {
1136 return false;
1137 }
1138
1139 switch ( $mime_type ) {
1140 case 'image/jpeg':
1141 $image = imagecreatefromjpeg( $filepath );
1142 break;
1143 case 'image/png':
1144 $image = imagecreatefrompng( $filepath );
1145 break;
1146 case 'image/gif':
1147 $image = imagecreatefromgif( $filepath );
1148 break;
1149 case 'image/webp':
1150 $image = false;
1151 if ( function_exists( 'imagecreatefromwebp' ) ) {
1152 $image = imagecreatefromwebp( $filepath );
1153 }
1154 break;
1155 default:
1156 $image = false;
1157 break;
1158 }
1159
1160 if ( is_gd_image( $image ) ) {
1161 /**
1162 * Filters the current image being loaded for editing.
1163 *
1164 * @since 2.9.0
1165 *
1166 * @param resource|GdImage $image Current image.
1167 * @param int $attachment_id Attachment ID.
1168 * @param string|int[] $size Requested image size. Can be any registered image size name, or
1169 * an array of width and height values in pixels (in that order).
1170 */
1171 $image = apply_filters( 'load_image_to_edit', $image, $attachment_id, $size );
1172
1173 if ( function_exists( 'imagealphablending' ) && function_exists( 'imagesavealpha' ) ) {
1174 imagealphablending( $image, false );
1175 imagesavealpha( $image, true );
1176 }
1177 }
1178
1179 return $image;
1180}
1181
1182/**
1183 * Retrieves the path or URL of an attachment's attached file.
1184 *
1185 * If the attached file is not present on the local filesystem (usually due to replication plugins),
1186 * then the URL of the file is returned if `allow_url_fopen` is supported.
1187 *
1188 * @since 3.4.0
1189 * @access private
1190 *
1191 * @param int $attachment_id Attachment ID.
1192 * @param string|int[] $size Optional. Image size. Accepts any registered image size name, or an array
1193 * of width and height values in pixels (in that order). Default 'full'.
1194 * @return string|false File path or URL on success, false on failure.
1195 */
1196function _load_image_to_edit_path( $attachment_id, $size = 'full' ) {
1197 $filepath = get_attached_file( $attachment_id );
1198
1199 if ( $filepath && file_exists( $filepath ) ) {
1200 if ( 'full' !== $size ) {
1201 $data = image_get_intermediate_size( $attachment_id, $size );
1202
1203 if ( $data ) {
1204 $filepath = path_join( dirname( $filepath ), $data['file'] );
1205
1206 /**
1207 * Filters the path to an attachment's file when editing the image.
1208 *
1209 * The filter is evaluated for all image sizes except 'full'.
1210 *
1211 * @since 3.1.0
1212 *
1213 * @param string $path Path to the current image.
1214 * @param int $attachment_id Attachment ID.
1215 * @param string|int[] $size Requested image size. Can be any registered image size name, or
1216 * an array of width and height values in pixels (in that order).
1217 */
1218 $filepath = apply_filters( 'load_image_to_edit_filesystempath', $filepath, $attachment_id, $size );
1219 }
1220 }
1221 } elseif ( function_exists( 'fopen' ) && ini_get( 'allow_url_fopen' ) ) {
1222 /**
1223 * Filters the path to an attachment's URL when editing the image.
1224 *
1225 * The filter is only evaluated if the file isn't stored locally and `allow_url_fopen` is enabled on the server.
1226 *
1227 * @since 3.1.0
1228 *
1229 * @param string|false $image_url Current image URL.
1230 * @param int $attachment_id Attachment ID.
1231 * @param string|int[] $size Requested image size. Can be any registered image size name, or
1232 * an array of width and height values in pixels (in that order).
1233 */
1234 $filepath = apply_filters( 'load_image_to_edit_attachmenturl', wp_get_attachment_url( $attachment_id ), $attachment_id, $size );
1235 }
1236
1237 /**
1238 * Filters the returned path or URL of the current image.
1239 *
1240 * @since 2.9.0
1241 *
1242 * @param string|false $filepath File path or URL to current image, or false.
1243 * @param int $attachment_id Attachment ID.
1244 * @param string|int[] $size Requested image size. Can be any registered image size name, or
1245 * an array of width and height values in pixels (in that order).
1246 */
1247 return apply_filters( 'load_image_to_edit_path', $filepath, $attachment_id, $size );
1248}
1249
1250/**
1251 * Copies an existing image file.
1252 *
1253 * @since 3.4.0
1254 * @access private
1255 *
1256 * @param int $attachment_id Attachment ID.
1257 * @return string|false New file path on success, false on failure.
1258 */
1259function _copy_image_file( $attachment_id ) {
1260 $dst_file = get_attached_file( $attachment_id );
1261 $src_file = $dst_file;
1262
1263 if ( ! file_exists( $src_file ) ) {
1264 $src_file = _load_image_to_edit_path( $attachment_id );
1265 }
1266
1267 if ( $src_file ) {
1268 $dst_file = str_replace( wp_basename( $dst_file ), 'copy-' . wp_basename( $dst_file ), $dst_file );
1269 $dst_file = dirname( $dst_file ) . '/' . wp_unique_filename( dirname( $dst_file ), wp_basename( $dst_file ) );
1270
1271 /*
1272 * The directory containing the original file may no longer
1273 * exist when using a replication plugin.
1274 */
1275 wp_mkdir_p( dirname( $dst_file ) );
1276
1277 if ( ! copy( $src_file, $dst_file ) ) {
1278 $dst_file = false;
1279 }
1280 } else {
1281 $dst_file = false;
1282 }
1283
1284 return $dst_file;
1285}
1286
Ui Ux Design – Teachers Night Out

Get in Touch

© 2024 Teachers Night Out. All Rights Reserved.