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 +563 -366 3.2.5 → 4.7.0 View file →
@@ -4,13 +4,13 @@
4 4 */
5 5
6 6 if (!defined('ABSPATH')) die('Access denied.');
7 7
8 -if (!class_exists('Updraft_Task_Manager_1_3')) require_once(WPO_PLUGIN_MAIN_PATH . 'vendor/team-updraft/common-libs/src/updraft-tasks/class-updraft-task-manager.php');
8 +if (!class_exists('Updraft_Task_Manager_1_4')) require_once(WPO_PLUGIN_MAIN_PATH . 'vendor/team-updraft/common-libs/src/updraft-tasks/class-updraft-task-manager.php');
9 9
10 10 if (!class_exists('Updraft_Smush_Manager')) :
11 11
12 -class Updraft_Smush_Manager extends Updraft_Task_Manager_1_3 {
12 +class Updraft_Smush_Manager extends Updraft_Task_Manager_1_4 {
13 13
14 14 static protected $_instance = null;
15 15
16 16 /**
@@ -50,9 +50,10 @@
50 50
51 51 $this->commands = new Updraft_Smush_Manager_Commands($this);
52 52 $this->options = WP_Optimize()->get_options();
53 53
54 - if (!isset($this->options)) {
54 + // we set default options when compression server is false - it means that options was not saved before
55 + if (!$this->options->get_option('compression_server')) {
55 56 $this->set_default_options();
56 57 }
57 58
58 59 $this->webservice = $this->options->get_option('compression_server', 'resmushit');
@@ -72,12 +73,11 @@
72 73 add_action('ud_task_started', array($this, 'set_task_logger'));
73 74 add_action('ud_task_completed', array($this, 'record_stats'));
74 75 add_action('ud_task_failed', array($this, 'record_stats'));
75 76 add_action('prune_smush_logs', array($this, 'prune_smush_logs'));
76 - add_action('autosmush_process_queue', array($this, 'autosmush_process_queue'));
77 - if ('show' == $this->options->get_option('show_smush_metabox', 'show')) {
77 + add_action('process_smush_tasks', array($this, 'process_smush_tasks'));
78 + if ('show' === $this->options->get_option('show_smush_metabox', 'show')) {
78 79 add_action('add_meta_boxes_attachment', array($this, 'add_smush_metabox'), 10, 2);
79 - add_filter('attachment_fields_to_edit', array($this, 'add_compress_button_to_media_modal' ), 10, 2);
80 80 }
81 81 add_action('delete_attachment', array($this, 'unscheduled_original_file_deletion'));
82 82
83 83 add_filter('manage_media_columns', array($this, 'manage_media_columns'));
@@ -88,11 +88,25 @@
88 88
89 89 // add filter for already compressed images by EWWW Image Optimizer.
90 90 add_filter('wpo_get_uncompressed_images_args', array($this, 'ewww_image_optimizer_compressed_images_args'));
91 91
92 - if (!wp_next_scheduled('wpo_smush_clear_backup_images')) {
93 - wp_schedule_event(time(), 'daily', 'wpo_smush_clear_backup_images');
92 + // schedule or unschedule clear backup images cron, if needed
93 + $scheduled = wp_next_scheduled('wpo_smush_clear_backup_images');
94 + if ($this->options->get_option('back_up_delete_after', true)) {
95 + if (!$scheduled) {
96 + wp_schedule_event(time(), 'daily', 'wpo_smush_clear_backup_images');
97 + }
98 + } else {
99 + if ($scheduled) {
100 + wp_unschedule_event($scheduled, 'wpo_smush_clear_backup_images');
101 + }
94 102 }
103 +
104 + // Schedule CRON job for deleting failed smush tasks
105 + add_action('wpo_smush_clear_failed_tasks', array($this, 'clear_failed_tasks'));
106 + if (!wp_next_scheduled('wpo_smush_clear_failed_tasks')) {
107 + wp_schedule_event(time(), 'wpo_monthly', 'wpo_smush_clear_failed_tasks');
108 + }
95 109 }
96 110
97 111 /**
98 112 * Add custom column to Media Library.
@@ -97,9 +111,9 @@
97 111 /**
98 112 * Add custom column to Media Library.
99 113 *
100 114 * @param array $columns
101 - * @return mixed
115 + * @return array
102 116 */
103 117 public function manage_media_columns($columns) {
104 118 $columns['wpo_smush'] = 'WP-Optimize';
105 119
@@ -113,34 +127,88 @@
113 127 * @param int $attachment_id
114 128 */
115 129 public function manage_media_custom_column($column, $attachment_id) {
116 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>';
117 145
118 - if (!$this->is_compressed($attachment_id)) return;
146 + return $info;
147 + }
119 148
120 - $smush_stats = get_post_meta($attachment_id, 'smush-stats', true);
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) {
157 + $file = get_attached_file($attachment_id);
158 + if (false === $file) {
159 + return '';
160 + }
161 + $ext = WPO_Image_Utils::get_extension($file);
162 + $allowed_extensions = WPO_Image_Utils::get_allowed_extensions();
121 163
122 - if (empty($smush_stats)) {
123 - _e('The file was either compressed using another tool or marked as compressed', 'wp-optimize');
124 - return;
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;
166 +
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']));
125 188 }
126 189
127 - $original_size = $smush_stats['original-size'];
128 - $smushed_size = $smush_stats['smushed-size'];
190 + $extract['compressed_by_another_plugin'] = $this->is_image_compressed_by_another_plugin($attachment_id);
129 191
130 - if (0 == $original_size) {
131 - $info = sprintf(__('The file was compressed to %s using WP-Optimize', 'wp-optimize'), WP_Optimize()->format_size($smushed_size));
192 + $output = '';
193 +
194 + if (WPO_Image_Utils::is_supported_extension($ext, $allowed_extensions)) {
195 + $output .= WP_Optimize()->include_template('admin-medialibrary-smush-column.php', true, $extract);
132 196 } else {
133 - $saved = round((($original_size - $smushed_size) / $original_size * 100), 2);
134 - $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 +
135 200 }
136 201
137 - 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 + }
138 209
139 - // Display additional information about resized images.
140 - if (!empty($smush_stats['sizes-info'])) {
141 - WP_Optimize()->include_template('images/smush-details.php', false, array('sizes_info' => $smush_stats['sizes-info']));
142 - }
210 + return $output;
143 211 }
144 212
145 213 /**
146 214 * The Task Manager AJAX handler
@@ -146,21 +214,25 @@
146 214 * The Task Manager AJAX handler
147 215 */
148 216 public function updraft_smush_ajax() {
149 217
150 - $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');
151 221
152 - if (!wp_verify_nonce($nonce, 'updraft-task-manager-ajax-nonce') || empty($_REQUEST['subaction']))
222 + if (empty($nonce) || empty($subaction)) {
153 223 die('Security check failed');
224 + }
154 225
155 - $subaction = $_REQUEST['subaction'];
226 + if (!WP_Optimize()->current_user_can()) {
227 + die('You are not allowed to run this command.');
228 + }
156 229
157 230 $allowed_commands = Updraft_Smush_Manager_Commands::get_allowed_ajax_commands();
158 231
159 232 if (in_array($subaction, $allowed_commands)) {
160 233
161 - if (isset($_REQUEST['data'])) {
162 - $data = $_REQUEST['data'];
234 + if ($data) {
163 235 $results = call_user_func(array($this->commands, $subaction), $data);
164 236 } else {
165 237 $results = call_user_func(array($this->commands, $subaction));
166 238 }
@@ -174,13 +246,13 @@
174 246 'error_data' => $results->get_error_data(),
175 247 );
176 248 }
177 249
178 - echo json_encode($results);
250 + echo wp_json_encode($results);
179 251 } else {
180 - echo json_encode(array('error' => 'No such command found'));
252 + echo wp_json_encode(array('error' => 'No such command found'));
181 253 }
182 - die;
254 + die();
183 255 }
184 256
185 257 /**
186 258 * Creates a task to auto compress an image on upload
@@ -189,66 +261,78 @@
189 261 */
190 262 public function autosmush_create_task($post_id) {
191 263
192 264 $post = get_post($post_id);
265 + $file = get_attached_file($post_id);
266 + $ext = WPO_Image_Utils::get_extension($file);
267 + $allowed_extensions = WPO_Image_Utils::get_allowed_extensions();
193 268
194 - if (!$this->options->get_option('autosmush', false))
269 + if(!in_array($ext, $allowed_extensions)) return;
270 +
271 + if (!$this->options->get_option('autosmush'))
195 272 return;
196 273
197 - if (!'image' == substr($post->post_mime_type, 0, 5))
274 + if ('image' !== substr($post->post_mime_type, 0, 5))
198 275 return;
199 276
200 277 if ($this->task_exists($post_id))
201 278 return;
202 -
203 - $options = array(
204 - 'attachment_id' => $post_id,
205 - 'blog_id' => get_current_blog_id(),
206 - 'image_quality' => $this->options->get_option('image_quality', 96),
207 - 'keep_original' => $this->options->get_option('back_up_original', true),
208 - 'preserve_exif' => $this->options->get_option('preserve_exif', true),
209 - 'lossy_compression' => $this->options->get_option('lossy_compression', false)
210 - );
211 279
212 - if (filesize(get_attached_file($post_id)) > 5242880) {
213 - $options['request_timeout'] = 180;
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 +
283 + if (filesize($file) > 5242880) {
284 + $task_options['request_timeout'] = 180;
214 285 }
215 286
216 287 $server = $this->options->get_option('compression_server', $this->webservice);
217 288 $task_name = $this->get_associated_task($server);
218 289
219 - $description = "$task_name with attachment ID : ".$post_id.", autocreated on : ".date("F d, Y h:i:s", time());
220 - $task = call_user_func(array($task_name, 'create_task'), 'smush', $description, $options, $task_name);
221 -
222 - if ($task) $task->add_logger($this->logger);
290 + $blog_info = is_multisite() ? ', blog ID : '.get_current_blog_id() : '';
291 + $description = "$task_name with attachment ID : ".$post_id . $blog_info .", auto created on : ".gmdate("F d, Y h:i:s", time());
292 +
293 + $task = call_user_func(array($task_name, 'create_task'), 'smush', $description, $task_options, $task_name);
294 +
295 + if ($task) $this->set_task_logger($task);
223 296 $this->log($description);
224 297
225 - if (!wp_next_scheduled('autosmush_process_queue')) {
226 - wp_schedule_single_event(time() + 300, 'autosmush_process_queue');
298 + if (!wp_next_scheduled('process_smush_tasks')) {
299 + wp_schedule_single_event(time() + 300, 'process_smush_tasks');
227 300 }
228 301 }
229 302
230 303 /**
231 - * Process the autosmush queue and sets up a cron job if needed
232 - * for future processing
304 + * Processes the smush tasks in the queue, then cleans up the completed tasks.
305 + *
306 + * Before processing the queue, it first schedules a cron job to re-initiate the process after a certain
307 + * interval, ensuring that the process will be completed later in case the current processing fails
308 + * or is interrupted. This method can be invoked directly or scheduled as a cron job.
233 309 */
234 - public function autosmush_process_queue() {
235 -
236 - if (!wp_next_scheduled('autosmush_process_queue') && !$this->is_queue_processed()) {
237 - wp_schedule_single_event(time() + 600, 'autosmush_process_queue');
310 + public function process_smush_tasks() {
311 + /*
312 + * Only add log header when called as a cron job, assuming the log header is already added by the caller
313 + * when called directly. This is to avoid duplicate log headers in the log file.
314 + */
315 + if (defined('DOING_CRON') && DOING_CRON) {
316 + $this->write_log_header();
238 317 }
239 318
240 - $this->write_log_header();
241 - $this->clear_cached_data();
242 - $this->process_queue('smush');
243 -
319 + // If there are no pending tasks, nothing to process. In that case, attempt to clean up old tasks and return
244 320 if ($this->is_queue_processed()) {
245 321 $this->clean_up_old_tasks('smush');
322 + return;
246 323 }
247 324
325 + if (!wp_next_scheduled('process_smush_tasks')) {
326 + wp_schedule_single_event(time() + 600, 'process_smush_tasks');
327 + }
328 +
329 + // Process the queue
330 + $this->clear_cached_data();
331 + $this->process_queue('smush');
332 + $this->clean_up_old_tasks('smush');
248 333 }
249 334
250 -
251 335 /**
252 336 * Process the compression of a single image
253 337 *
254 338 * @param int $image - ID of image
@@ -254,16 +338,17 @@
254 338 * @param int $image - ID of image
255 339 * @param array $options - options to use
256 340 * @param string $server - the server to process with
257 341 *
258 - * @return boolean - Status of the task
342 + * @return bool | WP_Error - Status of the task
259 343 */
260 344 public function compress_single_image($image, $options, $server) {
261 345 $task_name = $this->get_associated_task($server);
262 - $description = "$task_name - attachment ID : ". $image. ", started on : ". date("F d, Y h:i:s", time());
346 + $blog_info = is_multisite() ? ', blog ID : '.get_current_blog_id() : '';
347 + $description = "$task_name - attachment ID : ". $image . $blog_info. ", started on : ". gmdate("F d, Y h:i:s", time());
263 348
264 349 $task = call_user_func(array($task_name, 'create_task'), 'smush', $description, $options, $task_name);
265 - $task->add_logger($this->logger);
350 + if ($task) $this->set_task_logger($task);
266 351 $this->clear_cached_data();
267 352
268 353 if (!wp_next_scheduled('prune_smush_logs')) {
269 354 wp_schedule_single_event(time() + 7200, 'prune_smush_logs');
@@ -282,9 +367,9 @@
282 367 */
283 368 public function restore_single_image($image_id, $blog_id) {
284 369
285 370 $switched_blog = false;
286 - if (is_multisite() && current_user_can('manage_network_options')) {
371 + if (is_multisite() && WP_Optimize()->current_user_can('manage_network_options')) {
287 372 switch_to_blog($blog_id);
288 373 $switched_blog = true;
289 374 } elseif (is_multisite() && get_current_blog_id() != $blog_id) {
290 375 return new WP_Error('restore_backup_wrong_blog_id', __('The blog ID provided does not match the current blog.', 'wp-optimize'));
@@ -292,15 +377,23 @@
292 377
293 378 $error = false;
294 379
295 380 $image_path = get_attached_file($image_id);
296 - $backup_path = get_post_meta($image_id, 'original-file', true);
297 -
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 +
298 394 // If the file doesn't exist, check if it's relative
299 395 if (!is_file($backup_path)) {
300 - $uploads_dir = wp_upload_dir();
301 - $uploads_basedir = trailingslashit($uploads_dir['basedir']);
302 -
303 396 if (is_file($uploads_basedir . $backup_path)) {
304 397 $backup_path = $uploads_basedir . $backup_path;
305 398 }
306 399 }
@@ -329,17 +422,27 @@
329 422 $backup_path = $uploads_basedir . $backup_path;
330 423 }
331 424 }
332 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 +
333 435 if (!is_file($backup_path)) {
334 436 // Delete information about backup.
335 - delete_post_meta($image_id, 'original-file');
437 + delete_post_meta($image_id, '_wpo-original-file');
336 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'));
337 - } elseif (!is_writable($image_path)) {
338 - $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'));
339 441 } elseif (!copy($backup_path, $image_path)) {
340 - $error = new WP_Error('restore_failed', __('The file could not be copied; check your PHP error logs for details', 'wp-optimize'));
341 - } 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
342 445 $error = new WP_Error('restore_failed', sprintf(__('The backup file %s could not be deleted.', 'wp-optimize'), $backup_path));
343 446 }
344 447
345 448 if (!$error) {
@@ -344,12 +447,12 @@
344 447
345 448 if (!$error) {
346 449 // if backup image deleted successfully
347 450 // then delete from attachment meta associated smush data
348 - delete_post_meta($image_id, 'smush-complete');
349 - delete_post_meta($image_id, 'smush-stats');
350 - delete_post_meta($image_id, 'original-file');
351 - 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');
352 455 }
353 456
354 457 if ($switched_blog) {
355 458 restore_current_blog();
@@ -371,9 +474,9 @@
371 474 *
372 475 * @param bool $restore_backup if true then restore images from backup otherwise just delete meta.
373 476 * @param int $blog_id blog id.
374 477 * @param int $images_limit how many images process per time.
375 - * @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.
376 479 *
377 480 * @return array ['completed' => (bool), 'message' => (string), 'error' => (string)]
378 481 */
379 482 public function bulk_restore_compressed_images($restore_backup, $blog_id = 1, $images_limit = 100, $delete_only_backups_meta = false) {
@@ -385,8 +488,9 @@
385 488
386 489 $result = array(
387 490 'completed' => false,
388 491 'message' => '',
492 + 'smushed_images_count' => 0,
389 493 );
390 494
391 495 $processed = 0;
392 496
@@ -391,9 +495,9 @@
391 495 $processed = 0;
392 496
393 497 if ($restore_backup) {
394 498 // get post ids those have backup meta field.
395 - $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);
396 500
397 501 if (!empty($image_ids)) {
398 502 // run restore function for each found image.
399 503 foreach ($image_ids as $image) {
@@ -398,9 +502,9 @@
398 502 // run restore function for each found image.
399 503 foreach ($image_ids as $image) {
400 504 $restore_result = $this->restore_single_image($image['post_id'], $blog_id);
401 505
402 - // 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".
403 507 if (is_wp_error($restore_result) && 'restore_backup_not_found' != $restore_result->get_error_code()) {
404 508 // we need to stop the work as we haven't restored the backup.
405 509 $result['error'] = $restore_result->get_error_message();
406 510 $this->options->delete_option('smush_images_restored');
@@ -413,9 +517,9 @@
413 517
414 518 $images_count = count($image_ids);
415 519
416 520 // if all images processed then set flag completed to true.
417 - if ($processed == $images_count && $images_count < $images_limit) {
521 + if ($processed === $images_count && $images_count < $images_limit) {
418 522 $this->options->delete_option('smush_images_restored');
419 523 $result['completed'] = true;
420 524 } else {
421 525 // save into options total processed count.
@@ -422,10 +526,12 @@
422 526 $processed += $this->options->get_option('smush_images_restored', 0);
423 527 $this->options->update_option('smush_images_restored', $processed);
424 528
425 529 if (is_multisite()) {
426 - $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));
427 532 } else {
533 + // translators: %s is the number of restored images.
428 534 $result['message'] = sprintf(__('%s compressed images were restored from their backup', 'wp-optimize'), $processed);
429 535 }
430 536 }
431 537
@@ -434,16 +540,35 @@
434 540 $result['completed'] = true;
435 541 }
436 542
437 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 +
438 548 if ($delete_only_backups_meta) {
439 549 if (is_multisite()) {
440 - $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 + }
441 559 } else {
442 - $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 + }
443 567 }
444 568 } else {
445 569 if (is_multisite()) {
570 + // translators: %s is the site url
446 571 $result['message'] = sprintf(__('All the compressed images for the site %s were successfully marked as uncompressed.', 'wp-optimize'), get_site_url($blog_id));
447 572 } else {
448 573 $result['message'] = __('All the compressed images were successfully marked as uncompressed.', 'wp-optimize');
449 574 }
@@ -450,11 +575,11 @@
450 575 }
451 576
452 577 // clear all metas for smushed images after work completed.
453 578 // if $delete_only_backup_meta set to true then all meta fields was deleted in restore_single_image()
454 - // and we don't need delete metas for other images.
579 + // and we don't need to delete metas for other images.
455 580 if (!$delete_only_backups_meta) {
456 - $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');");
457 582 }
458 583 }
459 584
460 585 if (is_multisite()) {
@@ -470,9 +595,9 @@
470 595 * @param array $images - the array of images to process
471 596 * @return bool - true if processing complete
472 597 */
473 598 public function process_bulk_smush($images = array()) {
474 -
599 +
475 600 // Get a list of pending tasks so we can exclude those
476 601 $pending_tasks = $this->get_pending_tasks();
477 602 $queued_images = array();
478 603
@@ -485,37 +610,25 @@
485 610 'blog_id' => $task->get_option('blog_id')
486 611 );
487 612 }
488 613 }
489 -
614 + $default_task_options = $this->get_smush_options();
490 615 foreach ($images as $image) {
491 616 // Skip if already in the queue
492 617 if (in_array($image, $queued_images)) continue;
493 618
494 - $options = array(
495 - 'attachment_id' => intval($image['attachment_id']),
496 - 'blog_id' => intval($image['blog_id']),
497 - 'image_quality' => $this->options->get_option('image_quality', 85),
498 - 'keep_original' => $this->options->get_option('back_up_original', true),
499 - 'preserve_exif' => $this->options->get_option('preserve_exif', true),
500 - 'lossy_compression' => $this->options->get_option('lossy_compression', false)
501 - );
502 -
619 + $task_options = array_merge($default_task_options, array('attachment_id' => intval($image['attachment_id']), 'blog_id' => intval($image['blog_id'])));
503 620 $server = $this->options->get_option('compression_server', $this->webservice);
504 621 $task_name = $this->get_associated_task($server);
505 622
506 - $description = "$task_name - Attachment ID : ". intval($image['attachment_id']) . ", Started on : ". date("F d, Y h:i:s", time());
507 - $task = call_user_func(array($task_name, 'create_task'), 'smush', $description, $options, $task_name);
508 - $task->add_logger($this->logger);
623 + $blog_info = is_multisite() ? ', Blog ID : '.intval($image['blog_id']) : '';
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);
626 + if ($task) $this->set_task_logger($task);
509 627 }
510 628
511 - $this->clear_cached_data();
512 - $this->process_queue('smush');
629 + $this->process_smush_tasks();
513 630
514 - if ($this->is_queue_processed()) {
515 - $this->clean_up_old_tasks('smush');
516 - }
517 -
518 631 if (!wp_next_scheduled('prune_smush_logs')) {
519 632 wp_schedule_single_event(time() + 7200, 'prune_smush_logs');
520 633 }
521 634
@@ -543,9 +656,9 @@
543 656 return $online;
544 657 }
545 658
546 659 /**
547 - * Checks if the queue for smushing is compleete
660 + * Checks if the queue for smushing is complete
548 661 *
549 662 * @return bool - true if processed, false otherwise
550 663 */
551 664 public function is_queue_processed() {
@@ -563,19 +676,19 @@
563 676 */
564 677 public function record_stats($task) {
565 678
566 679 $attachment_id = $task->get_option('attachment_id');
567 - $completed_task_count = $this->options->get_option('completed_task_count', false);
680 + $completed_task_count = $this->options->get_option('completed_task_count');
568 681 $failed_task_count = $this->options->get_option('failed_task_count', 0);
569 - $total_bytes_saved = $this->options->get_option('total_bytes_saved', false);
682 + $total_bytes_saved = $this->options->get_option('total_bytes_saved');
570 683 $total_percent_saved = $this->options->get_option('total_percent_saved', 0);
571 684
572 - if ('ud_task_failed' == current_action()) {
685 + if ('ud_task_failed' === current_action()) {
573 686 $this->options->update_option('failed_task_count', ++$failed_task_count);
574 687 return;
575 688 }
576 689
577 - if (false === $completed_task_count) {
690 + if (empty($completed_task_count)) {
578 691 $completed_task_count = $total_bytes_saved = 0;
579 692 }
580 693
581 694 if (!$total_bytes_saved) {
@@ -583,12 +696,12 @@
583 696 }
584 697
585 698 if (is_multisite()) {
586 699 switch_to_blog($task->get_option('blog_id', 1));
587 - $stats = get_post_meta($attachment_id, 'smush-stats', true);
700 + $stats = get_post_meta($attachment_id, '_wpo-smush-stats', true);
588 701 restore_current_blog();
589 702 } else {
590 - $stats = get_post_meta($attachment_id, 'smush-stats', true);
703 + $stats = get_post_meta($attachment_id, '_wpo-smush-stats', true);
591 704 }
592 705
593 706 if (isset($stats['sizes-info'])) {
594 707
@@ -601,11 +714,11 @@
601 714 }
602 715
603 716 $percent = round((($original_size - $compressed_size) / $original_size * 100), 2);
604 717 } else {
605 - $original_size = isset($stats['original-size']) ? $stats['original-size'] : 0;
606 - $compressed_size = isset($stats['smushed-size']) ? $stats['smushed-size'] : 0;
607 - $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;
608 721 }
609 722
610 723 $saved = $original_size - $compressed_size;
611 724 $completed_task_count++;
@@ -618,29 +731,8 @@
618 731 $this->options->update_option('total_percent_saved', $total_percent_saved);
619 732 }
620 733
621 734 /**
622 - * Cleans out all complete + failed tasks from the DB.
623 - *
624 - * @param String $type type of the task
625 - * @return bool - true if processing complete
626 - */
627 - public function clean_up_old_tasks($type) {
628 - $completed_tasks = $this->get_tasks('all', $type);
629 -
630 - if (!$completed_tasks) return false;
631 -
632 - $this->log(sprintf('Cleaning up tasks of type (%s). A total of %d tasks will be deleted.', $type, count($completed_tasks)));
633 -
634 - foreach ($completed_tasks as $task) {
635 - $task->delete_meta();
636 - $task->delete();
637 - }
638 -
639 - return true;
640 - }
641 -
642 - /**
643 735 * Get current smush options.
644 736 *
645 737 * @return array
646 738 */
@@ -648,17 +740,18 @@
648 740 static $smush_options = array();
649 741 if (empty($smush_options)) {
650 742 $smush_options = array(
651 743 'compression_server' => $this->options->get_option('compression_server', $this->get_default_webservice()),
652 - 'image_quality' => $this->options->get_option('image_quality', 'very_good'),
653 - 'lossy_compression' => $this->options->get_option('lossy_compression', false),
744 + 'image_quality' => $this->options->get_option('image_quality', 92),
745 + 'lossy_compression' => $this->options->get_option('lossy_compression'),
746 + 'keep_original' => $this->options->get_option('back_up_original', true),//repeated below
654 747 'back_up_original' => $this->options->get_option('back_up_original', true),
655 748 'back_up_delete_after' => $this->options->get_option('back_up_delete_after', true),
656 749 'back_up_delete_after_days' => $this->options->get_option('back_up_delete_after_days', 50),
657 750 'preserve_exif' => $this->options->get_option('preserve_exif', false),
658 - 'autosmush' => $this->options->get_option('autosmush', false),
659 - 'show_smush_metabox' => $this->options->get_option('show_smush_metabox', 'show') == 'show' ? true : false,
660 - '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')
661 754 );
662 755 }
663 756 return $smush_options;
664 757 }
@@ -663,20 +756,29 @@
663 756 return $smush_options;
664 757 }
665 758
666 759 /**
667 - * Updates global smush options
760 + * Update smush options
761 + * Only options whose values differ from the stored values are updated.
668 762 *
669 - * @param array $options - sent in via AJAX
670 - * @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.
671 766 */
672 767 public function update_smush_options($options) {
673 -
768 + $success = true;
674 769 foreach ($options as $option => $value) {
675 - $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 + }
676 779 }
677 -
678 - return true;
780 + return $success;
679 781 }
680 782
681 783 /**
682 784 * Clears smush related stats
@@ -697,26 +799,40 @@
697 799 *
698 800 * @return array - translations used in JS
699 801 */
700 802 public function smush_js_translations() {
803 + $resmushit_article_link = WP_Optimize()->wp_optimize_url('https://resmush.it/api/', __('resmushIt', 'wp-optimize'), '', '', true);
804 +
701 805 return apply_filters('updraft_smush_js_translations', array(
702 806 'all_images_compressed' => __('No uncompressed images were found.', 'wp-optimize'),
703 - 'error_unexpected_response' => __('An unexpected response was received from the server. More information has been logged in the browser console.', 'wp-optimize'),
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'),
704 808 'compress_single_image_dialog' => __('Please wait: compressing the selected image.', 'wp-optimize'),
705 809 'error_try_again_later' => __('Please try again later.', 'wp-optimize'),
706 810 'server_check' => __('Connecting to the Smush API server, please wait', 'wp-optimize'),
707 811 'please_wait' => __('Please wait while the request is being processed', 'wp-optimize'),
708 - 'server_error' => __('There was an error connecting to the image compression server. This could mean either the server is temporarily unavailable or there are connectivity issues with your internet connection. 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'),
709 818 'please_select_images' => __('Please select the images you want compressed from the "Uncompressed images" panel first', 'wp-optimize'),
710 819 'please_updating_images_info' => __('Please wait: updating information about the selected image.', 'wp-optimize'),
711 820 'please_select_compressed_images' => __('Please select the images you want to mark as already compressed from the "Uncompressed images" panel first', 'wp-optimize'),
712 821 'view_image' => __('View Image', 'wp-optimize'),
713 - 'delete_image_backup_confirm' => __('Do you really want to delete all backup images now? This action is irreversible.', 'wp-optimize'),
714 - 'mark_all_images_uncompressed' => __('Do you really want to mark all the images as uncompressed? This action is irreversible.', 'wp-optimize'),
822 + 'delete_image_backup_confirm' => __('Do you really want to delete all backup images now?', 'wp-optimize') . ' ' . __('This action is irreversible.', 'wp-optimize'),
823 + 'mark_all_images_uncompressed' => __('Do you really want to mark all the images as uncompressed?', 'wp-optimize') . ' ' . __('This action is irreversible.', 'wp-optimize'),
715 824 'restore_images_from_backup' => __('Do you want to restore the original images from the backup (where they exist?)', 'wp-optimize'),
716 825 'restore_all_compressed_images' => __('Do you really want to restore all the compressed images?', 'wp-optimize'),
826 + 'webp_conversion_tool_error' => __('No WebP conversion tools are available on your web-server.', 'wp-optimize'),
827 + 'webp_conversion_tool_how_to' => __('How to get the WebP conversion tools to work?', 'wp-optimize'),
717 828 'more' => __('More', 'wp-optimize'),
718 829 'less' => __('Less', 'wp-optimize'),
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'),
719 835 ));
720 836 }
721 837
722 838 /**
@@ -741,32 +857,36 @@
741 857 * @param WP_Post $post - a post object
742 858 */
743 859 public function render_smush_metabox($post) {
744 860
745 - $compressed = get_post_meta($post->ID, 'smush-complete', true) ? true : false;
746 - $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);
747 863
748 - $smush_info = get_post_meta($post->ID, 'smush-info', true);
749 - $smush_stats = get_post_meta($post->ID, 'smush-stats', true);
750 - $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');
751 867
752 868 $options = Updraft_Smush_Manager()->get_smush_options();
753 -
869 +
754 870 $file = get_attached_file($post->ID);
871 + $ext = WPO_Image_Utils::get_extension($file);
872 + $allowed_extensions = WPO_Image_Utils::get_allowed_extensions();
755 873 $file_size = ($file && is_file($file)) ? filesize($file) : 0;
756 874
757 875 $extract = array(
758 876 'post_id' => $post->ID,
759 - 'smush_display' => $compressed ? "style='display:none;'" : "style='display:block;'",
760 - 'restore_display' => $compressed ? "style='display:block;'" : "style='display:none;'",
761 - 'restore_action' => $has_backup ? "style='display:block;'" : "style='display:none;'",
762 - 'smush_mark' => !$compressed && !$marked ? "style='display:block;'" : "style='display:none;'",
763 - 'smush_unmark' => $marked ? "style='display:block;'" : "style='display:none;'",
764 - '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 ?: ' ',
765 883 'file_size' => $file_size,
766 884 'smush_options' => $options,
767 - 'custom' => 100 == $options['image_quality'] || 90 == $options['image_quality'] ? false : true,
885 + 'custom' => 90 >= $options['image_quality'] && 65 <= $options['image_quality'],
768 886 'smush_details' => '',
887 + 'restore_tooltip' => $this->get_restore_image_tooltip_text(),
888 + 'smush_marked' => $marked,
769 889 );
770 890
771 891 if (!empty($smush_stats['sizes-info'])) {
772 892 $extract['smush_details'] = WP_Optimize()->include_template('images/smush-details.php', true, array('sizes_info' => $smush_stats['sizes-info']));
@@ -771,11 +891,28 @@
771 891 if (!empty($smush_stats['sizes-info'])) {
772 892 $extract['smush_details'] = WP_Optimize()->include_template('images/smush-details.php', true, array('sizes_info' => $smush_stats['sizes-info']));
773 893 }
774 894
895 + $extract['smush_settings_form'] = WP_Optimize()->include_template('admin-metabox-smush-settings.php', true, $extract);
775 896 $extract['compressed_by_another_plugin'] = $this->is_image_compressed_by_another_plugin($post->ID);
897 + if (WPO_Image_Utils::is_supported_extension($ext, $allowed_extensions)) {
898 + WP_Optimize()->include_template('admin-metabox-smush.php', false, $extract);
899 + } else {
900 + printf("<p>%s</p>", esc_html__('Compressing this file type extension is not supported', 'wp-optimize'));
901 + }
902 + }
776 903
777 - WP_Optimize()->include_template('admin-metabox-smush.php', false, $extract);
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;
778 915 }
779 916
780 917 /**
781 918 * Check if a single image compressed by another plugin.
@@ -784,10 +921,11 @@
784 921 * @return bool
785 922 */
786 923 private function is_image_compressed_by_another_plugin($image_id) {
787 924 global $wpdb;
925 + static $is_ewwwio_images_table_exists = null;
788 926
789 - $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);
790 928
791 929 if (is_array($meta)) {
792 930 foreach ($meta as $row) {
793 931 // Smush, Imagify, Compress JPEG & PNG images by TinyPNG.
@@ -792,16 +930,18 @@
792 930 foreach ($meta as $row) {
793 931 // Smush, Imagify, Compress JPEG & PNG images by TinyPNG.
794 932 if (in_array($row['meta_key'], array('wp-smpro-smush-data', '_imagify_optimization_level', 'tiny_compress_images'))) return true;
795 933 // ShortPixel Image Optimizer
796 - 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;
797 935 }
798 936 }
799 937
800 - 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) {
801 941 $old_show_errors = $wpdb->show_errors(false);
802 942 // EWWW Image Optimizer.
803 - $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));
804 944 if (!empty($ewww_image)) return true;
805 945 $wpdb->show_errors($old_show_errors);
806 946 }
807 947
@@ -820,15 +960,15 @@
820 960
821 961 if (!WP_Optimize()->get_db_info()->table_exists('ewwwio_images')) return $args;
822 962
823 963 $old_show_errors = $wpdb->show_errors(false);
824 - $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'");
825 965 $wpdb->show_errors($old_show_errors);
826 966
827 967 if (isset($args['post__not_in'])) {
828 - $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
829 969 } else {
830 - $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
831 971 }
832 972
833 973 return $args;
834 974 }
@@ -835,78 +975,32 @@
835 975
836 976 /**
837 977 * Returns a list of images for smush (from cache if available)
838 978 *
979 + * @param string $use_cache
839 980 * @return array - uncompressed images
840 981 */
841 - public function get_uncompressed_images() {
842 -
843 - $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 + }
844 987
845 - if ($uncompressed_images) return $uncompressed_images;
846 -
847 988 $uncompressed_images = array();
989 + $accepted_mimes = array('image/jpeg', 'image/gif', 'image/png');
848 990
849 991 $args = array(
850 992 'post_type' => 'attachment',
851 - 'post_mime_type' => 'image',
993 + 'post_mime_type' => $accepted_mimes,
852 994 'post_status' => 'inherit',
853 995 'posts_per_page' => apply_filters('updraft_smush_posts_per_page', 1000),
854 - 'meta_query' => array(
855 - 'relation' => 'AND',
856 - array(
857 - 'relation' => 'OR',
858 - array(
859 - 'key' => 'smush-complete',
860 - 'compare' => '!=',
861 - 'value' => '1',
862 - ),
863 - array(
864 - 'key' => 'smush-complete',
865 - 'compare' => 'NOT EXISTS',
866 - 'value' => '',
867 - ),
868 - ),
869 - // ShortPixel Image Optimizer plugin
870 - array(
871 - 'relation' => 'OR',
872 - array(
873 - 'key' => '_shortpixel_status',
874 - 'compare' => '<',
875 - 'value' => '2',
876 - ),
877 - array(
878 - 'key' => '_shortpixel_status',
879 - 'compare' => '>=',
880 - 'value' => '3',
881 - ),
882 - array(
883 - 'key' => '_shortpixel_status',
884 - 'compare' => 'NOT EXISTS',
885 - 'value' => '',
886 - ),
887 - ),
888 - // Smush plugin
889 - array(
890 - 'key' => 'wp-smpro-smush-data',
891 - 'compare' => 'NOT EXISTS',
892 - 'value' => '',
893 - ),
894 - // Imagify
895 - array(
896 - 'key' => '_imagify_optimization_level',
897 - 'compare' => 'NOT EXISTS',
898 - 'value' => '',
899 - ),
900 - // Compress JPEG & PNG images by TinyPNG
901 - array(
902 - 'key' => 'tiny_compress_images',
903 - 'compare' => 'NOT EXISTS',
904 - 'value' => '',
905 - ),
906 - )
996 + 'meta_query' => $this->get_uncompressed_images_meta_query(),
997 + 'no_found_rows' => true,
998 + 'fields' => 'ids'
907 999 );
908 1000
1001 + $allowed_extensions = WPO_Image_Utils::get_allowed_extensions();
1002 +
909 1003 if (is_multisite()) {
910 1004
911 1005 $sites = WP_Optimize()->get_sites();
912 1006
@@ -917,16 +1011,25 @@
917 1011 $args = apply_filters('wpo_get_uncompressed_images_args', $args);
918 1012 $images = new WP_Query($args);
919 1013
920 1014 foreach ($images->posts as $image) {
921 - if (file_exists(get_attached_file($image->ID))) {
922 - $uncompressed_images[$site->blog_id][] = array(
923 - 'id' => $image->ID,
924 - 'thumb_url' => wp_get_attachment_thumb_url($image->ID),
925 - 'filesize' => filesize(get_attached_file($image->ID))
926 - );
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);
1019 + $ext = WPO_Image_Utils::get_extension($file);
1020 + if (file_exists($file)) {
1021 + if (WPO_Image_Utils::is_supported_extension($ext, $allowed_extensions)) {
1022 + $uncompressed_images[$site->blog_id][] = array(
1023 + 'id' => $image_id,
1024 + 'thumb_url' => wp_get_attachment_thumb_url($image_id),
1025 + 'filesize' => filesize(get_attached_file($image_id))
1026 + );
1027 + } else {
1028 + $this->log("Blog_id=$site->blog_id, ID=$image_id, File=$file This image type is not supported.");
1029 + }
927 1030 } else {
928 - $this->log("Could not find file for image: blog_id={$site->blog_id}, ID={$image->ID}, file=".get_attached_file($image->ID));
1031 + $this->log("Could not find file for image: blog_id=$site->blog_id, ID=$image_id, file=$file");
929 1032 }
930 1033 }
931 1034
932 1035 restore_current_blog();
@@ -935,16 +1038,26 @@
935 1038 } else {
936 1039 $args = apply_filters('wpo_get_uncompressed_images_args', $args);
937 1040 $images = new WP_Query($args);
938 1041 foreach ($images->posts as $image) {
939 - if (file_exists(get_attached_file($image->ID))) {
940 - $uncompressed_images[1][] = array(
941 - 'id' => $image->ID,
942 - 'thumb_url' => wp_get_attachment_thumb_url($image->ID),
943 - 'filesize' => filesize(get_attached_file($image->ID))
944 - );
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);
1046 + $ext = WPO_Image_Utils::get_extension($file);
1047 +
1048 + if (file_exists($file)) {
1049 + if (WPO_Image_Utils::is_supported_extension($ext, $allowed_extensions)) {
1050 + $uncompressed_images[1][] = array(
1051 + 'id' => $image_id,
1052 + 'thumb_url' => wp_get_attachment_thumb_url($image_id),
1053 + 'filesize' => filesize(get_attached_file($image_id))
1054 + );
1055 + } else {
1056 + $this->log("Image ID=$image_id, File=$file This image type is not supported.");
1057 + }
945 1058 } else {
946 - $this->log("Could not find file for image: ID={$image->ID}, file=".get_attached_file($image->ID));
1059 + $this->log("Could not find file for image: ID=$image_id, file=$file");
947 1060 }
948 1061 }
949 1062 }
950 1063
@@ -991,17 +1104,22 @@
991 1104 * @return bool - true if yes, false otherwise
992 1105 */
993 1106 public function task_exists($image) {
994 1107
1108 + $blog_id = get_current_blog_id();
995 1109 $pending_tasks = $this->get_active_tasks('smush');
996 - $queued_images = array();
997 1110
998 1111 if (!empty($pending_tasks)) {
999 1112 foreach ($pending_tasks as $task) {
1000 - $queued_images[] = $task->get_option('attachment_id');
1113 + $task_attachment_id = $task->get_option('attachment_id');
1114 + $task_blog_id = $task->get_option('blog_id');
1115 +
1116 + if ($image === $task_attachment_id && $blog_id === $task_blog_id) {
1117 + return true;
1118 + }
1001 1119 }
1002 1120 }
1003 - return in_array($image, $queued_images);
1121 + return false;
1004 1122 }
1005 1123
1006 1124 /**
1007 1125 * Returns the status of images compressed in this iteration of the bulk compress
@@ -1014,13 +1132,13 @@
1014 1132 $stats = array();
1015 1133
1016 1134 foreach ($images as $image) {
1017 1135 if (is_multisite()) {
1018 - switch_to_blog($image['blog_id'], 1);
1019 - $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';
1020 1138 restore_current_blog();
1021 1139 } else {
1022 - $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';
1023 1141 }
1024 1142 }
1025 1143
1026 1144 return array_count_values($stats);
@@ -1028,9 +1146,9 @@
1028 1146
1029 1147 /**
1030 1148 * Returns a list of images for smush (from cache if available)
1031 1149 *
1032 - * @return array - List of task objects with uncompressed images
1150 + * @return array|mixed - List of task objects with uncompressed images
1033 1151 */
1034 1152 public function get_pending_tasks() {
1035 1153 return $this->get_active_tasks('smush');
1036 1154 }
@@ -1036,16 +1154,20 @@
1036 1154 }
1037 1155
1038 1156 /**
1039 1157 * Deletes and removes any pending tasks from queue
1158 + *
1159 + * @return bool
1040 1160 */
1041 1161 public function clear_pending_images() {
1042 1162
1043 1163 $pending_tasks = $this->get_active_tasks('smush');
1044 1164
1045 - foreach ($pending_tasks as $task) {
1046 - $task->delete_meta();
1047 - $task->delete();
1165 + if (!empty($pending_tasks)) {
1166 + foreach ($pending_tasks as $task) {
1167 + $task->delete_meta();
1168 + $task->delete();
1169 + }
1048 1170 }
1049 1171
1050 1172 return true;
1051 1173 }
@@ -1064,23 +1186,37 @@
1064 1186 * Adds the required scripts and styles
1065 1187 */
1066 1188 public function admin_enqueue_scripts() {
1067 1189 $current_screen = get_current_screen();
1068 - // load scripts and styles only on WP-Optimize pages or if show_smush_metabox option enabled.
1069 - if (!preg_match('/wp\-optimize/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;
1070 1193
1071 - $enqueue_version = (defined('WP_DEBUG') && WP_DEBUG) ? WPO_VERSION.'.'.time() : WPO_VERSION;
1072 - $min_or_not = (defined('SCRIPT_DEBUG') && SCRIPT_DEBUG) ? '' : '.min';
1073 - $min_or_not_internal = (defined('SCRIPT_DEBUG') && SCRIPT_DEBUG) ? '' : '-'. str_replace('.', '-', WPO_VERSION). '.min';
1074 -
1194 + $enqueue_version = WP_Optimize()->get_enqueue_version();
1195 + $min_or_not = WP_Optimize()->get_min_or_not_string();
1196 + $min_or_not_internal = WP_Optimize()->get_min_or_not_internal_string();
1197 +
1075 1198 $js_variables = $this->smush_js_translations();
1076 1199 $js_variables['ajaxurl'] = admin_url('admin-ajax.php');
1077 1200 $js_variables['features'] = $this->get_features();
1078 1201
1079 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');
1080 1210
1081 - wp_enqueue_script('block-ui-js', WPO_PLUGIN_URL.'js/jquery.blockUI'.$min_or_not.'.js', array('jquery'), $enqueue_version);
1082 - wp_enqueue_script('smush-js', WPO_PLUGIN_URL.'js/wposmush'.$min_or_not_internal.'.js', array('jquery', 'block-ui-js'), $enqueue_version);
1211 + wp_enqueue_script('block-ui-js', WPO_PLUGIN_URL.'includes/blockui/jquery.blockUI'.$min_or_not.'.js', array('jquery'), $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);
1083 1219 wp_enqueue_style('smush-css', WPO_PLUGIN_URL.'css/smush'.$min_or_not_internal.'.css', array(), $enqueue_version);
1084 1220 wp_localize_script('smush-js', 'wposmush', $js_variables);
1085 1221 }
1086 1222
@@ -1099,9 +1235,9 @@
1099 1235 public function set_default_options() {
1100 1236
1101 1237 $options = array(
1102 1238 'compression_server' => $this->get_default_webservice(),
1103 - 'image_quality' => 'very_good',
1239 + 'image_quality' => 92,
1104 1240 'lossy_compression' => false,
1105 1241 'back_up_original' => true,
1106 1242 'preserve_exif' => false,
1107 1243 'autosmush' => false,
@@ -1131,9 +1267,9 @@
1131 1267
1132 1268 /**
1133 1269 * Gets allowed service providers for smush
1134 1270 *
1135 - * @return array - key value pair of service name => task name
1271 + * @return array - A pair of key/value. e.g. service name => task name
1136 1272 */
1137 1273 public function get_allowed_services() {
1138 1274 return array(
1139 1275 'resmushit' => 'Re_Smush_It_Task',
@@ -1140,11 +1276,32 @@
1140 1276 );
1141 1277 }
1142 1278
1143 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 + /**
1144 1301 * Gets allowed service provider features smush
1145 1302 *
1146 - * @return array - key value pair of service name => features exposed
1303 + * @return array - A pair of key/value. e.g. service name => features exposed
1147 1304 */
1148 1305 public function get_features() {
1149 1306 $features = array();
1150 1307 foreach ($this->get_allowed_services() as $service => $class_name) {
@@ -1158,17 +1315,24 @@
1158 1315 *
1159 1316 * @return string - file path
1160 1317 */
1161 1318 public function get_logfile_path() {
1162 - $upload_dir = wp_upload_dir();
1163 - $upload_base = $upload_dir['basedir'];
1164 - return $upload_base . '/smush-' . substr(md5(wp_salt()), 0, 20) . '.log';
1319 + return WP_Optimize_Utils::get_log_file_path('smush');
1165 1320 }
1166 1321
1167 1322 /**
1323 + * Delete all smush log files
1324 + *
1325 + * @deprecated 3.5.0
1326 + */
1327 + public function delete_log_files() {
1328 + _deprecated_function(__METHOD__, '3.5.0');
1329 + }
1330 +
1331 + /**
1168 1332 * Adds a logger to the task
1169 1333 *
1170 - * @param Mixed $task - a task object
1334 + * @param mixed $task - a task object
1171 1335 */
1172 1336 public function set_task_logger($task) {
1173 1337 if (!$this->logger) {
1174 1338 $this->logger = new Updraft_File_Logger($this->get_logfile_path());
@@ -1182,15 +1346,14 @@
1182 1346 /**
1183 1347 * Writes a standardised header to the log file
1184 1348 */
1185 1349 public function write_log_header() {
1186 -
1187 1350 global $wpdb;
1188 1351
1189 1352 // phpcs:disable
1190 1353 $wp_version = $this->get_wordpress_version();
1191 1354 $mysql_version = $wpdb->db_version();
1192 - $safe_mode = $this->detect_safe_mode();
1355 + $disabled_functions = ini_get('disable_functions');
1193 1356 $max_execution_time = (int) @ini_get("max_execution_time");
1194 1357
1195 1358 $memory_limit = ini_get('memory_limit');
1196 1359 $memory_usage = round(@memory_get_usage(false)/1048576, 1);
@@ -1202,30 +1365,35 @@
1202 1365 $log_header = array();
1203 1366
1204 1367 // phpcs:enable
1205 1368 $log_header[] = "\n";
1206 - $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();
1207 1370 $log_header[] = "WP: ".$wp_version;
1208 - $log_header[] = "PHP: ".phpversion()." (".PHP_SAPI.", ".@php_uname().")";// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
1371 + $php_uname = '';
1372 + if (function_exists('php_uname')) {
1373 + $php_uname = ", " . php_uname();
1374 + }
1375 + $log_header[] = "PHP: ".phpversion()." (".PHP_SAPI.$php_uname.")";
1209 1376 $log_header[] = "MySQL: $mysql_version";
1210 1377 $log_header[] = "WPLANG: ".get_locale();
1211 - $log_header[] = "Server: ".$_SERVER["SERVER_SOFTWARE"];
1378 + $log_header[] = "Server: ". TeamUpdraft\WP_Optimize\Includes\Fragments\fetch_superglobal('server', 'SERVER_SOFTWARE', 'string', 'sanitize_text_field', '-');
1212 1379 $log_header[] = "Outbound connections: ".(defined('WP_HTTP_BLOCK_EXTERNAL') ? 'Y' : 'N');
1213 - $log_header[] = "safe_mode: $safe_mode";
1380 + $log_header[] = "Disabled Functions: $disabled_functions";
1214 1381 $log_header[] = "max_execution_time: $max_execution_time";
1215 - $log_header[] = "memory_limit: $memory_limit (used: ${memory_usage}M | ${total_memory_usage}M)";
1382 + $log_header[] = "memory_limit: $memory_limit (used: {$memory_usage}M | {$total_memory_usage}M)";
1216 1383 $log_header[] = "multisite: ".(is_multisite() ? 'Y' : 'N');
1217 1384 $log_header[] = "openssl: ".(defined('OPENSSL_VERSION_TEXT') ? OPENSSL_VERSION_TEXT : 'N');
1218 1385
1219 -
1220 - foreach ($log_header as $log_entry) {
1221 - $this->log($log_entry);
1386 + if (apply_filters("wpo_write_server_info_in_smush_log", false)) {
1387 + foreach ($log_header as $log_entry) {
1388 + $this->log($log_entry);
1389 + }
1222 1390 }
1223 1391
1224 - $memlim = $this->memory_check_current();
1392 + $memory_limit = $this->memory_check_current();
1225 1393
1226 - if ($memlim<65 && $memlim>0) {
1227 - $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');
1228 1396 }
1229 1397
1230 1398 if ($max_execution_time>0 && $max_execution_time<20) {
1231 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');
@@ -1242,9 +1410,9 @@
1242 1410
1243 1411 /**
1244 1412 * Get the WordPress version
1245 1413 *
1246 - * @return String - the version
1414 + * @return string - the version
1247 1415 */
1248 1416 public function get_wordpress_version() {
1249 1417 static $got_wp_version = false;
1250 1418
@@ -1249,9 +1417,9 @@
1249 1417 static $got_wp_version = false;
1250 1418
1251 1419 if (!$got_wp_version) {
1252 1420 global $wp_version;
1253 - @include(ABSPATH.WPINC.'/version.php');// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
1421 + @include(ABSPATH.WPINC.'/version.php');// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged -- suppress warning if `version.php` does not exist
1254 1422 $got_wp_version = $wp_version;
1255 1423 }
1256 1424
1257 1425 return $got_wp_version;
@@ -1259,16 +1427,18 @@
1259 1427
1260 1428 /**
1261 1429 * Get the current memory limit
1262 1430 *
1263 - * @return String - memory limit in megabytes
1431 + * @param ?string $memory_limit Memory limit in megabytes
1432 + *
1433 + * @return string - memory limit in megabytes
1264 1434 */
1265 - public function memory_check_current($memory_limit = false) {
1435 + public function memory_check_current($memory_limit = null) {
1266 1436 // Returns in megabytes
1267 - if (false == $memory_limit) $memory_limit = ini_get('memory_limit');
1437 + if (empty($memory_limit)) $memory_limit = ini_get('memory_limit');
1268 1438 $memory_limit = rtrim($memory_limit);
1269 1439 $memory_unit = $memory_limit[strlen($memory_limit)-1];
1270 - if (0 == (int) $memory_unit && '0' !== $memory_unit) {
1440 + if (0 === (int) $memory_unit && '0' !== $memory_unit) {
1271 1441 $memory_limit = substr($memory_limit, 0, strlen($memory_limit)-1);
1272 1442 } else {
1273 1443 $memory_unit = '';
1274 1444 }
@@ -1290,17 +1460,8 @@
1290 1460 return $memory_limit;
1291 1461 }
1292 1462
1293 1463 /**
1294 - * Detect if safe_mode is on
1295 - *
1296 - * @return Integer - 1 or 0
1297 - */
1298 - public function detect_safe_mode() {
1299 - return (@ini_get('safe_mode') && strtolower(@ini_get('safe_mode')) != "off") ? 1 : 0;// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
1300 - }
1301 -
1302 - /**
1303 1464 * Saves a value to the cache.
1304 1465 *
1305 1466 * @param string $key
1306 1467 * @param mixed $value
@@ -1309,9 +1470,9 @@
1309 1470 public function save_to_cache($key, $value, $blog_id = 1) {
1310 1471 $transient_limit = 3600 * 48;
1311 1472 $key = 'wpo_smush_cache_' . $blog_id . '_'. $key;
1312 1473
1313 - 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);
1314 1475 }
1315 1476
1316 1477 /**
1317 1478 * Gets value from the cache.
@@ -1322,11 +1483,9 @@
1322 1483 */
1323 1484 public function get_from_cache($key, $blog_id = 1) {
1324 1485 $key = 'wpo_smush_cache_' . $blog_id . '_'. $key;
1325 1486
1326 - $value = WP_Optimize_Transients_Cache::get_instance()->get($key);
1327 -
1328 - return $value;
1487 + return WP_Optimize_Transients_Cache::get_instance()->get($key);
1329 1488 }
1330 1489
1331 1490 /**
1332 1491 * Deletes a value from the cache.
@@ -1362,11 +1521,11 @@
1362 1521 global $wpdb;
1363 1522
1364 1523 // get list of cached data by optimization.
1365 1524 if ($this->is_multisite_mode()) {
1366 - $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_%'");
1367 1526 } else {
1368 - $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_%'");
1369 1528 }
1370 1529
1371 1530 if (!empty($keys)) {
1372 1531 $transient_keys = array();
@@ -1406,19 +1565,19 @@
1406 1565 $year = (int) $match[1];
1407 1566 $month = (int) $match[2];
1408 1567
1409 1568 $limit = strtotime('-'.$days_ago.' '.(($days_ago > 1) ? 'days' : 'day'));
1410 - $year_limit = (int) date('Y', $limit);
1411 - $month_limit = (int) date('m', $limit);
1412 - $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);
1413 1572
1414 1573 // if current directory is newer than needed then we skip it.
1415 - if ($year_limit < $year || ($year_limit == $year && $month_limit < $month)) {
1574 + if ($year_limit < $year || ($year_limit === $year && $month_limit < $month)) {
1416 1575 return;
1417 1576 }
1418 1577
1419 1578 // we will check dates only in directory that contain limit date.
1420 - $check_date = ($year_limit == $year && $month_limit == $month);
1579 + $check_date = ($year_limit === $year && $month_limit === $month);
1421 1580 }
1422 1581
1423 1582 // GLOB_BRACE isn't defined on some systems (Solaris, SunOS and more) > https://www.php.net/manual/en/function.glob.php
1424 1583 $files = glob($directory . '*-updraft-pre-smush-original.*', (defined('GLOB_BRACE') ? GLOB_BRACE : 0));
@@ -1424,13 +1583,13 @@
1424 1583 $files = glob($directory . '*-updraft-pre-smush-original.*', (defined('GLOB_BRACE') ? GLOB_BRACE : 0));
1425 1584
1426 1585 foreach ($files as $file) {
1427 1586 if ($check_date) {
1428 - $filedate_day = (int) date('j', filectime($file));
1587 + $filedate_day = (int) gmdate('j', filectime($file));
1429 1588 if ($filedate_day >= $day_limit) continue;
1430 1589 }
1431 1590
1432 - unlink($file);
1591 + wp_delete_file($file);
1433 1592 }
1434 1593
1435 1594 } else {
1436 1595 // scan directories recursively.
@@ -1441,9 +1600,9 @@
1441 1600 $file = readdir($handle);
1442 1601
1443 1602 while (false !== $file) {
1444 1603
1445 - if ('.' == $file || '..' == $file) {
1604 + if ('.' === $file || '..' === $file) {
1446 1605 $file = readdir($handle);
1447 1606 continue;
1448 1607 }
1449 1608
@@ -1451,9 +1610,9 @@
1451 1610 $this->clear_backup_images_directory($directory . $file, $days_ago);
1452 1611 } elseif (is_file($directory . $file) && preg_match('/^.+-updraft-pre-smush-original\.\S{3,4}/i', $file)) {
1453 1612 // check the file time and compare with $days_ago.
1454 1613 $filedate_day = (int) filectime($directory . $file);
1455 - 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);
1456 1615 }
1457 1616
1458 1617 $file = readdir($handle);
1459 1618 }
@@ -1464,9 +1623,9 @@
1464 1623 /**
1465 1624 * Clean backup smush images according to saved options.
1466 1625 */
1467 1626 public function clear_backup_images() {
1468 - $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');
1469 1628
1470 1629 if (!$back_up_delete_after) return;
1471 1630
1472 1631 $back_up_delete_after_days = $this->options->get_option('back_up_delete_after_days', 50);
@@ -1484,48 +1643,12 @@
1484 1643 *
1485 1644 * @return bool
1486 1645 */
1487 1646 public function is_compressed($attachment_id) {
1488 - return (true == get_post_meta($attachment_id, 'smush-complete', true));
1647 + return (true === (bool) get_post_meta($attachment_id, '_wpo-smush-complete', true));
1489 1648 }
1490 1649
1491 1650 /**
1492 - * @param array $form_fields
1493 - * @param WP_Post $post
1494 - *
1495 - * @return array
1496 - */
1497 - public function add_compress_button_to_media_modal($form_fields, $post) {
1498 -
1499 - if (!is_admin() || !function_exists('get_current_screen')) return $form_fields;
1500 -
1501 - /**
1502 - * In media modal get_current_screen() return null or id = 'async-upload' We don't need add smush fields elsewhere.
1503 - */
1504 - $current_screen = get_current_screen();
1505 - if (null !== $current_screen && 'async-upload' != $current_screen->id) return $form_fields;
1506 -
1507 - /**
1508 - * Don't show additional fields for non-image attachments.
1509 - */
1510 - if (!wp_attachment_is_image($post->ID)) return $form_fields;
1511 -
1512 - ob_start();
1513 - $this->render_smush_metabox($post);
1514 - $smush_metabox = ob_get_contents();
1515 - ob_end_clean();
1516 -
1517 - $form_fields['wpo_compress_image'] = array(
1518 - 'value' => '',
1519 - 'label' => __('Compress image', 'wp-optimize'),
1520 - 'input' => 'html',
1521 - 'html' => $smush_metabox,
1522 - );
1523 -
1524 - return $form_fields;
1525 - }
1526 -
1527 - /**
1528 1651 * Returns true if multisite
1529 1652 *
1530 1653 * @return bool
1531 1654 */
@@ -1538,21 +1661,34 @@
1538 1661 *
1539 1662 * @param int $post_id - WordPress Post ID
1540 1663 */
1541 1664 public function unscheduled_original_file_deletion($post_id) {
1542 - $the_original_file = get_post_meta($post_id, 'original-file', true);
1543 - if ('' != $the_original_file && file_exists($the_original_file)) {
1544 - @unlink($the_original_file);// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
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;
1545 1669 }
1670 + $uploads_dir = wp_get_upload_dir();
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);
1677 + }
1546 1678 }
1547 1679
1548 1680 /**
1549 - * Resets webp serving method by setting rewrite capability status to false
1550 - *
1551 - * @return bool
1681 + * Remove failed smush tasks from the wp_tm_tasks table
1552 1682 */
1553 - public function reset_webp_serving_method() {
1554 - return $this->options->update_option('rewrite_status', false);
1683 + public function clear_failed_tasks() {
1684 + $failed_tasks = $this->get_tasks('failed', 'smush');
1685 + if (empty($failed_tasks)) return;
1686 +
1687 + foreach ($failed_tasks as $task) {
1688 + $task->delete_meta();
1689 + $task->delete();
1690 + }
1555 1691 }
1556 1692
1557 1693 /**
1558 1694 * Instance of WP_Optimize_Page_Cache_Preloader.
@@ -1565,12 +1701,73 @@
1565 1701 }
1566 1702
1567 1703 return self::$_instance;
1568 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 + }
1569 1766 }
1570 1767
1571 1768 /**
1572 - * Returns a Updraft_Smush_Manager instance
1769 + * Returns Updraft_Smush_Manager instance
1573 1770 */
1574 1771 function Updraft_Smush_Manager() {
1575 1772 return Updraft_Smush_Manager::instance();
1576 1773 }