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
wp-optimize / includes / class-wp-optimization.php

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

534 lines 13.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if (!defined('ABSPATH')) die('No direct access allowed');
4
5 /**
6 * Parent class for all optimizations.
7 */
8 abstract class WP_Optimization {
9
10 /**
11 * Ideally, these would all be the same. But, historically, some are not; hence, three separate IDs.
12 *
13 * @var $id
14 */
15 public $id;
16
17 protected $setting_id;
18
19 protected $dom_id;
20
21 protected $auto_id;
22
23 protected $available_for_auto;
24
25 protected $ui_sort_order;
26
27 protected $run_sort_order = 1000;
28
29 public $run_multisite = true;
30
31 public $support_preview = true; // if true then optimization support preview action for optimization data.
32
33 /**
34 * This property indicates whether running this optimization is likely to change the overall table optimization state. We set this to 'true' on optimizations that run SQL OPTIMIZE commands. It is only used for the UI. Strictly, of course, any optimization that deletes something can cause increased fragmentation; so; in that sense, it would be true for every optimization; but since we are just using it to keep the UI reasonably fresh, and since there is a manual "refresh" button, we set it only on some optimizations.
35 *
36 * @var [$changes_table_data
37 */
38 protected $changes_table_data;
39
40 protected $optimizer;
41
42 protected $options;
43
44 protected $logger;
45
46 protected $data;
47
48 /**
49 * Blogs ids for optimization.
50 *
51 * @var $blogs_ids
52 */
53 public $blogs_ids;
54
55 /**
56 * Count of blogs for optimization.
57 *
58 * @var $blogs_count
59 */
60 public $blogs_count;
61
62 /**
63 * Store count of optimized items.
64 *
65 * @var $processed_count
66 */
67 public $processed_count;
68
69 /**
70 * Store found items for optimization. Used in get_info() and related functions.
71 *
72 * @var $found_count;
73 */
74 public $found_count;
75
76 public $retention_enabled;
77
78 public $retention_period;
79
80 public $revisions_retention_enabled;
81
82 public $revisions_retention_count;
83
84 /**
85 * Results. These should be accessed via get_results()
86 *
87 * @var $output
88 */
89 private $output;
90
91 private $meta;
92
93 private $sql_commands;
94
95 protected $wpdb;
96
97 /**
98 * This is abstracted so to provide future possibilities, e.g. logging.
99 *
100 * @param string $sql The prepared SQL query to run
101 * @return mixed Return array of results
102 */
103 protected function query($sql) {
104 $this->sql_commands[] = $sql;
105 do_action('wp_optimize_optimization_query', $sql, $this);
106 $result = $this->wpdb->query($sql); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- Already prepared query
107 $filtered_result = apply_filters('wp_optimize_optimization_query_result', $result, $sql, $this);
108 if (!empty($filtered_result) && is_array($filtered_result)) return $filtered_result;
109 return $result;
110 }
111
112 /**
113 * Display or hide optimization in optimizations list.
114 *
115 * @return bool
116 */
117 public function display_in_optimizations_list() {
118 return true;
119 }
120
121 /**
122 * Returns data those should be optimized. Used to display this information in a popup tool
123 * for previewing and removing certain data for optimization.
124 *
125 * @param array $params
126 *
127 * @return array
128 */
129 public function preview($params) {
130 return array(
131 'id_key' => 'id', // key is used to identify data.
132 'offset' => $params['offset'],
133 'limit' => $params['limit'],
134 'total' => 0,
135 'data' => array(), // returned data as associative array where keys are column names and values - database cell values.
136 );
137 }
138
139 /**
140 * Convert all applicable characters to HTML entities in array. Used to prepare data for output in browser for preview.
141 *
142 * @param array $array source array
143 * @param array $exclude_keys what items shouldn't be encoded.
144 *
145 * @return array
146 */
147 public function htmlentities_array($array, $exclude_keys = array()) {
148 if (!is_array($array) || empty($array)) return $array;
149
150 foreach ($array as $key => $value) {
151 if (in_array($key, $exclude_keys)) continue;
152
153 if (!is_array($value)) {
154 $array[$key] = htmlentities($value);
155 } else {
156 $array[$key] = $this->htmlentities_array($value);
157 }
158 }
159
160 return $array;
161 }
162
163 /**
164 * Do actions before get_info() function.
165 */
166 public function before_get_info() {
167 $this->found_count = 0;
168 }
169
170 /**
171 * Do actions after get_info() function.
172 */
173 public function after_get_info() {
174
175 }
176
177 abstract public function get_info();
178
179 /**
180 * Do actions before optimize() function.
181 */
182 public function before_optimize() {
183 $this->processed_count = 0;
184 }
185
186 /**
187 * Do actions after optimize() function.
188 */
189 public function after_optimize() {
190
191 }
192
193 abstract public function optimize();
194
195 abstract public function settings_label();
196
197 /**
198 * WP_Optimization constructor.
199 *
200 * @param array $data initial data for optimization.
201 */
202 public function __construct($data = array()) {
203 $class_name = get_class($this);
204 // Remove the prefixed WP_Optimization_.
205 $this->id = substr($class_name, 16);
206 $this->data = $data;
207 $this->optimizer = WP_Optimize()->get_optimizer();
208 $this->options = WP_Optimize()->get_options();
209 $this->logger = WP_Optimize()->get_logger();
210 $wpdb = $GLOBALS['wpdb'];
211 $this->wpdb = $wpdb;
212 $this->blogs_ids = $this->get_optimization_blogs();
213 $this->init();
214 }
215
216 /**
217 * This triggers the do_optimization function
218 * within class-wp-optimizer.php to kick off the optimizations.
219 * It also passed the data array from the wpadmin.js.
220 *
221 * @return array|object|WP_Error|WP_Optimization array of results that includes sql_commands, output and meta
222 */
223 public function do_optimization() {
224 return $this->optimizer->do_optimization($this);
225 }
226
227 /**
228 * This gathers the optimization information to be displayed
229 * before triggering any optimizations
230 *
231 * @return array|object|WP_Error|WP_Optimization Returns an object of optimization information
232 */
233 public function get_optimization_info() {
234 return $this->optimizer->get_optimization_info($this);
235 }
236
237 /**
238 * Returns array of blog ids
239 *
240 * @return array
241 */
242 public function get_optimization_blogs() {
243 $objects = array();
244
245 if ($this->is_multisite_mode()) {
246 $all_sites = false;
247 $selected_sites = array();
248
249 // support both arrays and single values in data site id parameter.
250 if (isset($this->data['site_id']) && !is_array($this->data['site_id'])) {
251 $this->data['site_id'] = array($this->data['site_id']);
252 }
253
254 $optimization_sites = (isset($this->data['site_id'])) ? $this->data['site_id'] : $this->options->get_wpo_sites_option();
255
256 // check selected sites field.
257 if (!empty($optimization_sites)) {
258 foreach ($optimization_sites as $site_id) {
259 if ('all' === (string) $site_id) {
260 $all_sites = true;
261 } else {
262 $selected_sites[] = $site_id;
263 }
264 }
265 }
266
267 $sites = $this->get_sites();
268 if (!empty($sites)) {
269 foreach ($sites as $site) {
270 if ($all_sites || (in_array($site->blog_id, $selected_sites))) {
271 $objects[] = $site->blog_id;
272 }
273 }
274 } else {
275 $objects[] = 1;
276 }
277 } else {
278 $objects[] = 1;
279 }
280
281 $filtered_objects = apply_filters('get_optimization_blogs', $objects);
282 if (is_array($filtered_objects)) return $filtered_objects;
283 return $objects;
284 }
285
286 /**
287 * Returns true if optimization works in multisite mode
288 *
289 * @return bool
290 */
291 public function is_multisite_mode() {
292 return WP_Optimize()->is_multisite_mode();
293 }
294
295 /**
296 * Returns list of all sites in multisite
297 *
298 * @return array
299 */
300 public function get_sites() {
301 return WP_Optimize()->get_sites();
302 }
303
304 /**
305 * Wrapper for switch_to_blog WordPress MU function
306 *
307 * @param int $new_blog new blog id.
308 * @return bool|void - if on multisite, then always true (see https://codex.wordpress.org/Function_Reference/switch_to_blog)
309 */
310 public function switch_to_blog($new_blog) {
311 if (function_exists('switch_to_blog') && $this->is_multisite_mode()) {
312 return switch_to_blog($new_blog);
313 }
314 }
315
316 /**
317 * Wrapper for restore_current_blog WordPress MU function
318 *
319 * @return bool|void
320 */
321 public function restore_current_blog() {
322 if (function_exists('restore_current_blog') && $this->is_multisite_mode()) {
323 return restore_current_blog();
324 }
325 }
326
327 /**
328 * This function adds output to the current registered output
329 *
330 * @param string $output Output message
331 */
332 public function register_output($output) {
333 $this->output[] = $output;
334 }
335
336 /**
337 * This function adds meta-data associated with the result to the registered output
338 *
339 * @param string $key The key value.
340 * @param mixed $value The value to be passed.
341 */
342 public function register_meta($key, $value) {
343 $this->meta[$key] = $value;
344 }
345
346 /**
347 * Get meta-data added to the registered output.
348 *
349 * @return array
350 */
351 public function get_meta() {
352 return $this->meta;
353 }
354
355 public function init() {
356
357 $this->output = array();
358 $this->meta = array();
359 $this->sql_commands = array();
360
361 list ($retention_enabled, $retention_period) = $this->optimizer->get_retain_info();
362
363 $this->retention_enabled = $retention_enabled;
364 $this->retention_period = $retention_period;
365
366 list($revisions_retention_enabled, $revisions_retention_count) = $this->optimizer->get_revisions_retain_info();
367 $this->revisions_retention_enabled = $revisions_retention_enabled;
368 $this->revisions_retention_count = $revisions_retention_count;
369
370 }
371
372
373 /**
374 * The next three functions reflect the fact that historically, WP-Optimize has not, for all optimizations, used the same ID consistently throughout forms, saved settings, and saved settings for scheduled clean-ups. Mostly, it has; but some flexibility is needed for the exceptions.
375 *
376 * @return string
377 */
378 public function get_setting_id() {
379 return empty($this->setting_id) ? 'user-'.$this->id : 'user-'.$this->setting_id;
380 }
381
382 /**
383 * This function, `get_setting_id` and `get_auto_id` functions reflect the fact that historically, WP-Optimize has not, for all optimizations, used the same ID consistently throughout forms, saved settings, and saved settings for scheduled clean-ups. Mostly, it has; but some flexibility is needed for the exceptions.
384 *
385 * @return string
386 */
387 public function get_dom_id() {
388 return empty($this->dom_id) ? 'clean-'.$this->id : $this->dom_id;
389 }
390
391 /**
392 * This function, `get_setting_id` and `get_dom_id` functions reflect the fact that historically, WP-Optimize has not, for all optimizations, used the same ID consistently throughout forms, saved settings, and saved settings for scheduled clean-ups. Mostly, it has; but some flexibility is needed for the exceptions.
393 *
394 * @return string
395 */
396 public function get_auto_id() {
397 return empty($this->auto_id) ? $this->id : $this->auto_id;
398 }
399
400 /**
401 * Checks whether this optimization has changes table data
402 *
403 * @return bool
404 */
405 public function get_changes_table_data() {
406 return empty($this->changes_table_data) ? false : true;
407 }
408
409 /**
410 * Returns the run sort order
411 *
412 * @return int
413 */
414 public function get_run_sort_order() {
415 return empty($this->run_sort_order) ? 0 : $this->run_sort_order;
416 }
417
418 /**
419 * What is returned must be at least convertible to an array
420 *
421 * @return object Results object.
422 */
423 public function get_results() {
424
425 // As yet, we have no need for a dedicated object type for our results.
426 $results = new stdClass;
427
428 $results->sql_commands = $this->sql_commands;
429 $results->output = $this->output;
430 $results->meta = $this->meta;
431
432 $filtered_results = apply_filters('wp_optimize_optimization_results', $results, $this->id, $this);
433 if (!empty($filtered_results) && is_object($filtered_results)) return $filtered_results;
434 return $results;
435 }
436
437 /**
438 * Generate information about optimization required for show it.
439 *
440 * @return array
441 */
442 public function get_settings_html() {
443
444 $wpo_user_selection = $this->options->get_main_settings();
445 $setting_id = $this->get_setting_id();
446 $dom_id = $this->get_dom_id();
447
448 // N.B. Some of the optimizations used to have an onclick call to fCheck(). But that function was commented out, so did nothing.
449 $settings_label = $this->settings_label();
450
451 $setting_activated = !empty($wpo_user_selection[$setting_id]) && 'false' !== $wpo_user_selection[$setting_id];
452
453 $info = $this->get_optimization_info()->output;
454
455 $settings_html = array(
456 'dom_id' => $dom_id,
457 'activated' => $setting_activated,
458 'settings_label' => $settings_label,
459 'info' => wp_kses(join('<br>', $info), $this->allow_checkboxes()),
460 );
461
462 if (empty($settings_label)) {
463 // Error_log, as this is a defect.
464 error_log("Optimization with setting ID ".$setting_id." lacks a settings label (method: settings_label())"); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- Using for debugging only
465 }
466
467 return $settings_html;
468 }
469
470 /**
471 * Wrap $text as a link for preview action. If preview is not supported then return just $text.
472 *
473 * @param string $text
474 * @param array $attributes
475 *
476 * @return string
477 */
478 public function get_preview_link($text, $attributes = array()) {
479 // if preview is not supported then return just $text.
480 if (!$this->support_preview || !WP_Optimize::is_premium()) return $text;
481
482 $attributes = array_merge(
483 array(
484 'title' => __('Preview found items', 'wp-optimize'),
485 'data-id' => $this->id,
486 'data-title' => $this->settings_label(),
487 ),
488 $attributes
489 );
490
491 $str_attr = '';
492
493 foreach ($attributes as $key => $value) {
494 $str_attr .= ' '.$key.'="'.esc_attr($value).'"';
495 }
496
497 $link = '<a href="#" class="wpo-optimization-preview"'.$str_attr.'>'.$text.'</a>';
498
499 return $link;
500 }
501
502 /**
503 * Adds input and label tags to allowed HTML tags.
504 *
505 * @return array
506 */
507 private function allow_checkboxes() {
508 $allowed_html = wp_kses_allowed_html('post');
509
510 $allowed_html['input'] = array(
511 'type' => true,
512 'name' => true,
513 'id' => true,
514 'class' => true,
515 'value' => true,
516 'placeholder' => true,
517 'required' => true,
518 'checked' => true,
519 'disabled' => true,
520 'min' => true,
521 'max' => true,
522 'step' => true
523 );
524
525 $allowed_html['label'] = array(
526 'for' => true,
527 'class' => true,
528 'id' => true
529 );
530
531 return $allowed_html;
532 }
533 }
534