PluginProbe
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance / 4.2.2
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance v4.2.2
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 3.8.0 All 110 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.2.2, at includes/class-wp-optimization.php

515 lines 12.8 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 * 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 array 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 return apply_filters('wp_optimize_optimization_query_result', $result, $sql, $this);
108 }
109
110 /**
111 * Display or hide optimization in optimizations list.
112 *
113 * @return bool
114 */
115 public function display_in_optimizations_list() {
116 return true;
117 }
118
119 /**
120 * Returns data those should be optimized. Used to display this information in a popup tool
121 * for previewing and removing certain data for optimization.
122 *
123 * @param array $params
124 *
125 * @return array
126 */
127 public function preview($params) {
128 return array(
129 'id_key' => 'id', // key used used to identify data.
130 'offset' => $params['offset'],
131 'limit' => $params['limit'],
132 'total' => 0,
133 'data' => array(), // returned data as associative array where keys are column names and values - database cell values.
134 );
135 }
136
137 /**
138 * Convert all applicable characters to HTML entities in array. Used to prepare data for output in browser for preview.
139 *
140 * @param array $array source array
141 * @param array $exclude_keys what items shouldn't be encoded.
142 *
143 * @return array
144 */
145 public function htmlentities_array($array, $exclude_keys = array()) {
146 if (!is_array($array) || empty($array)) return $array;
147
148 foreach ($array as $key => $value) {
149 if (in_array($key, $exclude_keys)) continue;
150
151 if (!is_array($value)) {
152 $array[$key] = htmlentities($value);
153 } else {
154 $array[$key] = $this->htmlentities_array($value);
155 }
156 }
157
158 return $array;
159 }
160
161 /**
162 * Do actions before get_info() function.
163 */
164 public function before_get_info() {
165 $this->found_count = 0;
166 }
167
168 /**
169 * Do actions after get_info() function.
170 */
171 public function after_get_info() {
172
173 }
174
175 abstract public function get_info();
176
177 /**
178 * Do actions before optimize() function.
179 */
180 public function before_optimize() {
181 $this->processed_count = 0;
182 }
183
184 /**
185 * Do actions after optimize() function.
186 */
187 public function after_optimize() {
188
189 }
190
191 abstract public function optimize();
192
193 abstract public function settings_label();
194
195 /**
196 * WP_Optimization constructor.
197 *
198 * @param array $data initial data for optimization.
199 */
200 public function __construct($data = array()) {
201 $class_name = get_class($this);
202 // Remove the prefixed WP_Optimization_.
203 $this->id = substr($class_name, 16);
204 $this->data = $data;
205 $this->optimizer = WP_Optimize()->get_optimizer();
206 $this->options = WP_Optimize()->get_options();
207 $this->logger = WP_Optimize()->get_logger();
208 $wpdb = $GLOBALS['wpdb'];
209 $this->wpdb = $wpdb;
210 $this->blogs_ids = $this->get_optimization_blogs();
211 $this->init();
212 }
213
214 /**
215 * This triggers the do_optimization function
216 * within class-wp-optimizer.php to kick off the optimizations.
217 * It also passed the data array from the wpadmin.js.
218 *
219 * @return array array of results that includes sql_commands, output and meta
220 */
221 public function do_optimization() {
222 return $this->optimizer->do_optimization($this);
223 }
224
225 /**
226 * This gathers the optimization information to be displayed
227 * before triggering any optimizations
228 *
229 * @return object Returns an object of optimization information
230 */
231 public function get_optimization_info() {
232 return $this->optimizer->get_optimization_info($this);
233 }
234
235 /**
236 * Returns array of blog ids
237 *
238 * @return array
239 */
240 public function get_optimization_blogs() {
241 $objects = array();
242
243 if ($this->is_multisite_mode()) {
244 $all_sites = false;
245 $selected_sites = array();
246
247 // support both arrays and single values in data site id parameter.
248 if (isset($this->data['site_id']) && !is_array($this->data['site_id'])) {
249 $this->data['site_id'] = array($this->data['site_id']);
250 }
251
252 $optimization_sites = (isset($this->data['site_id'])) ? $this->data['site_id'] : $this->options->get_wpo_sites_option();
253
254 // check selected sites field.
255 if (!empty($optimization_sites)) {
256 foreach ($optimization_sites as $site_id) {
257 if ('all' == $site_id) {
258 $all_sites = true;
259 } else {
260 $selected_sites[] = $site_id;
261 }
262 }
263 }
264
265 $sites = $this->get_sites();
266 if (!empty($sites)) {
267 foreach ($sites as $site) {
268 if ($all_sites || (in_array($site->blog_id, $selected_sites))) {
269 $objects[] = $site->blog_id;
270 }
271 }
272 } else {
273 $objects[] = 1;
274 }
275 } else {
276 $objects[] = 1;
277 }
278
279 return apply_filters('get_optimization_blogs', $objects);
280 }
281
282 /**
283 * Returns true if optimization works in multisite mode
284 *
285 * @return bool
286 */
287 public function is_multisite_mode() {
288 return WP_Optimize()->is_multisite_mode();
289 }
290
291 /**
292 * Returns list of all sites in multisite
293 *
294 * @return array
295 */
296 public function get_sites() {
297 return WP_Optimize()->get_sites();
298 }
299
300 /**
301 * Wrapper for switch_to_blog Wordpress MU function
302 *
303 * @param int $new_blog new blog id.
304 * @return bool|void - if on multisite, then always true (see https://codex.wordpress.org/Function_Reference/switch_to_blog)
305 */
306 public function switch_to_blog($new_blog) {
307 if (function_exists('switch_to_blog') && $this->is_multisite_mode()) {
308 return switch_to_blog($new_blog);
309 }
310 }
311
312 /**
313 * Wrapper for restore_current_blog Wordpress MU function
314 *
315 * @return bool
316 */
317 public function restore_current_blog() {
318 if (function_exists('restore_current_blog') && $this->is_multisite_mode()) {
319 return restore_current_blog();
320 }
321 }
322
323 /**
324 * This function adds output to the current registered output
325 *
326 * @param array $output Array of various outputs.
327 */
328 public function register_output($output) {
329 $this->output[] = $output;
330 }
331
332 /**
333 * This function adds meta-data associated with the result to the registered output
334 *
335 * @param string $key The key value.
336 * @param string $value The value to be passed.
337 */
338 public function register_meta($key, $value) {
339 $this->meta[$key] = $value;
340 }
341
342 /**
343 * Get meta-data added to the registered output.
344 *
345 * @return array
346 */
347 public function get_meta() {
348 return $this->meta;
349 }
350
351 public function init() {
352
353 $this->output = array();
354 $this->meta = array();
355 $this->sql_commands = array();
356
357 list ($retention_enabled, $retention_period) = $this->optimizer->get_retain_info();
358
359 $this->retention_enabled = $retention_enabled;
360 $this->retention_period = $retention_period;
361
362 list($revisions_retention_enabled, $revisions_retention_count) = $this->optimizer->get_revisions_retain_info();
363 $this->revisions_retention_enabled = $revisions_retention_enabled;
364 $this->revisions_retention_count = $revisions_retention_count;
365
366 }
367
368
369 /**
370 * 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.
371 */
372 public function get_setting_id() {
373 return empty($this->setting_id) ? 'user-'.$this->id : 'user-'.$this->setting_id;
374 }
375
376 public function get_dom_id() {
377 return empty($this->dom_id) ? 'clean-'.$this->id : $this->dom_id;
378 }
379
380 public function get_auto_id() {
381 return empty($this->auto_id) ? $this->id : $this->auto_id;
382 }
383
384 public function get_changes_table_data() {
385 return empty($this->changes_table_data) ? false : true;
386 }
387
388 public function get_run_sort_order() {
389 return empty($this->run_sort_order) ? 0 : $this->run_sort_order;
390 }
391
392 /**
393 * Only used if $available_for_auto is true, in which case this function should be over-ridden
394 *
395 * @return string Error message.
396 */
397 public function get_auto_option_description() {
398 return 'Error: missing scheduled option description ('.$this->id.')';
399 }
400
401 /**
402 * What is returned must be at least convertible to an array
403 *
404 * @return object Results object.
405 */
406 public function get_results() {
407
408 // As yet, we have no need for a dedicated object type for our results.
409 $results = new stdClass;
410
411 $results->sql_commands = $this->sql_commands;
412 $results->output = $this->output;
413 $results->meta = $this->meta;
414
415 return apply_filters('wp_optimize_optimization_results', $results, $this->id, $this);
416 }
417
418 /**
419 * Generate information about optimization required for show it.
420 *
421 * @return array
422 */
423 public function get_settings_html() {
424
425 $wpo_user_selection = $this->options->get_main_settings();
426 $setting_id = $this->get_setting_id();
427 $dom_id = $this->get_dom_id();
428
429 // N.B. Some of the optimizations used to have an onclick call to fCheck(). But that function was commented out, so did nothing.
430 $settings_label = $this->settings_label();
431
432 $setting_activated = ((empty($wpo_user_selection[$setting_id]) || 'false' == $wpo_user_selection[$setting_id]) ? false : true);
433
434 $info = $this->get_optimization_info()->output;
435
436 $settings_html = array(
437 'dom_id' => $dom_id,
438 'activated' => $setting_activated,
439 'settings_label' => $settings_label,
440 'info' => wp_kses(join('<br>', $info), $this->allow_checkboxes()),
441 );
442
443 if (empty($settings_label)) {
444 // Error_log, as this is a defect.
445 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
446 }
447
448 return $settings_html;
449 }
450
451 /**
452 * Wrap $text as a link for preview action. If preview is not supported then return just $text.
453 *
454 * @param string $text
455 * @param array $attributes
456 *
457 * @return string
458 */
459 public function get_preview_link($text, $attributes = array()) {
460 // if preview is not supported then return just $text.
461 if (false == $this->support_preview || false == WP_Optimize::is_premium()) return $text;
462
463 $attributes = array_merge(
464 array(
465 'title' => __('Preview found items', 'wp-optimize'),
466 'data-id' => $this->id,
467 'data-title' => $this->settings_label(),
468 ),
469 $attributes
470 );
471
472 $str_attr = '';
473
474 foreach ($attributes as $key => $value) {
475 $str_attr .= ' '.$key.'="'.esc_attr($value).'"';
476 }
477
478 $link = '<a href="#" class="wpo-optimization-preview"'.$str_attr.'>'.$text.'</a>';
479
480 return $link;
481 }
482
483 /**
484 * Adds input and label tags to allowed HTML tags.
485 *
486 * @return array
487 */
488 private function allow_checkboxes(): array {
489 $allowed_html = wp_kses_allowed_html('post');
490
491 $allowed_html['input'] = array(
492 'type' => true,
493 'name' => true,
494 'id' => true,
495 'class' => true,
496 'value' => true,
497 'placeholder' => true,
498 'required' => true,
499 'checked' => true,
500 'disabled' => true,
501 'min' => true,
502 'max' => true,
503 'step' => true
504 );
505
506 $allowed_html['label'] = array(
507 'for' => true,
508 'class' => true,
509 'id' => true
510 );
511
512 return $allowed_html;
513 }
514 }
515