PluginProbe
Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF / trunk
Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF vtrunk
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
← All changes | inc/classes/class-imagify-admin-ajax-post.php +268 -550 1.10 → trunk View file →
@@ -1,22 +1,20 @@
1 1 <?php
2 -defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
3 2
3 +use Imagify\Traits\InstanceGetterTrait;
4 +
4 5 /**
5 6 * Class that handles admin ajax/post callbacks.
6 7 *
7 8 * @since 1.6.11
8 - * @author Grégory Viguier
9 9 */
10 10 class Imagify_Admin_Ajax_Post extends Imagify_Admin_Ajax_Post_Deprecated {
11 - use \Imagify\Traits\InstanceGetterTrait;
11 + use InstanceGetterTrait;
12 12
13 13 /**
14 14 * Class version.
15 15 *
16 - * @var string
17 - * @since 1.6.11
18 - * @author Grégory Viguier
16 + * @var string
19 17 */
20 18 const VERSION = '1.1';
21 19
22 20 /**
@@ -21,12 +19,9 @@
21 19
22 20 /**
23 21 * Actions to be triggered on admin ajax and admin post.
24 22 *
25 - * @var array
26 - * @since 1.6.11
27 - * @access protected
28 - * @author Grégory Viguier
23 + * @var array
29 24 */
30 25 protected $ajax_post_actions = [
31 26 // WP optimization.
32 27 'imagify_manual_optimize',
@@ -31,10 +26,10 @@
31 26 // WP optimization.
32 27 'imagify_manual_optimize',
33 28 'imagify_manual_reoptimize',
34 29 'imagify_optimize_missing_sizes',
35 - 'imagify_generate_webp_versions',
36 - 'imagify_delete_webp_versions',
30 + 'imagify_generate_nextgen_versions',
31 + 'imagify_delete_nextgen_versions',
37 32 'imagify_restore',
38 33 // Custom folders optimization.
39 34 'imagify_optimize_file',
40 35 'imagify_reoptimize_file',
@@ -44,20 +39,11 @@
44 39
45 40 /**
46 41 * Actions to be triggered only on admin ajax.
47 42 *
48 - * @var array
49 - * @since 1.6.11
50 - * @access protected
51 - * @author Grégory Viguier
43 + * @var array
52 44 */
53 45 protected $ajax_only_actions = [
54 - // Bulk.
55 - 'imagify_get_media_ids',
56 - 'imagify_bulk_optimize',
57 - 'imagify_get_folder_type_data',
58 - 'imagify_bulk_info_seen',
59 - 'imagify_bulk_get_stats',
60 46 // Settings page.
61 47 'imagify_check_backup_dir_is_writable',
62 48 'imagify_get_files_tree',
63 49 // Account.
@@ -62,9 +48,8 @@
62 48 'imagify_get_files_tree',
63 49 // Account.
64 50 'imagify_signup',
65 51 'imagify_check_api_key_validity',
66 - 'imagify_get_admin_bar_profile',
67 52 'imagify_get_prices',
68 53 'imagify_check_coupon',
69 54 'imagify_get_discount',
70 55 'imagify_get_images_counts',
@@ -77,12 +62,9 @@
77 62
78 63 /**
79 64 * Actions to be triggered only on admin post.
80 65 *
81 - * @var array
82 - * @since 1.6.11
83 - * @access protected
84 - * @author Grégory Viguier
66 + * @var array
85 67 */
86 68 protected $post_only_actions = [
87 69 // Custom folders optimization.
88 70 'imagify_scan_custom_folders',
@@ -92,12 +74,9 @@
92 74
93 75 /**
94 76 * Filesystem object.
95 77 *
96 - * @var object Imagify_Filesystem
97 - * @since 1.7.1
98 - * @access protected
99 - * @author Grégory Viguier
78 + * @var Imagify_Filesystem
100 79 */
101 80 protected $filesystem;
102 81
103 82
@@ -106,13 +85,8 @@
106 85 /** ----------------------------------------------------------------------------------------- */
107 86
108 87 /**
109 88 * The constructor.
110 - *
111 - * @since 1.6.11
112 - * @since 1.9 Visibility set to public.
113 - * @access public
114 - * @author Grégory Viguier
115 89 */
116 90 public function __construct() {
117 91 $this->filesystem = Imagify_Filesystem::get_instance();
118 92 }
@@ -119,27 +93,31 @@
119 93
120 94 /**
121 95 * Launch the hooks.
122 96 *
123 - * @since 1.6.11
124 - * @access public
125 - * @author Grégory Viguier
97 + * @since 1.6.11
126 98 */
127 99 public function init() {
128 - if ( wp_doing_ajax() ) {
129 - // Actions triggered only on admin ajax.
130 - $actions = array_merge( $this->ajax_post_actions, $this->ajax_only_actions );
100 + $doing_ajax = wp_doing_ajax();
131 101
132 - foreach ( $actions as $action ) {
133 - add_action( 'wp_ajax_' . $action, array( $this, $action . '_callback' ) );
102 + foreach ( $this->ajax_post_actions as $action ) {
103 + $action_callback = "{$action}_callback";
104 + if ( $doing_ajax ) {
105 + add_action( 'wp_ajax_' . $action, [ $this, $action_callback ] );
134 106 }
107 + add_action( 'admin_post_' . $action, [ $this, $action_callback ] );
135 108 }
136 109
137 - // Actions triggered on both admin ajax and admin post.
138 - $actions = array_merge( $this->ajax_post_actions, $this->post_only_actions );
110 + // Actions triggered only on admin ajax.
111 + if ( $doing_ajax ) {
112 + foreach ( $this->ajax_only_actions as $action ) {
113 + add_action( 'wp_ajax_' . $action, [ $this, $action . '_callback' ] );
114 + }
115 + }
139 116
140 - foreach ( $actions as $action ) {
141 - add_action( 'admin_post_' . $action, array( $this, $action . '_callback' ) );
117 + // Actions triggered on admin post.
118 + foreach ( $this->post_only_actions as $action ) {
119 + add_action( 'admin_post_' . $action, [ $this, $action . '_callback' ] );
142 120 }
143 121 }
144 122
145 123
@@ -149,11 +127,9 @@
149 127
150 128 /**
151 129 * Optimize one media.
152 130 *
153 - * @since 1.9
154 - * @access protected
155 - * @author Grégory Viguier
131 + * @since 1.9
156 132 *
157 133 * @param int $media_id The media ID.
158 134 * @param string $context The context.
159 135 * @return bool|WP_Error True if successfully launched. A \WP_Error instance on failure.
@@ -158,17 +134,17 @@
158 134 * @param string $context The context.
159 135 * @return bool|WP_Error True if successfully launched. A \WP_Error instance on failure.
160 136 */
161 137 protected function optimize_media( $media_id, $context ) {
162 - return imagify_get_optimization_process( $media_id, $context )->optimize();
138 + // A manual click is an explicit, single-image user action: flag it as priority so it
139 + // jumps ahead of any bulk optimization queue.
140 + return imagify_get_optimization_process( $media_id, $context )->optimize( null, [ 'priority' => true ] );
163 141 }
164 142
165 143 /**
166 144 * Re-optimize a media to a different optimization level.
167 145 *
168 - * @since 1.9
169 - * @access protected
170 - * @author Grégory Viguier
146 + * @since 1.9
171 147 *
172 148 * @param int $media_id The media ID.
173 149 * @param string $context The context.
174 150 * @param int $level The optimization level.
@@ -174,9 +150,11 @@
174 150 * @param int $level The optimization level.
175 151 * @return bool|WP_Error True if successfully launched. A \WP_Error instance on failure.
176 152 */
177 153 protected function reoptimize_media( $media_id, $context, $level ) {
178 - return imagify_get_optimization_process( $media_id, $context )->reoptimize( $level );
154 + // A manual click is an explicit, single-image user action: flag it as priority so it
155 + // jumps ahead of any bulk optimization queue.
156 + return imagify_get_optimization_process( $media_id, $context )->reoptimize( $level, [ 'priority' => true ] );
179 157 }
180 158
181 159 /**
182 160 * Optimize all files from a media, whatever this media’s previous optimization status (will be restored if needed).
@@ -181,11 +159,9 @@
181 159 /**
182 160 * Optimize all files from a media, whatever this media’s previous optimization status (will be restored if needed).
183 161 * This is used by the bulk optimization page.
184 162 *
185 - * @since 1.9
186 - * @access protected
187 - * @author Grégory Viguier
163 + * @since 1.9
188 164 *
189 165 * @param int $media_id The media ID.
190 166 * @param string $context The context.
191 167 * @param int $level The optimization level.
@@ -210,11 +186,9 @@
210 186
211 187 /**
212 188 * Optimize one or some thumbnails that are not optimized yet.
213 189 *
214 - * @since 1.9
215 - * @access protected
216 - * @author Grégory Viguier
190 + * @since 1.9
217 191 *
218 192 * @param int $media_id The media ID.
219 193 * @param string $context The context.
220 194 * @return bool|WP_Error True if successfully launched. A \WP_Error instance on failure.
@@ -223,55 +197,51 @@
223 197 return imagify_get_optimization_process( $media_id, $context )->optimize_missing_thumbnails();
224 198 }
225 199
226 200 /**
227 - * Generate WebP images if they are missing.
201 + * Generate next-gen images if they are missing.
228 202 *
229 - * @since 1.9
230 - * @access protected
231 - * @author Grégory Viguier
203 + * @since 1.9
232 204 *
233 205 * @param int $media_id The media ID.
234 206 * @param string $context The context.
235 207 * @return bool|WP_Error True if successfully launched. A \WP_Error instance on failure.
236 208 */
237 - protected function generate_webp_versions( $media_id, $context ) {
238 - return imagify_get_optimization_process( $media_id, $context )->generate_webp_versions();
209 + protected function generate_nextgen_versions( $media_id, $context ) {
210 + return imagify_get_optimization_process( $media_id, $context )->generate_nextgen_versions();
239 211 }
240 212
241 213 /**
242 - * Delete WebP images for media that are "already_optimize".
214 + * Delete Next gen images for media that are "already_optimize".
243 215 *
244 - * @since 1.9.6
245 - * @access protected
246 - * @author Grégory Viguier
216 + * @since 1.9.6
247 217 *
248 218 * @param int $media_id The media ID.
249 219 * @param string $context The context.
250 220 * @return bool|WP_Error True if successfully launched. A \WP_Error instance on failure.
251 221 */
252 - protected function delete_webp_versions( $media_id, $context ) {
222 + protected function delete_nextgen_versions( $media_id, $context ) {
253 223 $process = imagify_get_optimization_process( $media_id, $context );
254 224
255 225 if ( ! $process->is_valid() ) {
256 - return new \WP_Error( 'invalid_media', __( 'This media is not valid.', 'imagify' ) );
226 + return new WP_Error( 'invalid_media', __( 'This media is not valid.', 'imagify' ) );
257 227 }
258 228
259 229 $data = $process->get_data();
260 230
261 231 if ( ! $data->is_already_optimized() ) {
262 - return new \WP_Error( 'not_already_optimized', __( 'This media does not have the right optimization status.', 'imagify' ) );
232 + return new WP_Error( 'not_already_optimized', __( 'This media does not have the right optimization status.', 'imagify' ) );
263 233 }
264 234
265 - if ( ! $process->has_webp() ) {
235 + if ( ! $process->has_next_gen() ) {
266 236 return true;
267 237 }
268 238
269 239 $data->delete_optimization_data();
270 - $deleted = $process->delete_webp_files();
240 + $deleted = $process->delete_nextgen_files( false, true );
271 241
272 242 if ( is_wp_error( $deleted ) ) {
273 - return new \WP_Error( 'webp_not_deleted', __( 'Previous WebP files could not be deleted.', 'imagify' ) );
243 + return new WP_Error( 'nextgen_not_deleted', __( 'Previous next-gen files could not be deleted.', 'imagify' ) );
274 244 }
275 245
276 246 return true;
277 247 }
@@ -278,11 +248,9 @@
278 248
279 249 /**
280 250 * Restore a media.
281 251 *
282 - * @since 1.9
283 - * @access protected
284 - * @author Grégory Viguier
252 + * @since 1.9
285 253 *
286 254 * @param int $media_id The media ID.
287 255 * @param string $context The context.
288 256 * @return bool|WP_Error True on success. A \WP_Error instance on failure.
@@ -290,190 +258,9 @@
290 258 protected function restore_media( $media_id, $context ) {
291 259 return imagify_get_optimization_process( $media_id, $context )->restore();
292 260 }
293 261
294 -
295 262 /** ----------------------------------------------------------------------------------------- */
296 - /** BULK OPTIMIZATION CALLBACKS ============================================================= */
297 - /** ----------------------------------------------------------------------------------------- */
298 -
299 - /**
300 - * Get media ids for the requested imagify bulk action.
301 - *
302 - * @since 1.9
303 - * @access public
304 - * @author Grégory Viguier
305 - */
306 - public function imagify_get_media_ids_callback() {
307 - imagify_check_nonce( 'imagify-bulk-optimize' );
308 -
309 - $context = $this->get_context();
310 -
311 - if ( ! $context ) {
312 - imagify_die( __( 'Invalid request', 'imagify' ) );
313 - }
314 -
315 - if ( ! imagify_get_context( $context )->current_user_can( 'bulk-optimize' ) ) {
316 - imagify_die();
317 - }
318 -
319 - $bulk = $this->get_bulk_instance( $context );
320 -
321 - switch ( $this->get_imagify_action() ) {
322 - case 'optimize':
323 - $this->check_can_optimize();
324 - $data = $bulk->get_unoptimized_media_ids( $this->get_optimization_level() );
325 - break;
326 -
327 - case 'generate_webp':
328 - $this->check_can_optimize();
329 - $data = $bulk->get_optimized_media_ids_without_webp();
330 -
331 - if ( ! $data['ids'] && $data['errors']['no_backup'] ) {
332 - // No backup, no WebP.
333 - $data = 'no-backup';
334 - } elseif ( ! $data['ids'] && $data['errors']['no_file_path'] ) {
335 - // Error.
336 - $data = __( 'The path to the selected files could not be retrieved.', 'imagify' );
337 - } else {
338 - // OK.
339 - $data = $data['ids'];
340 - }
341 - break;
342 -
343 - default:
344 - $data = [];
345 - }
346 -
347 - if ( ! is_array( $data ) ) {
348 - wp_send_json_error( [ 'message' => $data ] );
349 - }
350 -
351 - wp_send_json_success( $data );
352 - }
353 -
354 - /**
355 - * Process a media with the requested imagify bulk action.
356 - *
357 - * @since 1.6.11
358 - * @access public
359 - * @author Jonathan Buttigieg
360 - */
361 - public function imagify_bulk_optimize_callback() {
362 - imagify_check_nonce( 'imagify-bulk-optimize' );
363 -
364 - $media_id = $this->get_media_id( 'POST', 'media_id' );
365 - $context = $this->get_context( 'POST' );
366 -
367 - if ( ! $media_id || ! $context ) {
368 - imagify_die( __( 'Invalid request', 'imagify' ) );
369 - }
370 -
371 - if ( ! imagify_get_context( $context )->current_user_can( 'bulk-optimize', $media_id ) ) {
372 - imagify_die();
373 - }
374 -
375 - switch ( $this->get_imagify_action() ) {
376 - case 'optimize':
377 - $level = $this->get_optimization_level( 'POST' );
378 - $result = $this->force_optimize( $media_id, $context, $level );
379 - break;
380 -
381 - case 'generate_webp':
382 - $result = $this->generate_webp_versions( $media_id, $context );
383 - break;
384 -
385 - default:
386 - $result = new \WP_Error( 'unknown_action', __( 'Unknown action', 'imagify' ) );
387 - }
388 -
389 - if ( is_wp_error( $result ) ) {
390 - wp_send_json_error( [ 'error' => $result->get_error_message() ] );
391 - }
392 -
393 - wp_send_json_success();
394 - }
395 -
396 - /**
397 - * Get stats data for a specific folder type.
398 - *
399 - * @since 1.7
400 - * @access public
401 - * @author Grégory Viguier
402 - */
403 - public function imagify_get_folder_type_data_callback() {
404 - imagify_check_nonce( 'imagify-bulk-optimize' );
405 -
406 - $context = $this->get_context();
407 -
408 - if ( ! $context ) {
409 - imagify_die( __( 'Invalid request', 'imagify' ) );
410 - }
411 -
412 - if ( ! imagify_get_context( $context )->current_user_can( 'bulk-optimize' ) ) {
413 - imagify_die();
414 - }
415 -
416 - $bulk = $this->get_bulk_instance( $context );
417 -
418 - wp_send_json_success( $bulk->get_context_data() );
419 - }
420 -
421 - /**
422 - * Set the "bulk info" popup state as "seen".
423 - *
424 - * @since 1.7
425 - * @access public
426 - * @author Grégory Viguier
427 - */
428 - public function imagify_bulk_info_seen_callback() {
429 - imagify_check_nonce( 'imagify-bulk-optimize' );
430 -
431 - $context = $this->get_context();
432 -
433 - if ( ! $context ) {
434 - imagify_die( __( 'Invalid request', 'imagify' ) );
435 - }
436 -
437 - if ( ! imagify_get_context( $context )->current_user_can( 'bulk-optimize' ) ) {
438 - imagify_die();
439 - }
440 -
441 - set_transient( 'imagify_bulk_optimization_infos', 1, WEEK_IN_SECONDS );
442 -
443 - wp_send_json_success();
444 - }
445 -
446 - /**
447 - * Get generic stats to display in the bulk page.
448 - *
449 - * @since 1.7.1
450 - * @access public
451 - * @author Grégory Viguier
452 - */
453 - public function imagify_bulk_get_stats_callback() {
454 - imagify_check_nonce( 'imagify-bulk-optimize' );
455 -
456 - $folder_types = filter_input( INPUT_GET, 'types', FILTER_SANITIZE_STRING, FILTER_REQUIRE_ARRAY );
457 - $folder_types = is_array( $folder_types ) ? array_filter( $folder_types, 'is_string' ) : [];
458 -
459 - if ( ! $folder_types ) {
460 - imagify_die( __( 'Invalid request', 'imagify' ) );
461 - }
462 -
463 - foreach ( $folder_types as $folder_type_data ) {
464 - $context = ! empty( $folder_type_data['context'] ) ? $folder_type_data['context'] : 'noop';
465 -
466 - if ( ! imagify_get_context( $context )->current_user_can( 'bulk-optimize' ) ) {
467 - imagify_die();
468 - }
469 - }
470 -
471 - wp_send_json_success( imagify_get_bulk_stats( array_flip( $folder_types ) ) );
472 - }
473 -
474 -
475 - /** ----------------------------------------------------------------------------------------- */
476 263 /** WP OPTIMIZATION CALLBACKS =============================================================== */
477 264 /** ----------------------------------------------------------------------------------------- */
478 265
479 266 /**
@@ -478,11 +265,9 @@
478 265
479 266 /**
480 267 * Optimize all thumbnails of a specific image with the manual method.
481 268 *
482 - * @since 1.6.11
483 - * @access public
484 - * @author Jonathan Buttigieg
269 + * @since 1.6.11
485 270 */
486 271 public function imagify_manual_optimize_callback() {
487 272 $context = $this->get_context();
488 273 $media_id = $this->get_media_id();
@@ -513,11 +298,9 @@
513 298
514 299 /**
515 300 * Optimize all thumbnails of a specific image with a different optimization level.
516 301 *
517 - * @since 1.6.11
518 - * @access public
519 - * @author Jonathan Buttigieg
302 + * @since 1.6.11
520 303 */
521 304 public function imagify_manual_reoptimize_callback() {
522 305 $context = $this->get_context();
523 306 $media_id = $this->get_media_id();
@@ -548,11 +331,9 @@
548 331
549 332 /**
550 333 * Optimize one or some thumbnails that are not optimized yet.
551 334 *
552 - * @since 1.6.11
553 - * @access public
554 - * @author Grégory Viguier
335 + * @since 1.6.11
555 336 */
556 337 public function imagify_optimize_missing_sizes_callback() {
557 338 $context = $this->get_context();
558 339 $media_id = $this->get_media_id();
@@ -581,15 +362,13 @@
581 362 wp_send_json_success();
582 363 }
583 364
584 365 /**
585 - * Generate WebP images if they are missing.
366 + * Generate next-gen images if they are missing.
586 367 *
587 - * @since 1.9
588 - * @access public
589 - * @author Grégory Viguier
368 + * @since 1.9
590 369 */
591 - public function imagify_generate_webp_versions_callback() {
370 + public function imagify_generate_nextgen_versions_callback() {
592 371 $context = $this->get_context();
593 372 $media_id = $this->get_media_id();
594 373
595 374 if ( ! $media_id || ! $context ) {
@@ -595,15 +374,15 @@
595 374 if ( ! $media_id || ! $context ) {
596 375 imagify_die( __( 'Invalid request', 'imagify' ) );
597 376 }
598 377
599 - imagify_check_nonce( 'imagify-generate-webp-versions-' . $media_id . '-' . $context );
378 + imagify_check_nonce( 'imagify-generate-nextgen-versions-' . $media_id . '-' . $context );
600 379
601 380 if ( ! imagify_get_context( $context )->current_user_can( 'manual-optimize', $media_id ) ) {
602 381 imagify_die();
603 382 }
604 383
605 - $result = $this->generate_webp_versions( $media_id, $context );
384 + $result = $this->generate_nextgen_versions( $media_id, $context );
606 385
607 386 imagify_maybe_redirect( is_wp_error( $result ) ? $result : false );
608 387
609 388 if ( is_wp_error( $result ) ) {
@@ -616,15 +395,13 @@
616 395 wp_send_json_success();
617 396 }
618 397
619 398 /**
620 - * Generate WebP images if they are missing.
399 + * Generate next-gen images if they are missing.
621 400 *
622 - * @since 1.9.6
623 - * @access public
624 - * @author Grégory Viguier
401 + * @since 1.9.6
625 402 */
626 - public function imagify_delete_webp_versions_callback() {
403 + public function imagify_delete_nextgen_versions_callback() {
627 404 $context = $this->get_context();
628 405 $media_id = $this->get_media_id();
629 406
630 407 if ( ! $media_id || ! $context ) {
@@ -630,15 +407,15 @@
630 407 if ( ! $media_id || ! $context ) {
631 408 imagify_die( __( 'Invalid request', 'imagify' ) );
632 409 }
633 410
634 - imagify_check_nonce( 'imagify-delete-webp-versions-' . $media_id . '-' . $context );
411 + imagify_check_nonce( 'imagify-delete-nextgen-versions-' . $media_id . '-' . $context );
635 412
636 413 if ( ! imagify_get_context( $context )->current_user_can( 'manual-restore', $media_id ) ) {
637 414 imagify_die();
638 415 }
639 416
640 - $result = $this->delete_webp_versions( $media_id, $context );
417 + $result = $this->delete_nextgen_versions( $media_id, $context );
641 418
642 419 imagify_maybe_redirect( is_wp_error( $result ) ? $result : false );
643 420
644 421 if ( is_wp_error( $result ) ) {
@@ -653,11 +430,9 @@
653 430
654 431 /**
655 432 * Process a restoration to the original attachment.
656 433 *
657 - * @since 1.6.11
658 - * @access public
659 - * @author Jonathan Buttigieg
434 + * @since 1.6.11
660 435 */
661 436 public function imagify_restore_callback() {
662 437 $context = $this->get_context();
663 438 $media_id = $this->get_media_id();
@@ -683,14 +458,20 @@
683 458 wp_send_json_error( [ 'html' => $output ] );
684 459 }
685 460
686 461 // Return the optimization button.
687 - $output = Imagify_Views::get_instance()->get_template( 'button/optimize', [
688 - 'url' => get_imagify_admin_url( 'optimize', array(
689 - 'attachment_id' => $media_id,
690 - 'context' => $context,
691 - ) ),
692 - ] );
462 + $output = Imagify_Views::get_instance()->get_template(
463 + 'button/optimize',
464 + [
465 + 'url' => get_imagify_admin_url(
466 + 'optimize',
467 + [
468 + 'attachment_id' => $media_id,
469 + 'context' => $context,
470 + ]
471 + ),
472 + ]
473 + );
693 474
694 475 wp_send_json_success( [ 'html' => $output ] );
695 476 }
696 477
@@ -701,11 +482,9 @@
701 482
702 483 /**
703 484 * Optimize a file.
704 485 *
705 - * @since 1.7
706 - * @access public
707 - * @author Grégory Viguier
486 + * @since 1.7
708 487 */
709 488 public function imagify_optimize_file_callback() {
710 489 imagify_check_nonce( 'imagify_optimize_file' );
711 490
@@ -733,11 +512,9 @@
733 512
734 513 /**
735 514 * Re-optimize a file.
736 515 *
737 - * @since 1.7
738 - * @access public
739 - * @author Grégory Viguier
516 + * @since 1.7
740 517 */
741 518 public function imagify_reoptimize_file_callback() {
742 519 imagify_check_nonce( 'imagify_reoptimize_file' );
743 520
@@ -767,11 +544,9 @@
767 544
768 545 /**
769 546 * Restore a file.
770 547 *
771 - * @since 1.7
772 - * @access public
773 - * @author Grégory Viguier
548 + * @since 1.7
774 549 */
775 550 public function imagify_restore_file_callback() {
776 551 imagify_check_nonce( 'imagify_restore_file' );
777 552
@@ -800,11 +575,9 @@
800 575
801 576 /**
802 577 * Check if a file has been modified, and update the database accordingly.
803 578 *
804 - * @since 1.7
805 - * @access public
806 - * @author Grégory Viguier
579 + * @since 1.7
807 580 */
808 581 public function imagify_refresh_file_modified_callback() {
809 582 imagify_check_nonce( 'imagify_refresh_file_modified' );
810 583
@@ -817,10 +590,10 @@
817 590 if ( ! imagify_get_context( 'custom-folders' )->current_user_can( 'manual-optimize', $media_id ) ) {
818 591 imagify_die();
819 592 }
820 593
821 - $process = imagify_get_optimization_process( $media_id, 'custom-folders' );
822 - $result = Imagify_Custom_Folders::refresh_file( $process );
594 + $process = imagify_get_optimization_process( $media_id, 'custom-folders' );
595 + $result = Imagify_Custom_Folders::refresh_file( $process );
823 596
824 597 if ( is_wp_error( $result ) ) {
825 598 // The media is not valid or has been removed from the database.
826 599 $message = $result->get_error_message();
@@ -826,11 +599,13 @@
826 599 $message = $result->get_error_message();
827 600
828 601 imagify_maybe_redirect( $message );
829 602
830 - wp_send_json_error( array(
831 - 'row' => $message,
832 - ) );
603 + wp_send_json_error(
604 + [
605 + 'row' => $message,
606 + ]
607 + );
833 608 }
834 609
835 610 imagify_maybe_redirect();
836 611
@@ -840,11 +615,9 @@
840 615
841 616 /**
842 617 * Look for new files in custom folders.
843 618 *
844 - * @since 1.7
845 - * @access public
846 - * @author Grégory Viguier
619 + * @since 1.7
847 620 */
848 621 public function imagify_scan_custom_folders_callback() {
849 622 imagify_check_nonce( 'imagify_scan_custom_folders' );
850 623
@@ -866,23 +639,28 @@
866 639 }
867 640
868 641 $folder['folder_path'] = Imagify_Files_Scan::remove_placeholder( $folder['path'] );
869 642
870 - $folders = array(
643 + $folders = [
871 644 $folder[ $folders_key ] => $folder,
645 + ];
646 +
647 + Imagify_Custom_Folders::get_files_from_folders(
648 + $folders,
649 + [
650 + 'add_inactive_folder_files' => true,
651 + ]
872 652 );
873 653
874 - Imagify_Custom_Folders::get_files_from_folders( $folders, array(
875 - 'add_inactive_folder_files' => true,
876 - ) );
877 -
878 654 imagify_maybe_redirect();
879 655 }
880 656
881 657 // All selected custom folders.
882 - $folders = Imagify_Custom_Folders::get_folders( array(
883 - 'active' => true,
884 - ) );
658 + $folders = Imagify_Custom_Folders::get_folders(
659 + [
660 + 'active' => true,
661 + ]
662 + );
885 663 Imagify_Custom_Folders::get_files_from_folders( $folders );
886 664
887 665 imagify_maybe_redirect();
888 666 }
@@ -895,11 +673,9 @@
895 673 /**
896 674 * Check if the backup directory is writable.
897 675 * This is used to display an error message in the plugin's settings page.
898 676 *
899 - * @since 1.6.11
900 - * @access public
901 - * @author Grégory Viguier
677 + * @since 1.6.11
902 678 */
903 679 public function imagify_check_backup_dir_is_writable_callback() {
904 680 imagify_check_nonce( 'imagify_check_backup_dir_is_writable' );
905 681
@@ -906,19 +682,19 @@
906 682 if ( ! imagify_get_context( 'wp' )->current_user_can( 'manage' ) ) {
907 683 imagify_die();
908 684 }
909 685
910 - wp_send_json_success( array(
911 - 'is_writable' => (int) Imagify_Requirements::attachments_backup_dir_is_writable(),
912 - ) );
686 + wp_send_json_success(
687 + [
688 + 'is_writable' => (int) Imagify_Requirements::attachments_backup_dir_is_writable(),
689 + ]
690 + );
913 691 }
914 692
915 693 /**
916 694 * Get files and folders that are direct children of a given folder.
917 695 *
918 - * @since 1.7
919 - * @access public
920 - * @author Grégory Viguier
696 + * @since 1.7
921 697 */
922 698 public function imagify_get_files_tree_callback() {
923 699 imagify_check_nonce( 'get-files-tree' );
924 700
@@ -929,10 +705,10 @@
929 705 if ( ! isset( $_POST['folder'] ) || '' === $_POST['folder'] ) {
930 706 imagify_die( __( 'Invalid request', 'imagify' ) );
931 707 }
932 708
933 - $folder = wp_unslash( $_POST['folder'] );
934 - $folder = trailingslashit( sanitize_text_field( $folder ) );
709 + $folder = sanitize_text_field( wp_unslash( $_POST['folder'] ) );
710 + $folder = trailingslashit( $folder );
935 711 $folder = realpath( $this->filesystem->get_site_root() . ltrim( $folder, '/' ) );
936 712
937 713 if ( ! $folder ) {
938 714 imagify_die( __( 'This folder doesn\'t exist.', 'imagify' ) );
@@ -948,22 +724,25 @@
948 724 imagify_die( __( 'This folder is not allowed.', 'imagify' ) );
949 725 }
950 726
951 727 // Finally we made all our validations.
952 - $selected = ! empty( $_POST['selected'] ) && is_array( $_POST['selected'] ) ? array_flip( wp_unslash( $_POST['selected'] ) ) : array();
728 + $selected = ! empty( $_POST['selected'] ) && is_array( $_POST['selected'] ) ? array_flip( array_map( 'sanitize_text_field', wp_unslash( $_POST['selected'] ) ) ) : [];
953 729 $views = Imagify_Views::get_instance();
954 730 $output = '';
955 731
956 732 if ( $this->filesystem->is_site_root( $folder ) ) {
957 - $output .= $views->get_template( 'part-settings-files-tree-row', array(
958 - 'relative_path' => '/',
959 - // Value #///# Label.
960 - 'checkbox_value' => '{{ROOT}}/#///#' . esc_attr__( 'Site\'s root', 'imagify' ),
961 - 'checkbox_id' => 'ABSPATH',
962 - 'checkbox_selected' => isset( $selected['{{ROOT}}/'] ),
963 - 'label' => __( 'Site\'s root', 'imagify' ),
964 - 'no_button' => true,
965 - ) );
733 + $output .= $views->get_template(
734 + 'part-settings-files-tree-row',
735 + [
736 + 'relative_path' => '/',
737 + // Value #///# Label.
738 + 'checkbox_value' => '{{ROOT}}/#///#' . esc_attr__( 'Site\'s root', 'imagify' ),
739 + 'checkbox_id' => 'ABSPATH',
740 + 'checkbox_selected' => isset( $selected['{{ROOT}}/'] ),
741 + 'label' => __( 'Site\'s root', 'imagify' ),
742 + 'no_button' => true,
743 + ]
744 + );
966 745 }
967 746
968 747 $dir = new DirectoryIterator( $folder );
969 748 $dir = new Imagify_Files_Iterator( $dir );
@@ -978,16 +757,19 @@
978 757 $folder_path = trailingslashit( $file->getPathname() );
979 758 $relative_path = $this->filesystem->make_path_relative( $folder_path );
980 759 $placeholder = Imagify_Files_Scan::add_placeholder( $folder_path );
981 760
982 - $output .= $views->get_template( 'part-settings-files-tree-row', array(
983 - 'relative_path' => esc_attr( $relative_path ),
984 - // Value #///# Label.
985 - 'checkbox_value' => esc_attr( $placeholder ) . '#///#' . esc_attr( $relative_path ),
986 - 'checkbox_id' => sanitize_html_class( $placeholder ),
987 - 'checkbox_selected' => isset( $selected[ $placeholder ] ),
988 - 'label' => $this->filesystem->file_name( $folder_path ),
989 - ) );
761 + $output .= $views->get_template(
762 + 'part-settings-files-tree-row',
763 + [
764 + 'relative_path' => esc_attr( $relative_path ),
765 + // Value #///# Label.
766 + 'checkbox_value' => esc_attr( $placeholder ) . '#///#' . esc_attr( $relative_path ),
767 + 'checkbox_id' => sanitize_html_class( $placeholder ),
768 + 'checkbox_selected' => isset( $selected[ $placeholder ] ),
769 + 'label' => $this->filesystem->file_name( $folder_path ),
770 + ]
771 + );
990 772 }
991 773
992 774 if ( $images ) {
993 775 /* translators: %s is a formatted number, dont use %d. */
@@ -1008,11 +790,9 @@
1008 790
1009 791 /**
1010 792 * Create a new Imagify account.
1011 793 *
1012 - * @since 1.6.11
1013 - * @access public
1014 - * @author Jonathan Buttigieg
794 + * @since 1.6.11
1015 795 */
1016 796 public function imagify_signup_callback() {
1017 797 imagify_check_nonce( 'imagify-signup', 'imagifysignupnonce' );
1018 798
@@ -1023,19 +803,19 @@
1023 803 if ( empty( $_GET['email'] ) ) {
1024 804 imagify_die( __( 'Empty email address.', 'imagify' ) );
1025 805 }
1026 806
1027 - $email = wp_unslash( $_GET['email'] );
807 + $email = sanitize_email( wp_unslash( $_GET['email'] ) );
1028 808
1029 809 if ( ! is_email( $email ) ) {
1030 810 imagify_die( __( 'Not a valid email address.', 'imagify' ) );
1031 811 }
1032 812
1033 - $data = array(
813 + $data = [
1034 814 'email' => $email,
1035 815 'password' => wp_generate_password( 12, false ),
1036 816 'lang' => imagify_get_locale(),
1037 - );
817 + ];
1038 818
1039 819 $response = add_imagify_user( $data );
1040 820
1041 821 if ( is_wp_error( $response ) ) {
@@ -1047,11 +827,13 @@
1047 827
1048 828 /**
1049 829 * Check the API key validity.
1050 830 *
1051 - * @since 1.6.11
1052 - * @access public
1053 - * @author Jonathan Buttigieg
831 + * @since 1.6.11
832 + * @since 2.3.1 Ignore user abort while saving the key, so the option and its
833 + * related validity cache/notice are never left in a partial state
834 + * when the browser cancels the request (e.g. the user clicks away
835 + * or navigates while the check is still running).
1054 836 */
1055 837 public function imagify_check_api_key_validity_callback() {
1056 838 imagify_check_nonce( 'imagify-check-api-key', 'imagifycheckapikeynonce' );
1057 839
@@ -1062,9 +844,9 @@
1062 844 if ( empty( $_GET['api_key'] ) ) {
1063 845 imagify_die( __( 'Empty API key.', 'imagify' ) );
1064 846 }
1065 847
1066 - $api_key = wp_unslash( $_GET['api_key'] );
848 + $api_key = sanitize_key( wp_unslash( $_GET['api_key'] ) );
1067 849 $response = get_imagify_status( $api_key );
1068 850
1069 851 if ( is_wp_error( $response ) ) {
1070 852 imagify_die( $response );
@@ -1069,98 +851,33 @@
1069 851 if ( is_wp_error( $response ) ) {
1070 852 imagify_die( $response );
1071 853 }
1072 854
855 + /*
856 + * From this point, the key is known to be valid. Saving the option triggers
857 + * `after_save_options()`, which performs its own request to the Imagify API
858 + * to (re)set the "valid key" cache and dismiss/renew the "wrong-api-key" notice.
859 + * If the client disconnects (e.g. the user clicks elsewhere or navigates away
860 + * while the spinner is still showing), PHP would otherwise abort mid-way,
861 + * leaving the key saved but the validity cache/notice stale or missing.
862 + * Ignoring user abort for this short, bounded sequence guarantees the option
863 + * and its validity state are always saved consistently together.
864 + */
865 + $ignore_user_abort = ignore_user_abort( true );
866 +
1073 867 update_imagify_option( 'api_key', $api_key );
1074 868
1075 - wp_send_json_success();
1076 - }
869 + delete_transient( 'imagify_user_cache' );
1077 870
1078 - /**
1079 - * Get admin bar profile output.
1080 - *
1081 - * @since 1.6.11
1082 - * @access public
1083 - * @author Jonathan Buttigieg
1084 - */
1085 - public function imagify_get_admin_bar_profile_callback() {
1086 - imagify_check_nonce( 'imagify-get-admin-bar-profile', 'imagifygetadminbarprofilenonce' );
871 + ignore_user_abort( $ignore_user_abort );
1087 872
1088 - if ( ! imagify_get_context( 'wp' )->current_user_can( 'manage' ) ) {
1089 - imagify_die();
1090 - }
1091 -
1092 - $user = new Imagify_User();
1093 - $views = Imagify_Views::get_instance();
1094 - $unconsumed_quota = $views->get_quota_percent();
1095 - $message = '';
1096 -
1097 - if ( $unconsumed_quota <= 20 ) {
1098 - $message = '<div class="imagify-error">';
1099 - $message .= '<p><i class="dashicons dashicons-warning" aria-hidden="true"></i><strong>' . __( 'Oops, It\'s almost over!', 'imagify' ) . '</strong></p>';
1100 - /* translators: %s is a line break. */
1101 - $message .= '<p>' . sprintf( __( 'You have almost used all your credit.%sDon\'t forget to upgrade your subscription to continue optimizing your images.', 'imagify' ), '<br/><br/>' ) . '</p>';
1102 - $message .= '<p class="center txt-center text-center"><a class="btn imagify-btn-ghost" href="' . esc_url( imagify_get_external_url( 'subscription' ) ) . '" target="_blank">' . __( 'View My Subscription', 'imagify' ) . '</a></p>';
1103 - $message .= '</div>';
1104 - }
1105 -
1106 - if ( 0 === $unconsumed_quota ) {
1107 - $message = '<div class="imagify-error">';
1108 - $message .= '<p><i class="dashicons dashicons-warning" aria-hidden="true"></i><strong>' . __( 'Oops, It\'s Over!', 'imagify' ) . '</strong></p>';
1109 - $message .= '<p>' . sprintf(
1110 - /* translators: 1 is a data quota, 2 is a date. */
1111 - __( 'You have consumed all your credit for this month. You will have <strong>%1$s back on %2$s</strong>.', 'imagify' ),
1112 - imagify_size_format( $user->quota * pow( 1024, 2 ) ),
1113 - date_i18n( get_option( 'date_format' ), strtotime( $user->next_date_update ) )
1114 - ) . '</p>';
1115 - $message .= '<p class="center txt-center text-center"><a class="btn imagify-btn-ghost" href="' . esc_url( imagify_get_external_url( 'subscription' ) ) . '" target="_blank">' . __( 'Upgrade My Subscription', 'imagify' ) . '</a></p>';
1116 - $message .= '</div>';
1117 - }
1118 -
1119 - // Custom HTML.
1120 - $quota_section = '<div class="imagify-admin-bar-quota">';
1121 - $quota_section .= '<div class="imagify-abq-row">';
1122 -
1123 - if ( 1 === $user->plan_id ) {
1124 - $quota_section .= '<div class="imagify-meteo-icon">' . $views->get_quota_icon() . '</div>';
1125 - }
1126 -
1127 - $quota_section .= '<div class="imagify-account">';
1128 - $quota_section .= '<p class="imagify-meteo-title">' . __( 'Account status', 'imagify' ) . '</p>';
1129 - $quota_section .= '<p class="imagify-meteo-subs">' . __( 'Your subscription:', 'imagify' ) . '&nbsp;<strong class="imagify-user-plan">' . $user->plan_label . '</strong></p>';
1130 - $quota_section .= '</div>'; // .imagify-account
1131 - $quota_section .= '</div>'; // .imagify-abq-row
1132 -
1133 - if ( 1 === $user->plan_id ) {
1134 - $quota_section .= '<div class="imagify-abq-row">';
1135 - $quota_section .= '<div class="imagify-space-left">';
1136 - /* translators: %s is a data quota. */
1137 - $quota_section .= '<p>' . sprintf( __( 'You have %s space credit left', 'imagify' ), '<span class="imagify-unconsumed-percent">' . $unconsumed_quota . '%</span>' ) . '</p>';
1138 - $quota_section .= '<div class="' . $views->get_quota_class() . '">';
1139 - $quota_section .= '<div style="width: ' . $unconsumed_quota . '%;" class="imagify-unconsumed-bar imagify-progress"></div>';
1140 - $quota_section .= '</div>'; // .imagify-bar-{negative|neutral|positive}
1141 - $quota_section .= '</div>'; // .imagify-space-left
1142 - $quota_section .= '</div>'; // .imagify-abq-row
1143 - }
1144 -
1145 - $quota_section .= '<p class="imagify-abq-row">';
1146 - $quota_section .= '<a class="imagify-account-link" href="' . esc_url( imagify_get_external_url( 'subscription' ) ) . '" target="_blank">';
1147 - $quota_section .= '<span class="dashicons dashicons-admin-users"></span>';
1148 - $quota_section .= '<span class="button-text">' . __( 'View my subscription', 'imagify' ) . '</span>';
1149 - $quota_section .= '</a>'; // .imagify-account-link
1150 - $quota_section .= '</p>'; // .imagify-abq-row
1151 - $quota_section .= '</div>'; // .imagify-admin-bar-quota
1152 - $quota_section .= $message;
1153 -
1154 - wp_send_json_success( $quota_section );
873 + wp_send_json_success();
1155 874 }
1156 875
1157 876 /**
1158 877 * Get pricings from API for Onetime and Plans at the same time.
1159 878 *
1160 - * @since 1.6.11
1161 - * @access public
1162 - * @author Geoffrey Crofte
879 + * @since 1.6.11
1163 880 */
1164 881 public function imagify_get_prices_callback() {
1165 882 imagify_check_nonce( 'imagify_get_pricing_' . get_current_user_id(), 'imagifynonce' );
1166 883
@@ -1177,20 +894,19 @@
1177 894 if ( ! is_object( $prices_all ) ) {
1178 895 imagify_die( __( 'Wrongly formatted response from our server.', 'imagify' ) );
1179 896 }
1180 897
1181 - wp_send_json_success( array(
1182 - 'onetimes' => $prices_all->Packs,
1183 - 'monthlies' => $prices_all->Plans,
1184 - ) );
898 + wp_send_json_success(
899 + [
900 + 'monthlies' => $prices_all->Plans,
901 + ]
902 + );
1185 903 }
1186 904
1187 905 /**
1188 906 * Check Coupon code on modal popin.
1189 907 *
1190 - * @since 1.6.11
1191 - * @access public
1192 - * @author Geoffrey Crofte
908 + * @since 1.6.11
1193 909 */
1194 910 public function imagify_check_coupon_callback() {
1195 911 imagify_check_nonce( 'imagify_get_pricing_' . get_current_user_id(), 'imagifynonce' );
1196 912
@@ -1198,15 +914,17 @@
1198 914 imagify_die();
1199 915 }
1200 916
1201 917 if ( empty( $_POST['coupon'] ) ) {
1202 - wp_send_json_success( array(
1203 - 'success' => false,
1204 - 'detail' => __( 'Coupon is empty.', 'imagify' ),
1205 - ) );
918 + wp_send_json_success(
919 + [
920 + 'success' => false,
921 + 'detail' => __( 'Coupon is empty.', 'imagify' ),
922 + ]
923 + );
1206 924 }
1207 925
1208 - $coupon = wp_unslash( $_POST['coupon'] );
926 + $coupon = sanitize_text_field( wp_unslash( $_POST['coupon'] ) );
1209 927 $coupon = check_imagify_coupon_code( $coupon );
1210 928
1211 929 if ( is_wp_error( $coupon ) ) {
1212 930 imagify_die( $coupon );
@@ -1217,10 +935,9 @@
1217 935
1218 936 /**
1219 937 * Get current discount promotion to display information on payment modal.
1220 938 *
1221 - * @since 1.6.11
1222 - * @author Geoffrey Crofte
939 + * @since 1.6.11
1223 940 */
1224 941 public function imagify_get_discount_callback() {
1225 942 imagify_check_nonce( 'imagify_get_pricing_' . get_current_user_id(), 'imagifynonce' );
1226 943
@@ -1233,11 +950,9 @@
1233 950
1234 951 /**
1235 952 * Get estimated sizes from the WordPress library.
1236 953 *
1237 - * @since 1.6.11
1238 - * @access public
1239 - * @author Geoffrey Crofte
954 + * @since 1.6.11
1240 955 */
1241 956 public function imagify_get_images_counts_callback() {
1242 957 imagify_check_nonce( 'imagify_get_pricing_' . get_current_user_id(), 'imagifynonce' );
1243 958
@@ -1247,31 +962,33 @@
1247 962
1248 963 $raw_total_size_in_library = imagify_calculate_total_size_images_library() + Imagify_Files_Stats::get_overall_original_size();
1249 964 $raw_average_per_month = imagify_calculate_average_size_images_per_month() + Imagify_Files_Stats::calculate_average_size_per_month();
1250 965
1251 - Imagify_Data::get_instance()->set( array(
1252 - 'total_size_images_library' => $raw_total_size_in_library,
1253 - 'average_size_images_per_month' => $raw_average_per_month,
1254 - ) );
966 + Imagify_Data::get_instance()->set(
967 + [
968 + 'total_size_images_library' => $raw_total_size_in_library,
969 + 'average_size_images_per_month' => $raw_average_per_month,
970 + ]
971 + );
1255 972
1256 - wp_send_json_success( array(
1257 - 'total_library_size' => array(
1258 - 'raw' => $raw_total_size_in_library,
1259 - 'human' => imagify_size_format( $raw_total_size_in_library ),
1260 - ),
1261 - 'average_month_size' => array(
1262 - 'raw' => $raw_average_per_month,
1263 - 'human' => imagify_size_format( $raw_average_per_month ),
1264 - ),
1265 - ) );
973 + wp_send_json_success(
974 + [
975 + 'total_library_size' => [
976 + 'raw' => $raw_total_size_in_library,
977 + 'human' => imagify_size_format( $raw_total_size_in_library ),
978 + ],
979 + 'average_month_size' => [
980 + 'raw' => $raw_average_per_month,
981 + 'human' => imagify_size_format( $raw_average_per_month ),
982 + ],
983 + ]
984 + );
1266 985 }
1267 986
1268 987 /**
1269 988 * Estimate sizes and update the options values for them.
1270 989 *
1271 - * @since 1.6.11
1272 - * @access public
1273 - * @author Remy Perona
990 + * @since 1.6.11
1274 991 */
1275 992 public function imagify_update_estimate_sizes_callback() {
1276 993 imagify_check_nonce( 'update_estimate_sizes' );
1277 994
@@ -1281,12 +998,14 @@
1281 998
1282 999 $raw_total_size_in_library = imagify_calculate_total_size_images_library() + Imagify_Files_Stats::get_overall_original_size();
1283 1000 $raw_average_per_month = imagify_calculate_average_size_images_per_month() + Imagify_Files_Stats::calculate_average_size_per_month();
1284 1001
1285 - Imagify_Data::get_instance()->set( array(
1286 - 'total_size_images_library' => $raw_total_size_in_library,
1287 - 'average_size_images_per_month' => $raw_average_per_month,
1288 - ) );
1002 + Imagify_Data::get_instance()->set(
1003 + [
1004 + 'total_size_images_library' => $raw_total_size_in_library,
1005 + 'average_size_images_per_month' => $raw_average_per_month,
1006 + ]
1007 + );
1289 1008
1290 1009 die( 1 );
1291 1010 }
1292 1011
@@ -1292,11 +1011,9 @@
1292 1011
1293 1012 /**
1294 1013 * Get the Imagify User data.
1295 1014 *
1296 - * @since 1.7
1297 - * @access public
1298 - * @author Grégory Viguier
1015 + * @since 1.7
1299 1016 */
1300 1017 public function imagify_get_user_data_callback() {
1301 1018 imagify_check_nonce( 'imagify_get_user_data' );
1302 1019
@@ -1317,9 +1034,9 @@
1317 1034 $user->best_plan_title = __( 'Oops, It\'s Over!', 'imagify' );
1318 1035 } elseif ( $user->get_percent_unconsumed_quota <= 20 ) {
1319 1036 $user->best_plan_title = __( 'Oops, It\'s almost over!', 'imagify' );
1320 1037 } else {
1321 - $user->best_plan_title = __( 'You\'re new to Imagify?', 'imagify' );
1038 + $user->best_plan_title = __( 'Unlock Imagify\'s full potential', 'imagify' );
1322 1039 }
1323 1040
1324 1041 wp_send_json_success( $user );
1325 1042 }
@@ -1326,11 +1043,9 @@
1326 1043
1327 1044 /**
1328 1045 * Delete the Imagify User data cache.
1329 1046 *
1330 - * @since 1.9.5
1331 - * @access public
1332 - * @author Grégory Viguier
1047 + * @since 1.9.5
1333 1048 */
1334 1049 public function imagify_delete_user_data_cache_callback() {
1335 1050 imagify_check_nonce( 'imagify_delete_user_data_cache' );
1336 1051
@@ -1351,12 +1066,10 @@
1351 1066 /**
1352 1067 * Bridge between XML-RPC and actions triggered by imagify_do_async_job().
1353 1068 * When XML-RPC is used, a current user is set, but no cookies are set, so they cannot be sent with the request. Instead we stored the user ID in a transient.
1354 1069 *
1355 - * @since 1.6.11
1356 - * @access public
1357 - * @author Grégory Viguier
1358 - * @see imagify_do_async_job()
1070 + * @since 1.6.11
1071 + * @see imagify_do_async_job()
1359 1072 */
1360 1073 public function nopriv_imagify_rpc_callback() {
1361 1074 if ( empty( $_POST['imagify_rpc_action'] ) || empty( $_POST['imagify_rpc_id'] ) ) {
1362 1075 imagify_die( __( 'Invalid request', 'imagify' ) );
@@ -1361,9 +1074,9 @@
1361 1074 if ( empty( $_POST['imagify_rpc_action'] ) || empty( $_POST['imagify_rpc_id'] ) ) {
1362 1075 imagify_die( __( 'Invalid request', 'imagify' ) );
1363 1076 }
1364 1077
1365 - $action = wp_unslash( $_POST['imagify_rpc_action'] ); // WPCS: CSRF ok.
1078 + $action = sanitize_text_field( wp_unslash( $_POST['imagify_rpc_action'] ) );
1366 1079
1367 1080 if ( 32 !== strlen( $action ) ) {
1368 1081 imagify_die( __( 'Invalid request', 'imagify' ) );
1369 1082 }
@@ -1402,11 +1115,9 @@
1402 1115
1403 1116 /**
1404 1117 * Store the "closed" status of the ads.
1405 1118 *
1406 - * @since 1.7
1407 - * @access public
1408 - * @author Grégory Viguier
1119 + * @since 1.7
1409 1120 */
1410 1121 public function imagify_dismiss_ad_callback() {
1411 1122 imagify_check_nonce( 'imagify-dismiss-ad' );
1412 1123
@@ -1413,10 +1124,15 @@
1413 1124 if ( ! imagify_get_context( 'wp' )->current_user_can( 'manage' ) ) {
1414 1125 imagify_die();
1415 1126 }
1416 1127
1417 - $notice = filter_input( INPUT_GET, 'ad', FILTER_SANITIZE_STRING );
1128 + if ( empty( $_GET['ad'] ) ) {
1129 + imagify_maybe_redirect();
1130 + wp_send_json_error();
1131 + }
1418 1132
1133 + $notice = sanitize_text_field( wp_unslash( $_GET['ad'] ) );
1134 +
1419 1135 if ( ! $notice ) {
1420 1136 imagify_maybe_redirect();
1421 1137 wp_send_json_error();
1422 1138 }
@@ -1422,9 +1138,9 @@
1422 1138 }
1423 1139
1424 1140 $user_id = get_current_user_id();
1425 1141 $notices = get_user_meta( $user_id, '_imagify_ignore_ads', true );
1426 - $notices = $notices && is_array( $notices ) ? array_flip( $notices ) : array();
1142 + $notices = $notices && is_array( $notices ) ? array_flip( $notices ) : [];
1427 1143
1428 1144 if ( isset( $notices[ $notice ] ) ) {
1429 1145 imagify_maybe_redirect();
1430 1146 wp_send_json_success();
@@ -1448,12 +1164,10 @@
1448 1164
1449 1165 /**
1450 1166 * Get the submitted optimization level.
1451 1167 *
1452 - * @since 1.7
1453 - * @since 1.9 Added $method and $parameter parameters.
1454 - * @access public
1455 - * @author Grégory Viguier
1168 + * @since 1.7
1169 + * @since 1.9 Added $method and $parameter parameters.
1456 1170 *
1457 1171 * @param string $method The method used: 'GET' (default), or 'POST'.
1458 1172 * @param string $parameter The name of the parameter to look for.
1459 1173 * @return int
@@ -1462,8 +1176,12 @@
1462 1176 $method = 'POST' === $method ? INPUT_POST : INPUT_GET;
1463 1177 $level = filter_input( $method, $parameter );
1464 1178
1465 1179 if ( ! is_numeric( $level ) || $level < 0 || $level > 2 ) {
1180 + if ( get_imagify_option( 'lossless' ) ) {
1181 + return 0;
1182 + }
1183 +
1466 1184 return get_imagify_option( 'optimization_level' );
1467 1185 }
1468 1186
1469 1187 return (int) $level;
@@ -1471,11 +1189,9 @@
1471 1189
1472 1190 /**
1473 1191 * Get the submitted context.
1474 1192 *
1475 - * @since 1.9
1476 - * @access public
1477 - * @author Grégory Viguier
1193 + * @since 1.9
1478 1194 *
1479 1195 * @param string $method The method used: 'GET' (default), or 'POST'.
1480 1196 * @param string $parameter The name of the parameter to look for.
1481 1197 * @return string
@@ -1480,11 +1196,15 @@
1480 1196 * @param string $parameter The name of the parameter to look for.
1481 1197 * @return string
1482 1198 */
1483 1199 public function get_context( $method = 'GET', $parameter = 'context' ) {
1484 - $method = 'POST' === $method ? INPUT_POST : INPUT_GET;
1485 - $context = filter_input( $method, $parameter, FILTER_SANITIZE_STRING );
1200 + if ( empty( $_POST[ $parameter ] ) && empty( $_GET[ $parameter ] ) ) {
1201 + // No context.
1202 + return 'noop';
1203 + }
1486 1204
1205 + $context = 'POST' === $method ? sanitize_text_field( wp_unslash( $_POST[ $parameter ] ) ) : sanitize_text_field( wp_unslash( $_GET[ $parameter ] ) ); //phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.NonceVerification.Recommended
1206 +
1487 1207 return imagify_sanitize_context( $context );
1488 1208 }
1489 1209
1490 1210 /**
@@ -1489,11 +1209,9 @@
1489 1209
1490 1210 /**
1491 1211 * Get the submitted media ID.
1492 1212 *
1493 - * @since 1.9
1494 - * @access public
1495 - * @author Grégory Viguier
1213 + * @since 1.9
1496 1214 *
1497 1215 * @param string $method The method used: 'GET' (default), or 'POST'.
1498 1216 * @param string $parameter The name of the parameter to look for.
1499 1217 * @return int
@@ -1511,37 +1229,44 @@
1511 1229
1512 1230 /**
1513 1231 * Get the submitted folder_type.
1514 1232 *
1515 - * @since 1.9
1516 - * @access public
1517 - * @author Grégory Viguier
1233 + * @since 1.9
1518 1234 *
1519 - * @param string $method The method used: 'GET' (default), or 'POST'.
1520 - * @param string $parameter The name of the parameter to look for.
1235 + * @param string $method The method used: 'GET' (default), or 'POST'.
1236 + * @param string $parameter The name of the parameter to look for.
1237 + *
1521 1238 * @return string
1522 1239 */
1523 1240 public function get_folder_type( $method = 'GET', $parameter = 'folder_type' ) {
1524 - $method = 'POST' === $method ? INPUT_POST : INPUT_GET;
1241 + if ( empty( $_POST[ $parameter ] ) && empty( $_GET[ $parameter ] ) ) {
1242 + // No folder type.
1243 + return 'noop';
1244 + }
1525 1245
1526 - return filter_input( $method, $parameter, FILTER_SANITIZE_STRING );
1246 + $folder_type = 'POST' === $method ? sanitize_text_field( wp_unslash( $_POST[ $parameter ] ) ) : sanitize_text_field( wp_unslash( $_GET[ $parameter ] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.NonceVerification.Recommended
1247 +
1248 + return $folder_type;
1527 1249 }
1528 1250
1529 1251 /**
1530 1252 * Get the submitted imagify action.
1531 1253 *
1532 - * @since 1.9
1533 - * @access public
1534 - * @author Grégory Viguier
1254 + * @since 1.9
1535 1255 *
1536 - * @param string $method The method used: 'GET' (default), or 'POST'.
1537 - * @param string $parameter The name of the parameter to look for.
1256 + * @param string $method The method used: 'GET' (default), or 'POST'.
1257 + * @param string $parameter The name of the parameter to look for.
1258 + *
1538 1259 * @return string
1539 1260 */
1540 1261 public function get_imagify_action( $method = 'GET', $parameter = 'imagify_action' ) {
1541 - $method = 'POST' === $method ? INPUT_POST : INPUT_GET;
1542 - $action = filter_input( $method, $parameter, FILTER_SANITIZE_STRING );
1262 + if ( empty( $_POST[ $parameter ] ) && empty( $_GET[ $parameter ] ) ) {
1263 + // No action.
1264 + return 'optimize';
1265 + }
1543 1266
1267 + $action = 'POST' === $method ? sanitize_text_field( wp_unslash( $_POST[ $parameter ] ) ) : sanitize_text_field( wp_unslash( $_GET[ $parameter ] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.NonceVerification.Recommended
1268 +
1544 1269 return $action ? $action : 'optimize';
1545 1270 }
1546 1271
1547 1272 /**
@@ -1546,11 +1271,9 @@
1546 1271
1547 1272 /**
1548 1273 * Get the Bulk class name depending on a context.
1549 1274 *
1550 - * @since 1.9
1551 - * @access public
1552 - * @author Grégory Viguier
1275 + * @since 1.9
1553 1276 *
1554 1277 * @param string $context The context name. Default values are 'wp' and 'custom-folders'.
1555 1278 * @return string The Bulk class name.
1556 1279 */
@@ -1570,10 +1293,9 @@
1570 1293
1571 1294 /**
1572 1295 * Filter the name of the class to use for bulk process.
1573 1296 *
1574 - * @since 1.9
1575 - * @author Grégory Viguier
1297 + * @since 1.9
1576 1298 *
1577 1299 * @param int $class_name The class name.
1578 1300 * @param string $context The context name.
1579 1301 */
@@ -1584,11 +1306,9 @@
1584 1306
1585 1307 /**
1586 1308 * Get the Bulk instance depending on a context.
1587 1309 *
1588 - * @since 1.9
1589 - * @access public
1590 - * @author Grégory Viguier
1310 + * @since 1.9
1591 1311 *
1592 1312 * @param string $context The context name. Default values are 'wp' and 'custom-folders'.
1593 1313 * @return BulkInterface The optimization process instance.
1594 1314 */
@@ -1599,16 +1319,14 @@
1599 1319
1600 1320 /**
1601 1321 * Check if the user has a valid account and has quota. Die on failure.
1602 1322 *
1603 - * @since 1.7
1604 - * @access public
1605 - * @author Grégory Viguier
1323 + * @since 1.7
1606 1324 */
1607 1325 public function check_can_optimize() {
1608 1326 if ( ! Imagify_Requirements::is_api_key_valid() ) {
1609 1327 if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
1610 - wp_send_json_error( array( 'message' => 'invalid-api-key' ) );
1328 + wp_send_json_error( [ 'message' => 'invalid-api-key' ] );
1611 1329 }
1612 1330
1613 1331 imagify_die( __( 'Your API key is not valid!', 'imagify' ) );
1614 1332 }
@@ -1614,9 +1332,9 @@
1614 1332 }
1615 1333
1616 1334 if ( Imagify_Requirements::is_over_quota() ) {
1617 1335 if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
1618 - wp_send_json_error( array( 'message' => 'over-quota' ) );
1336 + wp_send_json_error( [ 'message' => 'over-quota' ] );
1619 1337 }
1620 1338
1621 1339 imagify_die( __( 'You have used all your credits!', 'imagify' ) );
1622 1340 }
@@ -1624,11 +1342,9 @@
1624 1342
1625 1343 /**
1626 1344 * Get a media columns for the "Other Media" page.
1627 1345 *
1628 - * @since 1.9
1629 - * @access public
1630 - * @author Grégory Viguier
1346 + * @since 1.9
1631 1347 *
1632 1348 * @param object $process A \Imagify\Optimization\Process\CustomFolders object.
1633 1349 * @param object $list_table A Imagify_Files_List_Table object.
1634 1350 * @return array An array of HTML, keyed by column name.
@@ -1648,22 +1364,24 @@
1648 1364
1649 1365 /**
1650 1366 * After a file optimization, restore, or whatever, redirect the user or output HTML for ajax.
1651 1367 *
1652 - * @since 1.7
1653 - * @since 1.9 Removed parameter $result.
1654 - * @since 1.9 Added $folder in the returned JSON.
1655 - * @access protected
1656 - * @author Grégory Viguier
1368 + * @since 1.7
1369 + * @since 1.9 Removed parameter $result.
1370 + * @since 1.9 Added $folder in the returned JSON.
1657 1371 *
1658 1372 * @param object $process A \Imagify\Optimization\Process\CustomFolders object.
1659 1373 */
1660 1374 protected function file_optimization_output( $process ) {
1661 - $list_table = new Imagify_Files_List_Table( [
1662 - 'screen' => 'imagify-files',
1663 - ] );
1375 + $list_table = new Imagify_Files_List_Table(
1376 + [
1377 + 'screen' => 'imagify-files',
1378 + ]
1379 + );
1664 1380
1665 - wp_send_json_success( [
1666 - 'columns' => $this->get_media_columns( $process, $list_table ),
1667 - ] );
1381 + wp_send_json_success(
1382 + [
1383 + 'columns' => $this->get_media_columns( $process, $list_table ),
1384 + ]
1385 + );
1668 1386 }
1669 1387 }