PluginProbe ʕ •ᴥ•ʔ
Smush – Image Optimization, Compression, Lazy Load, WebP & CDN / 3.12.4
Smush – Image Optimization, Compression, Lazy Load, WebP & CDN v3.12.4
4.1.0 4.0.3 4.0.2 2.8.1 2.9.1 3.0.0 3.0.1 3.0.2 3.1.1 3.10.1 3.10.2 3.10.3 3.11.1 3.12.3 3.12.4 3.12.5 3.12.6 3.13.0 3.13.1 3.13.2 3.14.0 3.14.1 3.14.2 3.15.0 3.15.1 3.15.2 3.15.3 3.15.4 3.15.5 3.16.2 3.16.4 3.16.5 3.16.6 3.17.0 3.17.1 3.18.0 3.18.1 3.2.0.1 3.2.1 3.2.2.1 3.2.4 3.20.0 3.21.1 3.22.1 3.22.3 3.23.0 3.23.1 3.23.2 3.23.3 3.23.4 3.24.0 3.24.0-beta.2 3.3.0 3.3.1 3.3.2 3.4.1 3.4.2 3.6.1 3.6.3 3.7.0 3.7.1 3.7.2 3.7.3 3.8.2 3.8.3 3.8.4 3.8.5 3.8.7 3.8.8 3.9.0 3.9.1 3.9.11 3.9.2 3.9.4 3.9.5 3.9.8 3.9.9 trunk 1.0.0 1.0.1 1.0.2 1.1 1.1.1 1.1.2 1.1.3 1.2 1.2.1 1.2.10 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 1.3.1 1.3.2 1.3.3 1.3.4 1.4.0 1.4.1 1.4.2 1.4.3 1.5.0 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.5.1 1.6.5.2 1.6.5.3 1.6.5.4 1.7 1.7.1 1.7.1.1 2.0 2.0.1 2.0.3 2.0.4 2.0.5 2.0.6 2.0.6.2 2.0.6.3 2.0.6.5 2.0.7 2.0.7.1 2.1 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.2 2.2.1 2.2.2 2.3 2.3.1 2.4 2.4.2 2.4.3 2.4.4 2.4.5 2.5.2 2.5.3 2.6.1 2.6.2 2.6.3 2.7 2.7.1 2.7.4 2.7.4.1 2.7.5 2.7.6 2.7.8 2.7.8.1 2.7.9.1 2.8.0 2.8.0.1
wp-smushit / app / class-ajax.php
wp-smushit / app Last commit date
assets 3 years ago common 3 years ago modals 3 years ago pages 3 years ago views 3 years ago class-abstract-page.php 3 years ago class-abstract-summary-page.php 3 years ago class-admin.php 3 years ago class-ajax.php 3 years ago class-interface-page.php 3 years ago class-media-library.php 3 years ago
class-ajax.php
1431 lines
1 <?php
2 /**
3 * Smush class for storing all Ajax related functionality: Ajax class
4 *
5 * @package Smush\App
6 * @since 2.9.0
7 *
8 * @copyright (c) 2018, Incsub (http://incsub.com)
9 */
10
11 namespace Smush\App;
12
13 use Smush\Core\Core;
14 use Smush\Core\Error_Handler;
15 use Smush\Core\Helper;
16 use Smush\Core\Configs;
17 use Smush\Core\Modules\CDN;
18 use Smush\Core\Modules\Helpers\Parser;
19 use Smush\Core\Modules\Smush;
20 use Smush\Core\Settings;
21 use WP_Smush;
22
23 if ( ! defined( 'WPINC' ) ) {
24 die;
25 }
26
27 /**
28 * Class Ajax for storing all Ajax related functionality.
29 *
30 * @since 2.9.0
31 */
32 class Ajax {
33
34 /**
35 * Settings instance.
36 *
37 * @since 3.3.0
38 * @var Settings
39 */
40 private $settings;
41
42 /**
43 * Ajax constructor.
44 */
45 public function __construct() {
46 $this->settings = Settings::get_instance();
47
48 /**
49 * QUICK SETUP
50 */
51 // Handle skip quick setup action.
52 add_action( 'wp_ajax_skip_smush_setup', array( $this, 'skip_smush_setup' ) );
53 // Ajax request for quick setup.
54 add_action( 'wp_ajax_smush_setup', array( $this, 'smush_setup' ) );
55
56 // Hide tutorials.
57 add_action( 'wp_ajax_smush_hide_tutorials', array( $this, 'hide_tutorials' ) );
58
59 /**
60 * NOTICES
61 */
62 // Handle the smush pro dismiss features notice ajax.
63 add_action( 'wp_ajax_dismiss_upgrade_notice', array( $this, 'dismiss_upgrade_notice' ) );
64 // Handle the smush pro dismiss features notice ajax.
65 add_action( 'wp_ajax_dismiss_update_info', array( $this, 'dismiss_update_info' ) );
66 // Handle ajax request to dismiss the s3 warning.
67 add_action( 'wp_ajax_dismiss_s3support_alert', array( $this, 'dismiss_s3support_alert' ) );
68 // Hide API message.
69 add_action( 'wp_ajax_hide_api_message', array( $this, 'hide_api_message' ) );
70 add_action( 'wp_ajax_smush_show_warning', array( $this, 'show_warning_ajax' ) );
71 // Detect conflicting plugins.
72 add_action( 'wp_ajax_smush_dismiss_notice', array( $this, 'dismiss_notice' ) );
73
74 /**
75 * SMUSH
76 */
77 // Handle Smush Single Ajax.
78 add_action( 'wp_ajax_wp_smushit_manual', array( $this, 'smush_manual' ) );
79 // Handle resmush operation.
80 add_action( 'wp_ajax_smush_resmush_image', array( $this, 'resmush_image' ) );
81 // Scan images as per the latest settings.
82 add_action( 'wp_ajax_scan_for_resmush', array( $this, 'scan_images' ) );
83 // Delete ReSmush list.
84 add_action( 'wp_ajax_delete_resmush_list', array( $this, 'delete_resmush_list' ), '', 2 );
85 // Send smush stats.
86 add_action( 'wp_ajax_get_stats', array( $this, 'get_stats' ) );
87
88 /**
89 * BULK SMUSH
90 */
91 // Ignore image from bulk Smush.
92 add_action( 'wp_ajax_ignore_bulk_image', array( $this, 'ignore_bulk_image' ) );
93 add_action( 'wp_ajax_wp_smush_ignore_all_failed_items', array( $this, 'ajax_ignore_all_failed_items' ) );
94 // Handle Smush Bulk Ajax.
95 add_action( 'wp_ajax_wp_smushit_bulk', array( $this, 'process_smush_request' ) );
96 // Remove from skip list.
97 add_action( 'wp_ajax_remove_from_skip_list', array( $this, 'remove_from_skip_list' ) );
98
99 /**
100 * DIRECTORY SMUSH
101 */
102 // Handle Ajax request for directory smush stats (stats meta box).
103 add_action( 'wp_ajax_get_dir_smush_stats', array( $this, 'get_dir_smush_stats' ) );
104
105 /**
106 * CDN
107 */
108 // Toggle CDN.
109 add_action( 'wp_ajax_smush_toggle_cdn', array( $this, 'toggle_cdn' ) );
110 // Update stats box and CDN status.
111 add_action( 'wp_ajax_get_cdn_stats', array( new CDN( new Parser() ), 'update_stats' ) );
112
113 /**
114 * WebP
115 */
116 // Toggle WebP.
117 add_action( 'wp_ajax_smush_webp_toggle', array( $this, 'webp_toggle' ) );
118 // Check server configuration status for WebP.
119 add_action( 'wp_ajax_smush_webp_get_status', array( $this, 'webp_get_status' ) );
120 // Apply apache rules for WebP support into .htaccess file.
121 add_action( 'wp_ajax_smush_webp_apply_htaccess_rules', array( $this, 'webp_apply_htaccess_rules' ) );
122 // Delete all webp images for all attachments.
123 add_action( 'wp_ajax_smush_webp_delete_all', array( $this, 'webp_delete_all' ) );
124 // Hide the webp wizard.
125 add_action( 'wp_ajax_smush_toggle_webp_wizard', array( $this, 'webp_toggle_wizard' ) );
126
127 /**
128 * LAZY LOADING
129 */
130 add_action( 'wp_ajax_smush_toggle_lazy_load', array( $this, 'smush_toggle_lazy_load' ) );
131 add_action( 'wp_ajax_smush_remove_icon', array( $this, 'remove_icon' ) );
132
133 /**
134 * Configs
135 */
136 add_action( 'wp_ajax_smush_upload_config', array( $this, 'upload_config' ) );
137 add_action( 'wp_ajax_smush_save_config', array( $this, 'save_config' ) );
138 add_action( 'wp_ajax_smush_apply_config', array( $this, 'apply_config' ) );
139
140 /**
141 * SETTINGS
142 */
143 add_action( 'wp_ajax_recheck_api_status', array( $this, 'recheck_api_status' ) );
144
145 /**
146 * MODALS
147 */
148 // Hide the new features modal.
149 add_action( 'wp_ajax_hide_new_features', array( $this, 'hide_new_features_modal' ) );
150 }
151
152 /***************************************
153 *
154 * QUICK SETUP
155 */
156
157 /**
158 * Process ajax action for skipping Smush setup.
159 */
160 public function skip_smush_setup() {
161 check_ajax_referer( 'smush_quick_setup' );
162 // Check capability.
163 if ( ! Helper::is_user_allowed( 'manage_options' ) ) {
164 wp_die( esc_html__( 'Unauthorized', 'wp-smushit' ), 403 );
165 }
166 update_option( 'skip-smush-setup', true );
167 wp_send_json_success();
168 }
169
170 /**
171 * Ajax action to save settings from quick setup.
172 */
173 public function smush_setup() {
174 check_ajax_referer( 'smush_quick_setup', '_wpnonce' );
175
176 // Check capability.
177 if ( ! Helper::is_user_allowed( 'manage_options' ) ) {
178 wp_die( esc_html__( 'Unauthorized', 'wp-smushit' ), 403 );
179 }
180
181 $quick_settings = array();
182 // Get the settings from $_POST.
183 if ( ! empty( $_POST['smush_settings'] ) ) {
184 // Required $quick_settings data is escaped later on in code.
185 $quick_settings = json_decode( wp_unslash( $_POST['smush_settings'] ) ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
186 }
187
188 // Check the last settings stored in db.
189 $settings = $this->settings->get();
190
191 // Available settings for free/pro version.
192 $available = array( 'auto', 'lossy', 'strip_exif', 'original', 'lazy_load', 'usage' );
193
194 foreach ( $settings as $name => $values ) {
195 // Update only specified settings.
196 if ( ! in_array( $name, $available, true ) ) {
197 continue;
198 }
199
200 // Skip premium features if not a member.
201 if ( ! in_array( $name, Settings::$basic_features, true ) && 'usage' !== $name && ! WP_Smush::is_pro() ) {
202 continue;
203 }
204
205 // Update value in settings.
206 $settings[ $name ] = (bool) $quick_settings->{$name};
207
208 // If Smush originals is selected, enable backups.
209 if ( 'original' === $name && $settings[ $name ] && WP_Smush::is_pro() ) {
210 $settings['backup'] = true;
211 }
212
213 // If lazy load enabled - init defaults.
214 if ( 'lazy_load' === $name && $quick_settings->{$name} ) {
215 $this->settings->init_lazy_load_defaults();
216 }
217 }
218
219 // Update the resize sizes.
220 $this->settings->set_setting( 'wp-smush-settings', $settings );
221
222 update_option( 'skip-smush-setup', true );
223
224 wp_send_json_success();
225 }
226
227 /**
228 * Hide tutorials.
229 *
230 * @sinde 3.8.6
231 */
232 public function hide_tutorials() {
233 check_ajax_referer( 'wp-smush-ajax' );
234
235 // Check capability.
236 if ( ! Helper::is_user_allowed( 'manage_options' ) ) {
237 wp_die( esc_html__( 'Unauthorized', 'wp-smushit' ), 403 );
238 }
239
240 update_option( 'wp-smush-hide-tutorials', true, false );
241
242 wp_send_json_success();
243 }
244
245 /***************************************
246 *
247 * NOTICES
248 */
249
250 /**
251 * Store a key/value to hide the smush features on bulk page
252 *
253 * There is no js code related to this action, it seems we are no longer use it, better to clean it?
254 */
255 public function dismiss_upgrade_notice() {
256 check_ajax_referer( 'wp-smush-ajax' );
257
258 // Check capability.
259 if ( ! Helper::is_user_allowed( 'manage_options' ) ) {
260 wp_die( esc_html__( 'Unauthorized', 'wp-smushit' ), 403 );
261 }
262 update_site_option( 'wp-smush-hide_upgrade_notice', true );
263 // No Need to send json response for other requests.
264 wp_send_json_success();
265 }
266
267 /**
268 * Remove the Update info
269 *
270 * @param bool $remove_notice Remove notice.
271 */
272 public function dismiss_update_info( $remove_notice = false ) {
273 check_ajax_referer( 'wp-smush-ajax' );
274
275 // Check capability.
276 if ( ! Helper::is_user_allowed( 'manage_options' ) ) {
277 wp_die( esc_html__( 'Unauthorized', 'wp-smushit' ), 403 );
278 }
279 WP_Smush::get_instance()->core()->mod->smush->dismiss_update_info( $remove_notice );
280 }
281
282 /**
283 * Hide S3 support alert by setting a flag.
284 */
285 public function dismiss_s3support_alert() {
286 check_ajax_referer( 'wp-smush-ajax' );
287 // Check capability.
288 if ( ! Helper::is_user_allowed( 'manage_options' ) ) {
289 wp_die( esc_html__( 'Unauthorized', 'wp-smushit' ), 403 );
290 }
291 // Just set a flag.
292 update_site_option( 'wp-smush-hide_s3support_alert', 1 );
293 wp_send_json_success();
294 }
295
296 /**
297 * Hide API Message
298 */
299 public function hide_api_message() {
300 check_ajax_referer( 'wp-smush-ajax' );
301
302 // Check capability.
303 if ( ! Helper::is_user_allowed( 'manage_options' ) ) {
304 wp_die( esc_html__( 'Unauthorized', 'wp-smushit' ), 403 );
305 }
306
307 $api_message = get_site_option( 'wp-smush-api_message', array() );
308 if ( ! empty( $api_message ) && is_array( $api_message ) ) {
309 $api_message[ key( $api_message ) ]['status'] = 'hide';
310 update_site_option( 'wp-smush-api_message', $api_message );
311 }
312
313 wp_send_json_success();
314 }
315
316 /**
317 * Send JSON response whether to show or not the warning
318 */
319 public function show_warning_ajax() {
320 check_ajax_referer( 'wp-smush-ajax' );
321 // Check capability.
322 if ( ! Helper::is_user_allowed( 'manage_options' ) ) {
323 wp_die( esc_html__( 'Unauthorized', 'wp-smushit' ), 403 );
324 }
325 $show = WP_Smush::get_instance()->core()->mod->smush->show_warning();
326 wp_send_json( (int) $show );
327 }
328
329 /**
330 * Dismiss the plugin conflicts notice.
331 *
332 * @since 3.6.0
333 */
334 public function dismiss_notice() {
335 check_ajax_referer( 'wp-smush-ajax' );
336
337 // Check capability.
338 if ( ! Helper::is_user_allowed( 'manage_options' ) ) {
339 wp_die( esc_html__( 'Unauthorized', 'wp-smushit' ), 403 );
340 }
341
342 if ( empty( $_REQUEST['key'] ) ) {
343 wp_send_json_error();
344 }
345
346 $this->set_notice_dismissed( sanitize_key( $_REQUEST['key'] ) );
347 wp_send_json_success();
348 }
349
350 private function set_notice_dismissed( $notice ) {
351 $option_id = 'wp-smush-dismissed-notices';
352 $dismissed_notices = get_option( $option_id, array() );
353 $dismissed_notices[ $notice ] = true;
354 update_option( $option_id, $dismissed_notices );
355 }
356
357 /***************************************
358 *
359 * SMUSH
360 */
361
362 /**
363 * Handle the Ajax request for smushing single image
364 *
365 * @uses smush_single()
366 */
367 public function smush_manual() {
368 if ( ! check_ajax_referer( 'wp-smush-ajax', '_nonce', false ) ) {
369 wp_send_json_error(
370 array(
371 'error_msg' => esc_html__( 'Nonce verification failed', 'wp-smushit' ),
372 )
373 );
374 }
375
376 if ( ! Helper::is_user_allowed( 'upload_files' ) ) {
377 wp_send_json_error(
378 array(
379 'error_msg' => esc_html__( "You don't have permission to work with uploaded files.", 'wp-smushit' ),
380 )
381 );
382 }
383
384 if ( ! isset( $_GET['attachment_id'] ) ) {
385 wp_send_json_error(
386 array(
387 'error_msg' => esc_html__( 'No attachment ID was provided.', 'wp-smushit' ),
388 )
389 );
390 }
391
392 $attachment_id = (int) $_GET['attachment_id'];
393
394 // Pass on the attachment id to smush single function.
395 WP_Smush::get_instance()->core()->mod->smush->smush_single( $attachment_id );
396 }
397
398 /**
399 * Resmush the image
400 *
401 * @uses smush_single()
402 */
403 public function resmush_image() {
404 // Check empty fields.
405 if ( empty( $_POST['attachment_id'] ) || empty( $_POST['_nonce'] ) ) {
406 wp_send_json_error(
407 array(
408 'error_msg' => esc_html__( 'Image not smushed, fields empty.', 'wp-smushit' ),
409 )
410 );
411 }
412
413 // Check nonce.
414 if ( ! wp_verify_nonce( wp_unslash( $_POST['_nonce'] ), 'wp-smush-resmush-' . (int) $_POST['attachment_id'] ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
415 wp_send_json_error(
416 array(
417 'error_msg' => esc_html__( "Image couldn't be smushed as the nonce verification failed, try reloading the page.", 'wp-smushit' ),
418 )
419 );
420 }
421
422 if ( ! Helper::is_user_allowed( 'upload_files' ) ) {
423 wp_send_json_error(
424 array(
425 'error_msg' => esc_html__( "You don't have permission to work with uploaded files.", 'wp-smushit' ),
426 )
427 );
428 }
429
430 $image_id = (int) $_POST['attachment_id'];
431
432 WP_Smush::get_instance()->core()->mod->smush->smush_single( $image_id );
433 }
434
435 /**
436 * Scans all the smushed attachments to check if they need to be resmushed as per the
437 * current settings, as user might have changed one of the configurations "Lossy", "Keep Original", "Preserve Exif"
438 *
439 * @todo: Needs some refactoring big time
440 */
441 public function scan_images() {
442 check_ajax_referer( 'save_wp_smush_options', 'wp_smush_options_nonce' );
443
444 // Check capability.
445 if ( ! Helper::is_user_allowed( 'manage_options' ) ) {
446 wp_send_json_error(
447 array(
448 'notice' => esc_html__( "You don't have permission to do this.", 'wp-smushit' ),
449 'noticeType' => 'error',
450 )
451 );
452 }
453
454 $resmush_list = array();
455
456 // Scanning for NextGen or Media Library.
457 $type = isset( $_REQUEST['type'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['type'] ) ) : '';
458
459 $core = WP_Smush::get_instance()->core();
460
461 // Save settings only if networkwide settings are disabled.
462 if ( Settings::can_access() && ( ! isset( $_REQUEST['process_settings'] ) || 'false' !== $_REQUEST['process_settings'] ) ) {
463 // Fetch the new settings.
464 $this->settings->init();
465 }
466
467 // If there aren't any images in the library, return the notice.
468 if ( 0 === count( $core->get_media_attachments() ) && 'nextgen' !== $type ) {
469 wp_send_json_success(
470 array(
471 'notice' => esc_html__( 'We haven’t found any images in your media library yet so there’s no smushing to be done! Once you upload images, reload this page and start playing!', 'wp-smushit' ),
472 'super_smush' => $this->settings->get( 'lossy' ),
473 'no_images' => true,
474 )
475 );
476 }
477
478 /**
479 * Logic: If none of the required settings is on, don't need to resmush any of the images
480 * We need at least one of these settings to be on, to check if any of the image needs resmush.
481 */
482
483 // Initialize Media Library Stats.
484 if ( 'nextgen' !== $type && empty( $core->remaining_count ) ) {
485 // Force update to clear caches.
486 $core->setup_global_stats( true );
487 }
488
489 // Initialize NextGen Stats.
490 if ( 'nextgen' === $type && is_object( $core->nextgen->ng_admin ) && empty( $core->nextgen->ng_admin->remaining_count ) ) {
491 $core->nextgen->ng_admin->setup_image_counts();
492 }
493
494 $key = 'nextgen' === $type ? 'wp-smush-nextgen-resmush-list' : 'wp-smush-resmush-list';
495
496 $remaining_count = 'nextgen' === $type ? $core->nextgen->ng_admin->remaining_count : $core->remaining_count;
497
498 if (
499 0 === (int) $remaining_count &&
500 ! $this->settings->get( 'lossy' ) &&
501 ( ! $this->settings->get( 'original' ) || ! WP_Smush::is_pro() ) &&
502 ! $core->mod->webp->is_active() &&
503 ! $this->settings->get( 'strip_exif' )
504 ) {
505 delete_option( $key );
506 // Default Notice, to be displayed at the top of page. Show a message, at the top.
507 wp_send_json_success(
508 array(
509 'notice' => esc_html__( 'Yay! All images are optimized as per your current settings.', 'wp-smushit' ),
510 )
511 );
512 }
513
514 // Set to empty by default.
515 $content = '';
516
517 // Get Smushed Attachments.
518 if ( 'nextgen' !== $type ) {
519 // Get list of Smushed images.
520 $attachments = ! empty( $core->smushed_attachments ) ? $core->smushed_attachments : $core->get_smushed_attachments();
521 } else {
522 // Get smushed attachments list from nextgen class, We get the meta as well.
523 $attachments = $core->nextgen->ng_stats->get_ngg_images();
524 }
525
526 $stats = array(
527 'size_before' => 0,
528 'size_after' => 0,
529 'savings_resize' => 0,
530 'savings_conversion' => 0,
531 );
532
533 $image_count = 0;
534 $super_smushed_count = 0;
535 $smushed_count = 0;
536 $resized_count = 0;
537 // Check if any of the smushed image needs to be resmushed.
538 if ( ! empty( $attachments ) && is_array( $attachments ) ) {
539 if ( 'nextgen' !== $type ) {
540 // Initialize resize class.
541 $core->mod->resize->initialize();
542 // Media lib.
543 $media_lib = WP_Smush::get_instance()->library();
544 }
545
546 foreach ( $attachments as $attachment_k => $attachment ) {
547 /** Check should resmush for nextgen type */
548 if ( 'nextgen' === $type ) {
549 if ( $this->nextgen_should_resmush( $attachment ) ) {
550 $resmush_list[] = $attachment_k;
551 }
552 continue;
553 }
554
555 /** Check should resmush for media type */
556 // Skip if already in ignored list.
557 if ( ! empty( $core->skipped_attachments ) && in_array( $attachment, $core->skipped_attachments ) ) {
558 continue;
559 }
560
561 // Retrieve smush data.
562 $smush_data = get_post_meta( $attachment, Smush::$smushed_meta_key, true );
563 if ( empty( $smush_data['stats'] ) ) {
564 continue;
565 }
566
567 // Check if the attachment need to be smushed.
568 if ( $media_lib->should_resmush( $attachment, $smush_data ) ) {
569 $resmush_list[] = $attachment;
570 }
571
572 /**
573 * Calculate stats during re-check images action.
574 */
575 $resize_savings = get_post_meta( $attachment, 'wp-smush-resize_savings', true );
576 $conversion_savings = Helper::get_pngjpg_savings( $attachment );
577
578 // Increase the smushed count.
579 $smushed_count ++;
580 // Get the resized image count.
581 if ( ! empty( $resize_savings ) ) {
582 $resized_count ++;
583 }
584
585 // Get the image count.
586 $image_count += ( ! empty( $smush_data['sizes'] ) && is_array( $smush_data['sizes'] ) ) ? count( $smush_data['sizes'] ) : 0;
587
588 // If the image is in resmush list, and it was super smushed earlier.
589 $super_smushed_count += $smush_data['stats']['lossy'] ? 1 : 0;
590
591 // Add to the stats.
592 $stats['size_before'] += ! empty( $smush_data['stats'] ) ? $smush_data['stats']['size_before'] : 0;
593 $stats['size_before'] += ! empty( $resize_savings['size_before'] ) ? $resize_savings['size_before'] : 0;
594 $stats['size_before'] += ! empty( $conversion_savings['size_before'] ) ? $conversion_savings['size_before'] : 0;
595
596 $stats['size_after'] += ! empty( $smush_data['stats'] ) ? $smush_data['stats']['size_after'] : 0;
597 $stats['size_after'] += ! empty( $resize_savings['size_after'] ) ? $resize_savings['size_after'] : 0;
598 $stats['size_after'] += ! empty( $conversion_savings['size_after'] ) ? $conversion_savings['size_after'] : 0;
599
600 $stats['savings_resize'] += ! empty( $resize_savings ) && isset( $resize_savings['bytes'] ) ? $resize_savings['bytes'] : 0;
601 $stats['savings_conversion'] += ! empty( $conversion_savings ) && isset( $conversion_savings['bytes'] ) ? $conversion_savings['bytes'] : 0;
602 }// End of Foreach Loop
603
604 // Store the resmush list in Options table.
605 update_option( $key, $resmush_list, false );
606 }
607
608 // Delete resmush list if empty.
609 if ( empty( $resmush_list ) ) {
610 delete_option( $key );
611 }
612
613 $unsmushed_ids = array();
614
615 // Get updated stats for NextGen.
616 if ( 'nextgen' === $type ) {
617 // Reinitialize NextGen stats.
618 $core->nextgen->ng_admin->setup_image_counts();
619 // Image count, Smushed Count, Super-smushed Count, Savings.
620 $stats = $core->nextgen->ng_stats->get_smush_stats();
621 $image_count = $core->nextgen->ng_admin->image_count;
622 $smushed_count = $core->nextgen->ng_admin->smushed_count;
623 $super_smushed_count = $core->nextgen->ng_admin->super_smushed;
624
625 $unsmushed_count = $core->nextgen->ng_admin->remaining_count;
626
627 if ( 0 < $unsmushed_count ) {
628 $raw_unsmushed = $core->nextgen->ng_stats->get_ngg_images( 'unsmushed' );
629 if ( ! empty( $raw_unsmushed ) && is_array( $raw_unsmushed ) ) {
630 $unsmushed_ids = array_keys( $raw_unsmushed );
631 }
632 }
633 } else {
634 $unsmushed_count = $core->remaining_count - count( $core->resmush_ids );
635
636 if ( 0 < $unsmushed_count ) {
637 $unsmushed_ids = array_values( $core->get_unsmushed_attachments() );
638 }
639 }
640
641 $resmush_count = count( $resmush_list );
642 $count = $unsmushed_count + $resmush_count;
643 $remaining_count = $count;
644
645 // If a user manually runs smush check, return the resmush list and UI to be appended to Bulk Smush UI.
646 if ( filter_input( INPUT_GET, 'get_ui', FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE ) ) {
647 if ( 'nextgen' !== $type ) {
648 // Set the variables.
649 $core->resmush_ids = $resmush_list;
650 } else {
651 // To avoid the php warning.
652 $core->nextgen->ng_admin->resmush_ids = $resmush_list;
653 }
654
655 if ( $count ) {
656 ob_start();
657 WP_Smush::get_instance()->admin()->print_pending_bulk_smush_content( $count, $resmush_count, $unsmushed_count );
658 $content = ob_get_clean();
659 }
660 }
661
662 // Directory Smush Stats
663 // Include directory smush stats if not requested for NextGen.
664 if ( 'nextgen' !== $type ) {
665 // Append the directory smush stats.
666 $dir_smush_stats = get_option( 'dir_smush_stats', array() );
667 if ( ! empty( $dir_smush_stats['dir_smush'] ) ) {
668 $dir_smush_stats = $dir_smush_stats['dir_smush'];
669 if ( ! empty( $dir_smush_stats['optimised'] ) ) {
670 $image_count += $dir_smush_stats['optimised'];
671 }
672
673 // Add directory smush stats if not empty.
674 if ( ! empty( $dir_smush_stats['image_size'] ) && ! empty( $dir_smush_stats['orig_size'] ) ) {
675 $stats['size_before'] += $dir_smush_stats['orig_size'];
676 $stats['size_after'] += $dir_smush_stats['image_size'];
677 }
678 }
679 }
680
681 $total_count = 'nextgen' !== $type
682 ? ( $core->total_count - $core->skipped_count )
683 : $core->nextgen->ng_admin->total_count;
684
685 list( $percent_optimized, $percent_metric, $percent_grade ) = $core->get_grade_data(
686 $remaining_count,
687 $core->total_count,
688 $core->skipped_count
689 );
690
691 $return = array(
692 // Leave one line here to easy separate NextGen after merging SMUSH-1124.
693 'count_total' => $total_count,
694 'resmush_ids' => $resmush_list,
695 'unsmushed' => $unsmushed_ids,
696 'count_image' => $image_count,
697 'count_supersmushed' => $super_smushed_count,
698 'count_smushed' => $smushed_count,
699 'count_resize' => $resized_count,
700 'size_before' => ! empty( $stats['size_before'] ) ? $stats['size_before'] : 0,
701 'size_after' => ! empty( $stats['size_after'] ) ? $stats['size_after'] : 0,
702 'savings_resize' => ! empty( $stats['savings_resize'] ) ? $stats['savings_resize'] : 0,
703 'savings_conversion' => ! empty( $stats['savings_conversion'] ) ? $stats['savings_conversion'] : 0,
704 'savings_percent' => ! empty( $stats['percent'] ) && $stats['percent'] > 0 ? number_format_i18n( $stats['percent'], 1 ) : 0,
705 'percent_grade' => $percent_grade,
706 'percent_metric' => $percent_metric,
707 'percent_optimized' => $percent_optimized,
708 'remaining_count' => $remaining_count,
709 );
710
711 if ( ! empty( $content ) ) {
712 $return['content'] = $content;
713 }
714
715 // Include the count.
716 if ( ! empty( $count ) ) {
717 $return['count'] = $count;
718
719 $return['noticeType'] = 'warning';
720 $return['notice'] = sprintf(
721 /* translators: %1$d - number of images, %2$s - opening a tag, %3$s - closing a tag */
722 esc_html__( 'Image check complete, you have %1$d images that need smushing. %2$sBulk smush now!%3$s', 'wp-smushit' ),
723 $count,
724 '<a href="#" class="wp-smush-trigger-bulk" data-type="' . $type . '">',
725 '</a>'
726 );
727 }
728
729 $return['super_smush'] = $this->settings->get( 'lossy' );
730 if ( WP_Smush::is_pro() && $this->settings->get( 'lossy' ) && 'nextgen' === $type ) {
731 $ss_count = $core->nextgen->ng_stats->nextgen_super_smushed_count( $core->nextgen->ng_stats->get_ngg_images( 'smushed' ) );
732 $return['super_smush_stats'] = sprintf( '<strong><span class="smushed-count">%d</span>/%d</strong>', $ss_count, $core->nextgen->ng_admin->total_count );
733 }
734
735 wp_send_json_success( $return );
736 }
737
738 /**
739 * Whether to resmush NextGen thumbnail or not.
740 *
741 * Separated it here for refactor stats.
742 *
743 * @param array $attachment Attachment metadata.
744 * @return bool
745 */
746 private function nextgen_should_resmush( $attachment ) {
747 if ( empty( $attachment['wp_smush'] ) ) {
748 // Do not have this case as we only query smushed item.
749 return false;
750 }
751 $smush_data = $attachment['wp_smush'];
752 if ( empty( $attachment['wp_smush']['stats'] ) ) {
753 // Something wrong, empty stats.
754 return false;
755 }
756
757 return $this->settings->get( 'lossy' ) && empty( $smush_data['stats']['lossy'] )
758 || $this->settings->get( 'strip_exif' ) && ! empty( $smush_data['stats']['keep_exif'] ) && ( 1 === (int) $smush_data['stats']['keep_exif'] )
759 || $this->settings->get( 'original' ) && WP_Smush::is_pro() && empty( $smush_data['sizes']['full'] );
760 }
761
762 /**
763 * Delete the resmush list for Nextgen or the Media Library
764 *
765 * Return Stats in ajax response
766 */
767 public function delete_resmush_list() {
768 $stats = array();
769
770 $key = ! empty( $_POST['type'] ) && 'nextgen' === $_POST['type'] ? 'wp-smush-nextgen-resmush-list' : 'wp-smush-resmush-list';
771
772 // For media Library.
773 if ( 'nextgen' !== $_POST['type'] ) {
774 $resmush_list = get_option( $key );
775 if ( ! empty( $resmush_list ) && is_array( $resmush_list ) ) {
776 $stats = WP_Smush::get_instance()->core()->get_stats_for_attachments( $resmush_list );
777 }
778 } else {
779 // For NextGen. Get the stats (get the re-Smush IDs).
780 $resmush_ids = get_option( 'wp-smush-nextgen-resmush-list', array() );
781
782 $stats = WP_Smush::get_instance()->core()->nextgen->ng_stats->get_stats_for_ids( $resmush_ids );
783
784 $stats['count_images'] = WP_Smush::get_instance()->core()->nextgen->ng_admin->get_image_count( $resmush_ids, false );
785 }
786
787 // Delete the resmush list.
788 delete_option( $key );
789 wp_send_json_success( array( 'stats' => $stats ) );
790 }
791
792 /**
793 * Return Latest stats.
794 */
795 public function get_stats() {
796 check_ajax_referer( 'wp-smush-ajax', '_nonce' );
797
798 // Check capability.
799 if ( ! Helper::is_user_allowed( 'manage_options' ) ) {
800 wp_die( esc_html__( 'Unauthorized', 'wp-smushit' ), 403 );
801 }
802
803 $core = WP_Smush::get_instance()->core();
804
805 if ( empty( $core->stats ) ) {
806 $core->setup_global_stats( true );
807 }
808
809 $stats = $core->get_global_stats();
810
811 wp_send_json_success( $stats );
812 }
813
814 /***************************************
815 *
816 * BULK SMUSH
817 */
818
819 /**
820 * Ignore image from bulk Smush.
821 *
822 * @since 1.9.0
823 */
824 public function ignore_bulk_image() {
825 check_ajax_referer( 'wp-smush-ajax' );
826
827 // Check capability.
828 if ( ! Helper::is_user_allowed( 'upload_files' ) ) {
829 wp_send_json_error(
830 array(
831 'error_msg' => esc_html__( "You don't have permission to work with uploaded files.", 'wp-smushit' ),
832 ),
833 403
834 );
835 }
836
837 if ( ! isset( $_POST['id'] ) ) {
838 wp_send_json_error();
839 }
840
841 $attachment_id = absint( $_POST['id'] );
842
843 // Ignore image.
844 update_post_meta( $attachment_id, 'wp-smush-ignore-bulk', true );
845
846 wp_send_json_success(
847 array(
848 'links' => WP_Smush::get_instance()->library()->get_optimization_links( $attachment_id ),
849 )
850 );
851 }
852
853 /**
854 * Bulk Smushing Handler.
855 *
856 * Processes the Smush request and sends back the next id for smushing.
857 */
858 public function process_smush_request() {
859 check_ajax_referer( 'wp-smush-ajax', '_nonce' );
860
861 // Check capability.
862 if ( ! Helper::is_user_allowed( 'manage_options' ) ) {
863 wp_send_json_error(
864 array(
865 'error' => 'unauthorized',
866 'error_message' => esc_html__( "You don't have permission to do this.", 'wp-smushit' ),
867 ),
868 403
869 );
870 }
871
872 $new_bulk_smush = ! empty( $_REQUEST['new_bulk_smush_started'] ) && $_REQUEST['new_bulk_smush_started'] !== 'false';
873 if ( $new_bulk_smush ) {
874 do_action( 'wp_smush_bulk_smush_start' );
875 }
876
877 $attachment_id = 0;
878 if ( ! empty( $_REQUEST['attachment_id'] ) ) {
879 $attachment_id = (int) $_REQUEST['attachment_id'];
880 }
881
882 $smush = WP_Smush::get_instance()->core()->mod->smush;
883
884 /**
885 * Smush image.
886 *
887 * @since 3.9.6
888 *
889 * @param int $attachment_id Attachment ID.
890 * @param array $meta Image metadata (passed by reference).
891 * @param WP_Error $errors WP_Error (passed by reference).
892 */
893 $smush->smushit( $attachment_id, $meta, $errors );
894
895 $smush_data = get_post_meta( $attachment_id, Smush::$smushed_meta_key, true );
896 $resize_savings = get_post_meta( $attachment_id, 'wp-smush-resize_savings', true );
897 $conversion_savings = Helper::get_pngjpg_savings( $attachment_id );
898
899 $stats = array(
900 'count' => ! empty( $smush_data['sizes'] ) ? count( $smush_data['sizes'] ) : 0,
901 'size_before' => ! empty( $smush_data['stats'] ) ? $smush_data['stats']['size_before'] : 0,
902 'size_after' => ! empty( $smush_data['stats'] ) ? $smush_data['stats']['size_after'] : 0,
903 'savings_resize' => max( $resize_savings, 0 ),
904 'savings_conversion' => $conversion_savings['bytes'] > 0 ? $conversion_savings : 0,
905 'is_lossy' => ! empty( $smush_data ['stats'] ) ? $smush_data['stats']['lossy'] : false,
906 );
907
908 if ( $errors && is_wp_error( $errors ) && $errors->has_errors() ) {
909 $error_code = $errors->get_error_code();
910 $error_message = $errors->get_error_message( $error_code );
911 $error_data = $errors->get_error_data( $error_code );
912
913 // Check for timeout error and suggest filtering timeout.
914 if ( strpos( $error_message, 'timed out' ) ) {
915 $error_code = 'timeout';
916 }
917
918 $response = array(
919 'stats' => $stats,
920 'error' => $error_code,
921 'error_message' => Helper::filter_error( $error_message, $attachment_id ),
922 'show_warning' => (int) $smush->show_warning(),
923 'error_class' => '',
924 );
925
926 // Add error_data (file_name) to response data.
927 if ( $error_data && is_array( $error_data ) ) {
928 $response = array_merge( $error_data, $response );
929 }
930
931 // Send data.
932 wp_send_json_error( $response );
933 }
934
935 // Check if a resmush request, update the resmush list.
936 if ( ! empty( $_REQUEST['is_bulk_resmush'] ) && 'false' !== $_REQUEST['is_bulk_resmush'] && $_REQUEST['is_bulk_resmush'] ) {
937 $smush->update_resmush_list( $attachment_id );
938 } else {
939 Core::add_to_smushed_list( $attachment_id );
940 }
941
942 // Runs after a image is successfully smushed.
943 do_action( 'image_smushed', $attachment_id, $stats );
944
945 // Send ajax response.
946 wp_send_json_success(
947 array(
948 'stats' => $stats,
949 'show_warning' => (int) $smush->show_warning(),
950 )
951 );
952 }
953
954 /**
955 * Remove the image meta that is making the image skip bulk smush.
956 *
957 * @since 3.0
958 */
959 public function remove_from_skip_list() {
960 check_ajax_referer( 'wp-smush-remove-skipped' );
961
962 if ( ! Helper::is_user_allowed( 'upload_files' ) ) {
963 wp_send_json_error(
964 array(
965 'error_message' => esc_html__( "You don't have permission to work with uploaded files.", 'wp-smushit' ),
966 ),
967 403
968 );
969 }
970
971 if ( ! isset( $_POST['id'] ) ) {
972 wp_send_json_error();
973 }
974
975 $attachment_id = absint( $_POST['id'] );
976
977 // Undo ignored file.
978 delete_post_meta( $attachment_id, 'wp-smush-ignore-bulk' );
979 wp_send_json_success(
980 array(
981 'html' => WP_Smush::get_instance()->library()->generate_markup( $attachment_id ),
982 )
983 );
984 }
985
986 /***************************************
987 *
988 * DIRECTORY SMUSH
989 */
990
991 /**
992 * Returns Directory Smush stats and Cumulative stats
993 */
994 public function get_dir_smush_stats() {
995 check_ajax_referer( 'wp-smush-ajax' );
996
997 // Check capability.
998 $capability = is_multisite() ? 'manage_network' : 'manage_options';
999 if ( ! Helper::is_user_allowed( $capability ) ) {
1000 wp_die( esc_html__( 'Unauthorized', 'wp-smushit' ), 403 );
1001 }
1002
1003 $result = array();
1004
1005 // Store the Total/Smushed count.
1006 $stats = WP_Smush::get_instance()->core()->mod->dir->total_stats();
1007
1008 $result['dir_smush'] = $stats;
1009
1010 // Cumulative Stats.
1011 $result['combined_stats'] = WP_Smush::get_instance()->core()->mod->dir->combine_stats( $stats );
1012
1013 // Store the stats in options table.
1014 update_option( 'dir_smush_stats', $result, false );
1015
1016 // Send ajax response.
1017 wp_send_json_success( $result );
1018 }
1019
1020 /***************************************
1021 *
1022 * CDN
1023 *
1024 * @since 3.0
1025 */
1026
1027 /**
1028 * Toggle CDN.
1029 *
1030 * Handles "Get Started" button press on the disabled CDN meta box.
1031 * Handles "Deactivate" button press on the CDN meta box.
1032 * Refreshes page on success.
1033 *
1034 * @since 3.0
1035 */
1036 public function toggle_cdn() {
1037 check_ajax_referer( 'save_wp_smush_options' );
1038
1039 if ( ! Helper::is_user_allowed( 'manage_options' ) ) {
1040 wp_send_json_error(
1041 array(
1042 'message' => __( 'User can not modify options', 'wp-smushit' ),
1043 ),
1044 403
1045 );
1046 }
1047
1048 $enable = filter_input( INPUT_POST, 'param', FILTER_VALIDATE_BOOLEAN );
1049 $response = WP_Smush::get_instance()->core()->mod->cdn->toggle_cdn( $enable );
1050
1051 if ( is_wp_error( $response ) ) {
1052 wp_send_json_error(
1053 array( 'message' => $response->get_error_message() )
1054 );
1055 }
1056
1057 wp_send_json_success();
1058 }
1059
1060 /***************************************
1061 *
1062 * WebP
1063 *
1064 * @since 3.8.0
1065 */
1066
1067 /**
1068 * Toggle WebP.
1069 *
1070 * Handles "Activate" button press on the disabled WebP meta box.
1071 * Handles "Deactivate" button press on the WebP meta box.
1072 * Refreshes page on success.
1073 *
1074 * @since 3.8.0
1075 */
1076 public function webp_toggle() {
1077 check_ajax_referer( 'save_wp_smush_options' );
1078
1079 $capability = is_multisite() ? 'manage_network' : 'manage_options';
1080 if ( ! Helper::is_user_allowed( $capability ) ) {
1081 wp_send_json_error(
1082 array(
1083 'message' => __( "You don't have permission to do this.", 'wp-smushit' ),
1084 ),
1085 403
1086 );
1087 }
1088
1089 $param = isset( $_POST['param'] ) ? sanitize_text_field( wp_unslash( $_POST['param'] ) ) : '';
1090 $enable_webp = 'true' === $param;
1091
1092 WP_Smush::get_instance()->core()->mod->webp->toggle_webp( $enable_webp );
1093
1094 wp_send_json_success();
1095 }
1096
1097 /**
1098 * Check server configuration status and other info for WebP.
1099 *
1100 * Handles "Re-Check Status" button press on the WebP meta box.
1101 *
1102 * @since 3.8.0
1103 */
1104 public function webp_get_status() {
1105 if ( ! check_ajax_referer( 'wp-smush-webp-nonce', false, false ) || ! Helper::is_user_allowed( 'manage_options' ) ) {
1106 wp_send_json_error( esc_html__( "Either the nonce expired or you can't modify options. Please reload the page and try again.", 'wp-smushit' ) );
1107 }
1108
1109 $is_configured = WP_Smush::get_instance()->core()->mod->webp->get_is_configured_with_error_message( true );
1110
1111 if ( true === $is_configured ) {
1112 wp_send_json_success();
1113 }
1114
1115 // The messages are set in React with dangerouslySetInnerHTML so they must be html-escaped.
1116 wp_send_json_error( esc_html( $is_configured ) );
1117 }
1118
1119 /**
1120 * Write apache rules for WebP support from .htaccess file.
1121 * Handles the "Apply Rules" button press on the WebP meta box.
1122 *
1123 * @since 3.8.0
1124 */
1125 public function webp_apply_htaccess_rules() {
1126 if ( ! check_ajax_referer( 'wp-smush-webp-nonce', false, false ) || ! Helper::is_user_allowed( 'manage_options' ) ) {
1127 wp_send_json_error( "Either the nonce expired or you can't modify options. Please reload the page and try again." );
1128 }
1129
1130 $was_written = WP_Smush::get_instance()->core()->mod->webp->save_htaccess();
1131
1132 if ( true === $was_written ) {
1133 wp_send_json_success();
1134 }
1135
1136 wp_send_json_error( wp_kses_post( $was_written ) );
1137 }
1138
1139 /**
1140 * Delete all webp images.
1141 * Triggered by the "Delete WebP images" button in the webp tab.
1142 *
1143 * @since 3.8.0
1144 */
1145 public function webp_delete_all() {
1146 check_ajax_referer( 'save_wp_smush_options' );
1147
1148 $capability = is_multisite() ? 'manage_network' : 'manage_options';
1149
1150 if ( ! Helper::is_user_allowed( $capability ) ) {
1151 wp_send_json_error(
1152 array(
1153 'message' => __( 'This user can not delete all WebP images.', 'wp-smushit' ),
1154 ),
1155 403
1156 );
1157 }
1158
1159 WP_Smush::get_instance()->core()->mod->webp->delete_all();
1160
1161 wp_send_json_success();
1162 }
1163
1164 /**
1165 * Toggles the webp wizard.
1166 *
1167 * @since 3.8.8
1168 */
1169 public function webp_toggle_wizard() {
1170 if ( check_ajax_referer( 'wp-smush-webp-nonce', false, false ) && Helper::is_user_allowed( 'manage_options' ) ) {
1171 $is_hidden = get_site_option( 'wp-smush-webp_hide_wizard' );
1172 update_site_option( 'wp-smush-webp_hide_wizard', ! $is_hidden );
1173 wp_send_json_success();
1174 }
1175 }
1176
1177 /***************************************
1178 *
1179 * LAZY LOADING
1180 *
1181 * @since 3.2.0
1182 */
1183
1184 /**
1185 * Toggle lazy loading module.
1186 *
1187 * Handles "Activate" button press on the disabled lazy loading meta box.
1188 * Handles "Deactivate" button press on the lazy loading meta box.
1189 * Refreshes page on success.
1190 *
1191 * @since 3.2.0
1192 */
1193 public function smush_toggle_lazy_load() {
1194 check_ajax_referer( 'save_wp_smush_options' );
1195
1196 if ( ! Helper::is_user_allowed( 'manage_options' ) ) {
1197 wp_send_json_error(
1198 array(
1199 'message' => __( 'User can not modify options', 'wp-smushit' ),
1200 ),
1201 403
1202 );
1203 }
1204
1205 $param = isset( $_POST['param'] ) ? sanitize_text_field( wp_unslash( $_POST['param'] ) ) : false;
1206
1207 if ( 'true' === $param ) {
1208 $settings = $this->settings->get_setting( 'wp-smush-lazy_load' );
1209
1210 // No settings, during init - set defaults.
1211 if ( ! $settings ) {
1212 $this->settings->init_lazy_load_defaults();
1213 }
1214 }
1215
1216 $this->settings->set( 'lazy_load', 'true' === $param );
1217
1218 wp_send_json_success();
1219 }
1220
1221 /**
1222 * Remove spinner/placeholder icon from lazy-loading.
1223 *
1224 * @since 3.2.2
1225 */
1226 public function remove_icon() {
1227 check_ajax_referer( 'save_wp_smush_options' );
1228
1229 // Check for permission.
1230 if ( ! Helper::is_user_allowed( 'manage_options' ) ) {
1231 wp_die( esc_html__( 'Unauthorized', 'wp-smushit' ), 403 );
1232 }
1233
1234 $id = filter_input( INPUT_POST, 'id', FILTER_SANITIZE_NUMBER_INT );
1235 $type = filter_input( INPUT_POST, 'type', FILTER_SANITIZE_SPECIAL_CHARS );
1236 if ( $id && $type ) {
1237 $settings = $this->settings->get_setting( 'wp-smush-lazy_load' );
1238 if ( false !== ( $key = array_search( $id, $settings['animation'][ $type ]['custom'] ) ) ) {
1239 unset( $settings['animation'][ $type ]['custom'][ $key ] );
1240 $this->settings->set_setting( 'wp-smush-lazy_load', $settings );
1241 }
1242 }
1243
1244 wp_send_json_success();
1245 }
1246
1247 /***************************************
1248 *
1249 * CONFIGS
1250 *
1251 * @since 3.8.5
1252 */
1253
1254 /**
1255 * Handles the upload of a config file.
1256 *
1257 * @since 3.8.5
1258 */
1259 public function upload_config() {
1260 check_ajax_referer( 'smush_handle_config' );
1261
1262 $capability = is_multisite() ? 'manage_network' : 'manage_options';
1263 if ( ! Helper::is_user_allowed( $capability ) ) {
1264 wp_send_json_error( null, 403 );
1265 }
1266
1267 /**
1268 * Data escaped and sanitized via \Smush\Core\Configs::save_uploaded_config()
1269 *
1270 * @see \Smush\Core\Configs::decode_and_validate_config_file()
1271 */
1272 $file = isset( $_FILES['file'] ) ? wp_unslash( $_FILES['file'] ) : false; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
1273
1274 $configs_handler = new Configs();
1275 $new_config = $configs_handler->save_uploaded_config( $file );
1276
1277 if ( ! is_wp_error( $new_config ) ) {
1278 wp_send_json_success( $new_config );
1279 }
1280
1281 wp_send_json_error(
1282 array( 'error_msg' => $new_config->get_error_message() )
1283 );
1284 }
1285 /**
1286 * Handles the upload of a config file.
1287 *
1288 * @since 3.8.5
1289 */
1290 public function save_config() {
1291 check_ajax_referer( 'smush_handle_config' );
1292
1293 $capability = is_multisite() ? 'manage_network' : 'manage_options';
1294 if ( ! Helper::is_user_allowed( $capability ) ) {
1295 wp_send_json_error( null, 403 );
1296 }
1297
1298 $configs_handler = new Configs();
1299 wp_send_json_success( $configs_handler->get_config_from_current() );
1300 }
1301
1302 /**
1303 * Applies the given config.
1304 *
1305 * @since 3.8.5
1306 */
1307 public function apply_config() {
1308 check_ajax_referer( 'smush_handle_config' );
1309
1310 $capability = is_multisite() ? 'manage_network' : 'manage_options';
1311 if ( ! Helper::is_user_allowed( $capability ) ) {
1312 wp_send_json_error( null, 403 );
1313 }
1314
1315 $id = filter_input( INPUT_POST, 'id', FILTER_SANITIZE_NUMBER_INT );
1316 if ( ! $id ) {
1317 // Abort if no config ID was given.
1318 wp_send_json_error(
1319 array( 'error_msg' => esc_html__( 'Missing config ID', 'wp-smushit' ) )
1320 );
1321 }
1322
1323 $configs_handler = new Configs();
1324 $response = $configs_handler->apply_config_by_id( $id );
1325
1326 if ( ! is_wp_error( $response ) ) {
1327 wp_send_json_success();
1328 }
1329
1330 wp_send_json_error(
1331 array( 'error_msg' => esc_html( $response->get_error_message() ) )
1332 );
1333 }
1334
1335 /***************************************
1336 *
1337 * SETTINGS
1338 *
1339 * @since 3.2.0.2
1340 */
1341
1342 /**
1343 * Re-check API status.
1344 *
1345 * @since 3.2.0.2
1346 */
1347 public function recheck_api_status() {
1348 // Check for permission.
1349 if ( ! Helper::is_user_allowed( 'manage_options' ) ) {
1350 wp_die( esc_html__( 'Unauthorized', 'wp-smushit' ), 403 );
1351 }
1352 WP_Smush::get_instance()->validate_install( true );
1353 wp_send_json_success();
1354 }
1355
1356 /***************************************
1357 *
1358 * MODALS
1359 *
1360 * @since 3.7.0
1361 */
1362
1363 /**
1364 * Hide the new features modal
1365 *
1366 * @since 3.7.0
1367 */
1368 public function hide_new_features_modal() {
1369 check_ajax_referer( 'wp-smush-ajax' );
1370
1371 // Check for permission.
1372 if ( ! Helper::is_user_allowed( 'manage_options' ) ) {
1373 wp_die( esc_html__( 'Unauthorized', 'wp-smushit' ), 403 );
1374 }
1375 delete_site_option( 'wp-smush-show_upgrade_modal' );
1376 wp_send_json_success();
1377 }
1378
1379 /**
1380 * Ignore image failed images.
1381 *
1382 * @since 3.12.0
1383 */
1384 public function ajax_ignore_all_failed_items() {
1385 check_ajax_referer( 'wp-smush-ajax' );
1386
1387 if ( ! Helper::is_user_allowed( 'manage_options' ) ) {
1388 wp_send_json_error(
1389 array(
1390 'message' => __( "You don't have permission to do this.", 'wp-smushit' ),
1391 ),
1392 403
1393 );
1394 }
1395
1396 // Ignore all failed images.
1397 if ( $this->ignore_all_failed_items() ) {
1398 wp_send_json_success();
1399 }
1400
1401 wp_send_json_error();
1402 }
1403
1404 /**
1405 * Ignore all failed items.
1406 *
1407 * @return bool
1408 */
1409 private function ignore_all_failed_items() {
1410 global $wpdb;
1411
1412 $failed_images = $wpdb->get_col(
1413 $wpdb->prepare(
1414 "SELECT post_meta_error.post_id FROM $wpdb->postmeta as post_meta_error
1415 LEFT JOIN $wpdb->postmeta as post_meta_ignored ON post_meta_ignored.post_id = post_meta_error.post_id AND post_meta_ignored.meta_key= %s
1416 WHERE post_meta_ignored.meta_value IS NULL AND post_meta_error.meta_key = %s",
1417 Error_Handler::IGNORE_KEY,
1418 Error_Handler::ERROR_KEY
1419 )
1420 );
1421 if ( empty( $failed_images ) ) {
1422 return;
1423 }
1424
1425 foreach ( $failed_images as $failed_image_id ) {
1426 update_post_meta( $failed_image_id, Error_Handler::IGNORE_KEY, 1 );
1427 }
1428 return true;
1429 }
1430 }
1431