PluginProbe
Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF / 1.9.8
Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF v1.9.8
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 1.9.8, at classes/Imagifybeat/Actions.php

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