get_optimizer() */ class WP_Optimizer { public function get_retain_info() { $options = WP_Optimize()->get_options(); $retain_enabled = $options->get_option('retention-enabled', 'false'); $retain_period = (($retain_enabled) ? $options->get_option('retention-period', '2') : null); return array($retain_enabled, $retain_period); } /** * Get data retention options * * @return array */ public function get_revisions_retain_info() { $options = WP_Optimize()->get_options(); $revisions_retention_enabled = $options->get_option('revisions-retention-enabled', 'false'); $revisions_retention_count = $revisions_retention_enabled ? $options->get_option('revisions-retention-count', '2') : null; return array($revisions_retention_enabled, $revisions_retention_count); } public function get_optimizations_list() { $optimizations = array(); $optimizations_dir = WPO_PLUGIN_MAIN_PATH.'optimizations'; if ($dh = opendir($optimizations_dir)) { while (($file = readdir($dh)) !== false) { if ('.' == $file || '..' == $file || '.php' != substr($file, -4, 4) || !is_file($optimizations_dir.'/'.$file) || 'inactive-' == substr($file, 0, 9)) continue; $optimizations[] = substr($file, 0, (strlen($file) - 4)); } closedir($dh); } return apply_filters('wp_optimize_get_optimizations_list', $optimizations); } /** * Currently, there is only one sort rule (so, the parameter's value is ignored) * * @param array $optimizations An array of optimizations (i.e. WP_Optimization instances). * @param string $sort_on Specify sort. * @param string $sort_rule Sort Rule. * @return array */ public function sort_optimizations($optimizations, $sort_on = 'ui_sort_order', $sort_rule = 'traditional') {// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable if ('run_sort_order' == $sort_on) { uasort($optimizations, array($this, 'sort_optimizations_run_traditional')); } else { uasort($optimizations, array($this, 'sort_optimizations_ui_traditional')); } return $optimizations; } public function sort_optimizations_ui_traditional($a, $b) { return $this->sort_optimizations_traditional($a, $b, 'ui_sort_order'); } public function sort_optimizations_run_traditional($a, $b) { return $this->sort_optimizations_traditional($a, $b, 'run_sort_order'); } public function sort_optimizations_traditional($a, $b, $sort_on = 'ui_sort_order') { if (!is_a($a, 'WP_Optimization')) return (!is_a($b, 'WP_Optimization')) ? 0 : 1; if (!is_a($b, 'WP_Optimization')) return -1; $sort_order_a = empty($a->$sort_on) ? 0 : $a->$sort_on; $sort_order_b = empty($b->$sort_on) ? 0 : $b->$sort_on; if ($sort_order_a == $sort_order_b) return 0; return ($sort_order_a < $sort_order_b) ? (-1) : 1; } /** * This method returns an array of available optimizations. * Each array key is an optimization ID, and the value is an object, * as returned by get_optimization() * * @return [array] array of optimizations or WP_Error objects */ public function get_optimizations() { $optimizations = $this->get_optimizations_list(); $optimization_objects = array(); foreach ($optimizations as $optimization) { $optimization_object = $this->get_optimization($optimization); if (is_wp_error($optimization_object)) { WP_Optimize()->log('Failed to load optimization ' . $optimization . ' - ' . $optimization_object->get_error_message()); } else { $optimization_objects[$optimization] = $optimization_object; } } return apply_filters('wp_optimize_get_optimizations', $optimization_objects); } /** * This method returns an object for a specific optimization. * * @param string $which_optimization An optimization ID. * @param array $data An array of anny options $data. * @return array WP_Error Will return the optimization, or a WP_Error object if it was not found. */ public function get_optimization($which_optimization, $data = array()) { $optimization_class = apply_filters('wp_optimize_optimization_class', 'WP_Optimization_'.$which_optimization); if (!class_exists('WP_Optimization')) include_once(WPO_PLUGIN_MAIN_PATH.'includes/class-wp-optimization.php'); if (!class_exists($optimization_class)) { $optimization_file = WPO_PLUGIN_MAIN_PATH.'optimizations/'.$which_optimization.'.php'; $class_file = apply_filters('wp_optimize_optimization_class_file', $optimization_file); if (!preg_match('/^[a-z]+$/', $which_optimization) || !file_exists($class_file)) { return new WP_Error('no_such_optimization', __('No such optimization', 'wp-optimize'), $which_optimization); } include_once($class_file); if (!class_exists($optimization_class)) { return new WP_Error('no_such_optimization', __('No such optimization', 'wp-optimize'), $which_optimization); } } // set sites option for Multisite cron job. if (defined('DOING_CRON') && DOING_CRON && is_multisite()) { $options = WP_Optimize()->get_options(); $data['optimization_sites'] = $options->get_option('wpo-sites-cron', array('all')); } $optimization = new $optimization_class($data); return $optimization; } /** * The method to call to perform an optimization. * * @param string|object $which_optimization An optimization ID, or a WP_Optimization object. * @return array Array of results from the optimization. */ public function do_optimization($which_optimization) { $optimization = (is_object($which_optimization) && is_a($which_optimization, 'WP_Optimization')) ? $which_optimization : $this->get_optimization($which_optimization); if (is_wp_error($optimization)) { WP_Optimize()->log('Error occurred. Unknown optimization.'); return $optimization; } WP_Optimize()->change_time_limit(); $optimization->init(); if (apply_filters('wp_optimize_do_optimization', true, $which_optimization, $optimization)) { $optimization->before_optimize(); if ($optimization->run_multisite) { foreach ($optimization->blogs_ids as $blog_id) { $optimization->switch_to_blog($blog_id); $optimization->optimize(); $optimization->restore_current_blog(); } } else { $optimization->optimize(); } $optimization->after_optimize(); } do_action('wp_optimize_after_optimization', $which_optimization, $optimization); $results = $optimization->get_results(); return $results; } /** * The method to call to get information about an optimization. * As with do_optimization, it is somewhat modelled after the template interface * * @param string|object $which_optimization An optimization ID, or a WP_Optimization object. * @return array returns the optimization information */ public function get_optimization_info($which_optimization) { $optimization = (is_object($which_optimization) && is_a($which_optimization, 'WP_Optimization')) ? $which_optimization : $this->get_optimization($which_optimization); if (is_wp_error($optimization)) return $optimization; WP_Optimize()->change_time_limit(); $optimization->before_get_info(); if ($optimization->run_multisite) { foreach ($optimization->blogs_ids as $blog_id) { $optimization->switch_to_blog($blog_id); $optimization->get_info(); $optimization->restore_current_blog(); } } else { $optimization->get_info(); } $optimization->after_get_info(); return $optimization->get_results(); } /** * THis runs the list of optimizations. * * @param array $optimization_options Whether to do an optimization depends on what keys are set (legacy - can be changed hopefully). * @param string $which_option Specify which option. * @return array Returns an array of result objects. */ public function do_optimizations($optimization_options, $which_option = 'dom') { $results = array(); if (empty($optimization_options)) return $results; $optimizations = $this->sort_optimizations($this->get_optimizations(), 'run_sort_order'); foreach ($optimizations as $optimization_id => $optimization) { $option_id = call_user_func(array($optimization, 'get_'.$which_option.'_id')); if (isset($optimization_options[$option_id])) { // if options saved as a string then compare with string (for support different versions) if (is_string($optimization_options[$option_id]) && 'false' === $optimization_options[$option_id]) continue; if ('auto' == $which_option && empty($optimization->available_for_auto)) continue; WP_Optimize()->change_time_limit(); $results[$optimization_id] = $this->do_optimization($optimization); } } // Run action after all optimizations completed. do_action('wp_optimize_after_optimizations'); return $results; } public function get_table_prefix($allow_override = false) { $wpdb = $GLOBALS['wpdb']; if (is_multisite() && !defined('MULTISITE')) { // In this case (which should only be possible on installs upgraded from pre WP 3.0 WPMU), $wpdb->get_blog_prefix() cannot be made to return the right thing. $wpdb->base_prefix is not explicitly marked as public, so we prefer to use get_blog_prefix if we can, for future compatibility. $prefix = $wpdb->base_prefix; } else { $prefix = $wpdb->get_blog_prefix(0); } return ($allow_override) ? apply_filters('wp_optimize_get_table_prefix', $prefix) : $prefix; } /** * Returns information about database tables. * * @param bool $update refresh or no cached data * * @return mixed */ public function get_tables($update = false) { static $tables_info = null; if (false === $update && null !== $tables_info) return $tables_info; $wpo_db_info = WP_Optimize()->get_db_info(); $table_status = WP_Optimize()->get_db_info()->get_show_table_status($update); // Filter on the site's DB prefix (was not done in releases up to 1.9.1). $table_prefix = $this->get_table_prefix(); if (is_array($table_status)) { $corrupted_tables_count = 0; foreach ($table_status as $index => $table) { $table_name = $table->Name; $include_table = (0 === stripos($table_name, $table_prefix)); $include_table = apply_filters('wp_optimize_get_tables_include_table', $include_table, $table_name, $table_prefix); if (!$include_table && '' !== $table_prefix) { unset($table_status[$index]); continue; } $table_status[$index]->Engine = $wpo_db_info->get_table_type($table_name); $table_status[$index]->is_optimizable = $wpo_db_info->is_table_optimizable($table_name); $table_status[$index]->is_type_supported = $wpo_db_info->is_table_type_optimize_supported($table_name); // add information about corrupted tables. $is_needing_repair = $wpo_db_info->is_table_needing_repair($table_name); $table_status[$index]->is_needing_repair = $is_needing_repair; if ($is_needing_repair) $corrupted_tables_count++; $table_status[$index] = $this->join_plugin_information($table_name, $table_status[$index]); $table_status[$index]->blog_id = $wpo_db_info->get_table_blog_id($table_name); } WP_Optimize()->get_options()->update_option('corrupted-tables-count', $corrupted_tables_count); } $tables_info = apply_filters('wp_optimize_get_tables', $table_status); return $tables_info; } /** * Returns information about single table by table name. * * @param String $table_name table name * @return Object|Boolean table information object. */ public function get_table($table_name) { $db_info = WP_Optimize()->get_db_info(); $table = $db_info->get_table_status($table_name); if (false === $table) return false; $table->is_optimizable = $db_info->is_table_optimizable($table_name); $table->is_type_supported = $db_info->is_table_type_optimize_supported($table_name); $table->is_needing_repair = $db_info->is_table_needing_repair($table_name); // add information about plugins. $table = $this->join_plugin_information($table_name, $table); $table = apply_filters('wp_optimize_get_table', $table); return $table; } /** * Add information about relationship database tables with plugins. * * @param {string} $table_name * @param {object} $table_obj * * @return {object} */ public function join_plugin_information($table_name, $table_obj) { // set can be removed flag. $can_be_removed = false; // set WP core table flag. $wp_core_table = false; // set WP actionscheduler table flag. $wp_actionscheduler_table = (false !== stripos($table_name, 'actionscheduler_')); // add information about using table by any of installed plugins. $table_obj->is_using = WP_Optimize()->get_db_info()->is_table_using_by_plugin($table_name); // if table belongs to any plugin then add plugins status. $plugins = WP_Optimize()->get_db_info()->get_table_plugin($table_name); if (false !== $plugins) { // if belongs to any of plugin then we can remove table if plugin not active. $can_be_removed = true; $plugin_status = array(); foreach ($plugins as $plugin) { $status = WP_Optimize()->get_db_info()->get_plugin_status($plugin); if (__('WordPress core', 'wp-optimize') == $plugin) $wp_core_table = true; // if plugin is active then we can't remove. if ($wp_core_table || $status['active'] || $wp_actionscheduler_table) $can_be_removed = false; if ($status['installed'] || $status['active'] || !$table_obj->is_using) { $plugin_status[] = array( 'plugin' => $plugin, 'status' => $status, ); } } $table_obj->plugin_status = $plugin_status; } $table_obj->wp_core_table = $wp_core_table; $table_obj->can_be_removed = $can_be_removed; return $table_obj; } /** * This function grabs a list of tables * and information regarding each table and returns * the results to optimizations-table.php and optimizationstable.php * * @param int $blog_id filter tables by prefix * * @return Array - an array of data such as table list, innodb info and data free */ public function get_table_information($blog_id = 0) { // Get table information. $tablesstatus = $this->get_tables(); // Set defaults. $table_information = array(); $table_information['total_gain'] = 0; $table_information['inno_db_tables'] = 0; $table_information['non_inno_db_tables'] = 0; $table_information['table_list'] = ''; $table_information['is_optimizable'] = true; // Make a list of tables to optimize. foreach ($tablesstatus as $each_table) { // if $blog_id is set then filter tables if ($blog_id > 0 && $blog_id != $each_table->blog_id) continue; $table_information['table_list'] .= $each_table->Name.'|'; // check if table type supported. if (!$each_table->is_type_supported) continue; // check if table is optimizable. if (!$each_table->is_optimizable) { $table_information['is_optimizable'] = false; } // calculate total gain value. $table_information['total_gain'] += $each_table->Data_free; // count InnoDB tables. if ('InnoDB' == $each_table->Engine) { $table_information['inno_db_tables']++; } else { $table_information['non_inno_db_tables']++; } } return $table_information; } /** * What sort of linkback to enable or disable: valid values are 'trackbacks' or 'comments', and whether to enable or disable. * * @param string $type Specify the type of linkbacks. * @param boolean $enable If it is enabled or disabled. */ public function enable_linkbacks($type, $enable = true) { $wpdb = $GLOBALS['wpdb']; $wpo_options = WP_Optimize()->get_options(); $new_status = $enable ? 'open' : 'closed'; switch ($type) { case "trackbacks": $thissql = "UPDATE `".$wpdb->posts."` SET ping_status='".$new_status."' WHERE post_status = 'publish' AND post_type = 'post';"; $wpdb->query($thissql); break; case "comments": $thissql = "UPDATE `".$wpdb->posts."` SET comment_status='".$new_status."' WHERE post_status = 'publish' AND post_type = 'post';"; $wpdb->query($thissql); break; default: break; } $wpo_options->update_option($type.'_action', array('action' => $enable, 'timestamp' => time())); } /** * This function will return total database size and a possible gain of db in KB. * * @param boolean $update - Wether to update the values or not * @return string total db size gained. */ public function get_current_db_size($update = false) { if (!$update && $db_size = get_transient('wpo_get_current_db_size')) { return $db_size; } $wp_optimize = WP_Optimize(); $total_gain = 0; $total_size = 0; $row_usage = 0;// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable -- $row_usage Used in the foreach below $data_usage = 0; $index_usage = 0; $overhead_usage = 0;// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable -- $overhead_usage Used in the foreach below $tablesstatus = $this->get_tables(); foreach ($tablesstatus as $tablestatus) { $row_usage += $tablestatus->Rows;// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable -- $row_usage declared up above $total_gain += $tablestatus->Data_free; $data_usage += $tablestatus->Data_length; $index_usage += $tablestatus->Index_length; if ('InnoDB' != $tablestatus->Engine) { $overhead_usage += $tablestatus->Data_free;// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable -- $overhead_usage declared up above $total_gain += $tablestatus->Data_free; } } $total_size = ($data_usage + $index_usage); $db_size = array($wp_optimize->format_size($total_size), $wp_optimize->format_size($total_gain)); set_transient('wpo_get_current_db_size', $db_size, 3600); return $db_size; } /** * This function will return total saved data in KB. * * @param string $current How big the data is. * @return string Returns new total value. */ public function update_total_cleaned($current) { $options = WP_Optimize()->get_options(); $previously_saved = floatval($options->get_option('total-cleaned', '0')); $converted_current = floatval($current); $total_now = strval($previously_saved + $converted_current); $options->update_option('total-cleaned', $total_now); return $total_now; } public function trackback_comment_actions($options) { $output = array(); $messages = array(); if (isset($options['comments'])) { if (!$options['comments']) { $this->enable_linkbacks('comments', false); $output[] = __('Comments have now been disabled on all current and previously published posts.', 'wp-optimize'); $messages[] = sprintf(__('All comments on existing posts were disabled at %s.', 'wp-optimize'), WP_Optimize()->format_date_time(time())); } else { $this->enable_linkbacks('comments'); $output[] = __('Comments have now been enabled on all current and previously published posts.', 'wp-optimize'); $messages[] = sprintf(__('All comments on existing posts were enabled at %s.', 'wp-optimize'), WP_Optimize()->format_date_time(time())); } } if (isset($options['trackbacks'])) { if (!$options['trackbacks']) { $this->enable_linkbacks('trackbacks', false); $output[] = __('Trackbacks have now been disabled on all current and previously published posts.', 'wp-optimize'); $messages[] = sprintf(__('All trackbacks on existing posts were disabled at %s.', 'wp-optimize'), WP_Optimize()->format_date_time(time())); } else { $this->enable_linkbacks('trackbacks'); $output[] = __('Trackbacks have now been enabled on all current and previously published posts.', 'wp-optimize'); $messages[] = sprintf(__('All trackbacks on existing posts were enabled at %s.', 'wp-optimize'), WP_Optimize()->format_date_time(time())); } } return array('output' => $output,'messages' => $messages); } /** * Wether InnoDB tables require confirmation to be optimized * * @return boolean */ public function show_innodb_force_optimize() { $tablesstatus = $this->get_table_information(); return false === $tablesstatus['is_optimizable'] && $tablesstatus['inno_db_tables'] > 0; } }