| @@ -2,14 +2,18 @@ | ||
| 2 | 2 | /* |
| 3 | 3 | Plugin Name: WP Reset |
| 4 | 4 | Plugin URI: https://wpreset.com/ |
| 5 | 5 | Description: Reset the entire site or just selected parts while reserving the option to undo by using snapshots. |
| 6 | - Version: 1.75 | |
| 6 | + Version: 2.05 | |
| 7 | + Requires at least: 4.0 | |
| 8 | + Requires PHP: 5.2 | |
| 9 | + Tested up to: 6.8 | |
| 10 | + License: GPLv2 or later | |
| 7 | 11 | Author: WebFactory Ltd |
| 8 | 12 | Author URI: https://www.webfactoryltd.com/ |
| 9 | 13 | Text Domain: wp-reset |
| 10 | 14 | |
| 11 | - Copyright 2015 - 2019 Web factory Ltd (email: wpreset@webfactoryltd.com) | |
| 15 | + Copyright 2015 - 2025 WebFactory Ltd (email: wpreset@webfactoryltd.com) | |
| 12 | 16 | |
| 13 | 17 | This program is free software; you can redistribute it and/or modify |
| 14 | 18 | it under the terms of the GNU General Public License, version 2, as |
| 15 | 19 | published by the Free Software Foundation. |
| @@ -25,2594 +29,3143 @@ | ||
| 25 | 29 | */ |
| 26 | 30 | |
| 27 | 31 | // include only file |
| 28 | 32 | if (!defined('ABSPATH')) { |
| 29 | - wp_die(__('Do not open this file directly.', 'wp-reset')); | |
| 33 | + die('Do not open this file directly.'); | |
| 30 | 34 | } |
| 31 | 35 | |
| 32 | 36 | |
| 37 | +define('WP_RESET_FILE', __FILE__); | |
| 38 | + | |
| 39 | +require_once dirname(__FILE__) . '/wp-reset-utility.php'; | |
| 40 | +require_once dirname(__FILE__) . '/wp-reset-licensing.php'; | |
| 41 | + | |
| 42 | +require_once dirname(__FILE__) . '/wf-flyout/wf-flyout.php'; | |
| 43 | +new wf_flyout(__FILE__); | |
| 44 | + | |
| 33 | 45 | // load WP-CLI commands, if needed |
| 34 | 46 | if (defined('WP_CLI') && WP_CLI) { |
| 35 | - require_once dirname(__FILE__) . '/wp-reset-cli.php'; | |
| 47 | + require_once dirname(__FILE__) . '/wp-reset-cli.php'; | |
| 36 | 48 | } |
| 37 | 49 | |
| 38 | 50 | |
| 39 | 51 | class WP_Reset |
| 40 | 52 | { |
| 41 | - protected static $instance = null; | |
| 42 | - public $version = 0; | |
| 43 | - public $plugin_url = ''; | |
| 44 | - public $plugin_dir = ''; | |
| 45 | - public $snapshots_folder = 'wp-reset-snapshots-export'; | |
| 46 | - protected $options = array(); | |
| 47 | - private $delete_count = 0; | |
| 48 | - private $licensing_servers = array('https://license1.wpreset.com/', 'https://license2.wpreset.com/'); | |
| 49 | - private $core_tables = array('commentmeta', 'comments', 'links', 'options', 'postmeta', 'posts', 'term_relationships', 'term_taxonomy', 'termmeta', 'terms', 'usermeta', 'users'); | |
| 53 | + protected static $instance = null; | |
| 54 | + public $version = 0; | |
| 55 | + public $plugin_url = ''; | |
| 56 | + public $plugin_dir = ''; | |
| 57 | + public $snapshots_folder = 'wp-reset-snapshots-export'; | |
| 58 | + protected $options = array(); | |
| 59 | + private $delete_count = 0; | |
| 60 | + private $licensing_servers = array('https://dashboard.wpreset.com/api/'); | |
| 61 | + public $core_tables = array('commentmeta', 'comments', 'links', 'options', 'postmeta', 'posts', 'term_relationships', 'term_taxonomy', 'termmeta', 'terms', 'usermeta', 'users'); | |
| 62 | + private $license = null; | |
| 63 | + public $filesystem_initialized = false; | |
| 50 | 64 | |
| 65 | + /** | |
| 66 | + * Creates a new WP_Reset object and implements singleton | |
| 67 | + * | |
| 68 | + * @return WP_Reset | |
| 69 | + */ | |
| 70 | + static function getInstance() | |
| 71 | + { | |
| 72 | + if (!is_a(self::$instance, 'WP_Reset')) { | |
| 73 | + self::$instance = new WP_Reset(); | |
| 74 | + } | |
| 51 | 75 | |
| 52 | - /** | |
| 53 | - * Creates a new WP_Reset object and implements singleton | |
| 54 | - * | |
| 55 | - * @return WP_Reset | |
| 56 | - */ | |
| 57 | - static function getInstance() | |
| 58 | - { | |
| 59 | - if (!is_a(self::$instance, 'WP_Reset')) { | |
| 60 | - self::$instance = new WP_Reset(); | |
| 61 | - } | |
| 76 | + return self::$instance; | |
| 77 | + } // getInstance | |
| 62 | 78 | |
| 63 | - return self::$instance; | |
| 64 | - } // getInstance | |
| 65 | 79 | |
| 80 | + /** | |
| 81 | + * Initialize properties, hook to filters and actions | |
| 82 | + * | |
| 83 | + * @return null | |
| 84 | + */ | |
| 85 | + private function __construct() | |
| 86 | + { | |
| 87 | + $this->version = $this->get_plugin_version(); | |
| 88 | + $this->plugin_dir = plugin_dir_path(__FILE__); | |
| 89 | + $this->plugin_url = plugin_dir_url(__FILE__); | |
| 90 | + $this->load_options(); | |
| 66 | 91 | |
| 67 | - /** | |
| 68 | - * Initialize properties, hook to filters and actions | |
| 69 | - * | |
| 70 | - * @return null | |
| 71 | - */ | |
| 72 | - private function __construct() | |
| 73 | - { | |
| 74 | - $this->version = $this->get_plugin_version(); | |
| 75 | - $this->plugin_dir = plugin_dir_path(__FILE__); | |
| 76 | - $this->plugin_url = plugin_dir_url(__FILE__); | |
| 77 | - $this->load_options(); | |
| 92 | + $this->license = new WF_Licensing(array( | |
| 93 | + 'prefix' => 'wpr', | |
| 94 | + 'licensing_servers' => $this->licensing_servers, | |
| 95 | + 'version' => $this->version, | |
| 96 | + 'plugin_file' => __FILE__, | |
| 97 | + 'plugin_page' => 'tools_page_wp-reset', | |
| 98 | + 'skip_hooks' => false, | |
| 99 | + 'debug' => true, | |
| 100 | + 'js_folder' => plugin_dir_url(__FILE__) . '/js/' | |
| 101 | + )); | |
| 78 | 102 | |
| 79 | - add_action('admin_menu', array($this, 'admin_menu')); | |
| 80 | - add_action('admin_init', array($this, 'do_all_actions')); | |
| 81 | - add_action('admin_enqueue_scripts', array($this, 'admin_enqueue_scripts')); | |
| 82 | - add_action('wp_ajax_wp_reset_dismiss_notice', array($this, 'ajax_dismiss_notice')); | |
| 83 | - add_action('wp_ajax_wp_reset_run_tool', array($this, 'ajax_run_tool')); | |
| 84 | - add_action('wp_ajax_wp_reset_submit_survey', array($this, 'ajax_submit_survey')); | |
| 85 | - add_action('admin_action_install_webhooks', array($this, 'install_webhooks')); | |
| 86 | - add_action('admin_print_scripts', array($this, 'remove_admin_notices')); | |
| 103 | + add_action('admin_menu', array($this, 'admin_menu')); | |
| 104 | + add_action('admin_init', array($this, 'do_all_actions')); | |
| 105 | + add_action('admin_enqueue_scripts', array($this, 'admin_enqueue_scripts')); | |
| 106 | + add_action('admin_action_wpr_dismiss_notice', array($this, 'action_dismiss_notice')); | |
| 107 | + add_action('wp_ajax_wp_reset_dismiss_notice', array($this, 'ajax_dismiss_notice')); | |
| 108 | + add_action('wp_ajax_wp_reset_run_tool', array($this, 'ajax_run_tool')); | |
| 109 | + add_action('admin_print_scripts', array($this, 'remove_admin_notices')); | |
| 110 | + add_action('admin_action_wpr_install_wpfssl', array($this, 'install_wpfssl')); | |
| 87 | 111 | |
| 88 | - add_filter('plugin_action_links_' . plugin_basename(__FILE__), array($this, 'plugin_action_links')); | |
| 89 | - add_filter('plugin_row_meta', array($this, 'plugin_meta_links'), 10, 2); | |
| 90 | - add_filter('admin_footer_text', array($this, 'admin_footer_text')); | |
| 91 | - add_filter('install_plugins_table_api_args_featured', array($this, 'featured_plugins_tab')); | |
| 112 | + add_filter('plugin_action_links_' . plugin_basename(__FILE__), array($this, 'plugin_action_links')); | |
| 113 | + add_filter('plugin_row_meta', array($this, 'plugin_meta_links'), 10, 2); | |
| 114 | + add_filter('admin_footer_text', array($this, 'admin_footer_text')); | |
| 92 | 115 | |
| 93 | - $this->core_tables = array_map(function ($tbl) { | |
| 94 | - global $wpdb; | |
| 95 | - return $wpdb->prefix . $tbl; | |
| 96 | - }, $this->core_tables); | |
| 97 | - } // __construct | |
| 116 | + $this->core_tables = array_map(function ($tbl) { | |
| 117 | + global $wpdb; | |
| 118 | + return $wpdb->prefix . $tbl; | |
| 119 | + }, $this->core_tables); | |
| 120 | + } // __construct | |
| 98 | 121 | |
| 99 | 122 | |
| 100 | - /** | |
| 101 | - * Get plugin version from file header | |
| 102 | - * | |
| 103 | - * @return string | |
| 104 | - */ | |
| 105 | - function get_plugin_version() | |
| 106 | - { | |
| 107 | - $plugin_data = get_file_data(__FILE__, array('version' => 'Version'), 'plugin'); | |
| 123 | + /** | |
| 124 | + * Get plugin version from file header | |
| 125 | + * | |
| 126 | + * @return string | |
| 127 | + */ | |
| 128 | + function get_plugin_version() | |
| 129 | + { | |
| 130 | + $plugin_data = get_file_data(__FILE__, array('version' => 'Version'), 'plugin'); | |
| 108 | 131 | |
| 109 | - return $plugin_data['version']; | |
| 110 | - } // get_plugin_version | |
| 132 | + return $plugin_data['version']; | |
| 133 | + } // get_plugin_version | |
| 111 | 134 | |
| 112 | 135 | |
| 113 | - /** | |
| 114 | - * Load and prepare the options array | |
| 115 | - * If needed create a new DB entry | |
| 116 | - * | |
| 117 | - * @return array | |
| 118 | - */ | |
| 119 | - private function load_options() | |
| 120 | - { | |
| 121 | - $options = get_option('wp-reset', array()); | |
| 122 | - $change = false; | |
| 136 | + /** | |
| 137 | + * Load and prepare the options array | |
| 138 | + * If needed create a new DB entry | |
| 139 | + * | |
| 140 | + * @return array | |
| 141 | + */ | |
| 142 | + private function load_options() | |
| 143 | + { | |
| 144 | + $options = get_option('wp-reset', array()); | |
| 145 | + $change = false; | |
| 123 | 146 | |
| 124 | - if (!isset($options['meta'])) { | |
| 125 | - $options['meta'] = array('first_version' => $this->version, 'first_install' => current_time('timestamp', true), 'reset_count' => 0); | |
| 126 | - $change = true; | |
| 127 | - } | |
| 128 | - if (!isset($options['dismissed_notices'])) { | |
| 129 | - $options['dismissed_notices'] = array(); | |
| 130 | - $change = true; | |
| 131 | - } | |
| 132 | - if (!isset($options['last_run'])) { | |
| 133 | - $options['last_run'] = array(); | |
| 134 | - $change = true; | |
| 135 | - } | |
| 136 | - if (!isset($options['options'])) { | |
| 137 | - $options['options'] = array(); | |
| 138 | - $change = true; | |
| 139 | - } | |
| 140 | - if ($change) { | |
| 141 | - update_option('wp-reset', $options, true); | |
| 142 | - } | |
| 147 | + if (!isset($options['meta'])) { | |
| 148 | + $options['meta'] = array('first_version' => $this->version, 'first_install' => current_time('timestamp', true), 'reset_count' => 0); | |
| 149 | + $change = true; | |
| 150 | + } | |
| 151 | + if (!isset($options['dismissed_notices'])) { | |
| 152 | + $options['dismissed_notices'] = array(); | |
| 153 | + $change = true; | |
| 154 | + } | |
| 155 | + if (!isset($options['last_run'])) { | |
| 156 | + $options['last_run'] = array(); | |
| 157 | + $change = true; | |
| 158 | + } | |
| 159 | + if (!isset($options['options'])) { | |
| 160 | + $options['options'] = array(); | |
| 161 | + $change = true; | |
| 162 | + } | |
| 163 | + if ($change) { | |
| 164 | + update_option('wp-reset', $options, true); | |
| 165 | + } | |
| 143 | 166 | |
| 144 | - $this->options = $options; | |
| 145 | - return $options; | |
| 146 | - } // load_options | |
| 167 | + $this->options = $options; | |
| 168 | + return $options; | |
| 169 | + } // load_options | |
| 147 | 170 | |
| 148 | 171 | |
| 149 | - /** | |
| 150 | - * Get meta part of plugin options | |
| 151 | - * | |
| 152 | - * @return array | |
| 153 | - */ | |
| 154 | - function get_meta() | |
| 155 | - { | |
| 156 | - return $this->options['meta']; | |
| 157 | - } // get_meta | |
| 172 | + /** | |
| 173 | + * Get meta part of plugin options | |
| 174 | + * | |
| 175 | + * @return array | |
| 176 | + */ | |
| 177 | + function get_meta() | |
| 178 | + { | |
| 179 | + return $this->options['meta']; | |
| 180 | + } // get_meta | |
| 158 | 181 | |
| 159 | 182 | |
| 160 | - /** | |
| 161 | - * Get all dismissed notices, or check for one specific notice | |
| 162 | - * | |
| 163 | - * @param string $notice_name Optional. Check if specified notice is dismissed. | |
| 164 | - * | |
| 165 | - * @return bool|array | |
| 166 | - */ | |
| 167 | - function get_dismissed_notices($notice_name = '') | |
| 168 | - { | |
| 169 | - $notices = $this->options['dismissed_notices']; | |
| 183 | + /** | |
| 184 | + * Get all dismissed notices, or check for one specific notice | |
| 185 | + * | |
| 186 | + * @param string $notice_name Optional. Check if specified notice is dismissed. | |
| 187 | + * | |
| 188 | + * @return bool|array | |
| 189 | + */ | |
| 190 | + function get_dismissed_notices($notice_name = '') | |
| 191 | + { | |
| 192 | + $notices = $this->options['dismissed_notices']; | |
| 170 | 193 | |
| 171 | - if (empty($notice_name)) { | |
| 172 | - return $notices; | |
| 173 | - } else { | |
| 174 | - if (empty($notices[$notice_name])) { | |
| 175 | - return false; | |
| 176 | - } else { | |
| 177 | - return true; | |
| 178 | - } | |
| 179 | - } | |
| 180 | - } // get_dismissed_notices | |
| 194 | + if (empty($notice_name)) { | |
| 195 | + return $notices; | |
| 196 | + } else { | |
| 197 | + if (empty($notices[$notice_name])) { | |
| 198 | + return false; | |
| 199 | + } else { | |
| 200 | + return true; | |
| 201 | + } | |
| 202 | + } | |
| 203 | + } // get_dismissed_notices | |
| 181 | 204 | |
| 182 | 205 | |
| 183 | - /** | |
| 184 | - * Get options part of plugin options | |
| 185 | - * | |
| 186 | - * todo: not completed | |
| 187 | - * | |
| 188 | - * @param string $key Optional. | |
| 189 | - * | |
| 190 | - * @return array | |
| 191 | - */ | |
| 192 | - function get_options($key = '') | |
| 193 | - { | |
| 194 | - return $this->options['options']; | |
| 195 | - } // get_options | |
| 206 | + /** | |
| 207 | + * Get options part of plugin options | |
| 208 | + * | |
| 209 | + * @param string $key Optional. | |
| 210 | + * | |
| 211 | + * @return array | |
| 212 | + */ | |
| 213 | + function get_options() | |
| 214 | + { | |
| 215 | + return $this->options['options']; | |
| 216 | + } // get_options | |
| 196 | 217 | |
| 197 | 218 | |
| 198 | - /** | |
| 199 | - * Update plugin options, currently entire array | |
| 200 | - * | |
| 201 | - * todo: this handles the entire options array although it should only do the options part - it's confusing | |
| 202 | - * | |
| 203 | - * @param string $key Data to save. | |
| 204 | - * @param string $data Option key. | |
| 205 | - * | |
| 206 | - * @return bool | |
| 207 | - */ | |
| 208 | - function update_options($key, $data) | |
| 209 | - { | |
| 210 | - $this->options[$key] = $data; | |
| 211 | - $tmp = update_option('wp-reset', $this->options); | |
| 219 | + /** | |
| 220 | + * Update specified plugin options key | |
| 221 | + * | |
| 222 | + * @param string $key Data to save. | |
| 223 | + * @param string $data Option key. | |
| 224 | + * | |
| 225 | + * @return bool | |
| 226 | + */ | |
| 227 | + function update_options($key, $data) | |
| 228 | + { | |
| 229 | + if (false === in_array($key, array('meta', 'license', 'dismissed_notices', 'options'))) { | |
| 230 | + user_error('Unknown options key.', E_USER_ERROR); | |
| 231 | + return false; | |
| 232 | + } | |
| 212 | 233 | |
| 213 | - return $tmp; | |
| 214 | - } // set_options | |
| 234 | + $this->options[$key] = $data; | |
| 235 | + $tmp = update_option('wp-reset', $this->options); | |
| 215 | 236 | |
| 237 | + return $tmp; | |
| 238 | + } // update_options | |
| 216 | 239 | |
| 217 | - /** | |
| 218 | - * Add plugin menu entry under Tools menu | |
| 219 | - * | |
| 220 | - * @return null | |
| 221 | - */ | |
| 222 | - function admin_menu() | |
| 223 | - { | |
| 224 | - add_management_page(__('WP Reset', 'wp-reset'), __('WP Reset', 'wp-reset'), 'administrator', 'wp-reset', array($this, 'plugin_page')); | |
| 225 | - } // admin_menu | |
| 226 | 240 | |
| 241 | + /** | |
| 242 | + * Add plugin menu entry under Tools menu | |
| 243 | + * | |
| 244 | + * @return null | |
| 245 | + */ | |
| 246 | + function admin_menu() | |
| 247 | + { | |
| 248 | + add_management_page(__('WP Reset', 'wp-reset'), __('WP Reset', 'wp-reset'), 'administrator', 'wp-reset', array($this, 'plugin_page')); | |
| 249 | + } // admin_menu | |
| 227 | 250 | |
| 228 | - /** | |
| 229 | - * Dismiss notice via AJAX call | |
| 230 | - * | |
| 231 | - * @return null | |
| 232 | - */ | |
| 233 | - function ajax_dismiss_notice() | |
| 234 | - { | |
| 235 | - check_ajax_referer('wp-reset_dismiss_notice'); | |
| 236 | 251 | |
| 237 | - if (!current_user_can('administrator')) { | |
| 238 | - wp_send_json_error(__('You are not allowed to run this action.', 'wp-reset')); | |
| 239 | - } | |
| 252 | + /** | |
| 253 | + * Dismiss notice via AJAX call | |
| 254 | + * | |
| 255 | + * @return null | |
| 256 | + */ | |
| 257 | + function ajax_dismiss_notice() | |
| 258 | + { | |
| 259 | + check_ajax_referer('wp-reset_dismiss_notice'); | |
| 240 | 260 | |
| 241 | - $notice_name = trim(@$_GET['notice_name']); | |
| 242 | - if (!$this->dismiss_notice($notice_name)) { | |
| 243 | - wp_send_json_error(__('Notice is already dismissed.', 'wp-reset')); | |
| 244 | - } else { | |
| 245 | - wp_send_json_success(); | |
| 246 | - } | |
| 247 | - } // ajax_dismiss_notice | |
| 261 | + if (!current_user_can('manage_options')) { | |
| 262 | + wp_send_json_error(__('You are not allowed to run this action.', 'wp-reset')); | |
| 263 | + } | |
| 248 | 264 | |
| 265 | + if (!isset($_GET['notice_name'])) { | |
| 266 | + wp_send_json_error(__('Unknown Notice.', 'wp-reset')); | |
| 267 | + } | |
| 249 | 268 | |
| 250 | - /** | |
| 251 | - * Dismiss notice by adding it to dismissed_notices options array | |
| 252 | - * | |
| 253 | - * @param string $notice_name Notice to dismiss. | |
| 254 | - * | |
| 255 | - * @return bool | |
| 256 | - */ | |
| 257 | - function dismiss_notice($notice_name) | |
| 258 | - { | |
| 259 | - if ($this->get_dismissed_notices($notice_name)) { | |
| 260 | - return false; | |
| 261 | - } else { | |
| 262 | - $notices = $this->get_dismissed_notices(); | |
| 263 | - $notices[$notice_name] = true; | |
| 264 | - $this->update_options('dismissed_notices', $notices); | |
| 265 | - return true; | |
| 266 | - } | |
| 267 | - } // dismiss_notice | |
| 269 | + $notice_name = trim(sanitize_text_field(wp_unslash($_GET['notice_name']))); | |
| 270 | + if (!$this->dismiss_notice($notice_name)) { | |
| 271 | + wp_send_json_error(__('Notice is already dismissed.', 'wp-reset')); | |
| 272 | + } else { | |
| 273 | + wp_send_json_success(); | |
| 274 | + } | |
| 275 | + } // ajax_dismiss_notice | |
| 268 | 276 | |
| 269 | 277 | |
| 270 | - /** | |
| 271 | - * Returns all WP pointers | |
| 272 | - * | |
| 273 | - * @return array | |
| 274 | - */ | |
| 275 | - function get_pointers() | |
| 276 | - { | |
| 277 | - $pointers = array(); | |
| 278 | + /** | |
| 279 | + * Dismiss notice via admin action | |
| 280 | + * | |
| 281 | + * @return null | |
| 282 | + */ | |
| 283 | + function action_dismiss_notice() | |
| 284 | + { | |
| 285 | + if (!isset($_GET['notice']) || !isset($_GET['_wpnonce']) || false == wp_verify_nonce(sanitize_text_field(wp_unslash($_GET['_wpnonce'])), 'wpr_dismiss_notice')) { | |
| 286 | + wp_die('Please reload the page and try again.'); | |
| 287 | + } | |
| 278 | 288 | |
| 279 | - $pointers['welcome'] = array('target' => '#menu-tools', 'edge' => 'left', 'align' => 'right', 'content' => 'Thank you for installing the <b style="font-weight: 800;">WP Reset</b> plugin!<br>Open <a href="' . admin_url('tools.php?page=wp-reset') . '">Tools - WP Reset</a> to access resetting tools and start developing & debugging faster.'); | |
| 289 | + if (empty($_GET['notice'])) { | |
| 290 | + wp_safe_redirect(admin_url()); | |
| 291 | + exit; | |
| 292 | + } | |
| 280 | 293 | |
| 281 | - return $pointers; | |
| 282 | - } // get_pointers | |
| 294 | + $notice_name = trim(sanitize_text_field(wp_unslash($_GET['notice']))); | |
| 295 | + $this->dismiss_notice($notice_name); | |
| 283 | 296 | |
| 297 | + if (!empty($_GET['redirect'])) { | |
| 298 | + wp_safe_redirect(sanitize_url(wp_unslash($_GET['redirect']))); | |
| 299 | + } else { | |
| 300 | + wp_safe_redirect(admin_url()); | |
| 301 | + } | |
| 284 | 302 | |
| 285 | - /** | |
| 286 | - * Enqueue CSS and JS files | |
| 287 | - * | |
| 288 | - * @return null | |
| 289 | - */ | |
| 290 | - function admin_enqueue_scripts($hook) | |
| 291 | - { | |
| 292 | - // welcome pointer is shown on all pages except WPR to admins, until dismissed | |
| 293 | - $pointers = $this->get_pointers(); | |
| 294 | - $dismissed_notices = $this->get_dismissed_notices(); | |
| 295 | - $meta = $this->get_meta(); | |
| 303 | + exit; | |
| 304 | + } // action_dismiss_notice | |
| 296 | 305 | |
| 297 | - foreach ($dismissed_notices as $notice_name => $tmp) { | |
| 298 | - if ($tmp) { | |
| 299 | - unset($pointers[$notice_name]); | |
| 300 | - } | |
| 301 | - } // foreach | |
| 302 | 306 | |
| 303 | - if (!empty($pointers) && !$this->is_plugin_page() && current_user_can('administrator')) { | |
| 304 | - $pointers['_nonce_dismiss_pointer'] = wp_create_nonce('wp-reset_dismiss_notice'); | |
| 307 | + /** | |
| 308 | + * Dismiss notice by adding it to dismissed_notices options array | |
| 309 | + * | |
| 310 | + * @param string $notice_name Notice to dismiss. | |
| 311 | + * | |
| 312 | + * @return bool | |
| 313 | + */ | |
| 314 | + function dismiss_notice($notice_name) | |
| 315 | + { | |
| 316 | + if ($this->get_dismissed_notices($notice_name)) { | |
| 317 | + return false; | |
| 318 | + } else { | |
| 319 | + $notices = $this->get_dismissed_notices(); | |
| 320 | + $notices[$notice_name] = true; | |
| 321 | + $this->update_options('dismissed_notices', $notices); | |
| 322 | + return true; | |
| 323 | + } | |
| 324 | + } // dismiss_notice | |
| 305 | 325 | |
| 306 | - wp_enqueue_style('wp-pointer'); | |
| 307 | 326 | |
| 308 | - wp_enqueue_script('wp-reset-pointers', $this->plugin_url . 'js/wp-reset-pointers.js', array('jquery'), $this->version, true); | |
| 309 | - wp_enqueue_script('wp-pointer'); | |
| 310 | - wp_localize_script('wp-pointer', 'wp_reset_pointers', $pointers); | |
| 311 | - } | |
| 327 | + /** | |
| 328 | + * Returns all WP pointers | |
| 329 | + * | |
| 330 | + * @return array | |
| 331 | + */ | |
| 332 | + function get_pointers() | |
| 333 | + { | |
| 334 | + $pointers = array(); | |
| 312 | 335 | |
| 313 | - // exit early if not on WP Reset page | |
| 314 | - if (!$this->is_plugin_page()) { | |
| 315 | - return; | |
| 316 | - } | |
| 336 | + $pointers['welcome'] = array('target' => '#menu-tools', 'edge' => 'left', 'align' => 'right', 'content' => 'Thank you for installing the <b style="font-weight: 800;">WP Reset</b> plugin!<br>Open <a href="' . esc_url(admin_url('tools.php?page=wp-reset')) . '">Tools - WP Reset</a> to access resetting tools and start developing & debugging faster.'); | |
| 317 | 337 | |
| 318 | - // features survey is shown 5min after install or after first reset | |
| 319 | - $survey = false; | |
| 320 | - if ($this->is_survey_active('features')) { | |
| 321 | - $survey = true; | |
| 322 | - } | |
| 338 | + return $pointers; | |
| 339 | + } // get_pointers | |
| 323 | 340 | |
| 324 | - $js_localize = array( | |
| 325 | - 'undocumented_error' => __('An undocumented error has occurred. Please refresh the page and try again.', 'wp-reset'), | |
| 326 | - 'documented_error' => __('An error has occurred.', 'wp-reset'), | |
| 327 | - 'plugin_name' => __('WP Reset', 'wp-reset'), | |
| 328 | - 'settings_url' => admin_url('tools.php?page=wp-reset'), | |
| 329 | - 'icon_url' => $this->plugin_url . 'img/wp-reset-icon.png', | |
| 330 | - 'invalid_confirmation' => __('Please type "reset" in the confirmation field.', 'wp-reset'), | |
| 331 | - 'invalid_confirmation_title' => __('Invalid confirmation', 'wp-reset'), | |
| 332 | - 'cancel_button' => __('Cancel', 'wp-reset'), | |
| 333 | - 'open_survey' => $survey, | |
| 334 | - 'ok_button' => __('OK', 'wp-reset'), | |
| 335 | - 'confirm_button' => __('Reset WordPress', 'wp-reset'), | |
| 336 | - 'confirm_title' => __('Are you sure you want to proceed?', 'wp-reset'), | |
| 337 | - 'confirm_title_reset' => __('Are you sure you want to reset the site?', 'wp-reset'), | |
| 338 | - 'confirm1' => __('Clicking "Reset WordPress" will reset your site to default values. All content will be lost. Always <a href="#" class="create-new-snapshot" data-description="Before resetting the site">create a snapshot</a> if you want to be able to undo.</b>', 'wp-reset'), | |
| 339 | - 'confirm2' => __('Click "Cancel" to abort.', 'wp-reset'), | |
| 340 | - 'doing_reset' => __('Resetting in progress. Please wait.', 'wp-reset'), | |
| 341 | - 'nonce_dismiss_notice' => wp_create_nonce('wp-reset_dismiss_notice'), | |
| 342 | - 'nonce_run_tool' => wp_create_nonce('wp-reset_run_tool'), | |
| 343 | - 'nonce_do_reset' => wp_create_nonce('wp-reset_do_reset'), | |
| 344 | - ); | |
| 345 | 341 | |
| 346 | - if ($survey) { | |
| 347 | - $js_localize['nonce_submit_survey'] = wp_create_nonce('wp-reset_submit_survey'); | |
| 348 | - } | |
| 349 | - if (!$this->is_webhooks_active()) { | |
| 350 | - $js_localize['webhooks_install_url'] = add_query_arg(array('action' => 'install_webhooks'), admin_url('admin.php')); | |
| 351 | - } | |
| 342 | + /** | |
| 343 | + * Enqueue CSS and JS files | |
| 344 | + * | |
| 345 | + * @return null | |
| 346 | + */ | |
| 347 | + function admin_enqueue_scripts($hook) | |
| 348 | + { | |
| 349 | + // welcome pointer is shown on all pages except WPR to admins, until dismissed | |
| 350 | + $pointers = $this->get_pointers(); | |
| 351 | + $dismissed_notices = $this->get_dismissed_notices(); | |
| 352 | 352 | |
| 353 | - wp_enqueue_style('plugin-install'); | |
| 354 | - wp_enqueue_style('wp-jquery-ui-dialog'); | |
| 355 | - wp_enqueue_style('wp-reset', $this->plugin_url . 'css/wp-reset.css', array(), $this->version); | |
| 356 | - wp_enqueue_style('wp-reset-sweetalert2', $this->plugin_url . 'css/sweetalert2.min.css', array(), $this->version); | |
| 353 | + foreach ($dismissed_notices as $notice_name => $tmp) { | |
| 354 | + if ($tmp) { | |
| 355 | + unset($pointers[$notice_name]); | |
| 356 | + } | |
| 357 | + } // foreach | |
| 357 | 358 | |
| 358 | - wp_enqueue_script('plugin-install'); | |
| 359 | - wp_enqueue_script('jquery-ui-dialog'); | |
| 360 | - wp_enqueue_script('jquery-ui-tabs'); | |
| 361 | - wp_enqueue_script('wp-reset-sweetalert2', $this->plugin_url . 'js/wp-reset-libs.min.js', array('jquery'), $this->version, true); | |
| 362 | - wp_enqueue_script('wp-reset', $this->plugin_url . 'js/wp-reset.js', array('jquery'), $this->version, true); | |
| 363 | - wp_localize_script('wp-reset', 'wp_reset', $js_localize); | |
| 359 | + if (!empty($pointers) && !$this->is_plugin_page() && current_user_can('manage_options')) { | |
| 360 | + $pointers['_nonce_dismiss_pointer'] = wp_create_nonce('wp-reset_dismiss_notice'); | |
| 364 | 361 | |
| 365 | - add_thickbox(); | |
| 362 | + wp_enqueue_style('wp-pointer'); | |
| 366 | 363 | |
| 367 | - // fix for aggressive plugins that include their CSS on all pages | |
| 368 | - wp_dequeue_style('uiStyleSheet'); | |
| 369 | - wp_dequeue_style('wpcufpnAdmin'); | |
| 370 | - wp_dequeue_style('unifStyleSheet'); | |
| 371 | - wp_dequeue_style('wpcufpn_codemirror'); | |
| 372 | - wp_dequeue_style('wpcufpn_codemirrorTheme'); | |
| 373 | - wp_dequeue_style('collapse-admin-css'); | |
| 374 | - wp_dequeue_style('jquery-ui-css'); | |
| 375 | - wp_dequeue_style('tribe-common-admin'); | |
| 376 | - wp_dequeue_style('file-manager__jquery-ui-css'); | |
| 377 | - wp_dequeue_style('file-manager__jquery-ui-css-theme'); | |
| 378 | - wp_dequeue_style('wpmegmaps-jqueryui'); | |
| 379 | - wp_dequeue_style('wp-botwatch-css'); | |
| 380 | - } // admin_enqueue_scripts | |
| 364 | + wp_enqueue_script('wp-reset-pointers', $this->plugin_url . 'js/wp-reset-pointers.js', array('jquery'), $this->version, true); | |
| 365 | + wp_enqueue_script('wp-pointer'); | |
| 366 | + wp_localize_script('wp-pointer', 'wp_reset_pointers', $pointers); | |
| 367 | + } | |
| 381 | 368 | |
| 369 | + // exit early if not on WP Reset page | |
| 370 | + if (!$this->is_plugin_page()) { | |
| 371 | + return; | |
| 372 | + } | |
| 382 | 373 | |
| 383 | - /** | |
| 384 | - * Remove all WP notices on WPR page | |
| 385 | - * | |
| 386 | - * @return null | |
| 387 | - */ | |
| 388 | - function remove_admin_notices() | |
| 389 | - { | |
| 390 | - if (!$this->is_plugin_page()) { | |
| 391 | - return false; | |
| 392 | - } | |
| 374 | + $js_localize = array( | |
| 375 | + 'undocumented_error' => __('An undocumented error has occurred. Please refresh the page and try again.', 'wp-reset'), | |
| 376 | + 'documented_error' => __('An error has occurred.', 'wp-reset'), | |
| 377 | + 'plugin_name' => __('WP Reset', 'wp-reset'), | |
| 378 | + 'settings_url' => admin_url('tools.php?page=wp-reset'), | |
| 379 | + 'wpfssl_install_url' => add_query_arg(array('action' => 'wpr_install_wpfssl', '_wpnonce' => wp_create_nonce('install_wpfssl'), 'rnd' => wp_rand()), admin_url('admin.php')), | |
| 380 | + 'icon_url' => $this->plugin_url . 'img/wp-reset-icon.png', | |
| 381 | + 'invalid_confirmation' => __('Please type "reset" in the confirmation field.', 'wp-reset'), | |
| 382 | + 'invalid_confirmation_title' => __('Invalid confirmation', 'wp-reset'), | |
| 383 | + 'cancel_button' => __('Cancel', 'wp-reset'), | |
| 384 | + 'ok_button' => __('OK', 'wp-reset'), | |
| 385 | + 'confirm_button' => __('Reset WordPress', 'wp-reset'), | |
| 386 | + 'confirm_title' => __('Are you sure you want to proceed?', 'wp-reset'), | |
| 387 | + 'confirm_title_reset' => __('Are you sure you want to reset the site?', 'wp-reset'), | |
| 388 | + 'confirm1' => __('Clicking "Reset WordPress" will reset your site to default values. All content will be lost. Always <a href="#" class="create-new-snapshot" data-description="Before resetting the site">create a snapshot</a> if you want to be able to undo.</b>', 'wp-reset'), | |
| 389 | + 'confirm2' => __('Click "Cancel" to abort.', 'wp-reset'), | |
| 390 | + 'doing_reset' => __('Resetting in progress. Please wait.', 'wp-reset'), | |
| 391 | + 'snapshot_success' => __('Snapshot created', 'wp-reset'), | |
| 392 | + 'snapshot_wait' => __('Creating snapshot. Please wait.', 'wp-reset'), | |
| 393 | + 'snapshot_confirm' => __('Create snapshot', 'wp-reset'), | |
| 394 | + 'snapshot_placeholder' => __('Snapshot name or brief description, ie: before plugin install', 'wp-reset'), | |
| 395 | + 'snapshot_text' => __('Enter snapshot name or brief description', 'wp-reset'), | |
| 396 | + 'snapshot_title' => __('Create a new snapshot', 'wp-reset'), | |
| 397 | + 'nonce_dismiss_notice' => wp_create_nonce('wp-reset_dismiss_notice'), | |
| 398 | + 'activating' => __('Activating', 'wp-reset'), | |
| 399 | + 'deactivating' => __('Deactivating', 'wp-reset'), | |
| 400 | + 'deleting' => __('Deleting', 'wp-reset'), | |
| 401 | + 'installing' => __('Installing', 'wp-reset'), | |
| 402 | + 'activate_failed' => __('Could not activate', 'wp-reset'), | |
| 403 | + 'deactivate_failed' => __('Could not deactivate', 'wp-reset'), | |
| 404 | + 'delete_failed' => __('Could not delete', 'wp-reset'), | |
| 405 | + 'install_failed' => __('Could not install', 'wp-reset'), | |
| 406 | + 'install_failed_existing' => __('is already installed', 'wp-reset'), | |
| 407 | + 'nonce_run_tool' => wp_create_nonce('wp-reset_run_tool'), | |
| 408 | + 'nonce_do_reset' => wp_create_nonce('wp-reset_do_reset'), | |
| 409 | + ); | |
| 393 | 410 | |
| 394 | - global $wp_filter; | |
| 395 | - unset($wp_filter['user_admin_notices'], $wp_filter['admin_notices']); | |
| 396 | - } // remove_admin_notices | |
| 411 | + wp_enqueue_style('plugin-install'); | |
| 412 | + wp_enqueue_style('wp-jquery-ui-dialog'); | |
| 413 | + wp_enqueue_style('wp-reset', $this->plugin_url . 'css/wp-reset.css', array(), $this->version); | |
| 414 | + wp_enqueue_style('wp-reset-sweetalert2', $this->plugin_url . 'css/sweetalert2.min.css', array(), $this->version); | |
| 415 | + wp_enqueue_style('wp-reset-tooltipster', $this->plugin_url . 'css/tooltipster.bundle.min.css', array(), $this->version); | |
| 397 | 416 | |
| 417 | + wp_enqueue_script('plugin-install'); | |
| 418 | + wp_enqueue_script('jquery-ui-tabs'); | |
| 419 | + wp_enqueue_script('jquery-ui-dialog'); | |
| 420 | + wp_enqueue_script('wp-reset-sweetalert2', $this->plugin_url . 'js/wp-reset-libs.min.js', array('jquery'), $this->version, true); | |
| 421 | + wp_enqueue_script('wp-reset', $this->plugin_url . 'js/wp-reset.js', array('jquery'), $this->version, true); | |
| 422 | + wp_localize_script('wp-reset', 'wp_reset', $js_localize); | |
| 398 | 423 | |
| 399 | - /** | |
| 400 | - * Submit user selected survey answers to WPR servers | |
| 401 | - * | |
| 402 | - * @return null | |
| 403 | - */ | |
| 404 | - function ajax_submit_survey() | |
| 405 | - { | |
| 406 | - check_ajax_referer('wp-reset_submit_survey'); | |
| 424 | + add_thickbox(); | |
| 407 | 425 | |
| 408 | - $meta = $this->get_meta(); | |
| 426 | + // fix for aggressive plugins that include their CSS on all pages | |
| 427 | + wp_dequeue_style('uiStyleSheet'); | |
| 428 | + wp_dequeue_style('wpcufpnAdmin'); | |
| 429 | + wp_dequeue_style('unifStyleSheet'); | |
| 430 | + wp_dequeue_style('wpcufpn_codemirror'); | |
| 431 | + wp_dequeue_style('wpcufpn_codemirrorTheme'); | |
| 432 | + wp_dequeue_style('collapse-admin-css'); | |
| 433 | + wp_dequeue_style('jquery-ui-css'); | |
| 434 | + wp_dequeue_style('tribe-common-admin'); | |
| 435 | + wp_dequeue_style('file-manager__jquery-ui-css'); | |
| 436 | + wp_dequeue_style('file-manager__jquery-ui-css-theme'); | |
| 437 | + wp_dequeue_style('wpmegmaps-jqueryui'); | |
| 438 | + wp_dequeue_style('wp-botwatch-css'); | |
| 439 | + wp_dequeue_style('uap_main_admin_style'); | |
| 440 | + wp_dequeue_style('uap_font_awesome'); | |
| 441 | + wp_dequeue_style('uap_jquery-ui.min.css'); | |
| 442 | + } // admin_enqueue_scripts | |
| 409 | 443 | |
| 410 | - $vars = wp_parse_args($_POST, array('survey' => '', 'answers' => '', 'custom_answer' => '', 'emailme' => '')); | |
| 411 | - $vars['answers'] = trim($vars['answers'], ','); | |
| 412 | - $vars['custom_answer'] = substr(trim(strip_tags($vars['custom_answer'])), 0, 256); | |
| 413 | 444 | |
| 414 | - if (empty($vars['survey']) || empty($vars['answers'])) { | |
| 415 | - wp_send_json_error(); | |
| 416 | - } | |
| 445 | + /** | |
| 446 | + * Remove all WP notices on WPR page | |
| 447 | + * | |
| 448 | + * @return null | |
| 449 | + */ | |
| 450 | + function remove_admin_notices() | |
| 451 | + { | |
| 452 | + if (!$this->is_plugin_page()) { | |
| 453 | + return false; | |
| 454 | + } | |
| 417 | 455 | |
| 418 | - $request_params = array('sslverify' => false, 'timeout' => 15, 'redirection' => 2); | |
| 419 | - $request_args = array( | |
| 420 | - 'action' => 'submit_survey', | |
| 421 | - 'survey' => $vars['survey'], | |
| 422 | - 'email' => $vars['emailme'], | |
| 423 | - 'answers' => $vars['answers'], | |
| 424 | - 'custom_answer' => $vars['custom_answer'], | |
| 425 | - 'first_version' => $meta['first_version'], | |
| 426 | - 'version' => $this->version, | |
| 427 | - 'codebase' => 'free', | |
| 428 | - 'site' => get_home_url() | |
| 429 | - ); | |
| 456 | + global $wp_filter; | |
| 457 | + unset($wp_filter['user_admin_notices'], $wp_filter['admin_notices']); | |
| 458 | + } // remove_admin_notices | |
| 430 | 459 | |
| 431 | - $url = add_query_arg($request_args, $this->licensing_servers[0]); | |
| 432 | - $response = wp_remote_get(esc_url_raw($url), $request_params); | |
| 433 | 460 | |
| 434 | - if (is_wp_error($response) || !wp_remote_retrieve_body($response)) { | |
| 435 | - $url = add_query_arg($request_args, $this->licensing_servers[1]); | |
| 436 | - $response = wp_remote_get(esc_url_raw($url), $request_params); | |
| 437 | - } | |
| 461 | + /** | |
| 462 | + * Check if WP-CLI is available and running | |
| 463 | + * | |
| 464 | + * @return bool | |
| 465 | + */ | |
| 466 | + static function is_cli_running() | |
| 467 | + { | |
| 468 | + if (!is_null($value = apply_filters('wp-reset-override-is-cli-running', null))) { | |
| 469 | + return (bool) $value; | |
| 470 | + } | |
| 438 | 471 | |
| 439 | - $this->dismiss_notice('survey-' . $vars['survey']); | |
| 472 | + if (defined('WP_CLI') && WP_CLI) { | |
| 473 | + return true; | |
| 474 | + } else { | |
| 475 | + return false; | |
| 476 | + } | |
| 477 | + } // is_cli_running | |
| 440 | 478 | |
| 441 | - wp_send_json_success(); | |
| 442 | - } // ajax_submit_survey | |
| 443 | 479 | |
| 480 | + /** | |
| 481 | + * Check if given plugin is installed | |
| 482 | + * | |
| 483 | + * @param [string] $slug Plugin slug | |
| 484 | + * @return boolean | |
| 485 | + */ | |
| 486 | + function is_plugin_installed($slug) | |
| 487 | + { | |
| 488 | + if (!function_exists('get_plugins')) { | |
| 489 | + require_once ABSPATH . 'wp-admin/includes/plugin.php'; | |
| 490 | + } | |
| 491 | + $all_plugins = get_plugins(); | |
| 444 | 492 | |
| 445 | - /** | |
| 446 | - * Check if named survey should be shown or not | |
| 447 | - * | |
| 448 | - * @param [string] $survey_name Name of the survey to check | |
| 449 | - * @return boolean | |
| 450 | - */ | |
| 451 | - function is_survey_active($survey_name) | |
| 452 | - { | |
| 453 | - if (empty($survey_name)) { | |
| 454 | - return false; | |
| 455 | - } | |
| 493 | + if (!empty($all_plugins[$slug])) { | |
| 494 | + return true; | |
| 495 | + } else { | |
| 496 | + return false; | |
| 497 | + } | |
| 498 | + } // is_plugin_installed | |
| 456 | 499 | |
| 457 | - // all surveys are curently disabled | |
| 458 | - return false; | |
| 459 | 500 | |
| 460 | - if ($this->get_dismissed_notices('survey-' . $survey_name)) { | |
| 461 | - return false; | |
| 462 | - } | |
| 501 | + /** | |
| 502 | + * Deletes all transients. | |
| 503 | + * | |
| 504 | + * @return int Number of deleted transient DB entries | |
| 505 | + */ | |
| 506 | + function do_delete_transients() | |
| 507 | + { | |
| 508 | + global $wpdb; | |
| 463 | 509 | |
| 464 | - $meta = $this->get_meta(); | |
| 465 | - if (current_time('timestamp', true) - $meta['first_install'] > 300 || $meta['reset_count'] > 0) { | |
| 466 | - return true; | |
| 467 | - } | |
| 510 | + // phpcs:ignore db call warning as we are using uncommon queries | |
| 511 | + $count = $wpdb->query("DELETE FROM $wpdb->options WHERE option_name LIKE '\_transient\_%' OR option_name LIKE '\_site\_transient\_%'"); // phpcs:ignore | |
| 468 | 512 | |
| 469 | - return false; | |
| 470 | - } // is_survey_active | |
| 513 | + wp_cache_flush(); | |
| 471 | 514 | |
| 472 | - /** | |
| 473 | - * Check if WP-CLI is available and running | |
| 474 | - * | |
| 475 | - * @return bool | |
| 476 | - */ | |
| 477 | - static function is_cli_running() | |
| 478 | - { | |
| 479 | - if (!is_null($value = apply_filters('wp-reset-override-is-cli-running', null))) { | |
| 480 | - return (bool) $value; | |
| 481 | - } | |
| 515 | + do_action('wp_reset_delete_transients', $count); | |
| 482 | 516 | |
| 483 | - if (defined('WP_CLI') && WP_CLI) { | |
| 484 | - return true; | |
| 485 | - } else { | |
| 486 | - return false; | |
| 487 | - } | |
| 488 | - } // is_cli_running | |
| 517 | + return $count; | |
| 518 | + } // do_delete_transients | |
| 489 | 519 | |
| 490 | 520 | |
| 491 | - /** | |
| 492 | - * Check if core WP Webhooks and WPR addon plugins are installed and activated | |
| 493 | - * | |
| 494 | - * @return bool | |
| 495 | - */ | |
| 496 | - function is_webhooks_active() | |
| 497 | - { | |
| 498 | - if (!function_exists('is_plugin_active') || !function_exists('get_plugin_data')) { | |
| 499 | - require_once ABSPATH . 'wp-admin/includes/plugin.php'; | |
| 500 | - } | |
| 521 | + /** | |
| 522 | + * Purge all cache for popular caching plugins | |
| 523 | + * | |
| 524 | + * @return bool true | |
| 525 | + */ | |
| 526 | + function do_purge_cache() | |
| 527 | + { | |
| 528 | + global $wp_reset; | |
| 501 | 529 | |
| 502 | - if (false == is_plugin_active('wp-webhooks/wp-webhooks.php')) { | |
| 503 | - return false; | |
| 504 | - } | |
| 530 | + wp_cache_flush(); | |
| 531 | + $wp_reset->do_delete_transients(); | |
| 505 | 532 | |
| 506 | - if (false == is_plugin_active('wpwh-wp-reset-webhook-integration/wpwhpro-wp-reset-webhook-integration.php')) { | |
| 507 | - return false; | |
| 508 | - } | |
| 533 | + if (function_exists('w3tc_flush_all')) { | |
| 534 | + w3tc_flush_all(); | |
| 535 | + } | |
| 536 | + if (function_exists('wp_cache_clear_cache')) { | |
| 537 | + wp_cache_clear_cache(); | |
| 538 | + } | |
| 539 | + if (method_exists('LiteSpeed_Cache_API', 'purge_all')) { | |
| 540 | + LiteSpeed_Cache_API::purge_all(); | |
| 541 | + } | |
| 542 | + if (class_exists('Endurance_Page_Cache')) { | |
| 543 | + $epc = new Endurance_Page_Cache; | |
| 544 | + $epc->purge_all(); | |
| 545 | + } | |
| 546 | + if (class_exists('SG_CachePress_Supercacher') && method_exists('SG_CachePress_Supercacher', 'purge_cache')) { | |
| 547 | + SG_CachePress_Supercacher::purge_cache(true); | |
| 548 | + } | |
| 549 | + if (class_exists('SiteGround_Optimizer\Supercacher\Supercacher')) { | |
| 550 | + SiteGround_Optimizer\Supercacher\Supercacher::purge_cache(); | |
| 551 | + } | |
| 552 | + if (isset($GLOBALS['wp_fastest_cache']) && method_exists($GLOBALS['wp_fastest_cache'], 'deleteCache')) { | |
| 553 | + $GLOBALS['wp_fastest_cache']->deleteCache(true); | |
| 554 | + } | |
| 555 | + if (is_callable(array('Swift_Performance_Cache', 'clear_all_cache'))) { | |
| 556 | + Swift_Performance_Cache::clear_all_cache(); | |
| 557 | + } | |
| 558 | + if (is_callable(array('Hummingbird\WP_Hummingbird', 'flush_cache'))) { | |
| 559 | + Hummingbird\WP_Hummingbird::flush_cache(true, false); | |
| 560 | + } | |
| 509 | 561 | |
| 510 | - return true; | |
| 511 | - } // is_webhooks_active | |
| 562 | + do_action('wp_reset_purge_cache'); | |
| 512 | 563 | |
| 564 | + return true; | |
| 565 | + } // do_purge_cache | |
| 513 | 566 | |
| 514 | - /** | |
| 515 | - * Check if given plugin is installed | |
| 516 | - * | |
| 517 | - * @param [string] $slug Plugin slug | |
| 518 | - * @return boolean | |
| 519 | - */ | |
| 520 | - function is_plugin_installed($slug) | |
| 521 | - { | |
| 522 | - if (!function_exists('get_plugins')) { | |
| 523 | - require_once ABSPATH . 'wp-admin/includes/plugin.php'; | |
| 524 | - } | |
| 525 | - $all_plugins = get_plugins(); | |
| 526 | 567 | |
| 527 | - if (!empty($all_plugins[$slug])) { | |
| 528 | - return true; | |
| 529 | - } else { | |
| 530 | - return false; | |
| 531 | - } | |
| 532 | - } // is_plugin_installed | |
| 568 | + /** | |
| 569 | + * Resets all theme options (mods). | |
| 570 | + * | |
| 571 | + * @param bool $all_themes Delete mods for all themes or just the current one | |
| 572 | + * | |
| 573 | + * @return int Number of deleted mod DB entries | |
| 574 | + */ | |
| 575 | + function do_reset_theme_options($all_themes = true) | |
| 576 | + { | |
| 577 | + global $wpdb; | |
| 533 | 578 | |
| 579 | + // phpcs:ignore db call warning as we are using uncommon queries | |
| 580 | + $count = $wpdb->query($wpdb->prepare("DELETE FROM $wpdb->options WHERE option_name LIKE %s OR option_name LIKE %s", array('mods\_%', 'theme_mods\_%'))); // phpcs:ignore | |
| 534 | 581 | |
| 535 | - /** | |
| 536 | - * Auto download/install/upgrade/activate WP Webhooks plugin | |
| 537 | - * | |
| 538 | - * @return null | |
| 539 | - */ | |
| 540 | - static function install_webhooks() | |
| 541 | - { | |
| 542 | - $plugin_slug = 'wp-webhooks/wp-webhooks.php'; | |
| 543 | - $plugin_zip = 'https://downloads.wordpress.org/plugin/wp-webhooks.latest-stable.zip'; | |
| 582 | + do_action('wp_reset_reset_theme_options', $count); | |
| 544 | 583 | |
| 545 | - @include_once ABSPATH . 'wp-admin/includes/plugin.php'; | |
| 546 | - @include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; | |
| 547 | - @include_once ABSPATH . 'wp-admin/includes/plugin-install.php'; | |
| 548 | - @include_once ABSPATH . 'wp-admin/includes/file.php'; | |
| 549 | - @include_once ABSPATH . 'wp-admin/includes/misc.php'; | |
| 550 | - echo '<style> | |
| 551 | - body{ | |
| 552 | - font-family: sans-serif; | |
| 553 | - font-size: 14px; | |
| 554 | - line-height: 1.5; | |
| 555 | - color: #444; | |
| 556 | - } | |
| 557 | - </style>'; | |
| 584 | + return $count; | |
| 585 | + } // do_reset_theme_options | |
| 558 | 586 | |
| 559 | - echo '<div style="margin: 20px; color:#444;">'; | |
| 560 | - echo 'If things are not done in a minute <a target="_parent" href="' . admin_url('plugin-install.php?s=ironikus&tab=search&type=term') . '">install the plugin manually via Plugins page</a><br><br>'; | |
| 561 | 587 | |
| 562 | - wp_cache_flush(); | |
| 563 | - $upgrader = new Plugin_Upgrader(); | |
| 564 | - echo 'Check if WP Webhooks plugin is already installed ... <br />'; | |
| 565 | - if (self::is_plugin_installed($plugin_slug)) { | |
| 566 | - echo 'WP Webhooks is already installed!<br />Making sure it\'s the latest version.<br />'; | |
| 567 | - $upgrader->upgrade($plugin_slug); | |
| 568 | - $installed = true; | |
| 569 | - } else { | |
| 570 | - echo 'Installing WP Webhooks.<br />'; | |
| 571 | - $installed = $upgrader->install($plugin_zip); | |
| 572 | - } | |
| 573 | - wp_cache_flush(); | |
| 588 | + /** | |
| 589 | + * Deletes all files in uploads folder. | |
| 590 | + * | |
| 591 | + * @return int Number of deleted files and folders. | |
| 592 | + */ | |
| 593 | + function do_delete_uploads() | |
| 594 | + { | |
| 595 | + global $wp_filesystem; | |
| 596 | + $this->wp_init_filesystem(); | |
| 597 | + | |
| 598 | + $upload_dir = wp_get_upload_dir(); | |
| 599 | + $this->delete_count = 0; | |
| 574 | 600 | |
| 575 | - if (!is_wp_error($installed) && $installed) { | |
| 576 | - echo 'Activating WP Webhooks.<br />'; | |
| 577 | - $activate = activate_plugin($plugin_slug); | |
| 601 | + if ( $wp_filesystem->is_dir( $upload_dir['basedir'] ) ) { | |
| 578 | 602 | |
| 579 | - if (is_null($activate)) { | |
| 580 | - echo 'WP Webhooks activated.<br />'; | |
| 581 | - } | |
| 582 | - } else { | |
| 583 | - echo 'Could not install WP Webhooks. You\'ll have to <a target="_parent" href="' . admin_url('plugin-install.php?s=ironikus&tab=search&type=term') . '">download and install manually</a>.'; | |
| 584 | - } | |
| 603 | + // Get all files and directories in the folder. | |
| 604 | + $files = $wp_filesystem->dirlist( $upload_dir['basedir'] ); | |
| 605 | + | |
| 606 | + // Loop through the files and delete them. | |
| 607 | + foreach ( $files as $file => $details ) { | |
| 608 | + $file_path = trailingslashit( $upload_dir['basedir'] ) . $file; | |
| 609 | + $wp_filesystem->delete( $file_path, true ); | |
| 610 | + $this->delete_count++; | |
| 611 | + } | |
| 612 | + } | |
| 585 | 613 | |
| 586 | - $plugin_slug = 'wpwh-wp-reset-webhook-integration/wpwhpro-wp-reset-webhook-integration.php'; | |
| 587 | - $plugin_zip = 'https://downloads.wordpress.org/plugin/wpwh-wp-reset-webhook-integration.latest-stable.zip'; | |
| 614 | + do_action('wp_reset_delete_uploads', $this->delete_count); | |
| 588 | 615 | |
| 589 | - wp_cache_flush(); | |
| 590 | - $upgrader = new Plugin_Upgrader(); | |
| 591 | - echo '<br>Check if WP Webhooks WPR addon plugin is already installed ... <br />'; | |
| 592 | - if (self::is_plugin_installed($plugin_slug)) { | |
| 593 | - echo 'WP Webhooks WPR addon is already installed!<br />Making sure it\'s the latest version.<br />'; | |
| 594 | - $upgrader->upgrade($plugin_slug); | |
| 595 | - $installed = true; | |
| 596 | - } else { | |
| 597 | - echo 'Installing WP Webhooks WPR addon.<br />'; | |
| 598 | - $installed = $upgrader->install($plugin_zip); | |
| 599 | - } | |
| 600 | - wp_cache_flush(); | |
| 616 | + return $this->delete_count; | |
| 617 | + } // do_delete_uploads | |
| 601 | 618 | |
| 602 | - if (!is_wp_error($installed) && $installed) { | |
| 603 | - echo 'Activating WP Webhooks WPR addon.<br />'; | |
| 604 | - $activate = activate_plugin($plugin_slug); | |
| 619 | + /** | |
| 620 | + * Deactivate all plugins | |
| 621 | + * | |
| 622 | + * @param array keep_wp_reset - Keep WP Reset active and installed, silent_deactivate - Skip individual plugin deactivation functions when deactivating | |
| 623 | + * | |
| 624 | + * @return int Number of deactivated plugins. | |
| 625 | + */ | |
| 626 | + function do_deactivate_plugins($params = array()) | |
| 627 | + { | |
| 628 | + if (!function_exists('get_plugins')) { | |
| 629 | + require_once ABSPATH . 'wp-admin/includes/plugin.php'; | |
| 630 | + } | |
| 631 | + if (!function_exists('request_filesystem_credentials')) { | |
| 632 | + require_once ABSPATH . 'wp-admin/includes/file.php'; | |
| 633 | + } | |
| 605 | 634 | |
| 606 | - if (is_null($activate)) { | |
| 607 | - echo 'WP Webhooks WPR addon activated.<br />'; | |
| 635 | + $wp_reset_basename = plugin_basename(WP_RESET_FILE); | |
| 636 | + $params = shortcode_atts(array('keep_wp_reset' => true, 'silent_deactivate' => false), (array) $params); | |
| 608 | 637 | |
| 609 | - echo '<script>setTimeout(function() { top.location = "tools.php?page=wp-reset"; }, 1000);</script>'; | |
| 610 | - echo '<br>If you are not redirected in a few seconds - <a href="tools.php?page=wp-reset" target="_parent">click here</a>.'; | |
| 611 | - } | |
| 612 | - } else { | |
| 613 | - echo 'Could not install WP Webhooks WPR addon. You\'ll have to <a target="_parent" href="' . admin_url('plugin-install.php?s=ironikus&tab=search&type=term') . '">download and install manually</a>.'; | |
| 614 | - } | |
| 638 | + $active_plugins = (array) get_option('active_plugins', array()); | |
| 639 | + if ($params['keep_wp_reset']) { | |
| 640 | + if (($key = array_search($wp_reset_basename, $active_plugins)) !== false) { | |
| 641 | + unset($active_plugins[$key]); | |
| 642 | + } | |
| 643 | + } | |
| 615 | 644 | |
| 616 | - echo '</div>'; | |
| 617 | - } // install_webhooks | |
| 645 | + if (!empty($active_plugins)) { | |
| 646 | + deactivate_plugins($active_plugins, $params['silent_deactivate'], false); | |
| 647 | + } | |
| 618 | 648 | |
| 649 | + do_action('wp_reset_deactivate_plugins', $active_plugins, $params); | |
| 619 | 650 | |
| 620 | - /** | |
| 621 | - * Deletes all transients. | |
| 622 | - * | |
| 623 | - * @return int Number of deleted transient DB entries | |
| 624 | - */ | |
| 625 | - function do_delete_transients() | |
| 626 | - { | |
| 627 | - global $wpdb; | |
| 651 | + return sizeof($active_plugins); | |
| 652 | + } // do_deactivate_plugins | |
| 628 | 653 | |
| 629 | - $count = $wpdb->query("DELETE FROM $wpdb->options WHERE option_name LIKE '\_transient\_%' OR option_name LIKE '\_site\_transient\_%'"); | |
| 630 | 654 | |
| 631 | - wp_cache_flush(); | |
| 655 | + /** | |
| 656 | + * Delete all plugins | |
| 657 | + * | |
| 658 | + * @param array keep_wp_reset - Keep WP Reset active and installed | |
| 659 | + * | |
| 660 | + * @return int Number of deleted plugins. | |
| 661 | + */ | |
| 662 | + function do_delete_plugins($params = array()) | |
| 663 | + { | |
| 664 | + if (!function_exists('get_plugins')) { | |
| 665 | + require_once ABSPATH . 'wp-admin/includes/plugin.php'; | |
| 666 | + } | |
| 667 | + if (!function_exists('request_filesystem_credentials')) { | |
| 668 | + require_once ABSPATH . 'wp-admin/includes/file.php'; | |
| 669 | + } | |
| 632 | 670 | |
| 633 | - do_action('wp_reset_delete_transients', $count); | |
| 671 | + $wp_reset_basename = plugin_basename(WP_RESET_FILE); | |
| 672 | + $params = shortcode_atts(array('keep_wp_reset' => true), (array) $params); | |
| 634 | 673 | |
| 635 | - return $count; | |
| 636 | - } // do_delete_transients | |
| 674 | + $all_plugins = get_plugins(); | |
| 675 | + if ($params['keep_wp_reset']) { | |
| 676 | + unset($all_plugins[$wp_reset_basename]); | |
| 677 | + } | |
| 637 | 678 | |
| 679 | + if (!empty($all_plugins)) { | |
| 680 | + delete_plugins(array_keys($all_plugins)); | |
| 681 | + } | |
| 638 | 682 | |
| 639 | - /** | |
| 640 | - * Resets all theme options (mods). | |
| 641 | - * | |
| 642 | - * @param bool $all_themes Delete mods for all themes or just the current one | |
| 643 | - * | |
| 644 | - * @return int Number of deleted mod DB entries | |
| 645 | - */ | |
| 646 | - function do_reset_theme_options($all_themes = true) | |
| 647 | - { | |
| 648 | - global $wpdb; | |
| 683 | + do_action('wp_reset_delete_plugins', $all_plugins, $params); | |
| 649 | 684 | |
| 650 | - $count = $wpdb->query("DELETE FROM $wpdb->options WHERE option_name LIKE 'theme_mods\_%' OR option_name LIKE 'mods\_%'"); | |
| 685 | + return sizeof($all_plugins); | |
| 686 | + } // do_delete_plugins | |
| 651 | 687 | |
| 652 | - do_action('wp_reset_reset_theme_options', $count); | |
| 653 | 688 | |
| 654 | - return $count; | |
| 655 | - } // do_reset_theme_options | |
| 689 | + /** | |
| 690 | + * Delete all themes | |
| 691 | + * | |
| 692 | + * @param bool $keep_default_theme Keep default theme | |
| 693 | + * | |
| 694 | + * @return int Number of deleted themes. | |
| 695 | + */ | |
| 696 | + function do_delete_themes($keep_default_theme = true) | |
| 697 | + { | |
| 698 | + global $wp_version; | |
| 656 | 699 | |
| 700 | + if (!function_exists('delete_theme')) { | |
| 701 | + require_once ABSPATH . 'wp-admin/includes/theme.php'; | |
| 702 | + } | |
| 657 | 703 | |
| 658 | - /** | |
| 659 | - * Deletes all files in uploads folder. | |
| 660 | - * | |
| 661 | - * @return int Number of deleted files and folders. | |
| 662 | - */ | |
| 663 | - function do_delete_uploads() | |
| 664 | - { | |
| 665 | - $upload_dir = wp_get_upload_dir(); | |
| 666 | - $this->delete_count = 0; | |
| 704 | + if (!function_exists('request_filesystem_credentials')) { | |
| 705 | + require_once ABSPATH . 'wp-admin/includes/file.php'; | |
| 706 | + } | |
| 667 | 707 | |
| 668 | - $this->delete_folder($upload_dir['basedir'], $upload_dir['basedir']); | |
| 708 | + if (version_compare($wp_version, '5.0', '<') === true) { | |
| 709 | + $default_theme = 'twentyseventeen'; | |
| 710 | + } else { | |
| 711 | + $default_theme = 'twentytwentyone'; | |
| 712 | + } | |
| 669 | 713 | |
| 670 | - do_action('wp_reset_delete_uploads', $this->delete_count); | |
| 714 | + $all_themes = wp_get_themes(array('errors' => null)); | |
| 671 | 715 | |
| 672 | - return $this->delete_count; | |
| 673 | - } // do_delete_uploads | |
| 716 | + if (true == $keep_default_theme) { | |
| 717 | + unset($all_themes[$default_theme]); | |
| 718 | + } | |
| 674 | 719 | |
| 720 | + foreach ($all_themes as $theme_slug => $theme_details) { | |
| 721 | + $res = delete_theme($theme_slug); | |
| 722 | + } | |
| 675 | 723 | |
| 676 | - /** | |
| 677 | - * Recursively deletes a folder | |
| 678 | - * | |
| 679 | - * @param string $folder Recursive param. | |
| 680 | - * @param string $base_folder Base folder. | |
| 681 | - * | |
| 682 | - * @return bool | |
| 683 | - */ | |
| 684 | - private function delete_folder($folder, $base_folder) | |
| 685 | - { | |
| 686 | - $files = array_diff(scandir($folder), array('.', '..')); | |
| 724 | + if (false == $keep_default_theme) { | |
| 725 | + update_option('template', ''); | |
| 726 | + update_option('stylesheet', ''); | |
| 727 | + update_option('current_theme', ''); | |
| 728 | + } | |
| 687 | 729 | |
| 688 | - foreach ($files as $file) { | |
| 689 | - if (is_dir($folder . DIRECTORY_SEPARATOR . $file)) { | |
| 690 | - $this->delete_folder($folder . DIRECTORY_SEPARATOR . $file, $base_folder); | |
| 691 | - } else { | |
| 692 | - $tmp = @unlink($folder . DIRECTORY_SEPARATOR . $file); | |
| 693 | - $this->delete_count = $this->delete_count + (int) $tmp; | |
| 694 | - } | |
| 695 | - } // foreach | |
| 730 | + do_action('wp_reset_delete_themes', $all_themes); | |
| 696 | 731 | |
| 697 | - if ($folder != $base_folder) { | |
| 698 | - $tmp = @rmdir($folder); | |
| 699 | - $this->delete_count = $this->delete_count + (int) $tmp; | |
| 700 | - return $tmp; | |
| 701 | - } else { | |
| 702 | - return true; | |
| 703 | - } | |
| 704 | - } // delete_folder | |
| 732 | + return sizeof($all_themes); | |
| 733 | + } // do_delete_themes | |
| 705 | 734 | |
| 706 | 735 | |
| 707 | - /** | |
| 708 | - * Deactivate and delete all plugins | |
| 709 | - * | |
| 710 | - * @param bool $keep_wp_reset Keep WP Reset active and installed | |
| 711 | - * @param bool $silent_deactivate Skip individual plugin deactivation functions when deactivating | |
| 712 | - * | |
| 713 | - * @return int Number of deleted plugins. | |
| 714 | - */ | |
| 715 | - function do_delete_plugins($keep_wp_reset = true, $silent_deactivate = false) | |
| 716 | - { | |
| 717 | - if (!function_exists('get_plugins')) { | |
| 718 | - require_once ABSPATH . 'wp-admin/includes/plugin.php'; | |
| 719 | - } | |
| 720 | - if (!function_exists('request_filesystem_credentials')) { | |
| 721 | - require_once ABSPATH . 'wp-admin/includes/file.php'; | |
| 722 | - } | |
| 736 | + /** | |
| 737 | + * Truncate custom tables | |
| 738 | + * | |
| 739 | + * @return int Number of truncated tables. | |
| 740 | + */ | |
| 741 | + function do_truncate_custom_tables() | |
| 742 | + { | |
| 743 | + global $wpdb; | |
| 744 | + $custom_tables = $this->get_custom_tables(); | |
| 723 | 745 | |
| 724 | - $wp_reset_basename = plugin_basename(__FILE__); | |
| 746 | + foreach ($custom_tables as $tbl) { | |
| 747 | + $wpdb->wpreset_custom_table = $tbl['name']; | |
| 748 | + // phpcs:ignore db call warning as we are using uncommon queries | |
| 749 | + $wpdb->query('SET foreign_key_checks = 0'); // phpcs:ignore | |
| 750 | + $wpdb->query("TRUNCATE TABLE " . $wpdb->wpreset_custom_table); // phpcs:ignore | |
| 751 | + } // foreach | |
| 725 | 752 | |
| 726 | - $all_plugins = get_plugins(); | |
| 727 | - $active_plugins = (array) get_option('active_plugins', array()); | |
| 728 | - if (true == $keep_wp_reset) { | |
| 729 | - if (($key = array_search($wp_reset_basename, $active_plugins)) !== false) { | |
| 730 | - unset($active_plugins[$key]); | |
| 731 | - } | |
| 732 | - unset($all_plugins[$wp_reset_basename]); | |
| 733 | - } | |
| 753 | + do_action('wp_reset_truncate_custom_tables', $custom_tables); | |
| 734 | 754 | |
| 735 | - if (!empty($active_plugins)) { | |
| 736 | - deactivate_plugins($active_plugins, $silent_deactivate, false); | |
| 737 | - } | |
| 755 | + return sizeof($custom_tables); | |
| 756 | + } // do_truncate_custom_tables | |
| 738 | 757 | |
| 739 | - if (!empty($all_plugins)) { | |
| 740 | - delete_plugins(array_keys($all_plugins)); | |
| 741 | - } | |
| 742 | 758 | |
| 743 | - do_action('wp_reset_delete_plugins', $all_plugins, $all_plugins); | |
| 759 | + /** | |
| 760 | + * Drop custom tables | |
| 761 | + * | |
| 762 | + * @return int Number of dropped tables. | |
| 763 | + */ | |
| 764 | + function do_drop_custom_tables() | |
| 765 | + { | |
| 766 | + global $wpdb; | |
| 767 | + $custom_tables = $this->get_custom_tables(); | |
| 744 | 768 | |
| 745 | - return sizeof($all_plugins); | |
| 746 | - } // do_delete_plugins | |
| 769 | + foreach ($custom_tables as $tbl) { | |
| 770 | + $wpdb->wpreset_custom_table = $tbl['name']; | |
| 771 | + // phpcs:ignore db call warning as we are using uncommon queries | |
| 772 | + $wpdb->query('SET foreign_key_checks = 0'); // phpcs:ignore | |
| 773 | + $wpdb->query("DROP TABLE IF EXISTS " . $wpdb->wpreset_custom_table); // phpcs:ignore | |
| 774 | + } // foreach | |
| 747 | 775 | |
| 776 | + do_action('wp_reset_drop_custom_tables', $custom_tables); | |
| 748 | 777 | |
| 749 | - /** | |
| 750 | - * Delete all themes | |
| 751 | - * | |
| 752 | - * @param bool $keep_default_theme Keep default theme | |
| 753 | - * | |
| 754 | - * @return int Number of deleted themes. | |
| 755 | - */ | |
| 756 | - function do_delete_themes($keep_default_theme = true) | |
| 757 | - { | |
| 758 | - global $wp_version; | |
| 778 | + return sizeof($custom_tables); | |
| 779 | + } // do_drop_custom_tables | |
| 759 | 780 | |
| 760 | - if (!function_exists('delete_theme')) { | |
| 761 | - require_once ABSPATH . 'wp-admin/includes/theme.php'; | |
| 762 | - } | |
| 763 | 781 | |
| 764 | - if (!function_exists('request_filesystem_credentials')) { | |
| 765 | - require_once ABSPATH . 'wp-admin/includes/file.php'; | |
| 766 | - } | |
| 782 | + /** | |
| 783 | + * Delete .htaccess file | |
| 784 | + * | |
| 785 | + * @return bool|WP_Error Action status. | |
| 786 | + */ | |
| 787 | + function do_delete_htaccess() | |
| 788 | + { | |
| 789 | + global $wp_filesystem; | |
| 767 | 790 | |
| 768 | - if (version_compare($wp_version, '5.0', '<') === true) { | |
| 769 | - $default_theme = 'twentyseventeen'; | |
| 770 | - } else { | |
| 771 | - $default_theme = 'twentynineteen'; | |
| 772 | - } | |
| 791 | + if (empty($wp_filesystem)) { | |
| 792 | + require_once ABSPATH . '/wp-admin/includes/file.php'; | |
| 793 | + WP_Filesystem(); | |
| 794 | + } | |
| 773 | 795 | |
| 774 | - $all_themes = wp_get_themes(array('errors' => null)); | |
| 796 | + $htaccess_path = $this->get_htaccess_path(); | |
| 797 | + clearstatcache(); | |
| 775 | 798 | |
| 776 | - if (true == $keep_default_theme) { | |
| 777 | - unset($all_themes[$default_theme]); | |
| 778 | - } | |
| 799 | + do_action('wp_reset_delete_htaccess', $htaccess_path); | |
| 779 | 800 | |
| 780 | - foreach ($all_themes as $theme_slug => $theme_details) { | |
| 781 | - $res = delete_theme($theme_slug); | |
| 782 | - } | |
| 801 | + if (!$wp_filesystem->is_readable($htaccess_path)) { | |
| 802 | + return new WP_Error(1, 'Htaccess file does not exist; there\'s nothing to delete.'); | |
| 803 | + } | |
| 783 | 804 | |
| 784 | - if (false == $keep_default_theme) { | |
| 785 | - update_option('template', ''); | |
| 786 | - update_option('stylesheet', ''); | |
| 787 | - update_option('current_theme', ''); | |
| 788 | - } | |
| 805 | + if (!$wp_filesystem->is_writable($htaccess_path)) { | |
| 806 | + return new WP_Error(1, 'Htaccess file is not writable.'); | |
| 807 | + } | |
| 789 | 808 | |
| 790 | - do_action('wp_reset_delete_themes', $all_themes); | |
| 809 | + if ($wp_filesystem->delete($htaccess_path, false, 'f')) { | |
| 810 | + return true; | |
| 811 | + } else { | |
| 812 | + return new WP_Error(1, 'Unknown error. Unable to delete htaccess file.'); | |
| 813 | + } | |
| 814 | + } // do_delete_htaccess | |
| 791 | 815 | |
| 792 | - return sizeof($all_themes); | |
| 793 | - } // do_delete_themes | |
| 794 | 816 | |
| 817 | + /** | |
| 818 | + * Get .htaccess file path. | |
| 819 | + * | |
| 820 | + * @return string | |
| 821 | + */ | |
| 822 | + function get_htaccess_path() | |
| 823 | + { | |
| 824 | + if (!function_exists('get_home_path')) { | |
| 825 | + require_once ABSPATH . 'wp-admin/includes/file.php'; | |
| 826 | + } | |
| 795 | 827 | |
| 796 | - /** | |
| 797 | - * Truncate custom tables | |
| 798 | - * | |
| 799 | - * @return int Number of truncated tables. | |
| 800 | - */ | |
| 801 | - function do_truncate_custom_tables() | |
| 802 | - { | |
| 803 | - global $wpdb; | |
| 804 | - $custom_tables = $this->get_custom_tables(); | |
| 828 | + if ($this->is_cli_running()) { | |
| 829 | + $_SERVER['SCRIPT_FILENAME'] = ABSPATH; | |
| 830 | + } | |
| 805 | 831 | |
| 806 | - foreach ($custom_tables as $tbl) { | |
| 807 | - $wpdb->query('TRUNCATE TABLE ' . $tbl['name']); | |
| 808 | - } // foreach | |
| 832 | + $filepath = get_home_path() . '.htaccess'; | |
| 809 | 833 | |
| 810 | - do_action('wp_reset_truncate_custom_tables', $custom_tables); | |
| 834 | + return $filepath; | |
| 835 | + } // get_htaccess_path | |
| 811 | 836 | |
| 812 | - return sizeof($custom_tables); | |
| 813 | - } // do_truncate_custom_tables | |
| 814 | 837 | |
| 838 | + /** | |
| 839 | + * Run one tool via AJAX call | |
| 840 | + * | |
| 841 | + * @return null | |
| 842 | + */ | |
| 843 | + function ajax_run_tool() | |
| 844 | + { | |
| 845 | + check_ajax_referer('wp-reset_run_tool'); | |
| 815 | 846 | |
| 816 | - /** | |
| 817 | - * Drop custom tables | |
| 818 | - * | |
| 819 | - * @return int Number of dropped tables. | |
| 820 | - */ | |
| 821 | - function do_drop_custom_tables() | |
| 822 | - { | |
| 823 | - global $wpdb; | |
| 824 | - $custom_tables = $this->get_custom_tables(); | |
| 847 | + if (!current_user_can('manage_options')) { | |
| 848 | + wp_send_json_error(__('You are not allowed to run this action.', 'wp-reset')); | |
| 849 | + } | |
| 825 | 850 | |
| 826 | - foreach ($custom_tables as $tbl) { | |
| 827 | - $wpdb->query('DROP TABLE IF EXISTS ' . $tbl['name']); | |
| 828 | - } // foreach | |
| 851 | + if(!isset($_GET['tool'])){ | |
| 852 | + wp_send_json_error(__('Unknown tool.', 'wp-reset')); | |
| 853 | + } | |
| 829 | 854 | |
| 830 | - do_action('wp_reset_drop_custom_tables', $custom_tables); | |
| 855 | + $tool = trim(sanitize_text_field(wp_unslash($_GET['tool']))); | |
| 831 | 856 | |
| 832 | - return sizeof($custom_tables); | |
| 833 | - } // do_drop_custom_tables | |
| 857 | + if(isset($_GET['extra_data'])){ | |
| 858 | + $extra_data = trim(sanitize_text_field(wp_unslash($_GET['extra_data']))); | |
| 859 | + } else { | |
| 860 | + $extra_data = ''; | |
| 861 | + } | |
| 834 | 862 | |
| 863 | + if ($tool == 'delete_transients') { | |
| 864 | + $cnt = $this->do_delete_transients(); | |
| 865 | + wp_send_json_success($cnt); | |
| 866 | + } elseif ($tool == 'reset_theme_options') { | |
| 867 | + $cnt = $this->do_reset_theme_options(true); | |
| 868 | + wp_send_json_success($cnt); | |
| 869 | + } elseif ($tool == 'purge_cache') { | |
| 870 | + $this->do_purge_cache(); | |
| 871 | + wp_send_json_success(); | |
| 872 | + } elseif ($tool == 'delete_wp_cookies') { | |
| 873 | + wp_clear_auth_cookie(); | |
| 874 | + wp_send_json_success(); | |
| 875 | + } elseif ($tool == 'delete_themes') { | |
| 876 | + $cnt = $this->do_delete_themes(false); | |
| 877 | + wp_send_json_success($cnt); | |
| 878 | + } elseif ($tool == 'deactivate_plugins') { | |
| 879 | + $cnt = $this->do_deactivate_plugins($extra_data); | |
| 880 | + wp_send_json_success($cnt); | |
| 881 | + } elseif ($tool == 'delete_plugins') { | |
| 882 | + $cnt = $this->do_delete_plugins($extra_data); | |
| 883 | + wp_send_json_success($cnt); | |
| 884 | + } elseif ($tool == 'delete_uploads') { | |
| 885 | + $cnt = $this->do_delete_uploads(); | |
| 886 | + wp_send_json_success($cnt); | |
| 887 | + } elseif ($tool == 'delete_htaccess') { | |
| 888 | + $tmp = $this->do_delete_htaccess(); | |
| 889 | + if (is_wp_error($tmp)) { | |
| 890 | + wp_send_json_error($tmp->get_error_message()); | |
| 891 | + } else { | |
| 892 | + wp_send_json_success($tmp); | |
| 893 | + } | |
| 894 | + } elseif ($tool == 'drop_custom_tables') { | |
| 895 | + $cnt = $this->do_drop_custom_tables(); | |
| 896 | + wp_send_json_success($cnt); | |
| 897 | + } elseif ($tool == 'truncate_custom_tables') { | |
| 898 | + $cnt = $this->do_truncate_custom_tables(); | |
| 899 | + wp_send_json_success($cnt); | |
| 900 | + } elseif ($tool == 'delete_snapshot') { | |
| 901 | + $res = $this->do_delete_snapshot($extra_data); | |
| 902 | + if (is_wp_error($res)) { | |
| 903 | + wp_send_json_error($res->get_error_message()); | |
| 904 | + } else { | |
| 905 | + wp_send_json_success(); | |
| 906 | + } | |
| 907 | + } elseif ($tool == 'download_snapshot') { | |
| 908 | + $res = $this->do_export_snapshot($extra_data); | |
| 909 | + if (is_wp_error($res)) { | |
| 910 | + wp_send_json_error($res->get_error_message()); | |
| 911 | + } else { | |
| 912 | + $url = content_url() . '/' . $this->snapshots_folder . '/' . $res; | |
| 913 | + wp_send_json_success($url); | |
| 914 | + } | |
| 915 | + } elseif ($tool == 'restore_snapshot') { | |
| 916 | + $res = $this->do_restore_snapshot($extra_data); | |
| 917 | + if (is_wp_error($res)) { | |
| 918 | + wp_send_json_error($res->get_error_message()); | |
| 919 | + } else { | |
| 920 | + wp_send_json_success(); | |
| 921 | + } | |
| 922 | + } elseif ($tool == 'compare_snapshots') { | |
| 923 | + $res = $this->do_compare_snapshots($extra_data); | |
| 924 | + if (is_wp_error($res)) { | |
| 925 | + wp_send_json_error($res->get_error_message()); | |
| 926 | + } else { | |
| 927 | + wp_send_json_success($res); | |
| 928 | + } | |
| 929 | + } elseif ($tool == 'create_snapshot') { | |
| 930 | + $res = $this->do_create_snapshot($extra_data); | |
| 931 | + if (is_wp_error($res)) { | |
| 932 | + wp_send_json_error($res->get_error_message()); | |
| 933 | + } else { | |
| 934 | + wp_send_json_success(); | |
| 935 | + } | |
| 936 | + } elseif ($tool == 'get_table_details') { | |
| 937 | + $res = WP_Reset_Utility::get_table_details(); | |
| 938 | + wp_send_json_success($res); | |
| 939 | + } elseif ( | |
| 940 | + $tool == 'check_deactivate_plugin' || | |
| 941 | + $tool == 'check_delete_plugin' || | |
| 942 | + $tool == 'check_install_plugin' || | |
| 943 | + $tool == 'check_activate_plugin' | |
| 944 | + ) { | |
| 945 | + if(!isset($_GET['slug'])){ | |
| 946 | + wp_send_json_success('unknown plugin'); | |
| 947 | + } | |
| 948 | + | |
| 949 | + $slug = sanitize_text_field(wp_unslash($_GET['slug'])); | |
| 950 | + $path = $this->get_plugin_path($slug); | |
| 835 | 951 | |
| 836 | - /** | |
| 837 | - * Delete .htaccess file | |
| 838 | - * | |
| 839 | - * @return bool|WP_Error Action status. | |
| 840 | - */ | |
| 841 | - function do_delete_htaccess() | |
| 842 | - { | |
| 843 | - global $wp_filesystem; | |
| 952 | + if (false !== ($error = get_transient('wf_install_error_' . $slug))) { | |
| 953 | + delete_transient('wf_install_error_' . $slug); | |
| 954 | + wp_send_json_success($error); | |
| 955 | + } | |
| 844 | 956 | |
| 845 | - if (empty($wp_filesystem)) { | |
| 846 | - require_once ABSPATH . '/wp-admin/includes/file.php'; | |
| 847 | - WP_Filesystem(); | |
| 848 | - } | |
| 957 | + if (false !== $path) { | |
| 958 | + $active_plugins = (array) get_option('active_plugins', array()); | |
| 959 | + if (false !== array_search($path, $active_plugins)) { | |
| 960 | + wp_send_json_success('active'); | |
| 961 | + } else { | |
| 962 | + wp_send_json_success('inactive'); | |
| 963 | + } | |
| 964 | + } else { | |
| 965 | + wp_send_json_success('deleted'); | |
| 966 | + } | |
| 967 | + } elseif ($tool == 'install_plugin') { | |
| 968 | + if(!isset($_GET['slug'])){ | |
| 969 | + wp_send_json_success('unknown plugin'); | |
| 970 | + } | |
| 971 | + | |
| 972 | + $slug = sanitize_text_field(wp_unslash($_GET['slug'])); | |
| 849 | 973 | |
| 850 | - $htaccess_path = $this->get_htaccess_path(); | |
| 851 | - clearstatcache(); | |
| 974 | + @include_once ABSPATH . 'wp-admin/includes/plugin.php'; | |
| 975 | + @include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; | |
| 976 | + @include_once ABSPATH . 'wp-admin/includes/plugin-install.php'; | |
| 977 | + @include_once ABSPATH . 'wp-admin/includes/file.php'; | |
| 978 | + @include_once ABSPATH . 'wp-admin/includes/misc.php'; | |
| 852 | 979 | |
| 853 | - do_action('wp_reset_delete_htaccess', $htaccess_path); | |
| 980 | + wp_cache_flush(); | |
| 854 | 981 | |
| 855 | - if (!$wp_filesystem->is_readable($htaccess_path)) { | |
| 856 | - return new WP_Error(1, 'Htaccess file does not exist; there\'s nothing to delete.'); | |
| 857 | - } | |
| 982 | + $path = $this->get_plugin_path($slug); | |
| 858 | 983 | |
| 859 | - if (!$wp_filesystem->is_writable($htaccess_path)) { | |
| 860 | - return new WP_Error(1, 'Htaccess file is not writable.'); | |
| 861 | - } | |
| 984 | + if (false !== $path) { | |
| 985 | + // Plugin is already installed | |
| 986 | + wp_send_json_success(); | |
| 987 | + } else { | |
| 988 | + // Install Plugin | |
| 989 | + $skin = new WP_Ajax_Upgrader_Skin(); | |
| 990 | + $upgrader = new Plugin_Upgrader($skin); | |
| 991 | + $upgrader->install('https://downloads.wordpress.org/plugin/' . $slug . '.latest-stable.zip'); | |
| 992 | + wp_send_json_success(); | |
| 993 | + } | |
| 994 | + } elseif ($tool == 'activate_plugin') { | |
| 995 | + if(!isset($_GET['slug'])){ | |
| 996 | + wp_send_json_success('unknown plugin'); | |
| 997 | + } | |
| 998 | + | |
| 999 | + $slug = sanitize_text_field(wp_unslash($_GET['slug'])); | |
| 862 | 1000 | |
| 863 | - if ($wp_filesystem->delete($htaccess_path, false, 'f')) { | |
| 864 | - return true; | |
| 865 | - } else { | |
| 866 | - return new WP_Error(1, 'Unknown error. Unable to delete htaccess file.'); | |
| 867 | - } | |
| 868 | - } // do_delete_htaccess | |
| 1001 | + $path = $this->get_plugin_path($slug); | |
| 1002 | + activate_plugin($path); | |
| 1003 | + wp_send_json_success(); | |
| 1004 | + } elseif ($tool == 'before_reset') { | |
| 1005 | + $active_plugins = get_option('active_plugins'); | |
| 1006 | + set_transient('wpr_active_plugins', $active_plugins, 100); | |
| 1007 | + remove_all_actions('update_option_active_plugins'); | |
| 1008 | + update_option('active_plugins', array(plugin_basename(__FILE__))); | |
| 1009 | + wp_send_json_success(); | |
| 1010 | + } else { | |
| 1011 | + wp_send_json_error(__('Unknown tool.', 'wp-reset')); | |
| 1012 | + } | |
| 1013 | + } // ajax_run_tool | |
| 869 | 1014 | |
| 870 | 1015 | |
| 871 | - /** | |
| 872 | - * Get .htaccess file path. | |
| 873 | - * | |
| 874 | - * @return string | |
| 875 | - */ | |
| 876 | - function get_htaccess_path() | |
| 877 | - { | |
| 878 | - if (!function_exists('get_home_path')) { | |
| 879 | - require_once ABSPATH . 'wp-admin/includes/file.php'; | |
| 880 | - } | |
| 1016 | + /** | |
| 1017 | + * Get plugin path from slug | |
| 1018 | + * | |
| 1019 | + * @return string path | |
| 1020 | + */ | |
| 1021 | + function get_plugin_path($slug) | |
| 1022 | + { | |
| 1023 | + $all_plugins = get_plugins(); | |
| 1024 | + foreach ($all_plugins as $plugin_path => $plugin) { | |
| 1025 | + if (strpos($plugin_path, $slug . '/') === 0) { | |
| 1026 | + return $plugin_path; | |
| 1027 | + } | |
| 1028 | + } | |
| 1029 | + return false; | |
| 1030 | + } // get_plugin_path | |
| 881 | 1031 | |
| 882 | - if ($this->is_cli_running()) { | |
| 883 | - $_SERVER['SCRIPT_FILENAME'] = ABSPATH; | |
| 884 | - } | |
| 885 | 1032 | |
| 886 | - $filepath = get_home_path() . '.htaccess'; | |
| 1033 | + /** | |
| 1034 | + * Reinstall / reset the WP site | |
| 1035 | + * There are no failsafes in the function - it reinstalls when called | |
| 1036 | + * Redirects when done | |
| 1037 | + * | |
| 1038 | + * @param array $params Optional. | |
| 1039 | + * | |
| 1040 | + * @return null | |
| 1041 | + */ | |
| 1042 | + function do_reinstall($params = array()) | |
| 1043 | + { | |
| 1044 | + global $current_user, $wpdb; | |
| 887 | 1045 | |
| 888 | - return $filepath; | |
| 889 | - } // get_htaccess_path | |
| 1046 | + // only admins can reset; double-check | |
| 1047 | + if (!$this->is_cli_running() && !current_user_can('manage_options')) { | |
| 1048 | + return false; | |
| 1049 | + } | |
| 890 | 1050 | |
| 1051 | + // make sure the function is available to us | |
| 1052 | + if (!function_exists('wp_install')) { | |
| 1053 | + require ABSPATH . '/wp-admin/includes/upgrade.php'; | |
| 1054 | + } | |
| 891 | 1055 | |
| 892 | - /** | |
| 893 | - * Run one tool via AJAX call | |
| 894 | - * | |
| 895 | - * @return null | |
| 896 | - */ | |
| 897 | - function ajax_run_tool() | |
| 898 | - { | |
| 899 | - check_ajax_referer('wp-reset_run_tool'); | |
| 1056 | + // save values that need to be restored after reset | |
| 1057 | + $blogname = get_option('blogname'); | |
| 1058 | + $blog_public = get_option('blog_public'); | |
| 1059 | + $wplang = get_option('wplang'); | |
| 1060 | + $siteurl = get_option('siteurl'); | |
| 1061 | + $home = get_option('home'); | |
| 1062 | + $snapshots = $this->get_snapshots(); | |
| 900 | 1063 | |
| 901 | - if (!current_user_can('administrator')) { | |
| 902 | - wp_send_json_error(__('You are not allowed to run this action.', 'wp-reset')); | |
| 903 | - } | |
| 1064 | + $active_plugins = get_transient('wpr_active_plugins'); | |
| 1065 | + $active_theme = wp_get_theme(); | |
| 904 | 1066 | |
| 905 | - $tool = trim(@$_GET['tool']); | |
| 906 | - $extra_data = trim(@$_GET['extra_data']); | |
| 1067 | + // for WP-CLI | |
| 1068 | + if (!$current_user->ID) { | |
| 1069 | + $tmp = get_users(array('role' => 'administrator', 'order' => 'ASC', 'order_by' => 'ID')); | |
| 1070 | + if (empty($tmp[0]->user_login)) { | |
| 1071 | + return new WP_Error(1, 'Reset failed. Unable to find any admin users in database.'); | |
| 1072 | + } | |
| 1073 | + $current_user = $tmp[0]; | |
| 1074 | + } | |
| 907 | 1075 | |
| 908 | - if ($tool == 'delete_transients') { | |
| 909 | - $cnt = $this->do_delete_transients(); | |
| 910 | - wp_send_json_success($cnt); | |
| 911 | - } elseif ($tool == 'reset_theme_options') { | |
| 912 | - $cnt = $this->do_reset_theme_options(true); | |
| 913 | - wp_send_json_success($cnt); | |
| 914 | - } elseif ($tool == 'delete_themes') { | |
| 915 | - $cnt = $this->do_delete_themes(false); | |
| 916 | - wp_send_json_success($cnt); | |
| 917 | - } elseif ($tool == 'delete_plugins') { | |
| 918 | - $cnt = $this->do_delete_plugins(true); | |
| 919 | - wp_send_json_success($cnt); | |
| 920 | - } elseif ($tool == 'delete_uploads') { | |
| 921 | - $cnt = $this->do_delete_uploads(); | |
| 922 | - wp_send_json_success($cnt); | |
| 923 | - } elseif ($tool == 'delete_htaccess') { | |
| 924 | - $tmp = $this->do_delete_htaccess(); | |
| 925 | - if (is_wp_error($tmp)) { | |
| 926 | - wp_send_json_error($tmp->get_error_message()); | |
| 927 | - } else { | |
| 928 | - wp_send_json_success($tmp); | |
| 929 | - } | |
| 930 | - } elseif ($tool == 'drop_custom_tables') { | |
| 931 | - $cnt = $this->do_drop_custom_tables(); | |
| 932 | - wp_send_json_success($cnt); | |
| 933 | - } elseif ($tool == 'truncate_custom_tables') { | |
| 934 | - $cnt = $this->do_truncate_custom_tables(); | |
| 935 | - wp_send_json_success($cnt); | |
| 936 | - } elseif ($tool == 'delete_snapshot') { | |
| 937 | - $res = $this->do_delete_snapshot($extra_data); | |
| 938 | - if (is_wp_error($res)) { | |
| 939 | - wp_send_json_error($res->get_error_message()); | |
| 940 | - } else { | |
| 941 | - wp_send_json_success(); | |
| 942 | - } | |
| 943 | - } elseif ($tool == 'download_snapshot') { | |
| 944 | - $res = $this->do_export_snapshot($extra_data); | |
| 945 | - if (is_wp_error($res)) { | |
| 946 | - wp_send_json_error($res->get_error_message()); | |
| 947 | - } else { | |
| 948 | - $url = content_url() . '/' . $this->snapshots_folder . '/' . $res; | |
| 949 | - wp_send_json_success($url); | |
| 950 | - } | |
| 951 | - } elseif ($tool == 'restore_snapshot') { | |
| 952 | - $res = $this->do_restore_snapshot($extra_data); | |
| 953 | - if (is_wp_error($res)) { | |
| 954 | - wp_send_json_error($res->get_error_message()); | |
| 955 | - } else { | |
| 956 | - wp_send_json_success(); | |
| 957 | - } | |
| 958 | - } elseif ($tool == 'compare_snapshots') { | |
| 959 | - $res = $this->do_compare_snapshots($extra_data); | |
| 960 | - if (is_wp_error($res)) { | |
| 961 | - wp_send_json_error($res->get_error_message()); | |
| 962 | - } else { | |
| 963 | - wp_send_json_success($res); | |
| 964 | - } | |
| 965 | - } elseif ($tool == 'create_snapshot') { | |
| 966 | - $res = $this->do_create_snapshot($extra_data); | |
| 967 | - if (is_wp_error($res)) { | |
| 968 | - wp_send_json_error($res->get_error_message()); | |
| 969 | - } else { | |
| 970 | - wp_send_json_success(); | |
| 971 | - } | |
| 972 | - } else { | |
| 973 | - wp_send_json_error(__('Unknown tool.', 'wp-reset')); | |
| 974 | - } | |
| 975 | - } // ajax_run_tool | |
| 1076 | + // delete custom tables with WP's prefix | |
| 1077 | + $prefix = str_replace('_', '\_', $wpdb->prefix); | |
| 976 | 1078 | |
| 1079 | + // phpcs:ignore db call warning as we are using uncommon queries | |
| 1080 | + $tables = $wpdb->get_col($wpdb->prepare("SHOW TABLES LIKE %s", array($prefix . '%'))); // phpcs:ignore | |
| 977 | 1081 | |
| 978 | - /** | |
| 979 | - * Reinstall / reset the WP site | |
| 980 | - * There are no failsafes in the function - it reinstalls when called | |
| 981 | - * Redirects when done | |
| 982 | - * | |
| 983 | - * @param array $params Optional. | |
| 984 | - * | |
| 985 | - * @return null | |
| 986 | - */ | |
| 987 | - function do_reinstall($params = array()) | |
| 988 | - { | |
| 989 | - global $current_user, $wpdb; | |
| 1082 | + foreach ($tables as $table) { | |
| 1083 | + $wpdb->wpreset_table = $table; | |
| 1084 | + $wpdb->query("DROP TABLE " . $wpdb->wpreset_table); // phpcs:ignore | |
| 1085 | + } | |
| 990 | 1086 | |
| 991 | - // only admins can reset; double-check | |
| 992 | - if (!$this->is_cli_running() && !current_user_can('administrator')) { | |
| 993 | - return false; | |
| 994 | - } | |
| 1087 | + $old_user_pass = $current_user->user_pass; | |
| 995 | 1088 | |
| 996 | - // make sure the function is available to us | |
| 997 | - if (!function_exists('wp_install')) { | |
| 998 | - require ABSPATH . '/wp-admin/includes/upgrade.php'; | |
| 999 | - } | |
| 1089 | + // suppress errors for WP_CLI | |
| 1090 | + $result = @wp_install($blogname, $current_user->user_login, $current_user->user_email, $blog_public, '', md5(wp_rand()), $wplang); | |
| 1091 | + $user_id = $result['user_id']; | |
| 1000 | 1092 | |
| 1001 | - // save values that need to be restored after reset | |
| 1002 | - // todo: use params to determine what gets restored after reset | |
| 1003 | - $blogname = get_option('blogname'); | |
| 1004 | - $blog_public = get_option('blog_public'); | |
| 1005 | - $wplang = get_option('wplang'); | |
| 1006 | - $siteurl = get_option('siteurl'); | |
| 1007 | - $home = get_option('home'); | |
| 1008 | - $snapshots = $this->get_snapshots(); | |
| 1093 | + // restore user pass | |
| 1094 | + // phpcs:ignore db call warning as we are using uncommon queries | |
| 1095 | + $wpdb->query($wpdb->prepare("UPDATE {$wpdb->users} SET user_pass = %s, user_activation_key = %s WHERE ID = %d LIMIT 1", array($old_user_pass, '', $user_id))); // phpcs:ignore | |
| 1096 | + $current_user->user_pass = $old_user_pass; | |
| 1009 | 1097 | |
| 1010 | - $active_plugins = get_option('active_plugins'); | |
| 1011 | - $active_theme = wp_get_theme(); | |
| 1098 | + // restore rest of the settings including WP Reset's | |
| 1099 | + update_option('siteurl', $siteurl); | |
| 1100 | + update_option('home', $home); | |
| 1101 | + update_option('wp-reset', $this->options); | |
| 1102 | + update_option('wp-reset-snapshots', $snapshots); | |
| 1012 | 1103 | |
| 1013 | - if (!empty($params['reactivate_webhooks'])) { | |
| 1014 | - $wpwh1 = get_option('wpwhpro_active_webhooks'); | |
| 1015 | - $wpwh2 = get_option('wpwhpro_activate_translations'); | |
| 1016 | - $wpwh3 = get_option('ironikus_webhook_webhooks'); | |
| 1017 | - } | |
| 1104 | + // remove password nag | |
| 1105 | + if (get_user_meta($user_id, 'default_password_nag')) { | |
| 1106 | + update_user_meta($user_id, 'default_password_nag', false); | |
| 1107 | + } | |
| 1108 | + if (get_user_meta($user_id, $wpdb->prefix . 'default_password_nag')) { | |
| 1109 | + update_user_meta($user_id, $wpdb->prefix . 'default_password_nag', false); | |
| 1110 | + } | |
| 1018 | 1111 | |
| 1019 | - // for WP-CLI | |
| 1020 | - if (!$current_user->ID) { | |
| 1021 | - $tmp = get_users(array('role' => 'administrator', 'order' => 'ASC', 'order_by' => 'ID')); | |
| 1022 | - if (empty($tmp[0]->user_login)) { | |
| 1023 | - return new WP_Error(1, 'Reset failed. Unable to find any admin users in database.'); | |
| 1024 | - } | |
| 1025 | - $current_user = $tmp[0]; | |
| 1026 | - } | |
| 1112 | + $meta = $this->get_meta(); | |
| 1113 | + $meta['reset_count']++; | |
| 1114 | + $this->update_options('meta', $meta); | |
| 1027 | 1115 | |
| 1028 | - // delete custom tables with WP's prefix | |
| 1029 | - $prefix = str_replace('_', '\_', $wpdb->prefix); | |
| 1030 | - $tables = $wpdb->get_col("SHOW TABLES LIKE '{$prefix}%'"); | |
| 1031 | - foreach ($tables as $table) { | |
| 1032 | - $wpdb->query("DROP TABLE $table"); | |
| 1033 | - } | |
| 1116 | + // reactivate theme | |
| 1117 | + if (!empty($params['reactivate_theme'])) { | |
| 1118 | + switch_theme($active_theme->get_stylesheet()); | |
| 1119 | + } | |
| 1034 | 1120 | |
| 1035 | - // supress errors for WP_CLI | |
| 1036 | - // todo: find a better way to supress errors and send/not send email on reset | |
| 1037 | - $result = @wp_install($blogname, $current_user->user_login, $current_user->user_email, $blog_public, '', md5(rand()), $wplang); | |
| 1038 | - $user_id = $result['user_id']; | |
| 1121 | + // reactivate WP Reset | |
| 1122 | + if (!empty($params['reactivate_wpreset'])) { | |
| 1123 | + activate_plugin(plugin_basename(__FILE__)); | |
| 1124 | + } | |
| 1039 | 1125 | |
| 1040 | - // restore user pass | |
| 1041 | - $query = $wpdb->prepare("UPDATE {$wpdb->users} SET user_pass = %s, user_activation_key = '' WHERE ID = %d LIMIT 1", array($current_user->user_pass, $user_id)); | |
| 1042 | - $wpdb->query($query); | |
| 1126 | + // reactivate all plugins | |
| 1127 | + if (!empty($params['reactivate_plugins'])) { | |
| 1128 | + foreach ($active_plugins as $plugin_file) { | |
| 1129 | + activate_plugin($plugin_file); | |
| 1130 | + } | |
| 1131 | + } | |
| 1043 | 1132 | |
| 1044 | - // restore rest of the settings including WP Reset's | |
| 1045 | - update_option('siteurl', $siteurl); | |
| 1046 | - update_option('home', $home); | |
| 1047 | - update_option('wp-reset', $this->options); | |
| 1048 | - update_option('wp-reset-snapshots', $snapshots); | |
| 1133 | + if (!$this->is_cli_running()) { | |
| 1134 | + // log out and log in the old/new user | |
| 1135 | + // since the password doesn't change this is potentially unnecessary | |
| 1136 | + wp_clear_auth_cookie(); | |
| 1137 | + wp_set_auth_cookie($user_id); | |
| 1049 | 1138 | |
| 1050 | - // remove password nag | |
| 1051 | - if (get_user_meta($user_id, 'default_password_nag')) { | |
| 1052 | - update_user_meta($user_id, 'default_password_nag', false); | |
| 1053 | - } | |
| 1054 | - if (get_user_meta($user_id, $wpdb->prefix . 'default_password_nag')) { | |
| 1055 | - update_user_meta($user_id, $wpdb->prefix . 'default_password_nag', false); | |
| 1056 | - } | |
| 1139 | + wp_safe_redirect(admin_url() . '?wp-reset=success'); | |
| 1140 | + exit; | |
| 1141 | + } | |
| 1142 | + } // do_reinstall | |
| 1057 | 1143 | |
| 1058 | - $meta = $this->get_meta(); | |
| 1059 | - $meta['reset_count']++; | |
| 1060 | - $this->update_options('meta', $meta); | |
| 1061 | 1144 | |
| 1062 | - // reactivate theme | |
| 1063 | - if (!empty($params['reactivate_theme'])) { | |
| 1064 | - switch_theme($active_theme->get_stylesheet()); | |
| 1065 | - } | |
| 1145 | + /** | |
| 1146 | + * Checks wp_reset post value and performs all actions | |
| 1147 | + * | |
| 1148 | + * @return null|bool | |
| 1149 | + */ | |
| 1150 | + function do_all_actions() | |
| 1151 | + { | |
| 1152 | + // only admins can perform actions | |
| 1153 | + if (!current_user_can('manage_options')) { | |
| 1154 | + return; | |
| 1155 | + } | |
| 1066 | 1156 | |
| 1067 | - // reactivate WP Reset | |
| 1068 | - if (!empty($params['reactivate_wpreset'])) { | |
| 1069 | - activate_plugin(plugin_basename(__FILE__)); | |
| 1070 | - } | |
| 1157 | + if (!empty($_GET['wp-reset']) && sanitize_text_field(wp_unslash($_GET['wp-reset'])) == 'success') { | |
| 1158 | + add_action('admin_notices', array($this, 'notice_successful_reset')); | |
| 1159 | + } | |
| 1071 | 1160 | |
| 1072 | - // reactivate WP Webhooks | |
| 1073 | - if (!empty($params['reactivate_webhooks'])) { | |
| 1074 | - activate_plugin('wp-webhooks/wp-webhooks.php'); | |
| 1075 | - activate_plugin('wpwh-wp-reset-webhook-integration/wpwhpro-wp-reset-webhook-integration.php'); | |
| 1161 | + // check nonce | |
| 1162 | + if (true === isset($_POST['wp_reset_confirm']) && (!isset($_POST['_wpnonce']) || false === wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['_wpnonce'])), 'wp-reset'))) { | |
| 1163 | + add_settings_error('wp-reset', 'bad-nonce', __('Something went wrong. Please refresh the page and try again.', 'wp-reset'), 'error'); | |
| 1164 | + return false; | |
| 1165 | + } | |
| 1076 | 1166 | |
| 1077 | - update_option('wpwhpro_active_webhooks', $wpwh1); | |
| 1078 | - update_option('wpwhpro_activate_translations', $wpwh2); | |
| 1079 | - update_option('ironikus_webhook_webhooks', $wpwh3); | |
| 1080 | - } | |
| 1167 | + // check confirmation code | |
| 1168 | + if (true === isset($_POST['wp_reset_confirm']) && 'reset' !== sanitize_text_field(wp_unslash($_POST['wp_reset_confirm']))) { | |
| 1169 | + add_settings_error('wp-reset', 'bad-confirm', __('<b>Invalid confirmation code.</b> Please type "reset" in the confirmation field.', 'wp-reset'), 'error'); | |
| 1170 | + return false; | |
| 1171 | + } | |
| 1081 | 1172 | |
| 1082 | - // reactivate all plugins | |
| 1083 | - if (!empty($params['reactivate_plugins'])) { | |
| 1084 | - foreach ($active_plugins as $plugin_file) { | |
| 1085 | - activate_plugin($plugin_file); | |
| 1086 | - } | |
| 1087 | - } | |
| 1173 | + // only one action at the moment | |
| 1174 | + if (true === isset($_POST['wp_reset_confirm']) && 'reset' === sanitize_text_field(wp_unslash($_POST['wp_reset_confirm']))) { | |
| 1175 | + $params = array( | |
| 1176 | + 'reactivate_theme' => '0', | |
| 1177 | + 'reactivate_plugins' => '0', | |
| 1178 | + 'reactivate_wpreset' => '0', | |
| 1179 | + ); | |
| 1180 | + if (isset($_POST['wpr-post-reset']['reactivate_theme'])) { | |
| 1181 | + $params['reactivate_theme'] = true; | |
| 1182 | + } | |
| 1183 | + if (isset($_POST['wpr-post-reset']['reactivate_plugins'])) { | |
| 1184 | + $params['reactivate_plugins'] = true; | |
| 1185 | + } | |
| 1186 | + if (isset($_POST['wpr-post-reset']['reactivate_wpreset'])) { | |
| 1187 | + $params['reactivate_wpreset'] = true; | |
| 1188 | + } | |
| 1088 | 1189 | |
| 1089 | - if (!$this->is_cli_running()) { | |
| 1090 | - // log out and log in the old/new user | |
| 1091 | - // since the password doesn't change this is potentially unnecessary | |
| 1092 | - wp_clear_auth_cookie(); | |
| 1093 | - wp_set_auth_cookie($user_id); | |
| 1190 | + $this->do_reinstall($params); | |
| 1191 | + } | |
| 1192 | + } // do_all_actions | |
| 1094 | 1193 | |
| 1095 | - wp_redirect(admin_url() . '?wp-reset=success'); | |
| 1096 | - exit; | |
| 1097 | - } | |
| 1098 | - } // do_reinstall | |
| 1099 | 1194 | |
| 1195 | + /** | |
| 1196 | + * Add "Open WP Reset Tools" action link to plugins table, left part | |
| 1197 | + * | |
| 1198 | + * @param array $links Initial list of links. | |
| 1199 | + * | |
| 1200 | + * @return array | |
| 1201 | + */ | |
| 1202 | + function plugin_action_links($links) | |
| 1203 | + { | |
| 1204 | + $settings_link = '<a href="' . esc_url(admin_url('tools.php?page=wp-reset')) . '" title="' . esc_attr(__('Open WP Reset Tools', 'wp-reset')) . '">' . esc_html(__('Open WP Reset Tools', 'wp-reset')) . '</a>'; | |
| 1100 | 1205 | |
| 1101 | - /** | |
| 1102 | - * Checks wp_reset post value and performs all actions | |
| 1103 | - * todo: handle messages for various actions | |
| 1104 | - * | |
| 1105 | - * @return null|bool | |
| 1106 | - */ | |
| 1107 | - function do_all_actions() | |
| 1108 | - { | |
| 1109 | - // only admins can perform actions | |
| 1110 | - if (!current_user_can('administrator')) { | |
| 1111 | - return; | |
| 1112 | - } | |
| 1206 | + array_unshift($links, $settings_link); | |
| 1113 | 1207 | |
| 1114 | - if (!empty($_GET['wp-reset']) && stristr($_SERVER['HTTP_REFERER'], 'wp-reset')) { | |
| 1115 | - add_action('admin_notices', array($this, 'notice_successful_reset')); | |
| 1116 | - } | |
| 1208 | + return $links; | |
| 1209 | + } // plugin_action_links | |
| 1117 | 1210 | |
| 1118 | - // check nonce | |
| 1119 | - if (true === isset($_POST['wp_reset_confirm']) && false === wp_verify_nonce(@$_POST['_wpnonce'], 'wp-reset')) { | |
| 1120 | - add_settings_error('wp-reset', 'bad-nonce', __('Something went wrong. Please refresh the page and try again.', 'wp-reset'), 'error'); | |
| 1121 | - return false; | |
| 1122 | - } | |
| 1123 | 1211 | |
| 1124 | - // check confirmation code | |
| 1125 | - if (true === isset($_POST['wp_reset_confirm']) && 'reset' !== $_POST['wp_reset_confirm']) { | |
| 1126 | - add_settings_error('wp-reset', 'bad-confirm', __('<b>Invalid confirmation code.</b> Please type "reset" in the confirmation field.', 'wp-reset'), 'error'); | |
| 1127 | - return false; | |
| 1128 | - } | |
| 1212 | + /** | |
| 1213 | + * Add links to plugin's description in plugins table | |
| 1214 | + * | |
| 1215 | + * @param array $links Initial list of links. | |
| 1216 | + * @param string $file Basename of current plugin. | |
| 1217 | + * | |
| 1218 | + * @return array | |
| 1219 | + */ | |
| 1220 | + function plugin_meta_links($links, $file) | |
| 1221 | + { | |
| 1222 | + if ($file !== plugin_basename(__FILE__)) { | |
| 1223 | + return $links; | |
| 1224 | + } | |
| 1129 | 1225 | |
| 1130 | - // only one action at the moment | |
| 1131 | - if (true === isset($_POST['wp_reset_confirm']) && 'reset' === $_POST['wp_reset_confirm']) { | |
| 1132 | - $defaults = array( | |
| 1133 | - 'reactivate_theme' => '0', | |
| 1134 | - 'reactivate_plugins' => '0', | |
| 1135 | - 'reactivate_wpreset' => '0', | |
| 1136 | - 'reactivate_webhooks' => '0' | |
| 1137 | - ); | |
| 1138 | - $params = shortcode_atts($defaults, (array) @$_POST['wpr-post-reset']); | |
| 1226 | + $support_link = '<a target="_blank" href="https://wordpress.org/support/plugin/wp-reset" title="' . __('Get help', 'wp-reset') . '">' . __('Support', 'wp-reset') . '</a>'; | |
| 1227 | + $home_link = '<a target="_blank" href="' . esc_url($this->generate_web_link('plugins-table-right')) . '" title="' . __('Plugin Homepage', 'wp-reset') . '">' . __('Plugin Homepage', 'wp-reset') . '</a>'; | |
| 1228 | + $rate_link = '<a target="_blank" href="https://wordpress.org/support/plugin/wp-reset/reviews/#new-post" title="' . __('Rate the plugin', 'wp-reset') . '">' . __('Rate the plugin ★★★★★', 'wp-reset') . '</a>'; | |
| 1139 | 1229 | |
| 1140 | - $this->do_reinstall($params); | |
| 1141 | - } | |
| 1142 | - } // do_all_actions | |
| 1230 | + $links[] = $support_link; | |
| 1231 | + $links[] = $home_link; | |
| 1232 | + $links[] = $rate_link; | |
| 1143 | 1233 | |
| 1234 | + return $links; | |
| 1235 | + } // plugin_meta_links | |
| 1144 | 1236 | |
| 1145 | - /** | |
| 1146 | - * Add "Open WP Reset Tools" action link to plugins table, left part | |
| 1147 | - * | |
| 1148 | - * @param array $links Initial list of links. | |
| 1149 | - * | |
| 1150 | - * @return array | |
| 1151 | - */ | |
| 1152 | - function plugin_action_links($links) | |
| 1153 | - { | |
| 1154 | - $settings_link = '<a href="' . admin_url('tools.php?page=wp-reset') . '" title="' . __('Open WP Reset Tools', 'wp-reset') . '">' . __('Open WP Reset Tools', 'wp-reset') . '</a>'; | |
| 1155 | 1237 | |
| 1156 | - array_unshift($links, $settings_link); | |
| 1238 | + /** | |
| 1239 | + * Test if we're on WPR's admin page | |
| 1240 | + * | |
| 1241 | + * @return bool | |
| 1242 | + */ | |
| 1243 | + function is_plugin_page() | |
| 1244 | + { | |
| 1245 | + $current_screen = get_current_screen(); | |
| 1157 | 1246 | |
| 1158 | - return $links; | |
| 1159 | - } // plugin_action_links | |
| 1247 | + if (!empty($current_screen->id) && $current_screen->id == 'tools_page_wp-reset') { | |
| 1248 | + return true; | |
| 1249 | + } else { | |
| 1250 | + return false; | |
| 1251 | + } | |
| 1252 | + } // is_plugin_page | |
| 1160 | 1253 | |
| 1161 | 1254 | |
| 1162 | - /** | |
| 1163 | - * Add links to plugin's description in plugins table | |
| 1164 | - * | |
| 1165 | - * @param array $links Initial list of links. | |
| 1166 | - * @param string $file Basename of current plugin. | |
| 1167 | - * | |
| 1168 | - * @return array | |
| 1169 | - */ | |
| 1170 | - function plugin_meta_links($links, $file) | |
| 1171 | - { | |
| 1172 | - if ($file !== plugin_basename(__FILE__)) { | |
| 1173 | - return $links; | |
| 1174 | - } | |
| 1255 | + /** | |
| 1256 | + * Add powered by text in admin footer | |
| 1257 | + * | |
| 1258 | + * @param string $text Default footer text. | |
| 1259 | + * | |
| 1260 | + * @return string | |
| 1261 | + */ | |
| 1262 | + function admin_footer_text($text) | |
| 1263 | + { | |
| 1264 | + if (!$this->is_plugin_page()) { | |
| 1265 | + return $text; | |
| 1266 | + } | |
| 1175 | 1267 | |
| 1176 | - $support_link = '<a target="_blank" href="https://wordpress.org/support/plugin/wp-reset" title="' . __('Get help', 'wp-reset') . '">' . __('Support', 'wp-reset') . '</a>'; | |
| 1177 | - $home_link = '<a target="_blank" href="' . $this->generate_web_link('plugins-table-right') . '" title="' . __('Plugin Homepage', 'wp-reset') . '">' . __('Plugin Homepage', 'wp-reset') . '</a>'; | |
| 1178 | - $rate_link = '<a target="_blank" href="https://wordpress.org/support/plugin/wp-reset/reviews/#new-post" title="' . __('Rate the plugin', 'wp-reset') . '">' . __('Rate the plugin ★★★★★', 'wp-reset') . '</a>'; | |
| 1268 | + $text = '<i><a href="' . esc_url($this->generate_web_link('admin_footer')) . '" title="' . esc_attr(__('Visit WP Reset page for more info', 'wp-reset')) . '" target="_blank">WP Reset</a> v' . $this->version . '. Please <a target="_blank" href="https://wordpress.org/support/plugin/wp-reset/reviews/#new-post" title="Rate the plugin">rate the plugin <span>★★★★★</span></a> to help us spread the word. Thank you from the WP Reset team!</i>'; | |
| 1179 | 1269 | |
| 1180 | - $links[] = $support_link; | |
| 1181 | - $links[] = $home_link; | |
| 1182 | - $links[] = $rate_link; | |
| 1270 | + return $text; | |
| 1271 | + } // admin_footer_text | |
| 1183 | 1272 | |
| 1184 | - return $links; | |
| 1185 | - } // plugin_meta_links | |
| 1186 | 1273 | |
| 1274 | + /** | |
| 1275 | + * Loads plugin's translated strings | |
| 1276 | + * | |
| 1277 | + * @return null | |
| 1278 | + */ | |
| 1279 | + function load_textdomain() | |
| 1280 | + { | |
| 1281 | + load_plugin_textdomain('wp-reset'); | |
| 1282 | + } // load_textdomain | |
| 1187 | 1283 | |
| 1188 | - /** | |
| 1189 | - * Test if we're on WPR's admin page | |
| 1190 | - * | |
| 1191 | - * @return bool | |
| 1192 | - */ | |
| 1193 | - function is_plugin_page() | |
| 1194 | - { | |
| 1195 | - $current_screen = get_current_screen(); | |
| 1196 | 1284 | |
| 1197 | - if ($current_screen->id == 'tools_page_wp-reset') { | |
| 1198 | - return true; | |
| 1199 | - } else { | |
| 1200 | - return false; | |
| 1201 | - } | |
| 1202 | - } // is_plugin_page | |
| 1285 | + /** | |
| 1286 | + * Inform the user that WordPress has been successfully reset | |
| 1287 | + * | |
| 1288 | + * @return null | |
| 1289 | + */ | |
| 1290 | + function notice_successful_reset() | |
| 1291 | + { | |
| 1292 | + global $current_user; | |
| 1293 | + /* translators: %1$s is replaced with the current user's username, %2$s is replaced with the URL to WP Reset settings page */ | |
| 1294 | + WP_Reset_Utility::wp_kses_wf('<div style="padding: 15px; display: inline-block; font-size: 14px;" id="message" class="updated"><p style="font-size: 14px;">' . sprintf(__('<b>Site has been successfully reset to default settings.</b><br>User "%1$s" was restored with the password unchanged. Open <a href="%2$s">WP Reset</a> to do another reset.', 'wp-reset'), esc_html($current_user->user_login), esc_url(admin_url('tools.php?page=wp-reset'))) . '</p>'); | |
| 1203 | 1295 | |
| 1204 | 1296 | |
| 1205 | - /** | |
| 1206 | - * Add powered by text in admin footer | |
| 1207 | - * | |
| 1208 | - * @param string $text Default footer text. | |
| 1209 | - * | |
| 1210 | - * @return string | |
| 1211 | - */ | |
| 1212 | - function admin_footer_text($text) | |
| 1213 | - { | |
| 1214 | - if (!$this->is_plugin_page()) { | |
| 1215 | - return $text; | |
| 1216 | - } | |
| 1297 | + if (false == $this->get_dismissed_notices('rate')) { | |
| 1298 | + $request_url = isset($_SERVER['REQUEST_URI'])?sanitize_url(wp_unslash($_SERVER['REQUEST_URI'])):''; | |
| 1299 | + $dismiss_url = add_query_arg(array('action' => 'wpr_dismiss_notice', 'notice' => 'rate', 'redirect' => urlencode($request_url)), admin_url('admin.php')); | |
| 1300 | + $dismiss_url = wp_nonce_url($dismiss_url, 'wpr_dismiss_notice'); | |
| 1217 | 1301 | |
| 1218 | - $text = '<i><a href="' . $this->generate_web_link('admin_footer') . '" title="' . __('Visit WP Reset page for more info', 'wp-reset') . '" target="_blank">WP Reset</a> v' . $this->version . '. Please <a target="_blank" href="https://wordpress.org/support/plugin/wp-reset/reviews/#new-post" title="Rate the plugin">rate the plugin <span>★★★★★</span></a> to help us spread the word. Thank you from the WP Reset team!</i>'; | |
| 1302 | + echo '<p style="font-size: 14px;">'; | |
| 1303 | + echo 'If WP Reset helped you please rate it so we can continue supporting it and helping others. Thank you!<br>'; | |
| 1304 | + echo '<a style="margin-top: 5px;" class="button button-secondary" href="https://wordpress.org/support/plugin/wp-reset/reviews/#new-post" target="_blank">You deserve it, I\'ll rate it!</a> <a href="' . esc_url($dismiss_url) . '">I already rated it</a>'; | |
| 1305 | + echo '</p>'; | |
| 1306 | + } | |
| 1219 | 1307 | |
| 1220 | - return $text; | |
| 1221 | - } // admin_footer_text | |
| 1308 | + echo '</div>'; | |
| 1309 | + } // notice_successful_reset | |
| 1222 | 1310 | |
| 1223 | 1311 | |
| 1224 | - /** | |
| 1225 | - * Loads plugin's translated strings | |
| 1226 | - * | |
| 1227 | - * @return null | |
| 1228 | - */ | |
| 1229 | - function load_textdomain() | |
| 1230 | - { | |
| 1231 | - load_plugin_textdomain('wp-reset'); | |
| 1232 | - } // load_textdomain | |
| 1312 | + /** | |
| 1313 | + * Generate a button that initiates snapshot creation | |
| 1314 | + * | |
| 1315 | + * @param string $tool_id Tool ID. | |
| 1316 | + * @param string $description Snapshot description. | |
| 1317 | + * | |
| 1318 | + * @return string | |
| 1319 | + */ | |
| 1320 | + function get_snapshot_button($tool_id = '', $description = '') | |
| 1321 | + { | |
| 1322 | + $out = ''; | |
| 1323 | + $out .= '<a data-tool-id="' . esc_attr($tool_id) . '" data-description="' . esc_attr($description) . '" class="button create-new-snapshot" href="#">Create snapshot</a>'; | |
| 1233 | 1324 | |
| 1325 | + return $out; | |
| 1326 | + } // get_snapshot_button | |
| 1234 | 1327 | |
| 1235 | - /** | |
| 1236 | - * Inform the user that WordPress has been successfully reset | |
| 1237 | - * | |
| 1238 | - * @return null | |
| 1239 | - */ | |
| 1240 | - function notice_successful_reset() | |
| 1241 | - { | |
| 1242 | - global $current_user; | |
| 1243 | 1328 | |
| 1244 | - echo '<div id="message" class="updated fade"><p>' . sprintf(__('<b>Site has been reset</b> to default settings. User "%s" was restored with the password unchanged. Open <a href="%s">WP Reset</a> to do another reset.', 'wp-reset'), $current_user->user_login, admin_url('tools.php?page=wp-reset')) . '</p></div>'; | |
| 1245 | - } // notice_successful_reset | |
| 1329 | + /** | |
| 1330 | + * Generate card header including title and action buttons | |
| 1331 | + * | |
| 1332 | + * @param string $title Card title. | |
| 1333 | + * @param string $card_id Card element #ID. | |
| 1334 | + * @param array $params Individual icons arguments | |
| 1335 | + * | |
| 1336 | + * @return string | |
| 1337 | + */ | |
| 1338 | + function get_card_header($title, $card_id, $params = array()) | |
| 1339 | + { | |
| 1340 | + $params = shortcode_atts(array( | |
| 1341 | + 'documentation_link' => false, | |
| 1342 | + 'iot_button' => false, | |
| 1343 | + 'collapse_button' => false, | |
| 1344 | + 'create_snapshot' => false, | |
| 1345 | + 'pro' => false | |
| 1346 | + ), (array) $params); | |
| 1246 | 1347 | |
| 1348 | + if ($params['documentation_link'] === true) { | |
| 1349 | + $params['documentation_link'] = $card_id; | |
| 1350 | + } | |
| 1247 | 1351 | |
| 1248 | - /** | |
| 1249 | - * Generate a button that initiates snapshot creation | |
| 1250 | - * | |
| 1251 | - * @param string $tool_id Tool ID. | |
| 1252 | - * @param string $description Snapshot description. | |
| 1253 | - * | |
| 1254 | - * @return string | |
| 1255 | - */ | |
| 1256 | - function get_snapshot_button($tool_id = '', $description = '') | |
| 1257 | - { | |
| 1258 | - $out = ''; | |
| 1259 | - $out .= '<a data-tool-id="' . $tool_id . '" data-description="' . esc_attr($description) . '" class="button create-new-snapshot" href="#">Create snapshot</a>'; | |
| 1352 | + $out = ''; | |
| 1353 | + $out .= '<h4 id="' . esc_attr($card_id) . '"><span class="card-name">' . esc_html($title); | |
| 1354 | + if ($params['pro']) { | |
| 1355 | + $out .= ' - <a data-feature="' . esc_attr($card_id) . '" class="pro-feature tooltip" title="WP Reset PRO tool" href="#"><span class="pro">PRO</span> tool</a>'; | |
| 1356 | + } | |
| 1357 | + $out .= '</span>'; | |
| 1358 | + $out .= '<div class="card-header-right">'; | |
| 1359 | + if ($params['documentation_link']) { | |
| 1360 | + $out .= '<a class="documentation-link tooltip" href="' . esc_url($this->generate_web_link('documentation_link', '/documentation/')) . '" title="' . __('Open documentation for this tool', 'wp-reset') . '" target="blank"><span class="dashicons dashicons-editor-help"></span></a>'; | |
| 1361 | + } | |
| 1362 | + if ($params['iot_button']) { | |
| 1363 | + $out .= '<a class="scrollto tooltip" href="#iot" title="Jump to Index of Tools"><span class="dashicons dashicons-screenoptions"></span></a>'; | |
| 1364 | + } | |
| 1365 | + if ($params['create_snapshot']) { | |
| 1366 | + $out .= '<a id="create-new-snapshot-primary" title="Create a new snapshot" href="#" class="button button-primary create-new-snapshot tooltip">' . __('Create Snapshot', 'wp-reset') . '</a>'; | |
| 1367 | + } | |
| 1368 | + if ($params['collapse_button']) { | |
| 1369 | + $out .= '<a class="toggle-card tooltip" href="#" title="' . __('Collapse / expand box', 'wp-reset') . '"><span class="dashicons dashicons-arrow-up-alt2"></span></a>'; | |
| 1370 | + } | |
| 1371 | + $out .= '</div></h4>'; | |
| 1260 | 1372 | |
| 1261 | - return $out; | |
| 1262 | - } // get_snapshot_button | |
| 1373 | + return $out; | |
| 1374 | + } // get_card_header | |
| 1263 | 1375 | |
| 1264 | 1376 | |
| 1265 | - /** | |
| 1266 | - * Generate card header including title and action buttons | |
| 1267 | - * | |
| 1268 | - * @param string $title Card title. | |
| 1269 | - * @param string $card_id Card ID. | |
| 1270 | - * @param bool $collapse_button Show collapse button. | |
| 1271 | - * @param bool $iot_button Show index of tools button. | |
| 1272 | - * | |
| 1273 | - * @return string | |
| 1274 | - */ | |
| 1275 | - function get_card_header($title, $card_id, $collapse_button = false, $iot_button = false) | |
| 1276 | - { | |
| 1277 | - $out = ''; | |
| 1278 | - $out .= '<h4 id="' . $card_id . '">' . $title; | |
| 1279 | - $out .= '<div class="card-header-right">'; | |
| 1280 | - if ($iot_button) { | |
| 1281 | - $out .= '<a class="scrollto" href="#iot" title="Jump to Index of Tools"><span class="dashicons dashicons-screenoptions"></span></a>'; | |
| 1282 | - } | |
| 1283 | - if ($collapse_button) { | |
| 1284 | - $out .= '<a class="toggle-card" href="#" title="' . __('Collapse / expand box', 'wp-reset') . '"><span class="dashicons dashicons-arrow-up-alt2"></span></a>'; | |
| 1285 | - } | |
| 1286 | - $out .= '</div></h4>'; | |
| 1377 | + /** | |
| 1378 | + * Generate tool icons and description detailing what it modifies | |
| 1379 | + * | |
| 1380 | + * @param bool $modify_files Does the tool modify files? | |
| 1381 | + * @param bool $modify_db Does the tool modify the database? | |
| 1382 | + * @param bool $plural Is there more than one tool in the set? | |
| 1383 | + * | |
| 1384 | + * @return string | |
| 1385 | + */ | |
| 1386 | + function get_tool_icons($modify_files = false, $modify_db = false, $plural = false) | |
| 1387 | + { | |
| 1388 | + $out = ''; | |
| 1389 | + $modify_files = (bool) $modify_files; | |
| 1390 | + $modify_db = (bool) $modify_db; | |
| 1391 | + $plural = (bool) $plural; | |
| 1287 | 1392 | |
| 1288 | - return $out; | |
| 1289 | - } // get_card_header | |
| 1393 | + $out .= '<p class="tool-icons">'; | |
| 1394 | + $out .= '<i class="icon-doc-text-inv' . ($modify_files ? ' red' : '') . '"></i> '; | |
| 1395 | + $out .= '<i class="icon-database' . ($modify_db ? ' red' : '') . '"></i> '; | |
| 1290 | 1396 | |
| 1397 | + if ($plural) { | |
| 1398 | + if ($modify_files && $modify_db) { | |
| 1399 | + $out .= 'these tools <b>modify files & the database</b>'; | |
| 1400 | + } elseif (!$modify_files && $modify_db) { | |
| 1401 | + $out .= 'these tools <b>modify the database</b> but they don\'t modify any files</b>'; | |
| 1402 | + } elseif ($modify_files && !$modify_db) { | |
| 1403 | + $out .= 'these tools <b>modify files</b> but they don\'t modify the database</b>'; | |
| 1404 | + } | |
| 1405 | + } else { | |
| 1406 | + if ($modify_files && $modify_db) { | |
| 1407 | + $out .= 'this tool <b>modifies files & the database</b>'; | |
| 1408 | + } elseif (!$modify_files && $modify_db) { | |
| 1409 | + $out .= 'this tool <b>modifies the database</b> but it doesn\'t modify any files</b>'; | |
| 1410 | + } elseif ($modify_files && !$modify_db) { | |
| 1411 | + $out .= 'this tool <b>modifies files</b> but it doesn\'t modify the database</b>'; | |
| 1412 | + } else { | |
| 1413 | + $out .= 'this tool doesn\'t modify files or the database'; | |
| 1414 | + } | |
| 1415 | + } | |
| 1416 | + $out .= '</p>'; | |
| 1291 | 1417 | |
| 1292 | - /** | |
| 1293 | - * Generate tool icons and description detailing what it modifies | |
| 1294 | - * | |
| 1295 | - * @param bool $modify_files Does the tool modify files? | |
| 1296 | - * @param bool $modify_db Does the tool modify the database? | |
| 1297 | - * @param bool $plural Is there more than one tool in the set? | |
| 1298 | - * | |
| 1299 | - * @return string | |
| 1300 | - */ | |
| 1301 | - function get_tool_icons($modify_files = false, $modify_db = false, $plural = false) | |
| 1302 | - { | |
| 1303 | - $out = ''; | |
| 1418 | + return $out; | |
| 1419 | + } // get_tool_icons | |
| 1304 | 1420 | |
| 1305 | - $out .= '<p class="tool-icons">'; | |
| 1306 | - $out .= '<i class="icon-doc-text-inv' . ($modify_files ? ' red' : '') . '"></i> '; | |
| 1307 | - $out .= '<i class="icon-database' . ($modify_db ? ' red' : '') . '"></i> '; | |
| 1308 | 1421 | |
| 1309 | - if ($plural) { | |
| 1310 | - if ($modify_files && $modify_db) { | |
| 1311 | - $out .= 'these tools <b>modify files & the database</b>'; | |
| 1312 | - } elseif (!$modify_files && $modify_db) { | |
| 1313 | - $out .= 'these tools <b>modify the database</b> but they don\'t modify any files</b>'; | |
| 1314 | - } elseif ($modify_files && !$modify_db) { | |
| 1315 | - $out .= 'these tools <b>modify files</b> but they don\'t modify the database</b>'; | |
| 1316 | - } | |
| 1317 | - } else { | |
| 1318 | - if ($modify_files && $modify_db) { | |
| 1319 | - $out .= 'this tool <b>modifies files & the database</b>'; | |
| 1320 | - } elseif (!$modify_files && $modify_db) { | |
| 1321 | - $out .= 'this tool <b>modifies the database</b> but it doesn\'t modify any files</b>'; | |
| 1322 | - } elseif ($modify_files && !$modify_db) { | |
| 1323 | - $out .= 'this tool <b>modifies files</b> but it doesn\'t modify the database</b>'; | |
| 1324 | - } | |
| 1325 | - } | |
| 1326 | - $out .= '</p>'; | |
| 1422 | + /** | |
| 1423 | + * Outputs complete plugin's admin page | |
| 1424 | + * | |
| 1425 | + * @return null | |
| 1426 | + */ | |
| 1427 | + function plugin_page() | |
| 1428 | + { | |
| 1429 | + // double check for admin privileges | |
| 1430 | + if (!current_user_can('manage_options')) { | |
| 1431 | + wp_die(esc_html__('Sorry, you are not allowed to access this page.', 'wp-reset')); | |
| 1432 | + } | |
| 1327 | 1433 | |
| 1328 | - return $out; | |
| 1329 | - } // get_tool_icons | |
| 1434 | + echo '<div class="wrap">'; | |
| 1435 | + echo '<form id="wp_reset_form" action="' . esc_url(admin_url('tools.php?page=wp-reset')) . '" method="post" autocomplete="off">'; | |
| 1330 | 1436 | |
| 1437 | + echo '<header>'; | |
| 1438 | + echo '<div class="wpr-container">'; | |
| 1439 | + echo '<img id="logo-icon" src="' . esc_url($this->plugin_url) . 'img/wp-reset-logo.png" title="' . esc_html__('WP Reset', 'wp-reset') . '" alt="' . esc_html__('WP Reset', 'wp-reset') . '">'; | |
| 1440 | + echo '</div>'; | |
| 1441 | + echo '</header>'; | |
| 1331 | 1442 | |
| 1332 | - /** | |
| 1333 | - * Outputs complete plugin's admin page | |
| 1334 | - * | |
| 1335 | - * @return null | |
| 1336 | - */ | |
| 1337 | - function plugin_page() | |
| 1338 | - { | |
| 1339 | - // double check for admin privileges | |
| 1340 | - if (!current_user_can('administrator')) { | |
| 1341 | - wp_die(__('Sorry, you are not allowed to access this page.', 'wp-reset')); | |
| 1342 | - } | |
| 1443 | + echo '<div id="loading-tabs"><img class="rotating" src="' . esc_url($this->plugin_url) . 'img/wp-reset-icon.png' . '" alt="Loading. Please wait." title="Loading. Please wait."></div>'; | |
| 1343 | 1444 | |
| 1344 | - echo '<div class="wrap">'; | |
| 1345 | - echo '<form id="wp_reset_form" action="' . admin_url('tools.php?page=wp-reset') . '" method="post" autocomplete="off">'; | |
| 1445 | + echo '<div id="wp-reset-tabs" class="ui-tabs" style="display: none;">'; | |
| 1346 | 1446 | |
| 1347 | - echo '<header>'; | |
| 1348 | - echo '<div class="wpr-container">'; | |
| 1349 | - echo '<img id="logo-icon" src="' . $this->plugin_url . 'img/wp-reset-logo.png" title="' . __('WP Reset', 'wp-reset') . '" alt="' . __('WP Reset', 'wp-reset') . '">'; | |
| 1350 | - echo '</div>'; | |
| 1351 | - echo '</header>'; | |
| 1447 | + echo '<nav>'; | |
| 1448 | + echo '<div class="wpr-container">'; | |
| 1449 | + echo '<ul class="wpr-main-tab">'; | |
| 1450 | + echo '<li><a href="#tab-reset">' . esc_html(__('Reset', 'wp-reset')) . '</a></li>'; | |
| 1451 | + echo '<li><a href="#tab-tools">' . esc_html(__('Tools', 'wp-reset')) . '</a></li>'; | |
| 1452 | + echo '<li><a href="#tab-snapshots">' . esc_html(__('Snapshots', 'wp-reset')) . '</a></li>'; | |
| 1453 | + echo '<li><a href="#tab-collections">' . esc_html(__('Collections', 'wp-reset')) . '</a></li>'; | |
| 1454 | + echo '<li><a href="#tab-support">' . esc_html(__('Support', 'wp-reset')) . '</a></li>'; | |
| 1455 | + echo '<li class="tab-pro"><a href="#tab-pro">' . esc_html(__('PRO', 'wp-reset')) . '</a></li>'; | |
| 1456 | + echo '</ul>'; | |
| 1457 | + echo '</div>'; // container | |
| 1458 | + echo '</nav>'; | |
| 1352 | 1459 | |
| 1353 | - echo '<div id="loading-tabs"><img class="rotating" src="' . $this->plugin_url . 'img/wp-reset-icon.png' . '" alt="Loading. Please wait." title="Loading. Please wait."></div>'; | |
| 1460 | + echo '<div id="wpr-notifications">'; | |
| 1461 | + echo '<div class="wpr-container">'; | |
| 1462 | + $this->custom_notifications(); | |
| 1463 | + echo '</div>'; | |
| 1464 | + echo '</div>'; // wpr-notifications | |
| 1354 | 1465 | |
| 1355 | - echo '<div id="wp-reset-tabs" class="ui-tabs" style="display: none;">'; | |
| 1466 | + // tabs | |
| 1467 | + echo '<div class="wpr-container">'; | |
| 1468 | + echo '<div id="wpr-content">'; | |
| 1356 | 1469 | |
| 1357 | - echo '<nav>'; | |
| 1358 | - echo '<div class="wpr-container">'; | |
| 1359 | - echo '<ul class="wpr-main-tab">'; | |
| 1360 | - echo '<li><a href="#tab-reset">' . __('Reset', 'wp-reset') . '</a></li>'; | |
| 1361 | - echo '<li><a href="#tab-tools">' . __('Tools', 'wp-reset') . '</a></li>'; | |
| 1362 | - echo '<li><a href="#tab-snapshots">' . __('Snapshots', 'wp-reset') . '</a></li>'; | |
| 1363 | - echo '<li><a href="#tab-collections">' . __('Collections', 'wp-reset') . '</a></li>'; | |
| 1364 | - echo '<li><a href="#tab-support">' . __('Support', 'wp-reset') . '</a></li>'; | |
| 1365 | - echo '</ul>'; | |
| 1366 | - echo '</div>'; // container | |
| 1367 | - echo '</nav>'; | |
| 1470 | + echo '<div style="display: none;" id="tab-reset">'; | |
| 1471 | + $this->tab_reset(); | |
| 1472 | + echo '</div>'; | |
| 1368 | 1473 | |
| 1369 | - echo '<div id="wpr-notifications">'; | |
| 1370 | - echo '<div class="wpr-container">'; | |
| 1371 | - $this->custom_notifications(); | |
| 1372 | - echo '</div>'; | |
| 1373 | - echo '</div>'; // wpr-notifications | |
| 1474 | + echo '<div style="display: none;" id="tab-tools">'; | |
| 1475 | + $this->tab_tools(); | |
| 1476 | + echo '</div>'; | |
| 1374 | 1477 | |
| 1375 | - // tabs | |
| 1376 | - echo '<div class="wpr-container">'; | |
| 1377 | - echo '<div id="wpr-content">'; | |
| 1478 | + echo '<div style="display: none;" id="tab-snapshots">'; | |
| 1479 | + $this->tab_snapshots(); | |
| 1480 | + echo '</div>'; | |
| 1378 | 1481 | |
| 1379 | - echo '<div style="display: none;" id="tab-reset">'; | |
| 1380 | - $this->tab_reset(); | |
| 1381 | - echo '</div>'; | |
| 1482 | + echo '<div style="display: none;" id="tab-collections">'; | |
| 1483 | + $this->tab_collections(); | |
| 1484 | + echo '</div>'; | |
| 1382 | 1485 | |
| 1383 | - echo '<div style="display: none;" id="tab-tools">'; | |
| 1384 | - $this->tab_tools(); | |
| 1385 | - echo '</div>'; | |
| 1486 | + echo '<div style="display: none;" id="tab-support">'; | |
| 1487 | + $this->tab_support(); | |
| 1488 | + echo '</div>'; | |
| 1386 | 1489 | |
| 1387 | - echo '<div style="display: none;" id="tab-snapshots">'; | |
| 1388 | - $this->tab_snapshots(); | |
| 1389 | - echo '</div>'; | |
| 1490 | + echo '<div style="display: none;" id="tab-pro">'; | |
| 1491 | + $this->tab_pro(); | |
| 1492 | + echo '</div>'; | |
| 1390 | 1493 | |
| 1391 | - echo '<div style="display: none;" id="tab-collections">'; | |
| 1392 | - $this->tab_collections(); | |
| 1393 | - echo '</div>'; | |
| 1494 | + echo '</div>'; // content | |
| 1495 | + echo '</div>'; // container | |
| 1496 | + echo '</div>'; // wp-reset-tabs | |
| 1394 | 1497 | |
| 1395 | - echo '<div style="display: none;" id="tab-support">'; | |
| 1396 | - $this->tab_support(); | |
| 1397 | - echo '</div>'; | |
| 1498 | + echo '</form>'; | |
| 1398 | 1499 | |
| 1399 | - echo '</div>'; // content | |
| 1400 | - echo '</div>'; // container | |
| 1401 | - echo '</div>'; // wp-reset-tabs | |
| 1500 | + echo '<div id="wpr-sidebar-ads">'; | |
| 1501 | + echo '<div id="wpr-ad">'; | |
| 1502 | + echo '<h3 class="textcenter"><b>Save time & money with WP Reset PRO! First WP dev tool for non-devs.</b></h3>'; | |
| 1503 | + echo '<p class="textcenter"><a href="#" data-feature="sidebar-logo" class="button-pro-feature textcenter"><img style="max-width: 90%;" src="' . esc_url($this->plugin_url) . '/img/wp-reset-logo.png" alt="WP Reset PRO" title="WP Reset PRO"></a></p>'; | |
| 1504 | + echo '<ul class="plain-list"> | |
| 1505 | + <li>25+ Reset Tools</li> | |
| 1506 | + <li>Plugins & Themes Collections</li> | |
| 1507 | + <li>Automatic Snapshots</li> | |
| 1508 | + <li>WP Reset Cloud, Dropbox & Google Drive support</li> | |
| 1509 | + <li>Emergency Recovery Script</li> | |
| 1510 | + <li>White-label Mode + Complete Plugin Rebranding</li> | |
| 1511 | + <li>Licenses & Sites Manager (remote SaaS dashboard)</li> | |
| 1512 | + <li>Friendly email support from plugin developers</li> | |
| 1513 | + </ul>'; | |
| 1514 | + echo '<p class="textcenter"><a href="#" data-feature="sidebar-button" class="button-pro-feature button button-primary">Get PRO now</a></p>'; | |
| 1515 | + echo '</div>'; | |
| 1402 | 1516 | |
| 1403 | - echo '</form>'; | |
| 1404 | - echo '</div>'; // wrap | |
| 1517 | + if (!defined('WPFSSL_OPTIONS_KEY')) { | |
| 1518 | + echo '<div id="wpfssl-ad">'; | |
| 1519 | + echo '<h3 class="textcenter"><b>Problems with SSL certificate?<br>Moving a site from HTTP to HTTPS?<br>Mixed content giving you troubles?<br><br><u>Fix all SSL problems with one plugin!</u></b></h3>'; | |
| 1520 | + echo '<p class="textcenter"><a href="#" class="textcenter install-wpfssl"><img style="max-width: 90%;" src="' . esc_url($this->plugin_url) . '/img/wp-force-ssl-logo.png" alt="WP Force SSL" title="WP Force SSL"></a></p>'; | |
| 1521 | + echo '<p class="textcenter"><br><a href="#" class="install-wpfssl button button-primary">Install & activate the free WP Force SSL plugin</a></p><p><a href="https://wordpress.org/plugins/wp-force-ssl/" target="_blank">WP Force SSL</a> is a free WP plugin maintained by the same team as this Maintenance plugin. It has <b>+150,000 users, 5-star rating</b>, and is hosted on the official WP repository.</p>'; | |
| 1522 | + echo '</div>'; | |
| 1523 | + } | |
| 1524 | + echo '</div>'; | |
| 1405 | 1525 | |
| 1406 | - // survey | |
| 1407 | - if ($this->is_survey_active('features')) { | |
| 1408 | - echo '<div id="survey-dialog" style="display: none;" title="Help us make WP Reset better for you"><span class="ui-helper-hidden-accessible"><input type="text"/></span>'; | |
| 1409 | - echo '<p class="subtitle"><b>What new features do you need the most?</b> Choose one or two;</p>'; | |
| 1526 | + echo '</div>'; // wrap | |
| 1527 | + } // plugin_page | |
| 1410 | 1528 | |
| 1411 | - $questions = array(); | |
| 1412 | - $questions[] = '<div class="question-wrapper" data-value="backup" title="Click to select/unselect answer">' . | |
| 1413 | - '<span class="dashicons dashicons-yes"></span>' . | |
| 1414 | - '<div class="question"><b>Off-site backups</b><br>' . | |
| 1415 | - '<i>Backup the site to Dropbox, FTP or Google Drive before using any tools</i></div>' . | |
| 1416 | - '</div>'; | |
| 1417 | 1529 | |
| 1418 | - $questions[] = '<div class="question-wrapper" data-value="wpmu" title="Click to select/unselect answer">' . | |
| 1419 | - '<span class="dashicons dashicons-yes"></span>' . | |
| 1420 | - '<div class="question"><b>WordPress Network (WPMU) compatibility</b><br>' . | |
| 1421 | - '<i>Full support & compatibility for all WP Reset tools for all sites in network</i></div>' . | |
| 1422 | - '</div>'; | |
| 1530 | + /** | |
| 1531 | + * Echoes all custom plugin notitications | |
| 1532 | + * | |
| 1533 | + * @return null | |
| 1534 | + */ | |
| 1535 | + private function custom_notifications() | |
| 1536 | + { | |
| 1537 | + $notice_shown = false; | |
| 1538 | + $meta = $this->get_meta(); | |
| 1539 | + $snapshots = $this->get_snapshots(); | |
| 1423 | 1540 | |
| 1424 | - $questions[] = '<div class="question-wrapper" data-value="nothing" title="Click to select/unselect answer">' . | |
| 1425 | - '<span class="dashicons dashicons-yes"></span>' . | |
| 1426 | - '<div class="question"><b>Don\'t add anything</b><br>' . | |
| 1427 | - '<i>WP Reset is perfect as is - I don\'t need any new features</i></div>' . | |
| 1428 | - '</div>'; | |
| 1541 | + // update to PRO after activating the license | |
| 1542 | + if ($this->license->is_active()) { | |
| 1543 | + echo '<div class="card notice-wrapper notice-info">'; | |
| 1544 | + echo '<h2>' . esc_html(__('Thank you for purchasing WP Reset PRO!', 'wp-reset')) . '</h2>'; | |
| 1545 | + echo '<p>Your license has been verified & activated.</b><br>To start using the PRO version, please follow these steps:'; | |
| 1546 | + echo '<ol>'; | |
| 1547 | + echo '<li><a href="https://dashboard.wpreset.com/pro-download/" target="_blank">Download</a> the latest version of the PRO plugin.</li>'; | |
| 1548 | + echo '<li>Go to <a href="' . esc_url(admin_url('plugin-install.php')) . '">Plugins - Add New - Upload Plugin</a> and upload the ZIP you just downloaded.</li>'; | |
| 1549 | + echo '<li>If asked to replace (overwrite) the free version - confirm it.</li>'; | |
| 1550 | + echo '<li>Activate the plugin.</li>'; | |
| 1551 | + echo '<li>That\'s it, no more steps.</li>'; | |
| 1552 | + echo '</ol>'; | |
| 1553 | + echo '</div>'; | |
| 1554 | + $notice_shown = true; | |
| 1555 | + } | |
| 1429 | 1556 | |
| 1430 | - $questions[] = '<div class="question-wrapper" data-value="nuclear" title="Click to select/unselect answer">' . | |
| 1431 | - '<span class="dashicons dashicons-yes"></span>' . | |
| 1432 | - '<div class="question"><b>Nuclear reset - run all tools at once</b><br>' . | |
| 1433 | - '<i>Besides resetting, delete all files and all other customizations with one click</i></div>' . | |
| 1434 | - '</div>'; | |
| 1557 | + // warn that WPR is not WPMU compatible | |
| 1558 | + if (false === $notice_shown && is_multisite()) { | |
| 1559 | + echo '<div class="card notice-wrapper notice-error">'; | |
| 1560 | + echo '<h2>' . esc_html__('WP Reset is not compatible with multisite!', 'wp-reset') . '</h2>'; | |
| 1561 | + WP_Reset_Utility::wp_kses_wf('<p>' . __('Please be careful when using WP Reset with multisite enabled. It\'s not recommended to reset the main site. Sub-sites should be OK. We\'re working on making it fully compatible with WP-MU. <b>Till then please be careful.</b> Thank you for understanding.', 'wp-reset') . '</p>'); | |
| 1562 | + echo '</div>'; | |
| 1563 | + $notice_shown = true; | |
| 1564 | + } | |
| 1435 | 1565 | |
| 1436 | - $questions[] = '<div class="question-wrapper" data-value="plugin-collections" title="Click to select/unselect answer">' . | |
| 1437 | - '<span class="dashicons dashicons-yes"></span>' . | |
| 1438 | - '<div class="question"><b>Install a set of plugins/themes after reset</b><br>' . | |
| 1439 | - '<i>Save lists of plugins/themes and automatically install them after resetting</i></div>' . | |
| 1440 | - '</div>'; | |
| 1566 | + // ask for review | |
| 1567 | + if ((!empty($meta['reset_count']) || !empty($snapshots) || current_time('timestamp', true) - $meta['first_install'] > DAY_IN_SECONDS) | |
| 1568 | + && false === $notice_shown | |
| 1569 | + && false == $this->get_dismissed_notices('rate') | |
| 1570 | + ) { | |
| 1571 | + echo '<div class="card notice-wrapper notice-info">'; | |
| 1572 | + echo '<h2>' . esc_html__('Please help us spread the word & keep the plugin up-to-date', 'wp-reset') . '</h2>'; | |
| 1573 | + WP_Reset_Utility::wp_kses_wf('<p>' . __('If you use & enjoy WP Reset, <b>please rate it on WordPress.org</b>. It only takes a second and helps us keep the plugin maintained. Thank you!', 'wp-reset') . '</p>'); | |
| 1574 | + echo '<p><a class="button-primary button" title="' . esc_html__('Rate WP Reset', 'wp-reset') . '" target="_blank" href="https://wordpress.org/support/plugin/wp-reset/reviews/#new-post">' . esc_html__('Rate the plugin ★★★★★', 'wp-reset') . '</a> <a href="#" class="wpr-dismiss-notice dismiss-notice-rate" data-notice="rate">' . esc_html__('I\'ve already rated it', 'wp-reset') . '</a></p>'; | |
| 1575 | + echo '</div>'; | |
| 1576 | + $notice_shown = true; | |
| 1577 | + } | |
| 1578 | + } // custom_notifications | |
| 1441 | 1579 | |
| 1442 | - $questions[] = '<div class="question-wrapper" data-value="change-wp-ver" title="Click to select/unselect answer">' . | |
| 1443 | - '<span class="dashicons dashicons-yes"></span>' . | |
| 1444 | - '<div class="question"><b>Change WordPress version - rollback or upgrade</b><br>' . | |
| 1445 | - '<i>Pick a version of WP you need (older or never) and switch to it with one click</i></div>' . | |
| 1446 | - '</div>'; | |
| 1447 | 1580 | |
| 1448 | - shuffle($questions); | |
| 1449 | - $questions[] = '<div class="question-wrapper" data-value="custom" title="Click to select/unselect answer">' . | |
| 1450 | - '<span class="dashicons dashicons-yes"></span>' . | |
| 1451 | - '<div class="question"><b>Something we missed?</b><br><i>Enter the feature you need below;</i>' . | |
| 1452 | - '<input type="text" class="custom-input"></div>' . | |
| 1453 | - '</div>'; | |
| 1581 | + /** | |
| 1582 | + * Echoes content for reset tab | |
| 1583 | + * | |
| 1584 | + * @return null | |
| 1585 | + */ | |
| 1586 | + private function tab_reset() | |
| 1587 | + { | |
| 1588 | + global $current_user, $wpdb; | |
| 1454 | 1589 | |
| 1455 | - echo implode(' ', $questions); | |
| 1590 | + echo '<div class="card">'; | |
| 1591 | + WP_Reset_Utility::wp_kses_wf($this->get_card_header(__('Please read carefully before proceeding', 'wp-reset'), 'reset-description', array('collapse_button' => true))); | |
| 1592 | + echo '<div class="card-body">'; | |
| 1593 | + echo '<p>The following table details what data will be deleted (reset or destroyed) when a selected reset tool is run. Please read it! '; | |
| 1594 | + echo 'If something is not clear <a href="#" class="change-tab" data-tab="4">contact support</a> before running any tools. It\'s better to ask than to be sorry!'; | |
| 1595 | + echo '</p>'; | |
| 1596 | + echo '<p><i class="dashicons dashicons-trash red tooltip" title="Tool WILL delete, reset or destroy the noted data" style="vertical-align: bottom;"></i> - tool WILL delete, reset or destroy the noted data<br>'; | |
| 1597 | + echo '<i class="dashicons dashicons-yes tooltip" title="Tool will NOT touch the noted data in any way" style="vertical-align: bottom;"></i> - tool will NOT touch the noted data in any way</p>'; | |
| 1456 | 1598 | |
| 1457 | - $current_user = wp_get_current_user(); | |
| 1458 | - echo '<div class="footer">'; | |
| 1459 | - echo '<input id="emailme" type="checkbox" value="' . $current_user->user_email . '"> <label for="emailme">Email me on ' . $current_user->user_email . ' when new features are added. We hate SPAM and never send it.</label><br>'; | |
| 1460 | - echo '<a data-survey="features" class="submit-survey button-primary button button-large" href="#">Add those features ASAP!</a>'; | |
| 1461 | - echo '<a href="#" class="dismiss-survey wpr-dismiss-notice" data-notice="survey-features" data-survey="features"><i>Close the survey and never show it again</i></a>'; | |
| 1462 | - echo '</div>'; | |
| 1599 | + echo '<table id="reset-details" class="">'; | |
| 1600 | + echo '<tr>'; | |
| 1601 | + echo '<th> </th>'; | |
| 1602 | + echo '<th>Options Reset<br><a data-feature="tool-options-reset" class="pro-feature" href="#"><span class="pro">PRO</span> tool</a></th>'; | |
| 1603 | + echo '<th nowrap>Site Reset</th>'; | |
| 1604 | + echo '<th>Nuclear Reset<br><a data-feature="tool-nuclear-reset" class="pro-feature" href="#"><span class="pro">PRO</span> tool</a></th>'; | |
| 1605 | + echo '</tr>'; | |
| 1463 | 1606 | |
| 1464 | - echo '</div>'; | |
| 1465 | - } // survey | |
| 1607 | + $rows = array(); | |
| 1608 | + $rows['Posts, pages & custom post types'] = array(0, 1, 1); | |
| 1609 | + $rows['Comments'] = array(0, 1, 1); | |
| 1610 | + $rows['Media'] = array(0, 1, 1); | |
| 1611 | + $rows['Media files'] = array(0, 0, 1); | |
| 1612 | + $rows['Users'] = array(0, 1, 1); | |
| 1613 | + $rows['User roles'] = array(1, 1, 1); | |
| 1614 | + $rows['Current user - ' . $current_user->user_login] = array(0, 0, 0); | |
| 1615 | + $rows['Widgets'] = array(1, 1, 1); | |
| 1616 | + $rows['Transients'] = array(1, 1, 1); | |
| 1617 | + $rows['Settings & options (from WP, plugins & themes)'] = array(1, 1, 1); | |
| 1618 | + $rows['Site title, WP address, site address,' . PHP_EOL . 'search engine visibility, timezone'] = array(0, 0, 0); | |
| 1619 | + $rows['Site language'] = array(0, 0, 1); | |
| 1620 | + $rows['Data in all default WP tables'] = array(0, 1, 1); | |
| 1621 | + $rows['Custom database tables with prefix ' . $wpdb->prefix] = array(0, 1, 1); | |
| 1622 | + $rows['Other database tables'] = array(0, 0, 0); | |
| 1623 | + $rows['Plugin files'] = array(0, 0, 1); | |
| 1624 | + $rows['MU plugin files'] = array(0, 0, 1); | |
| 1625 | + $rows['Drop-in files'] = array(0, 0, 1); | |
| 1626 | + $rows['Theme files'] = array(0, 0, 1); | |
| 1627 | + $rows['All files in uploads'] = array(0, 0, 1); | |
| 1628 | + $rows['Custom folders in wp-content'] = array(0, 0, 1); | |
| 1466 | 1629 | |
| 1467 | - if (!$this->is_webhooks_active()) { | |
| 1468 | - echo '<div id="webhooks-dialog" style="display: none;" title="Webhooks"><span class="ui-helper-hidden-accessible"><input type="text"/></span>'; | |
| 1469 | - echo '<div style="padding: 20px; font-size: 15px;">'; | |
| 1470 | - echo '<ul class="plain-list">'; | |
| 1471 | - echo '<li>Standard, platform-independant way of connecting WP to any 3rd party system</li>'; | |
| 1472 | - echo '<li>Supports actions - WP receives data on 3rd party events</li>'; | |
| 1473 | - echo '<li>And triggers - WP sends data on its events</li>'; | |
| 1474 | - echo '<li>Works wonders with Zapier</li>'; | |
| 1475 | - echo '<li>Compatible with any WordPress theme or plugin</li>'; | |
| 1476 | - echo '<li>Available from the official <a href="https://wordpress.org/plugins/wp-webhooks/" target="_blank">WP plugins repository</a></li>'; | |
| 1477 | - echo '</ul>'; | |
| 1478 | - echo '<p class="webhooks-footer"><a class="button button-primary" id="install-webhooks">Install WP Webhooks & connect WP to any 3rd party system</a></p>'; | |
| 1479 | - echo '</div>'; | |
| 1480 | - echo '</div>'; | |
| 1481 | - } | |
| 1482 | - } // plugin_page | |
| 1630 | + foreach ($rows as $tool => $opt) { | |
| 1631 | + echo '<tr>'; | |
| 1632 | + echo '<td>'; | |
| 1633 | + WP_Reset_Utility::wp_kses_wf(nl2br(esc_html($tool))); | |
| 1634 | + echo '</td>'; | |
| 1635 | + if (empty($opt[0])) { | |
| 1636 | + echo '<td><i class="dashicons dashicons-yes tooltip" title="Data will NOT be deleted, reset or modified"></i></td>'; | |
| 1637 | + } else { | |
| 1638 | + echo '<td><i class="dashicons dashicons-trash red tooltip" title="Data WILL BE deleted, reset or modified"></i></td>'; | |
| 1639 | + } | |
| 1640 | + if (empty($opt[1])) { | |
| 1641 | + echo '<td><i class="dashicons dashicons-yes tooltip" title="Data will NOT be deleted, reset or modified"></i></td>'; | |
| 1642 | + } else { | |
| 1643 | + echo '<td><i class="dashicons dashicons-trash red tooltip" title="Data WILL BE deleted, reset or modified"></i></td>'; | |
| 1644 | + } | |
| 1645 | + if (empty($opt[2])) { | |
| 1646 | + echo '<td><i class="dashicons dashicons-yes tooltip" title="Data will NOT be deleted, reset or modified"></i></td>'; | |
| 1647 | + } else { | |
| 1648 | + echo '<td><i class="dashicons dashicons-trash red tooltip" title="Data WILL BE deleted, reset or modified"></i></td>'; | |
| 1649 | + } | |
| 1650 | + echo '</tr>'; | |
| 1651 | + } // foreach $rows | |
| 1652 | + echo '<tfoot>'; | |
| 1653 | + echo '<tr>'; | |
| 1654 | + echo '<th> </th>'; | |
| 1655 | + echo '<th>Options Reset<br><a data-feature="tool-options-reset" class="pro-feature" href="#"><span class="pro">PRO</span> tool</a></th>'; | |
| 1656 | + echo '<th nowrap>Site Reset</th>'; | |
| 1657 | + echo '<th>Nuclear Reset<br><a data-feature="tool-nuclear-reset" class="pro-feature" href="#"><span class="pro">PRO</span> tool</a></th>'; | |
| 1658 | + echo '</tr>'; | |
| 1659 | + echo '</tfoot>'; | |
| 1660 | + echo '</table>'; | |
| 1483 | 1661 | |
| 1662 | + echo '<p><b>' . esc_html__('What happens when I run any Reset tool?', 'wp-reset') . '</b></p>'; | |
| 1663 | + echo '<ul class="plain-list">'; | |
| 1664 | + WP_Reset_Utility::wp_kses_wf('<li>' . __('remember, always <b>make a backup first</b> or use <a href="#" class="change-tab" data-tab="2">snapshots</a>', 'wp-reset') . '</li>'); | |
| 1665 | + echo '<li>' . esc_html__('you will have to confirm the action one more time', 'wp-reset') . '</li>'; | |
| 1666 | + echo '<li>' . esc_html__('see the table above to find out what exactly will be reset or deleted', 'wp-reset') . '</li>'; | |
| 1667 | + echo '<li>' . esc_html__('site title, WordPress URL, site URL, site language, search engine visibility and current user will always be restored', 'wp-reset') . '</li>'; | |
| 1668 | + echo '<li>' . esc_html__('you will be logged out, automatically logged back in and taken to the admin dashboard', 'wp-reset') . '</li>'; | |
| 1669 | + echo '<li>' . esc_html__('WP Reset plugin will be reactivated if that option is chosen', 'wp-reset') . '</li>'; | |
| 1670 | + echo '</ul>'; | |
| 1484 | 1671 | |
| 1485 | - /** | |
| 1486 | - * Echoes all custom plugin notitications | |
| 1487 | - * | |
| 1488 | - * @return null | |
| 1489 | - */ | |
| 1490 | - private function custom_notifications() | |
| 1491 | - { | |
| 1492 | - $notice_shown = false; | |
| 1493 | - $meta = $this->get_meta(); | |
| 1494 | - $snapshots = $this->get_snapshots(); | |
| 1672 | + echo '<p><b>' . esc_html__('WP-CLI Support', 'wp-reset') . '</b><br>'; | |
| 1673 | + /* translators: %s is replaced with the literal html "<code>wp help reset</code>" */ | |
| 1674 | + echo '' . sprintf(esc_html__('All tools available via GUI are available in WP-CLI as well. To get the list of commands run %s. Instead of the active user, the first user with admin privileges found in the database will be restored. ', 'wp-reset'), '<code>wp help reset</code>'); | |
| 1675 | + /* translators: %s is replaced with the literal html "<code>--yes</code>" */ | |
| 1676 | + echo sprintf(esc_html__('All actions have to be confirmed. If you want to skip confirmation use the standard %s option. Please be careful and backup first.', 'wp-reset'), '<code>--yes</code>') . '</p>'; | |
| 1495 | 1677 | |
| 1496 | - // warn that WPR is not WPMU compatible | |
| 1497 | - if (false === $notice_shown && is_multisite()) { | |
| 1498 | - echo '<div class="card notice-wrapper notice-error">'; | |
| 1499 | - echo '<h2>' . __('WP Reset is not compatible with multisite!', 'wp-reset') . '</h2>'; | |
| 1500 | - echo '<p>' . __('Please be careful when using WP Reset with multisite enabled. It\'s not recommended to reset the main site. Sub-sites should be OK. We\'re working on making it fully compatible with WP-MU. <b>Till then please be careful.</b> Thank you for understanding.', 'wp-reset') . '</p>'; | |
| 1501 | - echo '</div>'; | |
| 1502 | - $notice_shown = true; | |
| 1503 | - } | |
| 1678 | + echo '</div></div>'; // card description | |
| 1504 | 1679 | |
| 1505 | - // ask for review | |
| 1506 | - if ((!empty($meta['reset_count']) || !empty($snapshots) || current_time('timestamp', true) - $meta['first_install'] > DAY_IN_SECONDS) | |
| 1507 | - && false === $notice_shown | |
| 1508 | - && false == $this->get_dismissed_notices('rate') | |
| 1509 | - ) { | |
| 1510 | - echo '<div class="card notice-wrapper notice-info">'; | |
| 1511 | - echo '<h2>' . __('Please help us spread the word & keep the plugin up-to-date', 'wp-reset') . '</h2>'; | |
| 1512 | - echo '<p>' . __('If you use & enjoy WP Reset, <b>please rate it on WordPress.org</b>. It only takes a second and helps us keep the plugin maintained. Thank you!', 'wp-reset') . '</p>'; | |
| 1513 | - echo '<p><a class="button-primary button" title="' . __('Rate WP Reset', 'wp-reset') . '" target="_blank" href="https://wordpress.org/support/plugin/wp-reset/reviews/#new-post">' . __('Rate the plugin ★★★★★', 'wp-reset') . '</a> <a href="#" class="wpr-dismiss-notice dismiss-notice-rate" data-notice="rate">' . __('I\'ve already rated it', 'wp-reset') . '</a></p>'; | |
| 1514 | - echo '</div>'; | |
| 1515 | - $notice_shown = true; | |
| 1516 | - } | |
| 1517 | - } // custom_notifications | |
| 1680 | + $theme = wp_get_theme(); | |
| 1681 | + $theme_name = $theme->get('Name'); | |
| 1682 | + if (empty($theme_name)) { | |
| 1683 | + $theme_name = '<i>no active theme</i>'; | |
| 1684 | + } | |
| 1685 | + $active_plugins = get_option('active_plugins'); | |
| 1518 | 1686 | |
| 1687 | + // options reset | |
| 1688 | + echo '<div class="card">'; | |
| 1689 | + WP_Reset_Utility::wp_kses_wf($this->get_card_header(__('Options Reset', 'wp-reset'), 'tool-options-reset', array('collapse_button' => true, 'pro' => true))); | |
| 1690 | + echo '<div class="card-body">'; | |
| 1691 | + echo '<p>Options table will be reset to default values meaning all WP core settings, widgets, theme settings and customizations, and plugin settings will be gone. Other content and files will not be touched including posts, pages, custom post types, comments and other data stored in separate tables. Site URL and name will be kept as well. Please see the <a href="#reset-details" class="scrollto">table above</a> for details.</p>'; | |
| 1519 | 1692 | |
| 1520 | - /** | |
| 1521 | - * Echoes content for reset tab | |
| 1522 | - * | |
| 1523 | - * @return null | |
| 1524 | - */ | |
| 1525 | - private function tab_reset() | |
| 1526 | - { | |
| 1527 | - global $current_user, $wpdb; | |
| 1693 | + WP_Reset_Utility::wp_kses_wf($this->get_tool_icons(false, true)); | |
| 1528 | 1694 | |
| 1529 | - echo '<div class="card" id="card-description">'; | |
| 1530 | - echo '<h4>'; | |
| 1531 | - echo __('Please read carefully before proceeding', 'wp-reset'); | |
| 1532 | - echo '<div class="card-header-right"><a class="toggle-card" href="#" title="' . __('Collapse / expand box', 'wp-reset') . '"><span class="dashicons dashicons-arrow-up-alt2"></span></a></div>'; | |
| 1533 | - echo '</h4>'; | |
| 1534 | - echo '<div class="card-body">'; | |
| 1535 | - echo '<p><b class="red">' . __('Resetting will delete:', 'wp-reset') . '</b></p>'; | |
| 1536 | - echo '<ul class="plain-list">'; | |
| 1537 | - echo '<li>' . __('all posts, pages, custom post types, comments, media entries, users', 'wp-reset') . '</li>'; | |
| 1538 | - echo '<li>' . __('all default WP database tables', 'wp-reset') . '</li>'; | |
| 1539 | - echo '<li>' . sprintf(__('all custom database tables that have the same prefix "%s" as default tables in this installation', 'wp-reset'), $wpdb->prefix) . '</li>'; | |
| 1540 | - echo '<li>' . __('always <a href="#" class="create-new-snapshot">create a snapshot</a> or a full backup, so you can restore it later', 'wp-reset') . '</li>'; | |
| 1541 | - echo '</ul>'; | |
| 1695 | + echo '<p><br><label for="reset-options-reactivate-theme"><input type="checkbox" id="reset-options-reactivate-theme" value="1"> ' . esc_html__('Reactivate current theme', 'wp-reset') . ' - ' . esc_html($theme_name) . '</label></p>'; | |
| 1696 | + echo '<p><label for="reset-options-reactivate-plugins"><input type="checkbox" id="reset-options-reactivate-plugins" value="1"> Reactivate ' . esc_attr(sizeof($active_plugins)) . ' currently active plugin' . (sizeof($active_plugins) != 1 ? 's' : '') . ' (WP Reset will reactivate by default)</label></p>'; | |
| 1542 | 1697 | |
| 1543 | - echo '<p><b class="green">' . __('Resetting will not delete:', 'wp-reset') . '</b></p>'; | |
| 1544 | - echo '<ul class="plain-list">'; | |
| 1545 | - echo '<li>' . __('media files - they\'ll remain in the <i>wp-uploads</i> folder but will no longer be listed under Media', 'wp-reset'); | |
| 1546 | - echo __('; use the <a href="#tool-delete-uploads" data-tab="1" class="change-tab">Clean Uploads Folder</a> tool to remove media files', 'wp-reset') . '</li>'; | |
| 1547 | - echo '<li>' . __('no files are touched; plugins, themes, uploads - everything stays', 'wp-reset'); | |
| 1548 | - echo __('; if needed use the <a href="#tool-delete-themes" class="change-tab" data-tab="1">Delete Themes</a> & <a href="#tool-delete-plugins" class="change-tab" data-tab="1">Delete Plugins</a> tools', 'wp-reset') . '</li>'; | |
| 1549 | - echo '<li>' . __('site title, WordPress address, site address, site language and search engine visibility settings', 'wp-reset') . '</li>'; | |
| 1550 | - echo '<li>' . sprintf(__('logged in user "%s" will be restored with the current password', 'wp-reset'), $current_user->user_login) . '</li>'; | |
| 1551 | - echo '</ul>'; | |
| 1698 | + echo '<p class="mb0"><a class="button button-delete button-pro-feature" href="#">Reset all options - <span data-feature="tool-options-reset" class="pro-feature"><span class="pro">PRO</span> tool</span></a></p>'; | |
| 1699 | + echo '</div>'; | |
| 1700 | + echo '</div>'; // options reset | |
| 1552 | 1701 | |
| 1553 | - echo '<p><b>' . __('What happens when I click the Reset button?', 'wp-reset') . '</b></p>'; | |
| 1554 | - echo '<ul class="plain-list">'; | |
| 1555 | - echo '<li>' . __('remember, always <a href="#" class="create-new-snapshot">make a snapshot</a> or a full backup first', 'wp-reset') . '</li>'; | |
| 1556 | - echo '<li>' . __('you will have to confirm the action one more time', 'wp-reset') . '</li>'; | |
| 1557 | - echo '<li>' . __('everything will be reset; see bullets above for details', 'wp-reset') . '</li>'; | |
| 1558 | - echo '<li>' . __('site title, WordPress address, site address, site language, search engine visibility and current user will be restored', 'wp-reset') . '</li>'; | |
| 1559 | - echo '<li>' . __('you will be logged out, automatically logged in and taken to the admin dashboard', 'wp-reset') . '</li>'; | |
| 1560 | - echo '<li>' . __('WP Reset plugin will be reactivated if that option is chosen in the <a href="#card-reset">post-reset options</a>', 'wp-reset') . '</li>'; | |
| 1561 | - echo '</ul>'; | |
| 1702 | + echo '<div class="card">'; | |
| 1703 | + WP_Reset_Utility::wp_kses_wf($this->get_card_header(__('Site Reset', 'wp-reset'), 'tool-site-reset', array('collapse_button' => true))); | |
| 1704 | + echo '<div class="card-body">'; | |
| 1705 | + echo '<p><label for="reactivate-theme"><input name="wpr-post-reset[reactivate_theme]" type="checkbox" id="reactivate-theme" value="1"> ' . esc_html__('Reactivate current theme', 'wp-reset') . ' - ' . esc_html($theme->get('Name')) . '</label></p>'; | |
| 1706 | + echo '<p><label for="reactivate-wpreset"><input name="wpr-post-reset[reactivate_wpreset]" type="checkbox" id="reactivate-wpreset" value="1" checked> ' . esc_html__('Reactivate WP Reset plugin', 'wp-reset') . '</label></p>'; | |
| 1562 | 1707 | |
| 1563 | - echo '<p><b>' . __('WP-CLI Support', 'wp-reset') . '</b><br>'; | |
| 1564 | - echo '' . sprintf(__('All tools available via GUI are available in WP-CLI as well. To get the list of commands run %s. Instead of the active user, the first user with admin privileges found in the database will be restored. ', 'wp-reset'), '<code>wp help reset</code>'); | |
| 1565 | - echo sprintf(__('All actions have to be confirmed. If you want to skip confirmation use the standard %s option. Please be careful - there is NO UNDO.', 'wp-reset'), '<code>--yes</code>') . '</p>'; | |
| 1708 | + echo '<p><label for="reactivate-plugins"><input name="wpr-post-reset[reactivate_plugins]" type="checkbox" id="reactivate-plugins" value="1"> ' . esc_html__('Reactivate all currently active plugins', 'wp-reset') . '</label></p>'; | |
| 1709 | + WP_Reset_Utility::wp_kses_wf('<p>' . __('Type <b>reset</b> in the confirmation field to confirm the reset and then click the "Reset WordPress" button.<br>Always <a href="#" class="create-new-snapshot" data-description="Before resetting the site">create a snapshot</a> before resetting if you want to be able to undo.', 'wp-reset') . '</p>'); | |
| 1566 | 1710 | |
| 1567 | - echo '<p><b>' . __('WP Webhooks Support', 'wp-reset') . '</b><br>'; | |
| 1568 | - echo 'All WP Reset tools are integrated with <a href="https://wordpress.org/plugins/wp-webhooks/" target="_blank">WP Webhooks</a> and available as (receive data) actions. Webhooks are a standard, platform-independent way of connecting WordPress to any 3rd party system. This <a href="https://underconstructionpage.com/wp-webhooks-connect-integrate-wordpress/" target="_blank">article</a> has more info, videos and use-cases so you can see just how powerful and easy to use webhooks are.<br>'; | |
| 1569 | - if ($this->is_webhooks_active()) { | |
| 1570 | - echo 'WP Webhooks are active. Make sure you enable WP Reset actions in <a href="' . admin_url('options-general.php?page=wp-webhooks-pro&wpwhvrs=settings') . '">settings</a>.'; | |
| 1571 | - } else { | |
| 1572 | - echo '<a href="#" class="open-webhooks-dialog">Install WP Webhooks & WPR addon</a> to automate your workflow, develop faster and connect WordPress to any web app or 3rd party system.'; | |
| 1573 | - } | |
| 1574 | - echo '</p></div></div>'; // card description | |
| 1711 | + wp_nonce_field('wp-reset'); | |
| 1712 | + /* translators: %s is replaced with "reset"*/ | |
| 1713 | + echo '<p class="mb0"><input id="wp_reset_confirm" type="text" name="wp_reset_confirm" placeholder="' . esc_attr(sprintf(__('Type in: %s', 'wp-reset'), '"reset"')) . '" value="" autocomplete="off"> '; | |
| 1714 | + echo '<a id="wp_reset_submit" class="button button-delete">' . esc_html__('Reset Site', 'wp-reset') . '</a>'; | |
| 1715 | + WP_Reset_Utility::wp_kses_wf($this->get_snapshot_button('reset-wordpress', 'Before resetting the site')); | |
| 1716 | + echo '</p>'; | |
| 1717 | + echo '</div>'; | |
| 1718 | + echo '</div>'; // card reset | |
| 1575 | 1719 | |
| 1576 | - $theme = wp_get_theme(); | |
| 1720 | + // nuclear reset | |
| 1721 | + echo '<div class="card">'; | |
| 1722 | + WP_Reset_Utility::wp_kses_wf($this->get_card_header(__('Nuclear Site Reset', 'wp-reset'), 'tool-nuclear-reset', array('collapse_button' => true, 'pro' => true))); | |
| 1723 | + echo '<div class="card-body">'; | |
| 1724 | + echo '<p>All data will be deleted or reset (see the <a href="#reset-details" class="scrollto">explanation table</a> for details). All data stored in the database including custom tables with <code>' . esc_html($wpdb->prefix) . '</code> prefix, as well as all files in wp-content, themes and plugins folders. The only thing restored after reset will be your user account so you can log in again, and the basic WP settings like site URL. Please see the <a href="#reset-details" class="scrollto">table above</a> for details.</p>'; | |
| 1577 | 1725 | |
| 1578 | - echo '<div class="card" id="card-reset">'; | |
| 1579 | - echo '<h4>' . __('Site Reset', 'wp-reset'); | |
| 1580 | - echo '<div class="card-header-right"><a class="toggle-card" href="#" title="' . __('Collapse / expand box', 'wp-reset') . '"><span class="dashicons dashicons-arrow-up-alt2"></span></a></div>'; | |
| 1581 | - echo '</h4>'; | |
| 1582 | - echo '<div class="card-body">'; | |
| 1583 | - echo '<p><label for="reactivate-theme"><input name="wpr-post-reset[reactivate_theme]" type="checkbox" id="reactivate-theme" value="1"> ' . __('Reactivate current theme', 'wp-reset') . ' - ' . $theme->get('Name') . '</label></p>'; | |
| 1584 | - echo '<p><label for="reactivate-wpreset"><input name="wpr-post-reset[reactivate_wpreset]" type="checkbox" id="reactivate-wpreset" value="1" checked> ' . __('Reactivate WP Reset plugin', 'wp-reset') . '</label></p>'; | |
| 1585 | - if ($this->is_webhooks_active()) { | |
| 1586 | - echo '<p><label for="reactivate-webhooks"><input name="wpr-post-reset[reactivate_webhooks]" type="checkbox" id="reactivate-webhooks" value="1" checked> ' . __('Reactivate WP Webhooks plugin', 'wp-reset') . '</label></p>'; | |
| 1587 | - } | |
| 1588 | - echo '<p><label for="reactivate-plugins"><input name="wpr-post-reset[reactivate_plugins]" type="checkbox" id="reactivate-plugins" value="1"> ' . __('Reactivate all currently active plugins', 'wp-reset') . '</label></p>'; | |
| 1589 | - if ($this->is_webhooks_active()) { | |
| 1590 | - echo '<p><a href="' . admin_url('options-general.php?page=wp-webhooks-pro&wpwhvrs=settings') . '">Configure WP Webhooks</a> to run additional actions after reset, or connect to any 3rd party system.</p>'; | |
| 1591 | - } else { | |
| 1592 | - echo '<p>To run additional actions after reset or automate a complex workflow <a href="#" class="open-webhooks-dialog">install WP Webhooks & WPR addon</a>. It\'s a standard, platform-independent way of connecting WordPress to any web app. This <a href="https://www.youtube.com/watch?v=m8XDFXCNP9g" target="_blank">short video</a> explains it well.</p>'; | |
| 1593 | - } | |
| 1594 | - echo '<p><br>' . __('Type <b>reset</b> in the confirmation field to confirm the reset and then click the "Reset WordPress" button.<br>Always <a href="#" class="create-new-snapshot" data-description="Before resetting the site">create a snapshot</a> before resetting if you want to be able to undo.', 'wp-reset') . '</p>'; | |
| 1726 | + WP_Reset_Utility::wp_kses_wf($this->get_tool_icons(true, true)); | |
| 1595 | 1727 | |
| 1596 | - wp_nonce_field('wp-reset'); | |
| 1597 | - echo '<p><input id="wp_reset_confirm" type="text" name="wp_reset_confirm" placeholder="' . esc_attr__('Type in "reset"', 'wp-reset') . '" value="" autocomplete="off"> '; | |
| 1598 | - echo '<a id="wp_reset_submit" class="button button-delete">' . __('Reset Site', 'wp-reset') . '</a>' . $this->get_snapshot_button('reset-wordpress', 'Before resetting the site') . '</p>'; | |
| 1599 | - echo '</div>'; | |
| 1600 | - echo '</div>'; | |
| 1601 | - } // tab_reset | |
| 1728 | + if (is_multisite()) { | |
| 1729 | + echo '<p class="mb0 wpmu-error">This tool is <b>not compatible</b> with WP multisite (WPMU). Using it would delete files shared by multiple sites in the WP network.</p>'; | |
| 1730 | + } else { | |
| 1731 | + echo '<p><br><label for="nuclear-reset-reactivate-wpreset"><input type="checkbox" id="nuclear-reset-reactivate-wpreset" value="1" checked> ' . esc_html__('Reactivate WP Reset plugin', 'wp-reset') . '</label></p>'; | |
| 1602 | 1732 | |
| 1733 | + WP_Reset_Utility::wp_kses_wf('<p>' . __('Type <b>reset</b> in the confirmation field to confirm the reset and then click the "Reset WordPress & Delete All Custom Files & Data" button. <b>There is NO UNDO.', 'wp-reset') . '</b></p>'); | |
| 1603 | 1734 | |
| 1604 | - /** | |
| 1605 | - * Echoes content for tools tab | |
| 1606 | - * | |
| 1607 | - * @return null | |
| 1608 | - */ | |
| 1609 | - private function tab_tools() | |
| 1610 | - { | |
| 1611 | - global $wpdb; | |
| 1735 | + echo '<p class="mb0"><input id="nuclear_reset_confirm" type="text" placeholder="' . esc_html__('Type in "reset"', 'wp-reset') . '" value="" autocomplete="off"> '; | |
| 1736 | + echo '<a class="button button-delete button-pro-feature" href="#">' . esc_html__('Reset WordPress & Delete All Custom Files & Data', 'wp-reset') . ' - <span data-feature="tool-nuclear-reset" class="pro-feature"><span class="pro">PRO</span> tool</span></a></p>'; | |
| 1737 | + } | |
| 1738 | + echo '</div>'; | |
| 1739 | + echo '</div>'; // nuclear reset | |
| 1740 | + } // tab_reset | |
| 1612 | 1741 | |
| 1613 | - $tools = array( | |
| 1614 | - 'tool-delete-transients' => 'Delete Transients', | |
| 1615 | - 'tool-delete-uploads' => 'Clean Uploads Folder', | |
| 1616 | - 'tool-reset-theme-options' => 'Reset Theme Options', | |
| 1617 | - 'tool-delete-themes' => 'Delete Themes', | |
| 1618 | - 'tool-delete-plugins' => 'Delete Plugins', | |
| 1619 | - 'tool-empty-delete-custom-tables' => 'Empty or Delete Custom Tables', | |
| 1620 | - 'tool-delete-htaccess' => 'Delete .htaccess File' | |
| 1621 | - ); | |
| 1622 | 1742 | |
| 1623 | - echo '<div class="card">'; | |
| 1624 | - echo $this->get_card_header(__('Index of Tools', 'wp-reset'), 'iot', true, false); | |
| 1625 | - echo '<div class="card-body">'; | |
| 1626 | - $i = 0; | |
| 1627 | - $tools_nb = sizeof($tools); | |
| 1628 | - foreach ($tools as $tool_id => $tool_name) { | |
| 1629 | - if ($i == 0) { | |
| 1630 | - echo '<div class="half">'; | |
| 1631 | - echo '<ul class="mb0 plain-list">'; | |
| 1632 | - } | |
| 1633 | - if ($i == ceil($tools_nb / 2)) { | |
| 1743 | + /** | |
| 1744 | + * Echoes content for tools tab | |
| 1745 | + * | |
| 1746 | + * @return null | |
| 1747 | + */ | |
| 1748 | + private function tab_tools() | |
| 1749 | + { | |
| 1750 | + global $wpdb, $wp_version, $wp_filesystem; | |
| 1751 | + $this->wp_init_filesystem(); | |
| 1752 | + | |
| 1753 | + $tools = array( | |
| 1754 | + 'tool-reset-theme-options' => 'Reset Theme Options', | |
| 1755 | + '_tool-reset-user-roles' => 'Reset User Roles', | |
| 1756 | + 'tool-delete-transients' => 'Delete Transients', | |
| 1757 | + 'tool-purge-cache' => 'Purge Cache', | |
| 1758 | + 'tool-delete-local-data' => 'Delete Local Data', | |
| 1759 | + '_tool-delete-content' => 'Delete Content', | |
| 1760 | + '_tool-delete-widgets' => 'Delete Widgets', | |
| 1761 | + 'tool-delete-themes' => 'Delete Themes', | |
| 1762 | + 'tool-delete-plugins' => 'Delete Plugins', | |
| 1763 | + '_tool-delete-mu-plugins-dropins' => 'Delete MU Plugins & Drop-ins', | |
| 1764 | + 'tool-delete-uploads' => 'Clean uploads Folder', | |
| 1765 | + '_tool-delete-wp-content' => 'Clean wp-content Folder', | |
| 1766 | + 'tool-empty-delete-custom-tables' => 'Empty or Delete Custom Tables', | |
| 1767 | + '_tool-switch-wp-version' => 'Switch WP Version', | |
| 1768 | + 'tool-delete-htaccess' => 'Delete .htaccess File' | |
| 1769 | + ); | |
| 1770 | + | |
| 1771 | + echo '<div class="card">'; | |
| 1772 | + WP_Reset_Utility::wp_kses_wf($this->get_card_header(__('Index of Tools', 'wp-reset'), 'iot', array('collapse_button' => true))); | |
| 1773 | + echo '<div class="card-body">'; | |
| 1774 | + $i = 0; | |
| 1775 | + $tools_nb = sizeof($tools); | |
| 1776 | + foreach ($tools as $tool_id => $tool_name) { | |
| 1777 | + if ($i == 0) { | |
| 1778 | + echo '<div class="third">'; | |
| 1779 | + echo '<ul class="mb0 plain-list">'; | |
| 1780 | + } | |
| 1781 | + if ($i == 5 || $i == 10) { | |
| 1782 | + echo '</div>'; | |
| 1783 | + echo '<div class="third">'; | |
| 1784 | + echo '<ul class="mb0 plain-list">'; | |
| 1785 | + } | |
| 1786 | + | |
| 1787 | + if ($tool_id[0] == '_') { | |
| 1788 | + $tool_id = ltrim($tool_id, '_'); | |
| 1789 | + echo '<li><a title="Jump to ' . esc_attr($tool_name) . ' tool" class="scrollto" href="#' . esc_attr($tool_id) . '">' . esc_html($tool_name) . '</a> <a class="pro-feature" href="#" data-feature="' . esc_attr($tool_id) . '"><span class="pro">PRO</span> tool</a></li>'; | |
| 1790 | + } else { | |
| 1791 | + echo '<li><a title="Jump to ' . esc_attr($tool_name) . ' tool" class="scrollto" href="#' . esc_attr($tool_id) . '">' . esc_html($tool_name) . '</a></li>'; | |
| 1792 | + } | |
| 1793 | + | |
| 1794 | + if ($i == $tools_nb - 1) { | |
| 1795 | + echo '</ul>'; | |
| 1796 | + echo '</div>'; // third | |
| 1797 | + } | |
| 1798 | + $i++; | |
| 1799 | + } // foreach tools | |
| 1634 | 1800 | echo '</div>'; |
| 1635 | - echo '<div class="half">'; | |
| 1636 | - echo '<ul class="mb0 plain-list">'; | |
| 1637 | - } | |
| 1801 | + echo '</div>'; | |
| 1638 | 1802 | |
| 1639 | - echo '<li><a title="Jump to ' . $tool_name . ' tool" class="scrollto" href="#' . $tool_id . '">' . $tool_name . '</a></li>'; | |
| 1803 | + echo '<div class="card">'; | |
| 1804 | + WP_Reset_Utility::wp_kses_wf($this->get_card_header(__('Reset Theme Options', 'wp-reset'), 'tool-reset-theme-options', array('iot_button' => true, 'collapse_button' => true))); | |
| 1805 | + echo '<div class="card-body">'; | |
| 1806 | + WP_Reset_Utility::wp_kses_wf('<p>' . __('All options (mods) for all themes will be reset; not just for the active theme. The tool works only for themes that use the <a href="https://codex.wordpress.org/Theme_Modification_API" target="_blank">WordPress theme modification API</a>. If options are saved in some other, custom way they won\'t be reset.<br> Always <a href="#" class="create-new-snapshot" data-description="Before resetting theme options">create a snapshot</a> before using this tool if you want to be able to undo its actions.', 'wp-reset') . '</p>'); | |
| 1807 | + WP_Reset_Utility::wp_kses_wf($this->get_tool_icons(false, true)); | |
| 1808 | + echo '<p class="mb0"><a data-confirm-title="Are you sure you want to reset all theme options?" data-btn-confirm="Reset theme options" data-text-wait="Resetting theme options. Please wait." data-text-confirm="All options (mods) for all themes will be reset. Always ' . esc_attr('<a data-description="Before resetting theme options" href="#" class="create-new-snapshot">create a snapshot</a> if you want to be able to undo') . '." data-text-done="Options for %n themes have been reset." data-text-done-singular="Options for one theme have been reset." class="button button-delete" href="#" id="reset-theme-options">Reset theme options</a>'; | |
| 1809 | + WP_Reset_Utility::wp_kses_wf($this->get_snapshot_button('reset-theme-options', 'Before resetting theme options') . '</p>'); | |
| 1810 | + echo '</div>'; | |
| 1811 | + echo '</div>'; // reset theme options | |
| 1640 | 1812 | |
| 1641 | - if ($i == $tools_nb - 1) { | |
| 1642 | - echo '</ul>'; | |
| 1643 | - echo '</div>'; // half | |
| 1644 | - } | |
| 1645 | - $i++; | |
| 1646 | - } // foreach tools | |
| 1647 | - echo '</div>'; | |
| 1648 | - echo '</div>'; | |
| 1813 | + echo '<div class="card default-collapsed">'; | |
| 1814 | + WP_Reset_Utility::wp_kses_wf($this->get_card_header(__('Reset User Roles', 'wp-reset'), 'tool-reset-user-roles', array('collapse_button' => true, 'iot_button' => true, 'pro' => true))); | |
| 1815 | + echo '<div class="card-body">'; | |
| 1816 | + echo '<p>Default user roles\' capatibilities will be reset to their default values. All custom roles will be deleted.<br>Users that had custom roles will not be assigned any default ones and might not be able to log in. Roles have to be (re)assigned to them manually.</p>'; | |
| 1817 | + WP_Reset_Utility::wp_kses_wf($this->get_tool_icons(false, true)); | |
| 1818 | + echo '<p class="mb0"><a class="button button-delete button-pro-feature" href="#">Reset user roles - <span data-feature="tool-reset-user-roles" class="pro-feature"><span class="pro">PRO</span> tool</span></a>'; | |
| 1819 | + WP_Reset_Utility::wp_kses_wf($this->get_snapshot_button('reset-user-roles', 'Before resetting user roles') . '</p>'); | |
| 1820 | + echo '</div>'; | |
| 1821 | + echo '</div>'; // reset user roles | |
| 1649 | 1822 | |
| 1650 | - echo '<div class="card">'; | |
| 1651 | - echo $this->get_card_header(__('Delete Transients', 'wp-reset'), 'tool-delete-transients', true, true); | |
| 1652 | - echo '<div class="card-body">'; | |
| 1653 | - echo '<p>All transient related database entries will be deleted. Including expired and non-expired transients, and orphaned transient timeout entries.<br>Always <a href="#" data-description="Before deleting transients" class="create-new-snapshot">create a snapshot</a> before using this tool if you want to be able to undo its actions.</p>'; | |
| 1654 | - echo $this->get_tool_icons(false, true); | |
| 1655 | - echo '<p class="mb0"><a data-confirm-title="Are you sure you want to delete all transients?" data-btn-confirm="Delete all transients" data-text-wait="Deleting transients. Please wait." data-text-confirm="All database entries related to transients will be deleted. Always ' . esc_attr('<a data-description="Before deleting transients" href="#" class="create-new-snapshot">create a snapshot</a> if you want to be able to undo') . '." data-text-done="%n transient database entries have been deleted." data-text-done-singular="One transient database entry has been deleted." class="button button-delete" href="#" id="delete-transients">Delete all transients</a>' . $this->get_snapshot_button('delete-transients', 'Before deleting transients') . '</p>'; | |
| 1656 | - echo '</div>'; | |
| 1657 | - echo '</div>'; | |
| 1823 | + echo '<div class="card">'; | |
| 1824 | + WP_Reset_Utility::wp_kses_wf($this->get_card_header(__('Delete Transients', 'wp-reset'), 'tool-delete-transients', array('iot_button' => true, 'collapse_button' => true))); | |
| 1825 | + echo '<div class="card-body">'; | |
| 1826 | + echo '<p>All transient related database entries will be deleted. Including expired and non-expired transients, and orphaned transient timeout entries.<br>Always <a href="#" data-description="Before deleting transients" class="create-new-snapshot">create a snapshot</a> before using this tool if you want to be able to undo its actions.</p>'; | |
| 1827 | + WP_Reset_Utility::wp_kses_wf($this->get_tool_icons(false, true)); | |
| 1828 | + echo '<p class="mb0"><a data-confirm-title="Are you sure you want to delete all transients?" data-btn-confirm="Delete all transients" data-text-wait="Deleting transients. Please wait." data-text-confirm="All database entries related to transients will be deleted. Always ' . esc_attr('<a data-description="Before deleting transients" href="#" class="create-new-snapshot">create a snapshot</a> if you want to be able to undo') . '." data-text-done="%n transient database entries have been deleted." data-text-done-singular="One transient database entry has been deleted." class="button button-delete" href="#" id="delete-transients">Delete all transients</a>'; | |
| 1829 | + WP_Reset_Utility::wp_kses_wf($this->get_snapshot_button('delete-transients', 'Before deleting transients') . '</p>'); | |
| 1830 | + echo '</div>'; | |
| 1831 | + echo '</div>'; // delete transients | |
| 1658 | 1832 | |
| 1659 | - $upload_dir = wp_upload_dir(date('Y/m'), true); | |
| 1660 | - $upload_dir['basedir'] = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $upload_dir['basedir']); | |
| 1833 | + echo '<div class="card">'; | |
| 1834 | + WP_Reset_Utility::wp_kses_wf($this->get_card_header(__('Purge Cache', 'wp-reset'), 'tool-purge-cache', array('collapse_button' => true, 'iot_button' => true))); | |
| 1835 | + echo '<div class="card-body">'; | |
| 1836 | + echo '<p>All cache objects stored in both files and the database will be deleted. Along with WP object cache and transients, cache from the following plugins will be purged: W3 Total Cache, WP Cache, LiteSpeed Cache, Endurance Page Cache, SiteGround Optimizer, WP Fastest Cache and Swift Performance.</p>'; | |
| 1837 | + WP_Reset_Utility::wp_kses_wf($this->get_tool_icons(true, true)); | |
| 1838 | + echo '<p class="mb0"><a data-confirm-title="Are you sure you want to purge all cache?" data-btn-confirm="Purge cache" data-text-wait="Purging cache. Please wait." data-text-confirm="All cache objects will be deleted. There is NO UNDO. WP Reset does not make any file backups." data-text-done="Cache has been purged." data-text-done-singular="Cache has been purged." class="button button-delete" href="#" id="purge-cache">Purge cache</a></p>'; | |
| 1839 | + echo '</div>'; | |
| 1840 | + echo '</div>'; // purge cache | |
| 1661 | 1841 | |
| 1662 | - echo '<div class="card">'; | |
| 1663 | - echo $this->get_card_header(__('Clean Uploads Folder', 'wp-reset'), 'tool-delete-uploads', true, true); | |
| 1664 | - echo '<div class="card-body">'; | |
| 1665 | - echo '<p>' . __('All files in <code>' . $upload_dir['basedir'] . '</code> folder will be deleted. Including folders and subfolders, and files in subfolders. Files associated with <a href="' . admin_url('upload.php') . '">media</a> entries will be deleted too.<br><b>There is NO UNDO. WP Reset does not make any file backups.</b>', 'wp-reset') . '</p>'; | |
| 1842 | + echo '<div class="card">'; | |
| 1843 | + WP_Reset_Utility::wp_kses_wf($this->get_card_header(__('Delete Local Data', 'wp-reset'), 'tool-delete-local-data', array('collapse_button' => true, 'iot_button' => true))); | |
| 1844 | + echo '<div class="card-body">'; | |
| 1845 | + echo '<p>All local storage and session storage data will be deleted. Cookies without a custom set path will be deleted as well. WP cookies are not touched, with Delete Local Data button.<br>Deleting all WordPress cookies (including authentication cookies) will delete all WP related cookies and user (you) will be logged out on the next page reload. | |
| 1846 | + </p>'; | |
| 1847 | + WP_Reset_Utility::wp_kses_wf($this->get_tool_icons(false, false)); | |
| 1848 | + echo '<p class="mb0"><a data-confirm-title="Are you sure you want to delete all local data?" data-btn-confirm="Delete local data" data-text-wait="Deleting local data. Please wait." data-text-confirm="All local data; cookies, local storage and local session will be deleted. There is NO UNDO. WP Reset does not make backups of local data." data-text-done="%n local data objects have been deleted." data-text-done-singular="One local data object has been deleted." class="button button-delete" href="#" id="delete-local-data">Delete local data</a><a data-confirm-title="Are you sure you want to delete all WP related cookies?" data-btn-confirm="Delete all WordPress cookies" data-text-wait="Deleting WP cookies. Please wait." data-text-confirm="All WP cookies including authentication ones will be deleted. You will have to log in again. There is NO UNDO. WP Reset does not make backups of cookies." data-text-done="All WP cookies have been deleted. Reload the page to login again." data-text-done-singular="All WP cookies have been deleted. Reload the page to login again." class="button button-delete" href="#" id="delete-wp-cookies">Delete all WordPress cookies</a></p>'; | |
| 1849 | + echo '</div>'; | |
| 1850 | + echo '</div>'; // delete local data | |
| 1666 | 1851 | |
| 1667 | - echo $this->get_tool_icons(true, false); | |
| 1852 | + echo '<div class="card default-collapsed">'; | |
| 1853 | + WP_Reset_Utility::wp_kses_wf($this->get_card_header(__('Delete Content', 'wp-reset'), 'tool-delete-content', array('collapse_button' => true, 'iot_button' => true, 'pro' => true))); | |
| 1854 | + echo '<div class="card-body">'; | |
| 1855 | + echo '<p>Besides content, all linked or child records (for selected content) will be deleted to prevent creating orphaned rows in the database. For instance, for posts that\'s posts, post meta, and comments related to posts. Delete process does not call any WP hooks such as <i>before_delete_post</i>. Choosing a post type or taxonomy does not delete that parent object it deletes the child objects. Parent objects are defined in code. If you want to remove them, remove their code definition. When media is deleted, files are left in the uploads folder. To delete files use the <a class="scrollto" href="#tool-delete-uploads">Clean uploads Folder</a> tool. Deleting users does not affect the current, logged in user account. All orphaned objects will be reassigned to him.</p>'; | |
| 1668 | 1856 | |
| 1669 | - if (false != $upload_dir['error']) { | |
| 1670 | - echo '<p class="mb0"><span style="color:#dd3036;"><b>Tool is not available.</b></span> Folder is not writeable by WordPress. Please check file and folder access rights.</p>'; | |
| 1671 | - } else { | |
| 1672 | - echo '<p class="mb0"><a data-confirm-title="Are you sure you want to delete all files & folders in uploads folder?" data-btn-confirm="Delete everything in uploads folder" data-text-wait="Deleting uploads. Please wait." data-text-confirm="All files and folders in uploads will be deleted. There is NO UNDO. WP Reset does not make any file backups." data-text-done="%n files & folders have been deleted." data-text-done-singular="One file or folder has been deleted." class="button button-delete" href="#" id="delete-uploads">Delete all files & folders in uploads folder</a></p>'; | |
| 1673 | - } | |
| 1674 | - echo '</div>'; | |
| 1675 | - echo '</div>'; | |
| 1857 | + WP_Reset_Utility::wp_kses_wf($this->get_tool_icons(false, true)); | |
| 1676 | 1858 | |
| 1677 | - echo '<div class="card">'; | |
| 1678 | - echo $this->get_card_header(__('Reset Theme Options', 'wp-reset'), 'tool-reset-theme-options', true, true); | |
| 1679 | - echo '<div class="card-body">'; | |
| 1680 | - echo '<p>' . __('All options (mods) for all themes will be reset; not just for the active theme. The tool works only for themes that use the <a href="https://codex.wordpress.org/Theme_Modification_API" target="_blank">WordPress theme modification API</a>. If options are saved in some other, custom way they won\'t be reset.<br> Always <a href="#" class="create-new-snapshot" data-description="Before resetting theme options">create a snapshot</a> before using this tool if you want to be able to undo its actions.', 'wp-reset') . '</p>'; | |
| 1681 | - echo $this->get_tool_icons(false, true); | |
| 1682 | - echo '<p class="mb0"><a data-confirm-title="Are you sure you want to reset all theme options?" data-btn-confirm="Reset theme options" data-text-wait="Resetting theme options. Please wait." data-text-confirm="All options (mods) for all themes will be reset. Always ' . esc_attr('<a data-description="Before resetting theme options" href="#" class="create-new-snapshot">create a snapshot</a> if you want to be able to undo') . '." data-text-done="Options for %n themes have been reset." data-text-done-singular="Options for one theme have been reset." class="button button-delete" href="#" id="reset-theme-options">Reset theme options</a>' . $this->get_snapshot_button('reset-theme-options', 'Before resetting theme options') . '</p>'; | |
| 1683 | - echo '</div>'; | |
| 1684 | - echo '</div>'; | |
| 1859 | + $post_types = get_post_types('', false, 'and'); | |
| 1860 | + $taxonomies = get_taxonomies('', false, 'and'); | |
| 1685 | 1861 | |
| 1686 | - $theme = wp_get_theme(); | |
| 1862 | + echo '<p><select size="6" multiple id="delete-content-types">'; | |
| 1863 | + // phpcs:ignore db call warning as we are using uncommon queries | |
| 1864 | + echo '<option value="_comments">Comments (' . ((int) $wpdb->get_var("SELECT COUNT(comment_id) FROM $wpdb->comments")) . ')</option>'; // phpcs:ignore | |
| 1865 | + echo '<option value="_users">Users (' . ((int) $wpdb->get_var("SELECT COUNT(id) FROM $wpdb->users")) . ')</option>'; // phpcs:ignore | |
| 1866 | + foreach ($post_types as $type) { | |
| 1867 | + $count = wp_count_posts($type->name, 'readable'); | |
| 1868 | + $tmp = 0; | |
| 1869 | + foreach ($count as $cnt) { | |
| 1870 | + $tmp += (int) $cnt; | |
| 1871 | + } | |
| 1872 | + echo '<option value="' . esc_attr($type->name) . '">Post type - ' . esc_html($type->label . ' (' . $tmp) . ')</option>'; | |
| 1873 | + } // foreach post types | |
| 1874 | + foreach ($taxonomies as $tax) { | |
| 1875 | + echo '<option value="_tax_' . esc_attr($tax->name) . '">Taxonomy - ' . esc_html($tax->label . ' (' . wp_count_terms($tax->name)) . ')</option>'; | |
| 1876 | + } // foreach post types | |
| 1687 | 1877 | |
| 1688 | - echo '<div class="card">'; | |
| 1689 | - echo $this->get_card_header(__('Delete Themes', 'wp-reset'), 'tool-delete-themes', true, true); | |
| 1690 | - echo '<div class="card-body">'; | |
| 1691 | - echo '<p>' . __('All themes will be deleted. Including the currently active theme - ' . $theme->get('Name') . '.<br><b>There is NO UNDO. WP Reset does not make any file backups.</b>', 'wp-reset') . '</p>'; | |
| 1878 | + echo '</select><br>'; | |
| 1879 | + echo 'Select content object(s) you want to delete. Use ctrl + click to select multiple objects.</p>'; | |
| 1692 | 1880 | |
| 1693 | - echo $this->get_tool_icons(true, true); | |
| 1881 | + echo '<p class="mb0"><a class="button button-delete button-pro-feature" href="#">Delete content - <span data-feature="tool-delete-content" class="pro-feature"><span class="pro">PRO</span> tool</span></a></p>'; | |
| 1882 | + echo '</div>'; | |
| 1883 | + echo '</div>'; // delete content | |
| 1694 | 1884 | |
| 1695 | - echo '<p class="mb0"><a data-confirm-title="Are you sure you want to delete all themes?" data-btn-confirm="Delete all themes" data-text-wait="Deleting all themes. Please wait." data-text-confirm="All themes will be deleted. There is NO UNDO. WP Reset does not make any file backups." data-text-done="%n themes have been deleted." data-text-done-singular="One theme has been deleted." class="button button-delete" href="#" id="delete-themes">Delete all themes</a></p>'; | |
| 1696 | - echo '</div>'; | |
| 1697 | - echo '</div>'; | |
| 1885 | + echo '<div class="card default-collapsed">'; | |
| 1886 | + WP_Reset_Utility::wp_kses_wf($this->get_card_header(__('Delete Widgets', 'wp-reset'), 'tool-delete-widgets', array('collapse_button' => true, 'iot_button' => true, 'pro' => true))); | |
| 1887 | + echo '<div class="card-body">'; | |
| 1888 | + echo '<p>All widgets, orphaned, active and inactive ones, as well as widgets in active and inactive sidebars will be deleted including their settings. After deleting, WordPress will automatically recreate default, empty database entries related to widgets. So, no matter how many times users run the tool it will never return "no data deleted". That\'s expected and normal.</p>'; | |
| 1698 | 1889 | |
| 1699 | - echo '<div class="card">'; | |
| 1700 | - echo $this->get_card_header(__('Delete Plugins', 'wp-reset'), 'tool-delete-plugins', true, true); | |
| 1701 | - echo '<div class="card-body">'; | |
| 1702 | - echo '<p>' . __('All plugins will be deleted except for WP Reset which will remain active.<br><b>There is NO UNDO. WP Reset does not make any file backups.</b>', 'wp-reset') . '</p>'; | |
| 1890 | + WP_Reset_Utility::wp_kses_wf($this->get_tool_icons(false, true)); | |
| 1703 | 1891 | |
| 1704 | - echo $this->get_tool_icons(true, true); | |
| 1892 | + echo '<p class="mb0"><a class="button button-delete button-pro-feature" href="#">Delete widgets - <span data-feature="tool-delete-widgets" class="pro-feature"><span class="pro">PRO</span> tool</span></a></p>'; | |
| 1893 | + echo '</div>'; | |
| 1894 | + echo '</div>'; // delete widgets | |
| 1705 | 1895 | |
| 1706 | - echo '<p class="mb0"><a data-confirm-title="Are you sure you want to delete all plugins?" data-btn-confirm="Delete plugins" data-text-wait="Deleting plugins. Please wait." data-text-confirm="All plugins except WP Reset will be deleted. There is NO UNDO. WP Reset does not make any file backups." data-text-done="%n plugins have been deleted." data-text-done-singular="One plugin has been deleted." class="button button-delete" href="#" id="delete-plugins">Delete plugins</a></p>'; | |
| 1707 | - echo '</div>'; | |
| 1708 | - echo '</div>'; | |
| 1896 | + $theme = wp_get_theme(); | |
| 1709 | 1897 | |
| 1710 | - $custom_tables = $this->get_custom_tables(); | |
| 1898 | + echo '<div class="card">'; | |
| 1899 | + WP_Reset_Utility::wp_kses_wf($this->get_card_header(__('Delete Themes', 'wp-reset'), 'tool-delete-themes', array('iot_button' => true, 'collapse_button' => true))); | |
| 1900 | + echo '<div class="card-body">'; | |
| 1901 | + /* translators: %s is replaced with the currently active theme name */ | |
| 1902 | + WP_Reset_Utility::wp_kses_wf('<p>' . sprintf(__('All themes will be deleted. Including the currently active theme - %s.<br><b>There is NO UNDO. WP Reset does not make any file backups.</b>', 'wp-reset'), esc_html($theme->get('Name'))) . '</p>'); | |
| 1903 | + WP_Reset_Utility::wp_kses_wf($this->get_tool_icons(true, true)); | |
| 1904 | + echo '<p class="mb0"><a data-confirm-title="Are you sure you want to delete all themes?" data-btn-confirm="Delete all themes" data-text-wait="Deleting all themes. Please wait." data-text-confirm="All themes will be deleted. There is NO UNDO. WP Reset does not make any file backups." data-text-done="%n themes have been deleted." data-text-done-singular="One theme has been deleted." class="button button-delete" href="#" id="delete-themes">Delete all themes</a></p>'; | |
| 1905 | + echo '</div>'; | |
| 1906 | + echo '</div>'; // delete themes | |
| 1711 | 1907 | |
| 1712 | - echo '<div class="card">'; | |
| 1713 | - echo $this->get_card_header(__('Empty or Delete Custom Tables', 'wp-reset'), 'tool-empty-delete-custom-tables', true, true); | |
| 1714 | - echo '<div class="card-body">'; | |
| 1715 | - echo '<p>' . __('This action affects only custom tables with <code>' . $wpdb->prefix . '</code> prefix. Core WP tables and other tables in the database that do not have that prefix will not be deleted/emptied. Deleting (dropping) tables completely removes them from the database. Emptying (truncating) removes all content from them, but keeps the structure intact.<br>Always <a href="#" class="create-new-snapshot" data-description="Before deleting custom tables">create a snapshot</a> before using this tool if you want to be able to undo its actions.</p>', 'wp-reset'); | |
| 1716 | - if ($custom_tables) { | |
| 1717 | - echo '<p>' . __('The following ' . sizeof($custom_tables) . ' custom tables are affected by this tool: '); | |
| 1718 | - foreach ($custom_tables as $tbl) { | |
| 1719 | - echo '<code>' . $tbl['name'] . '</code>'; | |
| 1720 | - if (next($custom_tables)) { | |
| 1721 | - echo ', '; | |
| 1908 | + echo '<div class="card">'; | |
| 1909 | + WP_Reset_Utility::wp_kses_wf($this->get_card_header(__('Delete Plugins', 'wp-reset'), 'tool-delete-plugins', array('iot_button' => true, 'collapse_button' => true))); | |
| 1910 | + echo '<div class="card-body">'; | |
| 1911 | + WP_Reset_Utility::wp_kses_wf('<p>' . __('All plugins will be deleted except for WP Reset which will remain active.<br><b>There is NO UNDO. WP Reset does not make any file backups.</b>', 'wp-reset') . '</p>'); | |
| 1912 | + WP_Reset_Utility::wp_kses_wf($this->get_tool_icons(true, true)); | |
| 1913 | + echo '<p class="mb0"><a data-confirm-title="Are you sure you want to delete all plugins?" data-btn-confirm="Delete plugins" data-text-wait="Deleting plugins. Please wait." data-text-confirm="All plugins except WP Reset will be deleted. There is NO UNDO. WP Reset does not make any file backups." data-text-done="%n plugins have been deleted." data-text-done-singular="One plugin has been deleted." class="button button-delete" href="#" id="delete-plugins">Delete plugins</a></p>'; | |
| 1914 | + echo '</div>'; | |
| 1915 | + echo '</div>'; // delete plugins | |
| 1916 | + | |
| 1917 | + echo '<div class="card default-collapsed">'; | |
| 1918 | + WP_Reset_Utility::wp_kses_wf($this->get_card_header(__('Delete MU Plugins & Drop-ins', 'wp-reset'), 'tool-delete-mu-plugins-dropins', array('collapse_button' => true, 'iot_button' => true, 'pro' => true))); | |
| 1919 | + echo '<div class="card-body">'; | |
| 1920 | + echo '<p>MU Plugins are located in <code>/wp-content/mu-plugins/</code> and are, as the name suggests, must-use plugins that are automatically activated by WP and can\'t be deactiavated via the <a href="' . esc_url(admin_url('plugins.php?plugin_status=mustuse')) . '" target="_blank">plugins interface</a>, although if any are used, they are listed in the "Must Use" tab.<br>'; | |
| 1921 | + echo 'Drop-ins are pieces of code found in <code>/wp-content/</code> that replace default, built-in WordPress functionality. Most often used are <code>db.php</code> and <code>advanced-cache.php</code> that implement custom DB and cache functionality. They can\'t be deactivated via the <a href="' . esc_url(admin_url('plugins.php?plugin_status=dropins')) . '" target="_blank">plugins interface</a> but if any are present are listed in the "Drop-in" tab.</p>'; | |
| 1922 | + | |
| 1923 | + if (is_multisite()) { | |
| 1924 | + echo '<p class="mb0 wpmu-error">This tool is <b>not compatible</b> with WP multisite (WPMU). Using it would delete plugins for all sites in the network since they all share the same plugin files.</p>'; | |
| 1925 | + } else { | |
| 1926 | + WP_Reset_Utility::wp_kses_wf($this->get_tool_icons(true, false, true)); | |
| 1927 | + echo '<p class="mb0"><a class="button button-delete button-pro-feature" href="#">Delete must use plugins - <span data-feature="tool-delete-mu-plugins" class="pro-feature"><span class="pro">PRO</span> tool</span></a><a class="button button-delete button-pro-feature" href="#">Delete drop-ins - <span data-feature="tool-delete-dropins" class="pro-feature"><span class="pro">PRO</span> tool</span></a></p>'; | |
| 1722 | 1928 | } |
| 1723 | - } // foreach | |
| 1724 | - echo '.</p>'; | |
| 1725 | - $custom_tables_btns = ''; | |
| 1726 | - } else { | |
| 1727 | - echo '<p>' . __('There are no custom tables. There\'s nothing for this tool to empty or delete.', 'wp-reset') . '</p>'; | |
| 1728 | - $custom_tables_btns = ' disabled'; | |
| 1729 | - } | |
| 1929 | + echo '</div>'; | |
| 1930 | + echo '</div>'; // delete MU plugins and dropins | |
| 1730 | 1931 | |
| 1731 | - echo $this->get_tool_icons(false, true, true); | |
| 1932 | + $upload_dir = wp_upload_dir(gmdate('Y/m'), true); | |
| 1933 | + $upload_dir['basedir'] = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $upload_dir['basedir']); | |
| 1732 | 1934 | |
| 1733 | - echo '<p class="mb0"><a data-confirm-title="Are you sure you want to empty all custom tables?" data-btn-confirm="Empty custom tables" data-text-wait="Emptying custom tables. Please wait." data-text-confirm="All custom tables with prefix <code>' . $wpdb->prefix . '</code> will be emptied. Always ' . esc_attr('<a href="#" class="create-new-snapshot" data-description="Before emptying custom tables">create a snapshot</a> if you want to be able to undo') . '." data-text-done="%n custom tables have been emptied." data-text-done-singular="One custom table has been emptied." class="button button-delete' . $custom_tables_btns . '" href="#" id="truncate-custom-tables">Empty (truncate) custom tables</a>'; | |
| 1734 | - echo '<a data-confirm-title="Are you sure you want to delete all custom tables?" data-btn-confirm="Delete custom tables" data-text-wait="Deleting custom tables. Please wait." data-text-confirm="All custom tables with prefix <code>' . $wpdb->prefix . '</code> will be deleted. Always ' . esc_attr('<a href="#" class="create-new-snapshot" data-description="Before deleting custom tables">create a snapshot</a> if you want to be able to undo') . '." data-text-done="%n custom tables have been deleted." data-text-done-singular="One custom table has been deleted." class="button button-delete' . $custom_tables_btns . '" href="#" id="drop-custom-tables">Delete (drop) custom tables</a>' . $this->get_snapshot_button('drop-custom-tables', 'Before deleting custom tables') . '</p>'; | |
| 1735 | - echo '</div>'; | |
| 1736 | - echo '</div>'; | |
| 1935 | + echo '<div class="card">'; | |
| 1936 | + WP_Reset_Utility::wp_kses_wf($this->get_card_header(__('Clean uploads Folder', 'wp-reset'), 'tool-delete-uploads', array('iot_button' => true, 'collapse_button' => true))); | |
| 1937 | + echo '<div class="card-body">'; | |
| 1938 | + /* translators: %1$s is replaced with the uploads folder path, %2$s is replaced with the URL to WordPress Media upload page */ | |
| 1939 | + WP_Reset_Utility::wp_kses_wf('<p>' . sprintf(__('All files in <code>%1$s</code> folder will be deleted. Including folders and subfolders, and files in subfolders. Files associated with <a href="%2$s">media</a> entries will be deleted too.<br><b>There is NO UNDO. WP Reset does not make any file backups.</b>', 'wp-reset'), esc_html($upload_dir['basedir']), esc_url(admin_url('upload.php'))) . '</p>'); | |
| 1940 | + WP_Reset_Utility::wp_kses_wf($this->get_tool_icons(true, false)); | |
| 1941 | + if (false != $upload_dir['error']) { | |
| 1942 | + echo '<p class="mb0"><span style="color:#dd3036;"><b>Tool is not available.</b></span> Folder is not writeable by WordPress. Please check file and folder access rights.</p>'; | |
| 1943 | + } else { | |
| 1944 | + echo '<p class="mb0"><a data-confirm-title="Are you sure you want to delete all files & folders in uploads folder?" data-btn-confirm="Delete everything in uploads folder" data-text-wait="Deleting uploads. Please wait." data-text-confirm="All files and folders in uploads will be deleted. There is NO UNDO. WP Reset does not make any file backups." data-text-done="%n files & folders have been deleted." data-text-done-singular="One file or folder has been deleted." class="button button-delete" href="#" id="delete-uploads">Delete all files & folders in uploads folder</a></p>'; | |
| 1945 | + } | |
| 1946 | + echo '</div>'; | |
| 1947 | + echo '</div>'; // clean uploads folder | |
| 1737 | 1948 | |
| 1738 | - echo '<div class="card">'; | |
| 1739 | - echo $this->get_card_header(__('Delete .htaccess File', 'wp-reset'), 'tool-delete-htaccess', true, true); | |
| 1740 | - echo '<div class="card-body">'; | |
| 1741 | - echo '<p>' . __('This action deletes the .htaccess file located in <code>' . $this->get_htaccess_path() . '</code><br><b>There is NO UNDO. WP Reset does not make any file backups.</b></p>', 'wp-reset'); | |
| 1949 | + echo '<div class="card default-collapsed">'; | |
| 1950 | + WP_Reset_Utility::wp_kses_wf($this->get_card_header(__('Clean wp-content Folder', 'wp-reset'), 'tool-delete-wp-content', array('collapse_button' => true, 'iot_button' => true, 'pro' => true))); | |
| 1951 | + echo '<div class="card-body">'; | |
| 1952 | + echo '<p>All folders and their content in <code>wp-content</code> folder except the following ones will be deleted: <code>mu-plugins</code>, <code>plugins</code>, <code>themes</code>, <code>uploads</code>, <code>wp-reset-autosnapshots</code>, <code>wp-reset-snapshots-export</code>.</p>'; | |
| 1953 | + WP_Reset_Utility::wp_kses_wf($this->get_tool_icons(true, false)); | |
| 1954 | + if (false === $wp_filesystem->is_writable(trailingslashit(WP_CONTENT_DIR))) { | |
| 1955 | + echo '<p class="mb0"><span style="color:#dd3036;"><b>Tool is not available.</b></span> Folder is not writeable by WordPress. Please check file and folder access rights.</p>'; | |
| 1956 | + } else { | |
| 1957 | + echo '<p class="mb0"><a class="button button-delete button-pro-feature" href="#">Clean wp-content folder - <span data-feature="tool-delete-wp-content" class="pro-feature"><span class="pro">PRO</span> tool</span></a></p>'; | |
| 1958 | + } | |
| 1959 | + echo '</div>'; | |
| 1960 | + echo '</div>'; // clean wp-content | |
| 1742 | 1961 | |
| 1743 | - echo '<p>If you need to edit .htaccess, install our free <a href="' . admin_url('plugin-install.php?tab=plugin-information&plugin=wp-htaccess-editor&TB_iframe=true&width=600&height=550') . '" class="thickbox open-plugin-details-modal">WP Htaccess Editor</a> plugin. It automatically creates backups when you edit .htaccess as well as checks for syntax errors. To create the default .htaccess file open <a href="' . admin_url('options-permalink.php') . '">Settings - Permalinks</a> and re-save settings. WordPress will recreate the file.</p>'; | |
| 1962 | + $custom_tables = $this->get_custom_tables(); | |
| 1744 | 1963 | |
| 1745 | - echo $this->get_tool_icons(true, false); | |
| 1964 | + echo '<div class="card">'; | |
| 1965 | + WP_Reset_Utility::wp_kses_wf($this->get_card_header(__('Empty or Delete Custom Tables', 'wp-reset'), 'tool-empty-delete-custom-tables', array('iot_button' => true, 'collapse_button' => true))); | |
| 1966 | + echo '<div class="card-body">'; | |
| 1967 | + /* translators: %s is replaced with the table prefix */ | |
| 1968 | + WP_Reset_Utility::wp_kses_wf('<p>' . sprintf(__('This action affects only custom tables with <code>%s</code> prefix. Core WP tables and other tables in the database that do not have that prefix will not be deleted/emptied. Deleting (dropping) tables completely removes them from the database. Emptying (truncating) removes all content from them, but keeps the structure intact.<br>Always <a href="#" class="create-new-snapshot" data-description="Before deleting custom tables">create a snapshot</a> before using this tool if you want to be able to undo its actions.</p>', 'wp-reset'), esc_html($wpdb->prefix))); | |
| 1969 | + if ($custom_tables) { | |
| 1970 | + /* translators: %d is replaced with the number of custom tables */ | |
| 1971 | + WP_Reset_Utility::wp_kses_wf('<p>' . sprintf(__('The following %d custom tables are affected by this tool: ', 'wp-reset'), sizeof($custom_tables))); | |
| 1972 | + foreach ($custom_tables as $tbl) { | |
| 1973 | + echo '<code>' . esc_html($tbl['name']) . '</code>'; | |
| 1974 | + if (next($custom_tables)) { | |
| 1975 | + echo ', '; | |
| 1976 | + } | |
| 1977 | + } // foreach | |
| 1978 | + echo '.</p>'; | |
| 1979 | + $custom_tables_btns = ''; | |
| 1980 | + } else { | |
| 1981 | + echo '<p>' . esc_html__('There are no custom tables. There\'s nothing for this tool to empty or delete.', 'wp-reset') . '</p>'; | |
| 1982 | + $custom_tables_btns = ' disabled'; | |
| 1983 | + } | |
| 1984 | + WP_Reset_Utility::wp_kses_wf($this->get_tool_icons(false, true, true)); | |
| 1985 | + echo '<p class="mb0"><a data-confirm-title="Are you sure you want to empty all custom tables?" data-btn-confirm="Empty custom tables" data-text-wait="Emptying custom tables. Please wait." data-text-confirm="All custom tables with prefix <code>' . esc_attr($wpdb->prefix) . '</code> will be emptied. Always ' . esc_attr('<a href="#" class="create-new-snapshot" data-description="Before emptying custom tables">create a snapshot</a> if you want to be able to undo') . '." data-text-done="%n custom tables have been emptied." data-text-done-singular="One custom table has been emptied." class="button button-delete' . esc_attr($custom_tables_btns) . '" href="#" id="truncate-custom-tables">Empty (truncate) custom tables</a>'; | |
| 1986 | + echo '<a data-confirm-title="Are you sure you want to delete all custom tables?" data-btn-confirm="Delete custom tables" data-text-wait="Deleting custom tables. Please wait." data-text-confirm="All custom tables with prefix <code>' . esc_attr($wpdb->prefix) . '</code> will be deleted. Always ' . esc_attr('<a href="#" class="create-new-snapshot" data-description="Before deleting custom tables">create a snapshot</a> if you want to be able to undo') . '." data-text-done="%n custom tables have been deleted." data-text-done-singular="One custom table has been deleted." class="button button-delete' . esc_attr($custom_tables_btns) . '" href="#" id="drop-custom-tables">Delete (drop) custom tables</a>'; | |
| 1987 | + WP_Reset_Utility::wp_kses_wf($this->get_snapshot_button('drop-custom-tables', 'Before deleting custom tables')); | |
| 1988 | + echo '</p>'; | |
| 1989 | + echo '</div>'; | |
| 1990 | + echo '</div>'; // empty custom tables | |
| 1746 | 1991 | |
| 1747 | - echo '<p class="mb0"><a data-confirm-title="Are you sure you want to delete the .htaccess file?" data-btn-confirm="Delete .htaccess file" data-text-wait="Deleting .htaccess file. Please wait." data-text-confirm="Htaccess file will be deleted. There is NO UNDO. WP Reset does not make any file backups." data-text-done="Htaccess file has been deleted." data-text-done-singular="Htaccess file has been deleted." class="button button-delete" href="#" id="delete-htaccess">Delete .htaccess file</a></p>'; | |
| 1992 | + echo '<div class="card default-collapsed">'; | |
| 1993 | + WP_Reset_Utility::wp_kses_wf($this->get_card_header(__('Switch WP Version', 'wp-reset'), 'tool-switch-wp-version', array('collapse_button' => true, 'iot_button' => true, 'pro' => true))); | |
| 1994 | + echo '<div class="card-body">'; | |
| 1995 | + if (is_multisite()) { | |
| 1996 | + echo '<p class="mb0 wpmu-error">This tool is <b>not compatible</b> with WP multisite (WPMU). Using it would change the WP version for all sites in the network since they all share the same core files.</p>'; | |
| 1997 | + } else { | |
| 1998 | + echo '<p>Replace current WordPress version with the selected new version. Switching from a previous version, to a newer version is mostly supported and properly handled by the WP installer. Reverting WordPress, rolling back WordPress to a previous version is not supported. Results may vary!</p>'; | |
| 1999 | + WP_Reset_Utility::wp_kses_wf($this->get_tool_icons(true, true)); | |
| 1748 | 2000 | |
| 1749 | - echo '</div>'; | |
| 1750 | - echo '</div>'; | |
| 1751 | - } // tab_tools | |
| 2001 | + $wp_versions = WP_Reset_Utility::get_wordpress_versions(); | |
| 2002 | + echo '<p><label for="select-wp-version">Select the WordPress version to switch to:</label> '; | |
| 2003 | + echo '<select id="select-wp-version">'; | |
| 2004 | + echo '<option value="">select WordPress version</option>'; | |
| 2005 | + foreach ($wp_versions as $version => $release_date) { | |
| 2006 | + if ($release_date == 'bleeding') { | |
| 2007 | + echo '<option value="bleeding">WordPress v' . esc_html($version) . ' (Bleeding edge nightly)' . ($wp_version == $version ? ' - installed' : '') . '</option>'; | |
| 2008 | + } elseif ($release_date == 'point') { | |
| 2009 | + echo '<option value="point-' . esc_attr(substr($version, 0, 3)) . '">WordPress v' . esc_html($version) . ' (Point release nightly)' . ($wp_version == $version ? ' - installed' : '') . '</option>'; | |
| 2010 | + } else { | |
| 2011 | + echo '<option value="' . esc_attr($version) . '">WordPress v' . esc_html($version) . ' (' . esc_attr(gmdate('Y-m-d', $release_date)) . ')' . ($wp_version == $version ? ' - installed' : '') . '</option>'; | |
| 2012 | + } | |
| 2013 | + } | |
| 2014 | + echo '</select></p>'; | |
| 1752 | 2015 | |
| 2016 | + echo '<p class="mb0">'; | |
| 2017 | + echo '<a class="button button-delete button-pro-feature" href="#">Switch WordPress version - <span data-feature="tool-switch-wp-version" class="pro-feature"><span class="pro">PRO</span> tool</span></a>'; | |
| 2018 | + echo '</p>'; | |
| 2019 | + } | |
| 2020 | + echo '</div>'; | |
| 2021 | + echo '</div>'; // switch WP version | |
| 1753 | 2022 | |
| 1754 | - /** | |
| 1755 | - * Echoes content for collections tab | |
| 1756 | - * | |
| 1757 | - * @return null | |
| 1758 | - */ | |
| 1759 | - private function tab_collections() | |
| 1760 | - { | |
| 1761 | - echo '<div class="card">'; | |
| 1762 | - echo '<h4>' . __('What are Plugin & Theme Collections?', 'wp-reset') . '</h4>'; | |
| 1763 | - echo '<p>' . __('A tool that\'s coming with WP Reset PRO that will <b>save hours & hours of your precious time</b>! Have a set of plugins (and themes) that you install and activate after every reset? Or on every fresh WP installation? Well, no more clicking install & active for ten minutes! Build the collection once and install it with one click as many times as needed.<br>WP Reset stores collections in the cloud so they\'re accessible on every site you build. You can use free plugins and themes from the official repo, and PRO ones by uploading a ZIP file. We\'ll safely store your license keys too, so you have everything in one place.', 'wp-reset') . '</p>'; | |
| 1764 | - echo '<p><b>Interested in collections and other PRO features?</b> Ping us <a href="https://twitter.com/webfactoryltd" target="_blank">@webfactoryltd</a> and be among the first users who will get PRO in early January 2020.</p>'; | |
| 1765 | - echo '</div>'; | |
| 1766 | - } // tab_collections | |
| 2023 | + echo '<div class="card">'; | |
| 2024 | + WP_Reset_Utility::wp_kses_wf($this->get_card_header(__('Delete .htaccess File', 'wp-reset'), 'tool-delete-htaccess', array('iot_button' => true, 'collapse_button' => true))); | |
| 2025 | + echo '<div class="card-body">'; | |
| 2026 | + /* translators: %s is replaced with the .htaccess file path */ | |
| 2027 | + WP_Reset_Utility::wp_kses_wf('<p>' . sprintf(__('This action deletes the .htaccess file located in <code>%s</code><br><b>There is NO UNDO. WP Reset does not make any file backups.</b></p>', 'wp-reset'), esc_html($this->get_htaccess_path()))); | |
| 1767 | 2028 | |
| 2029 | + echo '<p>If you need to edit .htaccess, install our free <a href="' . esc_url(admin_url('plugin-install.php?tab=plugin-information&plugin=wp-htaccess-editor&TB_iframe=true&width=600&height=550')) . '" class="thickbox open-plugin-details-modal">WP Htaccess Editor</a> plugin. It automatically creates backups when you edit .htaccess as well as checks for syntax errors. To create the default .htaccess file open <a href="' . esc_url(admin_url('options-permalink.php')) . '">Settings - Permalinks</a> and re-save settings. WordPress will recreate the file.</p>'; | |
| 2030 | + WP_Reset_Utility::wp_kses_wf($this->get_tool_icons(true, false)); | |
| 2031 | + echo '<p class="mb0"><a data-confirm-title="Are you sure you want to delete the .htaccess file?" data-btn-confirm="Delete .htaccess file" data-text-wait="Deleting .htaccess file. Please wait." data-text-confirm="Htaccess file will be deleted. There is NO UNDO. WP Reset does not make any file backups." data-text-done="Htaccess file has been deleted." data-text-done-singular="Htaccess file has been deleted." class="button button-delete" href="#" id="delete-htaccess">Delete .htaccess file</a></p>'; | |
| 1768 | 2032 | |
| 1769 | - /** | |
| 1770 | - * Echoes content for support tab | |
| 1771 | - * | |
| 1772 | - * @return null | |
| 1773 | - */ | |
| 1774 | - private function tab_support() | |
| 1775 | - { | |
| 1776 | - echo '<div class="card">'; | |
| 1777 | - echo '<h4>' . __('Documentation', 'wp-reset') . '</h4>'; | |
| 1778 | - echo '<p>' . __('All tools and functions are explained in detail in <a href="' . $this->generate_web_link('support-tab', '/documentation/') . '" target="_blank">the documentation</a>. We did our best to describe how things work on both the code level and an "average user" level.', 'wp-reset') . '</p>'; | |
| 1779 | - echo '</div>'; | |
| 2033 | + echo '</div>'; | |
| 2034 | + echo '</div>'; // delete htaccess | |
| 2035 | + } // tab_tools | |
| 1780 | 2036 | |
| 1781 | - echo '<div class="card">'; | |
| 1782 | - echo '<h4>' . __('Public support forum', 'wp-reset') . '</h4>'; | |
| 1783 | - echo '<p>' . __('We are very active on the <a href="https://wordpress.org/support/plugin/wp-reset" target="_blank">official WP Reset support forum</a>. If you found a bug, have a feature idea or just want to say hi - please drop by. We love to hear back from our users.', 'wp-reset') . '</p>'; | |
| 1784 | - echo '</div>'; | |
| 1785 | 2037 | |
| 1786 | - echo '<div class="card">'; | |
| 1787 | - echo '<h4>' . __('Care to help out?', 'wp-reset') . '</h4>'; | |
| 1788 | - echo '<p>' . __('No need for donations or anything like that :) If you can give us a <a href="https://wordpress.org/support/plugin/wp-reset/reviews/#new-post" target="_blank">five star rating</a> you\'ll help out more than you can imagine. A public mention <a href="https://twitter.com/webfactoryltd" target="_blank">@webfactoryltd</a> also does wonders. Thank you!', 'wp-reset') . '</p>'; | |
| 1789 | - echo '</div>'; | |
| 1790 | - } // tab_support | |
| 2038 | + /** | |
| 2039 | + * Echoes content for collections tab | |
| 2040 | + * | |
| 2041 | + * @return null | |
| 2042 | + */ | |
| 2043 | + private function tab_collections() | |
| 2044 | + { | |
| 2045 | + echo '<div class="card">'; | |
| 2046 | + WP_Reset_Utility::wp_kses_wf($this->get_card_header('What are Plugin & Theme Collections?', 'collections-info', array('collapse_button' => false))); | |
| 2047 | + echo '<div class="card-body">'; | |
| 2048 | + WP_Reset_Utility::wp_kses_wf('<p>' . __('Have a set of plugins (and themes) that you install and activate after every reset? Or on every fresh WordPress installation? Well, no more clicking install & active for ten minutes! Build the collection once and install it with one click as many times as needed.</p><p>WP Reset stores collections in the cloud so they\'re accessible on every site you build. You can use free plugins and themes from the official repo, and PRO ones by uploading a ZIP file. We\'ll safely store your license keys too, so you have everything in one place.', 'wp-reset') . '</p>'); | |
| 2049 | + echo '<p><a class="button button-secondary button-pro-feature" href="#">Add a new collection - <span data-feature="collections" class="pro-feature"><span class="pro">PRO</span> feature</span></a> <a class="button button-secondary button-pro-feature" href="#">Reload my saved collections from the cloud - <span data-feature="collections" class="pro-feature"><span class="pro">PRO</span> feature</span></a></p>'; | |
| 2050 | + echo '</div>'; | |
| 2051 | + echo '</div>'; // collections-info | |
| 1791 | 2052 | |
| 2053 | + $plugins = array(); | |
| 2054 | + $plugins['eps-301-redirects'] = array('name' => '301 Redirects', 'desc' => 'Easiest way to manage redirects'); | |
| 2055 | + $plugins['classic-editor'] = array('name' => 'Classic Editor', 'desc' => 'Any easy fix for all your Gutenberg caused troubles'); | |
| 2056 | + $plugins['simple-author-box'] = array('name' => 'Simple Author Box', 'desc' => 'Simplest way to add responsive, great looking author boxes'); | |
| 2057 | + $plugins['sticky-menu-or-anything-on-scroll'] = array('name' => 'Sticky Menu (or Anything!) on Scroll', 'desc' => 'Make any element on the page sticky.'); | |
| 2058 | + $plugins['under-construction-page'] = array('name' => 'UnderConstructionPage', 'desc' => 'Working on your site? Put it in the under construction mode.'); | |
| 2059 | + $plugins['wp-external-links'] = array('name' => 'WP External Links', 'desc' => 'Manage all external & internal links. Control icons, nofollow, noopener, UGC, sponsored and if links open in new window or new tab.'); | |
| 1792 | 2060 | |
| 1793 | - /** | |
| 1794 | - * Echoes content for snapshots tab | |
| 1795 | - * | |
| 1796 | - * @return null | |
| 1797 | - */ | |
| 1798 | - private function tab_snapshots() | |
| 1799 | - { | |
| 1800 | - global $wpdb; | |
| 1801 | - $tbl_core = $tbl_custom = $tbl_size = $tbl_rows = 0; | |
| 2061 | + echo '<div class="card" data-collection-id="1">'; | |
| 2062 | + WP_Reset_Utility::wp_kses_wf($this->get_card_header('Must Have WordPress Plugins', 'collection-id-1', array('collapse_button' => false))); | |
| 2063 | + echo '<div class="card-body"><div class="thirdx2"><p class="_mb0"></p><div class="dropdown dropdown-right"> | |
| 2064 | + <a class="button dropdown-toggle" href="#">Install collection</a> | |
| 2065 | + <div class="dropdown-menu"> | |
| 2066 | + <a class="dropdown-item install-collection" data-activate="true" href="#">Install & activate collection</a> | |
| 2067 | + <a class="dropdown-item install-collection" href="#">Install collection</a> | |
| 2068 | + <a data-feature="collections" class="dropdown-item button-pro-feature" href="#">Delete installed plugins & themes then install & activate collection - <span class="pro-feature" data-feature="cloud-wpr"><span class="pro">PRO</span> Feature</span></a> | |
| 2069 | + <a data-feature="collections" class="dropdown-item button-pro-feature" href="#">Delete installed plugins & themes then install collection - <span class="pro-feature" data-feature="cloud-wpr"><span class="pro">PRO</span> Feature</span></a> | |
| 2070 | + </div> | |
| 2071 | + </div><a class="button add-collection-item button-pro-feature" href="#">Add new plugin or theme - <span data-feature="collections" class="pro-feature"><span class="pro">PRO</span> feature</span></a></div><div class="third textright"><p class="_mb0"></p><div class="dropdown"> | |
| 2072 | + <a class="button dropdown-toggle" href="#">Actions</a> | |
| 2073 | + <div class="dropdown-menu"> | |
| 2074 | + <a class="dropdown-item button-pro-feature" href="#">Add new collection - <span class="pro-feature" data-feature="collections"><span class="pro">PRO</span> Feature</span></a> | |
| 2075 | + <a class="dropdown-item button-pro-feature" href="#">Rename collection - <span class="pro-feature" data-feature="collections"><span class="pro">PRO</span> Feature</span></a> | |
| 2076 | + <a class="dropdown-item button-delete button-pro-feature" href="#">Delete collection - <span class="pro-feature" data-feature="collections"><span class="pro">PRO</span> Feature</span></a> | |
| 2077 | + </div> | |
| 2078 | + </div><p></p></div><table class="collection-table"><tbody><tr><th>Type</th><th>Name & Note</th><th class="actions">Actions</th></tr>'; | |
| 2079 | + foreach ($plugins as $slug => $plugin) { | |
| 2080 | + echo '<tr data-slug="' . esc_attr($slug) . '"><td><span class="dashicons dashicons-admin-plugins tooltip" title="Plugin"></span><span class="dashicons dashicons-wordpress tooltip" title="Comes from the WordPress repository"></span></td><td class="collection-item-details"><span>' . esc_html($plugin['name']) . '</span><i>' . esc_html($plugin['desc']) . '</i></td><td class="textcenter"><div class="dropdown"> | |
| 2081 | + <a class="button dropdown-toggle" href="#">Actions</a> | |
| 2082 | + <div class="dropdown-menu"> | |
| 2083 | + <a href="#" class="dropdown-item install-collection-item button-pro-feature">Install - <span class="pro-feature" data-feature="collections"><span class="pro">PRO</span> Feature</span></a> | |
| 2084 | + <a href="#" class="dropdown-item install-collection-item button-pro-feature">Install & Activate - <span class="pro-feature" data-feature="collections"><span class="pro">PRO</span> Feature</span></a> | |
| 2085 | + <a href="#" class="dropdown-item edit-collection-item button-pro-feature">Edit - <span class="pro-feature" data-feature="collections"><span class="pro">PRO</span> Feature</span></a> | |
| 2086 | + <a href="#" class="dropdown-item button-delete button-link-delete delete-collection-item button-pro-feature">Delete - <span class="pro-feature" data-feature="collections"><span class="pro">PRO</span> Feature</span></a> | |
| 2087 | + </div> | |
| 2088 | + </div></td></tr>'; | |
| 2089 | + } // foreach plugin | |
| 2090 | + echo '</tbody></table></div></div>'; | |
| 2091 | + } // tab_collections | |
| 1802 | 2092 | |
| 1803 | - echo '<div class="card" id="card-snapshots">'; | |
| 1804 | - echo '<h4>'; | |
| 1805 | - echo __('Snapshots', 'wp-reset'); | |
| 1806 | - echo '<div class="card-header-right"><a class="toggle-card" href="#" title="' . __('Collapse / expand box', 'wp-reset') . '"><span class="dashicons dashicons-arrow-up-alt2"></span></a></div>'; | |
| 1807 | - echo '</h4>'; | |
| 1808 | - echo '<div class="card-body">'; | |
| 1809 | - echo '<p>A snapshot is a copy of all WP database tables, standard and custom ones, saved in your database. Files are not saved or included in snapshots in any way. <a href="https://www.youtube.com/watch?v=xBfMmS12vMY" target="_blank">Watch a short video</a> overview and tutorial about Snapshots.</p>'; | |
| 1810 | - echo '<p>Snapshots are primarily a development tool. When using various reset tools that alter the database be sure to create a snapshot. Shortcuts are available in the confirmation dialog. If you need a full backup that includes files, use a dedicated <a target="_blank" href="' . admin_url('plugin-install.php?s=backup&tab=search&type=term') . '">backup plugin</a>.</p>'; | |
| 1811 | - echo '<p>Use snapshots to find out what changes a plugin made to your database or to quickly restore the dev environment after testing database related changes. Restoring a snapshot does not affect other snapshots, or WP Reset settings.</p>'; | |
| 1812 | 2093 | |
| 1813 | - $table_status = $wpdb->get_results('SHOW TABLE STATUS'); | |
| 1814 | - if (is_array($table_status)) { | |
| 1815 | - foreach ($table_status as $index => $table) { | |
| 1816 | - if (0 !== stripos($table->Name, $wpdb->prefix)) { | |
| 1817 | - continue; | |
| 2094 | + /** | |
| 2095 | + * Echoes content for support tab | |
| 2096 | + * | |
| 2097 | + * @return null | |
| 2098 | + */ | |
| 2099 | + private function tab_support() | |
| 2100 | + { | |
| 2101 | + echo '<div class="card">'; | |
| 2102 | + WP_Reset_Utility::wp_kses_wf($this->get_card_header(__('Documentation', 'wp-reset'), 'support-documentation', array('collapse_button' => false))); | |
| 2103 | + echo '<div class="card-body">'; | |
| 2104 | + /* translators: %s is replaced with the link to the documentation page */ | |
| 2105 | + WP_Reset_Utility::wp_kses_wf('<p class="mb0">' . sprintf(__('All tools and features are explained in detail in <a href="%s" target="_blank">the documentation</a>. We did our best to describe how things work on both the code level and an "average user" level.', 'wp-reset'), esc_url($this->generate_web_link('support-tab', '/documentation/'))) . '</p>'); | |
| 2106 | + echo '</div>'; | |
| 2107 | + echo '</div>'; // documentation | |
| 2108 | + | |
| 2109 | + echo '<div class="card">'; | |
| 2110 | + WP_Reset_Utility::wp_kses_wf($this->get_card_header('Emergency Recovery Script', 'support-ers', array('collapse_button' => false, 'pro' => true))); | |
| 2111 | + echo '<div class="card-body">'; | |
| 2112 | + echo '<p>Emergency Recovery Script is a standalone, single-file, WordPress independent PHP script created to <b>recover WordPress sites from the most difficult situations</b>. When access to the admin is not possible when core files are compromised (accidental delete or malware related situations), when you get the white screen of death, can\'t log in for whatever reason or a plugin has killed your site - emergency recovery script can fix the problem! Some of the things ERS can do;</p>'; | |
| 2113 | + echo '<ul class="plain-list">'; | |
| 2114 | + echo '<li>Test the integrity of all WP core files and reinstall them if needed</li>'; | |
| 2115 | + echo '<li>Detect and remove all files in core folders that are not a part of WP</li>'; | |
| 2116 | + echo '<li>Deactivate and activate plugins without logging in to WP admin</li>'; | |
| 2117 | + echo '<li>Deactivate and activate themes without logging in to WP admin</li>'; | |
| 2118 | + echo '<li>Reset user privileges and roles</li>'; | |
| 2119 | + echo '<li>Create new WP admin accounts without logging in to WP admin or knowing the admin username/password</li>'; | |
| 2120 | + echo '<li>Modify WordPress address and site address</li>'; | |
| 2121 | + echo '</ul>'; | |
| 2122 | + echo '<p class="mb0">You can install the script as a preventive measure, so it\'s always available in case of an emergency (don\'t worry, it\'s password protected), or upload it only when needed. On production sites, when big and potentially dangerous changes rarely happen, we suggest uploading it only when needed. On test sites, have it ready in advance because there\'s a higher probability that you\'ll need it. Emergency Recovery Script is a <span class="pro-feature pro-feature-text" data-feature="support-ers">WP Reset <span>PRO</span></span> tool.</p>'; | |
| 2123 | + echo '</div>'; | |
| 2124 | + echo '</div>'; // emergency recovery script | |
| 2125 | + | |
| 2126 | + echo '<div class="card">'; | |
| 2127 | + WP_Reset_Utility::wp_kses_wf($this->get_card_header(__('Public Support Forum', 'wp-reset'), 'support-forum', array('collapse_button' => false))); | |
| 2128 | + echo '<div class="card-body">'; | |
| 2129 | + WP_Reset_Utility::wp_kses_wf('<p>' . __('We are very active on the <a href="https://wordpress.org/support/plugin/wp-reset" target="_blank">official WP Reset support forum</a>. If you found a bug, have a feature idea or just want to say hi - please drop by. We love to hear back from our users.', 'wp-reset') . '</p>'); | |
| 2130 | + echo '</div>'; | |
| 2131 | + echo '</div>'; // forum | |
| 2132 | + | |
| 2133 | + echo '<div class="card">'; | |
| 2134 | + WP_Reset_Utility::wp_kses_wf($this->get_card_header(__('Premium Email Support', 'wp-reset'), 'support-email', array('collapse_button' => false, 'pro' => true))); | |
| 2135 | + echo '<div class="card-body">'; | |
| 2136 | + echo '<p class="mb0">Need urgent support? Have one of our devs personally help you with your issue. All PRO license holders have access to premium email support. Get <span class="pro-feature pro-feature-text" data-feature="support-email">WP Reset <span>PRO</span></span> now.</p>'; | |
| 2137 | + echo '</div>'; | |
| 2138 | + echo '</div>'; // email support | |
| 2139 | + | |
| 2140 | + echo '<div class="card">'; | |
| 2141 | + WP_Reset_Utility::wp_kses_wf($this->get_card_header(__('Care to Help Out?', 'wp-reset'), 'support-help-out', array('collapse_button' => false))); | |
| 2142 | + echo '<div class="card-body">'; | |
| 2143 | + WP_Reset_Utility::wp_kses_wf('<p class="mb0">' . __('No need for donations :) If you can give us a <a href="https://wordpress.org/support/plugin/wp-reset/reviews/#new-post" target="_blank">five star rating</a> you\'ll help out more than you can imagine. A public mention <a href="https://twitter.com/webfactoryltd" target="_blank">@webfactoryltd</a> also does wonders. Thank you!', 'wp-reset') . '</p>'); | |
| 2144 | + echo '</div>'; | |
| 2145 | + echo '</div>'; // help out | |
| 2146 | + } // tab_support | |
| 2147 | + | |
| 2148 | + | |
| 2149 | + /** | |
| 2150 | + * Echoes content for pro tab | |
| 2151 | + * | |
| 2152 | + * @return null | |
| 2153 | + */ | |
| 2154 | + private function tab_pro() | |
| 2155 | + { | |
| 2156 | + $agency_lifetime = $this->generate_web_link('pricing-table', '/buy/', array('p' => 'wp-reset-pro-agency-ltd-launch')); | |
| 2157 | + $team_lifetime = $this->generate_web_link('pricing-table', '/', array(), 'pricing'); | |
| 2158 | + $personal_lifetime = $this->generate_web_link('pricing-table', '/buy/', array('p' => 'wp-reset-pro-personal-ltd-launch')); | |
| 2159 | + | |
| 2160 | + echo '<div class="card">'; | |
| 2161 | + WP_Reset_Utility::wp_kses_wf($this->get_card_header(__('WP Reset PRO', 'wp-reset'), 'pro-features', array('collapse_button' => false))); | |
| 2162 | + echo '<div class="card-body">'; | |
| 2163 | + echo '<p>More ways to reset your site, more tools, automatic snapshots, collections, email support and the emergency recover script - that\'s WP Reset PRO in a nutshell. The same <b>quality and easy-of-use</b> you experienced in the free version is very much a part of the PRO one, but extended and upgraded with more tools that will save you even more time.</p>'; | |
| 2164 | + echo '<p>WP Reset PRO is aimed towards <b>webmasters, agencies, and everyone who buildsa a lot of WordPress sites</b>. It\'s much, much more than a "reset" tool. It\'s an easy way to start a new site, to test changes and to get out of the thickest jams. And thanks to its cloud features and the Dashboard it\'ll give you access to collections and snapshots on all the sites you\'re working on - instantly, without dragging any files along.</p>'; | |
| 2165 | + echo '<p>Give WP Reset PRO a go. <b>It\'ll pay itself out in hours saved within the first few days!</b></p>'; | |
| 2166 | + echo '<p>If you already have a PRO license, activate it below.</p>'; | |
| 2167 | + echo '<p class="textcenter"><a href="#" data-feature="purchase-pro" class="button-pro-feature button button-delete">Get PRO now</a></p>'; | |
| 2168 | + echo '</div>'; | |
| 2169 | + echo '</div>'; | |
| 2170 | + | |
| 2171 | + echo '<div class="card">'; | |
| 2172 | + WP_Reset_Utility::wp_kses_wf($this->get_card_header(__('Activate PRO License', 'wp-reset'), 'pro-activate', array('collapse_button' => false))); | |
| 2173 | + echo '<div class="card-body">'; | |
| 2174 | + | |
| 2175 | + echo '<p>License key is visible on the confirmation screen, right after purchasing. You can also find it in the confirmation email sent to the email address provided on purchase. Or use keys created with the <a href="https://dashboard.wpreset.com/licenses/" target="_blank">license manager</a>.</p> | |
| 2176 | + <p>If you don\'t have a license - <a class="button-pro-feature" href="#" data-feature="purchase-pro2">purchase one now</a>. In case of problems with the license please <a href="' . esc_url($this->generate_web_link('pro-tab-license', '/contact/')) . '" target="_blank">contact support</a>.</p>'; | |
| 2177 | + | |
| 2178 | + echo '<hr>'; | |
| 2179 | + echo '<p><label for="wpr-license-key">License Key: </label><input class="regular-text" type="text" id="wpr-license-key" value="' . ($this->license->get_license('license_key') != 'keyless' ? esc_attr($this->license->get_license('license_key')) : '') . '" placeholder="12345678-12345678-12345678-12345678">'; | |
| 2180 | + | |
| 2181 | + echo '<br><label>Status: </label>'; | |
| 2182 | + if ($this->license->is_active()) { | |
| 2183 | + $license_formatted = $this->license->get_license_formatted(); | |
| 2184 | + echo '<b style="color: #66b317;">Active</b><br> | |
| 2185 | + <label>Type: </label>' . esc_html($license_formatted['name_long']); | |
| 2186 | + echo '<br><label>Valid: </label>' . esc_html($license_formatted['valid_until']); | |
| 2187 | + | |
| 2188 | + echo '<p>Thank you for purchasing WP Reset PRO! <b>Your license has been verified and activated.</b>'; | |
| 2189 | + echo '<br>To start using the PRO version, please follow these steps:</p>'; | |
| 2190 | + echo '<ol>'; | |
| 2191 | + echo '<li><a href="https://dashboard.wpreset.com/pro-download/" target="_blank">Download</a> the latest version of the PRO plugin.</li>'; | |
| 2192 | + echo '<li>Go to <a href="' . esc_url(admin_url('plugin-install.php')) . '">Plugins - Add New - Upload Plugin</a> and upload the ZIP you just downloaded.</li>'; | |
| 2193 | + echo '<li>If asked to replace (overwrite) the free version - confirm it.</li>'; | |
| 2194 | + echo '<li>Activate the plugin.</li>'; | |
| 2195 | + echo '<li>That\'s it, no more steps.</li>'; | |
| 2196 | + echo '</ol>'; | |
| 2197 | + } else { // not active | |
| 2198 | + echo '<strong style="color: #ea1919;">Inactive</strong>'; | |
| 2199 | + if (!empty($this->license->get_license('error'))) { | |
| 2200 | + echo '<br><label>Error: </label>' . esc_html($this->license->get_license('error')); | |
| 2201 | + } | |
| 1818 | 2202 | } |
| 1819 | - if (empty($table->Engine)) { | |
| 1820 | - continue; | |
| 1821 | - } | |
| 2203 | + echo '</p>'; | |
| 1822 | 2204 | |
| 1823 | - $tbl_rows += $table->Rows; | |
| 1824 | - $tbl_size += $table->Data_length + $table->Index_length; | |
| 1825 | - if (in_array($table->Name, $this->core_tables)) { | |
| 1826 | - $tbl_core++; | |
| 2205 | + echo '<p>'; | |
| 2206 | + if ($this->license->is_active()) { | |
| 2207 | + echo '<a href="#" id="wpr-save-license" data-text-wait="Validating. Please wait." class="button button-secondary">Save & Revalidate License</a>'; | |
| 2208 | + echo ' <a href="#" id="wpr-deactivate-license" data-text-wait="Deactivating. Please wait." class="button button-delete">Deactivate License</a>'; | |
| 1827 | 2209 | } else { |
| 1828 | - $tbl_custom++; | |
| 2210 | + echo '<a href="#" id="wpr-save-license" data-text-wait="Activating. Please wait." class="button button-primary">Save & Activate License</a>'; | |
| 2211 | + echo ' <a href="#" data-text-wait="Activating. Please wait." class="button button-secondary" id="wpr-keyless-activation">Keyless Activation</a>'; | |
| 1829 | 2212 | } |
| 1830 | - } // foreach | |
| 2213 | + echo '</p>'; | |
| 2214 | + echo '<p class="mb0"><i>By attempting to activate a license you agree to share the following data with <a target="_blank" href="https://www.webfactoryltd.com/">WebFactory Ltd</a>: license key, site URL, site title, site WP version, site IP, and WP Reset plugin (free) version.</i>'; | |
| 2215 | + echo '</p>'; | |
| 1831 | 2216 | |
| 1832 | - echo '<p><b>Currently used WordPress tables</b>, prefixed with <i>' . $wpdb->prefix . '</i>, consist of ' . $tbl_core . ' standard and '; | |
| 1833 | - if ($tbl_custom) { | |
| 1834 | - echo $tbl_custom . ' custom table' . ($tbl_custom == 1 ? '' : 's'); | |
| 1835 | - } else { | |
| 1836 | - echo 'no custom tables'; | |
| 1837 | - } | |
| 1838 | - echo ' totaling ' . $this->format_size($tbl_size) . ' in ' . number_format($tbl_rows) . ' rows.</p>'; | |
| 1839 | - } | |
| 2217 | + echo '</div>'; | |
| 2218 | + echo '</div>'; // activate PRO | |
| 1840 | 2219 | |
| 1841 | - echo ''; | |
| 1842 | - echo '</div>'; | |
| 1843 | - echo '</div>'; | |
| 2220 | + WP_Reset_Utility::wp_kses_wf($this->pro_dialog()); | |
| 2221 | + } // tab_pro | |
| 1844 | 2222 | |
| 1845 | - echo '<div class="card">'; | |
| 1846 | - echo '<h4>'; | |
| 1847 | - echo __('Snapshots', 'wp-reset'); | |
| 1848 | - echo '<div class="card-header-right"><a id="create-new-snapshot-primary" data-msg-success="Snapshot created!" data-msg-wait="Creating snapshot. Please wait." data-btn-confirm="Create snapshot" data-placeholder="Snapshot name or brief description, ie: before plugin install" data-text="Enter snapshot name or brief description, up to 64 characters." data-title="Create a new snapshot" title="Create a new database snapshot" href="#" class="button button-primary create-new-snapshot">' . __('Create Snapshot', 'wp-reset') . '</a></div>'; | |
| 1849 | - echo '</h4>'; | |
| 1850 | 2223 | |
| 1851 | - if ($snapshots = $this->get_snapshots()) { | |
| 1852 | - $snapshots = array_reverse($snapshots); | |
| 1853 | - echo '<table id="wpr-snapshots">'; | |
| 1854 | - echo '<tr><th>Date</th><th>Description</th><th class="ss-actions"> </th></tr>'; | |
| 1855 | - foreach ($snapshots as $ss) { | |
| 1856 | - echo '<tr id="wpr-ss-' . $ss['uid'] . '">'; | |
| 1857 | - if (!empty($ss['name'])) { | |
| 1858 | - $name = $ss['name']; | |
| 1859 | - } else { | |
| 1860 | - $name = 'created on ' . date(get_option('date_format'), strtotime($ss['timestamp'])) . ' @ ' . date(get_option('time_format'), strtotime($ss['timestamp'])); | |
| 1861 | - } | |
| 2224 | + function pro_dialog() | |
| 2225 | + { | |
| 2226 | + $out = ''; | |
| 1862 | 2227 | |
| 1863 | - echo '<td>'; | |
| 1864 | - if (current_time('timestamp') - strtotime($ss['timestamp']) > 12 * HOUR_IN_SECONDS) { | |
| 1865 | - echo date(get_option('date_format'), strtotime($ss['timestamp'])) . '<br>@ ' . date(get_option('time_format'), strtotime($ss['timestamp'])); | |
| 1866 | - } else { | |
| 1867 | - echo human_time_diff(strtotime($ss['timestamp']), current_time('timestamp')) . ' ago'; | |
| 1868 | - } | |
| 1869 | - echo '</td>'; | |
| 1870 | - //echo '<td title="Created on ' . date(get_option('date_format'), strtotime($ss['timestamp'])) . ' @ ' . date(get_option('time_format'), strtotime($ss['timestamp'])) . '">' . '' . date(get_option('date_format'), strtotime($ss['timestamp'])) . '<br>@ ' . date(get_option('time_format'), strtotime($ss['timestamp'])) . '</td>'; | |
| 2228 | + $out .= '<div id="wpreset-pro-dialog" style="display: none;" title="WP Reset PRO"><span class="ui-helper-hidden-accessible"><input type="text"/></span>'; | |
| 1871 | 2229 | |
| 1872 | - echo '<td>'; | |
| 1873 | - if (!empty($ss['name'])) { | |
| 1874 | - echo '<b>' . $ss['name'] . '</b><br>'; | |
| 1875 | - } | |
| 1876 | - echo $ss['tbl_core'] . ' standard & '; | |
| 1877 | - if ($ss['tbl_custom']) { | |
| 1878 | - echo $ss['tbl_custom'] . ' custom table' . ($ss['tbl_custom'] == 1 ? '' : 's'); | |
| 1879 | - } else { | |
| 1880 | - echo 'no custom tables'; | |
| 1881 | - } | |
| 1882 | - echo ' totaling ' . $this->format_size($ss['tbl_size']) . ' in ' . number_format($ss['tbl_rows']) . ' rows</td>'; | |
| 1883 | - echo '<td>'; | |
| 1884 | - echo '<div class="dropdown"> | |
| 1885 | - <a class="button dropdown-toggle" href="#">Actions</a> | |
| 1886 | - <div class="dropdown-menu">'; | |
| 1887 | - echo '<a data-title="Current DB tables compared to snapshot %s" data-wait-msg="Comparing. Please wait." data-name="' . $name . '" title="Compare snapshot to current database tables" href="#" class="ss-action compare-snapshot dropdown-item" data-ss-uid="' . $ss['uid'] . '">Compare snapshot to current data</a>'; | |
| 1888 | - echo '<a data-btn-confirm="Restore snapshot" data-text-wait="Restoring snapshot. Please wait." data-text-confirm="Are you sure you want to restore the selected snapshot? There is NO UNDO.<br>Restoring the snapshot will delete all current standard and custom tables and replace them with tables from the snapshot." data-text-done="Snapshot has been restored. Click OK to reload the page with new data." title="Restore snapshot by overwriting current database tables" href="#" class="ss-action restore-snapshot dropdown-item" data-ss-uid="' . $ss['uid'] . '">Restore snapshot</a>'; | |
| 1889 | - echo '<a data-success-msg="Snapshot export created!<br><a href=\'%s\'>Download it</a>" data-wait-msg="Exporting snapshot. Please wait." title="Download snapshot as gzipped SQL dump" href="#" class="ss-action download-snapshot dropdown-item" data-ss-uid="' . $ss['uid'] . '">Download snapshot</a>'; | |
| 1890 | - echo '<a data-btn-confirm="Delete snapshot" data-text-wait="Deleting snapshot. Please wait." data-text-confirm="Are you sure you want to delete the selected snapshot and all its data? There is NO UNDO.<br>Deleting the snapshot will not affect the active database tables in any way." data-text-done="Snapshot has been deleted." title="Permanently delete snapshot" href="#" class="ss-action delete-snapshot dropdown-item" data-ss-uid="' . $ss['uid'] . '">Delete snapshot</a></div></div></td>'; | |
| 1891 | - echo '</tr>'; | |
| 1892 | - } // foreach | |
| 1893 | - echo '</table>'; | |
| 1894 | - echo '<p id="ss-no-snapshots" class="hidden">There are no saved snapshots. <a href="#" class="create-new-snapshot">Create a new snapshot.</a></p>'; | |
| 1895 | - } else { | |
| 1896 | - echo '<p id="ss-no-snapshots">There are no saved snapshots. <a href="#" class="create-new-snapshot">Create a new snapshot.</a></p>'; | |
| 1897 | - } | |
| 2230 | + $out .= '<div class="center logo"><a href="https://wpreset.com/?ref=wpreset-free-pricing-table" target="_blank"><img src="' . $this->plugin_url . 'img/wp-reset-logo.png' . '" alt="WP Reset PRO" title="WP Reset PRO"></a><br>'; | |
| 1898 | 2231 | |
| 1899 | - echo '</div>'; | |
| 1900 | - } // tab_snapshots | |
| 2232 | + $out .= '<span>Limited PRO Offer - <b>all prices are LIFETIME</b>! Pay once & use forever!</span>'; | |
| 2233 | + $out .= '</div>'; | |
| 1901 | 2234 | |
| 2235 | + $out .= '<table id="wpreset-pro-table">'; | |
| 2236 | + $out .= '<tr>'; | |
| 2237 | + $out .= '<td class="center">Lifetime Personal License</td>'; | |
| 2238 | + $out .= '<td class="center">Lifetime Team License</td>'; | |
| 2239 | + $out .= '<td class="center">Lifetime Agency License</td>'; | |
| 2240 | + $out .= '</tr>'; | |
| 1902 | 2241 | |
| 1903 | - /** | |
| 1904 | - * Helper function for generating UTM tagged links | |
| 1905 | - * | |
| 1906 | - * @param string $placement Optional. UTM content param. | |
| 1907 | - * @param string $page Optional. Page to link to. | |
| 1908 | - * @param array $params Optional. Extra URL params. | |
| 1909 | - * @param string $anchor Optional. URL anchor part. | |
| 1910 | - * | |
| 1911 | - * @return string | |
| 1912 | - */ | |
| 1913 | - function generate_web_link($placement = '', $page = '/', $params = array(), $anchor = '') | |
| 1914 | - { | |
| 1915 | - $base_url = 'https://wpreset.com'; | |
| 2242 | + $out .= '<tr class="prices">'; | |
| 2243 | + $out .= '<td class="center"><del>$39 /year</del><br><span>$59</span> <b>/lifetime</b></td>'; | |
| 2244 | + $out .= '<td class="center"><del>$79 /year</del><br><span>$69</span> <b>/lifetime</b></td>'; | |
| 2245 | + $out .= '<td class="center"><del>$119 /year</del><br><span>$149</span> <b>/lifetime</b></td>'; | |
| 2246 | + $out .= '</tr>'; | |
| 1916 | 2247 | |
| 1917 | - if ('/' != $page) { | |
| 1918 | - $page = '/' . trim($page, '/') . '/'; | |
| 1919 | - } | |
| 1920 | - if ($page == '//') { | |
| 1921 | - $page = '/'; | |
| 1922 | - } | |
| 2248 | + $out .= '<tr>'; | |
| 2249 | + $out .= '<td><span class="dashicons dashicons-yes"></span><b>1 Site License</b></td>'; | |
| 2250 | + $out .= '<td><span class="dashicons dashicons-yes"></span><b>5 Sites License</b></td>'; | |
| 2251 | + $out .= '<td><span class="dashicons dashicons-yes"></span><b>100 Sites License</b></td>'; | |
| 2252 | + $out .= '</tr>'; | |
| 1923 | 2253 | |
| 1924 | - $parts = array_merge(array('utm_source' => 'wp-reset-free', 'utm_medium' => 'plugin', 'utm_content' => $placement, 'utm_campaign' => 'wp-reset-free-v' . $this->version), $params); | |
| 2254 | + $out .= '<tr>'; | |
| 2255 | + $out .= '<td><span class="dashicons dashicons-yes"></span>All Plugin Features & Tools</td>'; | |
| 2256 | + $out .= '<td><span class="dashicons dashicons-yes"></span>All Plugin Features & Tools</td>'; | |
| 2257 | + $out .= '<td><span class="dashicons dashicons-yes"></span>All Plugin Features & Tools</td>'; | |
| 2258 | + $out .= '</tr>'; | |
| 1925 | 2259 | |
| 1926 | - if (!empty($anchor)) { | |
| 1927 | - $anchor = '#' . trim($anchor, '#'); | |
| 1928 | - } | |
| 2260 | + $out .= '<tr>'; | |
| 2261 | + $out .= '<td><span class="dashicons dashicons-yes"></span>Lifetime Updates & Support</td>'; | |
| 2262 | + $out .= '<td><span class="dashicons dashicons-yes"></span>Lifetime Updates & Support</td>'; | |
| 2263 | + $out .= '<td><span class="dashicons dashicons-yes"></span>Lifetime Updates & Support</td>'; | |
| 2264 | + $out .= '</tr>'; | |
| 1929 | 2265 | |
| 1930 | - $out = $base_url . $page . '?' . http_build_query($parts, '', '&') . $anchor; | |
| 2266 | + $out .= '<tr>'; | |
| 2267 | + $out .= '<td><span class="dashicons dashicons-yes"></span>2 GB WP Reset Cloud Storage</td>'; | |
| 2268 | + $out .= '<td><span class="dashicons dashicons-yes"></span>10 GB WP Reset Cloud Storage</td>'; | |
| 2269 | + $out .= '<td><span class="dashicons dashicons-yes"></span>100 GB WP Reset Cloud Storage</td>'; | |
| 2270 | + $out .= '</tr>'; | |
| 1931 | 2271 | |
| 1932 | - return $out; | |
| 1933 | - } // generate_web_link | |
| 2272 | + $out .= '<tr>'; | |
| 2273 | + $out .= '<td><span class="dashicons dashicons-yes"></span>Dropbox & Google Drive support</td>'; | |
| 2274 | + $out .= '<td><span class="dashicons dashicons-yes"></span>Dropbox & Google Drive support</td>'; | |
| 2275 | + $out .= '<td><span class="dashicons dashicons-yes"></span>Dropbox & Google Drive support</td>'; | |
| 2276 | + $out .= '</tr>'; | |
| 1934 | 2277 | |
| 2278 | + $out .= '<tr>'; | |
| 2279 | + $out .= '<td><span class="dashicons dashicons-yes"></span>Plugins & Themes Collections</td>'; | |
| 2280 | + $out .= '<td><span class="dashicons dashicons-yes"></span>Plugins & Themes Collections</td>'; | |
| 2281 | + $out .= '<td><span class="dashicons dashicons-yes"></span>Plugins & Themes Collections</td>'; | |
| 2282 | + $out .= '</tr>'; | |
| 1935 | 2283 | |
| 1936 | - /** | |
| 1937 | - * Returns all saved snapshots from DB | |
| 1938 | - * | |
| 1939 | - * @return array | |
| 1940 | - */ | |
| 1941 | - function get_snapshots() | |
| 1942 | - { | |
| 1943 | - $snapshots = get_option('wp-reset-snapshots', array()); | |
| 2284 | + $out .= '<tr>'; | |
| 2285 | + $out .= '<td><span class="dashicons dashicons-yes"></span>Automatic Snapshots</td>'; | |
| 2286 | + $out .= '<td><span class="dashicons dashicons-yes"></span>Automatic Snapshots</td>'; | |
| 2287 | + $out .= '<td><span class="dashicons dashicons-yes"></span>Automatic Snapshots</td>'; | |
| 2288 | + $out .= '</tr>'; | |
| 1944 | 2289 | |
| 1945 | - return $snapshots; | |
| 1946 | - } // get_snapshots | |
| 2290 | + $out .= '<tr>'; | |
| 2291 | + $out .= '<td><span class="dashicons dashicons-yes"></span>Emergency Recovery Script</td>'; | |
| 2292 | + $out .= '<td><span class="dashicons dashicons-yes"></span>Emergency Recovery Script</td>'; | |
| 2293 | + $out .= '<td><span class="dashicons dashicons-yes"></span>Emergency Recovery Script</td>'; | |
| 2294 | + $out .= '</tr>'; | |
| 1947 | 2295 | |
| 2296 | + $out .= '<tr>'; | |
| 2297 | + $out .= '<td><span class="dashicons dashicons-no"></span>Licenses & Sites Manager</td>'; | |
| 2298 | + $out .= '<td><span class="dashicons dashicons-yes"></span>Licenses & Sites Manager</td>'; | |
| 2299 | + $out .= '<td><span class="dashicons dashicons-yes"></span>Licenses & Sites Manager</td>'; | |
| 2300 | + $out .= '</tr>'; | |
| 1948 | 2301 | |
| 1949 | - /** | |
| 1950 | - * Returns all custom table names, with prefix | |
| 1951 | - * | |
| 1952 | - * @return array | |
| 1953 | - */ | |
| 1954 | - function get_custom_tables() | |
| 1955 | - { | |
| 1956 | - global $wpdb; | |
| 1957 | - $custom_tables = array(); | |
| 2302 | + $out .= '<tr>'; | |
| 2303 | + $out .= '<td><span class="dashicons dashicons-no"></span>White-label Mode</td>'; | |
| 2304 | + $out .= '<td><span class="dashicons dashicons-yes"></span>White-label Mode</td>'; | |
| 2305 | + $out .= '<td><span class="dashicons dashicons-yes"></span>White-label Mode</td>'; | |
| 2306 | + $out .= '</tr>'; | |
| 1958 | 2307 | |
| 1959 | - $table_status = $wpdb->get_results('SHOW TABLE STATUS'); | |
| 1960 | - if (is_array($table_status)) { | |
| 1961 | - foreach ($table_status as $index => $table) { | |
| 1962 | - if (0 !== stripos($table->Name, $wpdb->prefix)) { | |
| 1963 | - continue; | |
| 1964 | - } | |
| 1965 | - if (empty($table->Engine)) { | |
| 1966 | - continue; | |
| 1967 | - } | |
| 2308 | + $out .= '<tr>'; | |
| 2309 | + $out .= '<td><span class="dashicons dashicons-no"></span>Full Plugin Rebranding</td>'; | |
| 2310 | + $out .= '<td><span class="dashicons dashicons-no"></span>Full Plugin Rebranding</td>'; | |
| 2311 | + $out .= '<td><span class="dashicons dashicons-yes"></span>Full Plugin Rebranding</td>'; | |
| 2312 | + $out .= '</tr>'; | |
| 1968 | 2313 | |
| 1969 | - if (false === in_array($table->Name, $this->core_tables)) { | |
| 1970 | - $custom_tables[] = array('name' => $table->Name, 'rows' => $table->Rows, 'data_length' => $table->Data_length, 'index_length' => $table->Index_length); | |
| 1971 | - } | |
| 1972 | - } // foreach | |
| 1973 | - } | |
| 2314 | + $out .= '<tr>'; | |
| 2315 | + $out .= '<td><a class="button button-buy" data-href-org="https://wpreset.com/buy2/?product=personal-free&ref=pricing-table" href="https://wpreset.com/buy2/?product=personal-free&ref=pricing-table" target="_blank">Lifetime License<br>$59 -> BUY NOW</a> | |
| 2316 | + <br>or <a class="button-buy" data-href-org="https://wpreset.com/buy2/?product=personal-monthly&ref=pricing-table" href="https://wpreset.com/buy2/?product=personal-monthly&ref=pricing-table" target="_blank">only $6.99 <small>/month</small></a></td>'; | |
| 2317 | + $out .= '<td><a class="button button-buy" data-href-org="https://wpreset.com/buy2/?product=team-free&ref=pricing-table" href="https://wpreset.com/buy2/?product=team-free&ref=pricing-table" target="_blank">Lifetime License<br>$69 -> BUY NOW</a></td>'; | |
| 2318 | + $out .= '<td><a class="button button-buy" data-href-org="https://wpreset.com/buy2/?product=agency-free&ref=pricing-table" href="https://wpreset.com/buy2/?product=agency-free&ref=pricing-table" target="_blank">Lifetime License<br>$149 -> BUY NOW</a></td>'; | |
| 2319 | + $out .= '</tr>'; | |
| 1974 | 2320 | |
| 1975 | - return $custom_tables; | |
| 1976 | - } // get_custom tables | |
| 2321 | + $out .= '</table>'; | |
| 1977 | 2322 | |
| 2323 | + $out .= '<div class="center footer"><b>100% No-Risk Money Back Guarantee!</b> If you don\'t like the plugin over the next 7 days, we will happily refund 100% of your money. No questions asked! Payments are processed by our merchant of records - <a href="https://paddle.com/" target="_blank">Paddle</a>.</div></div>'; | |
| 1978 | 2324 | |
| 1979 | - /** | |
| 1980 | - * Format file size to human readable string | |
| 1981 | - * | |
| 1982 | - * @param int $bytes Size in bytes to format. | |
| 1983 | - * | |
| 1984 | - * @return string | |
| 1985 | - */ | |
| 1986 | - function format_size($bytes) | |
| 1987 | - { | |
| 1988 | - if ($bytes > 1073741824) { | |
| 1989 | - return number_format_i18n($bytes / 1073741824, 2) . ' GB'; | |
| 1990 | - } elseif ($bytes > 1048576) { | |
| 1991 | - return number_format_i18n($bytes / 1048576, 1) . ' MB'; | |
| 1992 | - } elseif ($bytes > 1024) { | |
| 1993 | - return number_format_i18n($bytes / 1024, 1) . ' KB'; | |
| 1994 | - } else { | |
| 1995 | - return number_format_i18n($bytes, 0) . ' bytes'; | |
| 1996 | - } | |
| 1997 | - } // format_size | |
| 2325 | + return $out; | |
| 2326 | + } // pro_dialog | |
| 1998 | 2327 | |
| 1999 | 2328 | |
| 2000 | - /** | |
| 2001 | - * Creates snapshot of current tables by copying them in the DB and saving metadata. | |
| 2002 | - * | |
| 2003 | - * @param int $name Optional. Name for the new snapshot. | |
| 2004 | - * | |
| 2005 | - * @return array|WP_Error Snapshot details in array on success, or error object on fail. | |
| 2006 | - */ | |
| 2007 | - function do_create_snapshot($name = '') | |
| 2008 | - { | |
| 2009 | - global $wpdb; | |
| 2010 | - $snapshots = $this->get_snapshots(); | |
| 2011 | - $snapshot = array(); | |
| 2012 | - $uid = $this->generate_snapshot_uid(); | |
| 2013 | - $tbl_core = $tbl_custom = $tbl_size = $tbl_rows = 0; | |
| 2329 | + /** | |
| 2330 | + * Echoes content for snapshots tab | |
| 2331 | + * | |
| 2332 | + * @return null | |
| 2333 | + */ | |
| 2334 | + private function tab_snapshots() | |
| 2335 | + { | |
| 2336 | + global $wpdb; | |
| 2337 | + $tbl_core = $tbl_custom = $tbl_size = $tbl_rows = 0; | |
| 2014 | 2338 | |
| 2015 | - if (!$uid) { | |
| 2016 | - return new WP_Error(1, 'Unable to generate a valid snapshot UID.'); | |
| 2017 | - } | |
| 2339 | + echo '<div class="card" id="card-snapshots">'; | |
| 2340 | + echo '<h4>'; | |
| 2341 | + echo esc_html__('Snapshots', 'wp-reset'); | |
| 2342 | + echo '<div class="card-header-right"><a class="toggle-card tooltip" href="#" title="' . esc_html__('Collapse / expand box', 'wp-reset') . '"><span class="dashicons dashicons-arrow-up-alt2"></span></a></div>'; | |
| 2343 | + echo '</h4>'; | |
| 2344 | + echo '<div class="card-body">'; | |
| 2345 | + echo '<p>A snapshot is a copy of all WP database tables, standard and custom ones, saved in the site\'s database. <a href="https://www.youtube.com/watch?v=xBfMmS12vMY" target="_blank">Watch a short video</a> overview and tutorial about Snapshots.</p>'; | |
| 2018 | 2346 | |
| 2019 | - if ($name) { | |
| 2020 | - $snapshot['name'] = substr(trim($name), 0, 64); | |
| 2021 | - } else { | |
| 2022 | - $snapshot['name'] = ''; | |
| 2023 | - } | |
| 2024 | - $snapshot['uid'] = $uid; | |
| 2025 | - $snapshot['timestamp'] = current_time('mysql'); | |
| 2347 | + echo '<p>Snapshots are primarily a development tool. When using various reset tools we advise using our 1-click snapshot tool available in every tool\'s confirmation dialog. If a full backup that includes files is needed, use one of the <a href="' . esc_url(admin_url('plugin-install.php?s=backup&tab=search&type=term')) . '" target="_blank">backup plugins</a> from the repo.</p>'; | |
| 2026 | 2348 | |
| 2027 | - $table_status = $wpdb->get_results('SHOW TABLE STATUS'); | |
| 2028 | - if (is_array($table_status)) { | |
| 2029 | - foreach ($table_status as $index => $table) { | |
| 2030 | - if (0 !== stripos($table->Name, $wpdb->prefix)) { | |
| 2031 | - continue; | |
| 2349 | + echo '<p>Use snapshots to find out what changes a plugin made to your database or to quickly restore the dev environment after testing database related changes. Restoring a snapshot does not affect other snapshots, or WP Reset settings.</p>'; | |
| 2350 | + | |
| 2351 | + echo '<p>To automatically generate snapshots on plugin, theme, and core update, activate, deactivate and similar events enable automatic snapshots available in <span class="pro-feature pro-feature-text" data-feature="snapshots-auto">WP Reset <span>PRO</span></span>.</p>'; | |
| 2352 | + | |
| 2353 | + // phpcs:ignore db call warning as we are using uncommon queries | |
| 2354 | + $tables = $wpdb->get_results('SHOW TABLES', ARRAY_N); // phpcs:ignore | |
| 2355 | + if (is_array($tables)) { | |
| 2356 | + foreach ($tables as $table) { | |
| 2357 | + if (0 !== stripos($table[0], $wpdb->prefix)) { | |
| 2358 | + continue; | |
| 2359 | + } | |
| 2360 | + | |
| 2361 | + if (in_array($table[0], $this->core_tables)) { | |
| 2362 | + $tbl_core++; | |
| 2363 | + } else { | |
| 2364 | + $tbl_custom++; | |
| 2365 | + } | |
| 2366 | + } // foreach | |
| 2367 | + | |
| 2368 | + echo '<p class="mb0"><b>Currently used WordPress tables</b>, prefixed with <i>' . esc_html($wpdb->prefix) . '</i>, consist of ' . esc_html($tbl_core) . ' standard and '; | |
| 2369 | + if ($tbl_custom) { | |
| 2370 | + echo esc_attr($tbl_custom) . ' custom table' . ($tbl_custom == 1 ? '' : 's'); | |
| 2371 | + } else { | |
| 2372 | + echo 'no custom tables'; | |
| 2373 | + } | |
| 2374 | + echo ' <span id="wpr-table-details"><a href="#" id="show-table-details">(show details)</a></span>'; | |
| 2375 | + } else { | |
| 2376 | + echo '<b>Tables information is not available.</b> Something is not working properly on your site. Snapshots won\'t work.'; | |
| 2032 | 2377 | } |
| 2033 | - if (empty($table->Engine)) { | |
| 2034 | - continue; | |
| 2035 | - } | |
| 2036 | 2378 | |
| 2037 | - $tbl_rows += $table->Rows; | |
| 2038 | - $tbl_size += $table->Data_length + $table->Index_length; | |
| 2039 | - if (in_array($table->Name, $this->core_tables)) { | |
| 2040 | - $tbl_core++; | |
| 2379 | + echo '</div>'; | |
| 2380 | + echo '</div>'; | |
| 2381 | + | |
| 2382 | + echo '<div class="card">'; | |
| 2383 | + WP_Reset_Utility::wp_kses_wf($this->get_card_header('User Created Snapshots', 'snapshots-user', array('collapse_button' => 1, 'create_snapshot' => true, 'snapshot_actions' => true))); | |
| 2384 | + echo '<div class="card-body">'; | |
| 2385 | + if ($snapshots = $this->get_snapshots()) { | |
| 2386 | + $snapshots = array_reverse($snapshots); | |
| 2387 | + echo '<table id="wpr-snapshots">'; | |
| 2388 | + echo '<tr><th>Date</th><th>Description</th><th class="ss-size">Size</th><th class="ss-actions"> | |
| 2389 | + <div class="dropdown" style="font-weight:normal; margin-left: 4px;"><a class="button dropdown-toggle" href="#">Actions</a> | |
| 2390 | + <div class="dropdown-menu"> | |
| 2391 | + <a class="dropdown-item button-pro-feature" href="#">Import a snapshot - <span class="pro-feature" data-feature="snapshots"><span class="pro">PRO</span> Feature</span></a> | |
| 2392 | + <a class="dropdown-item button-pro-feature" href="#">Cloud snapshots - <span class="pro-feature" data-feature="snapshots"><span class="pro">PRO</span> Feature</span></a> | |
| 2393 | + </div> | |
| 2394 | + </div></th></tr>'; | |
| 2395 | + foreach ($snapshots as $ss) { | |
| 2396 | + echo '<tr id="wpr-ss-' . esc_attr($ss['uid']) . '">'; | |
| 2397 | + if (!empty($ss['name'])) { | |
| 2398 | + $name = $ss['name']; | |
| 2399 | + } else { | |
| 2400 | + $name = 'created on ' . gmdate(get_option('date_format'), strtotime($ss['timestamp'])) . ' @ ' . gmdate(get_option('time_format'), strtotime($ss['timestamp'])); | |
| 2401 | + } | |
| 2402 | + | |
| 2403 | + echo '<td>'; | |
| 2404 | + if (current_time('timestamp') - strtotime($ss['timestamp']) > 12 * HOUR_IN_SECONDS) { | |
| 2405 | + echo esc_attr(gmdate(get_option('date_format'), strtotime($ss['timestamp']))) . '<br>@ ' . esc_attr(gmdate(get_option('time_format'), strtotime($ss['timestamp']))); | |
| 2406 | + } else { | |
| 2407 | + echo esc_attr(human_time_diff(strtotime($ss['timestamp']), current_time('timestamp'))) . ' ago'; | |
| 2408 | + } | |
| 2409 | + echo '</td>'; | |
| 2410 | + | |
| 2411 | + echo '<td>'; | |
| 2412 | + if (!empty($ss['name'])) { | |
| 2413 | + echo '<b>' . esc_html($ss['name']) . '</b><br>'; | |
| 2414 | + } | |
| 2415 | + echo esc_attr($ss['tbl_core']) . ' standard & '; | |
| 2416 | + if ($ss['tbl_custom']) { | |
| 2417 | + echo esc_attr($ss['tbl_custom']) . ' custom table' . ($ss['tbl_custom'] == 1 ? '' : 's'); | |
| 2418 | + } else { | |
| 2419 | + echo 'no custom tables'; | |
| 2420 | + } | |
| 2421 | + echo ' totaling ' . esc_attr(number_format($ss['tbl_rows'])) . ' rows</td>'; | |
| 2422 | + echo '<td class="ss-size">' . esc_attr(WP_Reset_Utility::format_size($ss['tbl_size'])) . '</td>'; | |
| 2423 | + echo '<td>'; | |
| 2424 | + echo '<div class="dropdown"> | |
| 2425 | + <a class="button dropdown-toggle" href="#">Actions</a> | |
| 2426 | + <div class="dropdown-menu">'; | |
| 2427 | + echo '<a data-title="Current DB tables compared to snapshot %s" data-wait-msg="Comparing. Please wait." data-name="' . esc_attr($name) . '" title="Compare snapshot to current database tables" href="#" class="ss-action compare-snapshot dropdown-item tooltip" data-ss-uid="' . esc_attr($ss['uid']) . '">Compare snapshot to current data</a>'; | |
| 2428 | + echo '<a data-btn-confirm="Restore snapshot" data-text-wait="Restoring snapshot. Please wait." data-text-confirm="Are you sure you want to restore the selected snapshot? There is NO UNDO.<br>Restoring the snapshot will delete all current standard and custom tables and replace them with tables from the snapshot." data-text-done="Snapshot has been restored. Click OK to reload the page with new data." title="Restore snapshot by overwriting current database tables" href="#" class="ss-action restore-snapshot dropdown-item tooltip" data-ss-uid="' . esc_attr($ss['uid']) . '">Restore snapshot</a>'; | |
| 2429 | + echo '<a data-success-msg="Snapshot export created!<br><a href=\'%s\'>Download it</a>" data-wait-msg="Exporting snapshot. Please wait." title="Download snapshot as gzipped SQL dump" href="#" class="ss-action download-snapshot dropdown-item tooltip" data-ss-uid="' . esc_attr($ss['uid']) . '">Download snapshot</a>'; | |
| 2430 | + echo '<a data-btn-confirm="Delete snapshot" data-text-wait="Deleting snapshot. Please wait." data-text-confirm="Are you sure you want to delete the selected snapshot and all its data? There is NO UNDO.<br>Deleting the snapshot will not affect the active database tables in any way." data-text-done="Snapshot has been deleted." title="Permanently delete snapshot" href="#" class="ss-action delete-snapshot dropdown-item tooltip" data-ss-uid="' . esc_attr($ss['uid']) . '">Delete snapshot</a>'; | |
| 2431 | + echo '<a href="#" title="WP Reset PRO feature" data-feature="cloud-wpr" class="ss-action dropdown-item button-pro-feature tooltip">Upload to WP Reset Cloud - <span class="pro-feature" data-feature="cloud-wpr"><span class="pro">PRO</span> Feature</span></a>'; | |
| 2432 | + echo '<a href="#" title="WP Reset PRO feature" class="ss-action dropdown-item button-pro-feature tooltip" data-feature="cloud-general">Upload to Dropbox, Google Drive, or pCloud - <span class="pro-feature" data-feature="cloud-general"><span class="pro">PRO</span> Feature</span></a>'; | |
| 2433 | + echo '</div></div></td>'; | |
| 2434 | + echo '</tr>'; | |
| 2435 | + } // foreach | |
| 2436 | + echo '</table>'; | |
| 2437 | + echo '<p id="ss-no-snapshots" class="mb0 textcenter hidden">There are no user created snapshots. <a href="#" class="create-new-snapshot">Create a new snapshot.</a></p>'; | |
| 2041 | 2438 | } else { |
| 2042 | - $tbl_custom++; | |
| 2439 | + echo '<p id="ss-no-snapshots" class="mb0 textcenter">There are no user created snapshots. <a href="#" class="create-new-snapshot">Create a new snapshot.</a></p>'; | |
| 2043 | 2440 | } |
| 2441 | + echo '</div>'; | |
| 2442 | + echo '</div>'; | |
| 2044 | 2443 | |
| 2045 | - $wpdb->query('OPTIMIZE TABLE ' . $table->Name); | |
| 2046 | - $wpdb->query('CREATE TABLE ' . $uid . '_' . $table->Name . ' LIKE ' . $table->Name); | |
| 2047 | - $wpdb->query('INSERT ' . $uid . '_' . $table->Name . ' SELECT * FROM ' . $table->Name); | |
| 2048 | - } // foreach | |
| 2049 | - } else { | |
| 2050 | - return new WP_Error(1, 'Can\'t get table status data.'); | |
| 2051 | - } | |
| 2444 | + echo '<div class="card">'; | |
| 2445 | + WP_Reset_Utility::wp_kses_wf($this->get_card_header('Automatic Snapshots', 'snapshots-auto', array('collapse_button' => false, 'pro' => true))); | |
| 2446 | + echo '<div class="card-body">'; | |
| 2447 | + echo '<p><span class="pro-feature pro-feature-text" data-feature="snapshots-auto">WP Reset <span>PRO</span></span> creates automatic snapshots before significant events occur on your site that can cause it to stop working correctly. Plugin, theme and core updates, plugin and theme activations and deactivations all of those can happen in the background without your knowledge. With automatic snapshots, you can roll back any update with a single click. Snapshots can be uploaded to the WP Reset Cloud, Dropbox, Google Drive or pCloud, giving you an extra layer of security.<br> | |
| 2448 | + Upgrade to <span class="pro-feature pro-feature-text" data-feature="snapshots-auto">WP Reset <span>PRO</span></span> to enable automatic snapshots and give your site an extra layer of safety.</p>'; | |
| 2449 | + echo '</div>'; | |
| 2450 | + echo '</div>'; | |
| 2451 | + } // tab_snapshots | |
| 2052 | 2452 | |
| 2053 | - $snapshot['tbl_core'] = $tbl_core; | |
| 2054 | - $snapshot['tbl_custom'] = $tbl_custom; | |
| 2055 | - $snapshot['tbl_rows'] = $tbl_rows; | |
| 2056 | - $snapshot['tbl_size'] = $tbl_size; | |
| 2057 | 2453 | |
| 2454 | + /** | |
| 2455 | + * Helper function for generating links | |
| 2456 | + * | |
| 2457 | + * @param string $placement Optional. UTM content param. | |
| 2458 | + * @param string $page Optional. Page to link to. | |
| 2459 | + * @param array $params Optional. Extra URL params. | |
| 2460 | + * @param string $anchor Optional. URL anchor part. | |
| 2461 | + * | |
| 2462 | + * @return string | |
| 2463 | + */ | |
| 2464 | + function generate_web_link($placement = '', $page = '/', $params = array(), $anchor = '') | |
| 2465 | + { | |
| 2466 | + $base_url = 'https://wpreset.com'; | |
| 2058 | 2467 | |
| 2059 | - $snapshots[$uid] = $snapshot; | |
| 2060 | - update_option('wp-reset-snapshots', $snapshots); | |
| 2468 | + if ('/' != $page) { | |
| 2469 | + $page = '/' . trim($page, '/') . '/'; | |
| 2470 | + } | |
| 2471 | + if ($page == '//') { | |
| 2472 | + $page = '/'; | |
| 2473 | + } | |
| 2061 | 2474 | |
| 2062 | - do_action('wp_reset_create_snapshot', $uid, $snapshot); | |
| 2475 | + if ($placement) { | |
| 2476 | + $placement = trim($placement); | |
| 2477 | + $placement = '-' . $placement; | |
| 2478 | + } | |
| 2063 | 2479 | |
| 2064 | - return $snapshot; | |
| 2065 | - } // create_snapshot | |
| 2480 | + $parts = array_merge(array('ref' => 'wp-reset-free' . $placement), $params); | |
| 2066 | 2481 | |
| 2482 | + if (!empty($anchor)) { | |
| 2483 | + $anchor = '#' . trim($anchor, '#'); | |
| 2484 | + } | |
| 2067 | 2485 | |
| 2068 | - /** | |
| 2069 | - * Delete snapshot metadata and tables from DB | |
| 2070 | - * | |
| 2071 | - * @param string $uid Snapshot unique 6-char ID. | |
| 2072 | - * | |
| 2073 | - * @return bool|WP_Error True on success, or error object on fail. | |
| 2074 | - */ | |
| 2075 | - function do_delete_snapshot($uid = '') | |
| 2076 | - { | |
| 2077 | - global $wpdb; | |
| 2078 | - $snapshots = $this->get_snapshots(); | |
| 2486 | + $out = $base_url . $page . '?' . http_build_query($parts, '', '&') . $anchor; | |
| 2079 | 2487 | |
| 2080 | - if (strlen($uid) != 6) { | |
| 2081 | - return new WP_Error(1, 'Invalid UID format.'); | |
| 2082 | - } | |
| 2488 | + return $out; | |
| 2489 | + } // generate_web_link | |
| 2083 | 2490 | |
| 2084 | - if (!isset($snapshots[$uid])) { | |
| 2085 | - return new WP_Error(1, 'Unknown snapshot ID.'); | |
| 2086 | - } | |
| 2087 | 2491 | |
| 2088 | - $tables = $wpdb->get_col($wpdb->prepare('SHOW TABLES LIKE %s', array($uid . '\_%'))); | |
| 2089 | - foreach ($tables as $table) { | |
| 2090 | - $wpdb->query('DROP TABLE IF EXISTS ' . $table); | |
| 2091 | - } | |
| 2492 | + /** | |
| 2493 | + * Returns all saved snapshots from DB | |
| 2494 | + * | |
| 2495 | + * @return array | |
| 2496 | + */ | |
| 2497 | + function get_snapshots() | |
| 2498 | + { | |
| 2499 | + $snapshots = get_option('wp-reset-snapshots', array()); | |
| 2092 | 2500 | |
| 2093 | - $snapshot_copy = $snapshots[$uid]; | |
| 2094 | - unset($snapshots[$uid]); | |
| 2095 | - update_option('wp-reset-snapshots', $snapshots); | |
| 2501 | + return $snapshots; | |
| 2502 | + } // get_snapshots | |
| 2096 | 2503 | |
| 2097 | - do_action('wp_reset_delete_snapshot', $uid, $snapshot_copy); | |
| 2098 | 2504 | |
| 2099 | - return true; | |
| 2100 | - } // delete_snapshot | |
| 2505 | + /** | |
| 2506 | + * Returns all custom table names, with prefix | |
| 2507 | + * | |
| 2508 | + * @return array | |
| 2509 | + */ | |
| 2510 | + function get_custom_tables() | |
| 2511 | + { | |
| 2512 | + global $wpdb; | |
| 2513 | + $custom_tables = array(); | |
| 2101 | 2514 | |
| 2515 | + // phpcs:ignore db call warning as we are using uncommon queries | |
| 2516 | + $table_status = $wpdb->get_results('SHOW TABLE STATUS'); // phpcs:ignore | |
| 2517 | + if (is_array($table_status)) { | |
| 2518 | + foreach ($table_status as $index => $table) { | |
| 2519 | + if (0 !== stripos($table->Name, $wpdb->prefix)) { | |
| 2520 | + continue; | |
| 2521 | + } | |
| 2522 | + if (empty($table->Engine)) { | |
| 2523 | + continue; | |
| 2524 | + } | |
| 2102 | 2525 | |
| 2103 | - /** | |
| 2104 | - * Exports snapshot as SQL dump; saved in gzipped file in WP_CONTENT folder. | |
| 2105 | - * | |
| 2106 | - * @param string $uid Snapshot unique 6-char ID. | |
| 2107 | - * | |
| 2108 | - * @return string|WP_Error Export base filename, or error object on fail. | |
| 2109 | - */ | |
| 2110 | - function do_export_snapshot($uid = '') | |
| 2111 | - { | |
| 2112 | - $snapshots = $this->get_snapshots(); | |
| 2526 | + if (false === in_array($table->Name, $this->core_tables)) { | |
| 2527 | + $custom_tables[] = array('name' => $table->Name, 'rows' => $table->Rows, 'data_length' => $table->Data_length, 'index_length' => $table->Index_length); | |
| 2528 | + } | |
| 2529 | + } // foreach | |
| 2530 | + } | |
| 2113 | 2531 | |
| 2114 | - if (strlen($uid) != 6) { | |
| 2115 | - return new WP_Error(1, 'Invalid snapshot ID format.'); | |
| 2116 | - } | |
| 2532 | + return $custom_tables; | |
| 2533 | + } // get_custom tables | |
| 2117 | 2534 | |
| 2118 | - if (!isset($snapshots[$uid])) { | |
| 2119 | - return new WP_Error(1, 'Unknown snapshot ID.'); | |
| 2120 | - } | |
| 2121 | 2535 | |
| 2122 | - require_once $this->plugin_dir . 'libs/dumper.php'; | |
| 2536 | + /** | |
| 2537 | + * Creates snapshot of current tables by copying them in the DB and saving metadata. | |
| 2538 | + * | |
| 2539 | + * @param int $name Optional. Name for the new snapshot. | |
| 2540 | + * | |
| 2541 | + * @return array|WP_Error Snapshot details in array on success, or error object on fail. | |
| 2542 | + */ | |
| 2543 | + function do_create_snapshot($name = '') | |
| 2544 | + { | |
| 2545 | + global $wpdb; | |
| 2546 | + $snapshots = $this->get_snapshots(); | |
| 2547 | + $snapshot = array(); | |
| 2548 | + $uid = $this->generate_snapshot_uid(); | |
| 2549 | + $tbl_core = $tbl_custom = $tbl_size = $tbl_rows = 0; | |
| 2123 | 2550 | |
| 2124 | - try { | |
| 2125 | - $world_dumper = WPR_Shuttle_Dumper::create(array( | |
| 2126 | - 'host' => DB_HOST, | |
| 2127 | - 'username' => DB_USER, | |
| 2128 | - 'password' => DB_PASSWORD, | |
| 2129 | - 'db_name' => DB_NAME, | |
| 2130 | - )); | |
| 2551 | + if (!$uid) { | |
| 2552 | + return new WP_Error(1, 'Unable to generate a valid snapshot UID.'); | |
| 2553 | + } | |
| 2131 | 2554 | |
| 2132 | - $folder = wp_mkdir_p(trailingslashit(WP_CONTENT_DIR) . $this->snapshots_folder); | |
| 2133 | - if (!$folder) { | |
| 2134 | - return new WP_Error(1, 'Unable to create wp-content/' . $this->snapshots_folder . '/ folder.'); | |
| 2135 | - } | |
| 2555 | + if ($name) { | |
| 2556 | + $snapshot['name'] = substr(trim($name), 0, 64); | |
| 2557 | + } else { | |
| 2558 | + $snapshot['name'] = ''; | |
| 2559 | + } | |
| 2560 | + $snapshot['uid'] = $uid; | |
| 2561 | + $snapshot['timestamp'] = current_time('mysql'); | |
| 2136 | 2562 | |
| 2137 | - $htaccess_content = 'AddType application/octet-stream .gz' . PHP_EOL; | |
| 2138 | - $htaccess_content .= 'Options -Indexes' . PHP_EOL; | |
| 2139 | - $htaccess_file = @fopen(trailingslashit(WP_CONTENT_DIR) . $this->snapshots_folder . '/.htaccess', 'w'); | |
| 2140 | - if ($htaccess_file) { | |
| 2141 | - fputs($htaccess_file, $htaccess_content); | |
| 2142 | - fclose($htaccess_file); | |
| 2143 | - } | |
| 2563 | + // phpcs:ignore db call warning as we are using uncommon queries | |
| 2564 | + $table_status = $wpdb->get_results('SHOW TABLE STATUS'); // phpcs:ignore | |
| 2565 | + if (is_array($table_status)) { | |
| 2566 | + foreach ($table_status as $index => $table) { | |
| 2567 | + if (0 !== stripos($table->Name, $wpdb->prefix)) { | |
| 2568 | + continue; | |
| 2569 | + } | |
| 2570 | + if (empty($table->Engine)) { | |
| 2571 | + continue; | |
| 2572 | + } | |
| 2144 | 2573 | |
| 2145 | - $world_dumper->dump(trailingslashit(WP_CONTENT_DIR) . $this->snapshots_folder . '/wp-reset-snapshot-' . $uid . '.sql.gz', $uid . '_'); | |
| 2146 | - } catch (Shuttle_Exception $e) { | |
| 2147 | - return new WP_Error(1, 'Couldn\'t create snapshot: ' . $e->getMessage()); | |
| 2148 | - } | |
| 2574 | + $tbl_rows += $table->Rows; | |
| 2575 | + $tbl_size += $table->Data_length + $table->Index_length; | |
| 2576 | + if (in_array($table->Name, $this->core_tables)) { | |
| 2577 | + $tbl_core++; | |
| 2578 | + } else { | |
| 2579 | + $tbl_custom++; | |
| 2580 | + } | |
| 2149 | 2581 | |
| 2150 | - do_action('wp_reset_export_snapshot', 'wp-reset-snapshot-' . $uid . '.sql.gz'); | |
| 2582 | + $wpdb->wpreset_snapshot_table_name = $table->Name; | |
| 2583 | + $wpdb->wpreset_snapshot_table_copy_name = $uid . '_' . $table->Name; | |
| 2584 | + | |
| 2585 | + // phpcs:ignore db call warning as we are using uncommon queries | |
| 2586 | + $wpdb->query("OPTIMIZE TABLE " . $wpdb->wpreset_snapshot_table_name); // phpcs:ignore | |
| 2587 | + $wpdb->query("CREATE TABLE " . $wpdb->wpreset_snapshot_table_copy_name . " LIKE " . $wpdb->wpreset_snapshot_table_name); // phpcs:ignore | |
| 2588 | + $wpdb->query("INSERT " . $wpdb->wpreset_snapshot_table_copy_name . " SELECT * FROM " . $wpdb->wpreset_snapshot_table_name); // phpcs:ignore | |
| 2589 | + } // foreach | |
| 2590 | + } else { | |
| 2591 | + return new WP_Error(1, 'Can\'t get table status data.'); | |
| 2592 | + } | |
| 2151 | 2593 | |
| 2152 | - return 'wp-reset-snapshot-' . $uid . '.sql.gz'; | |
| 2153 | - } // export_snapshot | |
| 2594 | + $snapshot['tbl_core'] = $tbl_core; | |
| 2595 | + $snapshot['tbl_custom'] = $tbl_custom; | |
| 2596 | + $snapshot['tbl_rows'] = $tbl_rows; | |
| 2597 | + $snapshot['tbl_size'] = $tbl_size; | |
| 2154 | 2598 | |
| 2155 | 2599 | |
| 2156 | - /** | |
| 2157 | - * Replace current tables with ones in snapshot. | |
| 2158 | - * | |
| 2159 | - * @param string $uid Snapshot unique 6-char ID. | |
| 2160 | - * | |
| 2161 | - * @return bool|WP_Error True on success, or error object on fail. | |
| 2162 | - */ | |
| 2163 | - function do_restore_snapshot($uid = '') | |
| 2164 | - { | |
| 2165 | - global $wpdb; | |
| 2166 | - $new_tables = array(); | |
| 2167 | - $snapshots = $this->get_snapshots(); | |
| 2600 | + $snapshots[$uid] = $snapshot; | |
| 2601 | + update_option('wp-reset-snapshots', $snapshots); | |
| 2168 | 2602 | |
| 2169 | - if (($res = $this->verify_snapshot_integrity($uid)) !== true) { | |
| 2170 | - return $res; | |
| 2171 | - } | |
| 2603 | + do_action('wp_reset_create_snapshot', $uid, $snapshot); | |
| 2172 | 2604 | |
| 2173 | - $table_status = $wpdb->get_results('SHOW TABLE STATUS'); | |
| 2174 | - if (is_array($table_status)) { | |
| 2175 | - foreach ($table_status as $index => $table) { | |
| 2176 | - if (0 !== stripos($table->Name, $uid . '_')) { | |
| 2177 | - continue; | |
| 2605 | + return $snapshot; | |
| 2606 | + } // create_snapshot | |
| 2607 | + | |
| 2608 | + | |
| 2609 | + /** | |
| 2610 | + * Delete snapshot metadata and tables from DB | |
| 2611 | + * | |
| 2612 | + * @param string $uid Snapshot unique 6-char ID. | |
| 2613 | + * | |
| 2614 | + * @return bool|WP_Error True on success, or error object on fail. | |
| 2615 | + */ | |
| 2616 | + function do_delete_snapshot($uid = '') | |
| 2617 | + { | |
| 2618 | + global $wpdb; | |
| 2619 | + $snapshots = $this->get_snapshots(); | |
| 2620 | + | |
| 2621 | + if (strlen($uid) != 6) { | |
| 2622 | + return new WP_Error(1, 'Invalid UID format.'); | |
| 2178 | 2623 | } |
| 2179 | - if (empty($table->Engine)) { | |
| 2180 | - continue; | |
| 2624 | + | |
| 2625 | + if (!isset($snapshots[$uid])) { | |
| 2626 | + return new WP_Error(1, 'Unknown snapshot ID.'); | |
| 2181 | 2627 | } |
| 2182 | 2628 | |
| 2183 | - $new_tables[] = $table->Name; | |
| 2184 | - } // foreach | |
| 2185 | - } else { | |
| 2186 | - return new WP_Error(1, 'Can\'t get table status data.'); | |
| 2187 | - } | |
| 2629 | + // phpcs:ignore db call warning as we are using uncommon queries | |
| 2630 | + $tables = $wpdb->get_col($wpdb->prepare('SHOW TABLES LIKE %s', array($uid . '\_%'))); // phpcs:ignore | |
| 2631 | + foreach ($tables as $table) { | |
| 2632 | + $wpdb->wpreset_snapshot_table = $table; | |
| 2633 | + $wpdb->query('DROP TABLE IF EXISTS ' . $wpdb->wpreset_snapshot_table); // phpcs:ignore | |
| 2634 | + } | |
| 2188 | 2635 | |
| 2189 | - foreach ($table_status as $index => $table) { | |
| 2190 | - if (0 !== stripos($table->Name, $wpdb->prefix)) { | |
| 2191 | - continue; | |
| 2192 | - } | |
| 2193 | - if (empty($table->Engine)) { | |
| 2194 | - continue; | |
| 2195 | - } | |
| 2636 | + $snapshot_copy = $snapshots[$uid]; | |
| 2637 | + unset($snapshots[$uid]); | |
| 2638 | + update_option('wp-reset-snapshots', $snapshots); | |
| 2196 | 2639 | |
| 2197 | - $wpdb->query('DROP TABLE ' . $table->Name); | |
| 2198 | - } // foreach | |
| 2640 | + do_action('wp_reset_delete_snapshot', $uid, $snapshot_copy); | |
| 2199 | 2641 | |
| 2200 | - // copy snapshot tables to original name | |
| 2201 | - foreach ($new_tables as $table) { | |
| 2202 | - $new_name = str_replace($uid . '_', '', $table); | |
| 2642 | + return true; | |
| 2643 | + } // delete_snapshot | |
| 2203 | 2644 | |
| 2204 | - $wpdb->query('CREATE TABLE ' . $new_name . ' LIKE ' . $table); | |
| 2205 | - $wpdb->query('INSERT ' . $new_name . ' SELECT * FROM ' . $table); | |
| 2206 | - } | |
| 2207 | 2645 | |
| 2208 | - wp_cache_flush(); | |
| 2209 | - update_option('wp-reset', $this->options); | |
| 2210 | - update_option('wp-reset-snapshots', $snapshots); | |
| 2646 | + /** | |
| 2647 | + * Exports snapshot as SQL dump; saved in gzipped file in WP_CONTENT folder. | |
| 2648 | + * | |
| 2649 | + * @param string $uid Snapshot unique 6-char ID. | |
| 2650 | + * | |
| 2651 | + * @return string|WP_Error Export base filename, or error object on fail. | |
| 2652 | + */ | |
| 2653 | + function do_export_snapshot($uid = '') | |
| 2654 | + { | |
| 2655 | + global $wp_filesystem; | |
| 2656 | + $this->wp_init_filesystem(); | |
| 2657 | + | |
| 2658 | + $snapshots = $this->get_snapshots(); | |
| 2211 | 2659 | |
| 2212 | - do_action('wp_reset_restore_snapshot', $uid); | |
| 2660 | + if (strlen($uid) != 6) { | |
| 2661 | + return new WP_Error(1, 'Invalid snapshot ID format.'); | |
| 2662 | + } | |
| 2213 | 2663 | |
| 2214 | - return true; | |
| 2215 | - } // restore_snapshot | |
| 2664 | + if (!isset($snapshots[$uid])) { | |
| 2665 | + return new WP_Error(1, 'Unknown snapshot ID.'); | |
| 2666 | + } | |
| 2216 | 2667 | |
| 2668 | + require_once $this->plugin_dir . 'libs/dumper.php'; | |
| 2217 | 2669 | |
| 2218 | - /** | |
| 2219 | - * Verifies snapshot integrity by comparing metadata and data in DB | |
| 2220 | - * | |
| 2221 | - * @param string $uid Snapshot unique 6-char ID. | |
| 2222 | - * | |
| 2223 | - * @return bool|WP_Error True on success, or error object on fail. | |
| 2224 | - */ | |
| 2225 | - function verify_snapshot_integrity($uid) | |
| 2226 | - { | |
| 2227 | - global $wpdb; | |
| 2228 | - $tbl_core = $tbl_custom = 0; | |
| 2229 | - $snapshots = $this->get_snapshots(); | |
| 2670 | + $snapshot_file_uid = md5($this->generate_snapshot_uid(10)); | |
| 2671 | + try { | |
| 2672 | + $world_dumper = WPR_Shuttle_Dumper::create(array( | |
| 2673 | + 'host' => DB_HOST, | |
| 2674 | + 'username' => DB_USER, | |
| 2675 | + 'password' => DB_PASSWORD, | |
| 2676 | + 'db_name' => DB_NAME, | |
| 2677 | + )); | |
| 2230 | 2678 | |
| 2231 | - if (strlen($uid) != 6) { | |
| 2232 | - return new WP_Error(1, 'Invalid snapshot ID format.'); | |
| 2233 | - } | |
| 2679 | + $folder = wp_mkdir_p(trailingslashit(WP_CONTENT_DIR) . $this->snapshots_folder); | |
| 2680 | + if (!$folder) { | |
| 2681 | + return new WP_Error(1, 'Unable to create wp-content/' . $this->snapshots_folder . '/ folder.'); | |
| 2682 | + } | |
| 2234 | 2683 | |
| 2235 | - if (!isset($snapshots[$uid])) { | |
| 2236 | - return new WP_Error(1, 'Unknown snapshot ID.'); | |
| 2237 | - } | |
| 2684 | + $htaccess_content = 'AddType application/octet-stream .gz' . PHP_EOL; | |
| 2685 | + $htaccess_content .= 'Options -Indexes' . PHP_EOL; | |
| 2238 | 2686 | |
| 2239 | - $snapshot = $snapshots[$uid]; | |
| 2687 | + $wp_filesystem->put_contents(trailingslashit(WP_CONTENT_DIR) . $this->snapshots_folder . '/.htaccess', $htaccess_content); | |
| 2240 | 2688 | |
| 2241 | - $table_status = $wpdb->get_results('SHOW TABLE STATUS'); | |
| 2242 | - if (is_array($table_status)) { | |
| 2243 | - foreach ($table_status as $index => $table) { | |
| 2244 | - if (0 !== stripos($table->Name, $uid . '_')) { | |
| 2245 | - continue; | |
| 2689 | + $world_dumper->dump(trailingslashit(WP_CONTENT_DIR) . $this->snapshots_folder . '/wp-reset-snapshot-' . $snapshot_file_uid . '.sql.gz', $uid . '_'); | |
| 2690 | + } catch (Shuttle_Exception $e) { | |
| 2691 | + return new WP_Error(1, 'Couldn\'t create snapshot: ' . $e->getMessage()); | |
| 2246 | 2692 | } |
| 2247 | - if (empty($table->Engine)) { | |
| 2248 | - continue; | |
| 2693 | + | |
| 2694 | + do_action('wp_reset_export_snapshot', 'wp-reset-snapshot-' . $snapshot_file_uid . '.sql.gz'); | |
| 2695 | + | |
| 2696 | + return 'wp-reset-snapshot-' . $snapshot_file_uid . '.sql.gz'; | |
| 2697 | + } // export_snapshot | |
| 2698 | + | |
| 2699 | + | |
| 2700 | + /** | |
| 2701 | + * Replace current tables with ones in snapshot. | |
| 2702 | + * | |
| 2703 | + * @param string $uid Snapshot unique 6-char ID. | |
| 2704 | + * | |
| 2705 | + * @return bool|WP_Error True on success, or error object on fail. | |
| 2706 | + */ | |
| 2707 | + function do_restore_snapshot($uid = '') | |
| 2708 | + { | |
| 2709 | + // phpcs:ignore db call warning as we are using uncommon queries | |
| 2710 | + global $wpdb; | |
| 2711 | + $new_tables = array(); | |
| 2712 | + $snapshots = $this->get_snapshots(); | |
| 2713 | + | |
| 2714 | + if (($res = $this->verify_snapshot_integrity($uid)) !== true) { | |
| 2715 | + return $res; | |
| 2249 | 2716 | } |
| 2250 | 2717 | |
| 2251 | - if (in_array(str_replace($uid . '_', '', $table->Name), $this->core_tables)) { | |
| 2252 | - $tbl_core++; | |
| 2718 | + $table_status = $wpdb->get_results('SHOW TABLE STATUS'); // phpcs:ignore | |
| 2719 | + if (is_array($table_status)) { | |
| 2720 | + foreach ($table_status as $index => $table) { | |
| 2721 | + if (0 !== stripos($table->Name, $uid . '_')) { | |
| 2722 | + continue; | |
| 2723 | + } | |
| 2724 | + if (empty($table->Engine)) { | |
| 2725 | + continue; | |
| 2726 | + } | |
| 2727 | + | |
| 2728 | + $new_tables[] = $table->Name; | |
| 2729 | + } // foreach | |
| 2253 | 2730 | } else { |
| 2254 | - $tbl_custom++; | |
| 2731 | + return new WP_Error(1, 'Can\'t get table status data.'); | |
| 2255 | 2732 | } |
| 2256 | - } // foreach | |
| 2257 | 2733 | |
| 2258 | - if ($tbl_core != $snapshot['tbl_core'] || $tbl_custom != $snapshot['tbl_custom']) { | |
| 2259 | - return new WP_Error(1, 'Snapshot data has been compromised. Saved metadata does not match data in the DB. Contact WP Reset support if data is critical, or restore it via a MySQL GUI.'); | |
| 2260 | - } | |
| 2261 | - } else { | |
| 2262 | - return new WP_Error(1, 'Can\'t get table status data.'); | |
| 2263 | - } | |
| 2734 | + foreach ($table_status as $index => $table) { | |
| 2735 | + if (0 !== stripos($table->Name, $wpdb->prefix)) { | |
| 2736 | + continue; | |
| 2737 | + } | |
| 2738 | + if (empty($table->Engine)) { | |
| 2739 | + continue; | |
| 2740 | + } | |
| 2264 | 2741 | |
| 2265 | - return true; | |
| 2266 | - } // verify_snapshot_integrity | |
| 2742 | + $wpdb->wpreset_snapshot_table = $table->Name; | |
| 2743 | + $wpdb->query('DROP TABLE ' . $wpdb->wpreset_snapshot_table); // phpcs:ignore | |
| 2744 | + } // foreach | |
| 2267 | 2745 | |
| 2746 | + // copy snapshot tables to original name | |
| 2747 | + foreach ($new_tables as $table) { | |
| 2748 | + $wpdb->wpreset_snapshot_table = $table; | |
| 2749 | + $wpdb->wpreset_snapshot_table_new = str_replace($uid . '_', '', $table); | |
| 2268 | 2750 | |
| 2269 | - /** | |
| 2270 | - * Compares a selected snapshot with the current table set in DB | |
| 2271 | - * | |
| 2272 | - * @param string $uid Snapshot unique 6-char ID. | |
| 2273 | - * | |
| 2274 | - * @return string|WP_Error Formatted table with details on success, or error object on fail. | |
| 2275 | - */ | |
| 2276 | - function do_compare_snapshots($uid) | |
| 2277 | - { | |
| 2278 | - global $wpdb; | |
| 2279 | - $current = $snapshot = array(); | |
| 2280 | - $out = $out2 = $out3 = ''; | |
| 2751 | + $wpdb->query("CREATE TABLE " . $wpdb->wpreset_snapshot_table_new . " LIKE " . $wpdb->wpreset_snapshot_table); // phpcs:ignore | |
| 2752 | + $wpdb->query("INSERT " . $wpdb->wpreset_snapshot_table_new . " SELECT * FROM " . $wpdb->wpreset_snapshot_table); // phpcs:ignore | |
| 2753 | + } | |
| 2281 | 2754 | |
| 2282 | - if (($res = $this->verify_snapshot_integrity($uid)) !== true) { | |
| 2283 | - return $res; | |
| 2284 | - } | |
| 2755 | + wp_cache_flush(); | |
| 2756 | + update_option('wp-reset', $this->options); | |
| 2757 | + update_option('wp-reset-snapshots', $snapshots); | |
| 2285 | 2758 | |
| 2286 | - $table_status = $wpdb->get_results('SHOW TABLE STATUS'); | |
| 2287 | - foreach ($table_status as $index => $table) { | |
| 2288 | - if (empty($table->Engine)) { | |
| 2289 | - continue; | |
| 2290 | - } | |
| 2759 | + do_action('wp_reset_restore_snapshot', $uid); | |
| 2291 | 2760 | |
| 2292 | - if (0 !== stripos($table->Name, $uid . '_') && 0 !== stripos($table->Name, $wpdb->prefix)) { | |
| 2293 | - continue; | |
| 2294 | - } | |
| 2761 | + return true; | |
| 2762 | + } // restore_snapshot | |
| 2295 | 2763 | |
| 2296 | - $info = array(); | |
| 2297 | - $info['rows'] = $table->Rows; | |
| 2298 | - $info['size_data'] = $table->Data_length; | |
| 2299 | - $info['size_index'] = $table->Index_length; | |
| 2300 | - $schema = $wpdb->get_row('SHOW CREATE TABLE ' . $table->Name, ARRAY_N); | |
| 2301 | - $info['schema'] = $schema[1]; | |
| 2302 | - $info['engine'] = $table->Engine; | |
| 2303 | - $info['fullname'] = $table->Name; | |
| 2304 | - $basename = str_replace(array($uid . '_'), array(''), $table->Name); | |
| 2305 | - $info['basename'] = $basename; | |
| 2306 | - $info['corename'] = str_replace(array($wpdb->prefix), array(''), $basename); | |
| 2307 | - $info['uid'] = $uid; | |
| 2308 | 2764 | |
| 2309 | - if (0 === stripos($table->Name, $uid . '_')) { | |
| 2310 | - $snapshot[$basename] = $info; | |
| 2311 | - } | |
| 2765 | + /** | |
| 2766 | + * Verifies snapshot integrity by comparing metadata and data in DB | |
| 2767 | + * | |
| 2768 | + * @param string $uid Snapshot unique 6-char ID. | |
| 2769 | + * | |
| 2770 | + * @return bool|WP_Error True on success, or error object on fail. | |
| 2771 | + */ | |
| 2772 | + function verify_snapshot_integrity($uid) | |
| 2773 | + { | |
| 2774 | + // phpcs:ignore db call warning as we are using uncommon queries | |
| 2775 | + global $wpdb; | |
| 2776 | + $tbl_core = $tbl_custom = 0; | |
| 2777 | + $snapshots = $this->get_snapshots(); | |
| 2312 | 2778 | |
| 2313 | - if (0 === stripos($table->Name, $wpdb->prefix)) { | |
| 2314 | - $info['uid'] = ''; | |
| 2315 | - $current[$basename] = $info; | |
| 2316 | - } | |
| 2317 | - } // foreach | |
| 2779 | + if (strlen($uid) != 6) { | |
| 2780 | + return new WP_Error(1, 'Invalid snapshot ID format.'); | |
| 2781 | + } | |
| 2318 | 2782 | |
| 2319 | - $in_both = array_keys(array_intersect_key($current, $snapshot)); | |
| 2320 | - $in_current_only = array_diff_key($current, $snapshot); | |
| 2321 | - $in_snapshot_only = array_diff_key($snapshot, $current); | |
| 2783 | + if (!isset($snapshots[$uid])) { | |
| 2784 | + return new WP_Error(1, 'Unknown snapshot ID.'); | |
| 2785 | + } | |
| 2322 | 2786 | |
| 2323 | - $out .= '<br><br>'; | |
| 2324 | - foreach ($in_current_only as $table) { | |
| 2325 | - $out .= '<div class="wpr-table-container in-current-only" data-table="' . $table['basename'] . '">'; | |
| 2326 | - $out .= '<table>'; | |
| 2327 | - $out .= '<tr title="Click to show/hide more info" class="wpr-table-missing header-row">'; | |
| 2328 | - $out .= '<td><b>' . $table['fullname'] . '</b></td>'; | |
| 2329 | - $out .= '<td>table is not present in snapshot<span class="dashicons dashicons-arrow-down-alt2"></span></td>'; | |
| 2330 | - $out .= '</tr>'; | |
| 2331 | - $out .= '<tr class="hidden">'; | |
| 2332 | - $out .= '<td>'; | |
| 2333 | - $out .= '<p>' . number_format($table['rows']) . ' row' . ($table['rows'] == 1 ? '' : 's') . ' totaling ' . $this->format_size($table['size_data']) . ' in data and ' . $this->format_size($table['size_index']) . ' in index.</p>'; | |
| 2334 | - $out .= '<pre>' . $table['schema'] . '</pre>'; | |
| 2335 | - $out .= '</td>'; | |
| 2336 | - $out .= '<td> </td>'; | |
| 2337 | - $out .= '</tr>'; | |
| 2338 | - $out .= '</table>'; | |
| 2339 | - $out .= '</div>'; | |
| 2340 | - } // foreach in current only | |
| 2787 | + $snapshot = $snapshots[$uid]; | |
| 2341 | 2788 | |
| 2342 | - foreach ($in_snapshot_only as $table) { | |
| 2343 | - $out .= '<div class="wpr-table-container in-snapshot-only" data-table="' . $table['basename'] . '">'; | |
| 2344 | - $out .= '<table>'; | |
| 2345 | - $out .= '<tr title="Click to show/hide more info" class="wpr-table-missing header-row">'; | |
| 2346 | - $out .= '<td>table is not present in current tables</td>'; | |
| 2347 | - $out .= '<td><b>' . $table['fullname'] . '</b><span class="dashicons dashicons-arrow-down-alt2"></span></td>'; | |
| 2348 | - $out .= '</tr>'; | |
| 2349 | - $out .= '<tr class="hidden">'; | |
| 2350 | - $out .= '<td> </td>'; | |
| 2351 | - $out .= '<td>'; | |
| 2352 | - $out .= '<p>' . number_format($table['rows']) . ' row' . ($table['rows'] == 1 ? '' : 's') . ' totaling ' . $this->format_size($table['size_data']) . ' in data and ' . $this->format_size($table['size_index']) . ' in index.</p>'; | |
| 2353 | - $out .= '<pre>' . $table['schema'] . '</pre>'; | |
| 2354 | - $out .= '</td>'; | |
| 2355 | - $out .= '</tr>'; | |
| 2356 | - $out .= '</table>'; | |
| 2357 | - $out .= '</div>'; | |
| 2358 | - } // foreach in snapshot only | |
| 2789 | + $table_status = $wpdb->get_results('SHOW TABLE STATUS'); // phpcs:ignore | |
| 2790 | + if (is_array($table_status)) { | |
| 2791 | + foreach ($table_status as $index => $table) { | |
| 2792 | + if (0 !== stripos($table->Name, $uid . '_')) { | |
| 2793 | + continue; | |
| 2794 | + } | |
| 2795 | + if (empty($table->Engine)) { | |
| 2796 | + continue; | |
| 2797 | + } | |
| 2359 | 2798 | |
| 2360 | - foreach ($in_both as $tablename) { | |
| 2361 | - $tbl_current = $current[$tablename]; | |
| 2362 | - $tbl_snapshot = $snapshot[$tablename]; | |
| 2799 | + if (in_array(str_replace($uid . '_', '', $table->Name), $this->core_tables)) { | |
| 2800 | + $tbl_core++; | |
| 2801 | + } else { | |
| 2802 | + $tbl_custom++; | |
| 2803 | + } | |
| 2804 | + } // foreach | |
| 2363 | 2805 | |
| 2364 | - $schema1 = preg_replace('/(auto_increment=)([0-9]*) /i', '${1}1 ', $tbl_current['schema'], 1); | |
| 2365 | - $schema2 = preg_replace('/(auto_increment=)([0-9]*) /i', '${1}1 ', $tbl_snapshot['schema'], 1); | |
| 2366 | - $tbl_snapshot['tmp_schema'] = str_replace($tbl_snapshot['uid'] . '_' . $tablename, $tablename, $tbl_snapshot['schema']); | |
| 2367 | - $schema2 = str_replace($tbl_snapshot['uid'] . '_' . $tablename, $tablename, $schema2); | |
| 2806 | + if ($tbl_core != $snapshot['tbl_core'] || $tbl_custom != $snapshot['tbl_custom']) { | |
| 2807 | + return new WP_Error(1, 'Snapshot data has been compromised. Saved metadata does not match data in the DB. Contact WP Reset support if data is critical, or restore it via a MySQL GUI.'); | |
| 2808 | + } | |
| 2809 | + } else { | |
| 2810 | + return new WP_Error(1, 'Can\'t get table status data.'); | |
| 2811 | + } | |
| 2368 | 2812 | |
| 2369 | - if ($tbl_current['rows'] == $tbl_snapshot['rows'] && $tbl_current['schema'] == $tbl_snapshot['tmp_schema']) { | |
| 2370 | - $out3 .= '<div class="wpr-table-container identical" data-table="' . $tablename . '">'; | |
| 2371 | - $out3 .= '<table>'; | |
| 2372 | - $out3 .= '<tr title="Click to show/hide more info" class="wpr-table-match header-row">'; | |
| 2373 | - $out3 .= '<td><b>' . $tbl_current['fullname'] . '</b></td>'; | |
| 2374 | - $out3 .= '<td><b>' . $tbl_snapshot['fullname'] . '</b><span class="dashicons dashicons-arrow-down-alt2"></span></td>'; | |
| 2375 | - $out3 .= '</tr>'; | |
| 2376 | - $out3 .= '<tr class="hidden">'; | |
| 2377 | - $out3 .= '<td>'; | |
| 2378 | - $out3 .= '<p>' . number_format($tbl_current['rows']) . ' rows totaling ' . $this->format_size($tbl_current['size_data']) . ' in data and ' . $this->format_size($tbl_current['size_index']) . ' in index.</p>'; | |
| 2379 | - $out3 .= '<pre>' . $tbl_current['schema'] . '</pre>'; | |
| 2380 | - $out3 .= '</td>'; | |
| 2381 | - $out3 .= '<td>'; | |
| 2382 | - $out3 .= '<p>' . number_format($tbl_snapshot['rows']) . ' rows totaling ' . $this->format_size($tbl_snapshot['size_data']) . ' in data and ' . $this->format_size($tbl_snapshot['size_index']) . ' in index.</p>'; | |
| 2383 | - $out3 .= '<pre>' . $tbl_snapshot['schema'] . '</pre>'; | |
| 2384 | - $out3 .= '</td>'; | |
| 2385 | - $out3 .= '</tr>'; | |
| 2386 | - $out3 .= '</table>'; | |
| 2387 | - $out3 .= '</div>'; | |
| 2388 | - } elseif ($schema1 != $schema2) { | |
| 2389 | - require_once $this->plugin_dir . 'libs/diff.php'; | |
| 2390 | - require_once $this->plugin_dir . 'libs/diff/Renderer/Html/SideBySide.php'; | |
| 2391 | - $diff = new WPR_Diff(explode("\n", $tbl_current['schema']), explode("\n", $tbl_snapshot['schema']), array('ignoreWhitespace' => false)); | |
| 2392 | - $renderer = new WPR_Diff_Renderer_Html_SideBySide; | |
| 2813 | + return true; | |
| 2814 | + } // verify_snapshot_integrity | |
| 2393 | 2815 | |
| 2394 | - $out2 .= '<div class="wpr-table-container" data-table="' . $tbl_current['basename'] . '">'; | |
| 2395 | - $out2 .= '<table>'; | |
| 2396 | - $out2 .= '<tr title="Click to show/hide more info" class="wpr-table-difference header-row">'; | |
| 2397 | - $out2 .= '<td><b>' . $tbl_current['fullname'] . '</b> table schemas do not match</td>'; | |
| 2398 | - $out2 .= '<td><b>' . $tbl_snapshot['fullname'] . '</b> table schemas do not match<span class="dashicons dashicons-arrow-down-alt2"></span></td>'; | |
| 2399 | - $out2 .= '</tr>'; | |
| 2400 | - $out2 .= '<tr class="hidden">'; | |
| 2401 | - $out2 .= '<td>'; | |
| 2402 | - $out2 .= '<p>' . number_format($tbl_current['rows']) . ' rows totaling ' . $this->format_size($tbl_current['size_data']) . ' in data and ' . $this->format_size($tbl_current['size_index']) . ' in index.</p>'; | |
| 2403 | - $out2 .= '</td>'; | |
| 2404 | - $out2 .= '<td>'; | |
| 2405 | - $out2 .= '<p>' . number_format($tbl_snapshot['rows']) . ' rows totaling ' . $this->format_size($tbl_snapshot['size_data']) . ' in data and ' . $this->format_size($tbl_snapshot['size_index']) . ' in index.</p>'; | |
| 2406 | - $out2 .= '</td>'; | |
| 2407 | - $out2 .= '</tr>'; | |
| 2408 | - $out2 .= '<tr class="hidden">'; | |
| 2409 | - $out2 .= '<td colspan="2" class="no-padding">'; | |
| 2410 | - $out2 .= $diff->Render($renderer); | |
| 2411 | - $out2 .= '</td>'; | |
| 2412 | - $out2 .= '</tr>'; | |
| 2413 | - $out2 .= '</table>'; | |
| 2414 | - $out2 .= '</div>'; | |
| 2415 | - } else { | |
| 2416 | - $out2 .= '<div class="wpr-table-container" data-table="' . $tbl_current['basename'] . '">'; | |
| 2417 | - $out2 .= '<table>'; | |
| 2418 | - $out2 .= '<tr title="Click to show/hide more info" class="wpr-table-difference header-row">'; | |
| 2419 | - $out2 .= '<td><b>' . $tbl_current['fullname'] . '</b> data in tables does not match</td>'; | |
| 2420 | - $out2 .= '<td><b>' . $tbl_snapshot['fullname'] . '</b> data in tables does not match<span class="dashicons dashicons-arrow-down-alt2"></span></td>'; | |
| 2421 | - $out2 .= '</tr>'; | |
| 2422 | - $out2 .= '<tr class="hidden">'; | |
| 2423 | - $out2 .= '<td>'; | |
| 2424 | - $out2 .= '<p>' . number_format($tbl_current['rows']) . ' rows totaling ' . $this->format_size($tbl_current['size_data']) . ' in data and ' . $this->format_size($tbl_current['size_index']) . ' in index.</p>'; | |
| 2425 | - $out2 .= '</td>'; | |
| 2426 | - $out2 .= '<td>'; | |
| 2427 | - $out2 .= '<p>' . number_format($tbl_snapshot['rows']) . ' rows totaling ' . $this->format_size($tbl_snapshot['size_data']) . ' in data and ' . $this->format_size($tbl_snapshot['size_index']) . ' in index.</p>'; | |
| 2428 | - $out2 .= '</td>'; | |
| 2429 | - $out2 .= '</tr>'; | |
| 2430 | 2816 | |
| 2431 | - $out2 .= '<tr class="hidden">'; | |
| 2432 | - $out2 .= '<td colspan="2">'; | |
| 2433 | - if ($tbl_current['corename'] == 'options') { | |
| 2434 | - $ss_prefix = $tbl_snapshot['uid'] . '_' . $wpdb->prefix; | |
| 2435 | - $diff_rows = $wpdb->get_results("SELECT {$wpdb->prefix}options.option_name, {$wpdb->prefix}options.option_value AS current_value, {$ss_prefix}options.option_value AS snapshot_value FROM {$wpdb->prefix}options LEFT JOIN {$ss_prefix}options ON {$ss_prefix}options.option_name = {$wpdb->prefix}options.option_name WHERE {$wpdb->prefix}options.option_value != {$ss_prefix}options.option_value LIMIT 100;"); | |
| 2436 | - $only_current = $wpdb->get_results("SELECT {$wpdb->prefix}options.option_name, {$wpdb->prefix}options.option_value AS current_value, {$ss_prefix}options.option_value AS snapshot_value FROM {$wpdb->prefix}options LEFT JOIN {$ss_prefix}options ON {$ss_prefix}options.option_name = {$wpdb->prefix}options.option_name WHERE {$ss_prefix}options.option_value IS NULL LIMIT 100;"); | |
| 2437 | - $only_snapshot = $wpdb->get_results("SELECT {$wpdb->prefix}options.option_name, {$wpdb->prefix}options.option_value AS current_value, {$ss_prefix}options.option_value AS snapshot_value FROM {$wpdb->prefix}options LEFT JOIN {$ss_prefix}options ON {$ss_prefix}options.option_name = {$wpdb->prefix}options.option_name WHERE {$wpdb->prefix}options.option_value IS NULL LIMIT 100;"); | |
| 2438 | - $out2 .= '<table class="table_diff">'; | |
| 2439 | - $out2 .= '<tr><td style="width: 100px;"><b>Option Name</b></td><td><b>Current Value</b></td><td><b>Snapshot Value</b></td></tr>'; | |
| 2440 | - foreach ($diff_rows as $row) { | |
| 2441 | - $out2 .= '<tr>'; | |
| 2442 | - $out2 .= '<td style="width: 100px;">' . $row->option_name . '</td>'; | |
| 2443 | - $out2 .= '<td>' . (empty($row->current_value) ? '<i>empty</i>' : $row->current_value) . '</td>'; | |
| 2444 | - $out2 .= '<td>' . (empty($row->snapshot_value) ? '<i>empty</i>' : $row->snapshot_value) . '</td>'; | |
| 2445 | - $out2 .= '</tr>'; | |
| 2446 | - } // foreach | |
| 2447 | - foreach ($only_current as $row) { | |
| 2448 | - $out2 .= '<tr>'; | |
| 2449 | - $out2 .= '<td style="width: 100px;">' . $row->option_name . '</td>'; | |
| 2450 | - $out2 .= '<td>' . (empty($row->current_value) ? '<i>empty</i>' : $row->current_value) . '</td>'; | |
| 2451 | - $out2 .= '<td><i>not found in snapshot</i></td>'; | |
| 2452 | - $out2 .= '</tr>'; | |
| 2453 | - } // foreach | |
| 2454 | - foreach ($only_current as $row) { | |
| 2455 | - $out2 .= '<tr>'; | |
| 2456 | - $out2 .= '<td style="width: 100px;">' . $row->option_name . '</td>'; | |
| 2457 | - $out2 .= '<td><i>not found in current tables</i></td>'; | |
| 2458 | - $out2 .= '<td>' . (empty($row->snapshot_value) ? '<i>empty</i>' : $row->snapshot_value) . '</td>'; | |
| 2459 | - $out2 .= '</tr>'; | |
| 2460 | - } // foreach | |
| 2461 | - $out2 .= '</table>'; | |
| 2462 | - } else { | |
| 2463 | - $out2 .= '<p class="textcenter">Detailed data diff is not available for this table.</p>'; | |
| 2817 | + /** | |
| 2818 | + * Compares a selected snapshot with the current table set in DB | |
| 2819 | + * | |
| 2820 | + * @param string $uid Snapshot unique 6-char ID. | |
| 2821 | + * | |
| 2822 | + * @return string|WP_Error Formatted table with details on success, or error object on fail. | |
| 2823 | + */ | |
| 2824 | + function do_compare_snapshots($uid) | |
| 2825 | + { | |
| 2826 | + // phpcs:ignore db call warning as we are using uncommon queries | |
| 2827 | + global $wpdb; | |
| 2828 | + $current = $snapshot = array(); | |
| 2829 | + $out = $out2 = $out3 = ''; | |
| 2830 | + | |
| 2831 | + if (($res = $this->verify_snapshot_integrity($uid)) !== true) { | |
| 2832 | + return $res; | |
| 2464 | 2833 | } |
| 2465 | - $out2 .= '</td>'; | |
| 2466 | - $out2 .= '</tr>'; | |
| 2467 | 2834 | |
| 2468 | - $out2 .= '</table>'; | |
| 2469 | - $out2 .= '</div>'; | |
| 2470 | - } | |
| 2471 | - } // foreach in both | |
| 2835 | + $table_status = $wpdb->get_results('SHOW TABLE STATUS'); // phpcs:ignore | |
| 2836 | + foreach ($table_status as $index => $table) { | |
| 2837 | + if (empty($table->Engine)) { | |
| 2838 | + continue; | |
| 2839 | + } | |
| 2472 | 2840 | |
| 2473 | - return $out . $out2 . $out3; | |
| 2474 | - } // do_compare_snapshots | |
| 2841 | + if (0 !== stripos($table->Name, $uid . '_') && 0 !== stripos($table->Name, $wpdb->prefix)) { | |
| 2842 | + continue; | |
| 2843 | + } | |
| 2475 | 2844 | |
| 2845 | + $info = array(); | |
| 2846 | + $info['rows'] = $table->Rows; | |
| 2847 | + $info['size_data'] = $table->Data_length; | |
| 2848 | + $info['size_index'] = $table->Index_length; | |
| 2849 | + $wpdb->wpreset_table_name = $table->Name; | |
| 2850 | + $schema = $wpdb->get_row('SHOW CREATE TABLE ' . $wpdb->wpreset_table_name, ARRAY_N); // phpcs:ignore | |
| 2851 | + $info['schema'] = $schema[1]; | |
| 2852 | + $info['engine'] = $table->Engine; | |
| 2853 | + $info['fullname'] = $table->Name; | |
| 2854 | + $basename = str_replace(array($uid . '_'), array(''), $table->Name); | |
| 2855 | + $info['basename'] = $basename; | |
| 2856 | + $info['corename'] = str_replace(array($wpdb->prefix), array(''), $basename); | |
| 2857 | + $info['uid'] = $uid; | |
| 2476 | 2858 | |
| 2477 | - /** | |
| 2478 | - * Generates a unique 6-char snapshot ID; verified non-existing | |
| 2479 | - * | |
| 2480 | - * @return string | |
| 2481 | - */ | |
| 2482 | - function generate_snapshot_uid() | |
| 2483 | - { | |
| 2484 | - global $wpdb; | |
| 2485 | - $snapshots = $this->get_snapshots(); | |
| 2486 | - $cnt = 0; | |
| 2487 | - $uid = false; | |
| 2859 | + if (0 === stripos($table->Name, $uid . '_')) { | |
| 2860 | + $snapshot[$basename] = $info; | |
| 2861 | + } | |
| 2488 | 2862 | |
| 2489 | - do { | |
| 2490 | - $cnt++; | |
| 2491 | - $uid = sprintf('%06x', mt_rand(0, 0xFFFFFF)); | |
| 2863 | + if (0 === stripos($table->Name, $wpdb->prefix)) { | |
| 2864 | + $info['uid'] = ''; | |
| 2865 | + $current[$basename] = $info; | |
| 2866 | + } | |
| 2867 | + } // foreach | |
| 2492 | 2868 | |
| 2493 | - $verify_db = $wpdb->get_col($wpdb->prepare('SHOW TABLES LIKE %s', array('%' . $uid . '%'))); | |
| 2494 | - } while (!empty($verify_db) && isset($snapshots[$uid]) && $cnt < 30); | |
| 2869 | + $in_both = array_keys(array_intersect_key($current, $snapshot)); | |
| 2870 | + $in_current_only = array_diff_key($current, $snapshot); | |
| 2871 | + $in_snapshot_only = array_diff_key($snapshot, $current); | |
| 2495 | 2872 | |
| 2496 | - if ($cnt == 30) { | |
| 2497 | - $uid = false; | |
| 2498 | - } | |
| 2873 | + $out .= '<br><br>'; | |
| 2874 | + foreach ($in_current_only as $table) { | |
| 2875 | + $out .= '<div class="wpr-table-container in-current-only" data-table="' . esc_attr($table['basename']) . '">'; | |
| 2876 | + $out .= '<table>'; | |
| 2877 | + $out .= '<tr title="Click to show/hide more info" class="wpr-table-missing header-row">'; | |
| 2878 | + $out .= '<td><b>' . $table['fullname'] . '</b></td>'; | |
| 2879 | + $out .= '<td>table is not present in snapshot<span class="dashicons dashicons-arrow-down-alt2"></span></td>'; | |
| 2880 | + $out .= '</tr>'; | |
| 2881 | + $out .= '<tr class="hidden">'; | |
| 2882 | + $out .= '<td>'; | |
| 2883 | + $out .= '<p>' . number_format($table['rows']) . ' row' . ($table['rows'] == 1 ? '' : 's') . ' totaling ' . WP_Reset_Utility::format_size($table['size_data']) . ' in data and ' . WP_Reset_Utility::format_size($table['size_index']) . ' in index.</p>'; | |
| 2884 | + $out .= '<pre>' . $table['schema'] . '</pre>'; | |
| 2885 | + $out .= '</td>'; | |
| 2886 | + $out .= '<td> </td>'; | |
| 2887 | + $out .= '</tr>'; | |
| 2888 | + $out .= '</table>'; | |
| 2889 | + $out .= '</div>'; | |
| 2890 | + } // foreach in current only | |
| 2499 | 2891 | |
| 2500 | - return $uid; | |
| 2501 | - } // generate_snapshot_uid | |
| 2892 | + foreach ($in_snapshot_only as $table) { | |
| 2893 | + $out .= '<div class="wpr-table-container in-snapshot-only" data-table="' . esc_attr($table['basename']) . '">'; | |
| 2894 | + $out .= '<table>'; | |
| 2895 | + $out .= '<tr title="Click to show/hide more info" class="wpr-table-missing header-row">'; | |
| 2896 | + $out .= '<td>table is not present in current tables</td>'; | |
| 2897 | + $out .= '<td><b>' . esc_html($table['fullname']) . '</b><span class="dashicons dashicons-arrow-down-alt2"></span></td>'; | |
| 2898 | + $out .= '</tr>'; | |
| 2899 | + $out .= '<tr class="hidden">'; | |
| 2900 | + $out .= '<td> </td>'; | |
| 2901 | + $out .= '<td>'; | |
| 2902 | + $out .= '<p>' . number_format($table['rows']) . ' row' . ($table['rows'] == 1 ? '' : 's') . ' totaling ' . WP_Reset_Utility::format_size($table['size_data']) . ' in data and ' . WP_Reset_Utility::format_size($table['size_index']) . ' in index.</p>'; | |
| 2903 | + $out .= '<pre>' . $table['schema'] . '</pre>'; | |
| 2904 | + $out .= '</td>'; | |
| 2905 | + $out .= '</tr>'; | |
| 2906 | + $out .= '</table>'; | |
| 2907 | + $out .= '</div>'; | |
| 2908 | + } // foreach in snapshot only | |
| 2502 | 2909 | |
| 2910 | + foreach ($in_both as $tablename) { | |
| 2911 | + $tbl_current = $current[$tablename]; | |
| 2912 | + $tbl_snapshot = $snapshot[$tablename]; | |
| 2503 | 2913 | |
| 2504 | - /** | |
| 2505 | - * Helper function for adding plugins to featured list | |
| 2506 | - * | |
| 2507 | - * @return array | |
| 2508 | - */ | |
| 2509 | - function featured_plugins_tab($args) | |
| 2510 | - { | |
| 2511 | - add_filter('plugins_api_result', array($this, 'plugins_api_result'), 10, 3); | |
| 2914 | + $schema1 = preg_replace('/(auto_increment=)([0-9]*) /i', '${1}1 ', $tbl_current['schema'], 1); | |
| 2915 | + $schema2 = preg_replace('/(auto_increment=)([0-9]*) /i', '${1}1 ', $tbl_snapshot['schema'], 1); | |
| 2916 | + $tbl_snapshot['tmp_schema'] = str_replace($tbl_snapshot['uid'] . '_' . $tablename, $tablename, $tbl_snapshot['schema']); | |
| 2917 | + $schema2 = str_replace($tbl_snapshot['uid'] . '_' . $tablename, $tablename, $schema2); | |
| 2512 | 2918 | |
| 2513 | - return $args; | |
| 2514 | - } // featured_plugins_tab | |
| 2919 | + if ($tbl_current['rows'] == $tbl_snapshot['rows'] && $tbl_current['schema'] == $tbl_snapshot['tmp_schema']) { | |
| 2920 | + $out3 .= '<div class="wpr-table-container identical" data-table="' . esc_attr($tablename) . '">'; | |
| 2921 | + $out3 .= '<table>'; | |
| 2922 | + $out3 .= '<tr title="Click to show/hide more info" class="wpr-table-match header-row">'; | |
| 2923 | + $out3 .= '<td><b>' . $tbl_current['fullname'] . '</b></td>'; | |
| 2924 | + $out3 .= '<td><b>' . $tbl_snapshot['fullname'] . '</b><span class="dashicons dashicons-arrow-down-alt2"></span></td>'; | |
| 2925 | + $out3 .= '</tr>'; | |
| 2926 | + $out3 .= '<tr class="hidden">'; | |
| 2927 | + $out3 .= '<td>'; | |
| 2928 | + $out3 .= '<p>' . number_format($tbl_current['rows']) . ' rows totaling ' . WP_Reset_Utility::format_size($tbl_current['size_data']) . ' in data and ' . WP_Reset_Utility::format_size($tbl_current['size_index']) . ' in index.</p>'; | |
| 2929 | + $out3 .= '<pre>' . $tbl_current['schema'] . '</pre>'; | |
| 2930 | + $out3 .= '</td>'; | |
| 2931 | + $out3 .= '<td>'; | |
| 2932 | + $out3 .= '<p>' . number_format($tbl_snapshot['rows']) . ' rows totaling ' . WP_Reset_Utility::format_size($tbl_snapshot['size_data']) . ' in data and ' . WP_Reset_Utility::format_size($tbl_snapshot['size_index']) . ' in index.</p>'; | |
| 2933 | + $out3 .= '<pre>' . $tbl_snapshot['schema'] . '</pre>'; | |
| 2934 | + $out3 .= '</td>'; | |
| 2935 | + $out3 .= '</tr>'; | |
| 2936 | + $out3 .= '</table>'; | |
| 2937 | + $out3 .= '</div>'; | |
| 2938 | + } elseif ($schema1 != $schema2) { | |
| 2939 | + require_once $this->plugin_dir . 'libs/diff.php'; | |
| 2940 | + require_once $this->plugin_dir . 'libs/diff/Renderer/Html/SideBySide.php'; | |
| 2941 | + $diff = new WPR_Diff(explode("\n", $tbl_current['schema']), explode("\n", $tbl_snapshot['schema']), array('ignoreWhitespace' => false)); | |
| 2942 | + $renderer = new WPR_Diff_Renderer_Html_SideBySide; | |
| 2515 | 2943 | |
| 2944 | + $out2 .= '<div class="wpr-table-container" data-table="' . $tbl_current['basename'] . '">'; | |
| 2945 | + $out2 .= '<table>'; | |
| 2946 | + $out2 .= '<tr title="Click to show/hide more info" class="wpr-table-difference header-row">'; | |
| 2947 | + $out2 .= '<td><b>' . $tbl_current['fullname'] . '</b> table schemas do not match</td>'; | |
| 2948 | + $out2 .= '<td><b>' . $tbl_snapshot['fullname'] . '</b> table schemas do not match<span class="dashicons dashicons-arrow-down-alt2"></span></td>'; | |
| 2949 | + $out2 .= '</tr>'; | |
| 2950 | + $out2 .= '<tr class="hidden">'; | |
| 2951 | + $out2 .= '<td>'; | |
| 2952 | + $out2 .= '<p>' . number_format($tbl_current['rows']) . ' rows totaling ' . WP_Reset_Utility::format_size($tbl_current['size_data']) . ' in data and ' . WP_Reset_Utility::format_size($tbl_current['size_index']) . ' in index.</p>'; | |
| 2953 | + $out2 .= '</td>'; | |
| 2954 | + $out2 .= '<td>'; | |
| 2955 | + $out2 .= '<p>' . number_format($tbl_snapshot['rows']) . ' rows totaling ' . WP_Reset_Utility::format_size($tbl_snapshot['size_data']) . ' in data and ' . WP_Reset_Utility::format_size($tbl_snapshot['size_index']) . ' in index.</p>'; | |
| 2956 | + $out2 .= '</td>'; | |
| 2957 | + $out2 .= '</tr>'; | |
| 2958 | + $out2 .= '<tr class="hidden">'; | |
| 2959 | + $out2 .= '<td colspan="2" class="no-padding">'; | |
| 2960 | + $out2 .= $diff->Render($renderer); | |
| 2961 | + $out2 .= '</td>'; | |
| 2962 | + $out2 .= '</tr>'; | |
| 2963 | + $out2 .= '</table>'; | |
| 2964 | + $out2 .= '</div>'; | |
| 2965 | + } else { | |
| 2966 | + $out2 .= '<div class="wpr-table-container" data-table="' . $tbl_current['basename'] . '">'; | |
| 2967 | + $out2 .= '<table>'; | |
| 2968 | + $out2 .= '<tr title="Click to show/hide more info" class="wpr-table-difference header-row">'; | |
| 2969 | + $out2 .= '<td><b>' . $tbl_current['fullname'] . '</b> data in tables does not match</td>'; | |
| 2970 | + $out2 .= '<td><b>' . $tbl_snapshot['fullname'] . '</b> data in tables does not match<span class="dashicons dashicons-arrow-down-alt2"></span></td>'; | |
| 2971 | + $out2 .= '</tr>'; | |
| 2972 | + $out2 .= '<tr class="hidden">'; | |
| 2973 | + $out2 .= '<td>'; | |
| 2974 | + $out2 .= '<p>' . number_format($tbl_current['rows']) . ' rows totaling ' . WP_Reset_Utility::format_size($tbl_current['size_data']) . ' in data and ' . WP_Reset_Utility::format_size($tbl_current['size_index']) . ' in index.</p>'; | |
| 2975 | + $out2 .= '</td>'; | |
| 2976 | + $out2 .= '<td>'; | |
| 2977 | + $out2 .= '<p>' . number_format($tbl_snapshot['rows']) . ' rows totaling ' . WP_Reset_Utility::format_size($tbl_snapshot['size_data']) . ' in data and ' . WP_Reset_Utility::format_size($tbl_snapshot['size_index']) . ' in index.</p>'; | |
| 2978 | + $out2 .= '</td>'; | |
| 2979 | + $out2 .= '</tr>'; | |
| 2516 | 2980 | |
| 2517 | - /** | |
| 2518 | - * Add single plugin to featured list | |
| 2519 | - * | |
| 2520 | - * @return object | |
| 2521 | - */ | |
| 2522 | - function add_plugin_featured($plugin_slug, $res) | |
| 2523 | - { | |
| 2524 | - // check if plugin is already on the list | |
| 2525 | - if (!empty($res->plugins) && is_array($res->plugins)) { | |
| 2526 | - foreach ($res->plugins as $plugin) { | |
| 2527 | - if (is_object($plugin) && !empty($plugin->slug) && $plugin->slug == $plugin_slug) { | |
| 2528 | - return $res; | |
| 2981 | + $out2 .= '<tr class="hidden">'; | |
| 2982 | + $out2 .= '<td colspan="2">'; | |
| 2983 | + if ($tbl_current['corename'] == 'options') { | |
| 2984 | + $ss_prefix = $tbl_snapshot['uid'] . '_' . $wpdb->prefix; | |
| 2985 | + //Due to the working with various table sets, not always prefixed with the WordPress Database Table prefix we need to use custom unprepared queries | |
| 2986 | + $diff_rows = $wpdb->get_results("SELECT {$wpdb->prefix}options.option_name, {$wpdb->prefix}options.option_value AS current_value, {$ss_prefix}options.option_value AS snapshot_value FROM {$wpdb->prefix}options LEFT JOIN {$ss_prefix}options ON {$ss_prefix}options.option_name = {$wpdb->prefix}options.option_name WHERE {$wpdb->prefix}options.option_value != {$ss_prefix}options.option_value LIMIT 100;"); //phpcs:ignore | |
| 2987 | + $only_current = $wpdb->get_results("SELECT {$wpdb->prefix}options.option_name, {$wpdb->prefix}options.option_value AS current_value, {$ss_prefix}options.option_value AS snapshot_value FROM {$wpdb->prefix}options LEFT JOIN {$ss_prefix}options ON {$ss_prefix}options.option_name = {$wpdb->prefix}options.option_name WHERE {$ss_prefix}options.option_value IS NULL LIMIT 100;"); //phpcs:ignore | |
| 2988 | + $only_snapshot = $wpdb->get_results("SELECT {$wpdb->prefix}options.option_name, {$wpdb->prefix}options.option_value AS current_value, {$ss_prefix}options.option_value AS snapshot_value FROM {$wpdb->prefix}options LEFT JOIN {$ss_prefix}options ON {$ss_prefix}options.option_name = {$wpdb->prefix}options.option_name WHERE {$wpdb->prefix}options.option_value IS NULL LIMIT 100;"); //phpcs:ignore | |
| 2989 | + $out2 .= '<table class="table_diff">'; | |
| 2990 | + $out2 .= '<tr><td style="width: 100px;"><b>Option Name</b></td><td><b>Current Value</b></td><td><b>Snapshot Value</b></td></tr>'; | |
| 2991 | + foreach ($diff_rows as $row) { | |
| 2992 | + $out2 .= '<tr>'; | |
| 2993 | + $out2 .= '<td style="width: 100px;">' . $row->option_name . '</td>'; | |
| 2994 | + $out2 .= '<td>' . (empty($row->current_value) ? '<i>empty</i>' : $row->current_value) . '</td>'; | |
| 2995 | + $out2 .= '<td>' . (empty($row->snapshot_value) ? '<i>empty</i>' : $row->snapshot_value) . '</td>'; | |
| 2996 | + $out2 .= '</tr>'; | |
| 2997 | + } // foreach | |
| 2998 | + foreach ($only_current as $row) { | |
| 2999 | + $out2 .= '<tr>'; | |
| 3000 | + $out2 .= '<td style="width: 100px;">' . $row->option_name . '</td>'; | |
| 3001 | + $out2 .= '<td>' . (empty($row->current_value) ? '<i>empty</i>' : $row->current_value) . '</td>'; | |
| 3002 | + $out2 .= '<td><i>not found in snapshot</i></td>'; | |
| 3003 | + $out2 .= '</tr>'; | |
| 3004 | + } // foreach | |
| 3005 | + foreach ($only_current as $row) { | |
| 3006 | + $out2 .= '<tr>'; | |
| 3007 | + $out2 .= '<td style="width: 100px;">' . $row->option_name . '</td>'; | |
| 3008 | + $out2 .= '<td><i>not found in current tables</i></td>'; | |
| 3009 | + $out2 .= '<td>' . (empty($row->snapshot_value) ? '<i>empty</i>' : $row->snapshot_value) . '</td>'; | |
| 3010 | + $out2 .= '</tr>'; | |
| 3011 | + } // foreach | |
| 3012 | + $out2 .= '</table>'; | |
| 3013 | + } else { | |
| 3014 | + $out2 .= '<p class="textcenter">Detailed data diff is not available for this table.</p>'; | |
| 3015 | + } | |
| 3016 | + $out2 .= '</td>'; | |
| 3017 | + $out2 .= '</tr>'; | |
| 3018 | + | |
| 3019 | + $out2 .= '</table>'; | |
| 3020 | + $out2 .= '</div>'; | |
| 3021 | + } | |
| 3022 | + } // foreach in both | |
| 3023 | + | |
| 3024 | + return $out . $out2 . $out3; | |
| 3025 | + } // do_compare_snapshots | |
| 3026 | + | |
| 3027 | + | |
| 3028 | + /** | |
| 3029 | + * Generates a unique snapshot ID; verified non-existing | |
| 3030 | + * | |
| 3031 | + * @return string | |
| 3032 | + */ | |
| 3033 | + function generate_snapshot_uid($length = 6) | |
| 3034 | + { | |
| 3035 | + global $wpdb; | |
| 3036 | + $snapshots = $this->get_snapshots(); | |
| 3037 | + $cnt = 0; | |
| 3038 | + $uid = false; | |
| 3039 | + | |
| 3040 | + do { | |
| 3041 | + $cnt++; | |
| 3042 | + $uid = substr(str_shuffle(str_repeat('abcdefghijklmnopqrstuvwxyz', $length)), 0, $length); | |
| 3043 | + // phpcs:ignore db call warning as we are using uncommon queries | |
| 3044 | + $verify_db = $wpdb->get_col($wpdb->prepare('SHOW TABLES LIKE %s', array('%' . $uid . '%'))); // phpcs:ignore | |
| 3045 | + } while (!empty($verify_db) && isset($snapshots[$uid]) && $cnt < 30); | |
| 3046 | + | |
| 3047 | + if ($cnt == 30) { | |
| 3048 | + $uid = false; | |
| 2529 | 3049 | } |
| 2530 | - } // foreach | |
| 2531 | - } | |
| 2532 | 3050 | |
| 2533 | - $plugin_info = get_transient('wf-plugin-info-' . $plugin_slug); | |
| 3051 | + return $uid; | |
| 3052 | + } // generate_snapshot_uid | |
| 2534 | 3053 | |
| 2535 | - if (!$plugin_info) { | |
| 2536 | - $plugin_info = plugins_api('plugin_information', array( | |
| 2537 | - 'slug' => $plugin_slug, | |
| 2538 | - 'is_ssl' => is_ssl(), | |
| 2539 | - 'fields' => array( | |
| 2540 | - 'banners' => true, | |
| 2541 | - 'reviews' => true, | |
| 2542 | - 'downloaded' => true, | |
| 2543 | - 'active_installs' => true, | |
| 2544 | - 'icons' => true, | |
| 2545 | - 'short_description' => true, | |
| 2546 | - ) | |
| 2547 | - )); | |
| 2548 | - if (!is_wp_error($plugin_info)) { | |
| 2549 | - set_transient('wf-plugin-info-' . $plugin_slug, $plugin_info, DAY_IN_SECONDS * 7); | |
| 2550 | - } | |
| 2551 | - } | |
| 2552 | 3054 | |
| 2553 | - if ($plugin_info && is_array($plugin_info)) { | |
| 2554 | - array_unshift($res->plugins, $plugin_info); | |
| 2555 | - } | |
| 3055 | + // auto download / install / activate WP Force SSL plugin | |
| 3056 | + function install_wpfssl() | |
| 3057 | + { | |
| 3058 | + check_ajax_referer('install_wpfssl'); | |
| 2556 | 3059 | |
| 2557 | - return $res; | |
| 2558 | - } // add_plugin_featured | |
| 3060 | + if (false === current_user_can('manage_options')) { | |
| 3061 | + wp_die('Sorry, you have to be an admin to run this action.'); | |
| 3062 | + } | |
| 2559 | 3063 | |
| 3064 | + $plugin_slug = 'wp-force-ssl/wp-force-ssl.php'; | |
| 3065 | + $plugin_zip = 'https://downloads.wordpress.org/plugin/wp-force-ssl.latest-stable.zip'; | |
| 2560 | 3066 | |
| 2561 | - /** | |
| 2562 | - * Add plugins to featured plugins list | |
| 2563 | - * | |
| 2564 | - * @return object | |
| 2565 | - */ | |
| 2566 | - function plugins_api_result($res, $action, $args) | |
| 2567 | - { | |
| 2568 | - remove_filter('plugins_api_result', array($this, 'plugins_api_result'), 10, 3); | |
| 3067 | + @include_once ABSPATH . 'wp-admin/includes/plugin.php'; | |
| 3068 | + @include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; | |
| 3069 | + @include_once ABSPATH . 'wp-admin/includes/plugin-install.php'; | |
| 3070 | + @include_once ABSPATH . 'wp-admin/includes/file.php'; | |
| 3071 | + @include_once ABSPATH . 'wp-admin/includes/misc.php'; | |
| 3072 | + echo '<style> | |
| 3073 | + body{ | |
| 3074 | + font-family: sans-serif; | |
| 3075 | + font-size: 14px; | |
| 3076 | + line-height: 1.5; | |
| 3077 | + color: #444; | |
| 3078 | + } | |
| 3079 | + </style>'; | |
| 2569 | 3080 | |
| 2570 | - $res = $this->add_plugin_featured('under-construction-page', $res); | |
| 2571 | - $res = $this->add_plugin_featured('wp-force-ssl', $res); | |
| 2572 | - $res = $this->add_plugin_featured('eps-301-redirects', $res); | |
| 3081 | + echo '<div style="margin: 20px; color:#444;">'; | |
| 3082 | + echo 'If things are not done in a minute <a target="_parent" href="' . esc_url(admin_url('plugin-install.php?s=force%20ssl%20webfactory&tab=search&type=term')) . '">install the plugin manually via Plugins page</a><br><br>'; | |
| 3083 | + echo 'Starting ...<br><br>'; | |
| 2573 | 3084 | |
| 2574 | - return $res; | |
| 2575 | - } // plugins_api_result | |
| 3085 | + wp_cache_flush(); | |
| 3086 | + $upgrader = new Plugin_Upgrader(); | |
| 3087 | + echo 'Check if WP Force SSL is already installed ... <br />'; | |
| 3088 | + if ($this->is_plugin_installed($plugin_slug)) { | |
| 3089 | + echo 'WP Force SSL is already installed! <br /><br />Making sure it\'s the latest version.<br />'; | |
| 3090 | + $upgrader->upgrade($plugin_slug); | |
| 3091 | + $installed = true; | |
| 3092 | + } else { | |
| 3093 | + echo 'Installing WP Force SSL.<br />'; | |
| 3094 | + $installed = $upgrader->install($plugin_zip); | |
| 3095 | + } | |
| 3096 | + wp_cache_flush(); | |
| 2576 | 3097 | |
| 3098 | + if (!is_wp_error($installed) && $installed) { | |
| 3099 | + echo 'Activating WP Force SSL.<br />'; | |
| 3100 | + $activate = activate_plugin($plugin_slug); | |
| 2577 | 3101 | |
| 2578 | - /** | |
| 2579 | - * Clean up on uninstall; no action on deactive at the moment | |
| 2580 | - * | |
| 2581 | - * @return null | |
| 2582 | - */ | |
| 2583 | - static function uninstall() | |
| 2584 | - { | |
| 2585 | - delete_option('wp-reset'); | |
| 2586 | - delete_option('wp-reset-snapshots'); | |
| 2587 | - } // uninstall | |
| 3102 | + if (is_null($activate)) { | |
| 3103 | + echo 'WP Force SSL Activated.<br />'; | |
| 2588 | 3104 | |
| 3105 | + echo '<script>setTimeout(function() { top.location = "tools.php?page=wp-reset"; }, 1000);</script>'; | |
| 3106 | + echo '<br>If you are not redirected in a few seconds - <a href="tools.php?page=wp-reset" target="_parent">click here</a>.'; | |
| 3107 | + } | |
| 3108 | + } else { | |
| 3109 | + echo 'Could not install WP Force SSL. You\'ll have to <a target="_parent" href="' . esc_url(admin_url('plugin-install.php?s=force%20ssl%20webfactory&tab=search&type=term')) . '">download and install manually</a>.'; | |
| 3110 | + } | |
| 2589 | 3111 | |
| 2590 | - /** | |
| 2591 | - * Disabled; we use singleton pattern so magic functions need to be disabled | |
| 2592 | - * | |
| 2593 | - * @return null | |
| 2594 | - */ | |
| 2595 | - private function __clone() | |
| 2596 | - { } | |
| 3112 | + echo '</div>'; | |
| 3113 | + } // install_wpfssl | |
| 2597 | 3114 | |
| 3115 | + /** | |
| 3116 | + * Initializes the WordPress filesystem. | |
| 3117 | + * | |
| 3118 | + * @return bool | |
| 3119 | + */ | |
| 3120 | + function wp_init_filesystem() | |
| 3121 | + { | |
| 3122 | + if (! $this->filesystem_initialized) { | |
| 3123 | + if (! class_exists('WP_Filesystem')) { | |
| 3124 | + require_once ABSPATH . 'wp-admin/includes/file.php'; | |
| 3125 | + } | |
| 2598 | 3126 | |
| 2599 | - /** | |
| 2600 | - * Disabled; we use singleton pattern so magic functions need to be disabled | |
| 2601 | - * | |
| 2602 | - * @return null | |
| 2603 | - */ | |
| 2604 | - private function __sleep() | |
| 2605 | - { } | |
| 3127 | + WP_Filesystem(); | |
| 3128 | + $this->filesystem_initialized = true; | |
| 3129 | + } | |
| 2606 | 3130 | |
| 3131 | + return true; | |
| 3132 | + } | |
| 2607 | 3133 | |
| 2608 | - /** | |
| 2609 | - * Disabled; we use singleton pattern so magic functions need to be disabled | |
| 2610 | - * | |
| 2611 | - * @return null | |
| 2612 | - */ | |
| 2613 | - private function __wakeup() | |
| 2614 | - { } | |
| 3134 | + /** | |
| 3135 | + * Clean up on uninstall; no action on deactive at the moment | |
| 3136 | + * | |
| 3137 | + * @return null | |
| 3138 | + */ | |
| 3139 | + static function uninstall() | |
| 3140 | + { | |
| 3141 | + delete_option('wp-reset'); | |
| 3142 | + delete_option('wp-reset-snapshots'); | |
| 3143 | + } // uninstall | |
| 3144 | + | |
| 3145 | + | |
| 3146 | + /** | |
| 3147 | + * Disabled; we use singleton pattern so magic functions need to be disabled | |
| 3148 | + * | |
| 3149 | + * @return null | |
| 3150 | + */ | |
| 3151 | + function __clone() {} | |
| 3152 | + | |
| 3153 | + | |
| 3154 | + /** | |
| 3155 | + * Disabled; we use singleton pattern so magic functions need to be disabled | |
| 3156 | + * | |
| 3157 | + * @return null | |
| 3158 | + */ | |
| 3159 | + function __sleep() {} | |
| 3160 | + | |
| 3161 | + | |
| 3162 | + /** | |
| 3163 | + * Disabled; we use singleton pattern so magic functions need to be disabled | |
| 3164 | + * | |
| 3165 | + * @return null | |
| 3166 | + */ | |
| 3167 | + function __wakeup() {} | |
| 2615 | 3168 | } // WP_Reset class |
| 2616 | 3169 | |
| 2617 | 3170 | |
| 2618 | 3171 | // Create plugin instance and hook things up |
| @@ -2617,9 +3170,9 @@ | ||
| 2617 | 3170 | |
| 2618 | 3171 | // Create plugin instance and hook things up |
| 2619 | 3172 | // Only if in admin - plugin has no frontend functionality |
| 2620 | 3173 | if (is_admin() || WP_Reset::is_cli_running()) { |
| 2621 | - global $wp_reset; | |
| 2622 | - $wp_reset = WP_Reset::getInstance(); | |
| 2623 | - add_action('plugins_loaded', array($wp_reset, 'load_textdomain')); | |
| 2624 | - register_uninstall_hook(__FILE__, array('WP_Reset', 'uninstall')); | |
| 3174 | + global $wp_reset; | |
| 3175 | + $wp_reset = WP_Reset::getInstance(); | |
| 3176 | + add_action('plugins_loaded', array($wp_reset, 'load_textdomain')); | |
| 3177 | + register_uninstall_hook(__FILE__, array('WP_Reset', 'uninstall')); | |
| 2625 | 3178 | } |