PluginProbe
Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF / 2.0
Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF v2.0
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 / classes / Imagifybeat / Actions.php

Actions.php in Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF 2.0, at classes/Imagifybeat/Actions.php

444 lines 13.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Imagify\Imagifybeat;
3
4 use Imagify_Requirements;
5
6 defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
7
8 /**
9 * Imagifybeat actions.
10 *
11 * @since 1.9.3
12 * @author Grégory Viguier
13 */
14 class Actions {
15 use \Imagify\Traits\InstanceGetterTrait;
16
17 /**
18 * The list of action IDs.
19 * Keys are related to method names, values are Imagifybeat IDs.
20 *
21 * @var array
22 * @since 1.9.3
23 * @access private
24 * @author Grégory Viguier
25 */
26 private $imagifybeat_ids = [
27 'requirements' => 'imagify_requirements',
28 'bulk_optimization_stats' => 'imagify_bulk_optimization_stats',
29 'bulk_optimization_status' => 'imagify_bulk_optimization_status',
30 'options_optimization_status' => 'imagify_options_optimization_status',
31 'library_optimization_status' => 'imagify_library_optimization_status',
32 'custom_folders_optimization_status' => 'imagify_custom_folders_optimization_status',
33 ];
34
35 /**
36 * Class init: launch hooks.
37 *
38 * @since 1.9.3
39 * @access public
40 * @author Grégory Viguier
41 */
42 public function init() {
43 foreach ( $this->imagifybeat_ids as $action => $imagifybeat_id ) {
44 add_filter( 'imagifybeat_received', [ $this, 'add_' . $action . '_to_response' ], 10, 2 );
45 }
46 }
47
48
49 /** ----------------------------------------------------------------------------------------- */
50 /** IMAGIFYBEAT CALLBACKS =================================================================== */
51 /** ----------------------------------------------------------------------------------------- */
52
53 /**
54 * Add requirements to Imagifybeat data.
55 *
56 * @since 1.9.3
57 * @access public
58 * @author Grégory Viguier
59 *
60 * @param array $response The Imagifybeat response.
61 * @param array $data The $_POST data sent.
62 * @return array
63 */
64 public function add_requirements_to_response( $response, $data ) {
65 $imagifybeat_id = $this->get_imagifybeat_id_for_callback( __FUNCTION__ );
66
67 if ( ! $imagifybeat_id || empty( $data[ $imagifybeat_id ] ) ) {
68 return $response;
69 }
70
71 $response[ $imagifybeat_id ] = [
72 'curl_missing' => ! Imagify_Requirements::supports_curl(),
73 'editor_missing' => ! Imagify_Requirements::supports_image_editor(),
74 'external_http_blocked' => Imagify_Requirements::is_imagify_blocked(),
75 'api_down' => ! Imagify_Requirements::is_api_up(),
76 'key_is_valid' => Imagify_Requirements::is_api_key_valid(),
77 'is_over_quota' => Imagify_Requirements::is_over_quota(),
78 ];
79
80 return $response;
81 }
82
83 /**
84 * Add bulk stats to Imagifybeat data.
85 *
86 * @since 1.9.3
87 * @access public
88 * @author Grégory Viguier
89 *
90 * @param array $response The Imagifybeat response.
91 * @param array $data The $_POST data sent.
92 * @return array
93 */
94 public function add_bulk_optimization_stats_to_response( $response, $data ) {
95 $imagifybeat_id = $this->get_imagifybeat_id_for_callback( __FUNCTION__ );
96
97 if ( ! $imagifybeat_id || empty( $data[ $imagifybeat_id ] ) ) {
98 return $response;
99 }
100
101 $folder_types = array_flip( array_filter( $data[ $imagifybeat_id ] ) );
102
103 $response[ $imagifybeat_id ] = imagify_get_bulk_stats(
104 $folder_types,
105 [
106 'fullset' => true,
107 ]
108 );
109
110 return $response;
111 }
112
113 /**
114 * Look for media where status has changed, compared to what Imagifybeat sends.
115 * This is used in the bulk optimization page.
116 *
117 * @since 1.9.3
118 * @access public
119 * @author Grégory Viguier
120 *
121 * @param array $response The Imagifybeat response.
122 * @param array $data The $_POST data sent.
123 * @return array
124 */
125 public function add_bulk_optimization_status_to_response( $response, $data ) {
126 $imagifybeat_id = $this->get_imagifybeat_id_for_callback( __FUNCTION__ );
127
128 if ( ! $imagifybeat_id || empty( $data[ $imagifybeat_id ] ) || ! is_array( $data[ $imagifybeat_id ] ) ) {
129 return $response;
130 }
131
132 $statuses = [];
133
134 foreach ( $data[ $imagifybeat_id ] as $item ) {
135 if ( empty( $statuses[ $item['context'] ] ) ) {
136 $statuses[ $item['context'] ] = [];
137 }
138
139 $statuses[ $item['context'] ][ '_' . $item['mediaID'] ] = 1;
140 }
141
142 $results = $this->get_modified_optimization_statuses( $statuses );
143
144 if ( ! $results ) {
145 return $response;
146 }
147
148 $response[ $imagifybeat_id ] = [];
149
150 // Sanitize received data and grab some other info.
151 foreach ( $results as $context_id => $media_atts ) {
152 $process = imagify_get_optimization_process( $media_atts['media_id'], $media_atts['context'] );
153 $optim_data = $process->get_data();
154
155 if ( $optim_data->is_optimized() ) {
156 // Successfully optimized.
157 $full_size_data = $optim_data->get_size_data();
158 $full_size_data = array_merge(
159 [
160 'original_size' => 0,
161 'optimized_size' => 0,
162 'percent' => 0,
163 ],
164 $full_size_data
165 );
166 $response[ $imagifybeat_id ][] = [
167 'mediaID' => $media_atts['media_id'],
168 'context' => $media_atts['context'],
169 'success' => true,
170 'status' => 'optimized',
171 // Raw data.
172 'originalOverallSize' => $full_size_data['original_size'],
173 'newOverallSize' => $full_size_data['optimized_size'],
174 'overallSaving' => $full_size_data['original_size'] - $full_size_data['optimized_size'],
175 'thumbnailsCount' => $optim_data->get_optimized_sizes_count(),
176 // Human readable data.
177 'originalSizeHuman' => imagify_size_format( $full_size_data['original_size'], 2 ),
178 'newSizeHuman' => imagify_size_format( $full_size_data['optimized_size'], 2 ),
179 'overallSavingHuman' => imagify_size_format( $full_size_data['original_size'] - $full_size_data['optimized_size'], 2 ),
180 'originalOverallSizeHuman' => imagify_size_format( $full_size_data['original_size'], 2 ),
181 'percentHuman' => $full_size_data['percent'] . '%',
182 ];
183 } elseif ( $optim_data->is_already_optimized() ) {
184 // Already optimized.
185 $response[ $imagifybeat_id ][] = [
186 'mediaID' => $media_atts['media_id'],
187 'context' => $media_atts['context'],
188 'success' => true,
189 'status' => 'already-optimized',
190 ];
191 } else {
192 // Error.
193 $full_size_data = $optim_data->get_size_data();
194 $message = ! empty( $full_size_data['error'] ) ? $full_size_data['error'] : '';
195 $status = 'error';
196
197 if ( 'You\'ve consumed all your data. You have to upgrade your account to continue' === $message ) {
198 $status = 'over-quota';
199 }
200
201 $response[ $imagifybeat_id ][] = [
202 'mediaID' => $media_atts['media_id'],
203 'context' => $media_atts['context'],
204 'success' => false,
205 'status' => $status,
206 'error' => imagify_translate_api_message( $message ),
207 ];
208 }
209 }
210
211 return $response;
212 }
213
214 /**
215 * Look for media where status has changed, compared to what Imagifybeat sends.
216 * This is used in the settings page.
217 *
218 * @since 1.9
219 * @author Grégory Viguier
220 *
221 * @param array $response The Imagifybeat response.
222 * @param array $data The $_POST data sent.
223 * @return array
224 */
225 public function add_options_optimization_status_to_response( $response, $data ) {
226 $imagifybeat_id = $this->get_imagifybeat_id_for_callback( __FUNCTION__ );
227
228 if ( ! $imagifybeat_id || empty( $data[ $imagifybeat_id ] ) || ! is_array( $data[ $imagifybeat_id ] ) ) {
229 return $response;
230 }
231
232 $statuses = [];
233
234 foreach ( $data[ $imagifybeat_id ] as $item ) {
235 if ( empty( $statuses[ $item['context'] ] ) ) {
236 $statuses[ $item['context'] ] = [];
237 }
238
239 $statuses[ $item['context'] ][ '_' . $item['mediaID'] ] = 1;
240 }
241
242 $results = $this->get_modified_optimization_statuses( $statuses );
243
244 if ( ! $results ) {
245 return $response;
246 }
247
248 $response[ $imagifybeat_id ] = [];
249
250 foreach ( $results as $result ) {
251 $response[ $imagifybeat_id ][] = [
252 'mediaID' => $result['media_id'],
253 'context' => $result['context'],
254 ];
255 }
256
257 return $response;
258 }
259
260 /**
261 * Look for media where status has changed, compared to what Imagifybeat sends.
262 * This is used in the WP Media Library.
263 *
264 * @since 1.9.3
265 * @access public
266 * @author Grégory Viguier
267 *
268 * @param array $response The Imagifybeat response.
269 * @param array $data The $_POST data sent.
270 * @return array
271 */
272 public function add_library_optimization_status_to_response( $response, $data ) {
273 $imagifybeat_id = $this->get_imagifybeat_id_for_callback( __FUNCTION__ );
274
275 if ( ! $imagifybeat_id || empty( $data[ $imagifybeat_id ] ) || ! is_array( $data[ $imagifybeat_id ] ) ) {
276 return $response;
277 }
278
279 $response[ $imagifybeat_id ] = $this->get_modified_optimization_statuses( $data[ $imagifybeat_id ] );
280
281 if ( ! $response[ $imagifybeat_id ] ) {
282 return $response;
283 }
284
285 // Sanitize received data and grab some other info.
286 foreach ( $response[ $imagifybeat_id ] as $context_id => $media_atts ) {
287 $process = imagify_get_optimization_process( $media_atts['media_id'], $media_atts['context'] );
288
289 $response[ $imagifybeat_id ][ $context_id ] = get_imagify_media_column_content( $process, false );
290 }
291
292 return $response;
293 }
294
295 /**
296 * Look for media where status has changed, compared to what Imagifybeat sends.
297 * This is used in the custom folders list (the "Other Media" page).
298 *
299 * @since 1.9.3
300 * @access public
301 * @author Grégory Viguier
302 *
303 * @param array $response The Imagifybeat response.
304 * @param array $data The $_POST data sent.
305 * @return array
306 */
307 public function add_custom_folders_optimization_status_to_response( $response, $data ) {
308 $imagifybeat_id = $this->get_imagifybeat_id_for_callback( __FUNCTION__ );
309
310 if ( ! $imagifybeat_id || empty( $data[ $imagifybeat_id ] ) || ! is_array( $data[ $imagifybeat_id ] ) ) {
311 return $response;
312 }
313
314 $response[ $imagifybeat_id ] = $this->get_modified_optimization_statuses( $data[ $imagifybeat_id ] );
315
316 if ( ! $response[ $imagifybeat_id ] ) {
317 return $response;
318 }
319
320 $admin_ajax_post = \Imagify_Admin_Ajax_Post::get_instance();
321 $list_table = new \Imagify_Files_List_Table( [
322 'screen' => 'imagify-files',
323 ] );
324
325 // Sanitize received data and grab some other info.
326 foreach ( $response[ $imagifybeat_id ] as $context_id => $media_atts ) {
327 $process = imagify_get_optimization_process( $media_atts['media_id'], $media_atts['context'] );
328
329 $response[ $imagifybeat_id ][ $context_id ] = $admin_ajax_post->get_media_columns( $process, $list_table );
330 }
331
332 return $response;
333 }
334
335
336 /** ----------------------------------------------------------------------------------------- */
337 /** TOOLS =================================================================================== */
338 /** ----------------------------------------------------------------------------------------- */
339
340 /**
341 * Look for media where status has changed, compared to what Imagifybeat sends.
342 *
343 * @since 1.9.3
344 * @access public
345 * @author Grégory Viguier
346 *
347 * @param array $data The data received.
348 * @return array
349 */
350 public function get_modified_optimization_statuses( $data ) {
351 if ( ! $data ) {
352 return [];
353 }
354
355 $output = [];
356
357 // Sanitize received data and grab some other info.
358 foreach ( $data as $context => $media_statuses ) {
359 if ( ! $context || ! $media_statuses || ! is_array( $media_statuses ) ) {
360 continue;
361 }
362
363 // Sanitize the IDs: IDs come as strings, prefixed with an undescore character (to prevent JavaScript from screwing everything).
364 $media_ids = array_keys( $media_statuses );
365 $media_ids = array_map( function( $media_id ) {
366 return (int) substr( $media_id, 1 );
367 }, $media_ids );
368 $media_ids = array_filter( $media_ids );
369
370 if ( ! $media_ids ) {
371 continue;
372 }
373
374 // Sanitize the context.
375 $context_instance = imagify_get_context( $context );
376 $context = $context_instance->get_name();
377 $process_class_name = imagify_get_optimization_process_class_name( $context );
378 $transient_name = sprintf( $process_class_name::LOCK_NAME, $context, '%' );
379 $is_network_wide = $context_instance->is_network_wide();
380
381 \Imagify_DB::cache_process_locks( $context, $media_ids );
382
383 // Now that everything is cached for this context, we can get the transients without hitting the DB.
384 foreach ( $media_ids as $id ) {
385 $is_locked = (bool) $media_statuses[ '_' . $id ];
386 $option_name = str_replace( '%', $id, $transient_name );
387
388 if ( $is_network_wide ) {
389 $in_db = (bool) get_site_transient( $option_name );
390 } else {
391 $in_db = (bool) get_transient( $option_name );
392 }
393
394 if ( $is_locked === $in_db ) {
395 continue;
396 }
397
398 $output[ $context . '_' . $id ] = [
399 'media_id' => $id,
400 'context' => $context,
401 ];
402 }
403 }
404
405 return $output;
406 }
407
408 /**
409 * Get an Imagifybeat ID, given an action.
410 *
411 * @since 1.9.3
412 * @access public
413 * @author Grégory Viguier
414 *
415 * @param string $action An action corresponding to the ID we want.
416 * @return string|bool The ID. False on failure.
417 */
418 public function get_imagifybeat_id( $action ) {
419 if ( ! empty( $this->imagifybeat_ids[ $action ] ) ) {
420 return $this->imagifybeat_ids[ $action ];
421 }
422
423 return false;
424 }
425
426 /**
427 * Get an Imagifybeat ID, given a callback name.
428 *
429 * @since 1.9.3
430 * @access private
431 * @author Grégory Viguier
432 *
433 * @param string $callback A method’s name.
434 * @return string|bool The ID. False on failure.
435 */
436 private function get_imagifybeat_id_for_callback( $callback ) {
437 if ( preg_match( '@^add_(?<id>.+)_to_response$@', $callback, $matches ) ) {
438 return $this->get_imagifybeat_id( $matches['id'] );
439 }
440
441 return false;
442 }
443 }
444