PluginProbe ʕ •ᴥ•ʔ
WP STAGING – WordPress Backup, Restore, Migration & Clone / 3.0.1
WP STAGING – WordPress Backup, Restore, Migration & Clone v3.0.1
4.9.1 4.9.0 4.8.1 trunk 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.1.0 3.1.1 3.1.2 3.1.3 3.1.4 3.10.0 3.2.0 3.3.1 3.3.2 3.3.3 3.4.1 3.4.3 3.5.0 3.6.0 3.7.1 3.8.0 3.8.1 3.8.2 3.8.3 3.8.4 3.8.5 3.8.6 3.8.7 3.9.0 3.9.1 3.9.2 3.9.3 3.9.4 4.0.0 4.1.0 4.1.1 4.1.2 4.1.3 4.1.4 4.2.0 4.2.1 4.3.0 4.3.1 4.3.2 4.4.0 4.5.0 4.6.0 4.7.0 4.7.1 4.7.2 4.7.3 4.8.0
wp-staging / Backend / Administrator.php
wp-staging / Backend Last commit date
Activation 5 years ago Feedback 2 years ago Modules 2 years ago Optimizer 3 years ago Pluginmeta 4 years ago Upgrade 3 years ago helpers 5 years ago views 2 years ago Administrator.php 2 years ago
Administrator.php
1350 lines
1 <?php
2
3 namespace WPStaging\Backend;
4
5 use WPStaging\Core\WPStaging;
6 use WPStaging\Core\DTO\Settings;
7 use WPStaging\Framework\Analytics\Actions\AnalyticsStagingReset;
8 use WPStaging\Framework\Analytics\Actions\AnalyticsStagingUpdate;
9 use WPStaging\Framework\Assets\Assets;
10 use WPStaging\Framework\Database\DbInfo;
11 use WPStaging\Framework\SiteInfo;
12 use WPStaging\Framework\Security\Auth;
13 use WPStaging\Framework\Mails\Report\Report;
14 use WPStaging\Framework\Filesystem\Filters\ExcludeFilter;
15 use WPStaging\Framework\Filesystem\DebugLogReader;
16 use WPStaging\Framework\Filesystem\PathIdentifier;
17 use WPStaging\Framework\TemplateEngine\TemplateEngine;
18 use WPStaging\Framework\CloningProcess\Database\CompareExternalDatabase;
19 use WPStaging\Framework\Utils\Math;
20 use WPStaging\Framework\Utils\WpDefaultDirectories;
21 use WPStaging\Framework\Notices\DismissNotice;
22 use WPStaging\Framework\Staging\Sites;
23 use WPStaging\Backend\Modules\Jobs\Cancel;
24 use WPStaging\Backend\Modules\Jobs\CancelUpdate;
25 use WPStaging\Backend\Modules\Jobs\Cloning;
26 use WPStaging\Backend\Modules\Jobs\Updating;
27 use WPStaging\Backend\Modules\Jobs\Delete;
28 use WPStaging\Backend\Modules\Jobs\Scan;
29 use WPStaging\Backend\Modules\Jobs\Logs;
30 use WPStaging\Backend\Modules\Jobs\ProcessLock;
31 use WPStaging\Backend\Modules\SystemInfo;
32 use WPStaging\Backend\Modules\Views\Tabs\Tabs;
33 use WPStaging\Backend\Modules\Views\Forms\Settings as FormSettings;
34 use WPStaging\Backend\Activation;
35 use WPStaging\Backend\Pro\Modules\Jobs\Processing;
36 use WPStaging\Backend\Pro\Modules\Jobs\Backups\BackupUploadsDir;
37 use WPStaging\Backend\Pluginmeta\Pluginmeta;
38 use WPStaging\Framework\Database\SelectedTables;
39 use WPStaging\Framework\Utils\Escape;
40 use WPStaging\Framework\Utils\Sanitize;
41 use WPStaging\Backend\Pro\Modules\Jobs\Scan as ScanProModule;
42 use WPStaging\Backend\Feedback\Feedback;
43 use WPStaging\Framework\Security\Nonce;
44
45 /**
46 * Class Administrator
47 * @package WPStaging\Backend
48 */
49 class Administrator
50 {
51
52 /**
53 * @var int Place WP Staging Menu below Plugins
54 */
55 const MENU_POSITION_ORDER = 65;
56
57 /**
58 * @var int Place WP Staging Menu below Plugins for multisite
59 */
60 const MENU_POSITION_ORDER_MULTISITE = 20;
61
62
63 /**
64 * Path to plugin's Backend Dir
65 * @var string
66 */
67 private $path;
68
69 /**
70 * @var Assets
71 */
72 private $assets;
73
74 /**
75 * @var Auth
76 */
77 private $auth;
78
79 /**
80 * @var SiteInfo
81 */
82 private $siteInfo;
83
84 /** @var Sanitize */
85 private $sanitize;
86
87 public function __construct()
88 {
89 $this->auth = WPStaging::make(Auth::class);
90 $this->assets = WPStaging::make(Assets::class);
91 $this->siteInfo = WPStaging::make(SiteInfo::class);
92
93 $this->defineHooks();
94
95 // Path to backend
96 $this->path = plugin_dir_path(__FILE__);
97
98 $this->sanitize = WPStaging::make(Sanitize::class);
99
100 // Load plugins meta data
101 $this->loadMeta();
102 }
103
104 /**
105 * Load plugin meta data
106 */
107 public function loadMeta()
108 {
109 new Pluginmeta();
110 }
111
112 /**
113 * Define Hooks
114 */
115 private function defineHooks()
116 {
117 if (!defined('WPSTGPRO_VERSION')) {
118 new Activation\Welcome();
119 }
120
121 add_action("admin_menu", [$this, "addMenu"], 10);
122 add_action("admin_init", [$this, "upgrade"]);
123 add_action("admin_post_wpstg_download_sysinfo", [$this, "systemInfoDownload"]); // phpcs:ignore WPStaging.Security.AuthorizationChecked
124
125 if (!defined('WPSTGPRO_VERSION') && $this->isPluginsPage()) {
126 add_filter('admin_footer', [$this, 'loadFeedbackForm']);
127 }
128
129 // Ajax Requests
130 add_action("wp_ajax_wpstg_overview", [$this, "ajaxOverview"]); // phpcs:ignore WPStaging.Security.AuthorizationChecked
131 add_action("wp_ajax_wpstg_scanning", [$this, "ajaxCloneScan"]); // phpcs:ignore WPStaging.Security.AuthorizationChecked
132 add_action("wp_ajax_wpstg_check_clone", [$this, "ajaxCheckCloneDirectoryName"]); // phpcs:ignore WPStaging.Security.AuthorizationChecked
133 add_action("wp_ajax_wpstg_restart", [$this, "ajaxRestart"]); // phpcs:ignore WPStaging.Security.AuthorizationChecked
134 add_action("wp_ajax_wpstg_update", [$this, "ajaxUpdateProcess"]); // phpcs:ignore WPStaging.Security.AuthorizationChecked
135 add_action("wp_ajax_wpstg_reset", [$this, "ajaxResetProcess"]); // phpcs:ignore WPStaging.Security.AuthorizationChecked
136 add_action("wp_ajax_wpstg_cloning", [$this, "ajaxStartClone"]); // phpcs:ignore WPStaging.Security.AuthorizationChecked
137 add_action("wp_ajax_wpstg_processing", [$this, "ajaxCloneDatabase"]); // phpcs:ignore WPStaging.Security.AuthorizationChecked
138 add_action("wp_ajax_wpstg_database_connect", [$this, "ajaxDatabaseConnect"]); // phpcs:ignore WPStaging.Security.AuthorizationChecked
139 add_action("wp_ajax_wpstg_database_verification", [$this, "ajaxDatabaseVerification"]); // phpcs:ignore WPStaging.Security.AuthorizationChecked
140 add_action("wp_ajax_wpstg_clone_prepare_directories", [$this, "ajaxPrepareDirectories"]); // phpcs:ignore WPStaging.Security.AuthorizationChecked
141 add_action("wp_ajax_wpstg_clone_files", [$this, "ajaxCopyFiles"]); // phpcs:ignore WPStaging.Security.AuthorizationChecked
142 add_action("wp_ajax_wpstg_clone_replace_data", [$this, "ajaxReplaceData"]); // phpcs:ignore WPStaging.Security.AuthorizationChecked
143 add_action("wp_ajax_wpstg_clone_finish", [$this, "ajaxFinish"]); // phpcs:ignore WPStaging.Security.AuthorizationChecked
144 add_action("wp_ajax_wpstg_confirm_delete_clone", [$this, "ajaxDeleteConfirmation"]); // phpcs:ignore WPStaging.Security.AuthorizationChecked
145 add_action("wp_ajax_wpstg_delete_clone", [$this, "ajaxDeleteClone"]); // phpcs:ignore WPStaging.Security.AuthorizationChecked
146 add_action("wp_ajax_wpstg_cancel_clone", [$this, "ajaxCancelClone"]); // phpcs:ignore WPStaging.Security.AuthorizationChecked
147 add_action("wp_ajax_wpstg_cancel_update", [$this, "ajaxCancelUpdate"]); // phpcs:ignore WPStaging.Security.AuthorizationChecked
148 add_action("wp_ajax_wpstg_hide_rating", [$this, "ajaxHideRating"]); // phpcs:ignore WPStaging.Security.AuthorizationChecked
149 add_action("wp_ajax_wpstg_hide_later", [$this, "ajaxHideLaterRating"]); // phpcs:ignore WPStaging.Security.AuthorizationChecked
150 add_action("wp_ajax_wpstg_hide_beta", [$this, "ajaxHideBeta"]); // phpcs:ignore WPStaging.Security.AuthorizationChecked
151 add_action("wp_ajax_wpstg_logs", [$this, "ajaxLogs"]); // phpcs:ignore WPStaging.Security.AuthorizationChecked
152 add_action("wp_ajax_wpstg_check_disk_space", [$this, "ajaxCheckFreeSpace"]); // phpcs:ignore WPStaging.Security.AuthorizationChecked
153 add_action("wp_ajax_wpstg_send_report", [$this, "ajaxSendReport"]); // phpcs:ignore WPStaging.Security.AuthorizationChecked
154 add_action("wp_ajax_wpstg_send_feedback", [$this, "sendFeedback"]); // phpcs:ignore WPStaging.Security.AuthorizationChecked
155 add_action("wp_ajax_wpstg_enable_staging_cloning", [$this, "ajaxEnableStagingCloning"]); // phpcs:ignore WPStaging.Security.AuthorizationChecked
156 add_action("wp_ajax_wpstg_clone_excludes_settings", [$this, "ajaxCloneExcludesSettings"]); // phpcs:ignore WPStaging.Security.AuthorizationChecked
157 add_action("wp_ajax_wpstg_fetch_dir_children", [$this, "ajaxFetchDirChildren"]); // phpcs:ignore WPStaging.Security.AuthorizationChecked
158 add_action("wp_ajax_wpstg_modal_error", [$this, "ajaxModalError"]); // phpcs:ignore WPStaging.Security.AuthorizationChecked
159 add_action("wp_ajax_wpstg_dismiss_notice", [$this, "ajaxDismissNotice"]); // phpcs:ignore WPStaging.Security.AuthorizationChecked
160 add_action("wp_ajax_wpstg_restore_settings", [$this, "ajaxRestoreSettings"]); // phpcs:ignore WPStaging.Security.AuthorizationChecked
161
162 // Ajax hooks pro Version
163 // TODO: move all below actions to pro service provider?
164 add_action("wp_ajax_wpstg_edit_clone_data", [$this, "ajaxEditCloneData"]); // phpcs:ignore WPStaging.Security.AuthorizationChecked
165 add_action("wp_ajax_wpstg_save_clone_data", [$this, "ajaxSaveCloneData"]); // phpcs:ignore WPStaging.Security.AuthorizationChecked
166 add_action("wp_ajax_wpstg_scan", [$this, "ajaxPushScan"]); // phpcs:ignore WPStaging.Security.AuthorizationChecked
167 add_action("wp_ajax_wpstg_push_tables", [$this, "ajaxPushTables"]); // phpcs:ignore WPStaging.Security.AuthorizationChecked
168 add_action("wp_ajax_wpstg_push_processing", [$this, "ajaxPushProcessing"]); // phpcs:ignore WPStaging.Security.AuthorizationChecked
169 add_action("wp_ajax_nopriv_wpstg_push_processing", [$this, "ajaxPushProcessing"]); // phpcs:ignore WPStaging.Security.AuthorizationChecked
170
171 // TODO: replace uploads backup during push once we have backups PR ready,
172 // Then there will be no need to have any cron to delete those backups
173 if (class_exists('WPStaging\Backend\Pro\Modules\Jobs\Backups\BackupUploadsDir')) {
174 add_action(BackupUploadsDir::BACKUP_DELETE_CRON_HOOK_NAME, [$this, "removeOldUploadsBackup"]); // phpcs:ignore WPStaging.Security.FirstArgNotAString -- Cron callback
175 }
176 }
177
178 /**
179 * Load Feedback Form on plugins.php
180 */
181 public function loadFeedbackForm()
182 {
183 $form = WPStaging::make(Feedback::class);
184 $form->loadForm();
185 }
186
187 /**
188 * Send Feedback data via mail
189 */
190 public function sendFeedback()
191 {
192
193 $nonce = isset($_POST['nonce']) ? sanitize_text_field($_POST['nonce']) : '';
194
195 if (!$this->isAuthenticated($nonce)) {
196 return;
197 }
198
199 $form = WPStaging::make(Feedback::class);
200 $form->sendMail();
201 }
202
203 /**
204 * Upgrade routine
205 * @action admin_init 10 0
206 * @see \WPStaging\Backend\Administrator::defineHooks
207 */
208 public function upgrade()
209 {
210 if (defined('WPSTGPRO_VERSION') && class_exists('WPStaging\Backend\Pro\Upgrade\Upgrade')) {
211 $upgrade = WPStaging::make('WPStaging\Backend\Pro\Upgrade\Upgrade');
212 } else {
213 $upgrade = WPStaging::make('WPStaging\Backend\Upgrade\Upgrade');
214 }
215 $upgrade->doUpgrade();
216 }
217
218 /**
219 * Add Admin Menu(s)
220 */
221 public function addMenu()
222 {
223 global $wp_version;
224 $logo = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4KPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgMTAwMCAxMDAwIiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCAxMDAwIDEwMDAiIHhtbDpzcGFjZT0icHJlc2VydmUiIGZpbGw9Im5vbmUiPgo8Zz48Zz48cGF0aCBzdHlsZT0iZmlsbDojZmZmIiAgZD0iTTEzNy42LDU2MS4zSDEzLjhIMTB2MzA2LjNsOTAuNy04My40QzE4OS42LDkwOC43LDMzNS4zLDk5MCw1MDAsOTkwYzI0OS45LDAsNDU2LjEtMTg3LjEsNDg2LjItNDI4LjhIODYyLjRDODMzLjMsNzM1LjEsNjgyLjEsODY3LjUsNTAwLDg2Ny41Yy0xMjksMC0yNDIuNS02Ni41LTMwOC4xLTE2Ny4ybDE1MS4zLTEzOS4xSDEzNy42eiIvPjxwYXRoIHN0eWxlPSJmaWxsOiNmZmYiICBkPSJNNTAwLDEwQzI1MC4xLDEwLDQzLjksMTk3LjEsMTMuOCw0MzguOGgxMjMuOEMxNjYuNywyNjQuOSwzMTcuOSwxMzIuNSw1MDAsMTMyLjVjMTMyLjksMCwyNDkuMyw3MC41LDMxMy44LDE3Ni4yTDY4My44LDQzOC44aDEyMi41aDU2LjJoMTIzLjhoMy44VjEzMi41bC04Ny43LDg3LjdDODEzLjgsOTMuMSw2NjYuNiwxMCw1MDAsMTB6Ii8+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjwvZz4KPC9zdmc+';
225
226 $pos = self::MENU_POSITION_ORDER;
227 if (is_multisite()) {
228 $pos = self::MENU_POSITION_ORDER_MULTISITE;
229 }
230
231 // Menu Position order needs to be unique for WordPress < 4.4
232 // We are not using a unique position by default to keep WP Staging directly below plugin menu
233 if (version_compare($wp_version, '4.4', '<')) {
234 $pos++;
235 }
236
237 $proSlug = defined('WPSTGPRO_VERSION') ? 'Pro' : '';
238
239 // Main WP Staging Menu
240 add_menu_page(
241 "WP STAGING",
242 __("WP Staging " . $proSlug, "wp-staging"),
243 "manage_options",
244 "wpstg_clone",
245 [$this, "getClonePage"],
246 $logo,
247 $pos
248 );
249
250 // Page: Clone
251 add_submenu_page(
252 "wpstg_clone",
253 __("WP Staging Jobs", "wp-staging"),
254 __("Staging Sites", "wp-staging"),
255 "manage_options",
256 "wpstg_clone",
257 [$this, "getClonePage"]
258 );
259
260 add_submenu_page(
261 "wpstg_clone",
262 __("WP Staging Jobs", "wp-staging"),
263 __("Backup & Migration", "wp-staging"),
264 "manage_options",
265 "wpstg_backup",
266 [$this, "getBackupPage"]
267 );
268
269 // Page: Settings
270 add_submenu_page(
271 "wpstg_clone",
272 __("WP Staging Settings", "wp-staging"),
273 __("Settings", "wp-staging"),
274 "manage_options",
275 "wpstg-settings",
276 [$this, "getSettingsPage"]
277 );
278
279 // Page: Tools
280 add_submenu_page(
281 "wpstg_clone",
282 __("WP Staging Tools", "wp-staging"),
283 __("System Info", "wp-staging"),
284 "manage_options",
285 "wpstg-tools",
286 [$this, "getToolsPage"]
287 );
288
289 if (!defined('WPSTGPRO_VERSION')) {
290 // Page: Tools
291 add_submenu_page(
292 "wpstg_clone",
293 __("WP Staging Welcome", "wp-staging"),
294 __("Get WP Staging Pro", "wp-staging"),
295 "manage_options",
296 "wpstg-welcome",
297 [$this, "getWelcomePage"]
298 );
299 }
300
301 if (defined('WPSTGPRO_VERSION')) {
302 // Page: License
303 add_submenu_page(
304 "wpstg_clone",
305 __("WP Staging License", "wp-staging"),
306 __("License", "wp-staging"),
307 "manage_options",
308 "wpstg-license",
309 [$this, "getLicensePage"]
310 );
311 }
312 }
313
314 /**
315 * Settings Page
316 */
317 public function getSettingsPage()
318 {
319
320 $license = get_option('wpstg_license_status');
321
322 // Tabs
323 $tabs = new Tabs(apply_filters('wpstg_main_settings_tabs', [
324 "general" => __("General", "wp-staging")
325 ]));
326
327 WPStaging::getInstance()
328 // Set tabs
329 ->set("tabs", $tabs)
330 // Forms
331 ->set("forms", new FormSettings($tabs));
332
333 require_once "{$this->path}views/settings/main-settings.php";
334 }
335
336 /**
337 * Clone Page
338 */
339 public function getClonePage()
340 {
341
342 $license = get_option('wpstg_license_status');
343
344 $availableClones = get_option(Sites::STAGING_SITES_OPTION, []);
345
346 require_once "{$this->path}views/clone/index.php";
347 }
348
349 /**
350 * Backup & Migration Page
351 */
352 public function getBackupPage()
353 {
354 $license = get_option('wpstg_license_status');
355
356 // Existing clones
357 $availableClones = get_option(Sites::STAGING_SITES_OPTION, []);
358
359 $isBackupPage = true;
360
361 require_once "{$this->path}views/clone/index.php";
362 }
363
364 /**
365 * Welcome Page
366 */
367 public function getWelcomePage()
368 {
369 if (defined('WPSTGPRO_VERSION')) {
370 return;
371 }
372 require_once "{$this->path}views/welcome/welcome.php";
373 }
374
375 /**
376 * Tools Page
377 */
378 public function getToolsPage()
379 {
380 // Tabs
381 $tabs = new Tabs([
382 "system-info" => __("System Info", "wp-staging")
383 ]);
384
385 WPStaging::getInstance()->set("tabs", $tabs);
386
387 WPStaging::getInstance()->set("systemInfo", new SystemInfo());
388
389 // Get license data
390 $license = get_option('wpstg_license_status');
391
392 require_once "{$this->path}views/tools/index.php";
393 }
394
395 /**
396 * System Information Download
397 */
398 public function systemInfoDownload()
399 {
400 if (!current_user_can("update_plugins")) {
401 return;
402 }
403
404 nocache_headers();
405 header("Content-Type: text/plain");
406 header('Content-Disposition: attachment; filename="wpstg-system-info.txt"');
407 echo esc_html(wp_strip_all_tags(WPStaging::make(SystemInfo::class)->get("systemInfo")));
408 echo esc_html("\n\n" . str_repeat("-", 25) . "\n\n");
409 $wpstgLogs = WPStaging::make(DebugLogReader::class)->getLastLogEntries(100 * KB_IN_BYTES, true, false);
410 echo esc_html(wp_strip_all_tags($wpstgLogs));
411 echo esc_html(PHP_EOL . PHP_EOL . str_repeat("-", 25) . PHP_EOL . PHP_EOL);
412 $wpCoreDebugLog = WPStaging::make(DebugLogReader::class)->getLastLogEntries((256 * KB_IN_BYTES ), false, true);
413 echo esc_html(wp_strip_all_tags($wpCoreDebugLog ));
414 }
415
416 /**
417 * Render a view file
418 * @param string $file
419 * @param array $vars
420 * @return string
421 */
422 public function render($file, $vars = [])
423 {
424 $fullPath = $this->path . "views/" . $file . ".php";
425 $fullPath = wp_normalize_path($fullPath);
426
427 if (!file_exists($fullPath) || !is_readable($fullPath)) {
428 return "Can't render : {$fullPath} either file doesn't exist or can't read it";
429 }
430
431 $contents = @file_get_contents($fullPath);
432
433 // Variables are set
434 if (count($vars) > 0) {
435 $vars = array_combine(
436 array_map(function ($key) {
437 return "{{" . $key . "}}";
438 }, array_keys($vars)),
439 $vars
440 );
441
442 $contents = str_replace(array_keys($vars), array_values($vars), $contents);
443 }
444
445 return $contents;
446 }
447
448 /**
449 * @return bool Whether the current request is considered to be authenticated.
450 */
451 private function isAuthenticated($nonce = Nonce::WPSTG_NONCE)
452 {
453 return $this->auth->isAuthenticatedRequest($nonce);
454 }
455
456 /**
457 * Restart cloning process
458 */
459 public function ajaxRestart()
460 {
461 if (!$this->isAuthenticated()) {
462 return;
463 }
464
465 $process = WPStaging::make(ProcessLock::class);
466 $process->restart();
467 }
468
469 /**
470 * Ajax Overview
471 */
472 public function ajaxOverview()
473 {
474 if (!$this->isAuthenticated()) {
475 return;
476 }
477
478 // Existing clones
479 $sites = WPStaging::make(Sites::class);
480 $availableClones = $sites->getSortedStagingSites();
481
482 // Get license data
483 $license = get_option('wpstg_license_status');
484
485 // Get db
486 $db = WPStaging::make('wpdb');
487
488 $iconPath = $this->assets->getAssetsUrl('svg/vendor/dashicons/cloud.svg');
489
490 require_once "{$this->path}views/clone/ajax/single-overview.php";
491
492 wp_die();
493 }
494
495 /**
496 * Ajax Scan
497 * @action wp_ajax_wpstg_scanning 10 0
498 * @see Administrator::defineHooks()
499 */
500 public function ajaxCloneScan()
501 {
502 if (!$this->isAuthenticated()) {
503 return;
504 }
505
506 // Check first if there is already a process running
507 $processLock = WPStaging::make(ProcessLock::class);
508 $response = $processLock->ajaxIsRunning();
509 if ($response !== false) {
510 echo json_encode($response);
511
512 exit();
513 }
514
515 $db = WPStaging::make('wpdb');
516
517 // Scan
518 $scan = WPStaging::make(Scan::class);
519 $scan->setGifLoaderPath($this->assets->getAssetsUrl('img/spinner.gif'));
520 $scan->setInfoIcon($this->assets->getAssetsUrl('svg/vendor/dashicons/info-outline.svg'));
521 $scan->start();
522
523 // Get Options
524 $options = $scan->getOptions();
525 $excludeUtils = WPStaging::make(ExcludeFilter::class);
526 $wpDefaultDirectories = WPStaging::make(WpDefaultDirectories::class);
527 require_once "{$this->path}views/clone/ajax/scan.php";
528
529 wp_die();
530 }
531
532 /**
533 * Fetch children of the given directory
534 */
535 public function ajaxFetchDirChildren()
536 {
537 if (!$this->isAuthenticated()) {
538 wp_send_json(['success' => false]);
539 return;
540 }
541
542 $isChecked = isset($_POST['isChecked']) ? $this->sanitize->sanitizeBool($_POST['isChecked']) : false;
543 $forceDefault = isset($_POST['forceDefault']) ? $this->sanitize->sanitizeBool($_POST['forceDefault']) : false;
544 $path = isset($_POST['dirPath']) ? $this->sanitize->sanitizePath($_POST['dirPath']) : "";
545 $prefix = isset($_POST['prefix']) ? $this->sanitize->sanitizePath($_POST['prefix']) : "";
546 $basePath = ABSPATH;
547 if ($prefix === PathIdentifier::IDENTIFIER_WP_CONTENT) {
548 $basePath = WP_CONTENT_DIR;
549 }
550
551 $path = trailingslashit($basePath) . $path;
552 $scan = new Scan($path);
553 $scan->setBasePath($basePath);
554 $scan->setPathIdentifier($prefix);
555 $scan->setGifLoaderPath($this->assets->getAssetsUrl('img/spinner.gif'));
556 $scan->getDirectories($path);
557 wp_send_json([
558 "success" => true,
559 "directoryListing" => json_encode($scan->directoryListing($isChecked, $forceDefault)),
560 ]);
561 }
562
563 /**
564 * Ajax Check Clone Name
565 */
566 public function ajaxCheckCloneDirectoryName()
567 {
568 if (!$this->isAuthenticated()) {
569 return;
570 }
571
572 /** @var Sites $sitesHelper */
573 $sitesHelper = WPStaging::make(Sites::class);
574 $cloneDirectoryName = isset($_POST["directoryName"]) ? $sitesHelper->sanitizeDirectoryName($_POST["directoryName"]) : '';
575
576 if (strlen($cloneDirectoryName) < 1) {
577 return;
578 }
579
580 $result = $sitesHelper->isCloneExists($cloneDirectoryName);
581 if ($result === false) {
582 wp_send_json(["status" => "success"]);
583 return;
584 }
585
586 wp_send_json([
587 "status" => "failed",
588 "message" => $result
589 ]);
590 }
591
592 /**
593 * Ajax Start Updating Clone (Basically just layout and saving data)
594 */
595 public function ajaxUpdateProcess()
596 {
597 if (!$this->isAuthenticated()) {
598 return;
599 }
600
601 $cloning = WPStaging::make(Updating::class);
602
603 if (!$cloning->save()) {
604 wp_die('Can not save clone data');
605 }
606
607 $options = $cloning->getOptions();
608 WPStaging::make(AnalyticsStagingUpdate::class)->enqueueStartEvent($options->jobIdentifier, $options);
609
610 require_once "{$this->path}views/clone/ajax/update.php";
611
612 wp_die();
613 }
614
615 /**
616 * Ajax Start Resetting Clone
617 */
618 public function ajaxResetProcess()
619 {
620 if (!$this->isAuthenticated()) {
621 return;
622 }
623
624 $cloning = WPStaging::make(Updating::class);
625 $cloning->setMainJob(Updating::RESET_UPDATE);
626 if (!$cloning->save()) {
627 wp_die('can not save clone data');
628 }
629
630 $options = $cloning->getOptions();
631 WPStaging::make(AnalyticsStagingReset::class)->enqueueStartEvent($options->jobIdentifier, $options);
632
633 require_once "{$this->path}views/clone/ajax/update.php";
634 wp_die();
635 }
636
637 /**
638 * Ajax Start Clone (Basically just layout and saving data)
639 */
640 public function ajaxStartClone()
641 {
642 if (!$this->isAuthenticated()) {
643 return;
644 }
645
646 // Check first if there is already a process running
647 $processLock = WPStaging::make(ProcessLock::class);
648 $processLock->isRunning();
649
650 $cloning = WPStaging::make(Cloning::class);
651
652 if (!$cloning->save()) {
653 $message = $cloning->getErrorMessage();
654 wp_send_json([
655 'success' => false,
656 'message' => $message !== '' ? $message : 'Can not save clone data'
657 ]);
658
659 wp_die();
660 }
661
662 require_once "{$this->path}views/clone/ajax/start.php";
663
664 wp_die();
665 }
666
667 /**
668 * Ajax Clone Database
669 */
670 public function ajaxCloneDatabase()
671 {
672 if (!$this->isAuthenticated()) {
673 return;
674 }
675
676 wp_send_json(WPStaging::make(Cloning::class)->start());
677 }
678
679 /**
680 * Ajax Prepare Directories (get listing of files)
681 */
682 public function ajaxPrepareDirectories()
683 {
684 if (!$this->isAuthenticated()) {
685 return;
686 }
687
688 wp_send_json(WPStaging::make(Cloning::class)->start());
689 }
690
691 /**
692 * Ajax Clone Files
693 */
694 public function ajaxCopyFiles()
695 {
696 if (!$this->isAuthenticated()) {
697 return;
698 }
699
700 wp_send_json(WPStaging::make(Cloning::class)->start());
701 }
702
703 /**
704 * Ajax Replace Data
705 */
706 public function ajaxReplaceData()
707 {
708 if (!$this->isAuthenticated()) {
709 return;
710 }
711
712 wp_send_json(WPStaging::make(Cloning::class)->start());
713 }
714
715 /**
716 * Ajax Finish
717 */
718 public function ajaxFinish()
719 {
720 if (!$this->isAuthenticated()) {
721 return;
722 }
723
724 wp_send_json(WPStaging::make(Cloning::class)->start());
725 }
726
727 /**
728 * Ajax Delete Confirmation
729 */
730 public function ajaxDeleteConfirmation()
731 {
732 if (!$this->isAuthenticated()) {
733 return;
734 }
735
736 $delete = WPStaging::make(Delete::class);
737
738 $isDatabaseConnected = $delete->setData();
739
740 $clone = $delete->getClone();
741
742 $dbname = $delete->getDbName();
743
744 require_once "{$this->path}views/clone/ajax/delete-confirmation.php";
745
746 wp_die();
747 }
748
749 /**
750 * Delete clone
751 */
752 public function ajaxDeleteClone()
753 {
754 if (!$this->isAuthenticated()) {
755 return;
756 }
757 $delete = WPStaging::make(Delete::class);
758
759 wp_send_json($delete->start());
760 }
761
762 /**
763 * Cancel clone
764 */
765 public function ajaxCancelClone()
766 {
767 if (!$this->isAuthenticated()) {
768 return;
769 }
770
771 $cancel = WPStaging::make(Cancel::class);
772 wp_send_json($cancel->start());
773 }
774
775 /**
776 * Cancel updating process / Do not delete clone!
777 */
778 public function ajaxCancelUpdate()
779 {
780 if (!$this->isAuthenticated()) {
781 return;
782 }
783
784 $cancelUpdate = WPStaging::make(CancelUpdate::class);
785 wp_send_json($cancelUpdate->start());
786 }
787
788 /**
789 * Ajax Hide Rating
790 *
791 * Runs when the user dismisses the notice to rate the plugin.
792 */
793 public function ajaxHideRating()
794 {
795 if (!$this->isAuthenticated()) {
796 return;
797 }
798
799 if (update_option("wpstg_rating", "no") !== false) {
800 wp_send_json(true);
801 }
802
803 wp_send_json(null);
804 }
805
806 /**
807 * Ajax Hide Rating and show it again after one week
808 *
809 * Runs when the user chooses to rate the plugin later.
810 */
811 public function ajaxHideLaterRating()
812 {
813 if (!$this->isAuthenticated()) {
814 return;
815 }
816
817 $date = date('Y-m-d', strtotime(date('Y-m-d') . ' + 7 days'));
818 if (update_option('wpstg_rating', $date) !== false) {
819 wp_send_json(true);
820 }
821
822 wp_send_json(false);
823 }
824
825 /**
826 * Ajax Hide Beta
827 */
828 public function ajaxHideBeta()
829 {
830 if (!$this->isAuthenticated()) {
831 return;
832 }
833
834 wp_send_json(update_option("wpstg_beta", "no"));
835 }
836
837 /**
838 * @return void
839 */
840 public function ajaxDismissNotice()
841 {
842 if (!$this->isAuthenticated()) {
843 return;
844 }
845
846 // Early bail if no notice option available
847 if (!isset($_POST['wpstg_notice'])) {
848 wp_send_json(null);
849 return;
850 }
851
852 /** @var DismissNotice */
853 $dismissNotice = WPStaging::make(DismissNotice::class);
854 $dismissNotice->dismiss($this->sanitize->sanitizeString($_POST['wpstg_notice']));
855 }
856
857 /**
858 * Clone logs
859 */
860 public function ajaxLogs()
861 {
862 if (!$this->isAuthenticated()) {
863 return;
864 }
865
866 $logs = WPStaging::make(Logs::class);
867 wp_send_json($logs->start());
868 }
869
870 /**
871 * Ajax Checks Free Disk Space
872 */
873 public function ajaxCheckFreeSpace()
874 {
875 if (!$this->isAuthenticated()) {
876 return false;
877 }
878
879 $excludedDirectories = isset($_POST["excludedDirectories"]) ? $this->sanitize->sanitizeString($_POST["excludedDirectories"]) : '';
880 $extraDirectories = isset($_POST["extraDirectories"]) ? $this->sanitize->sanitizeString($_POST["extraDirectories"]) : '';
881
882 $scan = WPStaging::make(Scan::class);
883 return $scan->hasFreeDiskSpace($excludedDirectories, $extraDirectories);
884 }
885
886 /**
887 * Allows the user to edit the clone's data
888 */
889 public function ajaxEditCloneData()
890 {
891 if (!$this->isAuthenticated()) {
892 return;
893 }
894
895 $existingClones = get_option(Sites::STAGING_SITES_OPTION, []);
896 if (isset($_POST["clone"]) && array_key_exists($_POST["clone"], $existingClones)) {
897 $clone = $existingClones[$this->sanitize->sanitizeString($_POST["clone"])];
898 require_once "{$this->path}Pro/views/edit-clone-data.php";
899 } else {
900 echo esc_html__("Unknown error. Please reload the page and try again", "wp-staging");
901 }
902
903 wp_die();
904 }
905
906 /**
907 * Allow the user to Save Clone Data
908 */
909 public function ajaxSaveCloneData()
910 {
911 if (!$this->isAuthenticated()) {
912 return;
913 }
914
915 $existingClones = get_option(Sites::STAGING_SITES_OPTION, []);
916 if (isset($_POST["clone"]) && array_key_exists($_POST["clone"], $existingClones)) {
917 if (empty($_POST['directoryName'])) {
918 echo esc_html__("Site name is required!", "wp-staging");
919 wp_die();
920 }
921
922 $cloneId = $this->sanitize->sanitizeString($_POST["clone"]);
923 $cloneName = isset($_POST["cloneName"]) ? $this->sanitize->sanitizeString($_POST["cloneName"]) : '';
924 $cloneDirectoryName = $this->sanitize->sanitizeString($_POST["directoryName"]);
925 $cloneDirectoryName = preg_replace("#\W+#", '-', strtolower($cloneDirectoryName));
926
927 $updateClones = [
928 "cloneName" => $this->sanitize->sanitizeString($cloneName),
929 "directoryName" => $this->sanitize->sanitizeString($cloneDirectoryName),
930 "path" => isset($_POST["path"]) ? $this->sanitize->sanitizeString($_POST["path"]) : '',
931 "url" => isset($_POST["url"]) ? $this->sanitize->sanitizeString($_POST["url"]) : '',
932 "prefix" => isset($_POST["prefix"]) ? $this->sanitize->sanitizeString($_POST["prefix"]) : '',
933 "databaseUser" => isset($_POST["externalDBUser"]) ? $this->sanitize->sanitizeString($_POST["externalDBUser"]) : '',
934 "databasePassword" => isset($_POST["externalDBPassword"]) ? $this->sanitize->sanitizePassword($_POST["externalDBPassword"]) : '',
935 "databaseDatabase" => isset($_POST["externalDBDatabase"]) ? $this->sanitize->sanitizeString($_POST["externalDBDatabase"]) : '',
936 "databaseServer" => isset($_POST["externalDBHost"]) ? $this->sanitize->sanitizeString($_POST["externalDBHost"]) : 'localhost',
937 "databasePrefix" => isset($_POST["externalDBPrefix"]) ? $this->sanitize->sanitizeString($_POST["externalDBPrefix"]) : 'wp_',
938 "databaseSsl" => isset($_POST["externalDBSsl"]) && 'true' === $this->sanitize->sanitizeString($_POST["externalDBSsl"]) ? true : false,
939 "datetime" => ! empty($existingClones["datetime"]) ? $existingClones["datetime"] : time(),
940 "ownerId" => ! empty($existingClones['ownerId']) ? $existingClones['ownerId'] : get_current_user_id()
941 ];
942
943 $existingClones[$cloneId] = array_merge($existingClones[$cloneId], $updateClones);
944
945 if (update_option(Sites::STAGING_SITES_OPTION, $existingClones)) {
946 // Update datetime if data was updated
947 $existingClones[$cloneId]["datetime"] = time();
948 update_option(Sites::STAGING_SITES_OPTION, $existingClones);
949 }
950
951 echo esc_html__("Success", "wp-staging");
952 } else {
953 echo esc_html__("Unknown error. Please reload the page and try again", "wp-staging");
954 }
955
956 wp_die();
957 }
958
959 /**
960 * Ajax Start Push Changes Process
961 * Start with the module Scan
962 * @action wp_ajax_wpstg_scans 10 0
963 * @see Administrator::defineHooks()
964 */
965 public function ajaxPushScan()
966 {
967 if (!$this->isAuthenticated()) {
968 return false;
969 }
970
971 if (!class_exists('WPStaging\Backend\Pro\Modules\Jobs\Scan')) {
972 return false;
973 }
974
975 // Scan
976 $scan = WPStaging::make(ScanProModule::class);
977
978 $scan->start();
979
980 // Get Options
981 $options = $scan->getOptions();
982
983 // Get Framework\Utils\Math
984 $utilsMath = WPStaging::make(Math::class);
985
986 require_once "{$this->path}Pro/views/scan.php";
987
988 wp_die();
989 }
990
991 /**
992 * Fetch all tables for push process
993 */
994 public function ajaxPushTables()
995 {
996 if (!$this->isAuthenticated()) {
997 return false;
998 }
999
1000 if (!class_exists('WPStaging\Backend\Pro\Modules\Jobs\Scan')) {
1001 return false;
1002 }
1003
1004 // Scan
1005 $scan = WPStaging::make(ScanProModule::class);
1006 $scan->loadStagingDBTables($onlyLoadStagingPrefixTables = false);
1007 $scan->start();
1008 $options = $scan->getOptions();
1009
1010 $includedTables = isset($_POST['includedTables']) ? $this->sanitize->sanitizeString($_POST['includedTables']) : '';
1011 $excludedTables = isset($_POST['excludedTables']) ? $this->sanitize->sanitizeString($_POST['excludedTables']) : '';
1012 $selectedTablesWithoutPrefix = isset($_POST['selectedTablesWithoutPrefix']) ? $this->sanitize->sanitizeString($_POST['selectedTablesWithoutPrefix']) : '';
1013 $selectedTables = new SelectedTables($includedTables, $excludedTables, $selectedTablesWithoutPrefix);
1014 $selectedTables->setDatabaseInfo($options->databaseServer, $options->databaseUser, $options->databasePassword, $options->databaseDatabase, empty($options->databasePrefix) ? $options->prefix : $options->databasePrefix, $options->databaseSsl);
1015 $tables = $selectedTables->getSelectedTables($options->networkClone);
1016
1017 $templateEngine = WPStaging::make(TemplateEngine::class);
1018
1019 echo json_encode([
1020 'success' => true,
1021 "content" => $templateEngine->render("/Backend/Pro/views/selections/tables.php", [
1022 'isNetworkClone' => $scan->isNetworkClone(),
1023 'options' => $options,
1024 'showAll' => true,
1025 'selected' => $tables
1026 ])
1027 ]);
1028
1029 exit();
1030 }
1031
1032 /**
1033 * Ajax Start Pushing. Needs WP Staging Pro
1034 */
1035 public function ajaxPushProcessing()
1036 {
1037 if (!$this->isAuthenticated()) {
1038 return false;
1039 }
1040
1041 if (!class_exists('WPStaging\Backend\Pro\Modules\Jobs\Processing')) {
1042 return false;
1043 }
1044
1045 // Start the process
1046 wp_send_json(WPStaging::make(Processing::class)->start());
1047
1048 return false;
1049 }
1050
1051 /**
1052 * License Page
1053 */
1054 public function getLicensePage()
1055 {
1056 // Get license data
1057 $license = get_option('wpstg_license_status');
1058
1059 require_once "{$this->path}Pro/views/licensing.php";
1060 }
1061
1062 /**
1063 * Send mail via ajax
1064 * @param array $args
1065 */
1066 public function ajaxSendReport($args = [])
1067 {
1068 if (!$this->isAuthenticated()) {
1069 return;
1070 }
1071
1072 // Set params
1073 if (empty($args)) {
1074 $args = stripslashes_deep($_POST);
1075 }
1076 // Set e-mail
1077 $emailRecipient = null;
1078 if (isset($args['wpstg_email'])) {
1079 $emailRecipient = trim($this->sanitize->sanitizeString($args['wpstg_email']));
1080 }
1081
1082 // Set hosting provider
1083 $providerName = null;
1084 if (isset($args['wpstg_provider'])) {
1085 $providerName = trim($this->sanitize->sanitizeString($args['wpstg_provider']));
1086 }
1087
1088 // Set message
1089 $messageBody = null;
1090 if (isset($args['wpstg_message'])) {
1091 $messageBody = trim($this->sanitize->sanitizeString($args['wpstg_message']));
1092 }
1093
1094 // Set syslog
1095 $sendLogFiles = false;
1096 if (isset($args['wpstg_syslog'])) {
1097 $sendLogFiles = $this->sanitize->sanitizeBool($args['wpstg_syslog']);
1098 }
1099
1100 // Set terms
1101 $termsAccepted = false;
1102 if (isset($args['wpstg_terms'])) {
1103 $termsAccepted = $this->sanitize->sanitizeBool($args['wpstg_terms']);
1104 }
1105
1106 // Set forceSend
1107 $forceSend = isset($_POST['wpstg_force_send']) && $this->sanitize->sanitizeBool($_POST['wpstg_force_send']);
1108
1109 $report = WPStaging::make(Report::class);
1110 $errors = $report->send($emailRecipient, $messageBody, $termsAccepted, $sendLogFiles, $providerName, $forceSend);
1111
1112 echo json_encode(['errors' => $errors]);
1113 exit;
1114 }
1115
1116 /**
1117 * Connect to external database for testing correct credentials
1118 */
1119 public function ajaxDatabaseConnect()
1120 {
1121 if (!$this->isAuthenticated()) {
1122 return;
1123 }
1124
1125 global $wpdb;
1126
1127 $args = $_POST;
1128 $user = !empty($args['databaseUser']) ? $this->sanitize->sanitizeString($args['databaseUser']) : '';
1129 $password = !empty($args['databasePassword']) ? $this->sanitize->sanitizePassword($args['databasePassword']) : '';
1130 $database = !empty($args['databaseDatabase']) ? $this->sanitize->sanitizeString($args['databaseDatabase']) : '';
1131 $server = !empty($args['databaseServer']) ? $this->sanitize->sanitizeString($args['databaseServer']) : 'localhost';
1132 $prefix = !empty($args['databasePrefix']) ? $this->sanitize->sanitizeString($args['databasePrefix']) : $wpdb->prefix;
1133 $useSsl = !empty($args['databaseSsl']) && 'true' === $this->sanitize->sanitizeString($args['databaseSsl']) ? true : false;
1134
1135 // make sure prefix doesn't contains any invalid character
1136 // same condition as in WordPress wpdb::set_prefix() method
1137 if (preg_match('|[^a-z0-9_]|i', $prefix)) {
1138 echo json_encode(['success' => 'false', 'errors' => __('Table prefix contains an invalid character.', 'wp-staging')]);
1139 exit;
1140 }
1141
1142 // ensure tables with the given prefix exist, default false
1143 $ensurePrefixTableExist = !empty($args['databaseEnsurePrefixTableExist']) ? $this->sanitize->sanitizeBool($args['databaseEnsurePrefixTableExist']) : false;
1144
1145 $dbInfo = new DbInfo($server, $user, stripslashes($password), $database, $useSsl);
1146 $wpdb = $dbInfo->connect();
1147
1148 // Can not connect to mysql database
1149 $error = $dbInfo->getError();
1150 if ($error !== null) {
1151 echo json_encode(['success' => 'false', 'errors' => $error]);
1152 exit;
1153 }
1154
1155 // Check if any table with provided prefix already exist
1156 $existingTables = $wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $wpdb->esc_like($prefix) . '%'));
1157 // used in new clone
1158 if ($existingTables !== null && !$ensurePrefixTableExist) {
1159 echo json_encode(['success' => 'false', 'errors' => __('Tables with prefix ' . $prefix . ' already exist in database. Select another prefix.', 'wp-staging')]);
1160 exit;
1161 }
1162
1163 // no need to check further for new clone
1164 if ($existingTables === null && !$ensurePrefixTableExist) {
1165 echo json_encode(['success' => 'true']);
1166 exit;
1167 }
1168
1169 // used in edit and update of clone
1170 if ($existingTables === null && $ensurePrefixTableExist) {
1171 echo json_encode(['success' => 'true', 'errors' => __('Tables with prefix "' . $prefix . '" not exist in database. Make sure it exists.', 'wp-staging')]);
1172 exit;
1173 }
1174
1175 // get production db
1176 $productionDb = WPStaging::make('wpdb');
1177
1178 $queryToFindHost = "SHOW VARIABLES WHERE Variable_name = 'hostname';";
1179 $queryToFindPort = "SHOW VARIABLES WHERE Variable_name = 'port';";
1180
1181 $stagingSiteAddress = gethostbyname($wpdb->get_var($wpdb->prepare($queryToFindHost), 1));
1182 $productionSiteAddress = gethostbyname($productionDb->get_var($productionDb->prepare($queryToFindHost), 1));
1183 if ($stagingSiteAddress === null || $productionSiteAddress === null) {
1184 echo json_encode(['success' => 'false', 'errors' => __('Unable to find database server hostname of the staging or the production site.', 'wp-staging')]);
1185 exit;
1186 }
1187
1188 $isSameAddress = $productionSiteAddress === $stagingSiteAddress;
1189 $isSamePort = $wpdb->get_var($wpdb->prepare($queryToFindPort), 1) === $productionDb->get_var($productionDb->prepare($queryToFindPort), 1);
1190
1191 $isSameServer = ($isSameAddress && $isSamePort) || $server === DB_HOST;
1192
1193 if ($database === DB_NAME && $prefix === $productionDb->prefix && $isSameServer) {
1194 echo json_encode(['success' => 'false', 'errors' => __('Cannot use production site database. Use another database.', 'wp-staging')]);
1195 exit;
1196 }
1197
1198 echo json_encode(['success' => 'true']);
1199 exit;
1200 }
1201
1202 /**
1203 * Action to perform when error modal confirm button is clicked
1204 *
1205 * @todo use constants instead of hardcoded strings for error types
1206 */
1207 public function ajaxModalError()
1208 {
1209 if (!$this->isAuthenticated()) {
1210 return;
1211 }
1212
1213 $type = isset($_POST['type']) ? $this->sanitize->sanitizeString($_POST['type']) : null;
1214 if ($type === 'processLock') {
1215 $process = WPStaging::make(ProcessLock::class);
1216 $process->restart();
1217
1218 exit();
1219 }
1220 }
1221
1222 /**
1223 * Render tables and files selection for RESET function
1224 */
1225 public function ajaxCloneExcludesSettings()
1226 {
1227 if (!$this->isAuthenticated()) {
1228 return;
1229 }
1230
1231 $processLock = WPStaging::make(ProcessLock::class);
1232 $response = $processLock->ajaxIsRunning();
1233 if ($response !== false) {
1234 echo json_encode($response);
1235
1236 exit();
1237 }
1238
1239 $templateEngine = WPStaging::make(TemplateEngine::class);
1240
1241 // Scan
1242 $scan = WPStaging::make(Scan::class);
1243 $scan->setGifLoaderPath($this->assets->getAssetsUrl('img/spinner.gif'));
1244 $scan->start();
1245
1246 echo json_encode([
1247 'success' => true,
1248 "html" => $templateEngine->render("/Backend/views/clone/ajax/exclude-settings.php", [
1249 'scan' => $scan,
1250 'options' => $scan->getOptions(),
1251 'excludeUtils' => WPStaging::make(ExcludeFilter::class),
1252 ])
1253 ]);
1254
1255 exit();
1256 }
1257
1258 /**
1259 * Compare database and table properties of separate db with local db
1260 */
1261 public function ajaxDatabaseVerification()
1262 {
1263 if (!$this->isAuthenticated()) {
1264 return;
1265 }
1266
1267 if (!$this->isPro()) {
1268 return;
1269 }
1270
1271 $user = !empty($_POST['databaseUser']) ? $this->sanitize->sanitizeString($_POST['databaseUser']) : '';
1272 $password = !empty($_POST['databasePassword']) ? $this->sanitize->sanitizePassword($_POST['databasePassword']) : '';
1273 $database = !empty($_POST['databaseDatabase']) ? $this->sanitize->sanitizeString($_POST['databaseDatabase']) : '';
1274 $server = !empty($_POST['databaseServer']) ? $this->sanitize->sanitizeString($_POST['databaseServer']) : 'localhost';
1275 $useSsl = !empty($_POST['databaseSsl']) && 'true' === $this->sanitize->sanitizeString($_POST['databaseSsl']) ? true : false;
1276
1277 $comparison = new CompareExternalDatabase($server, $user, stripslashes($password), $database, $useSsl);
1278 $results = $comparison->maybeGetComparison();
1279
1280 echo json_encode($results);
1281 exit();
1282 }
1283
1284 /**
1285 * Enable cloning on staging site if it is not enabled already
1286 */
1287 public function ajaxEnableStagingCloning()
1288 {
1289 if (!$this->isAuthenticated()) {
1290 return;
1291 }
1292
1293 if ($this->siteInfo->enableStagingSiteCloning()) {
1294 echo json_encode(['success' => 'true']);
1295 exit();
1296 }
1297
1298 echo json_encode(['success' => 'false', 'message' => __('Unable to enable cloning in the staging site', 'wp-staging')]);
1299 exit();
1300 }
1301
1302 /**
1303 * Restore Settings, can be used when settings are corrupted
1304 */
1305 public function ajaxRestoreSettings()
1306 {
1307 if (!$this->isAuthenticated()) {
1308 return;
1309 }
1310
1311 // Delete old settings
1312 delete_option('wpstg_settings');
1313 $settings = WPStaging::make(Settings::class);
1314 $settings->setDefault();
1315 }
1316
1317 /**
1318 * Remove uploads backup
1319 */
1320 public function removeOldUploadsBackup()
1321 {
1322 $backup = new BackupUploadsDir(null);
1323 $backup->removeUploadsBackup();
1324 }
1325
1326 /**
1327 * Check if Plugin is Pro version
1328 * @return bool
1329 */
1330 protected function isPro()
1331 {
1332 if (!defined("WPSTGPRO_VERSION")) {
1333 return false;
1334 }
1335
1336 return true;
1337 }
1338
1339 /**
1340 * Check if current page is plugins.php
1341 * @global array $pagenow
1342 * @return bool
1343 */
1344 private function isPluginsPage()
1345 {
1346 global $pagenow;
1347 return ($pagenow === 'plugins.php');
1348 }
1349 }
1350