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

wp-optimize.php in WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance 3.2.9, at wp-optimize.php

1,916 lines 62.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 Plugin Name: WP-Optimize - Clean, Compress, Cache
4 Plugin URI: https://getwpo.com
5 Description: WP-Optimize makes your site fast and efficient. It cleans the database, compresses images and caches pages. Fast sites attract more traffic and users.
6 Version: 3.2.9
7 Update URI: https://wordpress.org/plugins/wp-optimize/
8 Author: David Anderson, Ruhani Rabin, Team Updraft
9 Author URI: https://updraftplus.com
10 Text Domain: wp-optimize
11 Domain Path: /languages
12 License: GPLv2 or later
13 */
14
15 if (!defined('ABSPATH')) die('No direct access allowed');
16
17 // Check to make sure if WP_Optimize is already call and returns.
18 if (!class_exists('WP_Optimize')) :
19 define('WPO_VERSION', '3.2.9');
20 define('WPO_PLUGIN_URL', plugin_dir_url(__FILE__));
21 define('WPO_PLUGIN_MAIN_PATH', plugin_dir_path(__FILE__));
22 define('WPO_PREMIUM_NOTIFICATION', false);
23 define('WPO_MINIFY_PHP_VERSION_MET', version_compare(PHP_VERSION, '5.4', '>=') ? true : false);
24
25 class WP_Optimize {
26
27 public $premium_version_link = 'https://getwpo.com/buy/';
28
29 private $template_directories;
30
31 protected static $_instance = null;
32
33 /**
34 * Class constructor
35 */
36 public function __construct() {
37 spl_autoload_register(array($this, 'loader'));
38
39 // Checks if premium is installed along with plugins needed.
40 add_action('plugins_loaded', array($this, 'plugins_loaded'), 1);
41
42 register_activation_hook(__FILE__, 'wpo_activation_actions');
43 register_deactivation_hook(__FILE__, 'wpo_deactivation_actions');
44 register_uninstall_hook(__FILE__, 'wpo_uninstall_actions');
45
46 $this->load_admin();
47 add_action('admin_init', array($this, 'admin_init'));
48 add_action('admin_bar_menu', array($this, 'cache_admin_bar'), 100, 1);
49
50 add_action('init', array($this, 'schedule_plugin_cron_tasks'));
51
52 add_filter("plugin_action_links_".plugin_basename(__FILE__), array($this, 'plugin_settings_link'));
53 add_action('wpo_cron_event2', array($this, 'cron_action'));
54 add_filter('cron_schedules', array($this, 'cron_schedules'));
55
56 if (!$this->get_options()->get_option('installed-for', false)) $this->get_options()->update_option('installed-for', time());
57
58 if (!self::is_premium()) {
59 add_action('auto_option_settings', array($this->get_options(), 'auto_option_settings'));
60 }
61
62 add_action('admin_enqueue_scripts', array($this, 'admin_enqueue_scripts'));
63
64 add_action('wp_enqueue_scripts', array($this, 'frontend_enqueue_scripts'));
65
66 add_action('wp_ajax_wp_optimize_ajax', array($this, 'wp_optimize_ajax_handler'));
67
68 // Show update to Premium notice for non-premium multisite.
69 add_action('wpo_additional_options', array($this, 'show_multisite_update_to_premium_notice'));
70
71 // Action column (show repair button if need).
72 add_filter('wpo_tables_list_additional_column_data', array($this, 'tables_list_additional_column_data'), 15, 2);
73
74 /**
75 * Add action for display Images > Compress images tab.
76 */
77 add_action('wp_optimize_admin_page_wpo_images_smush', array($this, 'admin_page_wpo_images_smush'));
78
79 include_once(WPO_PLUGIN_MAIN_PATH.'includes/updraftcentral.php');
80
81 include_once(WPO_PLUGIN_MAIN_PATH.'includes/backward-compatibility-functions.php');
82
83 register_shutdown_function(array($this, 'log_fatal_errors'));
84
85 add_action('wpo_admin_before_closing_wrap', array($this, 'load_modal_template'), 20);
86
87 add_action('upgrader_process_complete', array($this, 'detect_active_plugins_and_themes_updates'), 10, 2);
88
89 $import_done_hooks = array(
90 'import_end', // wordpress importer
91 'pmxi_after_xml_import', // wp all import
92 );
93
94 $db_update_hooks = apply_filters('wp_optimize_db_update_hooks', $import_done_hooks);
95
96 foreach ($db_update_hooks as $hook) {
97 add_action($hook, array($this, 'maybe_schedule_update_record_count_event'));
98 }
99 add_action('wpo_update_record_count_event', array($this->get_db_info(), 'wpo_update_record_count'));
100 }
101
102 /**
103 * Auto-loads classes.
104 *
105 * @param string $class_name The name of the class.
106 */
107 private function loader($class_name) {
108 $dirs = $this->get_class_directories();
109
110 foreach ($dirs as $dir) {
111 $class_file = WPO_PLUGIN_MAIN_PATH . $dir . '/class-' . str_replace('_', '-', strtolower($class_name)) . '.php';
112 if (file_exists($class_file)) {
113 require_once($class_file);
114 return;
115 }
116 }
117 }
118
119 /**
120 * Returns an array of class directories
121 *
122 * @return array
123 */
124 private function get_class_directories() {
125 return array(
126 'cache',
127 'includes',
128 'minify',
129 'optimizations',
130 'webp',
131 );
132 }
133
134 /**
135 * Initialize Admin class to load admin UI
136 */
137 private function load_admin() {
138 $this->get_admin_instance();
139 }
140
141 /**
142 * Returns Admin class instance
143 *
144 * @return WP_Optimize_Admin
145 */
146 public function get_admin_instance() {
147 return WP_Optimize_Admin::instance();
148 }
149
150 /**
151 * Detect when an active plugin or theme is updated, and trigger an action
152 *
153 * @param object $upgrader_object
154 * @param array $options
155 * @return void
156 */
157 public function detect_active_plugins_and_themes_updates($upgrader_object, $options) {
158 if (empty($options) || !isset($options['type'])) return;
159
160 $should_purge_cache = false;
161 $skin = $upgrader_object->skin;
162 if ('plugin' === $options['type']) {
163 // A plugin is updated using the default update system (upgrader_overwrote_package is used for the upload method)
164 if (property_exists($skin, 'plugin_active') && $skin->plugin_active) {
165 $should_purge_cache = true;
166 }
167 } elseif ('theme' === $options['type']) {
168 $active_theme = get_stylesheet();
169 $parent_theme = get_template();
170 // A theme is updated using the upload system
171 if (isset($options['action']) && 'install' === $options['action'] && 'update-theme' === $skin->options['overwrite']) {
172 $updated_theme = $upgrader_object->result['destination_name'];
173 // Check if the theme is in use
174 if ($active_theme == $updated_theme || $parent_theme == $updated_theme) {
175 $should_purge_cache = true;
176 }
177 // A theme is updated using the classic update system
178 } elseif (isset($options['action']) && 'update' === $options['action'] && isset($options['themes']) && is_array($options['themes'])) {
179 // Check if the theme is in use
180 if (in_array($active_theme, $options['themes']) || in_array($parent_theme, $options['themes'])) {
181 $should_purge_cache = true;
182 }
183 }
184 }
185
186 /**
187 * Action executed when an active theme or plugin was updated
188 */
189 if ($should_purge_cache) do_action('wpo_active_plugin_or_theme_updated');
190
191 }
192
193 /**
194 * Sets a flag to indicate an import action is done, if needed
195 */
196 public function maybe_schedule_update_record_count_event() {
197 if (!wp_next_scheduled('wpo_update_record_count_event')) {
198 wp_schedule_single_event(time() + 60, 'wpo_update_record_count_event');
199 }
200 }
201
202 public function admin_page_wpo_images_smush() {
203 $options = Updraft_Smush_Manager()->get_smush_options();
204 $custom = 100 != $options['image_quality'] && 60 != $options['image_quality'] ? true : false;
205 $this->include_template('images/smush.php', false, array('smush_options' => $options, 'custom' => $custom, 'does_server_allows_local_webp_conversion' => $this->does_server_allows_local_webp_conversion()));
206 }
207
208 public static function instance() {
209 if (empty(self::$_instance)) {
210 self::$_instance = new self();
211 }
212 return self::$_instance;
213 }
214
215 public function get_optimizer() {
216 return WP_Optimizer::instance();
217 }
218
219 /**
220 * Get and instanciate WP_Optimize_Minify
221 *
222 * @return WP_Optimize_Minify
223 */
224 public function get_minify() {
225 return WP_Optimize_Minify::instance();
226 }
227
228 public function get_options() {
229 return WP_Optimize_Options::instance();
230 }
231
232 public function get_notices() {
233 return WP_Optimize_Notices::instance();
234 }
235
236 /**
237 * Returns instance if WPO_Page_Cache class.
238 *
239 * @return WPO_Page_Cache
240 */
241 public function get_page_cache() {
242 return WPO_Page_Cache::instance();
243 }
244
245 /**
246 * Returns instance if WP_Optimize_WebP class.
247 *
248 * @return WP_Optimize_WebP
249 */
250 public function get_webp_instance() {
251 return WP_Optimize_WebP::get_instance();
252 }
253
254 /**
255 * Detects if the platform is Kinsta or not
256 *
257 * @return bool Returns true if it is Kinsta platform, otherwise returns false
258 */
259 private function is_kinsta() {
260 return isset($_SERVER['KINSTA_CACHE_ZONE']);
261 }
262
263 /**
264 * Detects whether the server handles cache. eg. Nginx cache
265 */
266 public function does_server_handles_cache() {
267 return $this->is_kinsta();
268 }
269
270 /**
271 * Detects whether the server supports table optimization.
272 *
273 * Some servers prevent table optimization
274 * because InnoDB engine does not optimize table
275 * instead it drops tables and recreate them
276 * which results in elevated disk write operations
277 */
278 public function does_server_allows_table_optimization() {
279 return !$this->is_kinsta();
280 }
281
282 /**
283 * Detects whether the server supports local webp conversion tools
284 */
285 private function does_server_allows_local_webp_conversion() {
286 return !$this->is_kinsta();
287 }
288
289 /**
290 * Create instance of WP_Optimize_Browser_Cache.
291 *
292 * @return WP_Optimize_Browser_Cache
293 */
294 public function get_browser_cache() {
295 return WP_Optimize_Browser_Cache::instance();
296 }
297
298 /**
299 * Returns WP_Optimize_Database_Information instance.
300 *
301 * @return WP_Optimize_Database_Information
302 */
303 public function get_db_info() {
304 return WP_Optimize_Database_Information::instance();
305 }
306
307 /**
308 * Returns instance of WP_Optimize_Gzip_Compression.
309 *
310 * @return WP_Optimize_Gzip_Compression
311 */
312 public function get_gzip_compression() {
313 return WP_Optimize_Gzip_Compression::instance();
314 }
315
316 /**
317 * Create instance of WP_Optimize_Htaccess.
318 *
319 * @param string $htaccess_file absolute path to htaccess file, by default it use .htaccess in WordPress root directory.
320 * @return WP_Optimize_Htaccess
321 */
322 public static function get_htaccess($htaccess_file = '') {
323 return new WP_Optimize_Htaccess($htaccess_file);
324 }
325
326 /**
327 * Return instance of Updraft_Logger
328 *
329 * @return Updraft_Logger
330 */
331 public function get_logger() {
332 return Updraft_Logger::instance();
333 }
334
335 /**
336 * Check if the current page belongs to WP-Optimize.
337 *
338 * @return bool
339 */
340 public function is_wpo_page() {
341 $current_screen = get_current_screen();
342
343 return (bool) preg_match('/wp\-optimize/i', $current_screen->id);
344 }
345
346 /**
347 * Enqueue scripts and styles on WP-Optimize pages.
348 */
349 public function admin_enqueue_scripts() {
350 $enqueue_version = (defined('WP_DEBUG') && WP_DEBUG) ? WPO_VERSION.'.'.time() : WPO_VERSION;
351 $min_or_not = (defined('SCRIPT_DEBUG') && SCRIPT_DEBUG) ? '' : '.min';
352 $min_or_not_internal = (defined('SCRIPT_DEBUG') && SCRIPT_DEBUG) ? '' : '-'. str_replace('.', '-', WPO_VERSION). '.min';
353
354 // Register or enqueue common scripts
355 wp_register_script('wp-optimize-send-command', WPO_PLUGIN_URL.'js/send-command'.$min_or_not_internal.'.js', array(), $enqueue_version);
356 wp_localize_script('wp-optimize-send-command', 'wp_optimize_send_command_data', array('nonce' => wp_create_nonce('wp-optimize-ajax-nonce')));
357 wp_enqueue_style('wp-optimize-global', WPO_PLUGIN_URL.'css/wp-optimize-global'.$min_or_not_internal.'.css', array(), $enqueue_version);
358
359 // load scripts and styles only on WP-Optimize pages.
360 if (!$this->is_wpo_page()) return;
361
362 wp_enqueue_script('jquery-serialize-json', WPO_PLUGIN_URL.'js/serialize-json/jquery.serializejson'.$min_or_not.'.js', array('jquery'), $enqueue_version);
363
364 wp_register_script('updraft-queue-js', WPO_PLUGIN_URL.'js/queue'.$min_or_not_internal.'.js', array(), $enqueue_version);
365 wp_enqueue_script('wp-optimize-modal', WPO_PLUGIN_URL.'js/modal'.$min_or_not_internal.'.js', array('jquery', 'backbone', 'wp-util'), $enqueue_version);
366 wp_enqueue_script('wp-optimize-cache-js', WPO_PLUGIN_URL.'js/cache'.$min_or_not_internal.'.js', array('wp-optimize-send-command', 'smush-js'), $enqueue_version);
367 wp_enqueue_script('wp-optimize-admin-js', WPO_PLUGIN_URL.'js/wpoadmin'.$min_or_not_internal.'.js', array('jquery', 'updraft-queue-js', 'wp-optimize-send-command', 'smush-js', 'wp-optimize-modal', 'wp-optimize-cache-js'), $enqueue_version);
368 wp_enqueue_style('wp-optimize-admin-css', WPO_PLUGIN_URL.'css/wp-optimize-admin'.$min_or_not_internal.'.css', array(), $enqueue_version);
369 // Using tablesorter to help with organising the DB size on Table Information
370 // https://github.com/Mottie/tablesorter
371 wp_enqueue_script('tablesorter-js', WPO_PLUGIN_URL.'js/tablesorter/jquery.tablesorter'.$min_or_not.'.js', array('jquery', 'wp-optimize-send-command'), $enqueue_version);
372
373 wp_enqueue_script('tablesorter-widgets-js', WPO_PLUGIN_URL.'js/tablesorter/jquery.tablesorter.widgets'.$min_or_not.'.js', array('jquery'), $enqueue_version);
374
375 // wp_enqueue_style('tablesorter-css', WPO_PLUGIN_URL.'css/tablesorter/theme.default.min.css', array(), $enqueue_version);
376
377 $js_variables = $this->wpo_js_translations();
378 $js_variables['loggers_classes_info'] = $this->get_loggers_classes_info();
379
380 wp_localize_script('wp-optimize-admin-js', 'wpoptimize', $js_variables);
381
382 do_action('wpo_premium_scripts_styles', $min_or_not_internal, $min_or_not, $enqueue_version);
383 }
384
385 /**
386 * Enqueue any required front-end scripts
387 *
388 * @return void
389 */
390 public function frontend_enqueue_scripts() {
391 if (!current_user_can('manage_options') || !is_admin_bar_showing()) return;
392 $enqueue_version = (defined('WP_DEBUG') && WP_DEBUG) ? WPO_VERSION.'.'.time() : WPO_VERSION;
393 $min_or_not_internal = (defined('SCRIPT_DEBUG') && SCRIPT_DEBUG) ? '' : '-'. str_replace('.', '-', WPO_VERSION). '.min';
394
395 // Register or enqueue common scripts
396 wp_enqueue_style('wp-optimize-global', WPO_PLUGIN_URL.'css/wp-optimize-global'.$min_or_not_internal.'.css', array(), $enqueue_version);
397 }
398
399 /**
400 * Load Task Manager
401 */
402 public function get_task_manager() {
403 include_once(WPO_PLUGIN_MAIN_PATH.'vendor/team-updraft/common-libs/src/updraft-tasks/class-updraft-tasks-activation.php');
404
405 Updraft_Tasks_Activation::check_updates();
406
407 include_once(WPO_PLUGIN_MAIN_PATH . '/vendor/team-updraft/common-libs/src/updraft-tasks/class-updraft-task-meta.php');
408 include_once(WPO_PLUGIN_MAIN_PATH . '/vendor/team-updraft/common-libs/src/updraft-tasks/class-updraft-task-options.php');
409 include_once(WPO_PLUGIN_MAIN_PATH . '/vendor/team-updraft/common-libs/src/updraft-tasks/class-updraft-task.php');
410
411 include_once(WPO_PLUGIN_MAIN_PATH . '/includes/class-updraft-smush-task.php');
412 include_once(WPO_PLUGIN_MAIN_PATH . '/includes/class-updraft-smush-manager.php');
413
414 return Updraft_Smush_Manager();
415 }
416
417 /**
418 * Indicate whether we have an associated instance of WP-Optimize Premium or not.
419 *
420 * @returns Boolean
421 */
422 public static function is_premium() {
423 if (file_exists(WPO_PLUGIN_MAIN_PATH.'premium.php') && function_exists('WP_Optimize_Premium')) {
424 $wp_optimize_premium = WP_Optimize_Premium();
425 if (is_a($wp_optimize_premium, 'WP_Optimize_Premium')) return true;
426 }
427 return false;
428 }
429
430 /**
431 * Check if script running on Apache web server. $is_apache is set in wp-includes/vars.php. Also returns true if the server uses litespeed.
432 *
433 * @return bool
434 */
435 public function is_apache_server() {
436 global $is_apache;
437 return $is_apache;
438 }
439
440 /**
441 * Check if script running on IIS web server.
442 *
443 * @return bool
444 */
445 public function is_IIS_server() {
446 global $is_IIS, $is_iis7;
447 return $is_IIS || $is_iis7;
448 }
449
450 /**
451 * Check if Apache module or modules active.
452 *
453 * @param string|array $module - single Apache module name or list of Apache module names.
454 *
455 * @return bool|null - if null, the result was indeterminate
456 */
457 public function is_apache_module_loaded($module) {
458 if (!$this->is_apache_server()) return false;
459
460 if (!function_exists('apache_get_modules')) return null;
461
462 $module_loaded = true;
463
464 if (is_array($module)) {
465 foreach ($module as $single_module) {
466 if (!in_array($single_module, apache_get_modules())) {
467 $module_loaded = false;
468 break;
469 }
470 }
471 } else {
472 $module_loaded = in_array($module, apache_get_modules());
473 }
474
475 return $module_loaded;
476 }
477
478 /**
479 * Checks if this is the premium version and loads it. It also ensures that if the free version is installed then it is disabled with an appropriate error message.
480 */
481 public function plugins_loaded() {
482
483 if ($this->does_server_handles_cache()) {
484 add_filter('wp_optimize_admin_page_wpo_cache_tabs', array($this, 'filter_cache_tabs'), 99, 1);
485
486 // If newly migrated to server that handles cache, disable wpo cache
487 $cache = $this->get_page_cache();
488 if ($cache->is_enabled()) {
489 $cache->disable();
490 }
491 }
492
493 add_filter('robots_txt', array($this, 'robots_txt'), 99, 1);
494
495 // Run Premium loader if it exists
496 if (file_exists(WPO_PLUGIN_MAIN_PATH.'premium.php') && !class_exists('WP_Optimize_Premium')) {
497 include_once(WPO_PLUGIN_MAIN_PATH.'premium.php');
498 }
499
500 // load defaults
501 WP_Optimize()->get_options()->set_default_options();
502
503 // Initialize loggers.
504 $this->setup_loggers();
505
506 if ($this->is_active('premium') && false !== ($free_plugin = $this->is_active('free'))) {
507 if (!function_exists('deactivate_plugins')) include_once(ABSPATH.'wp-admin/includes/plugin.php');
508 deactivate_plugins($free_plugin);
509
510 // If WPO_ADVANCED_CACHE is defined, we empty advanced-cache.php to regenerate later. Otherwise it contains the path to free.
511 if (defined('WPO_ADVANCED_CACHE') && WPO_ADVANCED_CACHE) {
512 $advanced_cache_filename = trailingslashit(WP_CONTENT_DIR) . 'advanced-cache.php';
513
514 if (!is_file($advanced_cache_filename) && is_writable(dirname($advanced_cache_filename)) || (is_file($advanced_cache_filename) && is_writable($advanced_cache_filename))) {
515 file_put_contents($advanced_cache_filename, '');
516 }
517 }
518
519 // Registers the notice letting the user know it cannot be active if premium is active.
520 add_action('admin_notices', array($this, 'show_admin_notice_premium'));
521 return;
522 }
523
524 // Loads the task manager
525 $this->get_task_manager();
526
527 // Loads the language file.
528 load_plugin_textdomain('wp-optimize', false, dirname(plugin_basename(__FILE__)) . '/languages');
529
530 // Load page cache.
531 $this->get_page_cache();
532 $this->init_page_cache();
533
534 // Include minify
535 $this->get_minify();
536 $this->run_updates();
537
538 // Include WebP
539 $this->get_webp_instance();
540 }
541
542 /**
543 * Filter cache tabs (when it is Kinsta)
544 *
545 * @param array $tabs An array of tabs
546 *
547 * @return array $tabs An array of tabs
548 */
549 public function filter_cache_tabs($tabs) {
550 unset($tabs['preload']);
551 unset($tabs['advanced']);
552 unset($tabs['gzip']);
553 unset($tabs['settings']);
554 return $tabs;
555 }
556
557 /**
558 * Check whether one of free/Premium is active (whether it is this instance or not)
559 *
560 * @param String $which - 'free' or 'premium'
561 *
562 * @return String|Boolean - plugin path (if installed) or false if not
563 */
564 private function is_active($which = 'free') {
565 $active_plugins = $this->get_active_plugins();
566 foreach ($active_plugins as $file) {
567 if ('wp-optimize.php' == basename($file)) {
568 $plugin_dir = WP_PLUGIN_DIR.'/'.dirname($file);
569 if (('free' == $which && !file_exists($plugin_dir.'/premium.php')) || ('free' != $which && file_exists($plugin_dir.'/premium.php'))) return $file;
570 }
571 }
572 return false;
573 }
574
575 /**
576 * Gets an array of plugins active on either the current site, or site-wide
577 *
578 * @return Array - a list of plugin paths (relative to the plugin directory)
579 */
580 private function get_active_plugins() {
581
582 // Gets all active plugins on the current site
583 $active_plugins = get_option('active_plugins');
584
585 if (is_multisite()) {
586 $network_active_plugins = get_site_option('active_sitewide_plugins');
587 if (!empty($network_active_plugins)) {
588 $network_active_plugins = array_keys($network_active_plugins);
589 $active_plugins = array_merge($active_plugins, $network_active_plugins);
590 }
591 }
592
593 return $active_plugins;
594 }
595
596 /**
597 * This function checks whether a specific plugin is installed, and returns information about it
598 *
599 * @param string $name Specify "Plugin Name" to return details about it.
600 * @return array Returns an array of details such as if installed, the name of the plugin and if it is active.
601 */
602 public function is_installed($name) {
603
604 // Needed to have the 'get_plugins()' function
605 include_once(ABSPATH.'wp-admin/includes/plugin.php');
606
607 // Gets all plugins available
608 $get_plugins = get_plugins();
609
610 $active_plugins = $this->get_active_plugins();
611
612 $plugin_info = array();
613 $plugin_info['installed'] = false;
614 $plugin_info['active'] = false;
615
616 // Loops around each plugin available.
617 foreach ($get_plugins as $key => $value) {
618 // If the plugin name matches that of the specified name, it will gather details.
619 if ($value['Name'] != $name && $value['TextDomain'] != $name) continue;
620 $plugin_info['installed'] = true;
621 $plugin_info['name'] = $key;
622 $plugin_info['version'] = $value['Version'];
623 if (in_array($key, $active_plugins)) {
624 $plugin_info['active'] = true;
625 }
626 break;
627 }
628 return $plugin_info;
629 }
630
631 /**
632 * This is a notice to show users that premium is installed
633 */
634 public function show_admin_notice_premium() {
635 echo '<div id="wp-optimize-premium-installed-warning" class="error"><p>'.__('WP-Optimize (Free) has been de-activated, because WP-Optimize Premium is active.', 'wp-optimize').'</p></div>';
636 if (isset($_GET['activate'])) unset($_GET['activate']);
637 }
638
639 /**
640 * Show update to Premium notice for non-premium multisite.
641 */
642 public function show_multisite_update_to_premium_notice() {
643 if (!is_multisite() || self::is_premium()) return;
644
645 echo '<p><a href="'.$this->premium_version_link.'">'.__('New feature: WP-Optimize Premium can now optimize all sites within a multisite install, not just the main one.', 'wp-optimize').'</a></p>';
646 }
647
648 public function admin_init() {
649 $pagenow = $GLOBALS['pagenow'];
650
651 $this->register_template_directories();
652
653 if (('index.php' == $pagenow && current_user_can('update_plugins')) || ('index.php' == $pagenow && defined('WP_OPTIMIZE_FORCE_DASHNOTICE') && WP_OPTIMIZE_FORCE_DASHNOTICE)) {
654 $options = $this->get_options();
655
656 $dismissed_until = $options->get_option('dismiss_dash_notice_until', 0);
657
658 if (file_exists(WPO_PLUGIN_MAIN_PATH . '/index.html')) {
659 $installed = filemtime(WPO_PLUGIN_MAIN_PATH . '/index.html');
660 $installed_for = (time() - $installed);
661 }
662
663 if (($installed && time() > $dismissed_until && $installed_for > (14 * 86400) && !defined('WP_OPTIMIZE_NOADS_B')) || (defined('WP_OPTIMIZE_FORCE_DASHNOTICE') && WP_OPTIMIZE_FORCE_DASHNOTICE)) {
664 add_action('all_admin_notices', array($this, 'show_admin_notice_upgradead'));
665 }
666 }
667 $this->install_or_update_notice = $this->get_install_or_update_notice();
668 if ($this->is_wp_smush_installed()) {
669 add_filter('transient_wp-smush-conflict_check', array($this, 'modify_wp_smush_conflict_check'), 9, 1);
670 }
671 }
672
673 /**
674 * Checks whether the WP Smush plugin is active or not
675 *
676 * @return bool
677 */
678 private function is_wp_smush_installed() {
679 return is_plugin_active('wp-smushit/wp-smush.php');
680 }
681
682 /**
683 * Remove WPO plugin name from WP Smushit transient value
684 *
685 * @return array $active_plugins
686 */
687 public function modify_wp_smush_conflict_check($active_plugins) {
688 // This can be boolean value since it is return value of get_transient
689 if (!is_array($active_plugins)) return $active_plugins;
690
691 if (false !== ($key = array_search('WP-Optimize - Clean, Compress, Cache', $active_plugins))) {
692 unset($active_plugins[$key]);
693 }
694 return $active_plugins;
695 }
696
697 /**
698 * Get the install or update notice instance
699 *
700 * @return WP_Optimize_Install_Or_Update_Notice
701 */
702 public function get_install_or_update_notice() {
703 static $instance = null;
704 if (is_a($instance, 'WP_Optimize_Install_Or_Update_Notice')) return $instance;
705 $instance = new WP_Optimize_Install_Or_Update_Notice();
706 return $instance;
707 }
708
709 public function show_admin_notice_upgradead() {
710 $this->include_template('notices/thanks-for-using-main-dash.php');
711 }
712
713 public function capability_required() {
714 return apply_filters('wp_optimize_capability_required', 'manage_options');
715 }
716
717 public function wp_optimize_ajax_handler() {
718 $nonce = empty($_POST['nonce']) ? '' : $_POST['nonce'];
719
720 if (!wp_verify_nonce($nonce, 'wp-optimize-ajax-nonce') || empty($_POST['subaction'])) {
721 wp_send_json(array(
722 'result' => false,
723 'error_code' => 'security_check',
724 'error_message' => __('The security check failed; try refreshing the page.', 'wp-optimize')
725 ));
726 }
727
728 $subaction = $_POST['subaction'];
729 $data = isset($_POST['data']) ? $_POST['data'] : null;
730
731 if (!current_user_can($this->capability_required())) {
732 wp_send_json(array(
733 'result' => false,
734 'error_code' => 'security_check',
735 'error_message' => __('You are not allowed to run this command.', 'wp-optimize')
736 ));
737 }
738
739
740 // Currently the settings are only available to network admins.
741 if (is_multisite() && !current_user_can('manage_network_options')) {
742 /**
743 * Filters the commands allowed to the subsite admins. Other commands are only available to network admin. Only used in a multisite context.
744 */
745 $allowed_commands = apply_filters('wpo_multisite_allowed_commands', array('check_server_status', 'compress_single_image', 'restore_single_image'));
746 if (!in_array($subaction, $allowed_commands)) wp_send_json(array(
747 'result' => false,
748 'error_code' => 'update_failed',
749 'error_message' => __('Options can only be saved by network admin', 'wp-optimize')
750 ));
751 }
752
753 $options = $this->get_options();
754
755 $results = array();
756
757 // Some commands that are available via AJAX only.
758 if (in_array($subaction, array('dismiss_dash_notice_until', 'dismiss_season'))) {
759 $options->update_option($subaction, (time() + 366 * 86400));
760 } elseif (in_array($subaction, array('dismiss_page_notice_until', 'dismiss_notice'))) {
761 $options->update_option($subaction, (time() + 84 * 86400));
762 } elseif ('dismiss_review_notice' == $subaction) {
763 if (empty($data['dismiss_forever'])) {
764 $options->update_option($subaction, time() + 84*86400);
765 } else {
766 $options->update_option($subaction, 100 * (365.25 * 86400));
767 }
768 } else {
769
770 $commands = new WP_Optimize_Commands();
771 $minify_commands = new WP_Optimize_Minify_Commands();
772
773
774 if (self::is_premium()) {
775 $cache_commands = new WP_Optimize_Cache_Commands_Premium();
776 } else {
777 $cache_commands = new WP_Optimize_Cache_Commands();
778 }
779
780 // check if called command not in main commands class and exist in cache commands class then change class.
781 if (!is_callable(array($commands, $subaction)) && is_callable(array($minify_commands, $subaction))) {
782 $commands = $minify_commands;
783 }
784
785 // check if called command not in main commands class and exist in cache commands class then change class.
786 if (!is_callable(array($commands, $subaction)) && is_callable(array($cache_commands, $subaction))) {
787 $commands = $cache_commands;
788 }
789
790 if (!is_callable(array($commands, $subaction))) {
791 error_log("WP-Optimize: ajax_handler: no such command (".$subaction.")");
792 $results = array(
793 'result' => false,
794 'error_code' => 'command_not_found',
795 'error_message' => sprintf(__('The command "%s" was not found', 'wp-optimize'), $subaction)
796 );
797 } else {
798 $results = call_user_func(array($commands, $subaction), $data);
799
800 // clean status box content, it broke json sometimes.
801 if (isset($results['status_box_contents'])) {
802 $results['status_box_contents'] = str_replace(array("\n", "\t"), '', $results['status_box_contents']);
803 }
804
805 if (is_wp_error($results)) {
806 $results = array(
807 'result' => false,
808 'error_code' => $results->get_error_code(),
809 'error_message' => $results->get_error_message(),
810 'error_data' => $results->get_error_data(),
811 );
812 }
813
814 // if nothing was returned for some reason, set as result null.
815 if (empty($results)) {
816 $results = array(
817 'result' => null
818 );
819 }
820 }
821 }
822
823 $result = json_encode($results);
824
825 // Requires PHP 5.3+
826 $json_last_error = function_exists('json_last_error') ? json_last_error() : false;
827
828 // if json_encode returned error then return error.
829 if ($json_last_error) {
830 $result = array(
831 'result' => false,
832 'error_code' => $json_last_error,
833 'error_message' => 'json_encode error : '.$json_last_error,
834 'error_data' => '',
835 );
836
837 $result = json_encode($result);
838 }
839
840 echo $result;
841
842 die;
843 }
844
845 /**
846 * Returns array of translations used in javascript code.
847 *
848 * @return array
849 */
850 public function wpo_js_translations() {
851 return apply_filters('wpo_js_translations', array(
852 'automatic_backup_before_optimizations' => __('Automatic backup before optimizations', 'wp-optimize'),
853 'error_unexpected_response' => __('An unexpected response was received.', 'wp-optimize'),
854 'optimization_complete' => __('Optimization complete', 'wp-optimize'),
855 'with_warnings' => __('(with warnings - open the browser console for more details)', 'wp-optimize'),
856 'optimizing_table' => __('Optimizing table:', 'wp-optimize'),
857 'run_optimizations' => __('Run optimizations', 'wp-optimize'),
858 'table_optimization_timeout' => 120000,
859 'cancel' => __('Cancel', 'wp-optimize'),
860 'cancelling' => __('Cancelling...', 'wp-optimize'),
861 'enable' => __('Enable', 'wp-optimize'),
862 'disable' => __('Disable', 'wp-optimize'),
863 'please_select_settings_file' => __('Please, select settings file.', 'wp-optimize'),
864 'are_you_sure_you_want_to_remove_logging_destination' => __('Are you sure you want to remove this logging destination?', 'wp-optimize'),
865 'fill_all_settings_fields' => __('Before saving, you need to complete the currently incomplete settings (or remove them).', 'wp-optimize'),
866 'table_was_not_repaired' => __('%s was not repaired. For more details, please check the logs (configured in your logging destinations settings).', 'wp-optimize'),
867 'table_was_not_deleted' => __('%s was not deleted. For more details, please check your logs configured in logging destinations settings.', 'wp-optimize'),
868 'table_was_not_converted' => __('%s was not converted to InnoDB. For more details, please check your logs configured in logging destinations settings.', 'wp-optimize'),
869 'please_use_positive_integers' => __('Please use positive integers.', 'wp-optimize'),
870 'please_use_valid_values' => __('Please use valid values.', 'wp-optimize'),
871 'update' => __('Update', 'wp-optimize'),
872 'run_now' => __('Run now', 'wp-optimize'),
873 'starting_preload' => __('Started preload...', 'wp-optimize'),
874 'loading_urls' => __('Loading URLs...', 'wp-optimize'),
875 'current_cache_size' => __('Current cache size:', 'wp-optimize'),
876 'number_of_files' => __('Number of files:', 'wp-optimize'),
877 'toggle_info' => __('Show information', 'wp-optimize'),
878 'added_to_list' => __('Added to the list', 'wp-optimize'),
879 'added_notice' => __('The file was added to the list', 'wp-optimize'),
880 'save_notice' => __('Save the changes', 'wp-optimize'),
881 'page_refresh' => __('Refreshing the page to reflect changes...', 'wp-optimize'),
882 'settings_have_been_deleted_successfully' => __('WP-Optimize settings have been deleted successfully.', 'wp-optimize'),
883 'loading_data' => __('Loading data...', 'wp-optimize'),
884 'spinner_src' => esc_attr(admin_url('images/spinner-2x.gif')),
885 'settings_page_url' => is_multisite() ? network_admin_url('admin.php?page=wpo_settings') : admin_url('admin.php?page=wpo_settings'),
886 'sites' => $this->get_sites(),
887 'user_always_ignores_table_delete_warning' => (get_user_meta(get_current_user_id(), 'wpo-ignores-table-delete-warning', true)) ? true : false,
888 'post_meta_tweak_completed' => __('The tweak has been performed.', 'wp-optimize'),
889 'no_minified_assets' => __('No minified files are present', 'wp-optimize'),
890 'network_site_url' => network_site_url(),
891 'export_settings_file_name' => 'wpoptimize-settings-'.sanitize_title(get_bloginfo('name')).'.json',
892 'import_select_file' => __('You have not yet selected a file to import.', 'wp-optimize'),
893 'import_invalid_json_file' => __('Error: The chosen file is corrupt. Please choose a valid WP-Optimize export file.', 'wp-optimize'),
894 'importing' => __('Importing...', 'wp-optimize'),
895 'importing_data_from' => __('This will import data from:', 'wp-optimize'),
896 'exported_on' => __('Which was exported on:', 'wp-optimize'),
897 'continue_import' => __('Do you want to carry out the import?', 'wp-optimize'),
898
899 ));
900 }
901
902 /**
903 * Manages the admin bar menu for caching (currently page and minify)
904 */
905 public function cache_admin_bar($wp_admin_bar) {
906
907 $options = $this->get_options();
908 if (!$options->get_option('enable_cache_in_admin_bar', true)) return;
909
910 /**
911 * The "purge cache" menu items
912 *
913 * @param array $menu_items - The menu items, in the format required by $wp_admin_bar->add_menu()
914 * @param object $wp_admin_bar
915 */
916 $menu_items = apply_filters('wpo_cache_admin_bar_menu_items', array(), $wp_admin_bar);
917
918 if (empty($menu_items) || !is_array($menu_items)) return;
919
920 $wp_admin_bar->add_menu(array(
921 'id' => 'wpo_purge_cache',
922 'title' => __('Purge cache', 'wp-optimize'),
923 'href' => '#',
924 'meta' => array(
925 'title' => __('Purge cache', 'wp-optimize'),
926 ),
927 'parent' => false,
928 ));
929
930 foreach ($menu_items as $item) {
931 $wp_admin_bar->add_menu($item);
932 }
933 }
934
935 /**
936 * Add settings link on plugin page
937 *
938 * @param string $links Passing through the URL to be used within the HREF.
939 * @return string Returns the Links.
940 */
941 public function plugin_settings_link($links) {
942
943 $admin_page_url = $this->get_options()->admin_page_url();
944 $settings_page_url = $this->get_options()->admin_page_url('wpo_settings');
945
946 if (false == self::is_premium()) {
947 $premium_link = '<a href="' . esc_url($this->premium_version_link) . '" target="_blank">' . __('Premium', 'wp-optimize') . '</a>';
948 array_unshift($links, $premium_link);
949 }
950
951 $settings_link = '<a href="' . esc_url($settings_page_url) . '">' . __('Settings', 'wp-optimize') . '</a>';
952 array_unshift($links, $settings_link);
953
954 $optimize_link = '<a href="' . esc_url($admin_page_url) . '">' . __('Optimize', 'wp-optimize') . '</a>';
955 array_unshift($links, $optimize_link);
956 return $links;
957 }
958
959 /**
960 * Action wpo_tables_list_additional_column_data. Output button Optimize in the action column.
961 *
962 * @param string $content String for output to column
963 * @param object $table_info Object with table info.
964 *
965 * @return string
966 */
967 public function tables_list_additional_column_data($content, $table_info) {
968 if ($table_info->is_needing_repair) {
969 $content .= '<div class="wpo_button_wrap">'
970 . '<button class="button button-secondary run-single-table-repair" data-table="' . esc_attr($table_info->Name) . '">' . __('Repair', 'wp-optimize') . '</button>'
971 . '<img class="optimization_spinner visibility-hidden" src="' . esc_attr(admin_url('images/spinner-2x.gif')) . '" width="20" height="20" alt="...">'
972 . '<span class="optimization_done_icon dashicons dashicons-yes visibility-hidden"></span>'
973 . '</div>';
974 }
975
976 // table belongs to plugin.
977 if ($table_info->can_be_removed) {
978 $content .= '<div>'
979 . '<button class="button button-secondary run-single-table-delete" data-table="' . esc_attr($table_info->Name) . '">' . __('Remove', 'wp-optimize') . '</button>'
980 . '<img class="optimization_spinner visibility-hidden" src="' . esc_attr(admin_url('images/spinner-2x.gif')) . '" width="20" height="20" alt="...">'
981 . '<span class="optimization_done_icon dashicons dashicons-yes visibility-hidden"></span>'
982 . '</div>';
983 }
984
985 // Add option for MyISAM to InnoDB conversion.
986 if ('MyISAM' == $table_info->Engine) {
987 $content .= '<div class="wpo_button_convert wpo_button_wrap">'
988 . '<button class="button button-secondary toinnodb" data-table="' . esc_attr($table_info->Name) . '">' . __('Convert to InnoDB', 'wp-optimize') . '</button>'
989 . '<img class="optimization_spinner visibility-hidden" src="' . esc_attr(admin_url('images/spinner-2x.gif')) . '" width="20" height="20" alt="...">'
990 . '<span class="optimization_done_icon dashicons dashicons-yes visibility-hidden"></span>'
991 . '</div>';
992
993 }
994
995 return $content;
996 }
997
998 /**
999 * Initialize WP-Optimize page cache.
1000 */
1001 public function init_page_cache() {
1002 if ($this->get_page_cache()->config->get_option('enable_page_caching', false)) {
1003 $this->get_page_cache()->enable();
1004 }
1005 }
1006
1007 /**
1008 * Schedules cron event based on selected schedule type
1009 *
1010 * @return void
1011 */
1012 public function cron_activate() {
1013 $gmt_offset = (int) (3600 * get_option('gmt_offset'));
1014
1015 $options = $this->get_options();
1016
1017 if ($options->get_option('schedule') === false) {
1018 $options->set_default_options();
1019 } else {
1020 if ('true' == $options->get_option('schedule')) {
1021 if (!wp_next_scheduled('wpo_cron_event2')) {
1022 $schedule_type = $options->get_option('schedule-type', 'wpo_weekly');
1023
1024 // Backward compatibility
1025 if ('wpo_otherweekly' == $schedule_type) $schedule_type = 'wpo_fortnightly';
1026
1027 $this_time = (86400 * 7);
1028
1029 switch ($schedule_type) {
1030 case "wpo_daily":
1031 $this_time = 86400;
1032 break;
1033
1034 case "wpo_weekly":
1035 $this_time = (86400 * 7);
1036 break;
1037
1038 case "wpo_fortnightly":
1039 $this_time = (86400 * 14);
1040 break;
1041
1042 case "wpo_monthly":
1043 $this_time = (86400 * 30);
1044 break;
1045 }
1046
1047 add_action('wpo_cron_event2', array($this, 'cron_action'));
1048 $result = wp_schedule_event((current_time("timestamp", 0) + $this_time - $gmt_offset), $schedule_type, 'wpo_cron_event2');
1049 WP_Optimize()->log('running wp_schedule_event()');
1050 if (is_wp_error($result)) {
1051 $error_msg = $result->get_error_message();
1052 WP_Optimize()->log($error_msg);
1053 WP_Optimize()->log(print_r($result, true));
1054 } else {
1055 WP_Optimize()->log($result);
1056 }
1057 }
1058 }
1059 }
1060 }
1061
1062 /**
1063 * Clears all cron events
1064 *
1065 * @return void
1066 */
1067 public function wpo_cron_deactivate() {
1068 $cron_jobs = _get_cron_array();
1069 foreach ($cron_jobs as $job) {
1070 foreach (array_keys($job) as $hook) {
1071 if (preg_match('/^wpo_/', $hook)) wp_unschedule_hook($hook);
1072 }
1073 }
1074 }
1075
1076 /**
1077 * Scheduler public functions to update schedulers
1078 *
1079 * @param array $schedules An array of schedules being passed.
1080 * @return array An array of schedules being returned.
1081 */
1082 public function cron_schedules($schedules) {
1083 $schedules['wpo_daily'] = array('interval' => 86400, 'display' => 'Once Daily');
1084 $schedules['wpo_weekly'] = array('interval' => 86400 * 7, 'display' => 'Once Weekly');
1085 $schedules['wpo_fortnightly'] = array('interval' => 86400 * 14, 'display' => 'Once Every Fortnight');
1086 $schedules['wpo_monthly'] = array('interval' => 86400 * 30, 'display' => 'Once Every Month');
1087 return $schedules;
1088 }
1089
1090 /**
1091 * Returns count of overdue cron jobs.
1092 *
1093 * @return integer
1094 */
1095 public function howmany_overdue_crons() {
1096 $how_many_overdue = 0;
1097 if (function_exists('_get_cron_array') || (is_file(ABSPATH.WPINC.'/cron.php') && include_once(ABSPATH.WPINC.'/cron.php') && function_exists('_get_cron_array'))) {
1098 $crons = _get_cron_array();
1099 if (is_array($crons)) {
1100 $timenow = time();
1101 foreach ($crons as $jt => $job) {
1102 if ($jt < $timenow) {
1103 $how_many_overdue++;
1104 }
1105 }
1106 }
1107 }
1108 return $how_many_overdue;
1109 }
1110
1111 /**
1112 * Run updates on plugin activation.
1113 */
1114 public function run_updates() {
1115 include_once(WPO_PLUGIN_MAIN_PATH.'includes/class-wp-optimize-updates.php');
1116 WP_Optimize_Updates::check_updates();
1117 }
1118
1119 /**
1120 * Returns warning about overdue crons.
1121 *
1122 * @param int $howmany count of overdue crons
1123 * @return string
1124 */
1125 public function show_admin_warning_overdue_crons($howmany) {
1126 $ret = '<div class="updated below-h2"><p>';
1127 $ret .= '<strong>'.__('Warning', 'wp-optimize').':</strong> '.sprintf(__('WordPress has a number (%d) of scheduled tasks which are overdue. Unless this is a development site, this probably means that the scheduler in your WordPress install is not working.', 'wp-optimize'), $howmany).' <a href="'.apply_filters('wpoptimize_com_link', "https://getwpo.com/faqs/the-scheduler-in-my-wordpress-installation-is-not-working-what-should-i-do/").'">'.__('Read this page for a guide to possible causes and how to fix it.', 'wp-optimize').'</a>';
1128 $ret .= '</p></div>';
1129 return $ret;
1130 }
1131
1132 private function wp_normalize_path($path) {
1133 // Wp_normalize_path is not present before WP 3.9.
1134 if (function_exists('wp_normalize_path')) return wp_normalize_path($path);
1135 // Taken from WP 4.6.
1136 $path = str_replace('\\', '/', $path);
1137 $path = preg_replace('|(?<=.)/+|', '/', $path);
1138 if (':' === substr($path, 1, 1)) {
1139 $path = ucfirst($path);
1140 }
1141 return $path;
1142 }
1143
1144 public function get_templates_dir() {
1145 return apply_filters('wp_optimize_templates_dir', $this->wp_normalize_path(WPO_PLUGIN_MAIN_PATH.'templates'));
1146 }
1147
1148 public function get_templates_url() {
1149 return apply_filters('wp_optimize_templates_url', WPO_PLUGIN_URL.'/templates');
1150 }
1151
1152 /**
1153 * Return or output view content
1154 *
1155 * @param String $path - path to template, usually relative to templates/ within the WP-O directory
1156 * @param Boolean $return_instead_of_echo - what to do with the results
1157 * @param Array $extract_these - key/value pairs for substitution into the scope of the template
1158 *
1159 * @return String|Void
1160 */
1161 public function include_template($path, $return_instead_of_echo = false, $extract_these = array()) {
1162 if ($return_instead_of_echo) ob_start();
1163
1164 if (preg_match('#^([^/]+)/(.*)$#', $path, $matches)) {
1165 $prefix = $matches[1];
1166 $suffix = $matches[2];
1167 if (isset($this->template_directories[$prefix])) {
1168 $template_file = $this->template_directories[$prefix].'/'.$suffix;
1169 }
1170 }
1171
1172 if (!isset($template_file)) {
1173 $template_file = WPO_PLUGIN_MAIN_PATH.'templates/'.$path;
1174 }
1175
1176 $template_file = apply_filters('wp_optimize_template', $template_file, $path);
1177
1178 do_action('wp_optimize_before_template', $path, $template_file, $return_instead_of_echo, $extract_these);
1179
1180 if (!file_exists($template_file)) {
1181 error_log("WP Optimize: template not found: ".$template_file);
1182 echo __('Error:', 'wp-optimize').' '.__('template not found', 'wp-optimize')." (".$path.")";
1183 } else {
1184 extract($extract_these);
1185 // The following are useful variables which can be used in the template.
1186 // They appear as unused, but may be used in the $template_file.
1187 $wpdb = $GLOBALS['wpdb'];// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable -- $wpdb might be used in the included template
1188 $wp_optimize = $this;// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable -- $wp_optimize might be used in the included template
1189 $optimizer = $this->get_optimizer();// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable -- $optimizer might be used in the included template
1190 $options = $this->get_options();// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable -- $options might be used in the included template
1191 $wp_optimize_notices = $this->get_notices();// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable -- $wp_optimize_notices might be used in the included template
1192 include $template_file;
1193 }
1194
1195 do_action('wp_optimize_after_template', $path, $template_file, $return_instead_of_echo, $extract_these);
1196
1197 if ($return_instead_of_echo) return ob_get_clean();
1198 }
1199
1200 /**
1201 * Build a list of template directories (stored in self::$template_directories)
1202 */
1203 private function register_template_directories() {
1204
1205 $template_directories = array();
1206
1207 $templates_dir = $this->get_templates_dir();
1208
1209 if ($dh = opendir($templates_dir)) {
1210 while (($file = readdir($dh)) !== false) {
1211 if ('.' == $file || '..' == $file) continue;
1212 if (is_dir($templates_dir.'/'.$file)) {
1213 $template_directories[$file] = $templates_dir.'/'.$file;
1214 }
1215 }
1216 closedir($dh);
1217 }
1218
1219 // Optimal hook for most extensions to hook into.
1220 $this->template_directories = apply_filters('wp_optimize_template_directories', $template_directories);
1221
1222 }
1223
1224 /**
1225 * Message to debug
1226 *
1227 * @param string $message Message to insert into the log.
1228 * @param array $context array with variables used in $message like in template,
1229 * for ex.
1230 * $message = 'Hello {message}';
1231 * $context = ['message' => 'world']
1232 * 'Hello world' string will be saved in log.
1233 */
1234 public function log($message, $context = array()) {
1235 $this->get_logger()->debug($message, $context);
1236 }
1237
1238 /**
1239 * Format Bytes Into KB/MB
1240 *
1241 * @param mixed $bytes Number of bytes to be converted.
1242 * @param integer $decimals the number of decimal digits
1243 * @return integer return the correct format size.
1244 */
1245 public function format_size($bytes, $decimals = 2) {
1246 if (!is_numeric($bytes)) return __('N/A', 'wp-optimize');
1247
1248 if (1073741824 <= $bytes) {
1249 $bytes = number_format($bytes / 1073741824, $decimals) . ' GB';
1250 } elseif (1048576 <= $bytes) {
1251 $bytes = number_format($bytes / 1048576, $decimals) . ' MB';
1252 } elseif (1024 <= $bytes) {
1253 $bytes = number_format($bytes / 1024, $decimals) . ' KB';
1254 } elseif (1 < $bytes) {
1255 $bytes = $bytes . ' bytes';
1256 } elseif (1 == $bytes) {
1257 $bytes = $bytes . ' byte';
1258 } else {
1259 $bytes = '0 bytes';
1260 }
1261
1262 return $bytes;
1263 }
1264
1265 /**
1266 * Format a timestamp into a juman readable date time
1267 *
1268 * @param int $timestamp
1269 * @return string
1270 */
1271 public function format_date_time($timestamp) {
1272 return date_i18n(get_option('date_format').' @ '.get_option('time_format'), ($timestamp + get_option('gmt_offset') * 3600));
1273 }
1274
1275 /**
1276 * Executed this function on cron event.
1277 *
1278 * @return void
1279 */
1280 public function cron_action() {
1281
1282 $optimizer = $this->get_optimizer();
1283 $options = $this->get_options();
1284
1285 $this->log('WPO: Starting cron_action()');
1286 $options->update_option('last-optimized', time());
1287 if ('true' == $options->get_option('schedule')) {
1288 $this_options = $options->get_option('auto');
1289
1290 // Currently the output of the optimizations is not saved/used/logged.
1291 $optimizer->do_optimizations($this_options, 'auto');
1292 }
1293
1294 }
1295
1296 /**
1297 * Schedule cron tasks used by plugin.
1298 *
1299 * @return void
1300 */
1301 public function schedule_plugin_cron_tasks() {
1302 if (!wp_next_scheduled('wpo_weekly_cron_tasks')) {
1303 wp_schedule_event(current_time("timestamp", 0), 'weekly', 'wpo_weekly_cron_tasks');
1304 }
1305
1306 add_action('wpo_weekly_cron_tasks', array($this, 'do_weekly_cron_tasks'));
1307 }
1308
1309 /**
1310 * Do plugin background tasks.
1311 *
1312 * @return void
1313 */
1314 public function do_weekly_cron_tasks() {
1315 // add tasks here.
1316 $this->get_db_info()->update_plugin_json();
1317 }
1318
1319 /**
1320 * This will customize a URL with a correct Affiliate link
1321 * This function can be update to suit any URL as longs as the URL is passed
1322 *
1323 * @param String $url - URL to be check to see if it an updraftplus match.
1324 * @param String $text - Text to be entered within the href a tags.
1325 * @param String $html - Any specific HTML to be added.
1326 * @param String $class - Specify a class for the href (including the attribute label)
1327 * @param Boolean $return_instead_of_echo - if set, then the result will be returned, not echo-ed.
1328 *
1329 * @return String|void
1330 */
1331 public function wp_optimize_url($url, $text, $html = '', $class = '', $return_instead_of_echo = false) {
1332 // Check if the URL is UpdraftPlus.
1333 $url = $this->maybe_add_affiliate_params($url); // Return URL - check if there is HTML such as images.
1334 if ('' != $html) {
1335 $result = '<a '.$class.' href="'.esc_attr($url).'">'.$html.'</a>';
1336 } else {
1337 $result = '<a '.$class.' href="'.esc_attr($url).'">'.htmlspecialchars($text).'</a>';
1338 }
1339 if ($return_instead_of_echo) return $result;
1340 echo $result;
1341 }
1342
1343 /**
1344 * Get an URL with an eventual affiliate ID
1345 *
1346 * @param string $url
1347 * @return string
1348 */
1349 public function maybe_add_affiliate_params($url) {
1350 // Check if the URL is UpdraftPlus.
1351 if (false !== strpos($url, '//updraftplus.com')) {
1352 // Set URL with Affiliate ID.
1353 $url = add_query_arg(array('afref' => $this->get_notices()->get_affiliate_id()), $url);
1354
1355 // Apply filters.
1356 $url = apply_filters('wpoptimize_updraftplus_com_link', $url);
1357 }
1358 return apply_filters('wpoptimize_maybe_add_affiliate_params', $url);
1359 }
1360
1361 /**
1362 * Setup WPO logger(s)
1363 */
1364 public function setup_loggers() {
1365
1366 $logger = $this->get_logger();
1367 $loggers = $this->wpo_loggers();
1368
1369 if (!empty($loggers)) {
1370 foreach ($loggers as $_logger) {
1371 $logger->add_logger($_logger);
1372 }
1373 }
1374
1375 add_action('wp_optimize_after_optimizations', array($this, 'after_optimizations_logger_action'));
1376 }
1377
1378 /**
1379 * Run logger actions after all optimizations done
1380 */
1381 public function after_optimizations_logger_action() {
1382 $loggers = $this->get_logger()->get_loggers();
1383 if (!empty($loggers)) {
1384 foreach ($loggers as $logger) {
1385 if (is_a($logger, 'Updraft_Email_Logger')) {
1386 $logger->flush_log();
1387 }
1388 }
1389 }
1390 }
1391
1392 /**
1393 * Returns list of WPO loggers instances
1394 * Apply filter wp_optimize_loggers
1395 *
1396 * @return array
1397 */
1398 public function wpo_loggers() {
1399
1400 $loggers = array();
1401 $loggers_classes_by_id = array();
1402 $options_keys = array();
1403
1404 $loggers_classes = $this->get_loggers_classes();
1405
1406 foreach ($loggers_classes as $logger_class => $source) {
1407 $loggers_classes_by_id[strtolower($logger_class)] = $logger_class;
1408 }
1409
1410 $options = $this->get_options();
1411
1412 $saved_loggers = $options->get_option('logging');
1413 $logger_additional_options = $options->get_option('logging-additional');
1414
1415 // create loggers classes instances.
1416 if (!empty($saved_loggers)) {
1417 // check for previous version options format.
1418 $keys = array_keys($saved_loggers);
1419
1420 // if options stored in old format then reformat it.
1421 if (false == is_numeric($keys[0])) {
1422 $_saved_loggers = array();
1423 foreach ($saved_loggers as $logger_id => $enabled) {
1424 if ($enabled) {
1425 $_saved_loggers[] = $logger_id;
1426 }
1427 }
1428
1429 // fill email with admin.
1430 if (array_key_exists('updraft_email_logger', $saved_loggers) && $saved_loggers['updraft_email_logger']) {
1431 $logger_additional_options['updraft_email_logger'] = array(
1432 get_option('admin_email')
1433 );
1434 }
1435
1436 $saved_loggers = $_saved_loggers;
1437 }
1438
1439 foreach ($saved_loggers as $i => $logger_id) {
1440
1441 if (!array_key_exists($logger_id, $loggers_classes_by_id)) continue;
1442
1443 $logger_class = $loggers_classes_by_id[$logger_id];
1444
1445 $logger = new $logger_class();
1446
1447 $logger_options = $logger->get_options_list();
1448
1449 if (!empty($logger_options)) {
1450 foreach (array_keys($logger_options) as $option_name) {
1451 if (array_key_exists($option_name, $options_keys)) {
1452 $options_keys[$option_name]++;
1453 } else {
1454 $options_keys[$option_name] = 0;
1455 }
1456
1457 $option_value = isset($logger_additional_options[$option_name][$options_keys[$option_name]]) ? $logger_additional_options[$option_name][$options_keys[$option_name]] : '';
1458
1459 // if options in old format then get correct value.
1460 if ('' === $option_value && array_key_exists($logger_id, $logger_additional_options)) {
1461 $option_value = array_shift($logger_additional_options[$logger_id]);
1462 }
1463
1464 $logger->set_option($option_name, $option_value);
1465 }
1466 }
1467
1468 // check if logger is active.
1469 $active = (!is_array($logger_additional_options) || (array_key_exists('active', $logger_additional_options) && empty($logger_additional_options['active'][$i]))) ? false : true;
1470
1471 if ($active) {
1472 $logger->enable();
1473 } else {
1474 $logger->disable();
1475 }
1476
1477 $loggers[] = $logger;
1478 }
1479 }
1480
1481 $loggers = apply_filters('wp_optimize_loggers', $loggers);
1482
1483 return $loggers;
1484 }
1485
1486 /**
1487 * Returns associative array with logger class name in a key and path to class file in a value.
1488 *
1489 * @return array
1490 */
1491 public function get_loggers_classes() {
1492 $loggers_classes = array(
1493 'Updraft_PHP_Logger' => WPO_PLUGIN_MAIN_PATH . 'includes/class-updraft-php-logger.php',
1494 'Updraft_Email_Logger' => WPO_PLUGIN_MAIN_PATH . 'includes/class-updraft-email-logger.php',
1495 'Updraft_Ring_Logger' => WPO_PLUGIN_MAIN_PATH . 'includes/class-updraft-ring-logger.php'
1496 );
1497
1498 $loggers_classes = apply_filters('wp_optimize_loggers_classes', $loggers_classes);
1499
1500 if (!empty($loggers_classes)) {
1501 foreach ($loggers_classes as $logger_class => $logger_file) {
1502 if (!class_exists($logger_class)) {
1503 if (is_file($logger_file)) {
1504 include_once($logger_file);
1505 }
1506 }
1507 }
1508 }
1509
1510 return $loggers_classes;
1511 }
1512
1513 /**
1514 * Returns information about all loggers classes.
1515 *
1516 * @return array
1517 */
1518 public function get_loggers_classes_info() {
1519 $loggers_classes = $this->get_loggers_classes();
1520
1521 $loggers_classes_info = array();
1522
1523 if (!empty($loggers_classes)) {
1524 foreach (array_keys($loggers_classes) as $logger_class_name) {
1525
1526 if (!class_exists($logger_class_name)) continue;
1527
1528 $logger_id = strtolower($logger_class_name);
1529 $logger_class = new $logger_class_name();
1530
1531 $loggers_classes_info[$logger_id] = array(
1532 'description' => $logger_class->get_description(),
1533 'available' => $logger_class->is_available(),
1534 'allow_multiple' => $logger_class->is_allow_multiple(),
1535 'options' => $logger_class->get_options_list()
1536 );
1537 }
1538 }
1539
1540 return $loggers_classes_info;
1541 }
1542
1543 /**
1544 * Returns true if optimization works in multisite mode
1545 *
1546 * @return boolean
1547 */
1548 public function is_multisite_mode() {
1549 return (is_multisite() && self::is_premium());
1550 }
1551
1552 /**
1553 * Returns true if current user can run optimizations.
1554 *
1555 * @return bool
1556 */
1557 public function can_run_optimizations() {
1558 // we don't check permissions for cron jobs.
1559 if (defined('DOING_CRON') && DOING_CRON) return true;
1560
1561 if (self::is_premium() && false == user_can(get_current_user_id(), 'wpo_run_optimizations')) return false;
1562 return true;
1563 }
1564
1565 /**
1566 * Returns true if current user can manage plugin options.
1567 *
1568 * @return bool
1569 */
1570 public function can_manage_options() {
1571 if (self::is_premium() && false == user_can(get_current_user_id(), 'wpo_manage_settings')) return false;
1572 return true;
1573 }
1574
1575 /**
1576 * CHeck if current user can purge the cache.
1577 *
1578 * @return bool
1579 */
1580 public function can_purge_the_cache() {
1581 if (self::is_premium()) {
1582 return WP_Optimize_Premium()->can_purge_the_cache();
1583 }
1584
1585 return true;
1586 }
1587
1588 /**
1589 * Returns list of all sites in multisite
1590 *
1591 * @return array
1592 */
1593 public function get_sites() {
1594 $sites = array();
1595 // check if function get_sites exists (since 4.6.0) else use wp_get_sites.
1596 if (function_exists('get_sites')) {
1597 $sites = get_sites(array('network_id' => null, 'deleted' => 0, 'number' => 999999));
1598 } elseif (function_exists('wp_get_sites')) {
1599 $sites = wp_get_sites(array('network_id' => null, 'deleted' => 0, 'limit' => 999999));
1600 }
1601 return $sites;
1602 }
1603
1604 /**
1605 * Returns script memory limit in megabytes.
1606 *
1607 * @param bool $memory_limit
1608 * @return int
1609 */
1610 public function get_memory_limit($memory_limit = false) {
1611 // Returns in megabytes
1612 if (false == $memory_limit) $memory_limit = ini_get('memory_limit');
1613 $memory_limit = rtrim($memory_limit);
1614
1615 return $this->return_bytes($memory_limit);
1616 }
1617
1618 /**
1619 * Returns free memory in bytes.
1620 *
1621 * @return int
1622 */
1623 public function get_free_memory() {
1624 return $this->get_memory_limit() - memory_get_usage();
1625 }
1626
1627 /**
1628 * Checks PHP memory_limit and WP_MAX_MEMORY_LIMIT values and return minimal.
1629 *
1630 * @return int memory limit in bytes.
1631 */
1632 public function get_script_memory_limit() {
1633 $memory_limit = $this->get_memory_limit();
1634
1635 if (defined('WP_MAX_MEMORY_LIMIT')) {
1636 $wp_memory_limit = $this->get_memory_limit(WP_MAX_MEMORY_LIMIT);
1637
1638 if ($wp_memory_limit > 0 && $wp_memory_limit < $memory_limit) {
1639 $memory_limit = $wp_memory_limit;
1640 }
1641 }
1642
1643 return $memory_limit;
1644 }
1645
1646 /**
1647 * Returns max packet size for database.
1648 *
1649 * @return int|string
1650 */
1651 public function get_max_packet_size() {
1652 global $wpdb;
1653 static $mp = 0;
1654
1655 if ($mp > 0) return $mp;
1656
1657 $mp = (int) $wpdb->get_var("SELECT @@session.max_allowed_packet");
1658 // Default to 1MB
1659 $mp = (is_numeric($mp) && $mp > 0) ? $mp : 1048576;
1660 // 32MB
1661 if ($mp < 33554432) {
1662 $save = $wpdb->show_errors(false);
1663 @$wpdb->query("SET GLOBAL max_allowed_packet=33554432");// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
1664 $wpdb->show_errors($save);
1665
1666 $mp = (int) $wpdb->get_var("SELECT @@session.max_allowed_packet");
1667 // Default to 1MB
1668 $mp = (is_numeric($mp) && $mp > 0) ? $mp : 1048576;
1669 }
1670
1671 return $mp;
1672 }
1673
1674 /**
1675 * Converts shorthand memory notation value to bytes.
1676 * From http://php.net/manual/en/function.ini-get.php
1677 *
1678 * @param string $val shorthand memory notation value.
1679 */
1680 public function return_bytes($val) {
1681 $val = trim($val);
1682 $last = strtolower($val[strlen($val)-1]);
1683 $val = (int) $val;
1684 switch ($last) {
1685 case 'g':
1686 $val *= 1024;
1687 // no break
1688 case 'm':
1689 $val *= 1024;
1690 // no break
1691 case 'k':
1692 $val *= 1024;
1693 }
1694
1695 return $val;
1696 }
1697
1698 /**
1699 * Log fatal errors to defined log destinations.
1700 */
1701 public function log_fatal_errors() {
1702 $last_error = error_get_last();
1703
1704 if (isset($last_error['type']) && E_ERROR === $last_error['type']) {
1705 $this->get_logger()->critical($last_error['message']);
1706 }
1707 }
1708
1709 /**
1710 * Close browser connection and continue script work. - Taken from UpdraftPlus
1711 *
1712 * @param array $txt Response to browser; this must be JSON (or if not, alter the Content-Type header handling below)
1713 * @return void
1714 */
1715 public function close_browser_connection($txt = '') {
1716 if (!headers_sent()) {
1717 // Close browser connection so that it can resume AJAX polling
1718 header('Content-Length: '.(empty($txt) ? '0' : 4+strlen($txt)));
1719 header('Connection: close');
1720 header('Content-Encoding: none');
1721 }
1722
1723 if (session_id()) session_write_close();
1724 echo "\r\n\r\n";
1725 echo $txt;
1726 // These two added - 19-Feb-15 - started being required on local dev machine, for unknown reason (probably some plugin that started an output buffer).
1727 $ob_level = ob_get_level();
1728 while ($ob_level > 0) {
1729 ob_end_flush();
1730 $ob_level--;
1731 }
1732 flush();
1733 if (function_exists('fastcgi_finish_request')) fastcgi_finish_request();
1734 }
1735
1736 /**
1737 * Get the current theme's style.css headers
1738 *
1739 * @return array|WP_Error
1740 */
1741 public function get_stylesheet_headers() {
1742 static $headers;
1743 if (isset($headers)) return $headers;
1744
1745 $style = get_template_directory_uri() . '/style.css';
1746
1747 /**
1748 * Filters wp_remote_get parameters, when checking if browser cache is enabled.
1749 *
1750 * @param array $request_params Default parameters
1751 */
1752 $request_params = apply_filters('wpoptimize_get_stylesheet_headers_args', array('timeout' => 10));
1753
1754 // trying to load style.css.
1755 $response = wp_remote_get($style, $request_params);
1756
1757 if (is_a($response, 'WP_Error')) return $response;
1758
1759 $headers = wp_remote_retrieve_headers($response);
1760
1761 if (is_a($headers, 'Requests_Utility_CaseInsensitiveDictionary')) {
1762 $headers = $headers->getAll();
1763 }
1764
1765 return $headers;
1766 }
1767
1768 /**
1769 * Try to change PHP script time limit.
1770 */
1771 public function change_time_limit() {
1772 $time_limit = (defined('WP_OPTIMIZE_SET_TIME_LIMIT') && WP_OPTIMIZE_SET_TIME_LIMIT > 15) ? WP_OPTIMIZE_SET_TIME_LIMIT : 1800;
1773
1774 // Try to reduce the chances of PHP self-terminating via reaching max_execution_time.
1775 @set_time_limit($time_limit); // phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
1776 }
1777
1778 /**
1779 * Does the request come from UDC
1780 *
1781 * @return boolean
1782 */
1783 public function is_updraft_central_request() {
1784 return defined('UPDRAFTCENTRAL_COMMAND') && UPDRAFTCENTRAL_COMMAND;
1785 }
1786
1787 /**
1788 * Does the data need to be included in this request. Currently only true if the request is made from UpdraftCentral.
1789 *
1790 * @return boolean
1791 */
1792 public function template_should_include_data() {
1793 /**
1794 * Filters wether data should be included in certain templates or not.
1795 */
1796 return apply_filters('wpo_template_should_include_data', $this->is_updraft_central_request());
1797 }
1798
1799 /**
1800 * Load the templates for the modal window
1801 */
1802 public function load_modal_template() {
1803 $this->include_template('modal.php');
1804 }
1805
1806 /**
1807 * Delete transients and semaphores data from options table.
1808 */
1809 public function delete_transients_and_semaphores() {
1810 global $wpdb;
1811
1812 $masks = array(
1813 'updraft_locked_wpo_%',
1814 'updraft_unlocked_wpo_%',
1815 'updraft_last_lock_time_wpo_%',
1816 'updraft_semaphore_wpo_%',
1817 'wpo_locked_%',
1818 'wpo_unlocked_%',
1819 'wpo_last_lock_time_%',
1820 'wpo_semaphore_%',
1821 '_transient_timeout_wpo_%',
1822 '_transient_wpo_%',
1823 'updraft_lock_wpo_%',
1824 );
1825
1826 $where_parts = array();
1827 foreach ($masks as $mask) {
1828 $where_parts[] = "(`option_name` LIKE '{$mask}')";
1829 }
1830
1831 $wpdb->query("DELETE FROM {$wpdb->options} WHERE " . join(' OR ', $where_parts));
1832 }
1833
1834 /**
1835 * Prevents bots from indexing plugins list
1836 */
1837 public function robots_txt($output) {
1838 $upload_dir = wp_upload_dir();
1839 $path = parse_url($upload_dir['baseurl']);
1840 $output .= "\nDisallow: " . str_replace($path['scheme'].'://'.$path['host'], '', $upload_dir['baseurl']) . "/wpo-plugins-tables-list.json\n";
1841 return $output;
1842 }
1843 }
1844
1845 /**
1846 * Plugin activation actions.
1847 */
1848 function wpo_activation_actions() {
1849 // If plugin activated by not a Network Administrator then deactivate plugin and show message.
1850 if (is_multisite() && !is_network_admin()) {
1851 deactivate_plugins(plugin_basename(__FILE__));
1852 wp_die(__('Only Network Administrator can activate WP-Optimize plugin.', 'wp-optimize').
1853 ' <a href="'.admin_url('plugins.php').'">'.__('go back', 'wp-optimize').'</a>');
1854 }
1855
1856 // On activation, check if last-optimized option exists. If not, add 'newly-activated' option.
1857 if (!WP_Optimize()->get_options()->get_option('last-optimized', false)) {
1858 WP_Optimize()->get_options()->update_option('newly-activated', true);
1859 }
1860
1861 WP_Optimize()->get_options()->set_default_options();
1862 WP_Optimize()->get_minify()->plugin_activate();
1863
1864 WP_Optimize()->get_gzip_compression()->restore();
1865 WP_Optimize()->get_browser_cache()->restore();
1866
1867 if (!class_exists('Updraft_Tasks_Activation')) require_once(WPO_PLUGIN_MAIN_PATH . 'vendor/team-updraft/common-libs/src/updraft-tasks/class-updraft-tasks-activation.php');
1868 Updraft_Tasks_Activation::init_db();
1869 Updraft_Tasks_Activation::reinstall_if_needed();
1870
1871 // run premium activation actions.
1872 if (file_exists(WPO_PLUGIN_MAIN_PATH.'premium.php')) {
1873 if (!class_exists('WP_Optimize_Premium')) {
1874 include_once(WPO_PLUGIN_MAIN_PATH.'premium.php');
1875 }
1876 WP_Optimize_Premium()->plugin_activation_actions();
1877 }
1878 }
1879
1880 /**
1881 * Plugin deactivation actions.
1882 */
1883 function wpo_deactivation_actions() {
1884 WP_Optimize()->wpo_cron_deactivate();
1885 WP_Optimize()->get_page_cache()->disable();
1886 WP_Optimize()->get_minify()->plugin_deactivate();
1887 WP_Optimize()->get_gzip_compression()->disable();
1888 WP_Optimize()->get_browser_cache()->disable();
1889 }
1890
1891 function wpo_cron_deactivate() {
1892 WP_Optimize()->log('running wpo_cron_deactivate()');
1893 wp_clear_scheduled_hook('wpo_cron_event2');
1894 wp_clear_scheduled_hook('wpo_weekly_cron_tasks');
1895 }
1896
1897 /**
1898 * Plugin uninstall actions.
1899 */
1900 function wpo_uninstall_actions() {
1901 WP_Optimize()->get_gzip_compression()->disable();
1902 WP_Optimize()->get_browser_cache()->disable();
1903 WP_Optimize()->get_options()->delete_all_options();
1904 WP_Optimize()->get_minify()->plugin_uninstall();
1905 WP_Optimize()->get_options()->wipe_settings();
1906 WP_Optimize()->delete_transients_and_semaphores();
1907 }
1908
1909 function WP_Optimize() {
1910 return WP_Optimize::instance();
1911 }
1912
1913 endif;
1914
1915 $GLOBALS['wp_optimize'] = WP_Optimize();
1916