PluginProbe
Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF / 2.2.9
Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF v2.2.9
2.3.4 2.3.3 2.3.2 2.3.1 2.3.0 2.2.9 2.2.8 trunk 1.10 1.3.3 1.3.4 1.3.5 1.3.5.1 1.3.5.2 1.3.6 1.3.6.1 1.4 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.5 All 103 releases
imagify / inc / deprecated / classes / class-imagify-attachment.php

class-imagify-attachment.php in Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF 2.2.9, at inc/deprecated/classes/class-imagify-attachment.php

851 lines 26.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
3
4 /**
5 * Imagify Attachment class.
6 *
7 * @since 1.0
8 * @since 1.9 Deprecated
9 * @deprecated
10 */
11 class Imagify_Attachment extends Imagify_Abstract_Attachment {
12
13 /**
14 * Class version.
15 *
16 * @var string
17 */
18 const VERSION = '1.2';
19
20 /**
21 * The constructor.
22 *
23 * @since 1.2
24 * @access public
25 * @author Grégory Viguier
26 *
27 * @param int|object $id The attachment ID or the attachment itself.
28 * If an integer, make sure the attachment exists.
29 */
30 public function __construct( $id = 0 ) {
31 imagify_deprecated_class( get_class( $this ), '1.9', '\\Imagify\\Optimization\\Process\\WP( $id )' );
32
33 parent::__construct();
34 }
35
36 /**
37 * Get the attachment backup file path, even if the file doesn't exist.
38 *
39 * @since 1.6.13
40 * @author Grégory Viguier
41 * @access public
42 *
43 * @return string|bool The file path. False on failure.
44 */
45 public function get_raw_backup_path() {
46 return get_imagify_attachment_backup_path( $this->get_original_path() );
47 }
48
49 /**
50 * Get the attachment optimization data.
51 *
52 * @since 1.0
53 * @access public
54 *
55 * @return array
56 */
57 public function get_data() {
58 $data = get_post_meta( $this->id, '_imagify_data', true );
59 return is_array( $data ) ? $data : array();
60 }
61
62 /**
63 * Get the attachment optimization level.
64 *
65 * @since 1.0
66 * @access public
67 *
68 * @return int
69 */
70 public function get_optimization_level() {
71 $level = get_post_meta( $this->id, '_imagify_optimization_level', true );
72 return false !== $level ? (int) $level : false;
73 }
74
75 /**
76 * Get the attachment optimization status (success or error).
77 *
78 * @since 1.0
79 * @access public
80 *
81 * @return string
82 */
83 public function get_status() {
84 $status = get_post_meta( $this->id, '_imagify_status', true );
85 return is_string( $status ) ? $status : '';
86 }
87
88 /**
89 * Get the original attachment path.
90 *
91 * @since 1.0
92 * @access public
93 *
94 * @return string
95 */
96 public function get_original_path() {
97 return get_attached_file( $this->id );
98 }
99
100 /**
101 * Get the original attachment URL.
102 *
103 * @since 1.0
104 * @access public
105 *
106 * @return string
107 */
108 public function get_original_url() {
109 return wp_get_attachment_url( $this->id );
110 }
111
112 /**
113 * Get width and height of the original image.
114 *
115 * @since 1.7
116 * @author Grégory Viguier
117 * @access public
118 *
119 * @return array
120 */
121 public function get_dimensions() {
122 if ( ! $this->is_image() ) {
123 return parent::get_dimensions();
124 }
125
126 $values = wp_get_attachment_image_src( $this->id, 'full' );
127
128 return array(
129 'width' => $values[1],
130 'height' => $values[2],
131 );
132 }
133
134 /**
135 * Update the metadata size of the attachment.
136 *
137 * @since 1.2
138 * @access public
139 *
140 * @return bool
141 */
142 public function update_metadata_size() {
143 // Check if the attachment extension is allowed.
144 if ( ! $this->is_extension_supported() || ! $this->is_image() ) {
145 return false;
146 }
147
148 $size = $this->filesystem->get_image_size( $this->get_original_path() );
149
150 if ( ! $size ) {
151 return false;
152 }
153
154 /**
155 * Triggered before updating an image width and height into its metadata.
156 *
157 * @since 1.8.4
158 * @see Imagify_Filesystem->get_image_size()
159 * @author Grégory Viguier
160 *
161 * @param int $attachment_id The attachment ID.
162 * @param array $size {
163 * An array with, among other data:
164 *
165 * @type int $width The image width.
166 * @type int $height The image height.
167 * }
168 */
169 do_action( 'before_imagify_update_metadata_size', $this->id, $size );
170
171 $metadata = wp_get_attachment_metadata( $this->id );
172 $metadata['width'] = $size['width'];
173 $metadata['height'] = $size['height'];
174
175 wp_update_attachment_metadata( $this->id, $metadata );
176
177 /**
178 * Triggered after updating an image width and height into its metadata.
179 *
180 * @since 1.8.4
181 * @see Imagify_Filesystem->get_image_size()
182 * @author Grégory Viguier
183 *
184 * @param int $attachment_id The attachment ID.
185 * @param array $size {
186 * An array with, among other data:
187 *
188 * @type int $width The image width.
189 * @type int $height The image height.
190 * }
191 */
192 do_action( 'after_imagify_update_metadata_size', $this->id, $size );
193
194 return true;
195 }
196
197 /**
198 * Fills statistics data with values from $data array.
199 *
200 * @since 1.0
201 * @since 1.6.5 Not static anymore.
202 * @since 1.6.6 Removed the attachment ID parameter.
203 * @since 1.7 Removed the image URL parameter.
204 * @access public
205 *
206 * @param array $data The statistics data.
207 * @param object $response The API response.
208 * @param string $size The attachment size key.
209 * @return bool|array False if the original size has an error or an array contains the data for other result.
210 */
211 public function fill_data( $data, $response, $size = 'full' ) {
212 $data = is_array( $data ) ? $data : array();
213 $data['sizes'] = ! empty( $data['sizes'] ) && is_array( $data['sizes'] ) ? $data['sizes'] : array();
214
215 if ( empty( $data['stats'] ) ) {
216 $data['stats'] = array(
217 'original_size' => 0,
218 'optimized_size' => 0,
219 'percent' => 0,
220 );
221 }
222
223 if ( is_wp_error( $response ) ) {
224 $error = $response->get_error_message();
225 $error_status = 'error';
226
227 $data['sizes'][ $size ] = array(
228 'success' => false,
229 'error' => $error,
230 );
231
232 // Update the error status for the original size.
233 if ( 'full' === $size ) {
234 update_post_meta( $this->id, '_imagify_data', $data );
235
236 if ( false !== strpos( $error, 'This image is already compressed' ) ) {
237 $error_status = 'already_optimized';
238 }
239
240 update_post_meta( $this->id, '_imagify_status', $error_status );
241
242 return false;
243 }
244 } else {
245 $response = (object) array_merge( array(
246 'original_size' => 0,
247 'new_size' => 0,
248 'percent' => 0,
249 ), (array) $response );
250
251 $data['sizes'][ $size ] = array(
252 'success' => true,
253 'original_size' => $response->original_size,
254 'optimized_size' => $response->new_size,
255 'percent' => $response->percent,
256 );
257
258 $data['stats']['original_size'] += $response->original_size;
259 $data['stats']['optimized_size'] += $response->new_size;
260 } // End if().
261
262 return $data;
263 }
264
265 /**
266 * Create a thumbnail if it doesn't exist.
267 *
268 * @since 1.6.10
269 * @access protected
270 * @author Grégory Viguier
271 *
272 * @param array $thumbnail_data The thumbnail data (width, height, crop, name, file).
273 * @return bool|array|object True if the file exists. An array of thumbnail data if the file has just been created (width, height, crop, file). A WP_Error object on error.
274 */
275 protected function create_thumbnail( $thumbnail_data ) {
276 $thumbnail_size = $thumbnail_data['name'];
277 $metadata = wp_get_attachment_metadata( $this->id );
278 $metadata_sizes = ! empty( $metadata['sizes'] ) && is_array( $metadata['sizes'] ) ? $metadata['sizes'] : array();
279
280 $original_dirname = $this->filesystem->dir_path( $this->get_original_path() );
281 $thumbnail_path = $original_dirname . $thumbnail_data['file'];
282
283 if ( ! empty( $metadata_sizes[ $thumbnail_size ] ) && $this->filesystem->exists( $thumbnail_path ) ) {
284 $this->filesystem->chmod_file( $thumbnail_path );
285 return true;
286 }
287
288 // Get the editor.
289 $editor = $this->get_editor( $this->get_backup_path() );
290
291 if ( is_wp_error( $editor ) ) {
292 return $editor;
293 }
294
295 // Create the file.
296 $result = $editor->multi_resize( array( $thumbnail_size => $thumbnail_data ) );
297
298 if ( ! $result ) {
299 return new WP_Error( 'image_resize_error' );
300 }
301
302 // The file name can change from what we expected (1px wider, etc).
303 $backup_dirname = $this->filesystem->dir_path( $this->get_backup_path() );
304 $backup_thumb_path = $backup_dirname . $result[ $thumbnail_size ]['file'];
305 $thumbnail_path = $original_dirname . $result[ $thumbnail_size ]['file'];
306
307 // Since we used the backup image as source, the new image is still in the backup folder, we need to move it.
308 $moved = $this->filesystem->move( $backup_thumb_path, $thumbnail_path, true );
309
310 if ( ! $moved ) {
311 return new WP_Error( 'image_resize_error' );
312 }
313
314 return reset( $result );
315 }
316
317 /**
318 * Create all missing thumbnails if they don't exist and update the attachment metadata.
319 *
320 * @since 1.6.10
321 * @access protected
322 * @author Grégory Viguier
323 *
324 * @param array $missing_sizes An array of thumbnail data (width, height, crop, name, file) for each thumbnail size.
325 * @return array An array of thumbnail data (width, height, crop, file).
326 */
327 protected function create_missing_thumbnails( $missing_sizes ) {
328 if ( ! $missing_sizes || ! $this->is_image() ) {
329 return array();
330 }
331
332 $metadata = wp_get_attachment_metadata( $this->id );
333 $metadata['sizes'] = ! empty( $metadata['sizes'] ) && is_array( $metadata['sizes'] ) ? $metadata['sizes'] : array();
334 $thumbnail_new_datas = array();
335 $thumbnail_metadatas = array();
336
337 // Create the missing thumbnails.
338 foreach ( $missing_sizes as $size_name => $thumbnail_data ) {
339 $result = $this->create_thumbnail( $thumbnail_data );
340
341 if ( is_array( $result ) ) {
342 // New file.
343 $thumbnail_new_datas[ $size_name ] = $result;
344 unset( $thumbnail_new_datas[ $size_name ]['name'] );
345 } elseif ( true === $result ) {
346 // The file already exists.
347 $thumbnail_metadatas[ $size_name ] = $metadata['sizes'][ $size_name ];
348 }
349 }
350
351 // Save the new data into the attachment metadata.
352 if ( $thumbnail_new_datas ) {
353 $metadata['sizes'] = array_merge( $metadata['sizes'], $thumbnail_new_datas );
354
355 /**
356 * Here we don't use wp_update_attachment_metadata() to prevent triggering unwanted hooks.
357 */
358 update_post_meta( $this->id, '_wp_attachment_metadata', $metadata );
359 }
360
361 return array_merge( $thumbnail_metadatas, $thumbnail_new_datas );
362 }
363
364 /**
365 * Optimize all sizes with Imagify.
366 *
367 * @since 1.0
368 * @access public
369 *
370 * @param int $optimization_level The optimization level (2=ultra, 1=aggressive, 0=normal).
371 * @param array $metadata The attachment meta data.
372 * @return array $optimized_data The optimization data.
373 */
374 public function optimize( $optimization_level = null, $metadata = array() ) {
375 // Check if the attachment extension is allowed.
376 if ( ! $this->is_extension_supported() ) {
377 return;
378 }
379
380 $optimization_level = isset( $optimization_level ) ? (int) $optimization_level : get_imagify_option( 'optimization_level' );
381 $metadata = $metadata ? $metadata : wp_get_attachment_metadata( $this->id );
382 $sizes = ! empty( $metadata['sizes'] ) && is_array( $metadata['sizes'] ) && $this->is_image() ? $metadata['sizes'] : array();
383
384 // To avoid issue with "original_size" at 0 in "_imagify_data".
385 if ( 0 === (int) $this->get_stats_data( 'original_size' ) ) {
386 $this->delete_imagify_data();
387 }
388
389 // Check if the full size is already optimized.
390 if ( $this->is_optimized() && $this->get_optimization_level() === $optimization_level ) {
391 return;
392 }
393
394 // Get file path & URL for original image.
395 $attachment_path = $this->get_original_path();
396 $attachment_url = $this->get_original_url();
397 $attachment_original_size = $this->get_original_size( false );
398
399 /**
400 * Fires before optimizing an attachment.
401 *
402 * @since 1.0
403 *
404 * @param int $id The attachment ID.
405 */
406 do_action( 'before_imagify_optimize_attachment', $this->id );
407
408 $this->set_running_status();
409
410 // Get the resize values for the original size.
411 $resized = false;
412 $do_resize = $this->is_image() && get_imagify_option( 'resize_larger' );
413
414 if ( $do_resize ) {
415 $resize_width = get_imagify_option( 'resize_larger_w' );
416 $attachment_size = $this->filesystem->get_image_size( $attachment_path );
417
418 if ( $attachment_size && $resize_width < $attachment_size['width'] ) {
419 $resized_attachment_path = $this->resize( $attachment_path, $attachment_size, $resize_width );
420
421 if ( ! is_wp_error( $resized_attachment_path ) ) {
422 // TODO (@Greg): Send an error message if the backup fails.
423 imagify_backup_file( $attachment_path );
424
425 $this->filesystem->move( $resized_attachment_path, $attachment_path, true );
426
427 $resized = true;
428 }
429 }
430 }
431
432 // Optimize the original size.
433 $response = do_imagify( $attachment_path, array(
434 'optimization_level' => $optimization_level,
435 'context' => $this->get_context(),
436 'resized' => $resized,
437 'original_size' => $attachment_original_size,
438 ) );
439
440 $data = $this->fill_data( null, $response );
441
442 /**
443 * Filter the optimization data of the full size.
444 *
445 * @since 1.8
446 * @author Grégory Viguier
447 *
448 * @param array $data The statistics data.
449 * @param object $response The API response.
450 * @param int $id The attachment ID.
451 * @param string $attachment_path The attachment path.
452 * @param string $attachment_url The attachment URL.
453 * @param string $size_key The attachment size key. The value is obviously 'full' but it's kept for concistancy with other filters.
454 * @param int $optimization_level The optimization level.
455 * @param array $metadata WP metadata.
456 */
457 $data = apply_filters( 'imagify_fill_full_size_data', $data, $response, $this->id, $attachment_path, $attachment_url, 'full', $optimization_level, $metadata );
458
459 // Save the optimization level.
460 update_post_meta( $this->id, '_imagify_optimization_level', $optimization_level );
461
462 // If we resized the original with success, we have to update the attachment metadata.
463 // If not, WordPress keeps the old attachment size.
464 if ( $resized ) {
465 $this->update_metadata_size();
466 }
467
468 if ( ! $data ) {
469 $this->delete_running_status();
470 return;
471 }
472
473 // Optimize all thumbnails.
474 if ( $sizes ) {
475 $disallowed_sizes = get_imagify_option( 'disallowed-sizes' );
476 $is_active_for_network = imagify_is_active_for_network();
477 $attachment_path_dirname = $this->filesystem->dir_path( $attachment_path );
478 $attachment_url_dirname = $this->filesystem->dir_path( $attachment_url );
479
480 foreach ( $sizes as $size_key => $size_data ) {
481 $thumbnail_path = $attachment_path_dirname . $size_data['file'];
482 $thumbnail_url = $attachment_url_dirname . $size_data['file'];
483
484 // Check if this size has to be optimized.
485 if ( ! $is_active_for_network && isset( $disallowed_sizes[ $size_key ] ) ) {
486 $data['sizes'][ $size_key ] = array(
487 'success' => false,
488 'error' => __( 'This size is not authorized to be optimized. Update your Imagify settings if you want to optimize it.', 'imagify' ),
489 );
490
491 /**
492 * Filter the optimization data of an unauthorized thumbnail.
493 *
494 * @since 1.8
495 * @author Grégory Viguier
496 *
497 * @param array $data The statistics data.
498 * @param int $id The attachment ID.
499 * @param string $thumbnail_path The thumbnail path.
500 * @param string $thumbnail_url The thumbnail URL.
501 * @param string $size_key The thumbnail size key.
502 * @param int $optimization_level The optimization level.
503 * @param array $metadata WP metadata.
504 */
505 $data = apply_filters( 'imagify_fill_unauthorized_thumbnail_data', $data, $this->id, $thumbnail_path, $thumbnail_url, $size_key, $optimization_level, $metadata );
506 continue;
507 }
508
509 // Optimize the thumbnail size.
510 $response = do_imagify( $thumbnail_path, array(
511 'backup' => false,
512 'optimization_level' => $optimization_level,
513 'context' => $this->get_context(),
514 ) );
515
516 $data = $this->fill_data( $data, $response, $size_key );
517
518 /**
519 * Filter the optimization data of a specific thumbnail.
520 *
521 * @since 1.0
522 * @since 1.8 Added $metadata.
523 *
524 * @param array $data The statistics data.
525 * @param object $response The API response.
526 * @param int $id The attachment ID.
527 * @param string $thumbnail_path The thumbnail path.
528 * @param string $thumbnail_url The thumbnail URL.
529 * @param string $size_key The thumbnail size key.
530 * @param int $optimization_level The optimization level.
531 * @param array $metadata WP metadata.
532 */
533 $data = apply_filters( 'imagify_fill_thumbnail_data', $data, $response, $this->id, $thumbnail_path, $thumbnail_url, $size_key, $optimization_level, $metadata );
534 } // End foreach().
535 } // End if().
536
537 $data['stats']['percent'] = round( ( ( $data['stats']['original_size'] - $data['stats']['optimized_size'] ) / $data['stats']['original_size'] ) * 100, 2 );
538
539 update_post_meta( $this->id, '_imagify_data', $data );
540 update_post_meta( $this->id, '_imagify_status', 'success' );
541
542 $optimized_data = $this->get_data();
543
544 /**
545 * Fires after optimizing an attachment.
546 *
547 * @since 1.0
548 *
549 * @param int $id The attachment ID.
550 * @param array $optimized_data The optimization data.
551 */
552 do_action( 'after_imagify_optimize_attachment', $this->id, $optimized_data );
553
554 $this->delete_running_status();
555
556 return $optimized_data;
557 }
558
559 /**
560 * Optimize missing thumbnail sizes with Imagify.
561 *
562 * @since 1.6.10
563 * @access public
564 * @author Grégory Viguier
565 *
566 * @param int $optimization_level The optimization level (2=ultra, 1=aggressive, 0=normal).
567 * @return array|object An array of thumbnail data, size by size. A WP_Error object on failure.
568 */
569 public function optimize_missing_thumbnails( $optimization_level = null ) {
570 // Check if the attachment extension is allowed.
571 if ( ! $this->is_extension_supported() || ! $this->is_image() ) {
572 return new WP_Error( 'mime_type_not_supported', __( 'This type of file is not supported.', 'imagify' ) );
573 }
574
575 $optimization_level = isset( $optimization_level ) ? (int) $optimization_level : get_imagify_option( 'optimization_level' );
576 $missing_sizes = $this->get_unoptimized_sizes();
577
578 if ( ! $missing_sizes ) {
579 // We have everything we need.
580 return array();
581 }
582
583 // Stop the process if there is no backup file to use.
584 if ( ! $this->has_backup() ) {
585 return new WP_Error( 'no_backup', __( 'This file has no backup file.', 'imagify' ) );
586 }
587
588 /**
589 * Fires before optimizing the missing thumbnails.
590 *
591 * @since 1.6.10
592 * @author Grégory Viguier
593 * @see $this->get_unoptimized_sizes()
594 *
595 * @param int $id The attachment ID.
596 * @param array $missing_sizes An array of the missing sizes.
597 */
598 do_action( 'before_imagify_optimize_missing_thumbnails', $this->id, $missing_sizes );
599
600 $this->set_running_status();
601
602 $errors = new WP_Error();
603
604 // Create the missing thumbnails.
605 $result_sizes = $this->create_missing_thumbnails( $missing_sizes );
606 $failed_sizes = array_diff_key( $missing_sizes, $result_sizes );
607
608 if ( $failed_sizes ) {
609 $failed_count = count( $failed_sizes );
610 /* translators: %d is a number of thumbnails. */
611 $error_message = _n( '%d thumbnail failed to be created', '%d thumbnails failed to be created', $failed_count, 'imagify' );
612 $error_message = sprintf( $error_message, $failed_count );
613
614 $errors->add( 'image_resize_error', $error_message, array(
615 'nbr_failed' => $failed_count,
616 'sizes_failed' => $failed_sizes,
617 'sizes_succeeded' => $result_sizes,
618 ) );
619 }
620
621 if ( ! $result_sizes ) {
622 $this->delete_running_status();
623 return $errors;
624 }
625
626 // Optimize.
627 $imagify_data = $this->get_data();
628 $original_dirname = $this->filesystem->dir_path( $this->get_original_path() );
629 $orig_url_dirname = $this->filesystem->dir_path( $this->get_original_url() );
630
631 foreach ( $result_sizes as $size_name => $thumbnail_data ) {
632 $thumbnail_path = $original_dirname . $thumbnail_data['file'];
633 $thumbnail_url = $orig_url_dirname . $thumbnail_data['file'];
634
635 // Optimize the thumbnail size.
636 $response = do_imagify( $thumbnail_path, array(
637 'backup' => false,
638 'optimization_level' => $optimization_level,
639 'context' => $this->get_context(),
640 ) );
641
642 $imagify_data = $this->fill_data( $imagify_data, $response, $size_name );
643 $metadata = wp_get_attachment_metadata( $this->id );
644
645 /** This filter is documented in inc/classes/class-imagify-attachment.php. */
646 $imagify_data = apply_filters( 'imagify_fill_thumbnail_data', $imagify_data, $response, $this->id, $thumbnail_path, $thumbnail_url, $size_name, $optimization_level, $metadata );
647 }
648
649 // Save Imagify data.
650 $imagify_data['stats']['percent'] = round( ( ( $imagify_data['stats']['original_size'] - $imagify_data['stats']['optimized_size'] ) / $imagify_data['stats']['original_size'] ) * 100, 2 );
651
652 update_post_meta( $this->id, '_imagify_data', $imagify_data );
653
654 /**
655 * Fires after optimizing the missing thumbnails.
656 *
657 * @since 1.6.10
658 * @author Grégory Viguier
659 * @see $this->create_missing_thumbnails()
660 *
661 * @param int $id The attachment ID.
662 * @param array $result_sizes An array of created thumbnails.
663 * @param object $errors A WP_Error object that stores thumbnail creation failures.
664 */
665 do_action( 'after_imagify_optimize_missing_thumbnails', $this->id, $result_sizes, $errors );
666
667 $this->delete_running_status();
668
669 // Return the result.
670 if ( $errors->get_error_codes() ) {
671 return $errors;
672 }
673
674 return $result_sizes;
675 }
676
677 /**
678 * Re-optimize the given thumbnail sizes to the same level.
679 * Before doing this, the given sizes must be restored.
680 *
681 * @since 1.7.1
682 * @access public
683 * @author Grégory Viguier
684 *
685 * @param array $sizes The sizes to optimize.
686 * @return array|void A WP_Error object on failure.
687 */
688 public function reoptimize_thumbnails( $sizes ) {
689 // Check if the attachment extension is allowed.
690 if ( ! $this->is_extension_supported() || ! $this->is_image() ) {
691 return new WP_Error( 'mime_type_not_supported', __( 'This type of file is not supported.', 'imagify' ) );
692 }
693
694 if ( ! $sizes || ! is_array( $sizes ) ) {
695 return;
696 }
697
698 /**
699 * Fires before re-optimizing some thumbnails of an attachment.
700 *
701 * @since 1.7.1
702 * @author Grégory Viguier
703 *
704 * @param int $id The attachment ID.
705 * @param array $sizes The sizes to optimize.
706 */
707 do_action( 'before_imagify_reoptimize_attachment_thumbnails', $this->id, $sizes );
708
709 $this->set_running_status();
710
711 $data = $this->get_data();
712
713 $data['sizes'] = ! empty( $data['sizes'] ) && is_array( $data['sizes'] ) ? $data['sizes'] : array();
714
715 foreach ( $sizes as $size_key => $size_data ) {
716 // In case it's a disallowed size, fill in the new data. If it's not, it will be overwritten by $this->fill_data() later.
717 $data['sizes'][ $size_key ] = array(
718 'success' => false,
719 'error' => __( 'This size is not authorized to be optimized. Update your Imagify settings if you want to optimize it.', 'imagify' ),
720 );
721 }
722
723 // Update global attachment stats.
724 $data['stats'] = array(
725 'original_size' => 0,
726 'optimized_size' => 0,
727 'percent' => 0,
728 );
729
730 foreach ( $data['sizes'] as $size_data ) {
731 if ( ! empty( $size_data['original_size'] ) ) {
732 $data['stats']['original_size'] += $size_data['original_size'];
733 }
734 if ( ! empty( $size_data['optimized_size'] ) ) {
735 $data['stats']['optimized_size'] += $size_data['optimized_size'];
736 }
737 }
738
739 // Remove disallowed sizes.
740 if ( ! imagify_is_active_for_network() ) {
741 $sizes = array_diff_key( $sizes, get_imagify_option( 'disallowed-sizes' ) );
742 }
743
744 if ( ! $sizes ) {
745 $data['stats']['percent'] = $data['stats']['original_size'] ? round( ( ( $data['stats']['original_size'] - $data['stats']['optimized_size'] ) / $data['stats']['original_size'] ) * 100, 2 ) : 0;
746 update_post_meta( $this->id, '_imagify_data', $data );
747 $this->delete_running_status();
748 return;
749 }
750
751 $optimization_level = $this->get_optimization_level();
752 $thumbnail_path = $this->get_original_path();
753 $thumbnail_url = $this->get_original_url();
754 $attachment_path_dirname = $this->filesystem->dir_path( $thumbnail_path );
755 $attachment_url_dirname = $this->filesystem->dir_path( $thumbnail_url );
756
757 foreach ( $sizes as $size_key => $size_data ) {
758 $thumbnail_path = $attachment_path_dirname . $size_data['file'];
759 $thumbnail_url = $attachment_url_dirname . $size_data['file'];
760
761 // Optimize the thumbnail size.
762 $response = do_imagify( $thumbnail_path, array(
763 'backup' => false,
764 'optimization_level' => $optimization_level,
765 'context' => $this->get_context(),
766 ) );
767
768 $data = $this->fill_data( $data, $response, $size_key );
769
770 /** This filter is documented in /inc/classes/class-imagify-attachment.php. */
771 $data = apply_filters( 'imagify_fill_thumbnail_data', $data, $response, $this->id, $thumbnail_path, $thumbnail_url, $size_key, $optimization_level );
772 } // End foreach().
773
774 $data['stats']['percent'] = round( ( ( $data['stats']['original_size'] - $data['stats']['optimized_size'] ) / $data['stats']['original_size'] ) * 100, 2 );
775
776 update_post_meta( $this->id, '_imagify_data', $data );
777
778 /**
779 * Fires after re-optimizing some thumbnails of an attachment.
780 *
781 * @since 1.7.1
782 * @author Grégory Viguier
783 *
784 * @param int $id The attachment ID.
785 * @param array $sizes The sizes to optimize.
786 */
787 do_action( 'after_imagify_reoptimize_attachment_thumbnails', $this->id, $sizes );
788
789 $this->delete_running_status();
790 }
791
792 /**
793 * Process an attachment restoration from the backup file.
794 *
795 * @since 1.0
796 * @access public
797 *
798 * @return void
799 */
800 public function restore() {
801 // Check if the attachment extension is allowed.
802 if ( ! $this->is_extension_supported() ) {
803 return;
804 }
805
806 // Stop the process if there is no backup file to restore.
807 if ( ! $this->has_backup() ) {
808 return;
809 }
810
811 $backup_path = $this->get_backup_path();
812 $attachment_path = $this->get_original_path();
813
814 /**
815 * Fires before restoring an attachment.
816 *
817 * @since 1.0
818 *
819 * @param int $id The attachment ID
820 */
821 do_action( 'before_imagify_restore_attachment', $this->id );
822
823 // Create the original image from the backup.
824 $this->filesystem->copy( $backup_path, $attachment_path, true );
825 $this->filesystem->chmod_file( $attachment_path );
826
827 if ( $this->is_image() ) {
828 if ( ! function_exists( 'wp_generate_attachment_metadata' ) ) {
829 require_once ABSPATH . 'wp-admin/includes/image.php';
830 }
831
832 wp_generate_attachment_metadata( $this->id, $attachment_path );
833
834 // Restore the original size in the metadata.
835 $this->update_metadata_size();
836 }
837
838 // Remove old optimization data.
839 $this->delete_imagify_data();
840
841 /**
842 * Fires after restoring an attachment.
843 *
844 * @since 1.0
845 *
846 * @param int $id The attachment ID
847 */
848 do_action( 'after_imagify_restore_attachment', $this->id );
849 }
850 }
851