=') ? true : false); class WP_Optimize { public $premium_version_link = 'https://getwpo.com/buy/'; private $template_directories; protected static $_instance = null; protected static $_optimizer_instance = null; protected static $_options_instance = null; protected static $_minify_instance = null; protected static $_notices_instance = null; protected static $_logger_instance = null; protected static $_browser_cache = null; protected static $_db_info = null; protected static $_cache = null; protected static $_gzip_compression = null; /** * Class constructor */ public function __construct() { // Checks if premium is installed along with plugins needed. add_action('plugins_loaded', array($this, 'plugins_loaded'), 1); register_activation_hook(__FILE__, 'wpo_activation_actions'); register_deactivation_hook(__FILE__, 'wpo_deactivation_actions'); register_uninstall_hook(__FILE__, 'wpo_uninstall_actions'); add_action('admin_init', array($this, 'admin_init')); add_action('admin_menu', array($this, 'admin_menu')); add_action('admin_bar_menu', array($this, 'cache_admin_bar'), 100, 1); add_filter("plugin_action_links_".plugin_basename(__FILE__), array($this, 'plugin_settings_link')); add_action('wpo_cron_event2', array($this, 'cron_action')); add_filter('cron_schedules', array($this, 'cron_schedules')); if (!$this->get_options()->get_option('installed-for', false)) $this->get_options()->update_option('installed-for', time()); if (!self::is_premium()) { add_action('auto_option_settings', array($this->get_options(), 'auto_option_settings')); } add_action('admin_enqueue_scripts', array($this, 'admin_enqueue_scripts')); add_action('wp_enqueue_scripts', array($this, 'frontend_enqueue_scripts')); add_action('wp_ajax_wp_optimize_ajax', array($this, 'wp_optimize_ajax_handler')); // Show update to Premium notice for non-premium multisite. add_action('wpo_additional_options', array($this, 'show_multisite_update_to_premium_notice')); // Action column (show repair button if need). add_filter('wpo_tables_list_additional_column_data', array($this, 'tables_list_additional_column_data'), 15, 2); /** * Add action for display Images > Compress images tab. */ add_action('wp_optimize_admin_page_wpo_images_smush', array($this, 'admin_page_wpo_images_smush')); include_once(WPO_PLUGIN_MAIN_PATH.'includes/updraftcentral.php'); include_once(WPO_PLUGIN_MAIN_PATH.'includes/backward-compatibility-functions.php'); register_shutdown_function(array($this, 'log_fatal_errors')); $this->schedule_plugin_cron_tasks(); add_action('wpo_admin_before_closing_wrap', array($this, 'load_modal_template'), 20); add_action('upgrader_process_complete', array($this, 'detect_active_plugins_and_themes_updates'), 10, 2); } /** * Detect when an active plugin or theme is updated, and trigger an action * * @param object $upgrader_object * @param array $options * @return void */ public function detect_active_plugins_and_themes_updates($upgrader_object, $options) { if (empty($options) || !isset($options['type'])) return; $should_purge_cache = false; $skin = $upgrader_object->skin; if ('plugin' === $options['type']) { // A plugin is updated using the default update system (upgrader_overwrote_package is used for the upload method) if (property_exists($skin, 'plugin_active') && $skin->plugin_active) { $should_purge_cache = true; } } elseif ('theme' === $options['type']) { $active_theme = get_stylesheet(); $parent_theme = get_template(); // A theme is updated using the upload system if (isset($options['action']) && 'install' === $options['action'] && 'update-theme' === $skin->options['overwrite']) { $updated_theme = $upgrader_object->result['destination_name']; // Check if the theme is in use if ($active_theme == $updated_theme || $parent_theme == $updated_theme) { $should_purge_cache = true; } // A theme is updated using the classic update system } elseif (isset($options['action']) && 'update' === $options['action'] && isset($options['themes']) && is_array($options['themes'])) { // Check if the theme is in use if (in_array($active_theme, $options['themes']) || in_array($parent_theme, $options['themes'])) { $should_purge_cache = true; } } } /** * Action executed when an active theme or plugin was updated */ if ($should_purge_cache) do_action('wpo_active_plugin_or_theme_updated'); } public function admin_page_wpo_images_smush() { $options = Updraft_Smush_Manager()->get_smush_options(); $custom = 100 != $options['image_quality'] && 90 != $options['image_quality'] ? true : false; $this->include_template('images/smush.php', false, array('smush_options' => $options, 'custom' => $custom, 'does_server_allows_local_webp_conversion' => $this->does_server_allows_local_webp_conversion())); } public static function instance() { if (empty(self::$_instance)) { self::$_instance = new self(); } return self::$_instance; } public static function get_optimizer() { if (empty(self::$_optimizer_instance)) { if (!class_exists('WP_Optimizer')) include_once(WPO_PLUGIN_MAIN_PATH.'includes/class-wp-optimizer.php'); self::$_optimizer_instance = new WP_Optimizer(); } return self::$_optimizer_instance; } /** * Get and instanciate WP_Optimize_Minify * * @return WP_Optimize_Minify */ public function get_minify() { if (empty(self::$_minify_instance)) { if (!class_exists('WP_Optimize_Minify')) { include_once WPO_PLUGIN_MAIN_PATH.'minify/class-wp-optimize-minify.php'; } self::$_minify_instance = new WP_Optimize_Minify(); } return self::$_minify_instance; } public static function get_options() { if (empty(self::$_options_instance)) { if (!class_exists('WP_Optimize_Options')) include_once(WPO_PLUGIN_MAIN_PATH.'includes/class-wp-optimize-options.php'); self::$_options_instance = new WP_Optimize_Options(); } return self::$_options_instance; } public static function get_notices() { if (empty(self::$_notices_instance)) { if (!class_exists('WP_Optimize_Notices')) include_once(WPO_PLUGIN_MAIN_PATH.'includes/wp-optimize-notices.php'); self::$_notices_instance = new WP_Optimize_Notices(); } return self::$_notices_instance; } /** * Returns instance if WPO_Page_Cache class. * * @return WPO_Page_Cache */ public function get_page_cache() { if (!class_exists('WPO_Page_Cache')) include_once(WPO_PLUGIN_MAIN_PATH.'cache/class-wpo-page-cache.php'); return WPO_Page_Cache::instance(); } /** * Returns instance if WP_Optimize_WebP class. * * @return WP_Optimize_WebP */ public function get_webp_instance() { if (defined('WPO_USE_WEBP_CONVERSION') && true === WPO_USE_WEBP_CONVERSION) { if (!class_exists('WP_Optimize_WebP')) { include_once WPO_PLUGIN_MAIN_PATH . 'webp/class-wp-optimize-webp.php'; } return WP_Optimize_WebP::get_instance(); } } /** * Detects if the platform is Kinsta or not * * @return bool Returns true if it is Kinsta platform, otherwise returns false */ private function is_kinsta() { return isset($_SERVER['KINSTA_CACHE_ZONE']); } /** * Detects whether the server handles cache. eg. Nginx cache */ private function does_server_handles_cache() { return $this->is_kinsta(); } /** * Detects whether the server supports table optimization. * * Some servers prevent table optimization * because InnoDB engine does not optimize table * instead it drops tables and recreate them * which results in elevated disk write operations */ public function does_server_allows_table_optimization() { return !$this->is_kinsta(); } /** * Detects whether the server supports local webp conversion tools */ private function does_server_allows_local_webp_conversion() { return !$this->is_kinsta(); } /** * Create instance of WP_Optimize_Browser_Cache. * * @return WP_Optimize_Browser_Cache */ public static function get_browser_cache() { if (empty(self::$_browser_cache)) { if (!class_exists('WP_Optimize_Browser_Cache')) include_once(WPO_PLUGIN_MAIN_PATH.'includes/class-wp-optimize-browser-cache.php'); self::$_browser_cache = new WP_Optimize_Browser_Cache(); } return self::$_browser_cache; } /** * Returns WP_Optimize_Database_Information instance. * * @return WP_Optimize_Database_Information */ public function get_db_info() { if (empty(self::$_db_info)) { if (!class_exists('WP_Optimize_Database_Information')) include_once(WPO_PLUGIN_MAIN_PATH.'includes/wp-optimize-database-information.php'); self::$_db_info = new WP_Optimize_Database_Information(); } return self::$_db_info; } /** * Returns instance of WP_Optimize_Gzip_Compression. * * @return WP_Optimize_Gzip_Compression */ static public function get_gzip_compression() { if (empty(self::$_gzip_compression)) { if (!class_exists('WP_Optimize_Gzip_Compression')) include_once(WPO_PLUGIN_MAIN_PATH.'includes/class-wp-optimize-gzip-compression.php'); self::$_gzip_compression = new WP_Optimize_Gzip_Compression(); } return self::$_gzip_compression; } /** * Create instance of WP_Optimize_Htaccess. * * @param string $htaccess_file absolute path to htaccess file, by default it use .htaccess in WordPress root directory. * @return WP_Optimize_Htaccess */ public static function get_htaccess($htaccess_file = '') { if (!class_exists('WP_Optimize_Cache')) { include_once(WPO_PLUGIN_MAIN_PATH . '/includes/class-wp-optimize-htaccess.php'); } return new WP_Optimize_Htaccess($htaccess_file); } /** * Return instance of Updraft_Logger * * @return Updraft_Logger */ public static function get_logger() { if (empty(self::$_logger_instance)) { include_once(WPO_PLUGIN_MAIN_PATH.'includes/class-updraft-logger.php'); self::$_logger_instance = new Updraft_Logger(); } return self::$_logger_instance; } /** * Check if the current page belongs to WP-Optimize. * * @return bool */ public function is_wpo_page() { $current_screen = get_current_screen(); return (bool) preg_match('/wp\-optimize/i', $current_screen->id); } /** * Enqueue scripts and styles on WP-Optimize pages. */ public function admin_enqueue_scripts() { $enqueue_version = (defined('WP_DEBUG') && WP_DEBUG) ? WPO_VERSION.'.'.time() : WPO_VERSION; $min_or_not = (defined('SCRIPT_DEBUG') && SCRIPT_DEBUG) ? '' : '.min'; $min_or_not_internal = (defined('SCRIPT_DEBUG') && SCRIPT_DEBUG) ? '' : '-'. str_replace('.', '-', WPO_VERSION). '.min'; // Register or enqueue common scripts wp_register_script('wp-optimize-send-command', WPO_PLUGIN_URL.'js/send-command'.$min_or_not_internal.'.js', array(), $enqueue_version); wp_localize_script('wp-optimize-send-command', 'wp_optimize_send_command_data', array('nonce' => wp_create_nonce('wp-optimize-ajax-nonce'))); wp_enqueue_style('wp-optimize-global', WPO_PLUGIN_URL.'css/wp-optimize-global'.$min_or_not_internal.'.css', array(), $enqueue_version); // load scripts and styles only on WP-Optimize pages. if (!$this->is_wpo_page()) return; wp_enqueue_script('jquery-serialize-json', WPO_PLUGIN_URL.'js/serialize-json/jquery.serializejson'.$min_or_not.'.js', array('jquery'), $enqueue_version); wp_register_script('updraft-queue-js', WPO_PLUGIN_URL.'js/queue'.$min_or_not_internal.'.js', array(), $enqueue_version); wp_enqueue_script('wp-optimize-modal', WPO_PLUGIN_URL.'js/modal'.$min_or_not_internal.'.js', array('jquery', 'backbone', 'wp-util'), $enqueue_version); wp_enqueue_script('wp-optimize-cache-js', WPO_PLUGIN_URL.'js/cache'.$min_or_not_internal.'.js', array('wp-optimize-send-command', 'smush-js'), $enqueue_version); wp_enqueue_script('wp-optimize-admin-js', WPO_PLUGIN_URL.'js/wpoadmin'.$min_or_not_internal.'.js', array('jquery', 'updraft-queue-js', 'wp-optimize-send-command', 'smush-js', 'wp-optimize-modal'), $enqueue_version); wp_enqueue_style('wp-optimize-admin-css', WPO_PLUGIN_URL.'css/wp-optimize-admin'.$min_or_not_internal.'.css', array(), $enqueue_version); // Using tablesorter to help with organising the DB size on Table Information // https://github.com/Mottie/tablesorter wp_enqueue_script('tablesorter-js', WPO_PLUGIN_URL.'js/tablesorter/jquery.tablesorter'.$min_or_not.'.js', array('jquery', 'wp-optimize-send-command'), $enqueue_version); wp_enqueue_script('tablesorter-widgets-js', WPO_PLUGIN_URL.'js/tablesorter/jquery.tablesorter.widgets'.$min_or_not.'.js', array('jquery'), $enqueue_version); // wp_enqueue_style('tablesorter-css', WPO_PLUGIN_URL.'css/tablesorter/theme.default.min.css', array(), $enqueue_version); $js_variables = $this->wpo_js_translations(); $js_variables['loggers_classes_info'] = $this->get_loggers_classes_info(); wp_localize_script('wp-optimize-admin-js', 'wpoptimize', $js_variables); do_action('wpo_premium_scripts_styles', $min_or_not_internal, $min_or_not, $enqueue_version); } /** * Enqueue any required front-end scripts * * @return void */ public function frontend_enqueue_scripts() { if (!current_user_can('manage_options') || !is_admin_bar_showing()) return; $enqueue_version = (defined('WP_DEBUG') && WP_DEBUG) ? WPO_VERSION.'.'.time() : WPO_VERSION; $min_or_not_internal = (defined('SCRIPT_DEBUG') && SCRIPT_DEBUG) ? '' : '-'. str_replace('.', '-', WPO_VERSION). '.min'; // Register or enqueue common scripts wp_enqueue_style('wp-optimize-global', WPO_PLUGIN_URL.'css/wp-optimize-global'.$min_or_not_internal.'.css', array(), $enqueue_version); } /** * Load Task Manager */ public function get_task_manager() { include_once(WPO_PLUGIN_MAIN_PATH.'vendor/team-updraft/common-libs/src/updraft-tasks/class-updraft-tasks-activation.php'); Updraft_Tasks_Activation::check_updates(); include_once(WPO_PLUGIN_MAIN_PATH . '/vendor/team-updraft/common-libs/src/updraft-tasks/class-updraft-task-meta.php'); include_once(WPO_PLUGIN_MAIN_PATH . '/vendor/team-updraft/common-libs/src/updraft-tasks/class-updraft-task-options.php'); include_once(WPO_PLUGIN_MAIN_PATH . '/vendor/team-updraft/common-libs/src/updraft-tasks/class-updraft-task.php'); include_once(WPO_PLUGIN_MAIN_PATH . '/includes/class-updraft-smush-task.php'); include_once(WPO_PLUGIN_MAIN_PATH . '/includes/class-updraft-smush-manager.php'); return Updraft_Smush_Manager(); } /** * Indicate whether we have an associated instance of WP-Optimize Premium or not. * * @returns Boolean */ public static function is_premium() { if (file_exists(WPO_PLUGIN_MAIN_PATH.'premium.php') && function_exists('WP_Optimize_Premium')) { $wp_optimize_premium = WP_Optimize_Premium(); if (is_a($wp_optimize_premium, 'WP_Optimize_Premium')) return true; } return false; } /** * Check if script running on Apache web server. $is_apache is set in wp-includes/vars.php. Also returns true if the server uses litespeed. * * @return bool */ public function is_apache_server() { global $is_apache; return $is_apache; } /** * Check if script running on IIS web server. * * @return bool */ public function is_IIS_server() { global $is_IIS, $is_iis7; return $is_IIS || $is_iis7; } /** * Check if Apache module or modules active. * * @param string|array $module - single Apache module name or list of Apache module names. * * @return bool|null - if null, the result was indeterminate */ public function is_apache_module_loaded($module) { if (!$this->is_apache_server()) return false; if (!function_exists('apache_get_modules')) return null; $module_loaded = true; if (is_array($module)) { foreach ($module as $single_module) { if (!in_array($single_module, apache_get_modules())) { $module_loaded = false; break; } } } else { $module_loaded = in_array($module, apache_get_modules()); } return $module_loaded; } /** * 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. */ public function plugins_loaded() { if (is_multisite()) { add_action('network_admin_menu', array($this, 'admin_menu')); } if ($this->does_server_handles_cache()) { add_filter('wp_optimize_admin_page_wpo_cache_tabs', array($this, 'filter_cache_tabs'), 99, 1); // If newly migrated to server that handles cache, disable wpo cache $cache = $this->get_page_cache(); if ($cache->is_enabled()) { $cache->disable(); } } add_filter('robots_txt', array($this, 'robots_txt'), 99, 1); // Run Premium loader if it exists if (file_exists(WPO_PLUGIN_MAIN_PATH.'premium.php') && !class_exists('WP_Optimize_Premium')) { include_once(WPO_PLUGIN_MAIN_PATH.'premium.php'); } // load defaults WP_Optimize()->get_options()->set_default_options(); // Initialize loggers. $this->setup_loggers(); if ($this->is_active('premium') && false !== ($free_plugin = $this->is_active('free'))) { if (!function_exists('deactivate_plugins')) include_once(ABSPATH.'wp-admin/includes/plugin.php'); deactivate_plugins($free_plugin); // If WPO_ADVANCED_CACHE is defined, we empty advanced-cache.php to regenerate later. Otherwise it contains the path to free. if (defined('WPO_ADVANCED_CACHE') && WPO_ADVANCED_CACHE) { $advanced_cache_filename = trailingslashit(WP_CONTENT_DIR) . 'advanced-cache.php'; if (!is_file($advanced_cache_filename) && is_writable(dirname($advanced_cache_filename)) || (is_file($advanced_cache_filename) && is_writable($advanced_cache_filename))) { file_put_contents($advanced_cache_filename, ''); } } // Registers the notice letting the user know it cannot be active if premium is active. add_action('admin_notices', array($this, 'show_admin_notice_premium')); return; } // Loads the task manager $this->get_task_manager(); // Loads the language file. load_plugin_textdomain('wp-optimize', false, dirname(plugin_basename(__FILE__)) . '/languages'); // Load page cache. $this->get_page_cache(); $this->init_page_cache(); // Include minify $this->get_minify(); $this->run_updates(); $this->get_webp_instance(); } /** * Filter cache tabs (when it is Kinsta) * * @param array $tabs An array of tabs * * @return array $tabs An array of tabs */ public function filter_cache_tabs($tabs) { unset($tabs['preload']); unset($tabs['advanced']); unset($tabs['gzip']); unset($tabs['settings']); return $tabs; } /** * Check whether one of free/Premium is active (whether it is this instance or not) * * @param String $which - 'free' or 'premium' * * @return String|Boolean - plugin path (if installed) or false if not */ private function is_active($which = 'free') { $active_plugins = $this->get_active_plugins(); foreach ($active_plugins as $file) { if ('wp-optimize.php' == basename($file)) { $plugin_dir = WP_PLUGIN_DIR.'/'.dirname($file); if (('free' == $which && !file_exists($plugin_dir.'/premium.php')) || ('free' != $which && file_exists($plugin_dir.'/premium.php'))) return $file; } } return false; } /** * Gets an array of plugins active on either the current site, or site-wide * * @return Array - a list of plugin paths (relative to the plugin directory) */ private function get_active_plugins() { // Gets all active plugins on the current site $active_plugins = get_option('active_plugins'); if (is_multisite()) { $network_active_plugins = get_site_option('active_sitewide_plugins'); if (!empty($network_active_plugins)) { $network_active_plugins = array_keys($network_active_plugins); $active_plugins = array_merge($active_plugins, $network_active_plugins); } } return $active_plugins; } /** * This function checks whether a specific plugin is installed, and returns information about it * * @param string $name Specify "Plugin Name" to return details about it. * @return array Returns an array of details such as if installed, the name of the plugin and if it is active. */ public function is_installed($name) { // Needed to have the 'get_plugins()' function include_once(ABSPATH.'wp-admin/includes/plugin.php'); // Gets all plugins available $get_plugins = get_plugins(); $active_plugins = $this->get_active_plugins(); $plugin_info = array(); $plugin_info['installed'] = false; $plugin_info['active'] = false; // Loops around each plugin available. foreach ($get_plugins as $key => $value) { // If the plugin name matches that of the specified name, it will gather details. if ($value['Name'] != $name && $value['TextDomain'] != $name) continue; $plugin_info['installed'] = true; $plugin_info['name'] = $key; $plugin_info['version'] = $value['Version']; if (in_array($key, $active_plugins)) { $plugin_info['active'] = true; } break; } return $plugin_info; } /** * This is a notice to show users that premium is installed */ public function show_admin_notice_premium() { echo '

'.__('WP-Optimize (Free) has been de-activated, because WP-Optimize Premium is active.', 'wp-optimize').'

'; if (isset($_GET['activate'])) unset($_GET['activate']); } /** * Show update to Premium notice for non-premium multisite. */ public function show_multisite_update_to_premium_notice() { if (!is_multisite() || self::is_premium()) return; echo '

'.__('New feature: WP-Optimize Premium can now optimize all sites within a multisite install, not just the main one.', 'wp-optimize').'

'; } public function admin_init() { $pagenow = $GLOBALS['pagenow']; $this->register_template_directories(); if (('index.php' == $pagenow && current_user_can('update_plugins')) || ('index.php' == $pagenow && defined('WP_OPTIMIZE_FORCE_DASHNOTICE') && WP_OPTIMIZE_FORCE_DASHNOTICE)) { $options = $this->get_options(); $dismissed_until = $options->get_option('dismiss_dash_notice_until', 0); if (file_exists(WPO_PLUGIN_MAIN_PATH . '/index.html')) { $installed = filemtime(WPO_PLUGIN_MAIN_PATH . '/index.html'); $installed_for = (time() - $installed); } if (($installed && time() > $dismissed_until && $installed_for > (14 * 86400) && !defined('WP_OPTIMIZE_NOADS_B')) || (defined('WP_OPTIMIZE_FORCE_DASHNOTICE') && WP_OPTIMIZE_FORCE_DASHNOTICE)) { add_action('all_admin_notices', array($this, 'show_admin_notice_upgradead')); } } $this->install_or_update_notice = $this->get_install_or_update_notice(); } /** * Get the install or update notice instance * * @return WP_Optimize_Install_Or_Update_Notice */ private function get_install_or_update_notice() { static $instance = null; if (is_a($instance, 'WP_Optimize_Install_Or_Update_Notice')) return $instance; include_once WPO_PLUGIN_MAIN_PATH . 'includes/class-wp-optimize-install-or-update-notice.php'; $instance = new WP_Optimize_Install_Or_Update_Notice(); return $instance; } public function show_admin_notice_upgradead() { $this->include_template('notices/thanks-for-using-main-dash.php'); } public function capability_required() { return apply_filters('wp_optimize_capability_required', 'manage_options'); } public function wp_optimize_ajax_handler() { $nonce = empty($_POST['nonce']) ? '' : $_POST['nonce']; if (!wp_verify_nonce($nonce, 'wp-optimize-ajax-nonce') || empty($_POST['subaction'])) { wp_send_json(array( 'result' => false, 'error_code' => 'security_check', 'error_message' => __('The security check failed; try refreshing the page.', 'wp-optimize') )); } $subaction = $_POST['subaction']; $data = isset($_POST['data']) ? $_POST['data'] : null; if (!current_user_can($this->capability_required())) { wp_send_json(array( 'result' => false, 'error_code' => 'security_check', 'error_message' => __('You are not allowed to run this command.', 'wp-optimize') )); } // Currently the settings are only available to network admins. if (is_multisite() && !current_user_can('manage_network_options')) { /** * Filters the commands allowed to the subsite admins. Other commands are only available to network admin. Only used in a multisite context. */ $allowed_commands = apply_filters('wpo_multisite_allowed_commands', array('check_server_status', 'compress_single_image', 'restore_single_image')); if (!in_array($subaction, $allowed_commands)) wp_send_json(array( 'result' => false, 'error_code' => 'update_failed', 'error_message' => __('Options can only be saved by network admin', 'wp-optimize') )); } $options = $this->get_options(); $results = array(); // Some commands that are available via AJAX only. if (in_array($subaction, array('dismiss_dash_notice_until', 'dismiss_season'))) { $options->update_option($subaction, (time() + 366 * 86400)); } elseif (in_array($subaction, array('dismiss_page_notice_until', 'dismiss_notice'))) { $options->update_option($subaction, (time() + 84 * 86400)); } elseif ('dismiss_review_notice' == $subaction) { if (empty($data['dismiss_forever'])) { $options->update_option($subaction, time() + 84*86400); } else { $options->update_option($subaction, 100 * (365.25 * 86400)); } } else { // Other commands, available for any remote method. if (!class_exists('WP_Optimize_Commands')) include_once(WPO_PLUGIN_MAIN_PATH . 'includes/class-commands.php'); if (!class_exists('WP_Optimize_Minify_Commands')) include_once(WPO_PLUGIN_MAIN_PATH . 'minify/class-wp-optimize-minify-commands.php'); if (!class_exists('WP_Optimize_Cache_Commands')) include_once(WPO_PLUGIN_MAIN_PATH . 'cache/class-cache-commands.php'); $commands = new WP_Optimize_Commands(); $minify_commands = new WP_Optimize_Minify_Commands(); if (self::is_premium()) { if (!class_exists('WP_Optimize_Cache_Commands_Premium')) include_once(WPO_PLUGIN_MAIN_PATH . 'cache/class-cache-commands-premium.php'); $cache_commands = new WP_Optimize_Cache_Commands_Premium(); } else { $cache_commands = new WP_Optimize_Cache_Commands(); } // check if called command not in main commands class and exist in cache commands class then change class. if (!is_callable(array($commands, $subaction)) && is_callable(array($minify_commands, $subaction))) { $commands = $minify_commands; } // check if called command not in main commands class and exist in cache commands class then change class. if (!is_callable(array($commands, $subaction)) && is_callable(array($cache_commands, $subaction))) { $commands = $cache_commands; } if (!is_callable(array($commands, $subaction))) { error_log("WP-Optimize: ajax_handler: no such command (".$subaction.")"); $results = array( 'result' => false, 'error_code' => 'command_not_found', 'error_message' => sprintf(__('The command "%s" was not found', 'wp-optimize'), $subaction) ); } else { $results = call_user_func(array($commands, $subaction), $data); // clean status box content, it broke json sometimes. if (isset($results['status_box_contents'])) { $results['status_box_contents'] = str_replace(array("\n", "\t"), '', $results['status_box_contents']); } if (is_wp_error($results)) { $results = array( 'result' => false, 'error_code' => $results->get_error_code(), 'error_message' => $results->get_error_message(), 'error_data' => $results->get_error_data(), ); } // if nothing was returned for some reason, set as result null. if (empty($results)) { $results = array( 'result' => null ); } } } $result = json_encode($results); // Requires PHP 5.3+ $json_last_error = function_exists('json_last_error') ? json_last_error() : false; // if json_encode returned error then return error. if ($json_last_error) { $result = array( 'result' => false, 'error_code' => $json_last_error, 'error_message' => 'json_encode error : '.$json_last_error, 'error_data' => '', ); $result = json_encode($result); } echo $result; die; } /** * Builds the Tabs that should be displayed * * @return array Returns all tabs specified */ public function get_tabs($page) { // define tabs for pages. $pages_tabs = array( 'WP-Optimize' => array( 'optimize' => __('Optimizations', 'wp-optimize'), 'tables' => __('Tables', 'wp-optimize'), 'settings' => __('Settings', 'wp-optimize'), ), 'wpo_images' => array( 'smush' => __('Compress images', 'wp-optimize'), 'unused' => __('Unused images and sizes', 'wp-optimize').'Premium', 'lazyload' => __('Lazy-load', 'wp-optimize').'Premium', ), 'wpo_cache' => array( 'cache' => __('Page cache', 'wp-optimize'), 'preload' => __('Preload', 'wp-optimize'), 'advanced' => __('Advanced settings', 'wp-optimize'), 'gzip' => __('Gzip compression', 'wp-optimize'), 'settings' => __('Static file headers', 'wp-optimize') // Adds a settings tab ), 'wpo_minify' => array( "status" => __('Minify status', 'wp-optimize'), "js" => __('JavaScript', 'wp-optimize').'', "css" => __('CSS', 'wp-optimize').'', "font" => __('Fonts', 'wp-optimize'), "preload" => __('Preload', 'wp-optimize'), "settings" => __('Settings', 'wp-optimize'), "advanced" => __('Advanced', 'wp-optimize') ), 'wpo_settings' => array( 'settings' => array( 'title' => __('Settings', 'wp-optimize'), ), ), 'wpo_support' => array('support' => __('Support / FAQs', 'wp-optimize')), 'wpo_mayalso' => array('may_also' => __('Premium / Plugin family', 'wp-optimize')), ); $tabs = (array_key_exists($page, $pages_tabs)) ? $pages_tabs[$page] : array(); return apply_filters('wp_optimize_admin_page_'.$page.'_tabs', $tabs); } /** * Main page structure. */ public function display_admin() { $capability_required = $this->capability_required(); if (!current_user_can($capability_required) || (!$this->can_run_optimizations() && !$this->can_manage_options())) { echo "Permission denied."; return; } $this->register_admin_content(); echo '
'; $this->include_template('admin-page-header.php', false, array('show_notices' => !($this->get_install_or_update_notice()->show_current_notice()))); do_action('wpo_admin_after_header'); echo '
'; $pages = $this->get_submenu_items(); foreach ($pages as $page) { if (isset($page['menu_slug'])) { $this->display_admin_page($page['menu_slug']); } } do_action('wpo_admin_before_closing_wrap'); // closes main plugin wrapper div. #wp-optimize-wrap echo '
'; } /** * Prepare and display admin page with $page id. * * @param string $page wp-optimize page id i.e. dashboard, database, images, cache, ... */ public function display_admin_page($page) { $active_page = !empty($_REQUEST['page']) ? $_REQUEST['page'] : ''; echo '
'; echo '
'; // get defined tabs for $page. $tabs = $this->get_tabs($page); // if no tabs defined for $page then use $page as $active_tab for load template, doing related actions e t.c. if (empty($tabs)) { $active_tab = $page; } else { $tab_keys = array_keys($tabs); $default_tab = apply_filters('wp_optimize_admin_'.$page.'_default_tab', $tab_keys[0]); $active_tab = isset($_GET['tab']) ? substr($_GET['tab'], 12) : $default_tab; if (!in_array($active_tab, array_keys($tabs))) $active_tab = $default_tab; } do_action('wp_optimize_admin_page_'.$page, $active_tab); // if tabs defined then display if (!empty($tabs)) { $this->include_template('admin-page-header-tabs.php', false, array('page' => $page, 'active_tab' => $active_tab, 'tabs' => $tabs, 'wpo_is_premium' => self::is_premium())); } foreach ($tabs as $tab_id => $tab_description) { // output wrap div for tab with id #wp-optimize-nav-tab-contents-'.$page.'-'.$tab_id echo '
'; echo '
'; // call action for generate tab content. do_action('wp_optimize_admin_page_'.$page.'_'.$tab_id); // closes postbox. echo '
'; // closes tab wrapper. echo '
'; } echo '
'; do_action('wp_optimize_admin_after_page_'.$page, $active_tab); echo '
'; } /** * Define required actions for admin pages. */ public function register_admin_content() { do_action('wp_optimize_register_admin_content'); /** * SETTINGS */ add_action('wp_optimize_admin_page_wpo_settings_settings', array($this, 'output_dashboard_settings_tab'), 20); /** * Premium / other plugins */ add_action('wp_optimize_admin_page_wpo_mayalso_may_also', array($this, 'output_dashboard_other_plugins_tab'), 20); /** * DATABASE */ add_action('wp_optimize_admin_page_WP-Optimize_optimize', array($this, 'output_database_optimize_tab'), 20); add_action('wp_optimize_admin_page_WP-Optimize_tables', array($this, 'output_database_tables_tab'), 20); add_action('wp_optimize_admin_page_WP-Optimize_settings', array($this, 'output_database_settings_tab'), 20); /** * CACHE */ add_action('wp_optimize_admin_page_wpo_cache_cache', array($this, 'output_page_cache_tab'), 20); if (!$this->does_server_handles_cache()) { add_action('wp_optimize_admin_page_wpo_cache_preload', array($this, 'output_page_cache_preload_tab'), 20); add_action('wp_optimize_admin_page_wpo_cache_advanced', array($this, 'output_page_cache_advanced_tab'), 20); } add_action('wp_optimize_admin_page_wpo_cache_gzip', array($this, 'output_cache_gzip_tab'), 20); add_action('wp_optimize_admin_page_wpo_cache_settings', array($this, 'output_cache_settings_tab'), 20); add_action('wpo_page_cache_advanced_settings', array($this, 'output_cloudflare_settings'), 20); /** * SUPPORT */ add_action('wp_optimize_admin_page_wpo_support_support', array($this, 'output_dashboard_support_tab'), 20); // Display Support page. if (!self::is_premium()) { /** * Add action for display Images > Unused images and sizes tab. */ add_action('wp_optimize_admin_page_wpo_images_unused', array($this, 'admin_page_wpo_images_unused')); /** * Add action for display Dashboard > Lazyload tab. */ add_action('wp_optimize_admin_page_wpo_images_lazyload', array($this, 'admin_page_wpo_images_lazyload')); } else { /** * Add filter for display footer review message and link. */ add_filter('admin_footer_text', array($this, 'display_footer_review_message')); } } /** * Database settings */ public function output_database_settings_tab() { if ($this->can_manage_options()) { $this->include_template('database/settings.php'); } else { $this->prevent_manage_options_info(); } } /** * Dashboard settings */ public function output_dashboard_settings_tab() { $options = $this->get_options(); if ('POST' == $_SERVER['REQUEST_METHOD']) { // Nonce check. check_admin_referer('wpo_settings'); $output = $options->save_settings($_POST); if (isset($_POST['wp-optimize-settings'])) { // save settings request sent. $output = $options->save_settings($_POST); } $this->wpo_render_output_messages($output); } if ($this->can_manage_options()) { $this->include_template('settings/settings.php'); } else { $this->prevent_manage_options_info(); } } /** * Dashboard support tab */ public function output_dashboard_support_tab() { WP_Optimize()->include_template('settings/support-and-faqs.php'); } /** * Dashboard Other plugins / premium tab */ public function output_dashboard_other_plugins_tab() { $this->include_template('settings/may-also-like.php'); } /** * Cache tab */ public function output_page_cache_tab() { $wpo_cache = $this->get_page_cache(); $wpo_cache_options = $wpo_cache->config->get(); $display = $wpo_cache->is_enabled() ? "style='display:block'" : "style='display:none'"; WP_Optimize()->include_template('cache/page-cache.php', false, array( 'wpo_cache' => $wpo_cache, 'active_cache_plugins' => WP_Optimize_Detect_Cache_Plugins::instance()->get_active_cache_plugins(), 'wpo_cache_options' => $wpo_cache_options, 'cache_size' => $this->get_page_cache()->get_cache_size(), 'display' => $display, 'can_purge_the_cache' => $this->can_purge_the_cache(), 'does_server_handles_cache' => $this->does_server_handles_cache(), )); } /** * Preload tab */ public function output_page_cache_preload_tab() { $wpo_cache = $this->get_page_cache(); $wpo_cache_options = $wpo_cache->config->get(); $wpo_cache_preloader = WP_Optimize_Page_Cache_Preloader::instance(); $is_running = $wpo_cache_preloader->is_running(); $status = $wpo_cache_preloader->get_status_info(); WP_Optimize()->include_template('cache/page-cache-preload.php', false, array( 'wpo_cache_options' => $wpo_cache_options, 'is_running' => $is_running, 'status_message' => isset($status['message']) ? $status['message'] : '', 'schedule_options' => array( 'wpo_use_cache_lifespan' => __('Same as cache lifespan', 'wp-optimize'), 'wpo_daily' => __('Daily', 'wp-optimize'), 'wpo_weekly' => __('Weekly', 'wp-optimize'), 'wpo_fortnightly' => __('Fortnightly', 'wp-optimize'), 'wpo_monthly' => __('Monthly (approx. - every 30 days)', 'wp-optimize') ) )); } /** * Advanced tab */ public function output_page_cache_advanced_tab() { $wpo_cache = $this->get_page_cache(); $wpo_cache_options = $wpo_cache->config->get(); $cache_exception_urls = is_array($wpo_cache_options['cache_exception_urls']) ? join("\n", $wpo_cache_options['cache_exception_urls']) : ''; $cache_exception_cookies = is_array($wpo_cache_options['cache_exception_cookies']) ? join("\n", $wpo_cache_options['cache_exception_cookies']) : ''; $cache_exception_browser_agents = is_array($wpo_cache_options['cache_exception_browser_agents']) ? join("\n", $wpo_cache_options['cache_exception_browser_agents']) : ''; WP_Optimize()->include_template('cache/page-cache-advanced.php', false, array( 'wpo_cache' => $this->get_page_cache(), 'wpo_cache_options' => $wpo_cache_options, 'cache_exception_urls' => $cache_exception_urls, 'cache_exception_cookies' => $cache_exception_cookies, 'cache_exception_browser_agents' => $cache_exception_browser_agents, )); } /** * Gzip tab */ public function output_cache_gzip_tab() { $wpo_gzip_compression = $this->get_gzip_compression(); $wpo_gzip_compression_enabled = $wpo_gzip_compression->is_gzip_compression_enabled(true); $wpo_gzip_headers_information = $wpo_gzip_compression->get_headers_information(); $is_cloudflare_site = $this->is_cloudflare_site(); $is_gzip_compression_section_exists = $wpo_gzip_compression->is_gzip_compression_section_exists(); $wpo_gzip_compression_enabled_by_wpo = $is_gzip_compression_section_exists && $wpo_gzip_compression_enabled && !$is_cloudflare_site && !(is_array($wpo_gzip_headers_information) && 'brotli' == $wpo_gzip_headers_information['compression']); WP_Optimize()->include_template('cache/gzip-compression.php', false, array( 'wpo_gzip_headers_information' => $wpo_gzip_headers_information, 'wpo_gzip_compression_enabled' => $wpo_gzip_compression_enabled, 'is_cloudflare_site' => $is_cloudflare_site, 'wpo_gzip_compression_enabled_by_wpo' => $wpo_gzip_compression_enabled_by_wpo, 'wpo_gzip_compression_settings_added' => $is_gzip_compression_section_exists, 'info_link' => 'https://getwpo.com/gzip-compression-explained/', 'faq_link' => 'https://getwpo.com/gzip-faq-link/', 'class_name' => (!is_wp_error($wpo_gzip_compression_enabled) && $wpo_gzip_compression_enabled ? 'wpo-enabled' : 'wpo-disabled') )); } /** * Cache tab */ public function output_cache_settings_tab() { $wpo_browser_cache = $this->get_browser_cache(); $wpo_browser_cache_enabled = $wpo_browser_cache->is_enabled(); WP_Optimize()->include_template('cache/browser-cache.php', false, array( 'wpo_browser_cache_enabled' => $wpo_browser_cache_enabled, 'is_cloudflare_site' => $this->is_cloudflare_site(), 'wpo_browser_cache_settings_added' => $wpo_browser_cache->is_browser_cache_section_exists(), 'class_name' => (true === $wpo_browser_cache_enabled ? 'wpo-enabled' : 'wpo-disabled'), 'wpo_browser_cache_expire_days' => $this->get_options()->get_option('browser_cache_expire_days', '28'), 'wpo_browser_cache_expire_hours' => $this->get_options()->get_option('browser_cache_expire_hours', '0'), 'info_link' => 'https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching', 'faq_link' => 'https://www.digitalocean.com/community/tutorials/how-to-implement-browser-caching-with-nginx-s-header-module-on-ubuntu-16-04', )); } /** * Check if is the current site handled with Cloudflare. * * @return bool */ public function is_cloudflare_site() { return isset($_SERVER['HTTP_CF_RAY']); } /** * Include Cloudflare settings template. */ public function output_cloudflare_settings() { if (self::is_premium() || !apply_filters('show_cloudflare_settings', $this->is_cloudflare_site())) return; WP_Optimize()->include_template('cache/page-cache-cloudflare-placeholder.php'); } /** * Outputs the DB optimize Tab */ public function output_database_optimize_tab() { $optimizer = $this->get_optimizer(); $options = $this->get_options(); // check if nonce passed. $nonce_passed = (!empty($_REQUEST['_wpnonce']) && wp_verify_nonce($_REQUEST['_wpnonce'], 'wpo_optimization')) ? true : false; // save options. if ($nonce_passed && isset($_POST['wp-optimize'])) $options->save_sent_manual_run_optimization_options($_POST, true); $optimize_db = ($nonce_passed && isset($_POST["optimize-db"])) ? true : false; $optimization_results = (($nonce_passed) ? $optimizer->do_optimizations($_POST) : false); // display optimizations table or restricted access message. if ($this->can_run_optimizations()) { $this->include_template('database/optimize-table.php', false, array('optimize_db' => $optimize_db, 'optimization_results' => $optimization_results, 'load_data' => false, 'does_server_allows_table_optimization' => $this->does_server_allows_table_optimization())); } else { $this->prevent_run_optimizations_message(); } } /** * Outputs the DB Tables Tab */ public function output_database_tables_tab() { // check if nonce passed. $nonce_passed = (!empty($_REQUEST['_wpnonce']) && wp_verify_nonce($_REQUEST['_wpnonce'], 'wpo_optimization')) ? true : false; $optimize_db = ($nonce_passed && isset($_POST["optimize-db"])) ? true : false; if (!$this->does_server_allows_table_optimization()) { $message = __('Your server takes care of table optimization', 'wp-optimize'); $this->prevent_run_optimizations_message($message); } elseif ($this->can_run_optimizations()) { $this->include_template('database/tables.php', false, array('optimize_db' => $optimize_db, 'load_data' => WP_Optimize()->template_should_include_data())); } else { $this->prevent_run_optimizations_message(); } } /** * Runs upon the WP action admin_page_wpo_images_unused */ public function admin_page_wpo_images_unused() { WP_Optimize()->include_template('images/unused.php'); } /** * Runs upon the WP action wp_optimize_admin_page_wpo_images_lazyload */ public function admin_page_wpo_images_lazyload() { WP_Optimize()->include_template('images/lazyload.php'); } /** * Show footer review message and link. * * @return string */ public function display_footer_review_message() { $message = sprintf( __('Enjoyed %s? Please leave us a %s rating. We really appreciate your support!', 'wp-optimize'), 'WP-Optimize', '★★★★★' ); return $message; } /** * Returns array of translations used in javascript code. * * @return array */ public function wpo_js_translations() { return apply_filters('wpo_js_translations', array( 'automatic_backup_before_optimizations' => __('Automatic backup before optimizations', 'wp-optimize'), 'error_unexpected_response' => __('An unexpected response was received.', 'wp-optimize'), 'optimization_complete' => __('Optimization complete', 'wp-optimize'), 'with_warnings' => __('(with warnings - open the browser console for more details)', 'wp-optimize'), 'optimizing_table' => __('Optimizing table:', 'wp-optimize'), 'run_optimizations' => __('Run optimizations', 'wp-optimize'), 'table_optimization_timeout' => 120000, 'cancel' => __('Cancel', 'wp-optimize'), 'cancelling' => __('Cancelling...', 'wp-optimize'), 'enable' => __('Enable', 'wp-optimize'), 'disable' => __('Disable', 'wp-optimize'), 'please_select_settings_file' => __('Please, select settings file.', 'wp-optimize'), 'are_you_sure_you_want_to_remove_logging_destination' => __('Are you sure you want to remove this logging destination?', 'wp-optimize'), 'fill_all_settings_fields' => __('Before saving, you need to complete the currently incomplete settings (or remove them).', 'wp-optimize'), 'table_was_not_repaired' => __('%s was not repaired. For more details, please check the logs (configured in your logging destinations settings).', 'wp-optimize'), 'table_was_not_deleted' => __('%s was not deleted. For more details, please check your logs configured in logging destinations settings.', 'wp-optimize'), 'table_was_not_converted' => __('%s was not converted to InnoDB. For more details, please check your logs configured in logging destinations settings.', 'wp-optimize'), 'please_use_positive_integers' => __('Please use positive integers.', 'wp-optimize'), 'please_use_valid_values' => __('Please use valid values.', 'wp-optimize'), 'update' => __('Update', 'wp-optimize'), 'run_now' => __('Run now', 'wp-optimize'), 'starting_preload' => __('Started preload...', 'wp-optimize'), 'loading_urls' => __('Loading URLs...', 'wp-optimize'), 'current_cache_size' => __('Current cache size:', 'wp-optimize'), 'number_of_files' => __('Number of files:', 'wp-optimize'), 'toggle_info' => __('Show information', 'wp-optimize'), 'added_to_list' => __('Added to the list', 'wp-optimize'), 'added_notice' => __('The file was added to the list', 'wp-optimize'), 'save_notice' => __('Save the changes', 'wp-optimize'), 'page_refresh' => __('Refreshing the page to reflect changes...', 'wp-optimize'), 'settings_have_been_deleted_successfully' => __('WP-Optimize settings have been deleted successfully.', 'wp-optimize'), 'loading_data' => __('Loading data...', 'wp-optimize'), 'spinner_src' => esc_attr(admin_url('images/spinner-2x.gif')), 'settings_page_url' => is_multisite() ? network_admin_url('admin.php?page=wpo_settings') : admin_url('admin.php?page=wpo_settings'), 'sites' => $this->get_sites(), 'user_always_ignores_table_delete_warning' => (get_user_meta(get_current_user_id(), 'wpo-ignores-table-delete-warning', true)) ? true : false, 'post_meta_tweak_completed' => __('The tweak has been performed.', 'wp-optimize'), 'no_minified_assets' => __('No minified files are present', 'wp-optimize'), )); } public function wpo_admin_bar() { $wp_admin_bar = $GLOBALS['wp_admin_bar']; if (defined('WPOPTIMIZE_ADMINBAR_DISABLE') && WPOPTIMIZE_ADMINBAR_DISABLE) return; // Show menu item in top bar only for super admins. if (is_multisite() & !is_super_admin(get_current_user_id())) return; // Add a link called at the top admin bar. $args = array( 'id' => 'wp-optimize-node', 'title' => apply_filters('wpoptimize_admin_node_title', 'WP-Optimize') ); $wp_admin_bar->add_node($args); $pages = $this->get_submenu_items(); foreach ($pages as $page_id => $page) { if (!isset($page['create_submenu']) || !$page['create_submenu']) { if (isset($page['icon']) && 'separator' == $page['icon']) { $args = array( 'id' => 'wpo-separator-'.$page_id, 'parent' => 'wp-optimize-node', 'meta' => array( 'class' => 'separator', ), ); $wp_admin_bar->add_node($args); } continue; } // 'menu_slug' => 'WP-Optimize', $menu_page_url = menu_page_url($page['menu_slug'], false); if (is_multisite()) { $menu_page_url = network_admin_url('admin.php?page='.$page['menu_slug']); } $args = array( 'id' => 'wpoptimize_admin_node_'.$page_id, 'title' => $page['menu_title'], 'parent' => 'wp-optimize-node', 'href' => $menu_page_url, ); $wp_admin_bar->add_node($args); } } /** * Manages the admin bar menu for caching (currently page and minify) */ public function cache_admin_bar($wp_admin_bar) { $options = $this->get_options(); if (!$options->get_option('enable_cache_in_admin_bar', true)) return; /** * The "purge cache" menu items * * @param array $menu_items - The menu items, in the format required by $wp_admin_bar->add_menu() * @param object $wp_admin_bar */ $menu_items = apply_filters('wpo_cache_admin_bar_menu_items', array(), $wp_admin_bar); if (empty($menu_items) || !is_array($menu_items)) return; $wp_admin_bar->add_menu(array( 'id' => 'wpo_purge_cache', 'title' => __('Purge cache', 'wp-optimize'), 'href' => '#', 'meta' => array( 'title' => __('Purge cache', 'wp-optimize'), ), 'parent' => false, )); foreach ($menu_items as $item) { $wp_admin_bar->add_menu($item); } } /** * Add settings link on plugin page * * @param string $links Passing through the URL to be used within the HREF. * @return string Returns the Links. */ public function plugin_settings_link($links) { $admin_page_url = $this->get_options()->admin_page_url(); $settings_page_url = $this->get_options()->admin_page_url('wpo_settings'); if (false == self::is_premium()) { $premium_link = '' . __('Premium', 'wp-optimize') . ''; array_unshift($links, $premium_link); } $settings_link = '' . __('Settings', 'wp-optimize') . ''; array_unshift($links, $settings_link); $optimize_link = '' . __('Optimize', 'wp-optimize') . ''; array_unshift($links, $optimize_link); return $links; } /** * Action wpo_tables_list_additional_column_data. Output button Optimize in the action column. * * @param string $content String for output to column * @param object $table_info Object with table info. * * @return string */ public function tables_list_additional_column_data($content, $table_info) { if ($table_info->is_needing_repair) { $content .= '
' . '' . '...' . '' . '
'; } // table belongs to plugin. if ($table_info->can_be_removed) { $content .= '
' . '' . '...' . '' . '
'; } // Add option for MyISAM to InnoDB conversion. if ('MyISAM' == $table_info->Engine) { $content .= '
' . '' . '...' . '' . '
'; } return $content; } /** * Initialize WP-Optimize page cache. */ public function init_page_cache() { if ($this->get_page_cache()->config->get_option('enable_page_caching', false)) { $this->get_page_cache()->enable(); } } /** * Schedules cron event based on selected schedule type * * @return void */ public function cron_activate() { $gmt_offset = (int) (3600 * get_option('gmt_offset')); $options = $this->get_options(); if ($options->get_option('schedule') === false) { $options->set_default_options(); } else { if ('true' == $options->get_option('schedule')) { if (!wp_next_scheduled('wpo_cron_event2')) { $schedule_type = $options->get_option('schedule-type', 'wpo_weekly'); // Backward compatibility if ('wpo_otherweekly' == $schedule_type) $schedule_type = 'wpo_fortnightly'; $this_time = (86400 * 7); switch ($schedule_type) { case "wpo_daily": $this_time = 86400; break; case "wpo_weekly": $this_time = (86400 * 7); break; case "wpo_fortnightly": $this_time = (86400 * 14); break; case "wpo_monthly": $this_time = (86400 * 30); break; } add_action('wpo_cron_event2', array($this, 'cron_action')); wp_schedule_event((current_time("timestamp", 0) + $this_time - $gmt_offset), $schedule_type, 'wpo_cron_event2'); WP_Optimize()->log('running wp_schedule_event()'); } } } } /** * Clears all cron events * * @return void */ public function wpo_cron_deactivate() { $cron_jobs = _get_cron_array(); foreach ($cron_jobs as $job) { foreach (array_keys($job) as $hook) { if (preg_match('/^wpo_/', $hook)) wp_unschedule_hook($hook); } } } /** * Scheduler public functions to update schedulers * * @param array $schedules An array of schedules being passed. * @return array An array of schedules being returned. */ public function cron_schedules($schedules) { $schedules['wpo_daily'] = array('interval' => 86400, 'display' => 'Once Daily'); $schedules['wpo_weekly'] = array('interval' => 86400 * 7, 'display' => 'Once Weekly'); $schedules['wpo_fortnightly'] = array('interval' => 86400 * 14, 'display' => 'Once Every Fortnight'); $schedules['wpo_monthly'] = array('interval' => 86400 * 30, 'display' => 'Once Every Month'); return $schedules; } /** * Returns count of overdue cron jobs. * * @return integer */ public function howmany_overdue_crons() { $how_many_overdue = 0; if (function_exists('_get_cron_array') || (is_file(ABSPATH.WPINC.'/cron.php') && include_once(ABSPATH.WPINC.'/cron.php') && function_exists('_get_cron_array'))) { $crons = _get_cron_array(); if (is_array($crons)) { $timenow = time(); foreach ($crons as $jt => $job) { if ($jt < $timenow) { $how_many_overdue++; } } } } return $how_many_overdue; } /** * Run updates on plugin activation. */ public function run_updates() { include_once(WPO_PLUGIN_MAIN_PATH.'includes/class-wp-optimize-updates.php'); WP_Optimize_Updates::check_updates(); } /** * Returns warning about overdue crons. * * @param int $howmany count of overdue crons * @return string */ public function show_admin_warning_overdue_crons($howmany) { $ret = '

'; $ret .= ''.__('Warning', 'wp-optimize').': '.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).' '.__('Read this page for a guide to possible causes and how to fix it.', 'wp-optimize').''; $ret .= '

'; return $ret; } public function admin_menu() { $capability_required = $this->capability_required(); if (!current_user_can($capability_required) || (!$this->can_run_optimizations() && !$this->can_manage_options())) return; $icon_svg = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIgogICB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgdmlld0JveD0iMCAwIDE2IDE2IgogICB2ZXJzaW9uPSIxLjEiCiAgIGlkPSJzdmc0MzE2IgogICBoZWlnaHQ9IjE2IgogICB3aWR0aD0iMTYiPgogIDxkZWZzCiAgICAgaWQ9ImRlZnM0MzE4IiAvPgogIDxtZXRhZGF0YQogICAgIGlkPSJtZXRhZGF0YTQzMjEiPgogICAgPHJkZjpSREY+CiAgICAgIDxjYzpXb3JrCiAgICAgICAgIHJkZjphYm91dD0iIj4KICAgICAgICA8ZGM6Zm9ybWF0PmltYWdlL3N2Zyt4bWw8L2RjOmZvcm1hdD4KICAgICAgICA8ZGM6dHlwZQogICAgICAgICAgIHJkZjpyZXNvdXJjZT0iaHR0cDovL3B1cmwub3JnL2RjL2RjbWl0eXBlL1N0aWxsSW1hZ2UiIC8+CiAgICAgICAgPGRjOnRpdGxlPjwvZGM6dGl0bGU+CiAgICAgIDwvY2M6V29yaz4KICAgIDwvcmRmOlJERj4KICA8L21ldGFkYXRhPgogIDxnCiAgICAgaWQ9ImxheWVyMSI+CiAgICA8cGF0aAogICAgICAgc3R5bGU9ImZpbGw6I2EwYTVhYTtmaWxsLW9wYWNpdHk6MSIKICAgICAgIGlkPSJwYXRoNTciCiAgICAgICBkPSJtIDEwLjc2ODgwOSw2Ljc2MTYwNTEgMCwwIGMgLTAuMDE2ODgsLTAuMDE2ODc4IC0wLjAyNTMxLC0wLjA0MjE4MSAtMC4wMzM3NCwtMC4wNjc0OTkgLTAuMDA4NCwtMC4wMDgzOSAtMC4wMDg0LC0wLjAxNjg3OCAtMC4wMTY4OCwtMC4wMzM3NDMgQyA5Ljk5MjYxMTIsNS4xOTIzMzY2IDguMjIwODU1Nyw0LjU4NDg3ODEgNi43NDQzOTEyLDUuMjkzNTc5NyA1LjY3MjkwMDUsNS44MDgyMzI4IDUuMDU3MDA0Myw2Ljg4ODE2MTMgNS4wNjU0NDIsOC4wMDE4MzY1IDQuNDU3OTgyMiw3LjMxMDAwNzYgMy42OTg2NTg0LDYuNzk1MzU0NSAyLjg1NDk2NDIsNi40OTE2MjUzIDMuMjY4Mzc0Myw1LjA2NTc4MzEgNC4yNTU0OTYsMy44MTcxMTY2IDUuNjg5Nzc0NiwzLjEyNTI4NzggOC4zNjQyODMyLDEuODM0NDM2OCAxMS41NzAzMTksMi45Mzk2NzQ0IDEyLjg4NjQ4MSw1LjU4ODg3MjYgMTMuNDUxNzU1LDYuNzI3ODU5NiAxNC42NDk4MDEsNy4zNTIxOTIxIDE1Ljg0Nzg0Niw3LjIzNDA3NSAxNS43NjM0ODIsNi4zMzk3NiAxNS41MTg4MDUsNS40MzcwMDg2IDE1LjEwNTM5Niw0LjU3NjQ0MDQgMTMuMjE1NTIxLDAuNjg3MDEzNCA4LjUzMzAyMjYsLTAuOTQxMzE2MjcgNC42NDM1OTQzLDAuOTQwMTIxNzkgMi4zMjM0MzcsMi4wNjIyMzM0IDAuODA0Nzg4MTQsNC4xNzk5MDQ0IDAuMzU3NjMxMzIsNi41MzM4MDk4IDIuNDE2MjQzOCw2LjQyNDEyOSA0LjQzMjY3MTcsNy41MDQwNTc0IDUuNDM2NjY2Miw5LjQzNjExNjcgbCAwLjAwODM5LDAgYyAwLjc1OTMxOTIsMS4zNzUyMjAzIDIuNDcyMDE3OCwxLjk0MDQ5NTMgMy45MDYyOTYsMS4yNDg2NjczIDEuMDQ2MTc5OCwtMC41MDYyMTggMS42NTM2NDA4LC0xLjUzNTUyMzggMS42Nzg5NTA4LC0yLjYxNTQ1MTIgMC41ODIxNDgsMC43MDg3MDE4IDEuMzMzMDM1LDEuMjQ4NjY2OCAyLjE1OTg1NiwxLjU3NzcwNjQgLTAuNDM4NzIxLDEuMzU4MzQ3OCAtMS40MDA1MzMsMi41NDc5NTQ4IC0yLjc5MjYyNywzLjIxNDQ3ODggLTIuNTkwMTM4NywxLjI0ODY1OCAtNS42NzgwNTc0LDAuMjUzMTA0IC03LjA2MTcxNTEsLTIuMjI3MzU3IGwgMCwwIEMgMi43NjIxMDQ4LDkuNDUyOTg5NCAxLjUxMzQzODMsOC44MjAyMTkxIDAuMjgxNjQ1OTIsOC45NzIwODQ0IDAuMzgyODg3NjUsOS43OTg5MDQ2IDAuNjE5MTIzMzEsMTAuNjE3Mjg3IDAuOTk4Nzg1MiwxMS40MDE5MjIgYyAxLjg4MTQzNjgsMy44OTc4NjQgNi41NjM5MzcsNS41MjYxOTggMTAuNDYxODAwOCwzLjY0NDc2IDIuMjQ0MjI2LC0xLjA4ODM2OSAzLjczNzU2MiwtMy4xMDQ3OTYgNC4yMzUzNDIsLTUuMzc0MzMyMyAtMS45OTk1NTQsMC4wNDIxODEgLTMuOTQ4NDg2LC0xLjAyOTMwNjMgLTQuOTI3MTcsLTIuOTEwNzQzMyB6IgogICAgICAgY2xhc3M9InN0MTciIC8+CiAgPC9nPgo8L3N2Zz4K'; // Removes the admin menu items on the left WP bar. if (!is_multisite() || (is_multisite() && is_network_admin())) { add_menu_page("WP-Optimize", "WP-Optimize", $capability_required, "WP-Optimize", array($this, "display_admin"), $icon_svg); $sub_menu_items = $this->get_submenu_items(); foreach ($sub_menu_items as $menu_item) { if ($menu_item['create_submenu']) add_submenu_page('WP-Optimize', $menu_item['page_title'], $menu_item['menu_title'], $capability_required, $menu_item['menu_slug'], $menu_item['function']); } } $options = $this->get_options(); if ($options->get_option('enable-admin-menu', 'false') == 'true') { add_action('wp_before_admin_bar_render', array($this, 'wpo_admin_bar')); } } /** * Get the submenu items * * @return array */ public function get_submenu_items() { $sub_menu_items = array( array( 'page_title' => __('Database', 'wp-optimize'), 'menu_title' => __('Database', 'wp-optimize'), 'menu_slug' => 'WP-Optimize', 'function' => array($this, 'display_admin'), 'icon' => 'cloud', 'create_submenu' => true, 'order' => 20, ), array( 'page_title' => __('Images', 'wp-optimize'), 'menu_title' => __('Images', 'wp-optimize'), 'menu_slug' => 'wpo_images', 'function' => array($this, 'display_admin'), 'icon' => 'images-alt2', 'create_submenu' => true, 'order' => 30, ), array( 'page_title' => __('Cache', 'wp-optimize'), 'menu_title' => __('Cache', 'wp-optimize'), 'menu_slug' => 'wpo_cache', 'function' => array($this, 'display_admin'), 'icon' => 'archive', 'create_submenu' => true, 'order' => 40, ), array( 'page_title' => __('Minify', 'wp-optimize'), 'menu_title' => __('Minify', 'wp-optimize'), 'menu_slug' => 'wpo_minify', 'function' => array($this, 'display_admin'), 'icon' => 'dashboard', 'create_submenu' => true, 'order' => 50, ), array( 'create_submenu' => false, 'order' => 55, 'icon' => 'separator', ), array( 'page_title' => __('Settings', 'wp-optimize'), 'menu_title' => __('Settings', 'wp-optimize'), 'menu_slug' => 'wpo_settings', 'function' => array($this, 'display_admin'), 'icon' => 'admin-settings', 'create_submenu' => true, 'order' => 60, ), array( 'page_title' => __('Support & FAQs', 'wp-optimize'), 'menu_title' => __('Help', 'wp-optimize'), 'menu_slug' => 'wpo_support', 'function' => array($this, 'display_admin'), 'icon' => 'sos', 'create_submenu' => true, 'order' => 60, ), array( 'page_title' => __('Premium Upgrade', 'wp-optimize'), 'menu_title' => __('Premium Upgrade', 'wp-optimize'), 'menu_slug' => 'wpo_mayalso', 'function' => array($this, 'display_admin'), 'icon' => 'admin-plugins', 'create_submenu' => true, 'order' => 70, ), ); $sub_menu_items = apply_filters('wp_optimize_sub_menu_items', $sub_menu_items); usort($sub_menu_items, array($this, 'order_sort')); return $sub_menu_items; } public function order_sort($a, $b) { if ($a['order'] == $b['order']) return 0; return ($a['order'] > $b['order']) ? 1 : -1; } private function wp_normalize_path($path) { // Wp_normalize_path is not present before WP 3.9. if (function_exists('wp_normalize_path')) return wp_normalize_path($path); // Taken from WP 4.6. $path = str_replace('\\', '/', $path); $path = preg_replace('|(?<=.)/+|', '/', $path); if (':' === substr($path, 1, 1)) { $path = ucfirst($path); } return $path; } public function get_templates_dir() { return apply_filters('wp_optimize_templates_dir', $this->wp_normalize_path(WPO_PLUGIN_MAIN_PATH.'templates')); } public function get_templates_url() { return apply_filters('wp_optimize_templates_url', WPO_PLUGIN_URL.'/templates'); } /** * Return or output view content * * @param String $path - path to template, usually relative to templates/ within the WP-O directory * @param Boolean $return_instead_of_echo - what to do with the results * @param Array $extract_these - key/value pairs for substitution into the scope of the template * * @return String|Void */ public function include_template($path, $return_instead_of_echo = false, $extract_these = array()) { if ($return_instead_of_echo) ob_start(); if (preg_match('#^([^/]+)/(.*)$#', $path, $matches)) { $prefix = $matches[1]; $suffix = $matches[2]; if (isset($this->template_directories[$prefix])) { $template_file = $this->template_directories[$prefix].'/'.$suffix; } } if (!isset($template_file)) { $template_file = WPO_PLUGIN_MAIN_PATH.'templates/'.$path; } $template_file = apply_filters('wp_optimize_template', $template_file, $path); do_action('wp_optimize_before_template', $path, $template_file, $return_instead_of_echo, $extract_these); if (!file_exists($template_file)) { error_log("WP Optimize: template not found: ".$template_file); echo __('Error:', 'wp-optimize').' '.__('template not found', 'wp-optimize')." (".$path.")"; } else { extract($extract_these); // The following are useful variables which can be used in the template. // They appear as unused, but may be used in the $template_file. $wpdb = $GLOBALS['wpdb'];// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable -- $wpdb might be used in the included template $wp_optimize = $this;// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable -- $wp_optimize might be used in the included template $optimizer = $this->get_optimizer();// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable -- $optimizer might be used in the included template $options = $this->get_options();// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable -- $options might be used in the included template $wp_optimize_notices = $this->get_notices();// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable -- $wp_optimize_notices might be used in the included template include $template_file; } do_action('wp_optimize_after_template', $path, $template_file, $return_instead_of_echo, $extract_these); if ($return_instead_of_echo) return ob_get_clean(); } /** * Build a list of template directories (stored in self::$template_directories) */ private function register_template_directories() { $template_directories = array(); $templates_dir = $this->get_templates_dir(); if ($dh = opendir($templates_dir)) { while (($file = readdir($dh)) !== false) { if ('.' == $file || '..' == $file) continue; if (is_dir($templates_dir.'/'.$file)) { $template_directories[$file] = $templates_dir.'/'.$file; } } closedir($dh); } // Optimal hook for most extensions to hook into. $this->template_directories = apply_filters('wp_optimize_template_directories', $template_directories); } /** * Message to debug * * @param string $message Message to insert into the log. * @param array $context array with variables used in $message like in template, * for ex. * $message = 'Hello {message}'; * $context = ['message' => 'world'] * 'Hello world' string will be saved in log. */ public function log($message, $context = array()) { $this->get_logger()->debug($message, $context); } /** * Format Bytes Into KB/MB * * @param mixed $bytes Number of bytes to be converted. * @param integer $decimals the number of decimal digits * @return integer return the correct format size. */ public function format_size($bytes, $decimals = 2) { if (!is_numeric($bytes)) return __('N/A', 'wp-optimize'); if (1073741824 <= $bytes) { $bytes = number_format($bytes / 1073741824, $decimals) . ' GB'; } elseif (1048576 <= $bytes) { $bytes = number_format($bytes / 1048576, $decimals) . ' MB'; } elseif (1024 <= $bytes) { $bytes = number_format($bytes / 1024, $decimals) . ' KB'; } elseif (1 < $bytes) { $bytes = $bytes . ' bytes'; } elseif (1 == $bytes) { $bytes = $bytes . ' byte'; } else { $bytes = '0 bytes'; } return $bytes; } /** * Format a timestamp into a juman readable date time * * @param int $timestamp * @return string */ public function format_date_time($timestamp) { return date_i18n(get_option('date_format').' @ '.get_option('time_format'), ($timestamp + get_option('gmt_offset') * 3600)); } /** * Executed this function on cron event. * * @return void */ public function cron_action() { $optimizer = $this->get_optimizer(); $options = $this->get_options(); $this->log('WPO: Starting cron_action()'); if ('true' == $options->get_option('schedule')) { $this_options = $options->get_option('auto'); // Currently the output of the optimizations is not saved/used/logged. $optimizer->do_optimizations($this_options, 'auto'); } } /** * Schedule cron tasks used by plugin. * * @return void */ public function schedule_plugin_cron_tasks() { if (!wp_next_scheduled('wpo_weekly_cron_tasks')) { wp_schedule_event(current_time("timestamp", 0), 'weekly', 'wpo_weekly_cron_tasks'); } add_action('wpo_weekly_cron_tasks', array($this, 'do_weekly_cron_tasks')); } /** * Do plugin background tasks. * * @return void */ public function do_weekly_cron_tasks() { // add tasks here. $this->get_db_info()->update_plugin_json(); } /** * This will customize a URL with a correct Affiliate link * This function can be update to suit any URL as longs as the URL is passed * * @param String $url - URL to be check to see if it an updraftplus match. * @param String $text - Text to be entered within the href a tags. * @param String $html - Any specific HTML to be added. * @param String $class - Specify a class for the href (including the attribute label) * @param Boolean $return_instead_of_echo - if set, then the result will be returned, not echo-ed. * * @return String|void */ public function wp_optimize_url($url, $text, $html = '', $class = '', $return_instead_of_echo = false) { // Check if the URL is UpdraftPlus. $url = $this->maybe_add_affiliate_params($url); // Return URL - check if there is HTML such as images. if ('' != $html) { $result = ''.$html.''; } else { $result = ''.htmlspecialchars($text).''; } if ($return_instead_of_echo) return $result; echo $result; } /** * Get an URL with an eventual affiliate ID * * @param string $url * @return string */ public function maybe_add_affiliate_params($url) { // Check if the URL is UpdraftPlus. if (false !== strpos($url, '//updraftplus.com')) { // Set URL with Affiliate ID. $url = add_query_arg(array('afref' => $this->get_notices()->get_affiliate_id()), $url); // Apply filters. $url = apply_filters('wpoptimize_updraftplus_com_link', $url); } return apply_filters('wpoptimize_maybe_add_affiliate_params', $url); } /** * Setup WPO logger(s) */ public function setup_loggers() { $logger = $this->get_logger(); $loggers = $this->wpo_loggers(); if (!empty($loggers)) { foreach ($loggers as $_logger) { $logger->add_logger($_logger); } } add_action('wp_optimize_after_optimizations', array($this, 'after_optimizations_logger_action')); } /** * Run logger actions after all optimizations done */ public function after_optimizations_logger_action() { $loggers = $this->get_logger()->get_loggers(); if (!empty($loggers)) { foreach ($loggers as $logger) { if (is_a($logger, 'Updraft_Email_Logger')) { $logger->flush_log(); } } } } /** * Returns list of WPO loggers instances * Apply filter wp_optimize_loggers * * @return array */ public function wpo_loggers() { $loggers = array(); $loggers_classes_by_id = array(); $options_keys = array(); $loggers_classes = $this->get_loggers_classes(); foreach ($loggers_classes as $logger_class => $source) { $loggers_classes_by_id[strtolower($logger_class)] = $logger_class; } $options = $this->get_options(); $saved_loggers = $options->get_option('logging'); $logger_additional_options = $options->get_option('logging-additional'); // create loggers classes instances. if (!empty($saved_loggers)) { // check for previous version options format. $keys = array_keys($saved_loggers); // if options stored in old format then reformat it. if (false == is_numeric($keys[0])) { $_saved_loggers = array(); foreach ($saved_loggers as $logger_id => $enabled) { if ($enabled) { $_saved_loggers[] = $logger_id; } } // fill email with admin. if (array_key_exists('updraft_email_logger', $saved_loggers) && $saved_loggers['updraft_email_logger']) { $logger_additional_options['updraft_email_logger'] = array( get_option('admin_email') ); } $saved_loggers = $_saved_loggers; } foreach ($saved_loggers as $i => $logger_id) { if (!array_key_exists($logger_id, $loggers_classes_by_id)) continue; $logger_class = $loggers_classes_by_id[$logger_id]; $logger = new $logger_class(); $logger_options = $logger->get_options_list(); if (!empty($logger_options)) { foreach (array_keys($logger_options) as $option_name) { if (array_key_exists($option_name, $options_keys)) { $options_keys[$option_name]++; } else { $options_keys[$option_name] = 0; } $option_value = isset($logger_additional_options[$option_name][$options_keys[$option_name]]) ? $logger_additional_options[$option_name][$options_keys[$option_name]] : ''; // if options in old format then get correct value. if ('' === $option_value && array_key_exists($logger_id, $logger_additional_options)) { $option_value = array_shift($logger_additional_options[$logger_id]); } $logger->set_option($option_name, $option_value); } } // check if logger is active. $active = (!is_array($logger_additional_options) || (array_key_exists('active', $logger_additional_options) && empty($logger_additional_options['active'][$i]))) ? false : true; if ($active) { $logger->enable(); } else { $logger->disable(); } $loggers[] = $logger; } } $loggers = apply_filters('wp_optimize_loggers', $loggers); return $loggers; } /** * Returns associative array with logger class name in a key and path to class file in a value. * * @return array */ public function get_loggers_classes() { $loggers_classes = array( 'Updraft_PHP_Logger' => WPO_PLUGIN_MAIN_PATH . 'includes/class-updraft-php-logger.php', 'Updraft_Email_Logger' => WPO_PLUGIN_MAIN_PATH . 'includes/class-updraft-email-logger.php', 'Updraft_Ring_Logger' => WPO_PLUGIN_MAIN_PATH . 'includes/class-updraft-ring-logger.php' ); $loggers_classes = apply_filters('wp_optimize_loggers_classes', $loggers_classes); if (!empty($loggers_classes)) { foreach ($loggers_classes as $logger_class => $logger_file) { if (!class_exists($logger_class)) { if (is_file($logger_file)) { include_once($logger_file); } } } } return $loggers_classes; } /** * Returns information about all loggers classes. * * @return array */ public function get_loggers_classes_info() { $loggers_classes = $this->get_loggers_classes(); $loggers_classes_info = array(); if (!empty($loggers_classes)) { foreach (array_keys($loggers_classes) as $logger_class_name) { if (!class_exists($logger_class_name)) continue; $logger_id = strtolower($logger_class_name); $logger_class = new $logger_class_name(); $loggers_classes_info[$logger_id] = array( 'description' => $logger_class->get_description(), 'available' => $logger_class->is_available(), 'allow_multiple' => $logger_class->is_allow_multiple(), 'options' => $logger_class->get_options_list() ); } } return $loggers_classes_info; } /** * Returns true if optimization works in multisite mode * * @return boolean */ public function is_multisite_mode() { return (is_multisite() && self::is_premium()); } /** * Returns true if current user can run optimizations. * * @return bool */ public function can_run_optimizations() { // we don't check permissions for cron jobs. if (defined('DOING_CRON') && DOING_CRON) return true; if (self::is_premium() && false == user_can(get_current_user_id(), 'wpo_run_optimizations')) return false; return true; } /** * Returns true if current user can manage plugin options. * * @return bool */ public function can_manage_options() { if (self::is_premium() && false == user_can(get_current_user_id(), 'wpo_manage_settings')) return false; return true; } /** * CHeck if current user can purge the cache. * * @return bool */ public function can_purge_the_cache() { if (self::is_premium()) { return WP_Optimize_Premium()->can_purge_the_cache(); } return true; } /** * Output information message for users who have no permissions to run optimizations. * * @param string $message Message to display */ public function prevent_run_optimizations_message($message = '') { if (empty($message)) { $message = __('You have no permissions to run optimizations.', 'wp-optimize'); } $this->include_template('info-message.php', false, array('message' => $message)); } /** * Output information message for users who have no permissions to manage settings. */ public function prevent_manage_options_info() { $this->include_template('info-message.php', false, array('message' => __('You have no permissions to manage WP-Optimize settings.', 'wp-optimize'))); } /** * Returns list of all sites in multisite * * @return array */ public function get_sites() { $sites = array(); // check if function get_sites exists (since 4.6.0) else use wp_get_sites. if (function_exists('get_sites')) { $sites = get_sites(array('network_id' => null, 'deleted' => 0, 'number' => 999999)); } elseif (function_exists('wp_get_sites')) { $sites = wp_get_sites(array('network_id' => null, 'deleted' => 0, 'limit' => 999999)); } return $sites; } /** * Output success/error messages from $output array. * * @param array $output ['messages' => success messages, 'errors' => error messages] */ private function wpo_render_output_messages($output) { foreach ($output['messages'] as $item) { echo '
'.$item.'
'; } foreach ($output['errors'] as $item) { echo '
'.$item.'
'; } } /** * Returns script memory limit in megabytes. * * @param bool $memory_limit * @return int */ public function get_memory_limit($memory_limit = false) { // Returns in megabytes if (false == $memory_limit) $memory_limit = ini_get('memory_limit'); $memory_limit = rtrim($memory_limit); return $this->return_bytes($memory_limit); } /** * Returns free memory in bytes. * * @return int */ public function get_free_memory() { return $this->get_memory_limit() - memory_get_usage(); } /** * Checks PHP memory_limit and WP_MAX_MEMORY_LIMIT values and return minimal. * * @return int memory limit in bytes. */ public function get_script_memory_limit() { $memory_limit = $this->get_memory_limit(); if (defined('WP_MAX_MEMORY_LIMIT')) { $wp_memory_limit = $this->get_memory_limit(WP_MAX_MEMORY_LIMIT); if ($wp_memory_limit > 0 && $wp_memory_limit < $memory_limit) { $memory_limit = $wp_memory_limit; } } return $memory_limit; } /** * Returns max packet size for database. * * @return int|string */ public function get_max_packet_size() { global $wpdb; static $mp = 0; if ($mp > 0) return $mp; $mp = (int) $wpdb->get_var("SELECT @@session.max_allowed_packet"); // Default to 1MB $mp = (is_numeric($mp) && $mp > 0) ? $mp : 1048576; // 32MB if ($mp < 33554432) { $save = $wpdb->show_errors(false); @$wpdb->query("SET GLOBAL max_allowed_packet=33554432");// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged $wpdb->show_errors($save); $mp = (int) $wpdb->get_var("SELECT @@session.max_allowed_packet"); // Default to 1MB $mp = (is_numeric($mp) && $mp > 0) ? $mp : 1048576; } return $mp; } /** * Converts shorthand memory notation value to bytes. * From http://php.net/manual/en/function.ini-get.php * * @param string $val shorthand memory notation value. */ public function return_bytes($val) { $val = trim($val); $last = strtolower($val[strlen($val)-1]); $val = (int) $val; switch ($last) { case 'g': $val *= 1024; // no break case 'm': $val *= 1024; // no break case 'k': $val *= 1024; } return $val; } /** * Log fatal errors to defined log destinations. */ public function log_fatal_errors() { $last_error = error_get_last(); if (isset($last_error['type']) && E_ERROR === $last_error['type']) { $this->get_logger()->critical($last_error['message']); } } /** * Close browser connection and continue script work. - Taken from UpdraftPlus * * @param array $txt Response to browser; this must be JSON (or if not, alter the Content-Type header handling below) * @return void */ public function close_browser_connection($txt = '') { if (!headers_sent()) { // Close browser connection so that it can resume AJAX polling header('Content-Length: '.(empty($txt) ? '0' : 4+strlen($txt))); header('Connection: close'); header('Content-Encoding: none'); } if (session_id()) session_write_close(); echo "\r\n\r\n"; echo $txt; // These two added - 19-Feb-15 - started being required on local dev machine, for unknown reason (probably some plugin that started an output buffer). $ob_level = ob_get_level(); while ($ob_level > 0) { ob_end_flush(); $ob_level--; } flush(); if (function_exists('fastcgi_finish_request')) fastcgi_finish_request(); } /** * Get the current theme's style.css headers * * @return array|WP_Error */ public function get_stylesheet_headers() { static $headers; if (isset($headers)) return $headers; $style = get_template_directory_uri() . '/style.css'; /** * Filters wp_remote_get parameters, when checking if browser cache is enabled. * * @param array $request_params Default parameters */ $request_params = apply_filters('wpoptimize_get_stylesheet_headers_args', array('timeout' => 10)); // trying to load style.css. $response = wp_remote_get($style, $request_params); if (is_a($response, 'WP_Error')) return $response; $headers = wp_remote_retrieve_headers($response); if (is_a($headers, 'Requests_Utility_CaseInsensitiveDictionary')) { $headers = $headers->getAll(); } return $headers; } /** * Try to change PHP script time limit. */ public function change_time_limit() { $time_limit = (defined('WP_OPTIMIZE_SET_TIME_LIMIT') && WP_OPTIMIZE_SET_TIME_LIMIT > 15) ? WP_OPTIMIZE_SET_TIME_LIMIT : 1800; // Try to reduce the chances of PHP self-terminating via reaching max_execution_time. @set_time_limit($time_limit); // phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged } /** * Does the request come from UDC * * @return boolean */ public function is_updraft_central_request() { return defined('UPDRAFTCENTRAL_COMMAND') && UPDRAFTCENTRAL_COMMAND; } /** * Does the data need to be included in this request. Currently only true if the request is made from UpdraftCentral. * * @return boolean */ public function template_should_include_data() { /** * Filters wether data should be included in certain templates or not. */ return apply_filters('wpo_template_should_include_data', $this->is_updraft_central_request()); } /** * Load the templates for the modal window */ public function load_modal_template() { $this->include_template('modal.php'); } /** * Delete transients and semaphores data from options table. */ public function delete_transients_and_semaphores() { global $wpdb; $masks = array( 'updraft_locked_wpo_%', 'updraft_unlocked_wpo_%', 'updraft_last_lock_time_wpo_%', 'updraft_semaphore_wpo_%', 'wpo_locked_%', 'wpo_unlocked_%', 'wpo_last_lock_time_%', 'wpo_semaphore_%', '_transient_timeout_wpo_%', '_transient_wpo_%', 'updraft_lock_wpo_%', ); $where_parts = array(); foreach ($masks as $mask) { $where_parts[] = "(`option_name` LIKE '{$mask}')"; } $wpdb->query("DELETE FROM {$wpdb->options} WHERE " . join(' OR ', $where_parts)); } /** * Prevents bots from indexing plugins list */ public function robots_txt($output) { $upload_dir = wp_upload_dir(); $path = parse_url($upload_dir['baseurl']); $output .= "\nDisallow: " . str_replace($path['scheme'].'://'.$path['host'], '', $upload_dir['baseurl']) . "/wpo-plugins-tables-list.json\n"; return $output; } } /** * Plugin activation actions. */ function wpo_activation_actions() { // If plugin activated by not a Network Administrator then deactivate plugin and show message. if (is_multisite() && !is_network_admin()) { deactivate_plugins(plugin_basename(__FILE__)); wp_die(__('Only Network Administrator can activate WP-Optimize plugin.', 'wp-optimize'). ' '.__('go back', 'wp-optimize').''); } // On activation, check if last-optimized option exists. If not, add 'newly-activated' option. if (!WP_Optimize()->get_options()->get_option('last-optimized', false)) { WP_Optimize()->get_options()->update_option('newly-activated', true); } WP_Optimize()->get_options()->set_default_options(); WP_Optimize()->get_minify()->plugin_activate(); WP_Optimize::get_gzip_compression()->restore(); WP_Optimize::get_browser_cache()->restore(); if (!class_exists('Updraft_Tasks_Activation')) require_once(WPO_PLUGIN_MAIN_PATH . 'vendor/team-updraft/common-libs/src/updraft-tasks/class-updraft-tasks-activation.php'); Updraft_Tasks_Activation::init_db(); Updraft_Tasks_Activation::reinstall_if_needed(); // run premium activation actions. if (file_exists(WPO_PLUGIN_MAIN_PATH.'premium.php')) { if (!class_exists('WP_Optimize_Premium')) { include_once(WPO_PLUGIN_MAIN_PATH.'premium.php'); } WP_Optimize_Premium()->plugin_activation_actions(); } } /** * Plugin deactivation actions. */ function wpo_deactivation_actions() { WP_Optimize()->wpo_cron_deactivate(); WP_Optimize()->get_page_cache()->disable(); WP_Optimize()->get_minify()->plugin_deactivate(); WP_Optimize::get_gzip_compression()->disable(); WP_Optimize::get_browser_cache()->disable(); } function wpo_cron_deactivate() { WP_Optimize()->log('running wpo_cron_deactivate()'); wp_clear_scheduled_hook('wpo_cron_event2'); wp_clear_scheduled_hook('wpo_weekly_cron_tasks'); } /** * Plugin uninstall actions. */ function wpo_uninstall_actions() { WP_Optimize::get_gzip_compression()->disable(); WP_Optimize::get_browser_cache()->disable(); WP_Optimize()->get_options()->delete_all_options(); WP_Optimize()->get_minify()->plugin_uninstall(); WP_Optimize()->get_options()->wipe_settings(); WP_Optimize()->delete_transients_and_semaphores(); } function WP_Optimize() { return WP_Optimize::instance(); } endif; $GLOBALS['wp_optimize'] = WP_Optimize();