PluginProbe
Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF / 1.5
Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF v1.5
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 / classes / class-attachment.php

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

377 lines 10.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 defined( 'ABSPATH' ) or die( 'Cheatin\' uh?' );
3
4 class Imagify_Attachment extends Imagify_Abstract_Attachment {
5 /**
6 * The constructor
7 *
8 * @since 1.0
9 *
10 * @return void
11 **/
12 function __construct( $id = 0 ) {
13 global $post;
14
15 if ( is_object( $post ) && ! $id ) {
16 $this->id = $post->ID;
17 } else {
18 $this->id = (int) $id;
19 }
20 }
21
22 /**
23 * Get the attachment backup filepath.
24 *
25 * @since 1.0
26 *
27 * @access public
28 * @return string|false
29 */
30 public function get_backup_path() {
31 $file_path = $this->get_original_path();
32 $backup_path = get_imagify_attachment_backup_path( $file_path );
33
34 if( file_exists( $backup_path ) ) {
35 return $backup_path;
36 }
37
38 return false;
39 }
40
41 /**
42 * Get the attachment optimization data.
43 *
44 * @since 1.0
45 *
46 * @access public
47 * @return array
48 */
49 public function get_data() {
50 return get_post_meta( $this->id, '_imagify_data', true );
51 }
52
53 /**
54 * Get the attachment optimization level.
55 *
56 * @since 1.0
57 *
58 * @access public
59 * @return int
60 */
61 public function get_optimization_level() {
62 return get_post_meta( $this->id, '_imagify_optimization_level', true );
63 }
64
65 /**
66 * Get the attachment optimization status (success or error).
67 *
68 * @since 1.0
69 *
70 * @access public
71 * @return string
72 */
73 public function get_status() {
74 return get_post_meta( $this->id, '_imagify_status', true );
75 }
76
77 /**
78 * Get the original attachment path.
79 *
80 * @since 1.0
81 *
82 * @access public
83 * @return string
84 */
85 public function get_original_path() {
86 return get_attached_file( $this->id );
87 }
88
89 /**
90 * Get the original attachment URL.
91 *
92 * @since 1.0
93 *
94 * @access public
95 * @return string
96 */
97 public function get_original_url() {
98 return wp_get_attachment_url( $this->id );
99 }
100
101 /**
102 * Update the metadata size of the attachment
103 *
104 * @since 1.2
105 *
106 * @access public
107 * @return void
108 */
109 public function update_metadata_size() {
110 if ( ! wp_attachment_is_image( $this->id ) ) {
111 return false;
112 }
113
114 $size = @getimagesize( $this->get_original_path() );
115
116 if ( isset( $size[0], $size[1] ) ) {
117 $metadata = wp_get_attachment_metadata( $this->id );
118 $metadata['width'] = $size[0];
119 $metadata['height'] = $size[1];
120
121 wp_update_attachment_metadata( $this->id, $metadata );
122 }
123 }
124
125 /**
126 * Fills statistics data with values from $data array
127 *
128 * @since 1.0
129 *
130 * @access public
131 * @static
132 * @param array $data The statistics data
133 * @param object $response The API response
134 * @param int $id The attachment ID
135 * @param int $url The attachment URL
136 * @param string $size The attachment size key
137 * @return bool|array False if the original size has an error or an array contains the data for other result
138 */
139 static public function fill_data( $data, $response, $id, $url, $size = 'full' ) {
140 if ( is_wp_error( $response ) ) {
141 $error = $response->get_error_message();
142 $error_status = 'error';
143
144 $data['sizes'][ $size ] = array(
145 'success' => false,
146 'error' => $error
147 );
148
149 // Update the error status for the original size
150 if ( 'full' === $size ) {
151 update_post_meta( $id, '_imagify_data', $data );
152
153 if ( false !== strpos( $error, 'This image is already compressed' ) ) {
154 $error_status = 'already_optimized';
155 }
156
157 update_post_meta( $id, '_imagify_status', $error_status );
158
159 return false;
160 }
161 } else {
162 $data['sizes'][ $size ] = array(
163 'success' => true,
164 'file_url' => $url,
165 'original_size' => $response->original_size,
166 'optimized_size' => $response->new_size,
167 'percent' => $response->percent
168 );
169
170 $data['stats']['original_size'] += ( isset( $response->original_size ) ) ? $response->original_size : 0;
171 $data['stats']['optimized_size'] += ( isset( $response->new_size ) ) ? $response->new_size : 0;
172 }
173
174 return $data;
175 }
176
177 /**
178 * Optimize all sizes with Imagify.
179 *
180 * @since 1.0
181 *
182 * @access public
183 * @param int $optimization_level The optimization level (2=ultra, 1=aggressive, 0=normal)
184 * @param array $metadata The attachment meta data
185 * @return array $optimized_data The optimization data
186 */
187 public function optimize( $optimization_level = null, $metadata = array() ) {
188 $optimization_level = ( is_null( $optimization_level ) ) ? (int) get_imagify_option( 'optimization_level', 1 ) : (int) $optimization_level;
189
190 $id = $this->id;
191 $metadata = ( (bool) $metadata ) ? $metadata : wp_get_attachment_metadata( $id );
192 $sizes = ( isset( $metadata['sizes'] ) ) ? (array) $metadata['sizes'] : array();
193 $data = array(
194 'stats' => array(
195 'original_size' => 0,
196 'optimized_size' => 0,
197 'percent' => 0,
198 )
199 );
200
201 // Get file path & URL for original image
202 $attachment_path = $this->get_original_path();
203 $attachment_url = $this->get_original_url();
204
205 // Check if the attachment extension is allowed
206 if ( ! $id || ! wp_attachment_is_image( $id ) ) {
207 return;
208 }
209
210 // Check if the full size is already optimized
211 if ( $this->is_optimized() && ( $this->get_optimization_level() == $optimization_level ) ) {
212 return;
213 }
214
215 /**
216 * Fires before optimizing an attachment.
217 *
218 * @since 1.0
219 *
220 * @param int $id The attachment ID
221 */
222 do_action( 'before_imagify_optimize_attachment', $id );
223
224 set_transient( 'imagify-async-in-progress-' . $id, true, 10 * MINUTE_IN_SECONDS );
225
226 // Get the resize values for the original size
227 $resize = array();
228 $do_resize = get_imagify_option( 'resize_larger', false );
229 $resize_width = get_imagify_option( 'resize_larger_w' );
230 $attachment_size = @getimagesize( $attachment_path );
231
232 if ( $do_resize && isset( $attachment_size[0] ) && $resize_width < $attachment_size[0] ) {
233 $resize['width'] = $resize_width;
234 }
235
236 // Optimize the original size
237 $response = do_imagify( $attachment_path, array(
238 'optimization_level' => $optimization_level,
239 'resize' => $resize,
240 'context' => 'wp',
241 'original_size' => $this->get_original_size( false )
242 ) );
243 $data = $this->fill_data( $data, $response, $id, $attachment_url );
244
245 // Save the optimization level
246 update_post_meta( $id, '_imagify_optimization_level', $optimization_level );
247
248 if ( (bool) ! $data ) {
249 delete_transient( 'imagify-async-in-progress-' . $id );
250 return;
251 }
252
253 // If we resized the original with success, we have to update the attachment metadata
254 // If not, WordPress keeps the old attachment size.
255 if ( $do_resize && isset( $resize['width'] ) ) {
256 $this->update_metadata_size();
257 }
258
259 // Optimize all thumbnails
260 if ( (bool) $sizes ) {
261 foreach ( $sizes as $size_key => $size_data ) {
262 // Check if this size has to be optimized
263 if ( array_key_exists( $size_key, get_imagify_option( 'disallowed-sizes', array() ) ) && ! imagify_is_active_for_network() ) {
264 $data['sizes'][ $size_key ] = array(
265 'success' => false,
266 'error' => __( 'This size isn\'t authorized to be optimized. Update your Imagify settings if you want to optimize it.', 'imagify' )
267 );
268 continue;
269 }
270
271 $thumbnail_path = trailingslashit( dirname( $attachment_path ) ) . $size_data['file'];
272 $thumbnail_url = trailingslashit( dirname( $attachment_url ) ) . $size_data['file'];
273
274 // Optimize the thumbnail size
275 $response = do_imagify( $thumbnail_path, array(
276 'backup' => false,
277 'optimization_level' => $optimization_level,
278 'context' => 'wp'
279 ) );
280 $data = $this->fill_data( $data, $response, $id, $thumbnail_url, $size_key );
281
282 /**
283 * Filter the optimization data of a specific thumbnail
284 *
285 * @since 1.0
286 *
287 * @param array $data The statistics data
288 * @param object $response The API response
289 * @param int $id The attachment ID
290 * @param string $thumbnail_path The attachment path
291 * @param string $thumbnail_url The attachment URL
292 * @param string $size_key The attachment size key
293 * @param bool $is_aggressive The optimization level
294 * @return array $data The new optimization data
295 */
296 $data = apply_filters( 'imagify_fill_thumbnail_data', $data, $response, $id, $thumbnail_path, $thumbnail_url, $size_key, $optimization_level );
297 }
298 }
299
300 $data['stats']['percent'] = round( ( ( $data['stats']['original_size'] - $data['stats']['optimized_size'] ) / $data['stats']['original_size'] ) * 100, 2 );
301
302 update_post_meta( $id, '_imagify_data', $data );
303 update_post_meta( $id, '_imagify_status', 'success' );
304
305 $optimized_data = $this->get_data();
306
307 /**
308 * Fires after optimizing an attachment.
309 *
310 * @since 1.0
311 *
312 * @param int $id The attachment ID
313 * @param array $optimized_data The optimization data
314 */
315 do_action( 'after_imagify_optimize_attachment', $id, $optimized_data );
316
317 delete_transient( 'imagify-async-in-progress-' . $id );
318
319 return $optimized_data;
320 }
321
322 /**
323 * Process an attachment restoration from the backup file.
324 *
325 * @since 1.0
326 *
327 * @access public
328 * @return void
329 */
330 public function restore() {
331 // Stop the process if there is no backup file to restore
332 if ( ! $this->has_backup() ) {
333 return;
334 }
335
336 $id = $this->id;
337 $backup_path = $this->get_backup_path();
338 $attachment_path = $this->get_original_path();
339
340 /**
341 * Fires before restoring an attachment.
342 *
343 * @since 1.0
344 *
345 * @param int $id The attachment ID
346 */
347 do_action( 'before_imagify_restore_attachment', $id );
348
349 // Create the original image from the backup
350 @copy( $backup_path, $attachment_path );
351 imagify_chmod_file( $attachment_path );
352
353 if ( ! function_exists( 'wp_generate_attachment_metadata' ) ) {
354 require_once( ABSPATH . 'wp-admin/includes/image.php' );
355 }
356
357 remove_filter( 'wp_generate_attachment_metadata', '_imagify_optimize_attachment', PHP_INT_MAX );
358 wp_generate_attachment_metadata( $id, $attachment_path );
359
360 // Remove old optimization data
361 delete_post_meta( $id, '_imagify_data' );
362 delete_post_meta( $id, '_imagify_status' );
363 delete_post_meta( $id, '_imagify_optimization_level' );
364
365 // Restore the original size in the metadata
366 $this->update_metadata_size();
367
368 /**
369 * Fires after restoring an attachment.
370 *
371 * @since 1.0
372 *
373 * @param int $id The attachment ID
374 */
375 do_action( 'after_imagify_restore_attachment', $id );
376 }
377 }