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

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

2,403 lines 82.3 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.1.11
7 Author: David Anderson, Ruhani Rabin, Team Updraft
8 Author URI: https://updraftplus.com
9 Text Domain: wp-optimize
10 Domain Path: /languages
11 License: GPLv2 or later
12 */
13
14 if (!defined('ABSPATH')) die('No direct access allowed');
15
16 // Check to make sure if WP_Optimize is already call and returns.
17 if (!class_exists('WP_Optimize')) :
18 define('WPO_VERSION', '3.1.11');
19 define('WPO_PLUGIN_URL', plugin_dir_url(__FILE__));
20 define('WPO_PLUGIN_MAIN_PATH', plugin_dir_path(__FILE__));
21 define('WPO_PREMIUM_NOTIFICATION', false);
22 define('WPO_MINIFY_PHP_VERSION_MET', version_compare(PHP_VERSION, '5.4', '>=') ? true : false);
23
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 protected static $_optimizer_instance = null;
34
35 protected static $_options_instance = null;
36
37 protected static $_minify_instance = null;
38
39 protected static $_notices_instance = null;
40
41 protected static $_logger_instance = null;
42
43 protected static $_browser_cache = null;
44
45 protected static $_db_info = null;
46
47 protected static $_cache = null;
48
49 protected static $_gzip_compression = null;
50
51 /**
52 * Class constructor
53 */
54 public function __construct() {
55
56 // Checks if premium is installed along with plugins needed.
57 add_action('plugins_loaded', array($this, 'plugins_loaded'), 1);
58
59 register_activation_hook(__FILE__, 'wpo_activation_actions');
60 register_deactivation_hook(__FILE__, 'wpo_deactivation_actions');
61 register_uninstall_hook(__FILE__, 'wpo_uninstall_actions');
62
63 add_action('admin_init', array($this, 'admin_init'));
64 add_action('admin_menu', array($this, 'admin_menu'));
65 add_action('admin_bar_menu', array($this, 'cache_admin_bar'), 100, 1);
66
67 add_filter("plugin_action_links_".plugin_basename(__FILE__), array($this, 'plugin_settings_link'));
68 add_action('wpo_cron_event2', array($this, 'cron_action'));
69 add_filter('cron_schedules', array($this, 'cron_schedules'));
70
71 if (!$this->get_options()->get_option('installed-for', false)) $this->get_options()->update_option('installed-for', time());
72
73 if (!self::is_premium()) {
74 add_action('auto_option_settings', array($this->get_options(), 'auto_option_settings'));
75 }
76
77 add_action('admin_enqueue_scripts', array($this, 'admin_enqueue_scripts'));
78
79 add_action('wp_enqueue_scripts', array($this, 'frontend_enqueue_scripts'));
80
81 add_action('wp_ajax_wp_optimize_ajax', array($this, 'wp_optimize_ajax_handler'));
82
83 // Show update to Premium notice for non-premium multisite.
84 add_action('wpo_additional_options', array($this, 'show_multisite_update_to_premium_notice'));
85
86 // Action column (show repair button if need).
87 add_filter('wpo_tables_list_additional_column_data', array($this, 'tables_list_additional_column_data'), 15, 2);
88
89 /**
90 * Add action for display Images > Compress images tab.
91 */
92 add_action('wp_optimize_admin_page_wpo_images_smush', array($this, 'admin_page_wpo_images_smush'));
93
94 include_once(WPO_PLUGIN_MAIN_PATH.'includes/updraftcentral.php');
95
96 include_once(WPO_PLUGIN_MAIN_PATH.'includes/backward-compatibility-functions.php');
97
98 register_shutdown_function(array($this, 'log_fatal_errors'));
99
100 $this->schedule_plugin_cron_tasks();
101
102 add_action('wpo_admin_before_closing_wrap', array($this, 'load_modal_template'), 20);
103
104 add_action('upgrader_process_complete', array($this, 'detect_active_plugins_and_themes_updates'), 10, 2);
105 }
106
107 /**
108 * Detect when an active plugin or theme is updated, and trigger an action
109 *
110 * @param object $upgrader_object
111 * @param array $options
112 * @return void
113 */
114 public function detect_active_plugins_and_themes_updates($upgrader_object, $options) {
115 $should_purge_cache = false;
116 $skin = $upgrader_object->skin;
117 if ('plugin' === $options['type']) {
118 // A plugin is updated using the default update system (upgrader_overwrote_package is used for the upload method)
119 if (property_exists($skin, 'plugin_active') && $skin->plugin_active) {
120 $should_purge_cache = true;
121 }
122 } elseif ('theme' === $options['type']) {
123 $active_theme = get_stylesheet();
124 $parent_theme = get_template();
125 // A theme is updated using the upload system
126 if ('install' === $options['action'] && 'update-theme' === $skin->options['overwrite']) {
127 $updated_theme = $upgrader_object->result['destination_name'];
128 // Check if the theme is in use
129 if ($active_theme == $updated_theme || $parent_theme == $updated_theme) {
130 $should_purge_cache = true;
131 }
132 // A theme is updated using the classic update system
133 } elseif ('update' === $options['action']) {
134 // Check if the theme is in use
135 if (in_array($active_theme, $options['themes']) || in_array($parent_theme, $options['themes'])) {
136 $should_purge_cache = true;
137 }
138 }
139 }
140
141 /**
142 * Action executed when an active theme or plugin was updated
143 */
144 if ($should_purge_cache) do_action('wpo_active_plugin_or_theme_updated');
145
146 }
147
148 public function admin_page_wpo_images_smush() {
149 $options = Updraft_Smush_Manager()->get_smush_options();
150 $custom = 100 == $options['image_quality'] || 90 == $options['image_quality'] ? false : true;
151 $this->include_template('images/smush.php', false, array('smush_options' => $options, 'custom' => $custom));
152 }
153
154 public static function instance() {
155 if (empty(self::$_instance)) {
156 self::$_instance = new self();
157 }
158 return self::$_instance;
159 }
160
161 public static function get_optimizer() {
162 if (empty(self::$_optimizer_instance)) {
163 if (!class_exists('WP_Optimizer')) include_once(WPO_PLUGIN_MAIN_PATH.'includes/class-wp-optimizer.php');
164 self::$_optimizer_instance = new WP_Optimizer();
165 }
166 return self::$_optimizer_instance;
167 }
168
169 /**
170 * Get and instanciate WP_Optimize_Minify
171 *
172 * @return WP_Optimize_Minify
173 */
174 public function get_minify() {
175 if (empty(self::$_minify_instance)) {
176 if (!class_exists('WP_Optimize_Minify')) {
177 include_once WPO_PLUGIN_MAIN_PATH.'minify/class-wp-optimize-minify.php';
178 }
179 self::$_minify_instance = new WP_Optimize_Minify();
180 }
181 return self::$_minify_instance;
182 }
183
184 public static function get_options() {
185 if (empty(self::$_options_instance)) {
186 if (!class_exists('WP_Optimize_Options')) include_once(WPO_PLUGIN_MAIN_PATH.'includes/class-wp-optimize-options.php');
187 self::$_options_instance = new WP_Optimize_Options();
188 }
189 return self::$_options_instance;
190 }
191
192 public static function get_notices() {
193 if (empty(self::$_notices_instance)) {
194 if (!class_exists('WP_Optimize_Notices')) include_once(WPO_PLUGIN_MAIN_PATH.'includes/wp-optimize-notices.php');
195 self::$_notices_instance = new WP_Optimize_Notices();
196 }
197 return self::$_notices_instance;
198 }
199
200 /**
201 * Returns instance if WPO_Page_Cache class.
202 *
203 * @return WPO_Page_Cache
204 */
205 public function get_page_cache() {
206 if (!class_exists('WPO_Page_Cache')) include_once(WPO_PLUGIN_MAIN_PATH.'cache/class-wpo-page-cache.php');
207
208 return WPO_Page_Cache::instance();
209 }
210
211 /**
212 * Create instance of WP_Optimize_Browser_Cache.
213 *
214 * @return WP_Optimize_Browser_Cache
215 */
216 public static function get_browser_cache() {
217 if (empty(self::$_browser_cache)) {
218 if (!class_exists('WP_Optimize_Browser_Cache')) include_once(WPO_PLUGIN_MAIN_PATH.'includes/class-wp-optimize-browser-cache.php');
219 self::$_browser_cache = new WP_Optimize_Browser_Cache();
220 }
221 return self::$_browser_cache;
222 }
223
224 /**
225 * Returns WP_Optimize_Database_Information instance.
226 *
227 * @return WP_Optimize_Database_Information
228 */
229 public function get_db_info() {
230 if (empty(self::$_db_info)) {
231 if (!class_exists('WP_Optimize_Database_Information')) include_once(WPO_PLUGIN_MAIN_PATH.'includes/wp-optimize-database-information.php');
232 self::$_db_info = new WP_Optimize_Database_Information();
233 }
234 return self::$_db_info;
235 }
236
237 /**
238 * Returns instance of WP_Optimize_Gzip_Compression.
239 *
240 * @return WP_Optimize_Gzip_Compression
241 */
242 static public function get_gzip_compression() {
243 if (empty(self::$_gzip_compression)) {
244 if (!class_exists('WP_Optimize_Gzip_Compression')) include_once(WPO_PLUGIN_MAIN_PATH.'includes/class-wp-optimize-gzip-compression.php');
245 self::$_gzip_compression = new WP_Optimize_Gzip_Compression();
246 }
247 return self::$_gzip_compression;
248 }
249
250 /**
251 * Create instance of WP_Optimize_Htaccess.
252 *
253 * @param string $htaccess_file absolute path to htaccess file, by default it use .htaccess in WordPress root directory.
254 * @return WP_Optimize_Htaccess
255 */
256 public static function get_htaccess($htaccess_file = '') {
257 if (!class_exists('WP_Optimize_Cache')) {
258 include_once(WPO_PLUGIN_MAIN_PATH . '/includes/class-wp-optimize-htaccess.php');
259 }
260
261 return new WP_Optimize_Htaccess($htaccess_file);
262 }
263
264 /**
265 * Return instance of Updraft_Logger
266 *
267 * @return Updraft_Logger
268 */
269 public static function get_logger() {
270 if (empty(self::$_logger_instance)) {
271 include_once(WPO_PLUGIN_MAIN_PATH.'includes/class-updraft-logger.php');
272 self::$_logger_instance = new Updraft_Logger();
273 }
274 return self::$_logger_instance;
275 }
276
277 /**
278 * Check if the current page belongs to WP-Optimize.
279 *
280 * @return bool
281 */
282 public function is_wpo_page() {
283 $current_screen = get_current_screen();
284
285 return (bool) preg_match('/wp\-optimize/i', $current_screen->id);
286 }
287
288 /**
289 * Enqueue scripts and styles on WP-Optimize pages.
290 */
291 public function admin_enqueue_scripts() {
292 $enqueue_version = (defined('WP_DEBUG') && WP_DEBUG) ? WPO_VERSION.'.'.time() : WPO_VERSION;
293 $min_or_not = (defined('SCRIPT_DEBUG') && SCRIPT_DEBUG) ? '' : '.min';
294 $min_or_not_internal = (defined('SCRIPT_DEBUG') && SCRIPT_DEBUG) ? '' : '-'. str_replace('.', '-', WPO_VERSION). '.min';
295
296 // Register or enqueue common scripts
297 wp_register_script('wp-optimize-send-command', WPO_PLUGIN_URL.'js/send-command'.$min_or_not_internal.'.js', array(), $enqueue_version);
298 wp_localize_script('wp-optimize-send-command', 'wp_optimize_send_command_data', array('nonce' => wp_create_nonce('wp-optimize-ajax-nonce')));
299 wp_enqueue_style('wp-optimize-global', WPO_PLUGIN_URL.'css/wp-optimize-global'.$min_or_not_internal.'.css', array(), $enqueue_version);
300
301 // load scripts and styles only on WP-Optimize pages.
302 if (!$this->is_wpo_page()) return;
303
304 wp_enqueue_script('jquery-serialize-json', WPO_PLUGIN_URL.'js/serialize-json/jquery.serializejson'.$min_or_not.'.js', array('jquery'), $enqueue_version);
305
306 wp_register_script('updraft-queue-js', WPO_PLUGIN_URL.'js/queue'.$min_or_not_internal.'.js', array(), $enqueue_version);
307 wp_enqueue_script('wp-optimize-modal', WPO_PLUGIN_URL.'js/modal'.$min_or_not_internal.'.js', array('jquery', 'backbone', 'wp-util'), $enqueue_version);
308 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);
309 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'), $enqueue_version);
310 wp_enqueue_style('wp-optimize-admin-css', WPO_PLUGIN_URL.'css/wp-optimize-admin'.$min_or_not_internal.'.css', array(), $enqueue_version);
311 // Using tablesorter to help with organising the DB size on Table Information
312 // https://github.com/Mottie/tablesorter
313 wp_enqueue_script('tablesorter-js', WPO_PLUGIN_URL.'js/tablesorter/jquery.tablesorter'.$min_or_not.'.js', array('jquery', 'wp-optimize-send-command'), $enqueue_version);
314
315 wp_enqueue_script('tablesorter-widgets-js', WPO_PLUGIN_URL.'js/tablesorter/jquery.tablesorter.widgets'.$min_or_not.'.js', array('jquery'), $enqueue_version);
316
317 // wp_enqueue_style('tablesorter-css', WPO_PLUGIN_URL.'css/tablesorter/theme.default.min.css', array(), $enqueue_version);
318
319 $js_variables = $this->wpo_js_translations();
320 $js_variables['loggers_classes_info'] = $this->get_loggers_classes_info();
321
322 wp_localize_script('wp-optimize-admin-js', 'wpoptimize', $js_variables);
323
324 do_action('wpo_premium_scripts_styles', $min_or_not_internal, $min_or_not, $enqueue_version);
325 }
326
327 /**
328 * Enqueue any required front-end scripts
329 *
330 * @return void
331 */
332 public function frontend_enqueue_scripts() {
333 if (!current_user_can('manage_options') || !is_admin_bar_showing()) return;
334 $enqueue_version = (defined('WP_DEBUG') && WP_DEBUG) ? WPO_VERSION.'.'.time() : WPO_VERSION;
335 $min_or_not_internal = (defined('SCRIPT_DEBUG') && SCRIPT_DEBUG) ? '' : '-'. str_replace('.', '-', WPO_VERSION). '.min';
336
337 // Register or enqueue common scripts
338 wp_enqueue_style('wp-optimize-global', WPO_PLUGIN_URL.'css/wp-optimize-global'.$min_or_not_internal.'.css', array(), $enqueue_version);
339 }
340
341 /**
342 * Load Task Manager
343 */
344 public function get_task_manager() {
345 include_once(WPO_PLUGIN_MAIN_PATH.'vendor/team-updraft/common-libs/src/updraft-tasks/class-updraft-tasks-activation.php');
346
347 Updraft_Tasks_Activation::check_updates();
348
349 include_once(WPO_PLUGIN_MAIN_PATH . '/vendor/team-updraft/common-libs/src/updraft-tasks/class-updraft-task-meta.php');
350 include_once(WPO_PLUGIN_MAIN_PATH . '/vendor/team-updraft/common-libs/src/updraft-tasks/class-updraft-task-options.php');
351 include_once(WPO_PLUGIN_MAIN_PATH . '/vendor/team-updraft/common-libs/src/updraft-tasks/class-updraft-task.php');
352
353 include_once(WPO_PLUGIN_MAIN_PATH . '/includes/class-updraft-smush-task.php');
354 include_once(WPO_PLUGIN_MAIN_PATH . '/includes/class-updraft-smush-manager.php');
355
356 return Updraft_Smush_Manager();
357 }
358
359 /**
360 * Indicate whether we have an associated instance of WP-Optimize Premium or not.
361 *
362 * @returns Boolean
363 */
364 public static function is_premium() {
365 if (file_exists(WPO_PLUGIN_MAIN_PATH.'premium.php') && function_exists('WP_Optimize_Premium')) {
366 $wp_optimize_premium = WP_Optimize_Premium();
367 if (is_a($wp_optimize_premium, 'WP_Optimize_Premium')) return true;
368 }
369 return false;
370 }
371
372 /**
373 * 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.
374 *
375 * @return bool
376 */
377 public function is_apache_server() {
378 global $is_apache;
379 return $is_apache;
380 }
381
382 /**
383 * Check if script running on IIS web server.
384 *
385 * @return bool
386 */
387 public function is_IIS_server() {
388 global $is_IIS, $is_iis7;
389 return $is_IIS || $is_iis7;
390 }
391
392 /**
393 * Check if Apache module or modules active.
394 *
395 * @param string|array $module - single Apache module name or list of Apache module names.
396 *
397 * @return bool|null - if null, the result was indeterminate
398 */
399 public function is_apache_module_loaded($module) {
400 if (!$this->is_apache_server()) return false;
401
402 if (!function_exists('apache_get_modules')) return null;
403
404 $module_loaded = true;
405
406 if (is_array($module)) {
407 foreach ($module as $single_module) {
408 if (!in_array($single_module, apache_get_modules())) {
409 $module_loaded = false;
410 break;
411 }
412 }
413 } else {
414 $module_loaded = in_array($module, apache_get_modules());
415 }
416
417 return $module_loaded;
418 }
419
420 /**
421 * 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.
422 */
423 public function plugins_loaded() {
424
425 if (is_multisite()) {
426 add_action('network_admin_menu', array($this, 'admin_menu'));
427 }
428
429 add_filter('robots_txt', array($this, 'robots_txt'), 99, 1);
430
431 // Run Premium loader if it exists
432 if (file_exists(WPO_PLUGIN_MAIN_PATH.'premium.php') && !class_exists('WP_Optimize_Premium')) {
433 include_once(WPO_PLUGIN_MAIN_PATH.'premium.php');
434 }
435
436 // load defaults
437 WP_Optimize()->get_options()->set_default_options();
438
439 // Initialize loggers.
440 $this->setup_loggers();
441
442 if ($this->is_active('premium') && false !== ($free_plugin = $this->is_active('free'))) {
443 if (!function_exists('deactivate_plugins')) include_once(ABSPATH.'wp-admin/includes/plugin.php');
444 deactivate_plugins($free_plugin);
445
446 // If WPO_ADVANCED_CACHE is defined, we empty advanced-cache.php to regenerate later. Otherwise it contains the path to free.
447 if (defined('WPO_ADVANCED_CACHE') && WPO_ADVANCED_CACHE) {
448 $advanced_cache_filename = trailingslashit(WP_CONTENT_DIR) . 'advanced-cache.php';
449
450 if (!is_file($advanced_cache_filename) && is_writable(dirname($advanced_cache_filename)) || (is_file($advanced_cache_filename) && is_writable($advanced_cache_filename))) {
451 file_put_contents($advanced_cache_filename, '');
452 }
453 }
454
455 // Registers the notice letting the user know it cannot be active if premium is active.
456 add_action('admin_notices', array($this, 'show_admin_notice_premium'));
457 return;
458 }
459
460 // Loads the task manager
461 $this->get_task_manager();
462
463 // Loads the language file.
464 load_plugin_textdomain('wp-optimize', false, dirname(plugin_basename(__FILE__)) . '/languages');
465
466 // Load page cache.
467 $this->get_page_cache();
468 $this->init_page_cache();
469
470 // Include minify
471 $this->get_minify();
472 $this->run_updates();
473
474 if (defined('WPO_USE_WEBP_CONVERSION') && true === WPO_USE_WEBP_CONVERSION) {
475 // Include webP
476 include_once WPO_PLUGIN_MAIN_PATH . 'webp/class-wp-optimize-webp.php';
477 }
478 }
479
480 /**
481 * Check whether one of free/Premium is active (whether it is this instance or not)
482 *
483 * @param String $which - 'free' or 'premium'
484 *
485 * @return String|Boolean - plugin path (if installed) or false if not
486 */
487 private function is_active($which = 'free') {
488 $active_plugins = $this->get_active_plugins();
489 foreach ($active_plugins as $file) {
490 if ('wp-optimize.php' == basename($file)) {
491 $plugin_dir = WP_PLUGIN_DIR.'/'.dirname($file);
492 if (('free' == $which && !file_exists($plugin_dir.'/premium.php')) || ('free' != $which && file_exists($plugin_dir.'/premium.php'))) return $file;
493 }
494 }
495 return false;
496 }
497
498 /**
499 * Gets an array of plugins active on either the current site, or site-wide
500 *
501 * @return Array - a list of plugin paths (relative to the plugin directory)
502 */
503 private function get_active_plugins() {
504
505 // Gets all active plugins on the current site
506 $active_plugins = get_option('active_plugins');
507
508 if (is_multisite()) {
509 $network_active_plugins = get_site_option('active_sitewide_plugins');
510 if (!empty($network_active_plugins)) {
511 $network_active_plugins = array_keys($network_active_plugins);
512 $active_plugins = array_merge($active_plugins, $network_active_plugins);
513 }
514 }
515
516 return $active_plugins;
517 }
518
519 /**
520 * This function checks whether a specific plugin is installed, and returns information about it
521 *
522 * @param string $name Specify "Plugin Name" to return details about it.
523 * @return array Returns an array of details such as if installed, the name of the plugin and if it is active.
524 */
525 public function is_installed($name) {
526
527 // Needed to have the 'get_plugins()' function
528 include_once(ABSPATH.'wp-admin/includes/plugin.php');
529
530 // Gets all plugins available
531 $get_plugins = get_plugins();
532
533 $active_plugins = $this->get_active_plugins();
534
535 $plugin_info = array();
536 $plugin_info['installed'] = false;
537 $plugin_info['active'] = false;
538
539 // Loops around each plugin available.
540 foreach ($get_plugins as $key => $value) {
541 // If the plugin name matches that of the specified name, it will gather details.
542 if ($value['Name'] != $name && $value['TextDomain'] != $name) continue;
543 $plugin_info['installed'] = true;
544 $plugin_info['name'] = $key;
545 $plugin_info['version'] = $value['Version'];
546 if (in_array($key, $active_plugins)) {
547 $plugin_info['active'] = true;
548 }
549 break;
550 }
551 return $plugin_info;
552 }
553
554 /**
555 * This is a notice to show users that premium is installed
556 */
557 public function show_admin_notice_premium() {
558 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>';
559 if (isset($_GET['activate'])) unset($_GET['activate']);
560 }
561
562 /**
563 * Show update to Premium notice for non-premium multisite.
564 */
565 public function show_multisite_update_to_premium_notice() {
566 if (!is_multisite() || self::is_premium()) return;
567
568 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>';
569 }
570
571 public function admin_init() {
572 $pagenow = $GLOBALS['pagenow'];
573
574 $this->register_template_directories();
575
576 if (('index.php' == $pagenow && current_user_can('update_plugins')) || ('index.php' == $pagenow && defined('WP_OPTIMIZE_FORCE_DASHNOTICE') && WP_OPTIMIZE_FORCE_DASHNOTICE)) {
577 $options = $this->get_options();
578
579 $dismissed_until = $options->get_option('dismiss_dash_notice_until', 0);
580
581 if (file_exists(WPO_PLUGIN_MAIN_PATH . '/index.html')) {
582 $installed = filemtime(WPO_PLUGIN_MAIN_PATH . '/index.html');
583 $installed_for = (time() - $installed);
584 }
585
586 if (($installed && time() > $dismissed_until && $installed_for > (14 * 86400) && !defined('WP_OPTIMIZE_NOADS_B')) || (defined('WP_OPTIMIZE_FORCE_DASHNOTICE') && WP_OPTIMIZE_FORCE_DASHNOTICE)) {
587 add_action('all_admin_notices', array($this, 'show_admin_notice_upgradead'));
588 }
589 }
590 $this->install_or_update_notice = $this->get_install_or_update_notice();
591 }
592
593 /**
594 * Get the install or update notice instance
595 *
596 * @return WP_Optimize_Install_Or_Update_Notice
597 */
598 private function get_install_or_update_notice() {
599 static $instance = null;
600 if (is_a($instance, 'WP_Optimize_Install_Or_Update_Notice')) return $instance;
601 include_once WPO_PLUGIN_MAIN_PATH . 'includes/class-wp-optimize-install-or-update-notice.php';
602 $instance = new WP_Optimize_Install_Or_Update_Notice();
603 return $instance;
604 }
605
606 public function show_admin_notice_upgradead() {
607 $this->include_template('notices/thanks-for-using-main-dash.php');
608 }
609
610 public function capability_required() {
611 return apply_filters('wp_optimize_capability_required', 'manage_options');
612 }
613
614 public function wp_optimize_ajax_handler() {
615 $nonce = empty($_POST['nonce']) ? '' : $_POST['nonce'];
616
617 if (!wp_verify_nonce($nonce, 'wp-optimize-ajax-nonce') || empty($_POST['subaction'])) {
618 wp_send_json(array(
619 'result' => false,
620 'error_code' => 'security_check',
621 'error_message' => __('The security check failed; try refreshing the page.', 'wp-optimize')
622 ));
623 }
624
625 $subaction = $_POST['subaction'];
626 $data = isset($_POST['data']) ? $_POST['data'] : null;
627
628 if (!current_user_can($this->capability_required())) {
629 wp_send_json(array(
630 'result' => false,
631 'error_code' => 'security_check',
632 'error_message' => __('You are not allowed to run this command.', 'wp-optimize')
633 ));
634 }
635
636
637 // Currently the settings are only available to network admins.
638 if (is_multisite() && !current_user_can('manage_network_options')) {
639 /**
640 * Filters the commands allowed to the subsite admins. Other commands are only available to network admin. Only used in a multisite context.
641 */
642 $allowed_commands = apply_filters('wpo_multisite_allowed_commands', array('check_server_status', 'compress_single_image', 'restore_single_image'));
643 if (!in_array($subaction, $allowed_commands)) wp_send_json(array(
644 'result' => false,
645 'error_code' => 'update_failed',
646 'error_message' => __('Options can only be saved by network admin', 'wp-optimize')
647 ));
648 }
649
650 $options = $this->get_options();
651
652 $results = array();
653
654 // Some commands that are available via AJAX only.
655 if (in_array($subaction, array('dismiss_dash_notice_until', 'dismiss_season'))) {
656 $options->update_option($subaction, (time() + 366 * 86400));
657 } elseif (in_array($subaction, array('dismiss_page_notice_until', 'dismiss_notice'))) {
658 $options->update_option($subaction, (time() + 84 * 86400));
659 } elseif ('dismiss_review_notice' == $subaction) {
660 if (empty($data['dismiss_forever'])) {
661 $options->update_option($subaction, time() + 84*86400);
662 } else {
663 $options->update_option($subaction, 100 * (365.25 * 86400));
664 }
665 } else {
666 // Other commands, available for any remote method.
667 if (!class_exists('WP_Optimize_Commands')) include_once(WPO_PLUGIN_MAIN_PATH . 'includes/class-commands.php');
668 if (!class_exists('WP_Optimize_Minify_Commands')) include_once(WPO_PLUGIN_MAIN_PATH . 'minify/class-wp-optimize-minify-commands.php');
669 if (!class_exists('WP_Optimize_Cache_Commands')) include_once(WPO_PLUGIN_MAIN_PATH . 'cache/class-cache-commands.php');
670
671 $commands = new WP_Optimize_Commands();
672 $minify_commands = new WP_Optimize_Minify_Commands();
673
674
675 if (self::is_premium()) {
676 if (!class_exists('WP_Optimize_Cache_Commands_Premium')) include_once(WPO_PLUGIN_MAIN_PATH . 'cache/class-cache-commands-premium.php');
677 $cache_commands = new WP_Optimize_Cache_Commands_Premium();
678 } else {
679 $cache_commands = new WP_Optimize_Cache_Commands();
680 }
681
682 // check if called command not in main commands class and exist in cache commands class then change class.
683 if (!is_callable(array($commands, $subaction)) && is_callable(array($minify_commands, $subaction))) {
684 $commands = $minify_commands;
685 }
686
687 // check if called command not in main commands class and exist in cache commands class then change class.
688 if (!is_callable(array($commands, $subaction)) && is_callable(array($cache_commands, $subaction))) {
689 $commands = $cache_commands;
690 }
691
692 if (!is_callable(array($commands, $subaction))) {
693 error_log("WP-Optimize: ajax_handler: no such command (".$subaction.")");
694 $results = array(
695 'result' => false,
696 'error_code' => 'command_not_found',
697 'error_message' => sprintf(__('The command "%s" was not found', 'wp-optimize'), $subaction)
698 );
699 } else {
700 $results = call_user_func(array($commands, $subaction), $data);
701
702 // clean status box content, it broke json sometimes.
703 if (isset($results['status_box_contents'])) {
704 $results['status_box_contents'] = str_replace(array("\n", "\t"), '', $results['status_box_contents']);
705 }
706
707 if (is_wp_error($results)) {
708 $results = array(
709 'result' => false,
710 'error_code' => $results->get_error_code(),
711 'error_message' => $results->get_error_message(),
712 'error_data' => $results->get_error_data(),
713 );
714 }
715
716 // if nothing was returned for some reason, set as result null.
717 if (empty($results)) {
718 $results = array(
719 'result' => null
720 );
721 }
722 }
723 }
724
725 $result = json_encode($results);
726
727 // Requires PHP 5.3+
728 $json_last_error = function_exists('json_last_error') ? json_last_error() : false;
729
730 // if json_encode returned error then return error.
731 if ($json_last_error) {
732 $result = array(
733 'result' => false,
734 'error_code' => $json_last_error,
735 'error_message' => 'json_encode error : '.$json_last_error,
736 'error_data' => '',
737 );
738
739 $result = json_encode($result);
740 }
741
742 echo $result;
743
744 die;
745 }
746
747 /**
748 * Builds the Tabs that should be displayed
749 *
750 * @return array Returns all tabs specified
751 */
752 public function get_tabs($page) {
753 // define tabs for pages.
754 $pages_tabs = array(
755 'WP-Optimize' => array(
756 'optimize' => __('Optimizations', 'wp-optimize'),
757 'tables' => __('Tables', 'wp-optimize'),
758 'settings' => __('Settings', 'wp-optimize'),
759 ),
760 'wpo_images' => array(
761 'smush' => __('Compress images', 'wp-optimize'),
762 'unused' => __('Unused images and sizes', 'wp-optimize').'<span class="menu-pill premium-only">Premium</span>',
763 'lazyload' => __('Lazy-load', 'wp-optimize').'<span class="menu-pill premium-only">Premium</span>',
764 ),
765 'wpo_cache' => array(
766 'cache' => __('Page cache', 'wp-optimize'),
767 'preload' => __('Preload', 'wp-optimize'),
768 'advanced' => __('Advanced settings', 'wp-optimize'),
769 'gzip' => __('Gzip compression', 'wp-optimize'),
770 'settings' => __('Static file headers', 'wp-optimize') // Adds a settings tab
771 ),
772 'wpo_minify' => array(
773 "status" => __('Minify status', 'wp-optimize'),
774 "js" => __('JavaScript', 'wp-optimize').'<span class="menu-pill disabled hidden">'.__('Disabled', 'wp-optimize').'</span>',
775 "css" => __('CSS', 'wp-optimize').'<span class="menu-pill disabled hidden">'.__('Disabled', 'wp-optimize').'</span>',
776 "font" => __('Fonts', 'wp-optimize'),
777 "settings" => __('Settings', 'wp-optimize'),
778 "advanced" => __('Advanced', 'wp-optimize')
779 ),
780 'wpo_settings' => array(
781 'settings' => array(
782 'title' => __('Settings', 'wp-optimize'),
783 ),
784 ),
785 'wpo_support' => array('support' => __('Support / FAQs', 'wp-optimize')),
786 'wpo_mayalso' => array('may_also' => __('Premium / Plugin family', 'wp-optimize')),
787 );
788
789 $tabs = (array_key_exists($page, $pages_tabs)) ? $pages_tabs[$page] : array();
790
791 return apply_filters('wp_optimize_admin_page_'.$page.'_tabs', $tabs);
792 }
793
794 /**
795 * Main page structure.
796 */
797 public function display_admin() {
798 $capability_required = $this->capability_required();
799
800 if (!current_user_can($capability_required) || (!$this->can_run_optimizations() && !$this->can_manage_options())) {
801 echo "Permission denied.";
802 return;
803 }
804
805 $this->register_admin_content();
806
807 echo '<div id="wp-optimize-wrap">';
808
809 $this->include_template('admin-page-header.php', false, array('show_notices' => !($this->get_install_or_update_notice()->show_current_notice())));
810
811 do_action('wpo_admin_after_header');
812
813 echo '<div id="actions-results-area"></div>';
814
815 $pages = $this->get_submenu_items();
816
817 foreach ($pages as $page) {
818 if (isset($page['menu_slug'])) {
819 $this->display_admin_page($page['menu_slug']);
820 }
821 }
822
823 do_action('wpo_admin_before_closing_wrap');
824
825 // closes main plugin wrapper div. #wp-optimize-wrap
826 echo '</div><!-- END #wp-optimize-wrap -->';
827
828 }
829
830 /**
831 * Prepare and display admin page with $page id.
832 *
833 * @param string $page wp-optimize page id i.e. dashboard, database, images, cache, ...
834 */
835 public function display_admin_page($page) {
836
837 $active_page = !empty($_REQUEST['page']) ? $_REQUEST['page'] : '';
838
839 echo '<div class="wpo-page' . ($active_page == $page ? ' active' : '') . '" data-whichpage="'.$page.'">';
840
841 echo '<div class="wpo-main">';
842
843 // get defined tabs for $page.
844 $tabs = $this->get_tabs($page);
845
846 // if no tabs defined for $page then use $page as $active_tab for load template, doing related actions e t.c.
847 if (empty($tabs)) {
848 $active_tab = $page;
849 } else {
850 $tab_keys = array_keys($tabs);
851 $default_tab = apply_filters('wp_optimize_admin_'.$page.'_default_tab', $tab_keys[0]);
852 $active_tab = isset($_GET['tab']) ? substr($_GET['tab'], 12) : $default_tab;
853 if (!in_array($active_tab, array_keys($tabs))) $active_tab = $default_tab;
854 }
855
856 do_action('wp_optimize_admin_page_'.$page, $active_tab);
857
858 // if tabs defined then display
859 if (!empty($tabs)) {
860 $this->include_template('admin-page-header-tabs.php', false, array('page' => $page, 'active_tab' => $active_tab, 'tabs' => $tabs, 'wpo_is_premium' => self::is_premium()));
861 }
862
863 foreach ($tabs as $tab_id => $tab_description) {
864 // output wrap div for tab with id #wp-optimize-nav-tab-contents-'.$page.'-'.$tab_id
865 echo '<div class="wp-optimize-nav-tab-contents" id="wp-optimize-nav-tab-'.$page.'-'.$tab_id.'-contents" '.(($tab_id == $active_tab) ? '' : 'style="display:none;"').'>';
866
867 echo '<div class="postbox wpo-tab-postbox">';
868 // call action for generate tab content.
869
870 do_action('wp_optimize_admin_page_'.$page.'_'.$tab_id);
871
872 // closes postbox.
873 echo '</div><!-- END .postbox -->';
874 // closes tab wrapper.
875 echo '</div><!-- END .wp-optimize-nav-tab-contents -->';
876 }
877
878 echo '</div><!-- END .wpo-main -->';
879
880 do_action('wp_optimize_admin_after_page_'.$page, $active_tab);
881
882 echo '</div><!-- END .wpo-page -->';
883
884 }
885
886 /**
887 * Define required actions for admin pages.
888 */
889 public function register_admin_content() {
890
891 do_action('wp_optimize_register_admin_content');
892
893 /**
894 * SETTINGS
895 */
896 add_action('wp_optimize_admin_page_wpo_settings_settings', array($this, 'output_dashboard_settings_tab'), 20);
897
898 /**
899 * Premium / other plugins
900 */
901 add_action('wp_optimize_admin_page_wpo_mayalso_may_also', array($this, 'output_dashboard_other_plugins_tab'), 20);
902
903 /**
904 * DATABASE
905 */
906 add_action('wp_optimize_admin_page_WP-Optimize_optimize', array($this, 'output_database_optimize_tab'), 20);
907 add_action('wp_optimize_admin_page_WP-Optimize_tables', array($this, 'output_database_tables_tab'), 20);
908 add_action('wp_optimize_admin_page_WP-Optimize_settings', array($this, 'output_database_settings_tab'), 20);
909
910 /**
911 * CACHE
912 */
913
914 add_action('wp_optimize_admin_page_wpo_cache_cache', array($this, 'output_page_cache_tab'), 20);
915 add_action('wp_optimize_admin_page_wpo_cache_preload', array($this, 'output_page_cache_preload_tab'), 20);
916 add_action('wp_optimize_admin_page_wpo_cache_advanced', array($this, 'output_page_cache_advanced_tab'), 20);
917 add_action('wp_optimize_admin_page_wpo_cache_gzip', array($this, 'output_cache_gzip_tab'), 20);
918 add_action('wp_optimize_admin_page_wpo_cache_settings', array($this, 'output_cache_settings_tab'), 20);
919 add_action('wpo_page_cache_advanced_settings', array($this, 'output_cloudflare_settings'), 20);
920 /**
921 * SUPPORT
922 */
923 add_action('wp_optimize_admin_page_wpo_support_support', array($this, 'output_dashboard_support_tab'), 20);
924 // Display Support page.
925
926 if (!self::is_premium()) {
927 /**
928 * Add action for display Images > Unused images and sizes tab.
929 */
930 add_action('wp_optimize_admin_page_wpo_images_unused', array($this, 'admin_page_wpo_images_unused'));
931
932 /**
933 * Add action for display Dashboard > Lazyload tab.
934 */
935 add_action('wp_optimize_admin_page_wpo_images_lazyload', array($this, 'admin_page_wpo_images_lazyload'));
936 }
937 }
938
939 /**
940 * Database settings
941 */
942 public function output_database_settings_tab() {
943
944 if ($this->can_manage_options()) {
945 $this->include_template('database/settings.php');
946 } else {
947 $this->prevent_manage_options_info();
948 }
949 }
950
951 /**
952 * Dashboard settings
953 */
954 public function output_dashboard_settings_tab() {
955 $options = $this->get_options();
956
957 if ('POST' == $_SERVER['REQUEST_METHOD']) {
958 // Nonce check.
959 check_admin_referer('wpo_settings');
960
961 $output = $options->save_settings($_POST);
962
963 if (isset($_POST['wp-optimize-settings'])) {
964 // save settings request sent.
965 $output = $options->save_settings($_POST);
966 }
967
968 $this->wpo_render_output_messages($output);
969 }
970
971 if ($this->can_manage_options()) {
972 $this->include_template('settings/settings.php');
973 } else {
974 $this->prevent_manage_options_info();
975 }
976 }
977
978 /**
979 * Dashboard support tab
980 */
981 public function output_dashboard_support_tab() {
982 WP_Optimize()->include_template('settings/support-and-faqs.php');
983 }
984
985 /**
986 * Dashboard Other plugins / premium tab
987 */
988 public function output_dashboard_other_plugins_tab() {
989 $this->include_template('settings/may-also-like.php');
990 }
991
992 /**
993 * Cache tab
994 */
995 public function output_page_cache_tab() {
996 $wpo_cache = $this->get_page_cache();
997 $wpo_cache_options = $wpo_cache->config->get();
998 $display = $wpo_cache->is_enabled() ? "style='display:block'" : "style='display:none'";
999
1000 WP_Optimize()->include_template('cache/page-cache.php', false, array(
1001 'wpo_cache' => $wpo_cache,
1002 'active_cache_plugins' => WP_Optimize_Detect_Cache_Plugins::instance()->get_active_cache_plugins(),
1003 'wpo_cache_options' => $wpo_cache_options,
1004 'cache_size' => $this->get_page_cache()->get_cache_size(),
1005 'display' => $display,
1006 'can_purge_the_cache' => $this->can_purge_the_cache(),
1007 ));
1008 }
1009
1010 /**
1011 * Preload tab
1012 */
1013 public function output_page_cache_preload_tab() {
1014 $wpo_cache = $this->get_page_cache();
1015 $wpo_cache_options = $wpo_cache->config->get();
1016 $wpo_cache_preloader = WP_Optimize_Page_Cache_Preloader::instance();
1017 $is_running = $wpo_cache_preloader->is_running();
1018 $status = $wpo_cache_preloader->get_status_info();
1019
1020 WP_Optimize()->include_template('cache/page-cache-preload.php', false, array(
1021 'wpo_cache_options' => $wpo_cache_options,
1022 'is_running' => $is_running,
1023 'status_message' => isset($status['message']) ? $status['message'] : '',
1024 'schedule_options' => array(
1025 'wpo_use_cache_lifespan' => __('Same as cache lifespan', 'wp-optimize'),
1026 'wpo_daily' => __('Daily', 'wp-optimize'),
1027 'wpo_weekly' => __('Weekly', 'wp-optimize'),
1028 'wpo_fortnightly' => __('Fortnightly', 'wp-optimize'),
1029 'wpo_monthly' => __('Monthly (approx. - every 30 days)', 'wp-optimize')
1030 )
1031 ));
1032 }
1033
1034 /**
1035 * Advanced tab
1036 */
1037 public function output_page_cache_advanced_tab() {
1038 $wpo_cache = $this->get_page_cache();
1039 $wpo_cache_options = $wpo_cache->config->get();
1040
1041 $cache_exception_urls = is_array($wpo_cache_options['cache_exception_urls']) ? join("\n", $wpo_cache_options['cache_exception_urls']) : '';
1042 $cache_exception_cookies = is_array($wpo_cache_options['cache_exception_cookies']) ? join("\n", $wpo_cache_options['cache_exception_cookies']) : '';
1043 $cache_exception_browser_agents = is_array($wpo_cache_options['cache_exception_browser_agents']) ? join("\n", $wpo_cache_options['cache_exception_browser_agents']) : '';
1044
1045 WP_Optimize()->include_template('cache/page-cache-advanced.php', false, array(
1046 'wpo_cache' => $this->get_page_cache(),
1047 'wpo_cache_options' => $wpo_cache_options,
1048 'cache_exception_urls' => $cache_exception_urls,
1049 'cache_exception_cookies' => $cache_exception_cookies,
1050 'cache_exception_browser_agents' => $cache_exception_browser_agents,
1051 ));
1052 }
1053
1054 /**
1055 * Gzip tab
1056 */
1057 public function output_cache_gzip_tab() {
1058 $wpo_gzip_compression = $this->get_gzip_compression();
1059 $wpo_gzip_compression_enabled = $wpo_gzip_compression->is_gzip_compression_enabled(true);
1060 $wpo_gzip_headers_information = $wpo_gzip_compression->get_headers_information();
1061 $is_cloudflare_site = $this->is_cloudflare_site();
1062 $is_gzip_compression_section_exists = $wpo_gzip_compression->is_gzip_compression_section_exists();
1063 $wpo_gzip_compression_enabled_by_wpo = $is_gzip_compression_section_exists && $wpo_gzip_compression_enabled && !$is_cloudflare_site && !('brotli' == $wpo_gzip_headers_information['compression']);
1064
1065 WP_Optimize()->include_template('cache/gzip-compression.php', false, array(
1066 'wpo_gzip_headers_information' => $wpo_gzip_headers_information,
1067 'wpo_gzip_compression_enabled' => $wpo_gzip_compression_enabled,
1068 'is_cloudflare_site' => $is_cloudflare_site,
1069 'wpo_gzip_compression_enabled_by_wpo' => $wpo_gzip_compression_enabled_by_wpo,
1070 'wpo_gzip_compression_settings_added' => $is_gzip_compression_section_exists,
1071 'info_link' => 'https://getwpo.com/gzip-compression-explained/',
1072 'faq_link' => 'https://getwpo.com/gzip-faq-link/',
1073 'class_name' => (!is_wp_error($wpo_gzip_compression_enabled) && $wpo_gzip_compression_enabled ? 'wpo-enabled' : 'wpo-disabled')
1074 ));
1075 }
1076
1077 /**
1078 * Cache tab
1079 */
1080 public function output_cache_settings_tab() {
1081
1082 $wpo_browser_cache = $this->get_browser_cache();
1083 $wpo_browser_cache_enabled = $wpo_browser_cache->is_enabled();
1084
1085 WP_Optimize()->include_template('cache/browser-cache.php', false, array(
1086 'wpo_browser_cache_enabled' => $wpo_browser_cache_enabled,
1087 'is_cloudflare_site' => $this->is_cloudflare_site(),
1088 'wpo_browser_cache_settings_added' => $wpo_browser_cache->is_browser_cache_section_exists(),
1089 'class_name' => (true === $wpo_browser_cache_enabled ? 'wpo-enabled' : 'wpo-disabled'),
1090 'wpo_browser_cache_expire_days' => $this->get_options()->get_option('browser_cache_expire_days', '28'),
1091 'wpo_browser_cache_expire_hours' => $this->get_options()->get_option('browser_cache_expire_hours', '0'),
1092 'info_link' => 'https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching',
1093 'faq_link' => 'https://www.digitalocean.com/community/tutorials/how-to-implement-browser-caching-with-nginx-s-header-module-on-ubuntu-16-04',
1094 ));
1095 }
1096
1097 /**
1098 * Check if is the current site handled with Cloudflare.
1099 *
1100 * @return bool
1101 */
1102 public function is_cloudflare_site() {
1103 return isset($_SERVER['HTTP_CF_RAY']);
1104 }
1105
1106 /**
1107 * Include Cloudflare settings template.
1108 */
1109 public function output_cloudflare_settings() {
1110 if (self::is_premium() || !apply_filters('show_cloudflare_settings', $this->is_cloudflare_site())) return;
1111
1112 WP_Optimize()->include_template('cache/page-cache-cloudflare-placeholder.php');
1113 }
1114
1115 /**
1116 * Outputs the DB optimize Tab
1117 */
1118 public function output_database_optimize_tab() {
1119 $optimizer = $this->get_optimizer();
1120 $options = $this->get_options();
1121
1122 // check if nonce passed.
1123 $nonce_passed = (!empty($_REQUEST['_wpnonce']) && wp_verify_nonce($_REQUEST['_wpnonce'], 'wpo_optimization')) ? true : false;
1124
1125 // save options.
1126 if ($nonce_passed && isset($_POST['wp-optimize'])) $options->save_sent_manual_run_optimization_options($_POST, true);
1127
1128 $optimize_db = ($nonce_passed && isset($_POST["optimize-db"])) ? true : false;
1129
1130 $optimization_results = (($nonce_passed) ? $optimizer->do_optimizations($_POST) : false);
1131
1132 // display optimizations table or restricted access message.
1133 if ($this->can_run_optimizations()) {
1134 $this->include_template('database/optimize-table.php', false, array('optimize_db' => $optimize_db, 'optimization_results' => $optimization_results, 'load_data' => false));
1135 } else {
1136 $this->prevent_run_optimizations_message();
1137 }
1138 }
1139
1140 /**
1141 * Outputs the DB Tables Tab
1142 */
1143 public function output_database_tables_tab() {
1144 // check if nonce passed.
1145 $nonce_passed = (!empty($_REQUEST['_wpnonce']) && wp_verify_nonce($_REQUEST['_wpnonce'], 'wpo_optimization')) ? true : false;
1146
1147 $optimize_db = ($nonce_passed && isset($_POST["optimize-db"])) ? true : false;
1148
1149 if ($this->can_run_optimizations()) {
1150 $this->include_template('database/tables.php', false, array('optimize_db' => $optimize_db, 'load_data' => WP_Optimize()->template_should_include_data()));
1151 } else {
1152 $this->prevent_run_optimizations_message();
1153 }
1154 }
1155
1156 /**
1157 * Runs upon the WP action admin_page_wpo_images_unused
1158 */
1159 public function admin_page_wpo_images_unused() {
1160 WP_Optimize()->include_template('images/unused.php');
1161 }
1162
1163 /**
1164 * Runs upon the WP action wp_optimize_admin_page_wpo_images_lazyload
1165 */
1166 public function admin_page_wpo_images_lazyload() {
1167 WP_Optimize()->include_template('images/lazyload.php');
1168 }
1169
1170 /**
1171 * Returns array of translations used in javascript code.
1172 *
1173 * @return array
1174 */
1175 public function wpo_js_translations() {
1176 return apply_filters('wpo_js_translations', array(
1177 'automatic_backup_before_optimizations' => __('Automatic backup before optimizations', 'wp-optimize'),
1178 'error_unexpected_response' => __('An unexpected response was received.', 'wp-optimize'),
1179 'optimization_complete' => __('Optimization complete', 'wp-optimize'),
1180 'with_warnings' => __('(with warnings - open the browser console for more details)', 'wp-optimize'),
1181 'optimizing_table' => __('Optimizing table:', 'wp-optimize'),
1182 'run_optimizations' => __('Run optimizations', 'wp-optimize'),
1183 'table_optimization_timeout' => 120000,
1184 'cancel' => __('Cancel', 'wp-optimize'),
1185 'cancelling' => __('Cancelling...', 'wp-optimize'),
1186 'enable' => __('Enable', 'wp-optimize'),
1187 'disable' => __('Disable', 'wp-optimize'),
1188 'please_select_settings_file' => __('Please, select settings file.', 'wp-optimize'),
1189 'are_you_sure_you_want_to_remove_logging_destination' => __('Are you sure you want to remove this logging destination?', 'wp-optimize'),
1190 'fill_all_settings_fields' => __('Before saving, you need to complete the currently incomplete settings (or remove them).', 'wp-optimize'),
1191 'table_was_not_repaired' => __('%s was not repaired. For more details, please check the logs (configured in your logging destinations settings).', 'wp-optimize'),
1192 'table_was_not_deleted' => __('%s was not deleted. For more details, please check your logs configured in logging destinations settings.', 'wp-optimize'),
1193 'please_use_positive_integers' => __('Please use positive integers.', 'wp-optimize'),
1194 'please_use_valid_values' => __('Please use valid values.', 'wp-optimize'),
1195 'update' => __('Update', 'wp-optimize'),
1196 'run_now' => __('Run now', 'wp-optimize'),
1197 'starting_preload' => __('Started preload...', 'wp-optimize'),
1198 'loading_urls' => __('Loading URLs...', 'wp-optimize'),
1199 'current_cache_size' => __('Current cache size:', 'wp-optimize'),
1200 'number_of_files' => __('Number of files:', 'wp-optimize'),
1201 'toggle_info' => __('Show information', 'wp-optimize'),
1202 'add_to_exclusion' => __('Added to the exclusion list', 'wp-optimize'),
1203 'excluded' => __('The file was added to the exclusion list', 'wp-optimize'),
1204 'save_exclusions' => __('Save the exclusions', 'wp-optimize'),
1205 'page_refresh' => __('Refreshing the page to reflect changes...', 'wp-optimize'),
1206 'settings_have_been_deleted_successfully' => __('WP-Optimize settings have been deleted successfully.', 'wp-optimize'),
1207 'loading_data' => __('Loading data...', 'wp-optimize'),
1208 'spinner_src' => esc_attr(admin_url('images/spinner-2x.gif')),
1209 'settings_page_url' => admin_url('admin.php?page=wpo_settings'),
1210 'sites' => $this->get_sites(),
1211 'user_always_ignores_table_delete_warning' => (get_user_meta(get_current_user_id(), 'wpo-ignores-table-delete-warning', true)) ? true : false,
1212 'post_meta_tweak_completed' => __('The tweak has been performed.', 'wp-optimize'),
1213 ));
1214 }
1215
1216 public function wpo_admin_bar() {
1217 $wp_admin_bar = $GLOBALS['wp_admin_bar'];
1218
1219 if (defined('WPOPTIMIZE_ADMINBAR_DISABLE') && WPOPTIMIZE_ADMINBAR_DISABLE) return;
1220
1221 // Show menu item in top bar only for super admins.
1222 if (is_multisite() & !is_super_admin(get_current_user_id())) return;
1223
1224 // Add a link called at the top admin bar.
1225 $args = array(
1226 'id' => 'wp-optimize-node',
1227 'title' => apply_filters('wpoptimize_admin_node_title', 'WP-Optimize')
1228 );
1229 $wp_admin_bar->add_node($args);
1230
1231 $pages = $this->get_submenu_items();
1232
1233 foreach ($pages as $page_id => $page) {
1234
1235 if (!isset($page['create_submenu']) || !$page['create_submenu']) {
1236 if (isset($page['icon']) && 'separator' == $page['icon']) {
1237 $args = array(
1238 'id' => 'wpo-separator-'.$page_id,
1239 'parent' => 'wp-optimize-node',
1240 'meta' => array(
1241 'class' => 'separator',
1242 ),
1243 );
1244 $wp_admin_bar->add_node($args);
1245 }
1246 continue;
1247 }
1248
1249 // 'menu_slug' => 'WP-Optimize',
1250
1251 $menu_page_url = menu_page_url($page['menu_slug'], false);
1252
1253 if (is_multisite()) {
1254 $menu_page_url = network_admin_url('admin.php?page='.$page['menu_slug']);
1255 }
1256
1257 $args = array(
1258 'id' => 'wpoptimize_admin_node_'.$page_id,
1259 'title' => $page['menu_title'],
1260 'parent' => 'wp-optimize-node',
1261 'href' => $menu_page_url,
1262 );
1263 $wp_admin_bar->add_node($args);
1264 }
1265
1266 }
1267
1268 /**
1269 * Manages the admin bar menu for caching (currently page and minify)
1270 */
1271 public function cache_admin_bar($wp_admin_bar) {
1272
1273 $options = $this->get_options();
1274 if (!$options->get_option('enable_cache_in_admin_bar', true)) return;
1275
1276 /**
1277 * The "purge cache" menu items
1278 *
1279 * @param array $menu_items - The menu items, in the format required by $wp_admin_bar->add_menu()
1280 * @param object $wp_admin_bar
1281 */
1282 $menu_items = apply_filters('wpo_cache_admin_bar_menu_items', array(), $wp_admin_bar);
1283
1284 if (empty($menu_items) || !is_array($menu_items)) return;
1285
1286 $wp_admin_bar->add_menu(array(
1287 'id' => 'wpo_purge_cache',
1288 'title' => __('Purge cache', 'wp-optimize'),
1289 'href' => '#',
1290 'meta' => array(
1291 'title' => __('Purge cache', 'wp-optimize'),
1292 ),
1293 'parent' => false,
1294 ));
1295
1296 foreach ($menu_items as $item) {
1297 $wp_admin_bar->add_menu($item);
1298 }
1299 }
1300
1301 /**
1302 * Add settings link on plugin page
1303 *
1304 * @param string $links Passing through the URL to be used within the HREF.
1305 * @return string Returns the Links.
1306 */
1307 public function plugin_settings_link($links) {
1308
1309 $admin_page_url = $this->get_options()->admin_page_url();
1310 $settings_page_url = $this->get_options()->admin_page_url('wpo_settings');
1311
1312 if (false == self::is_premium()) {
1313 $premium_link = '<a href="' . esc_url($this->premium_version_link) . '" target="_blank">' . __('Premium', 'wp-optimize') . '</a>';
1314 array_unshift($links, $premium_link);
1315 }
1316
1317 $settings_link = '<a href="' . esc_url($settings_page_url) . '">' . __('Settings', 'wp-optimize') . '</a>';
1318 array_unshift($links, $settings_link);
1319
1320 $optimize_link = '<a href="' . esc_url($admin_page_url) . '">' . __('Optimize', 'wp-optimize') . '</a>';
1321 array_unshift($links, $optimize_link);
1322 return $links;
1323 }
1324
1325 /**
1326 * Action wpo_tables_list_additional_column_data. Output button Optimize in the action column.
1327 *
1328 * @param string $content String for output to column
1329 * @param object $table_info Object with table info.
1330 *
1331 * @return string
1332 */
1333 public function tables_list_additional_column_data($content, $table_info) {
1334 if ($table_info->is_needing_repair) {
1335 $content .= '<div class="wpo_button_wrap">'
1336 . '<button class="button button-secondary run-single-table-repair" data-table="' . esc_attr($table_info->Name) . '">' . __('Repair', 'wp-optimize') . '</button>'
1337 . '<img class="optimization_spinner visibility-hidden" src="' . esc_attr(admin_url('images/spinner-2x.gif')) . '" width="20" height="20" alt="...">'
1338 . '<span class="optimization_done_icon dashicons dashicons-yes visibility-hidden"></span>'
1339 . '</div>';
1340 }
1341
1342 // table belongs to plugin.
1343 if ($table_info->can_be_removed) {
1344 $content .= '<div>'
1345 . '<button class="button button-secondary run-single-table-delete" data-table="' . esc_attr($table_info->Name) . '">' . __('Remove', 'wp-optimize') . '</button>'
1346 . '<img class="optimization_spinner visibility-hidden" src="' . esc_attr(admin_url('images/spinner-2x.gif')) . '" width="20" height="20" alt="...">'
1347 . '<span class="optimization_done_icon dashicons dashicons-yes visibility-hidden"></span>'
1348 . '</div>';
1349 }
1350
1351 return $content;
1352 }
1353
1354 /**
1355 * Initialize WP-Optimize page cache.
1356 */
1357 public function init_page_cache() {
1358 if ($this->get_page_cache()->config->get_option('enable_page_caching', false)) {
1359 $this->get_page_cache()->enable();
1360 }
1361 }
1362
1363 /**
1364 * Schedules cron event based on selected schedule type
1365 *
1366 * @return void
1367 */
1368 public function cron_activate() {
1369 $gmt_offset = (int) (3600 * get_option('gmt_offset'));
1370
1371 $options = $this->get_options();
1372
1373 if ($options->get_option('schedule') === false) {
1374 $options->set_default_options();
1375 } else {
1376 if ('true' == $options->get_option('schedule')) {
1377 if (!wp_next_scheduled('wpo_cron_event2')) {
1378 $schedule_type = $options->get_option('schedule-type', 'wpo_weekly');
1379
1380 // Backward compatibility
1381 if ('wpo_otherweekly' == $schedule_type) $schedule_type = 'wpo_fortnightly';
1382
1383 $this_time = (86400 * 7);
1384
1385 switch ($schedule_type) {
1386 case "wpo_daily":
1387 $this_time = 86400;
1388 break;
1389
1390 case "wpo_weekly":
1391 $this_time = (86400 * 7);
1392 break;
1393
1394 case "wpo_fortnightly":
1395 $this_time = (86400 * 14);
1396 break;
1397
1398 case "wpo_monthly":
1399 $this_time = (86400 * 30);
1400 break;
1401 }
1402
1403 add_action('wpo_cron_event2', array($this, 'cron_action'));
1404 wp_schedule_event((current_time("timestamp", 0) + $this_time - $gmt_offset), $schedule_type, 'wpo_cron_event2');
1405 WP_Optimize()->log('running wp_schedule_event()');
1406 }
1407 }
1408 }
1409 }
1410
1411 /**
1412 * Clears all cron events
1413 *
1414 * @return void
1415 */
1416 public function wpo_cron_deactivate() {
1417 $cron_jobs = _get_cron_array();
1418 foreach ($cron_jobs as $job) {
1419 foreach (array_keys($job) as $hook) {
1420 if (preg_match('/^wpo_/', $hook)) wp_unschedule_hook($hook);
1421 }
1422 }
1423 }
1424
1425 /**
1426 * Scheduler public functions to update schedulers
1427 *
1428 * @param array $schedules An array of schedules being passed.
1429 * @return array An array of schedules being returned.
1430 */
1431 public function cron_schedules($schedules) {
1432 $schedules['wpo_daily'] = array('interval' => 86400, 'display' => 'Once Daily');
1433 $schedules['wpo_weekly'] = array('interval' => 86400 * 7, 'display' => 'Once Weekly');
1434 $schedules['wpo_fortnightly'] = array('interval' => 86400 * 14, 'display' => 'Once Every Fortnight');
1435 $schedules['wpo_monthly'] = array('interval' => 86400 * 30, 'display' => 'Once Every Month');
1436 return $schedules;
1437 }
1438
1439 /**
1440 * Returns count of overdue cron jobs.
1441 *
1442 * @return integer
1443 */
1444 public function howmany_overdue_crons() {
1445 $how_many_overdue = 0;
1446 if (function_exists('_get_cron_array') || (is_file(ABSPATH.WPINC.'/cron.php') && include_once(ABSPATH.WPINC.'/cron.php') && function_exists('_get_cron_array'))) {
1447 $crons = _get_cron_array();
1448 if (is_array($crons)) {
1449 $timenow = time();
1450 foreach ($crons as $jt => $job) {
1451 if ($jt < $timenow) {
1452 $how_many_overdue++;
1453 }
1454 }
1455 }
1456 }
1457 return $how_many_overdue;
1458 }
1459
1460 /**
1461 * Run updates on plugin activation.
1462 */
1463 public function run_updates() {
1464 include_once(WPO_PLUGIN_MAIN_PATH.'includes/class-wp-optimize-updates.php');
1465 WP_Optimize_Updates::check_updates();
1466 }
1467
1468 /**
1469 * Returns warning about overdue crons.
1470 *
1471 * @param int $howmany count of overdue crons
1472 * @return string
1473 */
1474 public function show_admin_warning_overdue_crons($howmany) {
1475 $ret = '<div class="updated below-h2"><p>';
1476 $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>';
1477 $ret .= '</p></div>';
1478 return $ret;
1479 }
1480
1481 public function admin_menu() {
1482
1483 $capability_required = $this->capability_required();
1484
1485 if (!current_user_can($capability_required) || (!$this->can_run_optimizations() && !$this->can_manage_options())) return;
1486
1487 $icon_svg = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIgogICB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgdmlld0JveD0iMCAwIDE2IDE2IgogICB2ZXJzaW9uPSIxLjEiCiAgIGlkPSJzdmc0MzE2IgogICBoZWlnaHQ9IjE2IgogICB3aWR0aD0iMTYiPgogIDxkZWZzCiAgICAgaWQ9ImRlZnM0MzE4IiAvPgogIDxtZXRhZGF0YQogICAgIGlkPSJtZXRhZGF0YTQzMjEiPgogICAgPHJkZjpSREY+CiAgICAgIDxjYzpXb3JrCiAgICAgICAgIHJkZjphYm91dD0iIj4KICAgICAgICA8ZGM6Zm9ybWF0PmltYWdlL3N2Zyt4bWw8L2RjOmZvcm1hdD4KICAgICAgICA8ZGM6dHlwZQogICAgICAgICAgIHJkZjpyZXNvdXJjZT0iaHR0cDovL3B1cmwub3JnL2RjL2RjbWl0eXBlL1N0aWxsSW1hZ2UiIC8+CiAgICAgICAgPGRjOnRpdGxlPjwvZGM6dGl0bGU+CiAgICAgIDwvY2M6V29yaz4KICAgIDwvcmRmOlJERj4KICA8L21ldGFkYXRhPgogIDxnCiAgICAgaWQ9ImxheWVyMSI+CiAgICA8cGF0aAogICAgICAgc3R5bGU9ImZpbGw6I2EwYTVhYTtmaWxsLW9wYWNpdHk6MSIKICAgICAgIGlkPSJwYXRoNTciCiAgICAgICBkPSJtIDEwLjc2ODgwOSw2Ljc2MTYwNTEgMCwwIGMgLTAuMDE2ODgsLTAuMDE2ODc4IC0wLjAyNTMxLC0wLjA0MjE4MSAtMC4wMzM3NCwtMC4wNjc0OTkgLTAuMDA4NCwtMC4wMDgzOSAtMC4wMDg0LC0wLjAxNjg3OCAtMC4wMTY4OCwtMC4wMzM3NDMgQyA5Ljk5MjYxMTIsNS4xOTIzMzY2IDguMjIwODU1Nyw0LjU4NDg3ODEgNi43NDQzOTEyLDUuMjkzNTc5NyA1LjY3MjkwMDUsNS44MDgyMzI4IDUuMDU3MDA0Myw2Ljg4ODE2MTMgNS4wNjU0NDIsOC4wMDE4MzY1IDQuNDU3OTgyMiw3LjMxMDAwNzYgMy42OTg2NTg0LDYuNzk1MzU0NSAyLjg1NDk2NDIsNi40OTE2MjUzIDMuMjY4Mzc0Myw1LjA2NTc4MzEgNC4yNTU0OTYsMy44MTcxMTY2IDUuNjg5Nzc0NiwzLjEyNTI4NzggOC4zNjQyODMyLDEuODM0NDM2OCAxMS41NzAzMTksMi45Mzk2NzQ0IDEyLjg4NjQ4MSw1LjU4ODg3MjYgMTMuNDUxNzU1LDYuNzI3ODU5NiAxNC42NDk4MDEsNy4zNTIxOTIxIDE1Ljg0Nzg0Niw3LjIzNDA3NSAxNS43NjM0ODIsNi4zMzk3NiAxNS41MTg4MDUsNS40MzcwMDg2IDE1LjEwNTM5Niw0LjU3NjQ0MDQgMTMuMjE1NTIxLDAuNjg3MDEzNCA4LjUzMzAyMjYsLTAuOTQxMzE2MjcgNC42NDM1OTQzLDAuOTQwMTIxNzkgMi4zMjM0MzcsMi4wNjIyMzM0IDAuODA0Nzg4MTQsNC4xNzk5MDQ0IDAuMzU3NjMxMzIsNi41MzM4MDk4IDIuNDE2MjQzOCw2LjQyNDEyOSA0LjQzMjY3MTcsNy41MDQwNTc0IDUuNDM2NjY2Miw5LjQzNjExNjcgbCAwLjAwODM5LDAgYyAwLjc1OTMxOTIsMS4zNzUyMjAzIDIuNDcyMDE3OCwxLjk0MDQ5NTMgMy45MDYyOTYsMS4yNDg2NjczIDEuMDQ2MTc5OCwtMC41MDYyMTggMS42NTM2NDA4LC0xLjUzNTUyMzggMS42Nzg5NTA4LC0yLjYxNTQ1MTIgMC41ODIxNDgsMC43MDg3MDE4IDEuMzMzMDM1LDEuMjQ4NjY2OCAyLjE1OTg1NiwxLjU3NzcwNjQgLTAuNDM4NzIxLDEuMzU4MzQ3OCAtMS40MDA1MzMsMi41NDc5NTQ4IC0yLjc5MjYyNywzLjIxNDQ3ODggLTIuNTkwMTM4NywxLjI0ODY1OCAtNS42NzgwNTc0LDAuMjUzMTA0IC03LjA2MTcxNTEsLTIuMjI3MzU3IGwgMCwwIEMgMi43NjIxMDQ4LDkuNDUyOTg5NCAxLjUxMzQzODMsOC44MjAyMTkxIDAuMjgxNjQ1OTIsOC45NzIwODQ0IDAuMzgyODg3NjUsOS43OTg5MDQ2IDAuNjE5MTIzMzEsMTAuNjE3Mjg3IDAuOTk4Nzg1MiwxMS40MDE5MjIgYyAxLjg4MTQzNjgsMy44OTc4NjQgNi41NjM5MzcsNS41MjYxOTggMTAuNDYxODAwOCwzLjY0NDc2IDIuMjQ0MjI2LC0xLjA4ODM2OSAzLjczNzU2MiwtMy4xMDQ3OTYgNC4yMzUzNDIsLTUuMzc0MzMyMyAtMS45OTk1NTQsMC4wNDIxODEgLTMuOTQ4NDg2LC0xLjAyOTMwNjMgLTQuOTI3MTcsLTIuOTEwNzQzMyB6IgogICAgICAgY2xhc3M9InN0MTciIC8+CiAgPC9nPgo8L3N2Zz4K';
1488
1489 // Removes the admin menu items on the left WP bar.
1490 if (!is_multisite() || (is_multisite() && is_network_admin())) {
1491 add_menu_page("WP-Optimize", "WP-Optimize", $capability_required, "WP-Optimize", array($this, "display_admin"), $icon_svg);
1492
1493 $sub_menu_items = $this->get_submenu_items();
1494
1495 foreach ($sub_menu_items as $menu_item) {
1496 if ($menu_item['create_submenu']) add_submenu_page('WP-Optimize', $menu_item['page_title'], $menu_item['menu_title'], $capability_required, $menu_item['menu_slug'], $menu_item['function']);
1497 }
1498 }
1499
1500 $options = $this->get_options();
1501
1502 if ($options->get_option('enable-admin-menu', 'false') == 'true') {
1503 add_action('wp_before_admin_bar_render', array($this, 'wpo_admin_bar'));
1504 }
1505 }
1506
1507 /**
1508 * Get the submenu items
1509 *
1510 * @return array
1511 */
1512 public function get_submenu_items() {
1513 $sub_menu_items = array(
1514 array(
1515 'page_title' => __('Database', 'wp-optimize'),
1516 'menu_title' => __('Database', 'wp-optimize'),
1517 'menu_slug' => 'WP-Optimize',
1518 'function' => array($this, 'display_admin'),
1519 'icon' => 'cloud',
1520 'create_submenu' => true,
1521 'order' => 20,
1522 ),
1523 array(
1524 'page_title' => __('Images', 'wp-optimize'),
1525 'menu_title' => __('Images', 'wp-optimize'),
1526 'menu_slug' => 'wpo_images',
1527 'function' => array($this, 'display_admin'),
1528 'icon' => 'images-alt2',
1529 'create_submenu' => true,
1530 'order' => 30,
1531 ),
1532 array(
1533 'page_title' => __('Cache', 'wp-optimize'),
1534 'menu_title' => __('Cache', 'wp-optimize'),
1535 'menu_slug' => 'wpo_cache',
1536 'function' => array($this, 'display_admin'),
1537 'icon' => 'archive',
1538 'create_submenu' => true,
1539 'order' => 40,
1540 ),
1541 array(
1542 'page_title' => __('Minify', 'wp-optimize'),
1543 'menu_title' => __('Minify', 'wp-optimize'),
1544 'menu_slug' => 'wpo_minify',
1545 'function' => array($this, 'display_admin'),
1546 'icon' => 'dashboard',
1547 'create_submenu' => true,
1548 'order' => 50,
1549 ),
1550 array(
1551 'create_submenu' => false,
1552 'order' => 55,
1553 'icon' => 'separator',
1554 ),
1555 array(
1556 'page_title' => __('Settings', 'wp-optimize'),
1557 'menu_title' => __('Settings', 'wp-optimize'),
1558 'menu_slug' => 'wpo_settings',
1559 'function' => array($this, 'display_admin'),
1560 'icon' => 'admin-settings',
1561 'create_submenu' => true,
1562 'order' => 60,
1563 ),
1564 array(
1565 'page_title' => __('Support & FAQs', 'wp-optimize'),
1566 'menu_title' => __('Help', 'wp-optimize'),
1567 'menu_slug' => 'wpo_support',
1568 'function' => array($this, 'display_admin'),
1569 'icon' => 'sos',
1570 'create_submenu' => true,
1571 'order' => 60,
1572 ),
1573 array(
1574 'page_title' => __('Premium Upgrade', 'wp-optimize'),
1575 'menu_title' => __('Premium Upgrade', 'wp-optimize'),
1576 'menu_slug' => 'wpo_mayalso',
1577 'function' => array($this, 'display_admin'),
1578 'icon' => 'admin-plugins',
1579 'create_submenu' => true,
1580 'order' => 70,
1581 ),
1582 );
1583
1584 $sub_menu_items = apply_filters('wp_optimize_sub_menu_items', $sub_menu_items);
1585
1586 usort($sub_menu_items, array($this, 'order_sort'));
1587
1588 return $sub_menu_items;
1589 }
1590
1591 public function order_sort($a, $b) {
1592 if ($a['order'] == $b['order']) return 0;
1593 return ($a['order'] > $b['order']) ? 1 : -1;
1594 }
1595
1596 private function wp_normalize_path($path) {
1597 // Wp_normalize_path is not present before WP 3.9.
1598 if (function_exists('wp_normalize_path')) return wp_normalize_path($path);
1599 // Taken from WP 4.6.
1600 $path = str_replace('\\', '/', $path);
1601 $path = preg_replace('|(?<=.)/+|', '/', $path);
1602 if (':' === substr($path, 1, 1)) {
1603 $path = ucfirst($path);
1604 }
1605 return $path;
1606 }
1607
1608 public function get_templates_dir() {
1609 return apply_filters('wp_optimize_templates_dir', $this->wp_normalize_path(WPO_PLUGIN_MAIN_PATH.'templates'));
1610 }
1611
1612 public function get_templates_url() {
1613 return apply_filters('wp_optimize_templates_url', WPO_PLUGIN_URL.'/templates');
1614 }
1615
1616 /**
1617 * Return or output view content
1618 *
1619 * @param String $path - path to template, usually relative to templates/ within the WP-O directory
1620 * @param Boolean $return_instead_of_echo - what to do with the results
1621 * @param Array $extract_these - key/value pairs for substitution into the scope of the template
1622 *
1623 * @return String|Void
1624 */
1625 public function include_template($path, $return_instead_of_echo = false, $extract_these = array()) {
1626 if ($return_instead_of_echo) ob_start();
1627
1628 if (preg_match('#^([^/]+)/(.*)$#', $path, $matches)) {
1629 $prefix = $matches[1];
1630 $suffix = $matches[2];
1631 if (isset($this->template_directories[$prefix])) {
1632 $template_file = $this->template_directories[$prefix].'/'.$suffix;
1633 }
1634 }
1635
1636 if (!isset($template_file)) {
1637 $template_file = WPO_PLUGIN_MAIN_PATH.'templates/'.$path;
1638 }
1639
1640 $template_file = apply_filters('wp_optimize_template', $template_file, $path);
1641
1642 do_action('wp_optimize_before_template', $path, $template_file, $return_instead_of_echo, $extract_these);
1643
1644 if (!file_exists($template_file)) {
1645 error_log("WP Optimize: template not found: ".$template_file);
1646 echo __('Error:', 'wp-optimize').' '.__('template not found', 'wp-optimize')." (".$path.")";
1647 } else {
1648 extract($extract_these);
1649 // The following are useful variables which can be used in the template.
1650 // They appear as unused, but may be used in the $template_file.
1651 $wpdb = $GLOBALS['wpdb'];// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable -- $wpdb might be used in the included template
1652 $wp_optimize = $this;// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable -- $wp_optimize might be used in the included template
1653 $optimizer = $this->get_optimizer();// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable -- $optimizer might be used in the included template
1654 $options = $this->get_options();// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable -- $options might be used in the included template
1655 $wp_optimize_notices = $this->get_notices();// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable -- $wp_optimize_notices might be used in the included template
1656 include $template_file;
1657 }
1658
1659 do_action('wp_optimize_after_template', $path, $template_file, $return_instead_of_echo, $extract_these);
1660
1661 if ($return_instead_of_echo) return ob_get_clean();
1662 }
1663
1664 /**
1665 * Build a list of template directories (stored in self::$template_directories)
1666 */
1667 private function register_template_directories() {
1668
1669 $template_directories = array();
1670
1671 $templates_dir = $this->get_templates_dir();
1672
1673 if ($dh = opendir($templates_dir)) {
1674 while (($file = readdir($dh)) !== false) {
1675 if ('.' == $file || '..' == $file) continue;
1676 if (is_dir($templates_dir.'/'.$file)) {
1677 $template_directories[$file] = $templates_dir.'/'.$file;
1678 }
1679 }
1680 closedir($dh);
1681 }
1682
1683 // Optimal hook for most extensions to hook into.
1684 $this->template_directories = apply_filters('wp_optimize_template_directories', $template_directories);
1685
1686 }
1687
1688 /**
1689 * Message to debug
1690 *
1691 * @param string $message Message to insert into the log.
1692 * @param array $context array with variables used in $message like in template,
1693 * for ex.
1694 * $message = 'Hello {message}';
1695 * $context = ['message' => 'world']
1696 * 'Hello world' string will be saved in log.
1697 */
1698 public function log($message, $context = array()) {
1699 $this->get_logger()->debug($message, $context);
1700 }
1701
1702 /**
1703 * Format Bytes Into KB/MB
1704 *
1705 * @param mixed $bytes Number of bytes to be converted.
1706 * @return integer return the correct format size.
1707 */
1708 public function format_size($bytes) {
1709 if (!is_numeric($bytes)) return __('N/A', 'wp-optimize');
1710
1711 if (1073741824 <= $bytes) {
1712 $bytes = number_format($bytes / 1073741824, 2) . ' GB';
1713 } elseif (1048576 <= $bytes) {
1714 $bytes = number_format($bytes / 1048576, 2) . ' MB';
1715 } elseif (1024 <= $bytes) {
1716 $bytes = number_format($bytes / 1024, 2) . ' KB';
1717 } elseif (1 < $bytes) {
1718 $bytes = $bytes . ' bytes';
1719 } elseif (1 == $bytes) {
1720 $bytes = $bytes . ' byte';
1721 } else {
1722 $bytes = '0 bytes';
1723 }
1724
1725 return $bytes;
1726 }
1727
1728 /**
1729 * Format a timestamp into a juman readable date time
1730 *
1731 * @param int $timestamp
1732 * @return string
1733 */
1734 public function format_date_time($timestamp) {
1735 return date_i18n(get_option('date_format').' @ '.get_option('time_format'), ($timestamp + get_option('gmt_offset') * 3600));
1736 }
1737
1738 /**
1739 * Executed this function on cron event.
1740 *
1741 * @return void
1742 */
1743 public function cron_action() {
1744
1745 $optimizer = $this->get_optimizer();
1746 $options = $this->get_options();
1747
1748 $this->log('WPO: Starting cron_action()');
1749
1750 if ('true' == $options->get_option('schedule')) {
1751 $this_options = $options->get_option('auto');
1752
1753 // Currently the output of the optimizations is not saved/used/logged.
1754 $optimizer->do_optimizations($this_options, 'auto');
1755 }
1756
1757 }
1758
1759 /**
1760 * Schedule cron tasks used by plugin.
1761 *
1762 * @return void
1763 */
1764 public function schedule_plugin_cron_tasks() {
1765 if (!wp_next_scheduled('wpo_weekly_cron_tasks')) {
1766 wp_schedule_event(current_time("timestamp", 0), 'weekly', 'wpo_weekly_cron_tasks');
1767 }
1768
1769 add_action('wpo_weekly_cron_tasks', array($this, 'do_weekly_cron_tasks'));
1770 }
1771
1772 /**
1773 * Do plugin background tasks.
1774 *
1775 * @return void
1776 */
1777 public function do_weekly_cron_tasks() {
1778 // add tasks here.
1779 $this->get_db_info()->update_plugin_json();
1780 }
1781
1782 /**
1783 * This will customize a URL with a correct Affiliate link
1784 * This function can be update to suit any URL as longs as the URL is passed
1785 *
1786 * @param String $url - URL to be check to see if it an updraftplus match.
1787 * @param String $text - Text to be entered within the href a tags.
1788 * @param String $html - Any specific HTML to be added.
1789 * @param String $class - Specify a class for the href (including the attribute label)
1790 * @param Boolean $return_instead_of_echo - if set, then the result will be returned, not echo-ed.
1791 *
1792 * @return String|void
1793 */
1794 public function wp_optimize_url($url, $text, $html = '', $class = '', $return_instead_of_echo = false) {
1795 // Check if the URL is UpdraftPlus.
1796 $url = $this->maybe_add_affiliate_params($url); // Return URL - check if there is HTML such as images.
1797 if ('' != $html) {
1798 $result = '<a '.$class.' href="'.esc_attr($url).'">'.$html.'</a>';
1799 } else {
1800 $result = '<a '.$class.' href="'.esc_attr($url).'">'.htmlspecialchars($text).'</a>';
1801 }
1802 if ($return_instead_of_echo) return $result;
1803 echo $result;
1804 }
1805
1806 /**
1807 * Get an URL with an eventual affiliate ID
1808 *
1809 * @param string $url
1810 * @return string
1811 */
1812 public function maybe_add_affiliate_params($url) {
1813 // Check if the URL is UpdraftPlus.
1814 if (false !== strpos($url, '//updraftplus.com')) {
1815 // Set URL with Affiliate ID.
1816 $url = add_query_arg(array('afref' => $this->get_notices()->get_affiliate_id()), $url);
1817
1818 // Apply filters.
1819 $url = apply_filters('wpoptimize_updraftplus_com_link', $url);
1820 }
1821 return apply_filters('wpoptimize_maybe_add_affiliate_params', $url);
1822 }
1823
1824 /**
1825 * Setup WPO logger(s)
1826 */
1827 public function setup_loggers() {
1828
1829 $logger = $this->get_logger();
1830 $loggers = $this->wpo_loggers();
1831
1832 if (!empty($loggers)) {
1833 foreach ($loggers as $_logger) {
1834 $logger->add_logger($_logger);
1835 }
1836 }
1837
1838 add_action('wp_optimize_after_optimizations', array($this, 'after_optimizations_logger_action'));
1839 }
1840
1841 /**
1842 * Run logger actions after all optimizations done
1843 */
1844 public function after_optimizations_logger_action() {
1845 $loggers = $this->get_logger()->get_loggers();
1846 if (!empty($loggers)) {
1847 foreach ($loggers as $logger) {
1848 if (is_a($logger, 'Updraft_Email_Logger')) {
1849 $logger->flush_log();
1850 }
1851 }
1852 }
1853 }
1854
1855 /**
1856 * Returns list of WPO loggers instances
1857 * Apply filter wp_optimize_loggers
1858 *
1859 * @return array
1860 */
1861 public function wpo_loggers() {
1862
1863 $loggers = array();
1864 $loggers_classes_by_id = array();
1865 $options_keys = array();
1866
1867 $loggers_classes = $this->get_loggers_classes();
1868
1869 foreach ($loggers_classes as $logger_class => $source) {
1870 $loggers_classes_by_id[strtolower($logger_class)] = $logger_class;
1871 }
1872
1873 $options = $this->get_options();
1874
1875 $saved_loggers = $options->get_option('logging');
1876 $logger_additional_options = $options->get_option('logging-additional');
1877
1878 // create loggers classes instances.
1879 if (!empty($saved_loggers)) {
1880 // check for previous version options format.
1881 $keys = array_keys($saved_loggers);
1882
1883 // if options stored in old format then reformat it.
1884 if (false == is_numeric($keys[0])) {
1885 $_saved_loggers = array();
1886 foreach ($saved_loggers as $logger_id => $enabled) {
1887 if ($enabled) {
1888 $_saved_loggers[] = $logger_id;
1889 }
1890 }
1891
1892 // fill email with admin.
1893 if (array_key_exists('updraft_email_logger', $saved_loggers) && $saved_loggers['updraft_email_logger']) {
1894 $logger_additional_options['updraft_email_logger'] = array(
1895 get_option('admin_email')
1896 );
1897 }
1898
1899 $saved_loggers = $_saved_loggers;
1900 }
1901
1902 foreach ($saved_loggers as $i => $logger_id) {
1903
1904 if (!array_key_exists($logger_id, $loggers_classes_by_id)) continue;
1905
1906 $logger_class = $loggers_classes_by_id[$logger_id];
1907
1908 $logger = new $logger_class();
1909
1910 $logger_options = $logger->get_options_list();
1911
1912 if (!empty($logger_options)) {
1913 foreach (array_keys($logger_options) as $option_name) {
1914 if (array_key_exists($option_name, $options_keys)) {
1915 $options_keys[$option_name]++;
1916 } else {
1917 $options_keys[$option_name] = 0;
1918 }
1919
1920 $option_value = isset($logger_additional_options[$option_name][$options_keys[$option_name]]) ? $logger_additional_options[$option_name][$options_keys[$option_name]] : '';
1921
1922 // if options in old format then get correct value.
1923 if ('' === $option_value && array_key_exists($logger_id, $logger_additional_options)) {
1924 $option_value = array_shift($logger_additional_options[$logger_id]);
1925 }
1926
1927 $logger->set_option($option_name, $option_value);
1928 }
1929 }
1930
1931 // check if logger is active.
1932 $active = (!is_array($logger_additional_options) || (array_key_exists('active', $logger_additional_options) && empty($logger_additional_options['active'][$i]))) ? false : true;
1933
1934 if ($active) {
1935 $logger->enable();
1936 } else {
1937 $logger->disable();
1938 }
1939
1940 $loggers[] = $logger;
1941 }
1942 }
1943
1944 $loggers = apply_filters('wp_optimize_loggers', $loggers);
1945
1946 return $loggers;
1947 }
1948
1949 /**
1950 * Returns associative array with logger class name in a key and path to class file in a value.
1951 *
1952 * @return array
1953 */
1954 public function get_loggers_classes() {
1955 $loggers_classes = array(
1956 'Updraft_PHP_Logger' => WPO_PLUGIN_MAIN_PATH . 'includes/class-updraft-php-logger.php',
1957 'Updraft_Email_Logger' => WPO_PLUGIN_MAIN_PATH . 'includes/class-updraft-email-logger.php',
1958 'Updraft_Ring_Logger' => WPO_PLUGIN_MAIN_PATH . 'includes/class-updraft-ring-logger.php'
1959 );
1960
1961 $loggers_classes = apply_filters('wp_optimize_loggers_classes', $loggers_classes);
1962
1963 if (!empty($loggers_classes)) {
1964 foreach ($loggers_classes as $logger_class => $logger_file) {
1965 if (!class_exists($logger_class)) {
1966 if (is_file($logger_file)) {
1967 include_once($logger_file);
1968 }
1969 }
1970 }
1971 }
1972
1973 return $loggers_classes;
1974 }
1975
1976 /**
1977 * Returns information about all loggers classes.
1978 *
1979 * @return array
1980 */
1981 public function get_loggers_classes_info() {
1982 $loggers_classes = $this->get_loggers_classes();
1983
1984 $loggers_classes_info = array();
1985
1986 if (!empty($loggers_classes)) {
1987 foreach (array_keys($loggers_classes) as $logger_class_name) {
1988
1989 if (!class_exists($logger_class_name)) continue;
1990
1991 $logger_id = strtolower($logger_class_name);
1992 $logger_class = new $logger_class_name();
1993
1994 $loggers_classes_info[$logger_id] = array(
1995 'description' => $logger_class->get_description(),
1996 'available' => $logger_class->is_available(),
1997 'allow_multiple' => $logger_class->is_allow_multiple(),
1998 'options' => $logger_class->get_options_list()
1999 );
2000 }
2001 }
2002
2003 return $loggers_classes_info;
2004 }
2005
2006 /**
2007 * Returns true if optimization works in multisite mode
2008 *
2009 * @return boolean
2010 */
2011 public function is_multisite_mode() {
2012 return (is_multisite() && self::is_premium());
2013 }
2014
2015 /**
2016 * Returns true if current user can run optimizations.
2017 *
2018 * @return bool
2019 */
2020 public function can_run_optimizations() {
2021 // we don't check permissions for cron jobs.
2022 if (defined('DOING_CRON') && DOING_CRON) return true;
2023
2024 if (self::is_premium() && false == user_can(get_current_user_id(), 'wpo_run_optimizations')) return false;
2025 return true;
2026 }
2027
2028 /**
2029 * Returns true if current user can manage plugin options.
2030 *
2031 * @return bool
2032 */
2033 public function can_manage_options() {
2034 if (self::is_premium() && false == user_can(get_current_user_id(), 'wpo_manage_settings')) return false;
2035 return true;
2036 }
2037
2038 /**
2039 * CHeck if current user can purge the cache.
2040 *
2041 * @return bool
2042 */
2043 public function can_purge_the_cache() {
2044 if (self::is_premium()) {
2045 return WP_Optimize_Premium()->can_purge_the_cache();
2046 }
2047
2048 return true;
2049 }
2050
2051 /**
2052 * Output information message for users who have no permissions to run optimizations.
2053 */
2054 public function prevent_run_optimizations_message() {
2055 $this->include_template('info-message.php', false, array('message' => __('You have no permissions to run optimizations.', 'wp-optimize')));
2056 }
2057
2058 /**
2059 * Output information message for users who have no permissions to manage settings.
2060 */
2061 public function prevent_manage_options_info() {
2062 $this->include_template('info-message.php', false, array('message' => __('You have no permissions to manage WP-Optimize settings.', 'wp-optimize')));
2063 }
2064
2065 /**
2066 * Returns list of all sites in multisite
2067 *
2068 * @return array
2069 */
2070 public function get_sites() {
2071 $sites = array();
2072 // check if function get_sites exists (since 4.6.0) else use wp_get_sites.
2073 if (function_exists('get_sites')) {
2074 $sites = get_sites(array('network_id' => null, 'deleted' => 0, 'number' => 999999));
2075 } elseif (function_exists('wp_get_sites')) {
2076 $sites = wp_get_sites(array('network_id' => null, 'deleted' => 0, 'limit' => 999999));
2077 }
2078 return $sites;
2079 }
2080
2081 /**
2082 * Output success/error messages from $output array.
2083 *
2084 * @param array $output ['messages' => success messages, 'errors' => error messages]
2085 */
2086 private function wpo_render_output_messages($output) {
2087 foreach ($output['messages'] as $item) {
2088 echo '<div class="updated fade below-h2"><strong>'.$item.'</strong></div>';
2089 }
2090
2091 foreach ($output['errors'] as $item) {
2092 echo '<div class="error fade below-h2"><strong>'.$item.'</strong></div>';
2093 }
2094 }
2095
2096 /**
2097 * Returns script memory limit in megabytes.
2098 *
2099 * @param bool $memory_limit
2100 * @return int
2101 */
2102 public function get_memory_limit($memory_limit = false) {
2103 // Returns in megabytes
2104 if (false == $memory_limit) $memory_limit = ini_get('memory_limit');
2105 $memory_limit = rtrim($memory_limit);
2106
2107 return $this->return_bytes($memory_limit);
2108 }
2109
2110 /**
2111 * Returns free memory in bytes.
2112 *
2113 * @return int
2114 */
2115 public function get_free_memory() {
2116 return $this->get_memory_limit() - memory_get_usage();
2117 }
2118
2119 /**
2120 * Checks PHP memory_limit and WP_MAX_MEMORY_LIMIT values and return minimal.
2121 *
2122 * @return int memory limit in bytes.
2123 */
2124 public function get_script_memory_limit() {
2125 $memory_limit = $this->get_memory_limit();
2126
2127 if (defined('WP_MAX_MEMORY_LIMIT')) {
2128 $wp_memory_limit = $this->get_memory_limit(WP_MAX_MEMORY_LIMIT);
2129
2130 if ($wp_memory_limit > 0 && $wp_memory_limit < $memory_limit) {
2131 $memory_limit = $wp_memory_limit;
2132 }
2133 }
2134
2135 return $memory_limit;
2136 }
2137
2138 /**
2139 * Returns max packet size for database.
2140 *
2141 * @return int|string
2142 */
2143 public function get_max_packet_size() {
2144 global $wpdb;
2145 static $mp = 0;
2146
2147 if ($mp > 0) return $mp;
2148
2149 $mp = (int) $wpdb->get_var("SELECT @@session.max_allowed_packet");
2150 // Default to 1MB
2151 $mp = (is_numeric($mp) && $mp > 0) ? $mp : 1048576;
2152 // 32MB
2153 if ($mp < 33554432) {
2154 $save = $wpdb->show_errors(false);
2155 @$wpdb->query("SET GLOBAL max_allowed_packet=33554432");// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
2156 $wpdb->show_errors($save);
2157
2158 $mp = (int) $wpdb->get_var("SELECT @@session.max_allowed_packet");
2159 // Default to 1MB
2160 $mp = (is_numeric($mp) && $mp > 0) ? $mp : 1048576;
2161 }
2162
2163 return $mp;
2164 }
2165
2166 /**
2167 * Converts shorthand memory notation value to bytes.
2168 * From http://php.net/manual/en/function.ini-get.php
2169 *
2170 * @param string $val shorthand memory notation value.
2171 */
2172 public function return_bytes($val) {
2173 $val = trim($val);
2174 $last = strtolower($val[strlen($val)-1]);
2175 $val = (int) $val;
2176 switch ($last) {
2177 case 'g':
2178 $val *= 1024;
2179 // no break
2180 case 'm':
2181 $val *= 1024;
2182 // no break
2183 case 'k':
2184 $val *= 1024;
2185 }
2186
2187 return $val;
2188 }
2189
2190 /**
2191 * Log fatal errors to defined log destinations.
2192 */
2193 public function log_fatal_errors() {
2194 $last_error = error_get_last();
2195
2196 if (isset($last_error['type']) && E_ERROR === $last_error['type']) {
2197 $this->get_logger()->critical($last_error['message']);
2198 }
2199 }
2200
2201 /**
2202 * Close browser connection and continue script work. - Taken from UpdraftPlus
2203 *
2204 * @param array $txt Response to browser; this must be JSON (or if not, alter the Content-Type header handling below)
2205 * @return void
2206 */
2207 public function close_browser_connection($txt = '') {
2208 if (!headers_sent()) {
2209 // Close browser connection so that it can resume AJAX polling
2210 header('Content-Length: '.(empty($txt) ? '0' : 4+strlen($txt)));
2211 header('Connection: close');
2212 header('Content-Encoding: none');
2213 }
2214
2215 if (session_id()) session_write_close();
2216 echo "\r\n\r\n";
2217 echo $txt;
2218 // These two added - 19-Feb-15 - started being required on local dev machine, for unknown reason (probably some plugin that started an output buffer).
2219 $ob_level = ob_get_level();
2220 while ($ob_level > 0) {
2221 ob_end_flush();
2222 $ob_level--;
2223 }
2224 flush();
2225 if (function_exists('fastcgi_finish_request')) fastcgi_finish_request();
2226 }
2227
2228 /**
2229 * Get the current theme's style.css headers
2230 *
2231 * @return array|WP_Error
2232 */
2233 public function get_stylesheet_headers() {
2234 static $headers;
2235 if (isset($headers)) return $headers;
2236
2237 $style = get_template_directory_uri() . '/style.css';
2238
2239 /**
2240 * Filters wp_remote_get parameters, when checking if browser cache is enabled.
2241 *
2242 * @param array $request_params Default parameters
2243 */
2244 $request_params = apply_filters('wpoptimize_get_stylesheet_headers_args', array('timeout' => 10));
2245
2246 // trying to load style.css.
2247 $response = wp_remote_get($style, $request_params);
2248
2249 if (is_a($response, 'WP_Error')) return $response;
2250
2251 $headers = wp_remote_retrieve_headers($response);
2252
2253 if (is_a($headers, 'Requests_Utility_CaseInsensitiveDictionary')) {
2254 $headers = $headers->getAll();
2255 }
2256
2257 return $headers;
2258 }
2259
2260 /**
2261 * Try to change PHP script time limit.
2262 */
2263 public function change_time_limit() {
2264 $time_limit = (defined('WP_OPTIMIZE_SET_TIME_LIMIT') && WP_OPTIMIZE_SET_TIME_LIMIT > 15) ? WP_OPTIMIZE_SET_TIME_LIMIT : 1800;
2265
2266 // Try to reduce the chances of PHP self-terminating via reaching max_execution_time.
2267 @set_time_limit($time_limit); // phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
2268 }
2269
2270 /**
2271 * Does the request come from UDC
2272 *
2273 * @return boolean
2274 */
2275 public function is_updraft_central_request() {
2276 return defined('UPDRAFTCENTRAL_COMMAND') && UPDRAFTCENTRAL_COMMAND;
2277 }
2278
2279 /**
2280 * Does the data need to be included in this request. Currently only true if the request is made from UpdraftCentral.
2281 *
2282 * @return boolean
2283 */
2284 public function template_should_include_data() {
2285 /**
2286 * Filters wether data should be included in certain templates or not.
2287 */
2288 return apply_filters('wpo_template_should_include_data', $this->is_updraft_central_request());
2289 }
2290
2291 /**
2292 * Load the templates for the modal window
2293 */
2294 public function load_modal_template() {
2295 $this->include_template('modal.php');
2296 }
2297
2298 /**
2299 * Delete transients and semaphores data from options table.
2300 */
2301 public function delete_transients_and_semaphores() {
2302 global $wpdb;
2303
2304 $masks = array(
2305 'updraft_locked_wpo_%',
2306 'updraft_unlocked_wpo_%',
2307 'updraft_last_lock_time_wpo_%',
2308 'updraft_semaphore_wpo_%',
2309 'wpo_locked_%',
2310 'wpo_unlocked_%',
2311 'wpo_last_lock_time_%',
2312 'wpo_semaphore_%',
2313 '_transient_timeout_wpo_%',
2314 '_transient_wpo_%',
2315 );
2316
2317 $where_parts = array();
2318 foreach ($masks as $mask) {
2319 $where_parts[] = "(`option_name` LIKE '{$mask}')";
2320 }
2321
2322 $wpdb->query("DELETE FROM {$wpdb->options} WHERE " . join(' OR ', $where_parts));
2323 }
2324
2325 /**
2326 * Prevents bots from indexing plugins list
2327 */
2328 public function robots_txt($output) {
2329 $upload_dir = wp_upload_dir();
2330 $output .= "\nDisallow: " . str_replace(site_url(), '', $upload_dir['baseurl']) . "/wpo-plugins-tables-list.json\n";
2331 return $output;
2332 }
2333 }
2334
2335 /**
2336 * Plugin activation actions.
2337 */
2338 function wpo_activation_actions() {
2339 // If plugin activated by not a Network Administrator then deactivate plugin and show message.
2340 if (is_multisite() && !is_network_admin()) {
2341 deactivate_plugins(plugin_basename(__FILE__));
2342 wp_die(__('Only Network Administrator can activate WP-Optimize plugin.', 'wp-optimize').
2343 ' <a href="'.admin_url('plugins.php').'">'.__('go back', 'wp-optimize').'</a>');
2344 }
2345
2346 // On activation, check if last-optimized option exists. If not, add 'newly-activated' option.
2347 if (!WP_Optimize()->get_options()->get_option('last-optimized', false)) {
2348 WP_Optimize()->get_options()->update_option('newly-activated', true);
2349 }
2350
2351 WP_Optimize()->get_options()->set_default_options();
2352 WP_Optimize()->get_minify()->plugin_activate();
2353
2354 WP_Optimize::get_gzip_compression()->restore();
2355 WP_Optimize::get_browser_cache()->restore();
2356
2357 // run premium activation actions.
2358 if (file_exists(WPO_PLUGIN_MAIN_PATH.'premium.php')) {
2359 if (!class_exists('WP_Optimize_Premium')) {
2360 include_once(WPO_PLUGIN_MAIN_PATH.'premium.php');
2361 }
2362
2363 WP_Optimize_Premium()->plugin_activation_actions();
2364 }
2365 }
2366
2367 /**
2368 * Plugin deactivation actions.
2369 */
2370 function wpo_deactivation_actions() {
2371 WP_Optimize()->wpo_cron_deactivate();
2372 WP_Optimize()->get_page_cache()->disable();
2373 WP_Optimize()->get_minify()->plugin_deactivate();
2374 WP_Optimize::get_gzip_compression()->disable();
2375 WP_Optimize::get_browser_cache()->disable();
2376 }
2377
2378 function wpo_cron_deactivate() {
2379 WP_Optimize()->log('running wpo_cron_deactivate()');
2380 wp_clear_scheduled_hook('wpo_cron_event2');
2381 wp_clear_scheduled_hook('wpo_weekly_cron_tasks');
2382 }
2383
2384 /**
2385 * Plugin uninstall actions.
2386 */
2387 function wpo_uninstall_actions() {
2388 WP_Optimize::get_gzip_compression()->disable();
2389 WP_Optimize::get_browser_cache()->disable();
2390 WP_Optimize()->get_options()->delete_all_options();
2391 WP_Optimize()->get_minify()->plugin_uninstall();
2392 WP_Optimize()->get_options()->wipe_settings();
2393 WP_Optimize()->delete_transients_and_semaphores();
2394 }
2395
2396 function WP_Optimize() {
2397 return WP_Optimize::instance();
2398 }
2399
2400 endif;
2401
2402 $GLOBALS['wp_optimize'] = WP_Optimize();
2403