PluginProbe
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance / 3.2.20
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance v3.2.20
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
wp-optimize / includes / class-wp-optimizer.php

class-wp-optimizer.php in WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance 3.2.20, at includes/class-wp-optimizer.php

608 lines 20.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if (!defined('WPO_VERSION')) die('No direct access allowed');
4
5 /**
6 * This class invokes optimiazations. The optimizations themselves live in the 'optimizations' sub-directory of the plugin. The proper way to obtain access to the instance is via WP_Optimize()->get_optimizer()
7 */
8 class WP_Optimizer {
9
10 /**
11 * Returns singleton instance object
12 *
13 * @return WP_Optimizer Returns `WP_Optimizer` object
14 */
15 public static function instance() {
16 static $_instance = null;
17 if (null === $_instance) {
18 $_instance = new self();
19 }
20 return $_instance;
21 }
22
23 public function get_retain_info() {
24
25 $options = WP_Optimize()->get_options();
26
27 $retain_enabled = $options->get_option('retention-enabled', 'false');
28 $retain_period = (($retain_enabled) ? $options->get_option('retention-period', '2') : null);
29
30 return array($retain_enabled, $retain_period);
31 }
32
33 /**
34 * Get data retention options
35 *
36 * @return array
37 */
38 public function get_revisions_retain_info() {
39 $options = WP_Optimize()->get_options();
40
41 $revisions_retention_enabled = $options->get_option('revisions-retention-enabled', 'false');
42 $revisions_retention_count = $revisions_retention_enabled ? $options->get_option('revisions-retention-count', '2') : null;
43
44 return array($revisions_retention_enabled, $revisions_retention_count);
45 }
46
47 public function get_optimizations_list() {
48
49 $optimizations = array();
50
51 $optimizations_dir = WPO_PLUGIN_MAIN_PATH.'optimizations';
52
53 if ($dh = opendir($optimizations_dir)) {
54 while (($file = readdir($dh)) !== false) {
55 if ('.' == $file || '..' == $file || '.php' != substr($file, -4, 4) || !is_file($optimizations_dir.'/'.$file) || 'inactive-' == substr($file, 0, 9)) continue;
56 $optimizations[] = substr($file, 0, (strlen($file) - 4));
57 }
58 closedir($dh);
59 }
60
61 return apply_filters('wp_optimize_get_optimizations_list', $optimizations);
62
63 }
64
65 /**
66 * Currently, there is only one sort rule (so, the parameter's value is ignored)
67 *
68 * @param array $optimizations An array of optimizations (i.e. WP_Optimization instances).
69 * @param string $sort_on Specify sort.
70 *
71 * @return array
72 */
73 public function sort_optimizations($optimizations, $sort_on = 'ui_sort_order') {
74 if ('run_sort_order' == $sort_on) {
75 uasort($optimizations, array($this, 'sort_optimizations_run_traditional'));
76 } else {
77 uasort($optimizations, array($this, 'sort_optimizations_ui_traditional'));
78 }
79 return $optimizations;
80 }
81
82 public function sort_optimizations_ui_traditional($a, $b) {
83 return $this->sort_optimizations_traditional($a, $b, 'ui_sort_order');
84 }
85
86 public function sort_optimizations_run_traditional($a, $b) {
87 return $this->sort_optimizations_traditional($a, $b, 'run_sort_order');
88 }
89
90 public function sort_optimizations_traditional($a, $b, $sort_on = 'ui_sort_order') {
91
92 if (!is_a($a, 'WP_Optimization')) return (!is_a($b, 'WP_Optimization')) ? 0 : 1;
93 if (!is_a($b, 'WP_Optimization')) return -1;
94
95 $sort_order_a = empty($a->$sort_on) ? 0 : $a->$sort_on;
96 $sort_order_b = empty($b->$sort_on) ? 0 : $b->$sort_on;
97
98 if ($sort_order_a == $sort_order_b) return 0;
99
100 return ($sort_order_a < $sort_order_b) ? (-1) : 1;
101
102 }
103
104 /**
105 * This method returns an array of available optimizations.
106 * Each array key is an optimization ID, and the value is an object,
107 * as returned by get_optimization()
108 *
109 * @return [array] array of optimizations or WP_Error objects
110 */
111 public function get_optimizations() {
112
113 $optimizations = $this->get_optimizations_list();
114
115 $optimization_objects = array();
116
117 foreach ($optimizations as $optimization) {
118 $optimization_object = $this->get_optimization($optimization);
119 if (is_wp_error($optimization_object)) {
120 WP_Optimize()->log('Failed to load optimization ' . $optimization . ' - ' . $optimization_object->get_error_message());
121 } else {
122 $optimization_objects[$optimization] = $optimization_object;
123 }
124 }
125
126 return apply_filters('wp_optimize_get_optimizations', $optimization_objects);
127
128 }
129
130 /**
131 * This method returns an object for a specific optimization.
132 *
133 * @param string $which_optimization An optimization ID.
134 * @param array $data An array of anny options $data.
135 * @return array WP_Error Will return the optimization, or a WP_Error object if it was not found.
136 */
137 public function get_optimization($which_optimization, $data = array()) {
138
139 $optimization_class = apply_filters('wp_optimize_optimization_class', 'WP_Optimization_'.$which_optimization);
140
141 if (!class_exists('WP_Optimization')) include_once(WPO_PLUGIN_MAIN_PATH.'includes/class-wp-optimization.php');
142
143 if (!class_exists($optimization_class)) {
144 $optimization_file = WPO_PLUGIN_MAIN_PATH.'optimizations/'.$which_optimization.'.php';
145 $class_file = apply_filters('wp_optimize_optimization_class_file', $optimization_file);
146 if (!preg_match('/^[a-z]+$/', $which_optimization) || !file_exists($class_file)) {
147 return new WP_Error('no_such_optimization', __('No such optimization', 'wp-optimize'), $which_optimization);
148 }
149
150 include_once($class_file);
151
152 if (!class_exists($optimization_class)) {
153 return new WP_Error('no_such_optimization', __('No such optimization', 'wp-optimize'), $which_optimization);
154 }
155 }
156
157 // set sites option for Multisite cron job.
158 if (defined('DOING_CRON') && DOING_CRON && is_multisite()) {
159 $options = WP_Optimize()->get_options();
160 $data['optimization_sites'] = $options->get_option('wpo-sites-cron', array('all'));
161 }
162
163 $optimization = new $optimization_class($data);
164
165 return $optimization;
166
167 }
168
169 /**
170 * The method to call to perform an optimization.
171 *
172 * @param string|object $which_optimization An optimization ID, or a WP_Optimization object.
173 * @return array Array of results from the optimization.
174 */
175 public function do_optimization($which_optimization) {
176
177 $optimization = (is_object($which_optimization) && is_a($which_optimization, 'WP_Optimization')) ? $which_optimization : $this->get_optimization($which_optimization);
178
179 if (is_wp_error($optimization)) {
180 WP_Optimize()->log('Error occurred. Unknown optimization.');
181 return $optimization;
182 }
183
184 WP_Optimize()->change_time_limit();
185
186 $optimization->init();
187
188 if (apply_filters('wp_optimize_do_optimization', true, $which_optimization, $optimization)) {
189
190 $optimization->before_optimize();
191
192 if ($optimization->run_multisite) {
193 foreach ($optimization->blogs_ids as $blog_id) {
194 $optimization->switch_to_blog($blog_id);
195 $optimization->optimize();
196 $optimization->restore_current_blog();
197 }
198 } else {
199 $optimization->optimize();
200 }
201
202 $optimization->after_optimize();
203
204 }
205
206 do_action('wp_optimize_after_optimization', $which_optimization, $optimization);
207
208 $results = $optimization->get_results();
209
210 return $results;
211 }
212
213 /**
214 * The method to call to get information about an optimization.
215 * As with do_optimization, it is somewhat modelled after the template interface
216 *
217 * @param string|object $which_optimization An optimization ID, or a WP_Optimization object.
218 * @return object returns the optimization information
219 */
220 public function get_optimization_info($which_optimization) {
221
222 $optimization = (is_object($which_optimization) && is_a($which_optimization, 'WP_Optimization')) ? $which_optimization : $this->get_optimization($which_optimization);
223
224 if (is_wp_error($optimization)) return $optimization;
225
226 WP_Optimize()->change_time_limit();
227
228 $optimization->before_get_info();
229
230 if ($optimization->run_multisite) {
231 foreach ($optimization->blogs_ids as $blog_id) {
232 $optimization->switch_to_blog($blog_id);
233 $optimization->get_info();
234 $optimization->restore_current_blog();
235 }
236 } else {
237 $optimization->get_info();
238 }
239
240 $optimization->after_get_info();
241
242 return $optimization->get_results();
243 }
244
245 /**
246 * THis runs the list of optimizations.
247 *
248 * @param array $optimization_options Whether to do an optimization depends on what keys are set (legacy - can be changed hopefully).
249 * @param string $which_option Specify which option.
250 * @return array Returns an array of result objects.
251 */
252 public function do_optimizations($optimization_options, $which_option = 'dom') {
253
254 $results = array();
255
256 if (empty($optimization_options)) return $results;
257
258 $optimizations = $this->sort_optimizations($this->get_optimizations(), 'run_sort_order');
259
260 foreach ($optimizations as $optimization_id => $optimization) {
261 $option_id = call_user_func(array($optimization, 'get_'.$which_option.'_id'));
262
263 if (isset($optimization_options[$option_id])) {
264 // if options saved as a string then compare with string (for support different versions)
265 if (is_string($optimization_options[$option_id]) && 'false' === $optimization_options[$option_id]) continue;
266
267 if ('auto' == $which_option && empty($optimization->available_for_auto)) continue;
268
269 WP_Optimize()->change_time_limit();
270
271 $results[$optimization_id] = $this->do_optimization($optimization);
272 }
273 }
274
275 // Run action after all optimizations completed.
276 do_action('wp_optimize_after_optimizations');
277
278 return $results;
279
280 }
281
282 public function get_table_prefix($allow_override = false) {
283 $wpdb = $GLOBALS['wpdb'];
284 if (is_multisite() && !defined('MULTISITE')) {
285 // In this case (which should only be possible on installs upgraded from pre WP 3.0 WPMU), $wpdb->get_blog_prefix() cannot be made to return the right thing. $wpdb->base_prefix is not explicitly marked as public, so we prefer to use get_blog_prefix if we can, for future compatibility.
286 $prefix = $wpdb->base_prefix;
287 } else {
288 $prefix = $wpdb->get_blog_prefix(0);
289 }
290 return ($allow_override) ? apply_filters('wp_optimize_get_table_prefix', $prefix) : $prefix;
291 }
292
293 /**
294 * Returns information about database tables.
295 *
296 * @param bool $update refresh or no cached data
297 *
298 * @return mixed
299 */
300 public function get_tables($update = false) {
301 static $tables_info = null;
302
303 if (false === $update && null !== $tables_info) return $tables_info;
304
305 $wpo_db_info = WP_Optimize()->get_db_info();
306
307 $table_status = $wpo_db_info->get_show_table_status($update);
308
309 // Filter on the site's DB prefix (was not done in releases up to 1.9.1).
310 $table_prefix = $this->get_table_prefix();
311
312 if (is_array($table_status)) {
313
314 $corrupted_tables_count = 0;
315
316 foreach ($table_status as $index => $table) {
317 $table_name = $table->Name;
318
319 $include_table = (0 === stripos($table_name, $table_prefix));
320
321 $include_table = apply_filters('wp_optimize_get_tables_include_table', $include_table, $table_name, $table_prefix);
322
323 if (!$include_table && '' !== $table_prefix) {
324 unset($table_status[$index]);
325 continue;
326 }
327
328 $table_status[$index]->Engine = $wpo_db_info->get_table_type($table_name);
329
330 $table_status[$index]->is_optimizable = $wpo_db_info->is_table_optimizable($table_name);
331 $table_status[$index]->is_type_supported = $wpo_db_info->is_table_type_optimize_supported($table_name);
332 // add information about corrupted tables.
333 $is_needing_repair = $wpo_db_info->is_table_needing_repair($table_name);
334 $table_status[$index]->is_needing_repair = $is_needing_repair;
335 if ($is_needing_repair) $corrupted_tables_count++;
336
337 $table_status[$index] = $this->join_plugin_information($table_name, $table_status[$index]);
338
339 $table_status[$index]->blog_id = $wpo_db_info->get_table_blog_id($table_name);
340 }
341
342 WP_Optimize()->get_options()->update_option('corrupted-tables-count', $corrupted_tables_count);
343 }
344
345 $tables_info = apply_filters('wp_optimize_get_tables', $table_status);
346 return $tables_info;
347 }
348
349 /**
350 * Returns information about single table by table name.
351 *
352 * @param String $table_name table name
353 * @return Object|Boolean table information object.
354 */
355 public function get_table($table_name) {
356
357 $db_info = WP_Optimize()->get_db_info();
358
359 $table = $db_info->get_table_status($table_name);
360
361 if (false === $table) return false;
362
363 $table->is_optimizable = $db_info->is_table_optimizable($table_name);
364 $table->is_type_supported = $db_info->is_table_type_optimize_supported($table_name);
365 $table->is_needing_repair = $db_info->is_table_needing_repair($table_name);
366
367 // add information about plugins.
368 $table = $this->join_plugin_information($table_name, $table);
369
370 $table = apply_filters('wp_optimize_get_table', $table);
371 return $table;
372 }
373
374 /**
375 * Add information about relationship database tables with plugins.
376 *
377 * @param {string} $table_name
378 * @param {object} $table_obj
379 *
380 * @return {object}
381 */
382 public function join_plugin_information($table_name, $table_obj) {
383 // set can be removed flag.
384 $can_be_removed = false;
385 // set WP core table flag.
386 $wp_core_table = false;
387 // set WP actionscheduler table flag.
388 $wp_actionscheduler_table = (false !== stripos($table_name, 'actionscheduler_'));
389 // add information about using table by any of installed plugins.
390 $table_obj->is_using = WP_Optimize()->get_db_info()->is_table_using_by_plugin($table_name);
391 // if table belongs to any plugin then add plugins status.
392 $plugins = WP_Optimize()->get_db_info()->get_table_plugin($table_name);
393
394 if (false !== $plugins) {
395 // if belongs to any of plugin then we can remove table if plugin not active.
396 $can_be_removed = true;
397
398 $plugin_status = array();
399 foreach ($plugins as $plugin) {
400 $status = WP_Optimize()->get_db_info()->get_plugin_status($plugin);
401
402 if (__('WordPress core', 'wp-optimize') == $plugin) $wp_core_table = true;
403 // if plugin is active then we can't remove.
404 if ($wp_core_table || $status['active'] || $wp_actionscheduler_table) $can_be_removed = false;
405
406 if ($status['installed'] || $status['active'] || !$table_obj->is_using) {
407 $plugin_status[] = array(
408 'plugin' => $plugin,
409 'status' => $status,
410 );
411 }
412 }
413
414 $table_obj->plugin_status = $plugin_status;
415 }
416
417 $table_obj->wp_core_table = $wp_core_table;
418 $table_obj->can_be_removed = $can_be_removed;
419
420 return $table_obj;
421 }
422
423 /**
424 * This function grabs a list of tables
425 * and information regarding each table and returns
426 * the results to optimizations-table.php and optimizationstable.php
427 *
428 * @param int $blog_id filter tables by prefix
429 *
430 * @return Array - an array of data such as table list, innodb info and data free
431 */
432 public function get_table_information($blog_id = 0) {
433 // Get table information.
434 $tablesstatus = $this->get_tables();
435
436 // Set defaults.
437 $table_information = array();
438 $table_information['total_gain'] = 0;
439 $table_information['inno_db_tables'] = 0;
440 $table_information['non_inno_db_tables'] = 0;
441 $table_information['table_list'] = '';
442 $table_information['is_optimizable'] = true;
443
444 // Make a list of tables to optimize.
445 foreach ($tablesstatus as $each_table) {
446 // if $blog_id is set then filter tables
447 if ($blog_id > 0 && $blog_id != $each_table->blog_id) continue;
448
449 $table_information['table_list'] .= $each_table->Name.'|';
450
451 // check if table type supported.
452 if (!$each_table->is_type_supported) continue;
453
454 // check if table is optimizable.
455 if (!$each_table->is_optimizable) {
456 $table_information['is_optimizable'] = false;
457 }
458
459 // calculate total gain value.
460 $table_information['total_gain'] += $each_table->Data_free;
461
462 // count InnoDB tables.
463 if ('InnoDB' == $each_table->Engine) {
464 $table_information['inno_db_tables']++;
465 } else {
466 $table_information['non_inno_db_tables']++;
467 }
468 }
469
470 return $table_information;
471 }
472
473 /**
474 * What sort of linkback to enable or disable: valid values are 'trackbacks' or 'comments', and whether to enable or disable.
475 *
476 * @param string $type Specify the type of linkbacks.
477 * @param boolean $enable If it is enabled or disabled.
478 */
479 public function enable_linkbacks($type, $enable = true) {
480
481 $wpdb = $GLOBALS['wpdb'];
482 $wpo_options = WP_Optimize()->get_options();
483
484 $new_status = $enable ? 'open' : 'closed';
485
486 switch ($type) {
487 case "trackbacks":
488 $thissql = "UPDATE `".$wpdb->posts."` SET ping_status='".$new_status."' WHERE post_status = 'publish' AND post_type = 'post';";
489 $wpdb->query($thissql);
490 break;
491
492 case "comments":
493 $thissql = "UPDATE `".$wpdb->posts."` SET comment_status='".$new_status."' WHERE post_status = 'publish' AND post_type = 'post';";
494 $wpdb->query($thissql);
495 break;
496
497 default:
498 break;
499 }
500 $wpo_options->update_option($type.'_action', array('action' => $enable, 'timestamp' => time()));
501
502 }
503
504 /**
505 * This function will return total database size and a possible gain of db in KB.
506 *
507 * @param boolean $update - Wether to update the values or not
508 * @return string total db size gained.
509 */
510 public function get_current_db_size($update = false) {
511
512 if (!$update && $db_size = get_transient('wpo_get_current_db_size')) {
513 return $db_size;
514 }
515
516 $wp_optimize = WP_Optimize();
517
518 $total_gain = 0;
519 $total_size = 0;
520 $row_usage = 0;// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable -- $row_usage Used in the foreach below
521 $data_usage = 0;
522 $index_usage = 0;
523 $overhead_usage = 0;// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable -- $overhead_usage Used in the foreach below
524
525 $tablesstatus = $this->get_tables();
526
527 foreach ($tablesstatus as $tablestatus) {
528 $row_usage += $tablestatus->Rows;// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable -- $row_usage declared up above
529 $total_gain += $tablestatus->Data_free;
530 $data_usage += $tablestatus->Data_length;
531 $index_usage += $tablestatus->Index_length;
532
533 if ('InnoDB' != $tablestatus->Engine) {
534 $overhead_usage += $tablestatus->Data_free;// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable -- $overhead_usage declared up above
535 $total_gain += $tablestatus->Data_free;
536 }
537 }
538
539 $total_size = ($data_usage + $index_usage);
540 $db_size = array($wp_optimize->format_size($total_size), $wp_optimize->format_size($total_gain));
541 set_transient('wpo_get_current_db_size', $db_size, 3600);
542 return $db_size;
543 }
544
545 /**
546 * This function will return total saved data in KB.
547 *
548 * @param string $current How big the data is.
549 * @return string Returns new total value.
550 */
551 public function update_total_cleaned($current) {
552
553 $options = WP_Optimize()->get_options();
554
555 $previously_saved = floatval($options->get_option('total-cleaned', '0'));
556 $converted_current = floatval($current);
557
558 $total_now = strval($previously_saved + $converted_current);
559
560 $options->update_option('total-cleaned', $total_now);
561
562 return $total_now;
563 }
564
565
566 public function trackback_comment_actions($options) {
567
568 $output = array();
569 $messages = array();
570
571 if (isset($options['comments'])) {
572 if (!$options['comments']) {
573 $this->enable_linkbacks('comments', false);
574 $output[] = __('Comments have now been disabled on all current and previously published posts.', 'wp-optimize');
575 $messages[] = sprintf(__('All comments on existing posts were disabled at %s.', 'wp-optimize'), WP_Optimize()->format_date_time(time()));
576 } else {
577 $this->enable_linkbacks('comments');
578 $output[] = __('Comments have now been enabled on all current and previously published posts.', 'wp-optimize');
579 $messages[] = sprintf(__('All comments on existing posts were enabled at %s.', 'wp-optimize'), WP_Optimize()->format_date_time(time()));
580 }
581 }
582
583 if (isset($options['trackbacks'])) {
584 if (!$options['trackbacks']) {
585 $this->enable_linkbacks('trackbacks', false);
586 $output[] = __('Trackbacks have now been disabled on all current and previously published posts.', 'wp-optimize');
587 $messages[] = sprintf(__('All trackbacks on existing posts were disabled at %s.', 'wp-optimize'), WP_Optimize()->format_date_time(time()));
588 } else {
589 $this->enable_linkbacks('trackbacks');
590 $output[] = __('Trackbacks have now been enabled on all current and previously published posts.', 'wp-optimize');
591 $messages[] = sprintf(__('All trackbacks on existing posts were enabled at %s.', 'wp-optimize'), WP_Optimize()->format_date_time(time()));
592 }
593 }
594
595 return array('output' => $output,'messages' => $messages);
596 }
597
598 /**
599 * Wether InnoDB tables require confirmation to be optimized
600 *
601 * @return boolean
602 */
603 public function show_innodb_force_optimize() {
604 $tablesstatus = $this->get_table_information();
605 return false === $tablesstatus['is_optimizable'] && $tablesstatus['inno_db_tables'] > 0;
606 }
607 }
608