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

1,383 lines 46.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
4 Plugin URI: https://getwpo.com
5 Description: WP-Optimize is WordPress's #1 most installed optimization plugin. With it, you can clean up your database easily and safely, without manual queries.
6 Version: 2.2.6
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', '2.2.6');
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
23 class WP_Optimize {
24
25 public $premium_version_link = 'https://getwpo.com/buy/';
26
27 private $template_directories;
28
29 protected static $_instance = null;
30
31 protected static $_optimizer_instance = null;
32
33 protected static $_options_instance = null;
34
35 protected static $_notices_instance = null;
36
37 protected static $_logger_instance = null;
38
39 protected static $_db_info = null;
40
41 public function __construct() {
42
43 // Checks if premium is installed along with plugins needed.
44 add_action('plugins_loaded', array($this, 'plugins_loaded'), 1);
45
46 register_activation_hook(__FILE__, 'wpo_activation_actions');
47 register_deactivation_hook(__FILE__, 'wpo_deactivation_actions');
48 register_uninstall_hook(__FILE__, 'wpo_uninstall_actions');
49
50 add_action('admin_init', array($this, 'admin_init'));
51 add_action('admin_menu', array($this, 'admin_menu'));
52
53 add_filter("plugin_action_links_".plugin_basename(__FILE__), array($this, 'plugin_settings_link'));
54 add_action('wpo_cron_event2', array($this, 'cron_action'));
55 add_filter('cron_schedules', array($this, 'cron_schedules'));
56
57 if (!$this->is_premium()) {
58 add_action('auto_option_settings', array($this->get_options(), 'auto_option_settings'));
59 }
60
61 add_action('wp_ajax_wp_optimize_ajax', array($this, 'wp_optimize_ajax_handler'));
62
63 // Initialize loggers.
64 add_action('plugins_loaded', array($this, 'setup_loggers'));
65
66 // Show update to Premium notice for non-premium multisite.
67 add_action('wpo_additional_options', array($this, 'show_multisite_update_to_premium_notice'));
68
69 // Action column (show repair button if need).
70 add_filter('wpo_tables_list_additional_column_data', array($this, 'tables_list_additional_column_data'), 15, 2);
71
72 include_once(WPO_PLUGIN_MAIN_PATH.'/includes/updraftcentral.php');
73
74 register_shutdown_function(array($this, 'log_fatal_errors'));
75
76 $this->schedule_plugin_cron_tasks();
77 }
78
79 public static function instance() {
80 if (empty(self::$_instance)) {
81 self::$_instance = new self();
82 }
83 return self::$_instance;
84 }
85
86 public static function get_optimizer() {
87 if (empty(self::$_optimizer_instance)) {
88 if (!class_exists('WP_Optimizer')) include_once(WPO_PLUGIN_MAIN_PATH.'/includes/class-wp-optimizer.php');
89 self::$_optimizer_instance = new WP_Optimizer();
90 }
91 return self::$_optimizer_instance;
92 }
93
94 public static function get_options() {
95 if (empty(self::$_options_instance)) {
96 if (!class_exists('WP_Optimize_Options')) include_once(WPO_PLUGIN_MAIN_PATH.'/includes/class-wp-optimize-options.php');
97 self::$_options_instance = new WP_Optimize_Options();
98 }
99 return self::$_options_instance;
100 }
101
102 public static function get_notices() {
103 if (empty(self::$_notices_instance)) {
104 if (!class_exists('WP_Optimize_Notices')) include_once(WPO_PLUGIN_MAIN_PATH.'/includes/wp-optimize-notices.php');
105 self::$_notices_instance = new WP_Optimize_Notices();
106 }
107 return self::$_notices_instance;
108 }
109
110 /**
111 * Returns WP_Optimize_Database_Information instance.
112 *
113 * @return WP_Optimize_Database_Information
114 */
115 public function get_db_info() {
116 if (empty(self::$_db_info)) {
117 if (!class_exists('WP_Optimize_Database_Information')) include_once(WPO_PLUGIN_MAIN_PATH.'/includes/wp-optimize-database-information.php');
118 self::$_db_info = new WP_Optimize_Database_Information();
119 }
120 return self::$_db_info;
121 }
122
123 /**
124 * Return instance of Updraft_Logger
125 *
126 * @return Updraft_Logger
127 */
128 public static function get_logger() {
129 if (empty(self::$_logger_instance)) {
130 include_once(WPO_PLUGIN_MAIN_PATH.'/includes/class-updraft-logger.php');
131 self::$_logger_instance = new Updraft_Logger();
132 }
133 return self::$_logger_instance;
134 }
135
136 /**
137 * Load Task Manager
138 */
139 public function get_task_manager() {
140 include_once(WPO_PLUGIN_MAIN_PATH.'/vendor/team-updraft/common-libs/src/updraft-tasks/class-updraft-tasks-activation.php');
141
142 Updraft_Tasks_Activation::check_updates();
143
144 include_once(WPO_PLUGIN_MAIN_PATH . '/vendor/team-updraft/common-libs/src/updraft-tasks/class-updraft-task-meta.php');
145 include_once(WPO_PLUGIN_MAIN_PATH . '/vendor/team-updraft/common-libs/src/updraft-tasks/class-updraft-task-options.php');
146 include_once(WPO_PLUGIN_MAIN_PATH . '/vendor/team-updraft/common-libs/src/updraft-tasks/class-updraft-task.php');
147 }
148
149 /**
150 * Indicate whether we have an associated instance of WP-Optimize Premium or not.
151 *
152 * @returns Boolean
153 */
154 public static function is_premium() {
155 if (file_exists(WPO_PLUGIN_MAIN_PATH.'/premium.php') && function_exists('WP_Optimize_Premium')) {
156 $wp_optimize_premium = WP_Optimize_Premium();
157 if (is_a($wp_optimize_premium, 'WP_Optimize_Premium')) return true;
158 }
159 return false;
160 }
161
162 /**
163 * 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.
164 */
165 public function plugins_loaded() {
166
167 if (is_multisite()) {
168 add_action('network_admin_menu', array($this, 'admin_menu'));
169 }
170
171 // Run Premium loader if it exists
172 if (file_exists(WPO_PLUGIN_MAIN_PATH.'/premium.php') && !class_exists('WP_Optimize_Premium')) {
173 include_once(WPO_PLUGIN_MAIN_PATH.'/premium.php');
174 }
175
176 // load defaults
177 WP_Optimize()->get_options()->set_default_options();
178
179 if ($this->is_active('premium') && false !== ($free_plugin = $this->is_active('free'))) {
180 if (!function_exists('deactivate_plugins')) include_once(ABSPATH.'wp-admin/includes/plugin.php');
181 deactivate_plugins($free_plugin);
182 // Registers the notice letting the user know it cannot be active if premium is active.
183 add_action('admin_notices', array($this, 'show_admin_notice_premium'));
184 return;
185 }
186
187
188 // Loads the language file.
189 load_plugin_textdomain('wp-optimize', false, dirname(plugin_basename(__FILE__)) . '/languages');
190 }
191
192 /**
193 * Check whether one of free/Premium is active (whether it is this instance or not)
194 *
195 * @param String $which - 'free' or 'premium'
196 *
197 * @return String|Boolean - plugin path (if installed) or false if not
198 */
199 private function is_active($which = 'free') {
200 $active_plugins = $this->get_active_plugins();
201 foreach ($active_plugins as $file) {
202 if ('wp-optimize.php' == basename($file)) {
203 $plugin_dir = WP_PLUGIN_DIR.'/'.dirname($file);
204 if (('free' == $which && !file_exists($plugin_dir.'/premium.php')) || ('free' != $which && file_exists($plugin_dir.'/premium.php'))) return $file;
205 }
206 }
207 return false;
208 }
209
210 /**
211 * Gets an array of plugins active on either the current site, or site-wide
212 *
213 * @return Array - a list of plugin paths (relative to the plugin directory)
214 */
215 private function get_active_plugins() {
216
217 // Gets all active plugins on the current site
218 $active_plugins = get_option('active_plugins');
219
220 if (is_multisite()) {
221 $network_active_plugins = get_site_option('active_sitewide_plugins');
222 if (!empty($network_active_plugins)) {
223 $network_active_plugins = array_keys($network_active_plugins);
224 $active_plugins = array_merge($active_plugins, $network_active_plugins);
225 }
226 }
227
228 return $active_plugins;
229 }
230
231 /**
232 * This function checks whether a specific plugin is installed, and returns information about it
233 *
234 * @param string $name Specify "Plugin Name" to return details about it.
235 * @return array Returns an array of details such as if installed, the name of the plugin and if it is active.
236 */
237 public function is_installed($name) {
238
239 // Needed to have the 'get_plugins()' function
240 include_once(ABSPATH.'wp-admin/includes/plugin.php');
241
242 // Gets all plugins available
243 $get_plugins = get_plugins();
244
245 $active_plugins = $this->get_active_plugins();
246
247 $plugin_info['installed'] = false;
248 $plugin_info['active'] = false;
249
250 // Loops around each plugin available.
251 foreach ($get_plugins as $key => $value) {
252 // If the plugin name matches that of the specified name, it will gather details.
253 if ($value['Name'] != $name) continue;
254 $plugin_info['installed'] = true;
255 $plugin_info['name'] = $key;
256 $plugin_info['version'] = $value['Version'];
257 if (in_array($key, $active_plugins)) {
258 $plugin_info['active'] = true;
259 }
260 break;
261 }
262 return $plugin_info;
263 }
264
265 /**
266 * This is a notice to show users that premium is installed
267 */
268 public function show_admin_notice_premium() {
269 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>';
270 if (isset($_GET['activate'])) unset($_GET['activate']);
271 }
272
273 /**
274 * Show update to Premium notice for non-premium multisite.
275 */
276 public function show_multisite_update_to_premium_notice() {
277 if (!is_multisite() || self::is_premium()) return;
278
279 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>';
280 }
281
282 public function admin_init() {
283 $pagenow = $GLOBALS['pagenow'];
284
285 $this->register_template_directories();
286
287 if (('index.php' == $pagenow && current_user_can('update_plugins')) || ('index.php' == $pagenow && defined('WP_OPTIMIZE_FORCE_DASHNOTICE') && WP_OPTIMIZE_FORCE_DASHNOTICE)) {
288 $options = $this->get_options();
289
290 $dismissed_until = $options->get_option('dismiss_dash_notice_until', 0);
291
292 if (file_exists(WPO_PLUGIN_MAIN_PATH . '/index.html')) {
293 $installed = filemtime(WPO_PLUGIN_MAIN_PATH . '/index.html');
294 $installed_for = (time() - $installed);
295 }
296
297 if (($installed && time() > $dismissed_until && $installed_for > (14 * 86400) && !defined('WP_OPTIMIZE_NOADS_B')) || (defined('WP_OPTIMIZE_FORCE_DASHNOTICE') && WP_OPTIMIZE_FORCE_DASHNOTICE)) {
298 add_action('all_admin_notices', array($this, 'show_admin_notice_upgradead'));
299 }
300 }
301 }
302
303 public function show_admin_notice_upgradead() {
304 $this->include_template('notices/thanks-for-using-main-dash.php');
305 }
306
307 public function capability_required() {
308 return apply_filters('wp_optimize_capability_required', 'manage_options');
309 }
310
311 public function wp_optimize_ajax_handler() {
312 $nonce = empty($_POST['nonce']) ? '' : $_POST['nonce'];
313
314 if (!wp_verify_nonce($nonce, 'wp-optimize-ajax-nonce') || empty($_POST['subaction'])) die('Security check');
315
316 $subaction = $_POST['subaction'];
317 $data = isset($_POST['data']) ? $_POST['data'] : null;
318
319 if (!current_user_can($this->capability_required())) die('Security check');
320
321 $wp_optimize = $this;
322 $optimizer = $this->get_optimizer();
323 $options = $this->get_options();
324
325 $results = array();
326
327 // Some commands that are available via AJAX only.
328 if (in_array($subaction, array('dismiss_dash_notice_until', 'dismiss_season'))) {
329 $options->update_option($subaction, (time() + 366 * 86400));
330 } elseif (in_array($subaction, array('dismiss_page_notice_until', 'dismiss_notice'))) {
331 $options->update_option($subaction, (time() + 84 * 86400));
332 } else {
333 // Other commands, available for any remote method.
334 if (!class_exists('WP_Optimize_Commands')) include_once(WPO_PLUGIN_MAIN_PATH . 'includes/class-commands.php');
335
336 $commands = new WP_Optimize_Commands();
337
338 if (!method_exists($commands, $subaction)) {
339 error_log("WP-Optimize: ajax_handler: no such command (".$subaction.")");
340 die('No such command');
341 } else {
342 $results = call_user_func(array($commands, $subaction), $data);
343
344 // clean status box content, it broke json sometimes.
345 if (isset($results['status_box_contents'])) {
346 $results['status_box_contents'] = str_replace(array("\n", "\t"), '', $results['status_box_contents']);
347 }
348
349 if (is_wp_error($results)) {
350 $results = array(
351 'result' => false,
352 'error_code' => $results->get_error_code(),
353 'error_message' => $results->get_error_message(),
354 'error_data' => $results->get_error_data(),
355 );
356 }
357
358 // if nothing was returned for some reason, set as result null.
359 if (empty($results)) {
360 $results = array(
361 'result' => null
362 );
363 }
364 }
365 }
366
367 $result = json_encode($results);
368
369 $json_last_error = json_last_error();
370
371 // if json_encode returned error then return error.
372 if ($json_last_error) {
373 $result = array(
374 'result' => false,
375 'error_code' => $json_last_error,
376 'error_message' => 'json_encode error : '.$json_last_error,
377 'error_data' => '',
378 );
379
380 $result = json_encode($result);
381 }
382
383 echo $result;
384
385 die;
386 }
387
388 /**
389 * Builds the Tabs that should be displayed
390 *
391 * @return String Returns all tabs specified
392 */
393 public function get_tabs() {
394 return apply_filters('wp_optimize_admin_page_tabs', array('optimize' => 'WP-Optimize', 'tables' => __('Table information', 'wp-optimize'), 'settings' => __('Settings', 'wp-optimize'), 'may_also' => __('Premium / Plugin family', 'wp-optimize')));
395 }
396
397 public function wp_optimize_menu() {
398 $capability_required = $this->capability_required();
399
400 if (!current_user_can($capability_required) || (!$this->can_run_optimizations() && !$this->can_manage_options())) {
401 echo "Permission denied.";
402 return;
403 }
404
405 $enqueue_version = (defined('WP_DEBUG') && WP_DEBUG) ? WPO_VERSION.'.'.time() : WPO_VERSION;
406 $min_or_not = (defined('SCRIPT_DEBUG') && SCRIPT_DEBUG) ? '' : '.min';
407
408 wp_enqueue_script('jquery-serialize-json', WPO_PLUGIN_URL.'js/serialize-json/jquery.serializejson'.$min_or_not.'.js', array('jquery'), $enqueue_version);
409
410 wp_register_script('updraft-queue-js', WPO_PLUGIN_URL.'js/queue'.$min_or_not.'.js', array(), $enqueue_version);
411 wp_enqueue_script('wp-optimize-admin-js', WPO_PLUGIN_URL.'js/wpadmin'.$min_or_not.'.js', array('jquery', 'updraft-queue-js'), $enqueue_version);
412 wp_enqueue_style('wp-optimize-admin-css', WPO_PLUGIN_URL.'css/admin'.$min_or_not.'.css', array(), $enqueue_version);
413 // Using tablesorter to help with organising the DB size on Table Information
414 // https://github.com/Mottie/tablesorter
415 wp_enqueue_script('tablesorter-js', WPO_PLUGIN_URL.'js/tablesorter/jquery.tablesorter'.$min_or_not.'.js', array('jquery'), $enqueue_version);
416
417 wp_enqueue_script('tablesorter-widgets-js', WPO_PLUGIN_URL.'js/tablesorter/jquery.tablesorter.widgets'.$min_or_not.'.js', array('jquery'), $enqueue_version);
418
419 wp_enqueue_style('tablesorter-css', WPO_PLUGIN_URL.'css/tablesorter/theme.default.min.css', array(), $enqueue_version);
420
421 $js_variables = $this->wpo_js_translations();
422 $js_variables['loggers_classes_info'] = $this->get_loggers_classes_info();
423
424 wp_localize_script('wp-optimize-admin-js', 'wpoptimize', $js_variables);
425
426 do_action('wpo_premium_scripts_styles', $min_or_not, $enqueue_version);
427
428 do_action('wpo_premium_scripts_styles', $min_or_not, $enqueue_version);
429
430 $options = $this->get_options();
431
432 $tabs = $this->get_tabs();
433
434 $default_tab = apply_filters('wp_optimize_admin_default_tab', 'optimize');
435
436 $active_tab = isset($_GET['tab']) ? substr($_GET['tab'], 12) : $default_tab;
437
438 if (!in_array($active_tab, array_keys($tabs))) $active_tab = $default_tab;
439
440 $nonce_passed = (!empty($_REQUEST['_wpnonce']) && wp_verify_nonce($_REQUEST['_wpnonce'], 'wpo_optimization')) ? true : false;
441
442 if ('optimize' == $active_tab && $nonce_passed && isset($_POST['wp-optimize'])) $options->save_sent_manual_run_optimization_options($_POST, true);
443
444 echo '<div id="wp-optimize-wrap" class="wrap">';
445
446 do_action('wp_optimize_admin_header');
447
448 $this->include_template('admin-page-header.php', false, array('active_tab' => $active_tab, 'tabs' => $tabs));
449
450 $optimize_db = ($nonce_passed && isset($_POST["optimize-db"])) ? true : false;
451
452 $optimizer = $this->get_optimizer();
453
454 foreach ($tabs as $tab_id => $tab_description) {
455 echo '<div class="wp-optimize-nav-tab-contents" id="wp-optimize-nav-tab-contents-'.$tab_id.'" '.(($tab_id == $active_tab) ? '' : 'style="display:none;"').'>';
456
457 do_action('wp_optimize_admin_tab_render_begin', $tab_id, $active_tab);
458
459 switch ($tab_id) {
460 case 'optimize':
461 $optimization_results = (($nonce_passed) ? $optimizer->do_optimizations($_POST) : false);
462
463 if (!empty($optimization_results)) {
464 echo '<div id="message" class="updated"><strong>';
465 foreach ($optimization_results as $optimization_result) {
466 if (!empty($optimization_result->output)) {
467 foreach ($optimization_result->output as $line) {
468 echo $line."<br>";
469 }
470 }
471 }
472 echo '</strong></div>';
473 }
474
475 if ($this->can_run_optimizations()) {
476 $this->include_template('optimize-table.php', false, array('optimize_db' => $optimize_db));
477 } else {
478 $this->prevent_run_optimizations_message();
479 }
480 break;
481
482 case 'tables':
483 if ($this->can_run_optimizations()) {
484 $this->include_template('tables.php', false, array('optimize_db' => $optimize_db));
485 } else {
486 $this->prevent_run_optimizations_message();
487 }
488 break;
489
490 case 'settings':
491 if ('POST' == $_SERVER['REQUEST_METHOD']) {
492 // Nonce check.
493 check_admin_referer('wpo_settings');
494
495 $output = $options->save_settings($_POST);
496
497 if (isset($_POST['wp-optimize-settings'])) {
498 // save settings request sent.
499 $output = $options->save_settings($_POST);
500 }
501
502 $this->wpo_render_output_messages($output);
503 }
504
505 if ($this->can_manage_options()) {
506 $this->include_template('admin-settings-general.php');
507 $this->include_template('admin-settings-auto-cleanup.php');
508 $this->include_template('admin-settings-logging.php');
509 $this->include_template('admin-settings-sidebar.php');
510 } else {
511 $this->prevent_manage_options_info();
512 }
513 break;
514
515 case 'may_also':
516 $this->include_template('may-also-like.php');
517 break;
518 }
519
520 do_action('wp_optimize_admin_tab_render_end', $tab_id, $active_tab);
521
522 echo '</div>';
523 }
524
525 echo '</div>';
526
527 }
528
529 /**
530 * Returns array of translations used in javascript code.
531 *
532 * @return array
533 */
534 public function wpo_js_translations() {
535 return apply_filters('wpo_js_translations', array(
536 'automatic_backup_before_optimizations' => __('Automatic backup before optimizations', 'wp-optimize'),
537 'error_unexpected_response' => __('An unexpected response was received.', 'wp-optimize'),
538 'optimization_complete' => __('Optimization complete', 'wp-optimize'),
539 'run_optimizations' => __('Run optimizations', 'wp-optimize'),
540 'cancel' => __('Cancel', 'wp-optimize'),
541 'please_select_settings_file' => __('Please, select settings file.', 'wp-optimize'),
542 'are_you_sure_you_want_to_remove_logging_destination' => __('Are you sure you want to remove this logging destination?', 'wp-optimize'),
543 'fill_all_settings_fields' => __('Before saving, you need to complete the currently incomplete settings (or remove them).', 'wp-optimize'),
544 'table_was_not_repaired' => __('%s was not repaired. For more details, please check your logs configured in logging destinations settings.', 'wp-optimize'),
545 'spinner_src' => esc_attr(admin_url('images/spinner-2x.gif')),
546 'sites' => $this->get_sites(),
547 ));
548 }
549
550 public function wpo_admin_bar() {
551 $wp_admin_bar = $GLOBALS['wp_admin_bar'];
552
553 if (defined('WPOPTIMIZE_ADMINBAR_DISABLE') && WPOPTIMIZE_ADMINBAR_DISABLE) return;
554
555 // Show menu item in top bar only for super admins.
556 if (is_multisite() & !is_super_admin(get_current_user_id())) return;
557
558 // Add a link called at the top admin bar.
559 $args = array(
560 'id' => 'wp-optimize-node',
561 'title' => apply_filters('wpoptimize_admin_node_title', 'WP-Optimize')
562 );
563 $wp_admin_bar->add_node($args);
564
565 $tabs = $this->get_tabs();
566
567 foreach ($tabs as $tab_id => $tab_title) {
568 $menu_page_url = menu_page_url('WP-Optimize', false). '&tab=wp_optimize_'.$tab_id;
569
570 if (is_multisite()) {
571 $menu_page_url = network_admin_url('admin.php?page=WP-Optimize&tab=wp_optimize_'.$tab_id);
572 }
573
574 $args = array(
575 'id' => 'wpoptimize_admin_node_'.$tab_id,
576 'title' => ('optimize' == $tab_id) ? __('Optimize', 'wp-optimize') : $tab_title,
577 'parent' => 'wp-optimize-node',
578 'href' => $menu_page_url
579 );
580 $wp_admin_bar->add_node($args);
581 }
582
583 }
584
585 /**
586 * Add settings link on plugin page
587 *
588 * @param string $links Passing through the URL to be used within the HREF.
589 * @return string Returns the Links.
590 */
591 public function plugin_settings_link($links) {
592
593 $admin_page_url = $this->get_options()->admin_page_url();
594
595 $settings_link = '<a href="' . esc_url($admin_page_url) . '">' . __('Settings', 'wp-optimize') . '</a>';
596 array_unshift($links, $settings_link);
597
598 $optimize_link = '<a href="' . esc_url($admin_page_url) . '">' . __('Optimizer', 'wp-optimize') . '</a>';
599 array_unshift($links, $optimize_link);
600 return $links;
601 }
602
603 /**
604 * Action wpo_tables_list_additional_column_data. Output button Optimize in the action column.
605 *
606 * @param string $content String for output to column
607 * @param object $table_info Object with table info.
608 *
609 * @return string
610 */
611 public function tables_list_additional_column_data($content, $table_info) {
612 if ($table_info->is_needing_repair) {
613 $content .= '<div class="wpo_button_wrap">'
614 .'<button class="button button-secondary run-single-table-repair" data-table="'.esc_attr($table_info->Name).'">'.__('Repair', 'wp-optimize').'</button>'
615 .'<img class="optimization_spinner visibility-hidden" src="'.esc_attr(admin_url('images/spinner-2x.gif')).'" width="20" height="20" alt="...">'
616 .'<span class="optimization_done_icon dashicons dashicons-yes visibility-hidden"></span>'
617 .'</div>';
618 }
619
620 return $content;
621 }
622
623 /**
624 * Schedules cron event based on selected schedule type
625 *
626 * @return void
627 */
628 public function cron_activate() {
629 $gmt_offset = (int) (3600 * get_option('gmt_offset'));
630
631 $options = $this->get_options();
632
633 if ($options->get_option('schedule') === false) {
634 $options->set_default_options();
635 } else {
636 if ('true' == $options->get_option('schedule')) {
637 if (!wp_next_scheduled('wpo_cron_event2')) {
638 $schedule_type = $options->get_option('schedule-type', 'wpo_weekly');
639
640 $this_time = (86400 * 7);
641
642 switch ($schedule_type) {
643 case "wpo_daily":
644 $this_time = 86400;
645 break;
646
647 case "wpo_weekly":
648 $this_time = (86400 * 7);
649 break;
650
651 case "wpo_otherweekly":
652 $this_time = (86400 * 14);
653 break;
654
655 case "wpo_monthly":
656 $this_time = (86400 * 30);
657 break;
658 }
659
660 add_action('wpo_cron_event2', array($this, 'cron_action'));
661 wp_schedule_event((current_time("timestamp", 0) + $this_time - $gmt_offset), $schedule_type, 'wpo_cron_event2');
662 WP_Optimize()->log('running wp_schedule_event()');
663 }
664 }
665 }
666 }
667
668 /**
669 * Clears all cron events
670 *
671 * @return void
672 */
673 public function wpo_cron_deactivate() {
674 wp_clear_scheduled_hook('wpo_cron_event2');
675 }
676
677 /**
678 * Scheduler public functions to update schedulers
679 *
680 * @param array $schedules An array of schedules being passed.
681 * @return array An array of schedules being returned.
682 */
683 public function cron_schedules($schedules) {
684 $schedules['wpo_daily'] = array('interval' => 86400, 'display' => 'Once Daily');
685 $schedules['wpo_weekly'] = array('interval' => 86400 * 7, 'display' => 'Once Weekly');
686 $schedules['wpo_fortnightly'] = array('interval' => 86400 * 14, 'display' => 'Once Every Fortnight');
687 $schedules['wpo_monthly'] = array('interval' => 86400 * 30, 'display' => 'Once Every Month');
688 return $schedules;
689 }
690
691 /**
692 * Returns count of overdue cron jobs.
693 *
694 * @return integer
695 */
696 public function howmany_overdue_crons() {
697 $how_many_overdue = 0;
698 if (function_exists('_get_cron_array') || (is_file(ABSPATH.WPINC.'/cron.php') && include_once(ABSPATH.WPINC.'/cron.php') && function_exists('_get_cron_array'))) {
699 $crons = _get_cron_array();
700 if (is_array($crons)) {
701 $timenow = time();
702 foreach ($crons as $jt => $job) {
703 if ($jt < $timenow) {
704 $how_many_overdue++;
705 }
706 }
707 }
708 }
709 return $how_many_overdue;
710 }
711
712 /**
713 * Returns warning about overdue crons.
714 *
715 * @param int $howmany count of overdue crons
716 * @return string
717 */
718 public function show_admin_warning_overdue_crons($howmany) {
719 $ret = '<div class="updated"><p>';
720 $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>';
721 $ret .= '</p></div>';
722 return $ret;
723 }
724
725 public function admin_menu() {
726
727 $capability_required = $this->capability_required();
728
729 if (!current_user_can($capability_required) || (!$this->can_run_optimizations() && !$this->can_manage_options())) return;
730
731 $icon_svg = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIgogICB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgdmlld0JveD0iMCAwIDE2IDE2IgogICB2ZXJzaW9uPSIxLjEiCiAgIGlkPSJzdmc0MzE2IgogICBoZWlnaHQ9IjE2IgogICB3aWR0aD0iMTYiPgogIDxkZWZzCiAgICAgaWQ9ImRlZnM0MzE4IiAvPgogIDxtZXRhZGF0YQogICAgIGlkPSJtZXRhZGF0YTQzMjEiPgogICAgPHJkZjpSREY+CiAgICAgIDxjYzpXb3JrCiAgICAgICAgIHJkZjphYm91dD0iIj4KICAgICAgICA8ZGM6Zm9ybWF0PmltYWdlL3N2Zyt4bWw8L2RjOmZvcm1hdD4KICAgICAgICA8ZGM6dHlwZQogICAgICAgICAgIHJkZjpyZXNvdXJjZT0iaHR0cDovL3B1cmwub3JnL2RjL2RjbWl0eXBlL1N0aWxsSW1hZ2UiIC8+CiAgICAgICAgPGRjOnRpdGxlPjwvZGM6dGl0bGU+CiAgICAgIDwvY2M6V29yaz4KICAgIDwvcmRmOlJERj4KICA8L21ldGFkYXRhPgogIDxnCiAgICAgaWQ9ImxheWVyMSI+CiAgICA8cGF0aAogICAgICAgc3R5bGU9ImZpbGw6I2EwYTVhYTtmaWxsLW9wYWNpdHk6MSIKICAgICAgIGlkPSJwYXRoNTciCiAgICAgICBkPSJtIDEwLjc2ODgwOSw2Ljc2MTYwNTEgMCwwIGMgLTAuMDE2ODgsLTAuMDE2ODc4IC0wLjAyNTMxLC0wLjA0MjE4MSAtMC4wMzM3NCwtMC4wNjc0OTkgLTAuMDA4NCwtMC4wMDgzOSAtMC4wMDg0LC0wLjAxNjg3OCAtMC4wMTY4OCwtMC4wMzM3NDMgQyA5Ljk5MjYxMTIsNS4xOTIzMzY2IDguMjIwODU1Nyw0LjU4NDg3ODEgNi43NDQzOTEyLDUuMjkzNTc5NyA1LjY3MjkwMDUsNS44MDgyMzI4IDUuMDU3MDA0Myw2Ljg4ODE2MTMgNS4wNjU0NDIsOC4wMDE4MzY1IDQuNDU3OTgyMiw3LjMxMDAwNzYgMy42OTg2NTg0LDYuNzk1MzU0NSAyLjg1NDk2NDIsNi40OTE2MjUzIDMuMjY4Mzc0Myw1LjA2NTc4MzEgNC4yNTU0OTYsMy44MTcxMTY2IDUuNjg5Nzc0NiwzLjEyNTI4NzggOC4zNjQyODMyLDEuODM0NDM2OCAxMS41NzAzMTksMi45Mzk2NzQ0IDEyLjg4NjQ4MSw1LjU4ODg3MjYgMTMuNDUxNzU1LDYuNzI3ODU5NiAxNC42NDk4MDEsNy4zNTIxOTIxIDE1Ljg0Nzg0Niw3LjIzNDA3NSAxNS43NjM0ODIsNi4zMzk3NiAxNS41MTg4MDUsNS40MzcwMDg2IDE1LjEwNTM5Niw0LjU3NjQ0MDQgMTMuMjE1NTIxLDAuNjg3MDEzNCA4LjUzMzAyMjYsLTAuOTQxMzE2MjcgNC42NDM1OTQzLDAuOTQwMTIxNzkgMi4zMjM0MzcsMi4wNjIyMzM0IDAuODA0Nzg4MTQsNC4xNzk5MDQ0IDAuMzU3NjMxMzIsNi41MzM4MDk4IDIuNDE2MjQzOCw2LjQyNDEyOSA0LjQzMjY3MTcsNy41MDQwNTc0IDUuNDM2NjY2Miw5LjQzNjExNjcgbCAwLjAwODM5LDAgYyAwLjc1OTMxOTIsMS4zNzUyMjAzIDIuNDcyMDE3OCwxLjk0MDQ5NTMgMy45MDYyOTYsMS4yNDg2NjczIDEuMDQ2MTc5OCwtMC41MDYyMTggMS42NTM2NDA4LC0xLjUzNTUyMzggMS42Nzg5NTA4LC0yLjYxNTQ1MTIgMC41ODIxNDgsMC43MDg3MDE4IDEuMzMzMDM1LDEuMjQ4NjY2OCAyLjE1OTg1NiwxLjU3NzcwNjQgLTAuNDM4NzIxLDEuMzU4MzQ3OCAtMS40MDA1MzMsMi41NDc5NTQ4IC0yLjc5MjYyNywzLjIxNDQ3ODggLTIuNTkwMTM4NywxLjI0ODY1OCAtNS42NzgwNTc0LDAuMjUzMTA0IC03LjA2MTcxNTEsLTIuMjI3MzU3IGwgMCwwIEMgMi43NjIxMDQ4LDkuNDUyOTg5NCAxLjUxMzQzODMsOC44MjAyMTkxIDAuMjgxNjQ1OTIsOC45NzIwODQ0IDAuMzgyODg3NjUsOS43OTg5MDQ2IDAuNjE5MTIzMzEsMTAuNjE3Mjg3IDAuOTk4Nzg1MiwxMS40MDE5MjIgYyAxLjg4MTQzNjgsMy44OTc4NjQgNi41NjM5MzcsNS41MjYxOTggMTAuNDYxODAwOCwzLjY0NDc2IDIuMjQ0MjI2LC0xLjA4ODM2OSAzLjczNzU2MiwtMy4xMDQ3OTYgNC4yMzUzNDIsLTUuMzc0MzMyMyAtMS45OTk1NTQsMC4wNDIxODEgLTMuOTQ4NDg2LC0xLjAyOTMwNjMgLTQuOTI3MTcsLTIuOTEwNzQzMyB6IgogICAgICAgY2xhc3M9InN0MTciIC8+CiAgPC9nPgo8L3N2Zz4K';
732
733 // Removes the admin menu items on the left WP bar.
734 if (!is_multisite() || (is_multisite() && is_network_admin())) {
735 add_menu_page("WP-Optimize", "WP-Optimize", $capability_required, "WP-Optimize", array($this, "wp_optimize_menu"), $icon_svg);
736 }
737
738 $options = $this->get_options();
739
740 if ($options->get_option('enable-admin-menu', 'false') == 'true') {
741 add_action('wp_before_admin_bar_render', array($this, 'wpo_admin_bar'));
742 }
743
744 }
745
746 private function wp_normalize_path($path) {
747 // Wp_normalize_path is not present before WP 3.9.
748 if (function_exists('wp_normalize_path')) return wp_normalize_path($path);
749 // Taken from WP 4.6.
750 $path = str_replace('\\', '/', $path);
751 $path = preg_replace('|(?<=.)/+|', '/', $path);
752 if (':' === substr($path, 1, 1)) {
753 $path = ucfirst($path);
754 }
755 return $path;
756 }
757
758 public function get_templates_dir() {
759 return apply_filters('wp_optimize_templates_dir', $this->wp_normalize_path(WPO_PLUGIN_MAIN_PATH.'/templates'));
760 }
761
762 public function get_templates_url() {
763 return apply_filters('wp_optimize_templates_url', WPO_PLUGIN_URL.'/templates');
764 }
765
766 public function include_template($path, $return_instead_of_echo = false, $extract_these = array()) {
767 if ($return_instead_of_echo) ob_start();
768
769 if (preg_match('#^([^/]+)/(.*)$#', $path, $matches)) {
770 $prefix = $matches[1];
771 $suffix = $matches[2];
772 if (isset($this->template_directories[$prefix])) {
773 $template_file = $this->template_directories[$prefix].'/'.$suffix;
774 }
775 }
776
777 if (!isset($template_file)) {
778 $template_file = WPO_PLUGIN_MAIN_PATH.'/templates/'.$path;
779 }
780
781 $template_file = apply_filters('wp_optimize_template', $template_file, $path);
782
783 do_action('wp_optimize_before_template', $path, $template_file, $return_instead_of_echo, $extract_these);
784
785 if (!file_exists($template_file)) {
786 error_log("WP Optimize: template not found: ".$template_file);
787 echo __('Error:', 'wp-optimize').' '.__('template not found', 'wp-optimize')." (".$path.")";
788 } else {
789 extract($extract_these);
790 $wpdb = $GLOBALS['wpdb'];
791 $wp_optimize = $this;
792 $optimizer = $this->get_optimizer();
793 $options = $this->get_options();
794 $wp_optimize_notices = $this->get_notices();
795 include $template_file;
796 }
797
798 do_action('wp_optimize_after_template', $path, $template_file, $return_instead_of_echo, $extract_these);
799
800 if ($return_instead_of_echo) return ob_get_clean();
801 }
802
803 /**
804 * Build a list of template directories (stored in self::$template_directories)
805 */
806 private function register_template_directories() {
807
808 $template_directories = array();
809
810 $templates_dir = $this->get_templates_dir();
811
812 if ($dh = opendir($templates_dir)) {
813 while (($file = readdir($dh)) !== false) {
814 if ('.' == $file || '..' == $file) continue;
815 if (is_dir($templates_dir.'/'.$file)) {
816 $template_directories[$file] = $templates_dir.'/'.$file;
817 }
818 }
819 closedir($dh);
820 }
821
822 // Optimal hook for most extensions to hook into.
823 $this->template_directories = apply_filters('wp_optimize_template_directories', $template_directories);
824
825 }
826
827 /**
828 * Not currently used; needs looking at.
829 * N.B. The description does not match the actual function
830 *
831 * @param integer $date Date of when the optimization was executed.
832 */
833 public function send_email($date) {
834 ob_start();
835 // This need to work on - currently not using the parameter values.
836 $my_time = current_time("timestamp", 0);
837 $my_date = gmdate(get_option('date_format') . ' ' . get_option('time_format'), $my_time);
838 $sendto = (!$options->get_option('email-address') ? get_bloginfo('admin_email') : $options->get_option('email-address'));
839 $subject = get_bloginfo('name').": ".__("Automatic Operation Completed", "wp-optimize")." ".$my_date;
840
841 $msg = __("Scheduled optimization was executed at", "wp-optimize")." ".$my_date."\r\n"."\r\n";
842 $msg .= __("You can safely delete this email.", "wp-optimize")."\r\n";
843 $msg .= "\r\n";
844 $msg .= __("Regards,", "wp-optimize")."\r\n";
845 $msg .= __("WP-Optimize Plugin", "wp-optimize");
846 ob_end_clean();
847 }
848
849 /**
850 * Message to debug
851 *
852 * @param string $message Message to insert into the log.
853 * @param array $context Context of the log.
854 */
855 public function log($message, $context = array()) {
856 $this->get_logger()->debug($message, $context);
857 }
858
859 /**
860 * Format Bytes Into KB/MB
861 *
862 * @param mixed $bytes Number of bytes to be converted.
863 * @return integer return the correct format size.
864 */
865 public function format_size($bytes) {
866 if ($bytes > 1073741824) {
867 return number_format_i18n(($bytes / 1073741824), 2) . ' '.__('GB', 'wp-optimize');
868 } elseif ($bytes > 1048576) {
869 return number_format_i18n(($bytes / 1048576), 1) . ' '.__('MB', 'wp-optimize');
870 } elseif ($bytes > 1024) {
871 return number_format_i18n(($bytes / 1024), 1) . ' '.__('KB', 'wp-optimize');
872 } else {
873 return number_format_i18n($bytes, 0) . ' '.__('bytes', 'wp-optimize');
874 }
875 }
876
877 /**
878 * Executed this function on cron event.
879 *
880 * @return void
881 */
882 public function cron_action() {
883
884 $optimizer = $this->get_optimizer();
885 $options = $this->get_options();
886
887 $this->log('WPO: Starting cron_action()');
888
889 if ('true' == $options->get_option('schedule')) {
890 $this_options = $options->get_option('auto');
891
892 $optimizations = $optimizer->get_optimizations();
893
894 // Currently the output of the optimizations is not saved/used/logged.
895 $results = $optimizer->do_optimizations($this_options, 'auto');
896 }
897
898 }
899
900 /**
901 * Schedule cron tasks used by plugin.
902 *
903 * @return void
904 */
905 public function schedule_plugin_cron_tasks() {
906 if (!wp_next_scheduled('wpo_plugin_cron_tasks')) {
907 wp_schedule_event(current_time("timestamp", 0), 'twicedaily', 'wpo_plugin_cron_tasks');
908 }
909
910 add_action('wpo_plugin_cron_tasks', array($this, 'do_plugin_cron_tasks'));
911 }
912
913 /**
914 * Do plugin background tasks.
915 *
916 * @return void
917 */
918 public function do_plugin_cron_tasks() {
919 // get information about corrupted tables.
920 $this->update_corrupted_tables_count();
921 }
922
923 /**
924 * Update corrupted tables count used with wp_optimize_get_tables filter.
925
926 * @return void
927 */
928 public function update_corrupted_tables_count() {
929 $tables = $this->get_optimizer()->get_tables();
930
931 $corrupted_tables_count = 0;
932
933 if (!empty($tables)) {
934 foreach ($tables as $table) {
935 if ($table->is_needing_repair) {
936 $corrupted_tables_count++;
937 }
938 }
939 }
940
941 // save results to options table and use it to notify user about corrupted tables.
942 $this->get_options()->update_option('corrupted-tables-count', $corrupted_tables_count);
943 }
944
945 /**
946 * This will customize a URL with a correct Affiliate link
947 * This function can be update to suit any URL as longs as the URL is passed
948 *
949 * @param String $url - URL to be check to see if it an updraftplus match.
950 * @param String $text - Text to be entered within the href a tags.
951 * @param String $html - Any specific HTML to be added.
952 * @param String $class - Specify a class for the href (including the attribute label)
953 * @param Boolean $return_instead_of_echo - if set, then the result will be returned, not echo-ed.
954 *
955 * @return String|void
956 */
957 public function wp_optimize_url($url, $text, $html = '', $class = '', $return_instead_of_echo = false) {
958 // Check if the URL is UpdraftPlus.
959 if (false !== strpos($url, '//updraftplus.com')) {
960 // Set URL with Affiliate ID.
961 $url = $url.'?afref='.$this->get_notices()->get_affiliate_id();
962
963 // Apply filters.
964 $url = apply_filters('wpoptimize_updraftplus_com_link', $url);
965 }
966 // Return URL - check if there is HTML such as images.
967 if ('' != $html) {
968 $result = '<a '.$class.' href="'.esc_attr($url).'">'.$html.'</a>';
969 } else {
970 $result = '<a '.$class.' href="'.esc_attr($url).'">'.htmlspecialchars($text).'</a>';
971 }
972 if ($return_instead_of_echo) return $result;
973 echo $result;
974 }
975
976 /**
977 * Setup WPO logger(s)
978 */
979 public function setup_loggers() {
980
981 $logger = $this->get_logger();
982 $loggers = $this->wpo_loggers();
983
984 if (!empty($loggers)) {
985 foreach ($loggers as $_logger) {
986 $logger->add_logger($_logger);
987 }
988 }
989
990 add_action('wp_optimize_after_optimizations', array($this, 'after_optimizations_logger_action'));
991 }
992
993 /**
994 * Run logger actions after all optimizations done
995 */
996 public function after_optimizations_logger_action() {
997 $loggers = $this->get_logger()->get_loggers();
998 if (!empty($loggers)) {
999 foreach ($loggers as $logger) {
1000 if (is_a($logger, 'Updraft_Email_Logger')) {
1001 $logger->flush_log();
1002 }
1003 }
1004 }
1005 }
1006
1007 /**
1008 * Returns list of WPO loggers instances
1009 * Apply filter wp_optimize_loggers
1010 *
1011 * @return array
1012 */
1013 public function wpo_loggers() {
1014
1015 $loggers = array();
1016 $loggers_classes_by_id = array();
1017 $options_keys = array();
1018
1019 $loggers_classes = $this->get_loggers_classes();
1020
1021 foreach ($loggers_classes as $logger_class => $source) {
1022 $loggers_classes_by_id[strtolower($logger_class)] = $logger_class;
1023 }
1024
1025 $saved_loggers = $this->get_options()->get_option('logging');
1026 $logger_additional_options = $this->get_options()->get_option('logging-additional');
1027
1028 // create loggers classes instances.
1029 if (!empty($saved_loggers)) {
1030 // check for previous version options format.
1031 $keys = array_keys($saved_loggers);
1032
1033 // if options stored in old format then reformat it.
1034 if (false == is_numeric($keys[0])) {
1035 $_saved_loggers = array();
1036 foreach ($saved_loggers as $logger_id => $enabled) {
1037 if ($enabled) {
1038 $_saved_loggers[] = $logger_id;
1039 }
1040 }
1041
1042 // fill email with admin.
1043 if (array_key_exists('updraft_email_logger', $saved_loggers) && $saved_loggers['updraft_email_logger']) {
1044 $logger_additional_options['updraft_email_logger'] = array(
1045 get_option('admin_email')
1046 );
1047 }
1048
1049 $saved_loggers = $_saved_loggers;
1050 }
1051
1052 foreach ($saved_loggers as $i => $logger_id) {
1053
1054 if (!array_key_exists($logger_id, $loggers_classes_by_id)) continue;
1055
1056 $logger_class = $loggers_classes_by_id[$logger_id];
1057
1058 $logger = new $logger_class();
1059
1060 $logger_options = $logger->get_options_list();
1061
1062 if (!empty($logger_options)) {
1063 foreach (array_keys($logger_options) as $option_name) {
1064 if (array_key_exists($option_name, $options_keys)) {
1065 $options_keys[$option_name]++;
1066 } else {
1067 $options_keys[$option_name] = 0;
1068 }
1069
1070 $option_value = isset($logger_additional_options[$option_name][$options_keys[$option_name]]) ? $logger_additional_options[$option_name][$options_keys[$option_name]] : '';
1071
1072 // if options in old format then get correct value.
1073 if ('' === $option_value && array_key_exists($logger_id, $logger_additional_options)) {
1074 $option_value = array_shift($logger_additional_options[$logger_id]);
1075 }
1076
1077 $logger->set_option($option_name, $option_value);
1078 }
1079 }
1080
1081 // check if logger is active.
1082 $active = (!is_array($logger_additional_options) || (array_key_exists('active', $logger_additional_options) && empty($logger_additional_options['active'][$i]))) ? false : true;
1083
1084 if ($active) {
1085 $logger->enable();
1086 } else {
1087 $logger->disable();
1088 }
1089
1090 $loggers[] = $logger;
1091 }
1092 }
1093
1094 $loggers = apply_filters('wp_optimize_loggers', $loggers);
1095
1096 return $loggers;
1097 }
1098
1099 /**
1100 * Returns associative array with logger class name in a key and path to class file in a value.
1101 *
1102 * @return array
1103 */
1104 public function get_loggers_classes() {
1105 $loggers_classes = array(
1106 'Updraft_PHP_Logger' => WPO_PLUGIN_MAIN_PATH . 'includes/class-updraft-php-logger.php',
1107 'Updraft_Email_Logger' => WPO_PLUGIN_MAIN_PATH . 'includes/class-updraft-email-logger.php',
1108 'Updraft_Ring_Logger' => WPO_PLUGIN_MAIN_PATH . 'includes/class-updraft-ring-logger.php'
1109 );
1110
1111 $loggers_classes = apply_filters('wp_optimize_loggers_classes', $loggers_classes);
1112
1113 if (!empty($loggers_classes)) {
1114 foreach ($loggers_classes as $logger_class => $logger_file) {
1115 if (!class_exists($logger_class)) {
1116 if (is_file($logger_file)) {
1117 include_once($logger_file);
1118 }
1119 }
1120 }
1121 }
1122
1123 return $loggers_classes;
1124 }
1125
1126 /**
1127 * Returns information about all loggers classes.
1128 *
1129 * @return array
1130 */
1131 public function get_loggers_classes_info() {
1132 $loggers_classes = $this->get_loggers_classes();
1133
1134 $loggers_classes_info = array();
1135
1136 if (!empty($loggers_classes)) {
1137 foreach (array_keys($loggers_classes) as $logger_class_name) {
1138
1139 if (!class_exists($logger_class_name)) continue;
1140
1141 $logger_id = strtolower($logger_class_name);
1142 $logger_class = new $logger_class_name();
1143
1144 $loggers_classes_info[$logger_id] = array(
1145 'description' => $logger_class->get_description(),
1146 'available' => $logger_class->is_available(),
1147 'allow_multiple' => $logger_class->is_allow_multiple(),
1148 'options' => $logger_class->get_options_list()
1149 );
1150 }
1151 }
1152
1153 return $loggers_classes_info;
1154 }
1155
1156 /**
1157 * Returns true if optimization works in multisite mode
1158 *
1159 * @return boolean
1160 */
1161 public function is_multisite_mode() {
1162 return (is_multisite() && WP_Optimize()->is_premium());
1163 }
1164
1165 /**
1166 * Returns true if current user can run optimizations.
1167 *
1168 * @return bool
1169 */
1170 public function can_run_optimizations() {
1171 // we don't check permissions for cron jobs.
1172 if (defined('DOING_CRON') && DOING_CRON) return true;
1173
1174 if (self::is_premium() && false == user_can(get_current_user_id(), 'wpo_run_optimizations')) return false;
1175 return true;
1176 }
1177
1178 /**
1179 * Returns true if current user can manage plugin options.
1180 *
1181 * @return bool
1182 */
1183 public function can_manage_options() {
1184 if (self::is_premium() && false == user_can(get_current_user_id(), 'wpo_manage_settings')) return false;
1185 return true;
1186 }
1187
1188 /**
1189 * Output information message for users who have no permissions to run optimizations.
1190 */
1191 public function prevent_run_optimizations_message() {
1192 $this->include_template('info-message.php', false, array('message' => __('You have no permissions to run optimizations.', 'wp-optimize')));
1193 }
1194
1195 /**
1196 * Output information message for users who have no permissions to manage settings.
1197 */
1198 public function prevent_manage_options_info() {
1199 $this->include_template('info-message.php', false, array('message' => __('You have no permissions to manage WP-Optimize settings.', 'wp-optimize')));
1200 }
1201
1202 /**
1203 * Returns list of all sites in multisite
1204 *
1205 * @return array
1206 */
1207 public function get_sites() {
1208 $sites = array();
1209 // check if function get_sites exists (since 4.6.0) else use wp_get_sites.
1210 if (function_exists('get_sites')) {
1211 $sites = get_sites(array('network_id' => null, 'number' => 99999));
1212 } elseif (function_exists('wp_get_sites')) {
1213 // @codingStandardsIgnoreLine
1214 $sites = wp_get_sites(array('network_id' => null, 'limit' => 99999));
1215 }
1216 return $sites;
1217 }
1218
1219 /**
1220 * Output success/error messages from $output array.
1221 *
1222 * @param array $output ['messages' => success messages, 'errors' => error messages]
1223 */
1224 private function wpo_render_output_messages($output) {
1225 foreach ($output['messages'] as $item) {
1226 echo '<div class="updated fade"><strong>'.$item.'</strong></div>';
1227 }
1228
1229 foreach ($output['errors'] as $item) {
1230 echo '<div class="error fade"><strong>'.$item.'</strong></div>';
1231 }
1232 }
1233
1234 /**
1235 * Returns script memory limit in megabytes.
1236 *
1237 * @param bool $memory_limit
1238 * @return int
1239 */
1240 public function get_memory_limit($memory_limit = false) {
1241 // Returns in megabytes
1242 if (false == $memory_limit) $memory_limit = ini_get('memory_limit');
1243 $memory_limit = rtrim($memory_limit);
1244
1245 return $this->return_bytes($memory_limit);
1246 }
1247
1248 /**
1249 * Returns free memory in bytes.
1250 *
1251 * @return int
1252 */
1253 public function get_free_memory() {
1254 return $this->get_memory_limit() - memory_get_usage();
1255 }
1256
1257 /**
1258 * Checks PHP memory_limit and WP_MAX_MEMORY_LIMIT values and return minimal.
1259 *
1260 * @return int memory limit in bytes.
1261 */
1262 public function get_script_memory_limit() {
1263 $memory_limit = $this->get_memory_limit();
1264
1265 if (defined('WP_MAX_MEMORY_LIMIT')) {
1266 $wp_memory_limit = $this->get_memory_limit(WP_MAX_MEMORY_LIMIT);
1267
1268 if ($wp_memory_limit > 0 && $wp_memory_limit < $memory_limit) {
1269 $memory_limit = $wp_memory_limit;
1270 }
1271 }
1272
1273 return $memory_limit;
1274 }
1275
1276 /**
1277 * Returns max packet size for database.
1278 *
1279 * @return int|string
1280 */
1281 public function get_max_packet_size() {
1282 global $wpdb;
1283 static $mp = 0;
1284
1285 if ($mp > 0) return $mp;
1286
1287 $mp = (int) $wpdb->get_var("SELECT @@session.max_allowed_packet");
1288 // Default to 1MB
1289 $mp = (is_numeric($mp) && $mp > 0) ? $mp : 1048576;
1290 // 32MB
1291 if ($mp < 33554432) {
1292 $save = $wpdb->show_errors(false);
1293 // @codingStandardsIgnoreLine
1294 $req = @$wpdb->query("SET GLOBAL max_allowed_packet=33554432");
1295 $wpdb->show_errors($save);
1296
1297 $mp = (int) $wpdb->get_var("SELECT @@session.max_allowed_packet");
1298 // Default to 1MB
1299 $mp = (is_numeric($mp) && $mp > 0) ? $mp : 1048576;
1300 }
1301
1302 return $mp;
1303 }
1304
1305 /**
1306 * Converts shorthand memory notation value to bytes.
1307 * From http://php.net/manual/en/function.ini-get.php
1308 *
1309 * @param string $val shorthand memory notation value.
1310 */
1311 public function return_bytes($val) {
1312 $val = trim($val);
1313 $last = strtolower($val[strlen($val)-1]);
1314 $val = (int) $val;
1315 switch ($last) {
1316 case 'g':
1317 $val *= 1024;
1318 // no break
1319 case 'm':
1320 $val *= 1024;
1321 // no break
1322 case 'k':
1323 $val *= 1024;
1324 }
1325
1326 return $val;
1327 }
1328
1329 /**
1330 * Log fatal errors to defined log destinations.
1331 */
1332 public function log_fatal_errors() {
1333 $last_error = error_get_last();
1334
1335 if (E_ERROR === $last_error['type']) {
1336 $this->get_logger()->critical($last_error['message']);
1337 die();
1338 }
1339 }
1340 }
1341
1342 /**
1343 * Plugin activation actions.
1344 */
1345 function wpo_activation_actions() {
1346 // If plugin activated by not a Network Administrator then deactivate plugin and show message.
1347 if (is_multisite() && !is_network_admin()) {
1348 deactivate_plugins(plugin_basename(__FILE__));
1349 wp_die(__('Only Network Administrator can activate WP-Optimize plugin.', 'wp-optimize').
1350 ' <a href="'.admin_url('plugins.php').'">'.__('go back', 'wp-optimize').'</a>');
1351 }
1352
1353 WP_Optimize()->get_options()->set_default_options();
1354 }
1355
1356 /**
1357 * Plugin deactivation actions.
1358 */
1359 function wpo_deactivation_actions() {
1360 WP_Optimize()->wpo_cron_deactivate();
1361 }
1362
1363 function wpo_cron_deactivate() {
1364 WP_Optimize()->log('running wpo_cron_deactivate()');
1365 wp_clear_scheduled_hook('wpo_cron_event2');
1366 }
1367
1368 /**
1369 * Plugin uninstall actions.
1370 */
1371 function wpo_uninstall_actions() {
1372 WP_Optimize()->get_options()->delete_all_options();
1373 wp_clear_scheduled_hook('wpo_cron_plugin');
1374 }
1375
1376 function WP_Optimize() {
1377 return WP_Optimize::instance();
1378 }
1379
1380 endif;
1381
1382 $GLOBALS['wp_optimize'] = WP_Optimize();
1383