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

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