PluginProbe
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance / 4.7.0
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance v4.7.0
4.7.0 4.6.1 4.6.0 4.5.5 4.5.4 4.5.3 4.5.2 3.2.20 3.2.21 3.2.22 3.2.3 3.2.5 3.2.6 3.2.7 3.2.9 3.3.0 3.3.1 3.3.2 3.4.0 3.4.1 3.4.2 3.5.0 3.6.0 3.7.0 3.7.1 All 111 releases
← All changes | includes/class-updraft-smush-manager.php +422 -297 3.3.2 → 4.7.0 View file →
@@ -74,11 +74,10 @@
74 74 add_action('ud_task_completed', array($this, 'record_stats'));
75 75 add_action('ud_task_failed', array($this, 'record_stats'));
76 76 add_action('prune_smush_logs', array($this, 'prune_smush_logs'));
77 77 add_action('process_smush_tasks', array($this, 'process_smush_tasks'));
78 - if ('show' == $this->options->get_option('show_smush_metabox', 'show')) {
78 + if ('show' === $this->options->get_option('show_smush_metabox', 'show')) {
79 79 add_action('add_meta_boxes_attachment', array($this, 'add_smush_metabox'), 10, 2);
80 - add_filter('attachment_fields_to_edit', array($this, 'add_compress_button_to_media_modal' ), 10, 2);
81 80 }
82 81 add_action('delete_attachment', array($this, 'unscheduled_original_file_deletion'));
83 82
84 83 add_filter('manage_media_columns', array($this, 'manage_media_columns'));
@@ -89,9 +88,9 @@
89 88
90 89 // add filter for already compressed images by EWWW Image Optimizer.
91 90 add_filter('wpo_get_uncompressed_images_args', array($this, 'ewww_image_optimizer_compressed_images_args'));
92 91
93 - // schedule or unschedule clear backup images cron if need
92 + // schedule or unschedule clear backup images cron, if needed
94 93 $scheduled = wp_next_scheduled('wpo_smush_clear_backup_images');
95 94 if ($this->options->get_option('back_up_delete_after', true)) {
96 95 if (!$scheduled) {
97 96 wp_schedule_event(time(), 'daily', 'wpo_smush_clear_backup_images');
@@ -112,9 +111,9 @@
112 111 /**
113 112 * Add custom column to Media Library.
114 113 *
115 114 * @param array $columns
116 - * @return mixed
115 + * @return array
117 116 */
118 117 public function manage_media_columns($columns) {
119 118 $columns['wpo_smush'] = 'WP-Optimize';
120 119
@@ -128,48 +127,88 @@
128 127 * @param int $attachment_id
129 128 */
130 129 public function manage_media_custom_column($column, $attachment_id) {
131 130 if ('wpo_smush' !== $column) return;
131 + echo $this->get_smush_details($attachment_id); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Output already escaped when generating smush details
132 + }
133 +
134 + /**
135 + * Get smush details of given image ID
136 + *
137 + * @param int $attachment_id
138 + *
139 + * @return string smush details
140 + */
141 + public function get_smush_details($attachment_id) {
142 + $info = '<div class="wpo-smush-media-library-column" data-blog="'.esc_attr(get_current_blog_id()).'" data-id="'.esc_attr($attachment_id).'">';
143 + $info .= $this->get_media_smush_column_content($attachment_id);
144 + $info .= '</div>';
132 145
146 + return $info;
147 + }
148 +
149 + /**
150 + * Get content for Media Library column.
151 + *
152 + * @param int $attachment_id
153 + *
154 + * @return string
155 + */
156 + public function get_media_smush_column_content($attachment_id) {
133 157 $file = get_attached_file($attachment_id);
158 + if (false === $file) {
159 + return '';
160 + }
134 161 $ext = WPO_Image_Utils::get_extension($file);
135 162 $allowed_extensions = WPO_Image_Utils::get_allowed_extensions();
136 163
137 - $smush_stats = get_post_meta($attachment_id, 'smush-stats', true);
164 + $compressed = get_post_meta($attachment_id, '_wpo-smush-complete', true) ? true : false;
165 + $has_backup = get_post_meta($attachment_id, '_wpo-original-file', true) ? true : false;
138 166
139 - if (empty($smush_stats)) {
140 - if ($this->is_compressed($attachment_id)) {
141 - _e('The file was either compressed using another tool or marked as compressed', 'wp-optimize');
142 - } else {
143 - if (in_array($ext, $allowed_extensions) && file_exists($file)) {
144 - printf('<a href="%1$s">%2$s</a><br>', admin_url("post.php?post=" . (int) $attachment_id . "&action=edit"), __('Compress', 'wp-optimize'));
145 - }
146 - }
147 - return;
167 + $smush_info = get_post_meta($attachment_id, '_wpo-smush-info', true);
168 + $smush_stats = get_post_meta($attachment_id, '_wpo-smush-stats', true);
169 + $marked = get_post_meta($attachment_id, '_wpo-smush-marked');
170 +
171 + $extract = array(
172 + 'blog_id' => get_current_blog_id(),
173 + 'post_id' => $attachment_id,
174 + 'smush_info_display'=> $compressed ? "display:inline-block;" : "display:none;",
175 + 'smush_display' => $compressed ? "display:none;" : "display:inline-block;",
176 + 'before_smush_sep' => !$compressed ? '<span class="wpo-action-separator"> | </span>' : '',
177 + 'restore_action' => $has_backup && $compressed ? "display:block;" : "display:none;",
178 + 'smush_mark' => !$compressed && !$marked ? "display:inline-block;" : "display:none;",
179 + 'smush_unmark' => $marked ? "display:inline-block;" : "display:none;",
180 + 'smush_info' => $smush_info ?: ' ',
181 + 'smush_details' => '',
182 + 'restore_tooltip' => $this->get_restore_image_tooltip_text(),
183 + 'smush_marked' => $marked,
184 + );
185 +
186 + if (!empty($smush_stats['sizes-info'])) {
187 + $extract['smush_details'] = WP_Optimize()->include_template('images/smush-details.php', true, array('sizes_info' => $smush_stats['sizes-info']));
148 188 }
149 189
150 - if (WPO_Image_Utils::is_supported_extension($ext, array_diff($allowed_extensions, array('gif'))) && file_exists($file) && !file_exists($file . '.webp')) {
151 - if (WPO_WebP_Utils::can_do_webp_conversion()) {
152 - printf('<a href="#" class="convert-to-webp" data-attachment-id="%d">%s</a><br>', $attachment_id, __('Convert to WebP', 'wp-optimize'));
153 - }
154 - }
190 + $extract['compressed_by_another_plugin'] = $this->is_image_compressed_by_another_plugin($attachment_id);
155 191
156 - $original_size = $smush_stats['original-size'];
157 - $smushed_size = $smush_stats['smushed-size'];
192 + $output = '';
158 193
159 - if (0 == $original_size) {
160 - $info = sprintf(__('The file was compressed to %s using WP-Optimize', 'wp-optimize'), WP_Optimize()->format_size($smushed_size));
194 + if (WPO_Image_Utils::is_supported_extension($ext, $allowed_extensions)) {
195 + $output .= WP_Optimize()->include_template('admin-medialibrary-smush-column.php', true, $extract);
161 196 } else {
162 - $saved = round((($original_size - $smushed_size) / $original_size * 100), 2);
163 - $info = sprintf(__('The file was compressed from %s to %s, saving %s percent, using WP-Optimize', 'wp-optimize'), WP_Optimize()->format_size($original_size), WP_Optimize()->format_size($smushed_size), $saved);
197 + $message = __('Compressing this file type extension is not supported', 'wp-optimize');
198 + $output .= sprintf("<p>%s</p>", esc_html($message));
199 +
164 200 }
165 201
166 - echo htmlentities($info);
202 + if (WPO_Image_Utils::is_supported_extension($ext, array_diff($allowed_extensions, array('gif'))) && file_exists($file) && !file_exists($file . '.webp')) {
203 + if (WPO_WebP_Utils::can_do_webp_conversion()) {
204 + $link_text = __('Convert to WebP', 'wp-optimize');
205 + $output .= '<span class="wpo-action-separator"> | </span>';
206 + $output .= sprintf('<a href="#" class="convert-to-webp" data-attachment-id="%d">%s</a><br>', esc_attr($attachment_id), esc_html($link_text));
207 + }
208 + }
167 209
168 - // Display additional information about resized images.
169 - if (!empty($smush_stats['sizes-info'])) {
170 - WP_Optimize()->include_template('images/smush-details.php', false, array('sizes_info' => $smush_stats['sizes-info']));
171 - }
210 + return $output;
172 211 }
173 212
174 213 /**
175 214 * The Task Manager AJAX handler
@@ -175,25 +214,25 @@
175 214 * The Task Manager AJAX handler
176 215 */
177 216 public function updraft_smush_ajax() {
178 217
179 - $nonce = empty($_REQUEST['nonce']) ? '' : $_REQUEST['nonce'];
218 + $nonce = TeamUpdraft\WP_Optimize\Includes\Fragments\verify_nonce('nonce', 'updraft-task-manager-ajax-nonce');
219 + $subaction = TeamUpdraft\WP_Optimize\Includes\Fragments\fetch_superglobal('request', 'subaction', null, 'sanitize_key');
220 + $data = TeamUpdraft\WP_Optimize\Includes\Fragments\fetch_superglobal('request', 'data');
180 221
181 - if (!wp_verify_nonce($nonce, 'updraft-task-manager-ajax-nonce') || empty($_REQUEST['subaction']))
222 + if (empty($nonce) || empty($subaction)) {
182 223 die('Security check failed');
224 + }
183 225
184 - if (!current_user_can(WP_Optimize()->capability_required())) {
226 + if (!WP_Optimize()->current_user_can()) {
185 227 die('You are not allowed to run this command.');
186 228 }
187 229
188 - $subaction = $_REQUEST['subaction'];
189 -
190 230 $allowed_commands = Updraft_Smush_Manager_Commands::get_allowed_ajax_commands();
191 231
192 232 if (in_array($subaction, $allowed_commands)) {
193 233
194 - if (isset($_REQUEST['data'])) {
195 - $data = $_REQUEST['data'];
234 + if ($data) {
196 235 $results = call_user_func(array($this->commands, $subaction), $data);
197 236 } else {
198 237 $results = call_user_func(array($this->commands, $subaction));
199 238 }
@@ -207,13 +246,13 @@
207 246 'error_data' => $results->get_error_data(),
208 247 );
209 248 }
210 249
211 - echo json_encode($results);
250 + echo wp_json_encode($results);
212 251 } else {
213 - echo json_encode(array('error' => 'No such command found'));
252 + echo wp_json_encode(array('error' => 'No such command found'));
214 253 }
215 - die;
254 + die();
216 255 }
217 256
218 257 /**
219 258 * Creates a task to auto compress an image on upload
@@ -228,28 +267,22 @@
228 267 $allowed_extensions = WPO_Image_Utils::get_allowed_extensions();
229 268
230 269 if(!in_array($ext, $allowed_extensions)) return;
231 270
232 - if (!$this->options->get_option('autosmush', false))
271 + if (!$this->options->get_option('autosmush'))
233 272 return;
234 273
235 - if (!'image' == substr($post->post_mime_type, 0, 5))
274 + if ('image' !== substr($post->post_mime_type, 0, 5))
236 275 return;
237 276
238 277 if ($this->task_exists($post_id))
239 278 return;
240 -
241 - $options = array(
242 - 'attachment_id' => $post_id,
243 - 'blog_id' => get_current_blog_id(),
244 - 'image_quality' => $this->options->get_option('image_quality', 92),
245 - 'keep_original' => $this->options->get_option('back_up_original', true),
246 - 'preserve_exif' => $this->options->get_option('preserve_exif', true),
247 - 'lossy_compression' => $this->options->get_option('lossy_compression', false)
248 - );
249 279
280 + $task_options = $this->get_smush_options();
281 + $task_options = array_merge($task_options, array('attachment_id' => $post_id, 'blog_id' => get_current_blog_id()));
282 +
250 283 if (filesize($file) > 5242880) {
251 - $options['request_timeout'] = 180;
284 + $task_options['request_timeout'] = 180;
252 285 }
253 286
254 287 $server = $this->options->get_option('compression_server', $this->webservice);
255 288 $task_name = $this->get_associated_task($server);
@@ -254,11 +287,11 @@
254 287 $server = $this->options->get_option('compression_server', $this->webservice);
255 288 $task_name = $this->get_associated_task($server);
256 289
257 290 $blog_info = is_multisite() ? ', blog ID : '.get_current_blog_id() : '';
258 - $description = "$task_name with attachment ID : ".$post_id . $blog_info .", autocreated on : ".date("F d, Y h:i:s", time());
291 + $description = "$task_name with attachment ID : ".$post_id . $blog_info .", auto created on : ".gmdate("F d, Y h:i:s", time());
259 292
260 - $task = call_user_func(array($task_name, 'create_task'), 'smush', $description, $options, $task_name);
293 + $task = call_user_func(array($task_name, 'create_task'), 'smush', $description, $task_options, $task_name);
261 294
262 295 if ($task) $this->set_task_logger($task);
263 296 $this->log($description);
264 297
@@ -305,14 +338,14 @@
305 338 * @param int $image - ID of image
306 339 * @param array $options - options to use
307 340 * @param string $server - the server to process with
308 341 *
309 - * @return boolean - Status of the task
342 + * @return bool | WP_Error - Status of the task
310 343 */
311 344 public function compress_single_image($image, $options, $server) {
312 345 $task_name = $this->get_associated_task($server);
313 346 $blog_info = is_multisite() ? ', blog ID : '.get_current_blog_id() : '';
314 - $description = "$task_name - attachment ID : ". $image . $blog_info. ", started on : ". date("F d, Y h:i:s", time());
347 + $description = "$task_name - attachment ID : ". $image . $blog_info. ", started on : ". gmdate("F d, Y h:i:s", time());
315 348
316 349 $task = call_user_func(array($task_name, 'create_task'), 'smush', $description, $options, $task_name);
317 350 if ($task) $this->set_task_logger($task);
318 351 $this->clear_cached_data();
@@ -334,9 +367,9 @@
334 367 */
335 368 public function restore_single_image($image_id, $blog_id) {
336 369
337 370 $switched_blog = false;
338 - if (is_multisite() && current_user_can('manage_network_options')) {
371 + if (is_multisite() && WP_Optimize()->current_user_can('manage_network_options')) {
339 372 switch_to_blog($blog_id);
340 373 $switched_blog = true;
341 374 } elseif (is_multisite() && get_current_blog_id() != $blog_id) {
342 375 return new WP_Error('restore_backup_wrong_blog_id', __('The blog ID provided does not match the current blog.', 'wp-optimize'));
@@ -344,15 +377,23 @@
344 377
345 378 $error = false;
346 379
347 380 $image_path = get_attached_file($image_id);
348 - $backup_path = get_post_meta($image_id, 'original-file', true);
349 -
381 + $backup_path = get_post_meta($image_id, '_wpo-original-file', true);
382 + $uploads_dir = wp_upload_dir();
383 + $uploads_basedir = realpath($uploads_dir['basedir']);
384 +
385 + if (false === $uploads_basedir) {
386 + if ($switched_blog) {
387 + restore_current_blog();
388 + }
389 + return new WP_Error('restore_backup_issue', __('The uploads base directory is not correct.', 'wp-optimize'));
390 + }
391 +
392 + $uploads_basedir = trailingslashit($uploads_basedir);
393 +
350 394 // If the file doesn't exist, check if it's relative
351 395 if (!is_file($backup_path)) {
352 - $uploads_dir = wp_upload_dir();
353 - $uploads_basedir = trailingslashit($uploads_dir['basedir']);
354 -
355 396 if (is_file($uploads_basedir . $backup_path)) {
356 397 $backup_path = $uploads_basedir . $backup_path;
357 398 }
358 399 }
@@ -381,17 +422,27 @@
381 422 $backup_path = $uploads_basedir . $backup_path;
382 423 }
383 424 }
384 425
426 + $backup_path = realpath($backup_path);
427 + if (!$backup_path || 0 !== strpos(trailingslashit(dirname($backup_path)), $uploads_basedir)) {
428 + if ($switched_blog) {
429 + restore_current_blog();
430 + }
431 + return new WP_Error('restore_failed', __('The backup file path seems suspicious, and could not be deleted.', 'wp-optimize'));
432 + }
433 +
434 +
385 435 if (!is_file($backup_path)) {
386 436 // Delete information about backup.
387 - delete_post_meta($image_id, 'original-file');
437 + delete_post_meta($image_id, '_wpo-original-file');
388 438 $error = new WP_Error('restore_backup_not_found', __('The backup was not found; it may have been deleted or was already restored', 'wp-optimize'));
389 - } elseif (!is_writable($image_path)) {
390 - $error = new WP_Error('restore_failed', __('The destination could not be written to.', 'wp-optimize').' '.__("Please check your folder's permissions", 'wp-optimize'));
439 + } elseif (!wp_is_writable($image_path)) {
440 + $error = new WP_Error('restore_failed', __('The destination could not be written to.', 'wp-optimize').' '.__("Please check your folder's permissions", 'wp-optimize'));
391 441 } elseif (!copy($backup_path, $image_path)) {
392 - $error = new WP_Error('restore_failed', __('The file could not be copied; check your PHP error logs for details', 'wp-optimize'));
393 - } elseif (!unlink($backup_path)) {
442 + $error = new WP_Error('restore_failed', __('The file could not be copied; check your PHP error logs for details', 'wp-optimize'));
443 + } elseif (!WP_Optimize_Utils::wp_delete_file($backup_path)) {
444 + // translators: %s is the backup file path
394 445 $error = new WP_Error('restore_failed', sprintf(__('The backup file %s could not be deleted.', 'wp-optimize'), $backup_path));
395 446 }
396 447
397 448 if (!$error) {
@@ -396,12 +447,12 @@
396 447
397 448 if (!$error) {
398 449 // if backup image deleted successfully
399 450 // then delete from attachment meta associated smush data
400 - delete_post_meta($image_id, 'smush-complete');
401 - delete_post_meta($image_id, 'smush-stats');
402 - delete_post_meta($image_id, 'original-file');
403 - delete_post_meta($image_id, 'smush-info');
451 + delete_post_meta($image_id, '_wpo-smush-complete');
452 + delete_post_meta($image_id, '_wpo-smush-stats');
453 + delete_post_meta($image_id, '_wpo-original-file');
454 + delete_post_meta($image_id, '_wpo-smush-info');
404 455 }
405 456
406 457 if ($switched_blog) {
407 458 restore_current_blog();
@@ -423,9 +474,9 @@
423 474 *
424 475 * @param bool $restore_backup if true then restore images from backup otherwise just delete meta.
425 476 * @param int $blog_id blog id.
426 477 * @param int $images_limit how many images process per time.
427 - * @param bool $delete_only_backups_meta meta fields will deleted only for images those will restored from backup.
478 + * @param bool $delete_only_backups_meta meta fields will be deleted only for images those will be restored from backup.
428 479 *
429 480 * @return array ['completed' => (bool), 'message' => (string), 'error' => (string)]
430 481 */
431 482 public function bulk_restore_compressed_images($restore_backup, $blog_id = 1, $images_limit = 100, $delete_only_backups_meta = false) {
@@ -437,8 +488,9 @@
437 488
438 489 $result = array(
439 490 'completed' => false,
440 491 'message' => '',
492 + 'smushed_images_count' => 0,
441 493 );
442 494
443 495 $processed = 0;
444 496
@@ -443,9 +495,9 @@
443 495 $processed = 0;
444 496
445 497 if ($restore_backup) {
446 498 // get post ids those have backup meta field.
447 - $image_ids = $wpdb->get_results($wpdb->prepare("SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key = 'original-file' LIMIT %d;", $images_limit), ARRAY_A);
499 + $image_ids = $wpdb->get_results($wpdb->prepare("SELECT post_id FROM `{$wpdb->postmeta}` WHERE meta_key = '_wpo-original-file' LIMIT %d;", $images_limit), ARRAY_A);
448 500
449 501 if (!empty($image_ids)) {
450 502 // run restore function for each found image.
451 503 foreach ($image_ids as $image) {
@@ -450,9 +502,9 @@
450 502 // run restore function for each found image.
451 503 foreach ($image_ids as $image) {
452 504 $restore_result = $this->restore_single_image($image['post_id'], $blog_id);
453 505
454 - // if we get an error then we stop the work, except situation when "backup already restored'.
506 + // if we get an error then we stop the work, except situation when "backup already restored".
455 507 if (is_wp_error($restore_result) && 'restore_backup_not_found' != $restore_result->get_error_code()) {
456 508 // we need to stop the work as we haven't restored the backup.
457 509 $result['error'] = $restore_result->get_error_message();
458 510 $this->options->delete_option('smush_images_restored');
@@ -465,9 +517,9 @@
465 517
466 518 $images_count = count($image_ids);
467 519
468 520 // if all images processed then set flag completed to true.
469 - if ($processed == $images_count && $images_count < $images_limit) {
521 + if ($processed === $images_count && $images_count < $images_limit) {
470 522 $this->options->delete_option('smush_images_restored');
471 523 $result['completed'] = true;
472 524 } else {
473 525 // save into options total processed count.
@@ -474,10 +526,12 @@
474 526 $processed += $this->options->get_option('smush_images_restored', 0);
475 527 $this->options->update_option('smush_images_restored', $processed);
476 528
477 529 if (is_multisite()) {
478 - $result['message'] = sprintf(__('%s compressed images were restored from their backup for the site %s', 'wp-optimize'), $processed, get_site_url($blog_id));
530 + // translators: %1$s is the number of restored images, %2$s is the site url.
531 + $result['message'] = sprintf(__('%1$s compressed images were restored from their backup for the site %2$s', 'wp-optimize'), $processed, get_site_url($blog_id));
479 532 } else {
533 + // translators: %s is the number of restored images.
480 534 $result['message'] = sprintf(__('%s compressed images were restored from their backup', 'wp-optimize'), $processed);
481 535 }
482 536 }
483 537
@@ -486,16 +540,35 @@
486 540 $result['completed'] = true;
487 541 }
488 542
489 543 if ($result['completed']) {
544 +
545 + $smushed_images_count = $wpdb->get_var("SELECT COUNT(*) FROM `{$wpdb->postmeta}` WHERE meta_key='_wpo-smush-complete' AND meta_value=1");
546 + $result['smushed_images_count'] = $smushed_images_count;
547 +
490 548 if ($delete_only_backups_meta) {
491 549 if (is_multisite()) {
492 - $result['message'] = sprintf(__('All the compressed images for the site %s were successfully restored.', 'wp-optimize'), get_site_url($blog_id));
550 + if ($smushed_images_count > 0) {
551 + // translators: %s is the site url
552 + $result['message'] = sprintf(__('All the compressed images for site %s with backup copies of their original files were successfully restored.', 'wp-optimize'), get_site_url($blog_id));
553 + // translators: %s is the number of images
554 + $result['message'] .= ' '.sprintf(_n('Unable to restore %s image without backup files.', 'Unable to restore %s images without backup files.', $smushed_images_count, 'wp-optimize'), $smushed_images_count);
555 + } else {
556 + // translators: %s is the site url
557 + $result['message'] = sprintf(__('All the compressed images for the site %s were successfully restored.', 'wp-optimize'), get_site_url($blog_id));
558 + }
493 559 } else {
494 - $result['message'] = __('All the compressed images were successfully restored.', 'wp-optimize');
560 + if ($smushed_images_count > 0) {
561 + $result['message'] = __('All the compressed images with backup copies of their original files were successfully restored.', 'wp-optimize');
562 + // translators: %s is the number of images
563 + $result['message'] .= ' '.sprintf(_n('Unable to restore %s image without backup files.', 'Unable to restore %s images without backup files.', $smushed_images_count, 'wp-optimize'), $smushed_images_count);
564 + } else {
565 + $result['message'] = __('All the compressed images were successfully restored.', 'wp-optimize');
566 + }
495 567 }
496 568 } else {
497 569 if (is_multisite()) {
570 + // translators: %s is the site url
498 571 $result['message'] = sprintf(__('All the compressed images for the site %s were successfully marked as uncompressed.', 'wp-optimize'), get_site_url($blog_id));
499 572 } else {
500 573 $result['message'] = __('All the compressed images were successfully marked as uncompressed.', 'wp-optimize');
501 574 }
@@ -502,11 +575,11 @@
502 575 }
503 576
504 577 // clear all metas for smushed images after work completed.
505 578 // if $delete_only_backup_meta set to true then all meta fields was deleted in restore_single_image()
506 - // and we don't need delete metas for other images.
579 + // and we don't need to delete metas for other images.
507 580 if (!$delete_only_backups_meta) {
508 - $wpdb->query("DELETE FROM {$wpdb->postmeta} WHERE meta_key IN ('smush-complete', 'smush-stats', 'original-file', 'smush-info');");
581 + $wpdb->query("DELETE FROM `{$wpdb->postmeta}` WHERE meta_key IN ('_wpo-smush-complete', '_wpo-smush-stats', '_wpo-original-file', '_wpo-smush-info');");
509 582 }
510 583 }
511 584
512 585 if (is_multisite()) {
@@ -522,9 +595,9 @@
522 595 * @param array $images - the array of images to process
523 596 * @return bool - true if processing complete
524 597 */
525 598 public function process_bulk_smush($images = array()) {
526 -
599 +
527 600 // Get a list of pending tasks so we can exclude those
528 601 $pending_tasks = $this->get_pending_tasks();
529 602 $queued_images = array();
530 603
@@ -537,28 +610,20 @@
537 610 'blog_id' => $task->get_option('blog_id')
538 611 );
539 612 }
540 613 }
541 -
614 + $default_task_options = $this->get_smush_options();
542 615 foreach ($images as $image) {
543 616 // Skip if already in the queue
544 617 if (in_array($image, $queued_images)) continue;
545 618
546 - $options = array(
547 - 'attachment_id' => intval($image['attachment_id']),
548 - 'blog_id' => intval($image['blog_id']),
549 - 'image_quality' => $this->options->get_option('image_quality', 92),
550 - 'keep_original' => $this->options->get_option('back_up_original', true),
551 - 'preserve_exif' => $this->options->get_option('preserve_exif', true),
552 - 'lossy_compression' => $this->options->get_option('lossy_compression', false)
553 - );
554 -
619 + $task_options = array_merge($default_task_options, array('attachment_id' => intval($image['attachment_id']), 'blog_id' => intval($image['blog_id'])));
555 620 $server = $this->options->get_option('compression_server', $this->webservice);
556 621 $task_name = $this->get_associated_task($server);
557 622
558 623 $blog_info = is_multisite() ? ', Blog ID : '.intval($image['blog_id']) : '';
559 - $description = "$task_name - Attachment ID : ". intval($image['attachment_id']) . $blog_info . ", Started on : ". date("F d, Y h:i:s", time());
560 - $task = call_user_func(array($task_name, 'create_task'), 'smush', $description, $options, $task_name);
624 + $description = "$task_name - Attachment ID : ". intval($image['attachment_id']) . $blog_info . ", Started on : ". gmdate("F d, Y h:i:s", time());
625 + $task = call_user_func(array($task_name, 'create_task'), 'smush', $description, $task_options, $task_name);
561 626 if ($task) $this->set_task_logger($task);
562 627 }
563 628
564 629 $this->process_smush_tasks();
@@ -611,19 +676,19 @@
611 676 */
612 677 public function record_stats($task) {
613 678
614 679 $attachment_id = $task->get_option('attachment_id');
615 - $completed_task_count = $this->options->get_option('completed_task_count', false);
680 + $completed_task_count = $this->options->get_option('completed_task_count');
616 681 $failed_task_count = $this->options->get_option('failed_task_count', 0);
617 - $total_bytes_saved = $this->options->get_option('total_bytes_saved', false);
682 + $total_bytes_saved = $this->options->get_option('total_bytes_saved');
618 683 $total_percent_saved = $this->options->get_option('total_percent_saved', 0);
619 684
620 - if ('ud_task_failed' == current_action()) {
685 + if ('ud_task_failed' === current_action()) {
621 686 $this->options->update_option('failed_task_count', ++$failed_task_count);
622 687 return;
623 688 }
624 689
625 - if (false === $completed_task_count) {
690 + if (empty($completed_task_count)) {
626 691 $completed_task_count = $total_bytes_saved = 0;
627 692 }
628 693
629 694 if (!$total_bytes_saved) {
@@ -631,12 +696,12 @@
631 696 }
632 697
633 698 if (is_multisite()) {
634 699 switch_to_blog($task->get_option('blog_id', 1));
635 - $stats = get_post_meta($attachment_id, 'smush-stats', true);
700 + $stats = get_post_meta($attachment_id, '_wpo-smush-stats', true);
636 701 restore_current_blog();
637 702 } else {
638 - $stats = get_post_meta($attachment_id, 'smush-stats', true);
703 + $stats = get_post_meta($attachment_id, '_wpo-smush-stats', true);
639 704 }
640 705
641 706 if (isset($stats['sizes-info'])) {
642 707
@@ -649,11 +714,11 @@
649 714 }
650 715
651 716 $percent = round((($original_size - $compressed_size) / $original_size * 100), 2);
652 717 } else {
653 - $original_size = isset($stats['original-size']) ? $stats['original-size'] : 0;
654 - $compressed_size = isset($stats['smushed-size']) ? $stats['smushed-size'] : 0;
655 - $percent = isset($stats['savings-percent']) ? $stats['savings-percent'] : 0;
718 + $original_size = $stats['original-size'] ?? 0;
719 + $compressed_size = $stats['smushed-size'] ?? 0;
720 + $percent = $stats['savings-percent'] ?? 0;
656 721 }
657 722
658 723 $saved = $original_size - $compressed_size;
659 724 $completed_task_count++;
@@ -676,16 +741,17 @@
676 741 if (empty($smush_options)) {
677 742 $smush_options = array(
678 743 'compression_server' => $this->options->get_option('compression_server', $this->get_default_webservice()),
679 744 'image_quality' => $this->options->get_option('image_quality', 92),
680 - 'lossy_compression' => $this->options->get_option('lossy_compression', false),
745 + 'lossy_compression' => $this->options->get_option('lossy_compression'),
746 + 'keep_original' => $this->options->get_option('back_up_original', true),//repeated below
681 747 'back_up_original' => $this->options->get_option('back_up_original', true),
682 748 'back_up_delete_after' => $this->options->get_option('back_up_delete_after', true),
683 749 'back_up_delete_after_days' => $this->options->get_option('back_up_delete_after_days', 50),
684 750 'preserve_exif' => $this->options->get_option('preserve_exif', false),
685 - 'autosmush' => $this->options->get_option('autosmush', false),
686 - 'show_smush_metabox' => $this->options->get_option('show_smush_metabox', 'show') == 'show' ? true : false,
687 - 'webp_conversion' => $this->options->get_option('webp_conversion', false)
751 + 'autosmush' => $this->options->get_option('autosmush'),
752 + 'show_smush_metabox' => $this->options->get_option('show_smush_metabox', 'show') === 'show',
753 + 'webp_conversion' => $this->options->get_option('webp_conversion')
688 754 );
689 755 }
690 756 return $smush_options;
691 757 }
@@ -690,20 +756,29 @@
690 756 return $smush_options;
691 757 }
692 758
693 759 /**
694 - * Updates global smush options
760 + * Update smush options
761 + * Only options whose values differ from the stored values are updated.
695 762 *
696 - * @param array $options - sent in via AJAX
697 - * @return bool - status of the update
763 + * @param array $options Associative array of option names and values sent in via AJAX.
764 + * @return bool True if all updates succeeded or no changes were required,
765 + * false if at least one option update failed.
698 766 */
699 767 public function update_smush_options($options) {
700 -
768 + $success = true;
701 769 foreach ($options as $option => $value) {
702 - $this->options->update_option($option, $value);
770 + // Here we only store string, array as string after serialization, boolean, and integer values which will be stored as strings (LONGTEXT field type)
771 + // So loose comparison is fine, strict comparison results to buggy behavior
772 + if ($this->options->get_option($option) == $value) {
773 + continue;
774 + }
775 +
776 + if (!$this->options->update_option($option, $value)) {
777 + $success = false;
778 + }
703 779 }
704 -
705 - return true;
780 + return $success;
706 781 }
707 782
708 783 /**
709 784 * Clears smush related stats
@@ -724,8 +799,10 @@
724 799 *
725 800 * @return array - translations used in JS
726 801 */
727 802 public function smush_js_translations() {
803 + $resmushit_article_link = WP_Optimize()->wp_optimize_url('https://resmush.it/api/', __('resmushIt', 'wp-optimize'), '', '', true);
804 +
728 805 return apply_filters('updraft_smush_js_translations', array(
729 806 'all_images_compressed' => __('No uncompressed images were found.', 'wp-optimize'),
730 807 'error_unexpected_response' => __('An unexpected response was received from the server.', 'wp-optimize') . ' ' . __('More information has been logged in the browser console.', 'wp-optimize'),
731 808 'compress_single_image_dialog' => __('Please wait: compressing the selected image.', 'wp-optimize'),
@@ -731,9 +808,14 @@
731 808 'compress_single_image_dialog' => __('Please wait: compressing the selected image.', 'wp-optimize'),
732 809 'error_try_again_later' => __('Please try again later.', 'wp-optimize'),
733 810 'server_check' => __('Connecting to the Smush API server, please wait', 'wp-optimize'),
734 811 'please_wait' => __('Please wait while the request is being processed', 'wp-optimize'),
735 - 'server_error' => __('There was an error connecting to the image compression server.', 'wp-optimize') . ' ' . __('This could mean either the server is temporarily unavailable or there are connectivity issues with your internet connection.', 'wp-optimize') . ' ' . __('Please try later.', 'wp-optimize'),
812 + 'server_error' => __('There was an error connecting to the image compression server.', 'wp-optimize') .
813 + '<br>' . __('This could mean either the server is temporarily unavailable or there are connectivity issues with your internet connection.', 'wp-optimize') . ' ' .
814 + // translators: %s is a link
815 + '<i>' . sprintf(__('(Also ensure IPs listed at the bottom of this %s page are whitelisted by your webserver).', 'wp-optimize'), $resmushit_article_link) . '</i>' .
816 + '<br>' . __('Please try later.', 'wp-optimize'),
817 + 'exceeded_max_filesize' => __('This image is too large to be optimized — it exceeds the provider\'s size limit', 'wp-optimize'),
736 818 'please_select_images' => __('Please select the images you want compressed from the "Uncompressed images" panel first', 'wp-optimize'),
737 819 'please_updating_images_info' => __('Please wait: updating information about the selected image.', 'wp-optimize'),
738 820 'please_select_compressed_images' => __('Please select the images you want to mark as already compressed from the "Uncompressed images" panel first', 'wp-optimize'),
739 821 'view_image' => __('View Image', 'wp-optimize'),
@@ -745,8 +827,12 @@
745 827 'webp_conversion_tool_how_to' => __('How to get the WebP conversion tools to work?', 'wp-optimize'),
746 828 'more' => __('More', 'wp-optimize'),
747 829 'less' => __('Less', 'wp-optimize'),
748 830 'converting_to_webp' => __('Converting image to WebP format, please wait', 'wp-optimize'),
831 + 'compress_image' => __('Compress Image', 'wp-optimize'),
832 + 'compress' => __('Compress', 'wp-optimize'),
833 + 'cancel' => __('Cancel', 'wp-optimize'),
834 + 'close' => __('Close', 'wp-optimize'),
749 835 ));
750 836 }
751 837
752 838 /**
@@ -771,14 +857,14 @@
771 857 * @param WP_Post $post - a post object
772 858 */
773 859 public function render_smush_metabox($post) {
774 860
775 - $compressed = get_post_meta($post->ID, 'smush-complete', true) ? true : false;
776 - $has_backup = get_post_meta($post->ID, 'original-file', true) ? true : false;
861 + $compressed = (bool) get_post_meta($post->ID, '_wpo-smush-complete', true);
862 + $has_backup = (bool) get_post_meta($post->ID, '_wpo-original-file', true);
777 863
778 - $smush_info = get_post_meta($post->ID, 'smush-info', true);
779 - $smush_stats = get_post_meta($post->ID, 'smush-stats', true);
780 - $marked = get_post_meta($post->ID, 'smush-marked', false);
864 + $smush_info = get_post_meta($post->ID, '_wpo-smush-info', true);
865 + $smush_stats = get_post_meta($post->ID, '_wpo-smush-stats', true);
866 + $marked = get_post_meta($post->ID, '_wpo-smush-marked');
781 867
782 868 $options = Updraft_Smush_Manager()->get_smush_options();
783 869
784 870 $file = get_attached_file($post->ID);
@@ -787,18 +873,20 @@
787 873 $file_size = ($file && is_file($file)) ? filesize($file) : 0;
788 874
789 875 $extract = array(
790 876 'post_id' => $post->ID,
791 - 'smush_display' => $compressed ? "style='display:none;'" : "style='display:block;'",
792 - 'restore_display' => $compressed ? "style='display:block;'" : "style='display:none;'",
793 - 'restore_action' => $has_backup ? "style='display:block;'" : "style='display:none;'",
794 - 'smush_mark' => !$compressed && !$marked ? "style='display:block;'" : "style='display:none;'",
795 - 'smush_unmark' => $marked ? "style='display:block;'" : "style='display:none;'",
796 - 'smush_info' => $smush_info ? $smush_info : ' ',
877 + 'smush_display' => $compressed ? "display:none;" : "display:block;",
878 + 'restore_display' => $compressed ? "display:block;" : "display:none;",
879 + 'restore_action' => $has_backup ? "display:block;" : "display:none;",
880 + 'smush_mark' => !$compressed && !$marked ? "display:block;" : "display:none;",
881 + 'smush_unmark' => $marked ? "display:block;" : "display:none;",
882 + 'smush_info' => $smush_info ?: ' ',
797 883 'file_size' => $file_size,
798 884 'smush_options' => $options,
799 885 'custom' => 90 >= $options['image_quality'] && 65 <= $options['image_quality'],
800 886 'smush_details' => '',
887 + 'restore_tooltip' => $this->get_restore_image_tooltip_text(),
888 + 'smush_marked' => $marked,
801 889 );
802 890
803 891 if (!empty($smush_stats['sizes-info'])) {
804 892 $extract['smush_details'] = WP_Optimize()->include_template('images/smush-details.php', true, array('sizes_info' => $smush_stats['sizes-info']));
@@ -803,17 +891,31 @@
803 891 if (!empty($smush_stats['sizes-info'])) {
804 892 $extract['smush_details'] = WP_Optimize()->include_template('images/smush-details.php', true, array('sizes_info' => $smush_stats['sizes-info']));
805 893 }
806 894
895 + $extract['smush_settings_form'] = WP_Optimize()->include_template('admin-metabox-smush-settings.php', true, $extract);
807 896 $extract['compressed_by_another_plugin'] = $this->is_image_compressed_by_another_plugin($post->ID);
808 897 if (WPO_Image_Utils::is_supported_extension($ext, $allowed_extensions)) {
809 898 WP_Optimize()->include_template('admin-metabox-smush.php', false, $extract);
810 899 } else {
811 - printf("<p>%s</p>", __('Compressing this file type extension is not supported', 'wp-optimize'));
900 + printf("<p>%s</p>", esc_html__('Compressing this file type extension is not supported', 'wp-optimize'));
812 901 }
813 902 }
814 903
815 904 /**
905 + * Get text for restore image tooltip.
906 + *
907 + * @return string
908 + */
909 + private function get_restore_image_tooltip_text() {
910 + $text = __('Only the original image will be restored.', 'wp-optimize');
911 + $text .= ' ';
912 + $text .= __('In order to restore the other sizes, you should use a plugin such as "Regenerate Thumbnails".', 'wp-optimize');
913 +
914 + return $text;
915 + }
916 +
917 + /**
816 918 * Check if a single image compressed by another plugin.
817 919 *
818 920 * @param int $image_id
819 921 * @return bool
@@ -819,10 +921,11 @@
819 921 * @return bool
820 922 */
821 923 private function is_image_compressed_by_another_plugin($image_id) {
822 924 global $wpdb;
925 + static $is_ewwwio_images_table_exists = null;
823 926
824 - $meta = $wpdb->get_results("SELECT meta_key, meta_value FROM {$wpdb->postmeta} WHERE `post_id`={$image_id}", ARRAY_A);
927 + $meta = $wpdb->get_results($wpdb->prepare("SELECT meta_key, meta_value FROM `{$wpdb->postmeta}` WHERE `post_id`=%d", $image_id), ARRAY_A);
825 928
826 929 if (is_array($meta)) {
827 930 foreach ($meta as $row) {
828 931 // Smush, Imagify, Compress JPEG & PNG images by TinyPNG.
@@ -827,16 +930,18 @@
827 930 foreach ($meta as $row) {
828 931 // Smush, Imagify, Compress JPEG & PNG images by TinyPNG.
829 932 if (in_array($row['meta_key'], array('wp-smpro-smush-data', '_imagify_optimization_level', 'tiny_compress_images'))) return true;
830 933 // ShortPixel Image Optimizer
831 - if ('_shortpixel_status' == $row['meta_key'] && 2 <= $row['meta_key'] && 3 > $row['meta_key']) return true;
934 + if ('_shortpixel_status' === $row['meta_key'] && 2 <= (int) $row['meta_value'] && 3 > (int) $row['meta_value']) return true;
832 935 }
833 936 }
834 937
835 - if (WP_Optimize()->get_db_info()->table_exists('ewwwio_images')) {
938 + $is_ewwwio_images_table_exists = is_null($is_ewwwio_images_table_exists) ? WP_Optimize()->get_db_info()->table_exists('ewwwio_images') : $is_ewwwio_images_table_exists;
939 +
940 + if ($is_ewwwio_images_table_exists) {
836 941 $old_show_errors = $wpdb->show_errors(false);
837 942 // EWWW Image Optimizer.
838 - $ewww_image = $wpdb->get_col("SELECT attachment_id FROM {$wpdb->prefix}ewwwio_images WHERE attachment_id={$image_id} AND gallery='media' LIMIT 1");
943 + $ewww_image = $wpdb->get_col($wpdb->prepare("SELECT attachment_id FROM `{$wpdb->prefix}ewwwio_images` WHERE attachment_id=%d AND gallery='media' LIMIT 1", $image_id));
839 944 if (!empty($ewww_image)) return true;
840 945 $wpdb->show_errors($old_show_errors);
841 946 }
842 947
@@ -855,15 +960,15 @@
855 960
856 961 if (!WP_Optimize()->get_db_info()->table_exists('ewwwio_images')) return $args;
857 962
858 963 $old_show_errors = $wpdb->show_errors(false);
859 - $compressed_images = $wpdb->get_col("SELECT DISTINCT(attachment_id) FROM {$wpdb->prefix}ewwwio_images WHERE gallery='media'");
964 + $compressed_images = $wpdb->get_col("SELECT DISTINCT(attachment_id) FROM `{$wpdb->prefix}ewwwio_images` WHERE gallery='media'");
860 965 $wpdb->show_errors($old_show_errors);
861 966
862 967 if (isset($args['post__not_in'])) {
863 - $args['post__not_in'] = array_merge($args['post__not_in'], $compressed_images);
968 + $args['post__not_in'] = array_merge($args['post__not_in'], $compressed_images); // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_post__not_in -- is necessary and used with caution
864 969 } else {
865 - $args['post__not_in'] = $compressed_images;
970 + $args['post__not_in'] = $compressed_images; // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_post__not_in -- is necessary and used with caution
866 971 }
867 972
868 973 return $args;
869 974 }
@@ -870,16 +975,17 @@
870 975
871 976 /**
872 977 * Returns a list of images for smush (from cache if available)
873 978 *
979 + * @param string $use_cache
874 980 * @return array - uncompressed images
875 981 */
876 - public function get_uncompressed_images() {
877 -
878 - $uncompressed_images = $this->get_from_cache('uncompressed_images');
982 + public function get_uncompressed_images($use_cache = "true") {
983 + if ("true" === $use_cache) {
984 + $uncompressed_images = $this->get_from_cache('uncompressed_images');
985 + if ($uncompressed_images && is_array($uncompressed_images)) return $uncompressed_images;
986 + }
879 987
880 - if ($uncompressed_images) return $uncompressed_images;
881 -
882 988 $uncompressed_images = array();
883 989 $accepted_mimes = array('image/jpeg', 'image/gif', 'image/png');
884 990
885 991 $args = array(
@@ -886,61 +992,11 @@
886 992 'post_type' => 'attachment',
887 993 'post_mime_type' => $accepted_mimes,
888 994 'post_status' => 'inherit',
889 995 'posts_per_page' => apply_filters('updraft_smush_posts_per_page', 1000),
890 - 'meta_query' => array(
891 - 'relation' => 'AND',
892 - array(
893 - 'relation' => 'OR',
894 - array(
895 - 'key' => 'smush-complete',
896 - 'compare' => '!=',
897 - 'value' => '1',
898 - ),
899 - array(
900 - 'key' => 'smush-complete',
901 - 'compare' => 'NOT EXISTS',
902 - 'value' => '',
903 - ),
904 - ),
905 - // ShortPixel Image Optimizer plugin
906 - array(
907 - 'relation' => 'OR',
908 - array(
909 - 'key' => '_shortpixel_status',
910 - 'compare' => '<',
911 - 'value' => '2',
912 - ),
913 - array(
914 - 'key' => '_shortpixel_status',
915 - 'compare' => '>=',
916 - 'value' => '3',
917 - ),
918 - array(
919 - 'key' => '_shortpixel_status',
920 - 'compare' => 'NOT EXISTS',
921 - 'value' => '',
922 - ),
923 - ),
924 - // Smush plugin
925 - array(
926 - 'key' => 'wp-smpro-smush-data',
927 - 'compare' => 'NOT EXISTS',
928 - 'value' => '',
929 - ),
930 - // Imagify
931 - array(
932 - 'key' => '_imagify_optimization_level',
933 - 'compare' => 'NOT EXISTS',
934 - 'value' => '',
935 - ),
936 - // Compress JPEG & PNG images by TinyPNG
937 - array(
938 - 'key' => 'tiny_compress_images',
939 - 'compare' => 'NOT EXISTS',
940 - 'value' => '',
941 - ),
942 - )
996 + 'meta_query' => $this->get_uncompressed_images_meta_query(),
997 + 'no_found_rows' => true,
998 + 'fields' => 'ids'
943 999 );
944 1000
945 1001 $allowed_extensions = WPO_Image_Utils::get_allowed_extensions();
946 1002
@@ -955,22 +1011,25 @@
955 1011 $args = apply_filters('wpo_get_uncompressed_images_args', $args);
956 1012 $images = new WP_Query($args);
957 1013
958 1014 foreach ($images->posts as $image) {
959 - $file = get_attached_file($image->ID);
1015 + // If `field` is removed from $args it returns a WP_Post obj
1016 + $image_id = is_int($image) ? $image : $image->ID;
1017 +
1018 + $file = get_attached_file($image_id);
960 1019 $ext = WPO_Image_Utils::get_extension($file);
961 1020 if (file_exists($file)) {
962 1021 if (WPO_Image_Utils::is_supported_extension($ext, $allowed_extensions)) {
963 1022 $uncompressed_images[$site->blog_id][] = array(
964 - 'id' => $image->ID,
965 - 'thumb_url' => wp_get_attachment_thumb_url($image->ID),
966 - 'filesize' => filesize(get_attached_file($image->ID))
1023 + 'id' => $image_id,
1024 + 'thumb_url' => wp_get_attachment_thumb_url($image_id),
1025 + 'filesize' => filesize(get_attached_file($image_id))
967 1026 );
968 1027 } else {
969 - $this->log("Blog_id={$site->blog_id}, ID={$image->ID}, File={$file} This image type is not supported.");
1028 + $this->log("Blog_id=$site->blog_id, ID=$image_id, File=$file This image type is not supported.");
970 1029 }
971 1030 } else {
972 - $this->log("Could not find file for image: blog_id={$site->blog_id}, ID={$image->ID}, file={$file}");
1031 + $this->log("Could not find file for image: blog_id=$site->blog_id, ID=$image_id, file=$file");
973 1032 }
974 1033 }
975 1034
976 1035 restore_current_blog();
@@ -979,23 +1038,26 @@
979 1038 } else {
980 1039 $args = apply_filters('wpo_get_uncompressed_images_args', $args);
981 1040 $images = new WP_Query($args);
982 1041 foreach ($images->posts as $image) {
983 - $file = get_attached_file($image->ID);
1042 + // If `field` is removed from $args it returns a WP_Post obj
1043 + $image_id = is_int($image) ? $image : $image->ID;
1044 +
1045 + $file = get_attached_file($image_id);
984 1046 $ext = WPO_Image_Utils::get_extension($file);
985 1047
986 1048 if (file_exists($file)) {
987 1049 if (WPO_Image_Utils::is_supported_extension($ext, $allowed_extensions)) {
988 1050 $uncompressed_images[1][] = array(
989 - 'id' => $image->ID,
990 - 'thumb_url' => wp_get_attachment_thumb_url($image->ID),
991 - 'filesize' => filesize(get_attached_file($image->ID))
1051 + 'id' => $image_id,
1052 + 'thumb_url' => wp_get_attachment_thumb_url($image_id),
1053 + 'filesize' => filesize(get_attached_file($image_id))
992 1054 );
993 1055 } else {
994 - $this->log("Image ID={$image->ID}, File={$file} This image type is not supported.");
1056 + $this->log("Image ID=$image_id, File=$file This image type is not supported.");
995 1057 }
996 1058 } else {
997 - $this->log("Could not find file for image: ID={$image->ID}, file={$file}");
1059 + $this->log("Could not find file for image: ID=$image_id, file=$file");
998 1060 }
999 1061 }
1000 1062 }
1001 1063
@@ -1070,13 +1132,13 @@
1070 1132 $stats = array();
1071 1133
1072 1134 foreach ($images as $image) {
1073 1135 if (is_multisite()) {
1074 - switch_to_blog($image['blog_id'], 1);
1075 - $stats[] = get_post_meta($image['attachment_id'], 'smush-complete', true) ? 'success' : 'fail';
1136 + switch_to_blog($image['blog_id']);
1137 + $stats[] = get_post_meta($image['attachment_id'], '_wpo-smush-complete', true) ? 'success' : 'fail';
1076 1138 restore_current_blog();
1077 1139 } else {
1078 - $stats[] = get_post_meta($image['attachment_id'], 'smush-complete', true) ? 'success' : 'fail';
1140 + $stats[] = get_post_meta($image['attachment_id'], '_wpo-smush-complete', true) ? 'success' : 'fail';
1079 1141 }
1080 1142 }
1081 1143
1082 1144 return array_count_values($stats);
@@ -1084,9 +1146,9 @@
1084 1146
1085 1147 /**
1086 1148 * Returns a list of images for smush (from cache if available)
1087 1149 *
1088 - * @return array - List of task objects with uncompressed images
1150 + * @return array|mixed - List of task objects with uncompressed images
1089 1151 */
1090 1152 public function get_pending_tasks() {
1091 1153 return $this->get_active_tasks('smush');
1092 1154 }
@@ -1092,16 +1154,20 @@
1092 1154 }
1093 1155
1094 1156 /**
1095 1157 * Deletes and removes any pending tasks from queue
1158 + *
1159 + * @return bool
1096 1160 */
1097 1161 public function clear_pending_images() {
1098 1162
1099 1163 $pending_tasks = $this->get_active_tasks('smush');
1100 1164
1101 - foreach ($pending_tasks as $task) {
1102 - $task->delete_meta();
1103 - $task->delete();
1165 + if (!empty($pending_tasks)) {
1166 + foreach ($pending_tasks as $task) {
1167 + $task->delete_meta();
1168 + $task->delete();
1169 + }
1104 1170 }
1105 1171
1106 1172 return true;
1107 1173 }
@@ -1120,23 +1186,37 @@
1120 1186 * Adds the required scripts and styles
1121 1187 */
1122 1188 public function admin_enqueue_scripts() {
1123 1189 $current_screen = get_current_screen();
1124 - // load scripts and styles only on WP-Optimize pages or if show_smush_metabox option enabled.
1125 - if (!preg_match('/wp\-optimize|attachment|upload/i', $current_screen->id) && 'show' != $this->options->get_option('show_smush_metabox', 'show')) return;
1190 + if (null === $current_screen) return;
1191 + // load scripts and styles only on WP-Optimize pages
1192 + if (!preg_match('/wp\-optimize|attachment|upload/i', $current_screen->id)) return;
1126 1193
1127 1194 $enqueue_version = WP_Optimize()->get_enqueue_version();
1128 1195 $min_or_not = WP_Optimize()->get_min_or_not_string();
1129 1196 $min_or_not_internal = WP_Optimize()->get_min_or_not_internal_string();
1130 -
1197 +
1131 1198 $js_variables = $this->smush_js_translations();
1132 1199 $js_variables['ajaxurl'] = admin_url('admin-ajax.php');
1133 1200 $js_variables['features'] = $this->get_features();
1134 1201
1135 1202 $js_variables['smush_ajax_nonce'] = wp_create_nonce('updraft-task-manager-ajax-nonce');
1203 + $js_variables['smush_settings'] = $this->get_smush_options();
1204 + $js_variables['blog_id'] = get_current_blog_id();
1205 + $js_variables['compress'] = esc_html__('Compress', 'wp-optimize');
1206 + $js_variables['cancel'] = esc_html__('Cancel', 'wp-optimize');
1207 + $js_variables['cancelling'] = esc_html__('Cancelling...', 'wp-optimize');
1208 + $js_variables['images_restored_successfully'] = esc_html__('The images were restored successfully', 'wp-optimize');
1209 + $js_variables['logo_src'] = esc_url(WPO_PLUGIN_URL.'images/notices/wp_optimize_logo.png');
1136 1210
1137 1211 wp_enqueue_script('block-ui-js', WPO_PLUGIN_URL.'includes/blockui/jquery.blockUI'.$min_or_not.'.js', array('jquery'), $enqueue_version);
1138 - wp_enqueue_script('smush-js', WPO_PLUGIN_URL.'js/wposmush'.$min_or_not_internal.'.js', array('jquery', 'block-ui-js', 'wp-optimize-send-command'), $enqueue_version);
1212 + wp_enqueue_script('wp-optimize-heartbeat-js', WPO_PLUGIN_URL.'js/heartbeat'.$min_or_not_internal.'.js', array('jquery'), $enqueue_version);
1213 + wp_localize_script('wp-optimize-heartbeat-js', 'wpo_heartbeat_ajax', array(
1214 + 'ajaxurl' => admin_url('admin-ajax.php'),
1215 + 'nonce' => wp_create_nonce('heartbeat-nonce'),
1216 + 'interval' => WPO_Ajax::HEARTBEAT_INTERVAL
1217 + ));
1218 + wp_enqueue_script('smush-js', WPO_PLUGIN_URL.'js/wposmush'.$min_or_not_internal.'.js', array('jquery', 'block-ui-js', 'wp-optimize-block-ui', 'wp-optimize-send-command', 'wp-optimize-heartbeat-js'), $enqueue_version);
1139 1219 wp_enqueue_style('smush-css', WPO_PLUGIN_URL.'css/smush'.$min_or_not_internal.'.css', array(), $enqueue_version);
1140 1220 wp_localize_script('smush-js', 'wposmush', $js_variables);
1141 1221 }
1142 1222
@@ -1187,9 +1267,9 @@
1187 1267
1188 1268 /**
1189 1269 * Gets allowed service providers for smush
1190 1270 *
1191 - * @return array - key value pair of service name => task name
1271 + * @return array - A pair of key/value. e.g. service name => task name
1192 1272 */
1193 1273 public function get_allowed_services() {
1194 1274 return array(
1195 1275 'resmushit' => 'Re_Smush_It_Task',
@@ -1196,11 +1276,32 @@
1196 1276 );
1197 1277 }
1198 1278
1199 1279 /**
1280 + * Gets current compression server hint.
1281 + *
1282 + * @return string
1283 + */
1284 + public function get_compression_server_hint() {
1285 +
1286 + switch ($this->webservice) {
1287 + case 'resmushit':
1288 + $title = 'reSmush.it';
1289 + break;
1290 + default:
1291 + $title = $this->webservice;
1292 + }
1293 +
1294 + // translators: %s is a service used to compress images
1295 + $hint = sprintf(__('Service is provided by %s', 'wp-optimize'), $title);
1296 +
1297 + return $hint;
1298 + }
1299 +
1300 + /**
1200 1301 * Gets allowed service provider features smush
1201 1302 *
1202 - * @return array - key value pair of service name => features exposed
1303 + * @return array - A pair of key/value. e.g. service name => features exposed
1203 1304 */
1204 1305 public function get_features() {
1205 1306 $features = array();
1206 1307 foreach ($this->get_allowed_services() as $service => $class_name) {
@@ -1219,27 +1320,19 @@
1219 1320 }
1220 1321
1221 1322 /**
1222 1323 * Delete all smush log files
1324 + *
1325 + * @deprecated 3.5.0
1223 1326 */
1224 1327 public function delete_log_files() {
1225 - if (!function_exists('glob')) return;
1226 - $upload_dir = wp_get_upload_dir();
1227 - $upload_base = $upload_dir['basedir'];
1228 - $files = glob($upload_base . '/smush-*.log');
1229 - if (false === $files) return;
1230 - foreach ($files as $file) {
1231 - if (is_file($file)) {
1232 - @unlink($file); // phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged -- suppress error due to file permission issues
1233 - }
1234 - }
1235 -
1328 + _deprecated_function(__METHOD__, '3.5.0');
1236 1329 }
1237 1330
1238 1331 /**
1239 1332 * Adds a logger to the task
1240 1333 *
1241 - * @param Mixed $task - a task object
1334 + * @param mixed $task - a task object
1242 1335 */
1243 1336 public function set_task_logger($task) {
1244 1337 if (!$this->logger) {
1245 1338 $this->logger = new Updraft_File_Logger($this->get_logfile_path());
@@ -1272,9 +1365,9 @@
1272 1365 $log_header = array();
1273 1366
1274 1367 // phpcs:enable
1275 1368 $log_header[] = "\n";
1276 - $log_header[] = "Header for logs at time: ".date('r')." on ".network_site_url();
1369 + $log_header[] = "Header for logs at time: ".gmdate('r')." on ".network_site_url();
1277 1370 $log_header[] = "WP: ".$wp_version;
1278 1371 $php_uname = '';
1279 1372 if (function_exists('php_uname')) {
1280 1373 $php_uname = ", " . php_uname();
@@ -1281,9 +1374,9 @@
1281 1374 }
1282 1375 $log_header[] = "PHP: ".phpversion()." (".PHP_SAPI.$php_uname.")";
1283 1376 $log_header[] = "MySQL: $mysql_version";
1284 1377 $log_header[] = "WPLANG: ".get_locale();
1285 - $log_header[] = "Server: ".$_SERVER["SERVER_SOFTWARE"];
1378 + $log_header[] = "Server: ". TeamUpdraft\WP_Optimize\Includes\Fragments\fetch_superglobal('server', 'SERVER_SOFTWARE', 'string', 'sanitize_text_field', '-');
1286 1379 $log_header[] = "Outbound connections: ".(defined('WP_HTTP_BLOCK_EXTERNAL') ? 'Y' : 'N');
1287 1380 $log_header[] = "Disabled Functions: $disabled_functions";
1288 1381 $log_header[] = "max_execution_time: $max_execution_time";
1289 1382 $log_header[] = "memory_limit: $memory_limit (used: {$memory_usage}M | {$total_memory_usage}M)";
@@ -1295,12 +1388,12 @@
1295 1388 $this->log($log_entry);
1296 1389 }
1297 1390 }
1298 1391
1299 - $memlim = $this->memory_check_current();
1392 + $memory_limit = $this->memory_check_current();
1300 1393
1301 - if ($memlim<65 && $memlim>0) {
1302 - $this->log(sprintf('The amount of memory (RAM) allowed for PHP is very low (%s Mb) - you should increase it to avoid failures due to insufficient memory (consult your web hosting company for more help)', round($memlim, 1)), 'warning');
1394 + if ($memory_limit<65 && $memory_limit>0) {
1395 + $this->log(sprintf('The amount of memory (RAM) allowed for PHP is very low (%s Mb) - you should increase it to avoid failures due to insufficient memory (consult your web hosting company for more help)', round($memory_limit, 1)), 'warning');
1303 1396 }
1304 1397
1305 1398 if ($max_execution_time>0 && $max_execution_time<20) {
1306 1399 $this->log(sprintf('The amount of time allowed for WordPress plugins to run is very low (%s seconds) - you should increase it to avoid failures due to time-outs (consult your web hosting company for more help - it is the max_execution_time PHP setting; the recommended value is %s seconds or more)', $max_execution_time, 90), 'warning');
@@ -1317,9 +1410,9 @@
1317 1410
1318 1411 /**
1319 1412 * Get the WordPress version
1320 1413 *
1321 - * @return String - the version
1414 + * @return string - the version
1322 1415 */
1323 1416 public function get_wordpress_version() {
1324 1417 static $got_wp_version = false;
1325 1418
@@ -1324,9 +1417,9 @@
1324 1417 static $got_wp_version = false;
1325 1418
1326 1419 if (!$got_wp_version) {
1327 1420 global $wp_version;
1328 - @include(ABSPATH.WPINC.'/version.php');// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged -- suppress warning if `version.php` does not exists
1421 + @include(ABSPATH.WPINC.'/version.php');// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged -- suppress warning if `version.php` does not exist
1329 1422 $got_wp_version = $wp_version;
1330 1423 }
1331 1424
1332 1425 return $got_wp_version;
@@ -1334,16 +1427,18 @@
1334 1427
1335 1428 /**
1336 1429 * Get the current memory limit
1337 1430 *
1338 - * @return String - memory limit in megabytes
1431 + * @param ?string $memory_limit Memory limit in megabytes
1432 + *
1433 + * @return string - memory limit in megabytes
1339 1434 */
1340 - public function memory_check_current($memory_limit = false) {
1435 + public function memory_check_current($memory_limit = null) {
1341 1436 // Returns in megabytes
1342 - if (false == $memory_limit) $memory_limit = ini_get('memory_limit');
1437 + if (empty($memory_limit)) $memory_limit = ini_get('memory_limit');
1343 1438 $memory_limit = rtrim($memory_limit);
1344 1439 $memory_unit = $memory_limit[strlen($memory_limit)-1];
1345 - if (0 == (int) $memory_unit && '0' !== $memory_unit) {
1440 + if (0 === (int) $memory_unit && '0' !== $memory_unit) {
1346 1441 $memory_limit = substr($memory_limit, 0, strlen($memory_limit)-1);
1347 1442 } else {
1348 1443 $memory_unit = '';
1349 1444 }
@@ -1375,9 +1470,9 @@
1375 1470 public function save_to_cache($key, $value, $blog_id = 1) {
1376 1471 $transient_limit = 3600 * 48;
1377 1472 $key = 'wpo_smush_cache_' . $blog_id . '_'. $key;
1378 1473
1379 - return WP_Optimize_Transients_Cache::get_instance()->set($key, $value, $transient_limit);
1474 + WP_Optimize_Transients_Cache::get_instance()->set_transient($key, $value, $transient_limit);
1380 1475 }
1381 1476
1382 1477 /**
1383 1478 * Gets value from the cache.
@@ -1388,11 +1483,9 @@
1388 1483 */
1389 1484 public function get_from_cache($key, $blog_id = 1) {
1390 1485 $key = 'wpo_smush_cache_' . $blog_id . '_'. $key;
1391 1486
1392 - $value = WP_Optimize_Transients_Cache::get_instance()->get($key);
1393 -
1394 - return $value;
1487 + return WP_Optimize_Transients_Cache::get_instance()->get($key);
1395 1488 }
1396 1489
1397 1490 /**
1398 1491 * Deletes a value from the cache.
@@ -1428,11 +1521,11 @@
1428 1521 global $wpdb;
1429 1522
1430 1523 // get list of cached data by optimization.
1431 1524 if ($this->is_multisite_mode()) {
1432 - $keys = $wpdb->get_col("SELECT meta_key FROM {$wpdb->sitemeta} WHERE meta_key LIKE '%wpo_smush_cache_%'");
1525 + $keys = $wpdb->get_col("SELECT meta_key FROM `{$wpdb->sitemeta}` WHERE meta_key LIKE '%wpo_smush_cache_%'");
1433 1526 } else {
1434 - $keys = $wpdb->get_col("SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE '%wpo_smush_cache_%'");
1527 + $keys = $wpdb->get_col("SELECT option_name FROM `{$wpdb->options}` WHERE option_name LIKE '%wpo_smush_cache_%'");
1435 1528 }
1436 1529
1437 1530 if (!empty($keys)) {
1438 1531 $transient_keys = array();
@@ -1472,19 +1565,19 @@
1472 1565 $year = (int) $match[1];
1473 1566 $month = (int) $match[2];
1474 1567
1475 1568 $limit = strtotime('-'.$days_ago.' '.(($days_ago > 1) ? 'days' : 'day'));
1476 - $year_limit = (int) date('Y', $limit);
1477 - $month_limit = (int) date('m', $limit);
1478 - $day_limit = (int) date('j', $limit);
1569 + $year_limit = (int) gmdate('Y', $limit);
1570 + $month_limit = (int) gmdate('m', $limit);
1571 + $day_limit = (int) gmdate('j', $limit);
1479 1572
1480 1573 // if current directory is newer than needed then we skip it.
1481 - if ($year_limit < $year || ($year_limit == $year && $month_limit < $month)) {
1574 + if ($year_limit < $year || ($year_limit === $year && $month_limit < $month)) {
1482 1575 return;
1483 1576 }
1484 1577
1485 1578 // we will check dates only in directory that contain limit date.
1486 - $check_date = ($year_limit == $year && $month_limit == $month);
1579 + $check_date = ($year_limit === $year && $month_limit === $month);
1487 1580 }
1488 1581
1489 1582 // GLOB_BRACE isn't defined on some systems (Solaris, SunOS and more) > https://www.php.net/manual/en/function.glob.php
1490 1583 $files = glob($directory . '*-updraft-pre-smush-original.*', (defined('GLOB_BRACE') ? GLOB_BRACE : 0));
@@ -1490,13 +1583,13 @@
1490 1583 $files = glob($directory . '*-updraft-pre-smush-original.*', (defined('GLOB_BRACE') ? GLOB_BRACE : 0));
1491 1584
1492 1585 foreach ($files as $file) {
1493 1586 if ($check_date) {
1494 - $filedate_day = (int) date('j', filectime($file));
1587 + $filedate_day = (int) gmdate('j', filectime($file));
1495 1588 if ($filedate_day >= $day_limit) continue;
1496 1589 }
1497 1590
1498 - unlink($file);
1591 + wp_delete_file($file);
1499 1592 }
1500 1593
1501 1594 } else {
1502 1595 // scan directories recursively.
@@ -1507,9 +1600,9 @@
1507 1600 $file = readdir($handle);
1508 1601
1509 1602 while (false !== $file) {
1510 1603
1511 - if ('.' == $file || '..' == $file) {
1604 + if ('.' === $file || '..' === $file) {
1512 1605 $file = readdir($handle);
1513 1606 continue;
1514 1607 }
1515 1608
@@ -1517,9 +1610,9 @@
1517 1610 $this->clear_backup_images_directory($directory . $file, $days_ago);
1518 1611 } elseif (is_file($directory . $file) && preg_match('/^.+-updraft-pre-smush-original\.\S{3,4}/i', $file)) {
1519 1612 // check the file time and compare with $days_ago.
1520 1613 $filedate_day = (int) filectime($directory . $file);
1521 - if ($filedate_day > 0 && ($current_time - $filedate_day) / 86400 >= $days_ago) unlink($directory . $file);
1614 + if ($filedate_day > 0 && ($current_time - $filedate_day) / 86400 >= $days_ago) wp_delete_file($directory . $file);
1522 1615 }
1523 1616
1524 1617 $file = readdir($handle);
1525 1618 }
@@ -1530,9 +1623,9 @@
1530 1623 /**
1531 1624 * Clean backup smush images according to saved options.
1532 1625 */
1533 1626 public function clear_backup_images() {
1534 - $back_up_delete_after = $this->options->get_option('back_up_delete_after', false);
1627 + $back_up_delete_after = $this->options->get_option('back_up_delete_after');
1535 1628
1536 1629 if (!$back_up_delete_after) return;
1537 1630
1538 1631 $back_up_delete_after_days = $this->options->get_option('back_up_delete_after_days', 50);
@@ -1550,48 +1643,12 @@
1550 1643 *
1551 1644 * @return bool
1552 1645 */
1553 1646 public function is_compressed($attachment_id) {
1554 - return (true == get_post_meta($attachment_id, 'smush-complete', true));
1647 + return (true === (bool) get_post_meta($attachment_id, '_wpo-smush-complete', true));
1555 1648 }
1556 1649
1557 1650 /**
1558 - * @param array $form_fields
1559 - * @param WP_Post $post
1560 - *
1561 - * @return array
1562 - */
1563 - public function add_compress_button_to_media_modal($form_fields, $post) {
1564 -
1565 - if (!is_admin() || !function_exists('get_current_screen')) return $form_fields;
1566 -
1567 - /**
1568 - * In media modal get_current_screen() return null or id = 'async-upload' We don't need add smush fields elsewhere.
1569 - */
1570 - $current_screen = get_current_screen();
1571 - if (null !== $current_screen && 'async-upload' != $current_screen->id) return $form_fields;
1572 -
1573 - /**
1574 - * Don't show additional fields for non-image attachments.
1575 - */
1576 - if (!wp_attachment_is_image($post->ID)) return $form_fields;
1577 -
1578 - ob_start();
1579 - $this->render_smush_metabox($post);
1580 - $smush_metabox = ob_get_contents();
1581 - ob_end_clean();
1582 -
1583 - $form_fields['wpo_compress_image'] = array(
1584 - 'value' => '',
1585 - 'label' => __('Compress image', 'wp-optimize'),
1586 - 'input' => 'html',
1587 - 'html' => $smush_metabox,
1588 - );
1589 -
1590 - return $form_fields;
1591 - }
1592 -
1593 - /**
1594 1651 * Returns true if multisite
1595 1652 *
1596 1653 * @return bool
1597 1654 */
@@ -1604,13 +1661,20 @@
1604 1661 *
1605 1662 * @param int $post_id - WordPress Post ID
1606 1663 */
1607 1664 public function unscheduled_original_file_deletion($post_id) {
1608 - $the_original_file = get_post_meta($post_id, 'original-file', true);
1665 + $the_original_file = get_post_meta($post_id, '_wpo-original-file', true);
1666 + // If no original file meta exists, there is nothing to delete.
1667 + if (empty($the_original_file)) {
1668 + return;
1669 + }
1609 1670 $uploads_dir = wp_get_upload_dir();
1610 - $the_original_file = trailingslashit($uploads_dir['basedir']) . $the_original_file;
1611 - if ('' != $the_original_file && file_exists($the_original_file)) {
1612 - @unlink($the_original_file);// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged -- suppress warning because of file permission issues
1671 + $uploads_basedir = realpath($uploads_dir['basedir']);
1672 + if (!$uploads_basedir) return;
1673 + $uploads_basedir = trailingslashit($uploads_basedir);
1674 + $the_original_file = realpath($uploads_basedir . $the_original_file);
1675 + if ($the_original_file && 0 === strpos($the_original_file, $uploads_basedir) && file_exists($the_original_file)) {
1676 + wp_delete_file($the_original_file);
1613 1677 }
1614 1678 }
1615 1679
1616 1680 /**
@@ -1637,12 +1701,73 @@
1637 1701 }
1638 1702
1639 1703 return self::$_instance;
1640 1704 }
1705 +
1706 + /**
1707 + * Meta query array for getting uncompressed images
1708 + *
1709 + * @return array
1710 + */
1711 + public function get_uncompressed_images_meta_query() {
1712 + return array(
1713 + 'relation' => 'AND',
1714 + array(
1715 + 'relation' => 'OR',
1716 + array(
1717 + 'key' => '_wpo-smush-complete',
1718 + 'compare' => '!=',
1719 + 'value' => '1',
1720 + ),
1721 + array(
1722 + 'key' => '_wpo-smush-complete',
1723 + 'compare' => 'NOT EXISTS',
1724 + 'value' => '',
1725 + ),
1726 + ),
1727 + // ShortPixel Image Optimizer plugin
1728 + array(
1729 + 'relation' => 'OR',
1730 + array(
1731 + 'key' => '_shortpixel_status',
1732 + 'compare' => '<',
1733 + 'value' => '2',
1734 + ),
1735 + array(
1736 + 'key' => '_shortpixel_status',
1737 + 'compare' => '>=',
1738 + 'value' => '3',
1739 + ),
1740 + array(
1741 + 'key' => '_shortpixel_status',
1742 + 'compare' => 'NOT EXISTS',
1743 + 'value' => '',
1744 + ),
1745 + ),
1746 + // Smush plugin
1747 + array(
1748 + 'key' => 'wp-smpro-smush-data',
1749 + 'compare' => 'NOT EXISTS',
1750 + 'value' => '',
1751 + ),
1752 + // Imagify
1753 + array(
1754 + 'key' => '_imagify_optimization_level',
1755 + 'compare' => 'NOT EXISTS',
1756 + 'value' => '',
1757 + ),
1758 + // Compress JPEG & PNG images by TinyPNG
1759 + array(
1760 + 'key' => 'tiny_compress_images',
1761 + 'compare' => 'NOT EXISTS',
1762 + 'value' => '',
1763 + ),
1764 + );
1765 + }
1641 1766 }
1642 1767
1643 1768 /**
1644 - * Returns a Updraft_Smush_Manager instance
1769 + * Returns Updraft_Smush_Manager instance
1645 1770 */
1646 1771 function Updraft_Smush_Manager() {
1647 1772 return Updraft_Smush_Manager::instance();
1648 1773 }