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