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

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