| 1 |
<?php |
| 2 |
/* |
| 3 |
Plugin Name: WP-Optimize |
| 4 |
Plugin URI: http://updraftplus.com |
| 5 |
Description: WP-Optimize is WordPress's #1 most installed optimization plugin. With it, you can clean up your database easily and safely, without manual queries. |
| 6 |
Version: 2.0.1 |
| 7 |
Author: David Anderson, Ruhani Rabin, Team Updraft |
| 8 |
Author URI: https://updraftplus.com |
| 9 |
Text Domain: wp-optimize |
| 10 |
Domain Path: /languages |
| 11 |
License: GPLv2 or later |
| 12 |
*/ |
| 13 |
|
| 14 |
if (!defined('ABSPATH')) die('No direct access allowed'); |
| 15 |
|
| 16 |
define('WPO_VERSION', '2.0.1'); |
| 17 |
define('WPO_PLUGIN_URL', plugin_dir_url( __FILE__ )); |
| 18 |
define('WPO_PLUGIN_MAIN_PATH', plugin_dir_path( __FILE__ )); |
| 19 |
|
| 20 |
class WP_Optimize { |
| 21 |
|
| 22 |
private $template_directories; |
| 23 |
|
| 24 |
protected static $_instance = null; |
| 25 |
protected static $_optimizer_instance = null; |
| 26 |
protected static $_options_instance = null; |
| 27 |
|
| 28 |
public function __construct() { |
| 29 |
|
| 30 |
register_activation_hook(__FILE__, 'wpo_activation_actions'); |
| 31 |
register_deactivation_hook(__FILE__, 'wpo_deactivation_actions'); |
| 32 |
|
| 33 |
add_action('plugins_loaded', array($this, 'plugins_loaded')); |
| 34 |
|
| 35 |
$plugin = plugin_basename(__FILE__); |
| 36 |
add_filter("plugin_action_links_$plugin", array($this, 'plugin_settings_link')); |
| 37 |
add_action('admin_init', array($this, 'admin_init')); |
| 38 |
add_action('admin_menu', array($this, 'admin_menu')); |
| 39 |
add_action('admin_head', array($this, 'admin_head')); |
| 40 |
add_action('wpo_cron_event2', array($this, 'cron_action')); |
| 41 |
add_filter('cron_schedules', array($this, 'cron_schedules')); |
| 42 |
|
| 43 |
} |
| 44 |
|
| 45 |
public static function instance() { |
| 46 |
if (empty(self::$_instance)) { |
| 47 |
self::$_instance = new self(); |
| 48 |
} |
| 49 |
return self::$_instance; |
| 50 |
} |
| 51 |
|
| 52 |
public static function get_optimizer() { |
| 53 |
if (empty(self::$_optimizer_instance)) { |
| 54 |
if (!class_exists('WP_Optimizer')) require_once(WPO_PLUGIN_MAIN_PATH.'/includes/class-wp-optimizer.php'); |
| 55 |
self::$_optimizer_instance = new WP_Optimizer(); |
| 56 |
} |
| 57 |
return self::$_optimizer_instance; |
| 58 |
} |
| 59 |
|
| 60 |
public static function get_options() { |
| 61 |
if (empty(self::$_options_instance)) { |
| 62 |
if (!class_exists('WP_Optimize_Options')) require_once(WPO_PLUGIN_MAIN_PATH.'/includes/class-wp-optimize-options.php'); |
| 63 |
self::$_options_instance = new WP_Optimize_Options(); |
| 64 |
} |
| 65 |
return self::$_options_instance; |
| 66 |
} |
| 67 |
|
| 68 |
public function admin_init() { |
| 69 |
$this->register_template_directories(); |
| 70 |
} |
| 71 |
|
| 72 |
public function plugins_loaded() { |
| 73 |
load_plugin_textdomain('wp-optimize', false, dirname( plugin_basename( __FILE__ ) ) . '/languages' ); |
| 74 |
} |
| 75 |
|
| 76 |
public function capability_required() { |
| 77 |
return apply_filters('wp_optimize_capability_required', 'manage_options'); |
| 78 |
} |
| 79 |
|
| 80 |
public function wp_optimize_menu() { |
| 81 |
|
| 82 |
$capability_required = $this->capability_required(); |
| 83 |
|
| 84 |
if (!current_user_can($capability_required)) { echo "Permission denied."; return; } |
| 85 |
|
| 86 |
$enqueue_version = (defined('WP_DEBUG') && WP_DEBUG) ? WPO_VERSION.'.'.time() : WPO_VERSION; |
| 87 |
|
| 88 |
wp_enqueue_script('wp-optimize-admin', WPO_PLUGIN_URL.'js/admin.js', array('jquery'), $enqueue_version); |
| 89 |
|
| 90 |
$options = $this->get_options(); |
| 91 |
|
| 92 |
$active_tab = isset($_GET['tab']) ? $_GET['tab'] : 'wp_optimize_optimize'; |
| 93 |
if ('wp_optimize_tables' != $active_tab && 'wp_optimize_settings' != $active_tab && 'wp_optimize_may_also' != $active_tab) $active_tab = 'wp_optimize_optimize'; |
| 94 |
|
| 95 |
if ('wp_optimize_optimize' == $active_tab && !empty($_REQUEST['_wpnonce']) && wp_verify_nonce($_REQUEST['_wpnonce'], 'wpo_optimization')) $options->save_posted_options(); |
| 96 |
|
| 97 |
$this->include_template('admin-page-header.php', false, array('active_tab' => $active_tab)); |
| 98 |
|
| 99 |
echo '<div class="wrap wp-optimize-wrap">'; |
| 100 |
|
| 101 |
// TODO: Make the page more interactive by printing all the tabs, and switching using JavaScript instead of using page re-loads |
| 102 |
if ('wp_optimize_tables' == $active_tab) { |
| 103 |
|
| 104 |
// There's no way to trigger this, AFAICT. If we add it, it should have a nonce to protect it. |
| 105 |
$optimize_db = false;//isset($_POST["optimize-db"]); |
| 106 |
|
| 107 |
$this->include_template('tables.php', false, array('optimize_db' => $optimize_db)); |
| 108 |
|
| 109 |
} elseif ('wp_optimize_settings' == $active_tab) { |
| 110 |
|
| 111 |
$output = $options->save_posted_settings(); |
| 112 |
|
| 113 |
foreach ($output as $item) { |
| 114 |
echo '<div class="updated fade"><strong>'.$item.'</strong></div>'; |
| 115 |
} |
| 116 |
|
| 117 |
$this->include_template('admin-settings.php'); |
| 118 |
|
| 119 |
} elseif ('wp_optimize_may_also' == $active_tab) { |
| 120 |
|
| 121 |
$this->include_template('may-also-like.php'); |
| 122 |
|
| 123 |
} else { |
| 124 |
|
| 125 |
$nonce_passed = (!empty($_REQUEST['_wpnonce']) && wp_verify_nonce($_REQUEST['_wpnonce'], 'wpo_optimization')) ? true : false; |
| 126 |
|
| 127 |
// Default tab: wp_optimize_optimize |
| 128 |
|
| 129 |
$optimizer = $this->get_optimizer(); |
| 130 |
|
| 131 |
$optimization_results = $nonce_passed ? $optimizer->do_optimizations($_POST) : false; |
| 132 |
|
| 133 |
if (!empty($optimization_results)) { |
| 134 |
|
| 135 |
echo '<div id="message" class="updated"><strong>'; |
| 136 |
|
| 137 |
foreach ($optimization_results as $optimization_result) { |
| 138 |
|
| 139 |
if (!empty($optimization_result->output)) { |
| 140 |
|
| 141 |
foreach ($optimization_result->output as $line) { |
| 142 |
echo $line."<br>"; |
| 143 |
} |
| 144 |
|
| 145 |
} |
| 146 |
|
| 147 |
} |
| 148 |
|
| 149 |
echo '</strong></div>'; |
| 150 |
|
| 151 |
} |
| 152 |
|
| 153 |
$optimize_db = ($nonce_passed && isset($_POST["optimize-db"])); |
| 154 |
|
| 155 |
$this->include_template('optimize-table.php', false, array('optimize_db' => $optimize_db)); |
| 156 |
|
| 157 |
} |
| 158 |
|
| 159 |
echo '</div>'; |
| 160 |
|
| 161 |
} |
| 162 |
|
| 163 |
public function wpo_admin_bar() { |
| 164 |
global $wp_admin_bar; |
| 165 |
|
| 166 |
// Add a link called at the top admin bar |
| 167 |
$wp_admin_bar->add_node(array( |
| 168 |
'id' => 'wp-optimize', |
| 169 |
'title' => 'WP-Optimize', |
| 170 |
'href' => menu_page_url( 'WP-Optimize', false ), |
| 171 |
)); |
| 172 |
|
| 173 |
} |
| 174 |
|
| 175 |
// Add settings link on plugin page |
| 176 |
public function plugin_settings_link($links) { |
| 177 |
|
| 178 |
$admin_page_url = $this->get_options()->admin_page_url(); |
| 179 |
|
| 180 |
$settings_link = '<a href="' . esc_url( $admin_page_url ) . '">' . __( 'Settings', 'wp-optimize' ) . '</a>'; |
| 181 |
array_unshift($links, $settings_link); |
| 182 |
|
| 183 |
$optimize_link = '<a href="' . esc_url( $admin_page_url ) . '">' . __( 'Optimizer', 'wp-optimize' ) . '</a>'; |
| 184 |
array_unshift($links, $optimize_link); |
| 185 |
return $links; |
| 186 |
} |
| 187 |
|
| 188 |
// TODO: Need to find out why the schedule time is not refreshing |
| 189 |
public function cron_activate() { |
| 190 |
$gmtoffset = (int) (3600 * ((double) get_option('gmt_offset'))); |
| 191 |
|
| 192 |
$options = $this->get_options(); |
| 193 |
|
| 194 |
if ($options->get_option('schedule') === false ) { |
| 195 |
$options->set_default_options(); |
| 196 |
} else { |
| 197 |
if ($options->get_option('schedule') == 'true') { |
| 198 |
if (!wp_next_scheduled('wpo_cron_event2')) { |
| 199 |
|
| 200 |
$schedule_type = $options->get_option('schedule-type', 'wpo_weekly'); |
| 201 |
|
| 202 |
$this_time = 86400*7; |
| 203 |
|
| 204 |
switch ($schedule_type) { |
| 205 |
case "wpo_daily": |
| 206 |
$this_time = 86400; |
| 207 |
break; |
| 208 |
|
| 209 |
case "wpo_weekly": |
| 210 |
$this_time = 86400*7; |
| 211 |
break; |
| 212 |
|
| 213 |
case "wpo_otherweekly": |
| 214 |
$this_time = 86400*14; |
| 215 |
break; |
| 216 |
|
| 217 |
case "wpo_monthly": |
| 218 |
$this_time = 86400*30; |
| 219 |
break; |
| 220 |
} |
| 221 |
|
| 222 |
add_action('wpo_cron_event2', array($this, 'cron_action')); |
| 223 |
wp_schedule_event(current_time( "timestamp", 0 ) + $this_time , $schedule_type, 'wpo_cron_event2'); |
| 224 |
WP_Optimize()->log('running wp_schedule_event()'); |
| 225 |
} |
| 226 |
} |
| 227 |
} |
| 228 |
} |
| 229 |
|
| 230 |
|
| 231 |
// scheduler public functions to update schedulers |
| 232 |
public function cron_schedules( $schedules ) { |
| 233 |
$schedules['wpo_daily'] = array('interval' => 86400, 'display' => 'Once Daily'); |
| 234 |
$schedules['wpo_weekly'] = array('interval' => 86400*7, 'display' => 'Once Weekly'); |
| 235 |
$schedules['wpo_otherweekly'] = array('interval' => 86400*14, 'display' => 'Once Every Other Week'); |
| 236 |
$schedules['wpo_monthly'] = array('interval' => 86400*30, 'display' => 'Once Every Month'); |
| 237 |
return $schedules; |
| 238 |
} |
| 239 |
|
| 240 |
|
| 241 |
public function admin_head() { |
| 242 |
$style_url = plugins_url( '/css/wpo_admin.css', __FILE__ ) ; |
| 243 |
echo "<link rel='stylesheet' type='text/css' href='".$style_url."' />\n"; |
| 244 |
} |
| 245 |
|
| 246 |
public function admin_menu() { |
| 247 |
|
| 248 |
$capability_required = $this->capability_required(); |
| 249 |
|
| 250 |
if (!current_user_can($capability_required)) return; |
| 251 |
|
| 252 |
if (function_exists('add_meta_box')) { |
| 253 |
add_menu_page("WP-Optimize", "WP-Optimize", $capability_required, "WP-Optimize", array($this,"wp_optimize_menu"), plugin_dir_url( __FILE__ ).'images/icon/wpo.png'); |
| 254 |
} else { |
| 255 |
add_submenu_page("index.php", "WP-Optimize", "WP-Optimize", $capability_required, "WP-Optimize", array($this,"wp_optimize_menu"), plugin_dir_url( __FILE__ ).'images/icon/wpo.png'); |
| 256 |
} |
| 257 |
|
| 258 |
$options = $this->get_options(); |
| 259 |
|
| 260 |
if ($options->get_option('enable-admin-menu', 'false' ) == 'true') { |
| 261 |
add_action('wp_before_admin_bar_render', array($this, 'wpo_admin_bar')); |
| 262 |
} |
| 263 |
|
| 264 |
$options->set_default_options(); |
| 265 |
$this->cron_activate(); |
| 266 |
} |
| 267 |
|
| 268 |
private function wp_normalize_path($path) { |
| 269 |
// wp_normalize_path is not present before WP 3.9 |
| 270 |
if (function_exists('wp_normalize_path')) return wp_normalize_path($path); |
| 271 |
// Taken from WP 4.6 |
| 272 |
$path = str_replace( '\\', '/', $path ); |
| 273 |
$path = preg_replace( '|(?<=.)/+|', '/', $path ); |
| 274 |
if ( ':' === substr( $path, 1, 1 ) ) { |
| 275 |
$path = ucfirst( $path ); |
| 276 |
} |
| 277 |
return $path; |
| 278 |
} |
| 279 |
|
| 280 |
public function get_templates_dir() { |
| 281 |
return apply_filters('wp_optimize_templates_dir', $this->wp_normalize_path(WPO_PLUGIN_MAIN_PATH.'/templates')); |
| 282 |
} |
| 283 |
|
| 284 |
public function get_templates_url() { |
| 285 |
return apply_filters('wp_optimize_templates_url', WPO_PLUGIN_MAIN_PATH.'/templates'); |
| 286 |
} |
| 287 |
|
| 288 |
public function include_template($path, $return_instead_of_echo = false, $extract_these = array()) { |
| 289 |
if ($return_instead_of_echo) ob_start(); |
| 290 |
|
| 291 |
if (preg_match('#^([^/]+)/(.*)$#', $path, $matches)) { |
| 292 |
$prefix = $matches[1]; |
| 293 |
$suffix = $matches[2]; |
| 294 |
if (isset($this->template_directories[$prefix])) { |
| 295 |
$template_file = $this->template_directories[$prefix].'/'.$suffix; |
| 296 |
} |
| 297 |
} |
| 298 |
|
| 299 |
if (!isset($template_file)) { |
| 300 |
$template_file = WPO_PLUGIN_MAIN_PATH.'/templates/'.$path; |
| 301 |
} |
| 302 |
|
| 303 |
$template_file = apply_filters('wp_optimize_template', $template_file, $path); |
| 304 |
|
| 305 |
do_action('wp_optimize_before_template', $path, $template_file, $return_instead_of_echo, $extract_these); |
| 306 |
|
| 307 |
if (!file_exists($template_file)) { |
| 308 |
error_log("WP Optimize: template not found: $template_file"); |
| 309 |
echo __('Error:', 'wp-optimize').' '.__('template not found', 'wp-optimize')." ($path)"; |
| 310 |
} else { |
| 311 |
extract($extract_these); |
| 312 |
global $wpdb; |
| 313 |
$wp_optimize = $this; |
| 314 |
$optimizer = $this->get_optimizer(); |
| 315 |
$options = $this->get_options(); |
| 316 |
include $template_file; |
| 317 |
} |
| 318 |
|
| 319 |
do_action('wp_optimize_after_template', $path, $template_file, $return_instead_of_echo, $extract_these); |
| 320 |
|
| 321 |
if ($return_instead_of_echo) return ob_get_clean(); |
| 322 |
} |
| 323 |
|
| 324 |
private function register_template_directories() { |
| 325 |
|
| 326 |
$template_directories = array(); |
| 327 |
|
| 328 |
$templates_dir = $this->get_templates_dir(); |
| 329 |
|
| 330 |
if ($dh = opendir($templates_dir)) { |
| 331 |
while (($file = readdir($dh)) !== false) { |
| 332 |
if ('.' == $file || '..' == $file) continue; |
| 333 |
if (is_dir($templates_dir.'/'.$file)) { |
| 334 |
$template_directories[$file] = $templates_dir.'/'.$file; |
| 335 |
} |
| 336 |
} |
| 337 |
closedir($dh); |
| 338 |
} |
| 339 |
|
| 340 |
// This is the optimal hook for most extensions to hook into |
| 341 |
$this->template_directories = apply_filters('wp_optimize_template_directories', $template_directories); |
| 342 |
|
| 343 |
} |
| 344 |
|
| 345 |
// TODO: Not currently used; investigate. |
| 346 |
// TODO: The description does not match the actual function |
| 347 |
/** |
| 348 |
* send_email($sendto, $msg) |
| 349 |
* @return success |
| 350 |
* @param $sentdo - eg. who to send it to, abc@def.com |
| 351 |
* @param $msg - the msg in text |
| 352 |
*/ |
| 353 |
public function send_email($date, $cleanedup){ |
| 354 |
// |
| 355 |
ob_start(); |
| 356 |
// #TODO this need to work on - currently not using the parameter values |
| 357 |
$myTime = current_time( "timestamp", 0 ); |
| 358 |
$myDate = gmdate(get_option('date_format') . ' ' . get_option('time_format'), $myTime ); |
| 359 |
|
| 360 |
//$formattedCleanedup = $wp_optimize->format_size($cleanedup); |
| 361 |
|
| 362 |
$sendto = $options->get_option('email-address'); |
| 363 |
if (!$sendto) $sendto = get_bloginfo ( 'admin_email' ); |
| 364 |
|
| 365 |
//$thiscleanup = $wp_optimize->format_size($cleanedup); |
| 366 |
|
| 367 |
$subject = get_bloginfo ( 'name' ).": ".__("Automatic Operation Completed","wp-optimize")." ".$myDate; |
| 368 |
|
| 369 |
$msg = __("Scheduled optimization was executed at","wp-optimize")." ".$myDate."\r\n"."\r\n"; |
| 370 |
//$msg .= __("Recovered space","wp-optimize").": ".$thiscleanup."\r\n"; |
| 371 |
$msg .= __("You can safely delete this email.","wp-optimize")."\r\n"; |
| 372 |
$msg .= "\r\n"; |
| 373 |
$msg .= __("Regards,","wp-optimize")."\r\n"; |
| 374 |
$msg .= __("WP-Optimize Plugin","wp-optimize"); |
| 375 |
|
| 376 |
//wp_mail( $sendto, $subject, $msg ); |
| 377 |
|
| 378 |
ob_end_flush(); |
| 379 |
} |
| 380 |
|
| 381 |
/* |
| 382 |
* function log() |
| 383 |
* |
| 384 |
* parameters: message to debug |
| 385 |
* |
| 386 |
* @return none |
| 387 |
*/ |
| 388 |
public function log($message) { |
| 389 |
if (defined('WP_DEBUG') && WP_DEBUG) { |
| 390 |
error_log($message); |
| 391 |
} |
| 392 |
} |
| 393 |
|
| 394 |
/** |
| 395 |
* $wp_optimize->format_size() |
| 396 |
* Function: Format Bytes Into KB/MB |
| 397 |
* @param mixed $bytes |
| 398 |
* @return |
| 399 |
*/ |
| 400 |
public function format_size($bytes) { |
| 401 |
if ($bytes > 1073741824) { |
| 402 |
return number_format_i18n($bytes/1073741824, 2) . ' '.__('GB', 'wp-optimize'); |
| 403 |
} elseif ($bytes > 1048576) { |
| 404 |
return number_format_i18n($bytes/1048576, 1) . ' '.__('MB', 'wp-optimize'); |
| 405 |
} elseif ($bytes > 1024) { |
| 406 |
return number_format_i18n($bytes/1024, 1) . ' '.__('KB', 'wp-optimize'); |
| 407 |
} else { |
| 408 |
return number_format_i18n($bytes, 0) . ' '.__('bytes', 'wp-optimize'); |
| 409 |
} |
| 410 |
} |
| 411 |
|
| 412 |
/* |
| 413 |
* function cron_action() |
| 414 |
* |
| 415 |
* parameters: none |
| 416 |
* |
| 417 |
* executed this function on cron event |
| 418 |
* |
| 419 |
* @return none |
| 420 |
*/ |
| 421 |
public function cron_action() { |
| 422 |
|
| 423 |
$optimizer = $this->get_optimizer(); |
| 424 |
$options = $this->get_options(); |
| 425 |
|
| 426 |
$this->log('WPO: Starting cron_action()'); |
| 427 |
|
| 428 |
if ('true' == $options->get_option('schedule')) { |
| 429 |
|
| 430 |
$this_options = $options->get_option('auto'); |
| 431 |
|
| 432 |
$optimizations = $optimizer->get_optimizations(); |
| 433 |
|
| 434 |
// TODO: The output of the optimizations is not saved/used/logged |
| 435 |
$results = $optimizer->do_optimizations($this_options, 'auto'); |
| 436 |
|
| 437 |
} |
| 438 |
|
| 439 |
} |
| 440 |
|
| 441 |
} |
| 442 |
|
| 443 |
function WP_Optimize() { |
| 444 |
return WP_Optimize::instance(); |
| 445 |
} |
| 446 |
|
| 447 |
$GLOBALS['wp_optimize'] = WP_Optimize(); |
| 448 |
|
| 449 |
// plugin activation actions |
| 450 |
function wpo_activation_actions() { |
| 451 |
WP_Optimize()->get_options()->set_default_options(); |
| 452 |
} |
| 453 |
|
| 454 |
// plugin deactivation actions |
| 455 |
function wpo_deactivation_actions() { |
| 456 |
wpo_cron_deactivate(); |
| 457 |
WP_Optimize()->get_options()->delete_all_options(); |
| 458 |
} |
| 459 |
|
| 460 |
function wpo_cron_deactivate() { |
| 461 |
WP_Optimize()->log('running wpo_cron_deactivate()'); |
| 462 |
wp_clear_scheduled_hook('wpo_cron_event2'); |
| 463 |
} |
| 464 |
|