WP Staging – DB & File Duplicator & Migration - Version 2.8.4

Version Description

  • Feat: Compatible up to WordPress 5.7.2
  • Enh: Preserve directories/tables selection and excludes rules for RESET and UPDATE process #809
  • Enh: If any wpstg process is running allow to stop that process within RESET modal #942
  • Fix: Fix multisite subsite capabilities on the staging site #852
  • Fix: Properly resets the properties between Cloning tasks #896
  • Fix: Avoid PHP warning when building version of missing asset file #929
  • Fix: Make RESET modal show error message within modal on failed response instead of browser logs #942
  • Fix: Replace wpstgGetCloneSettings() in mail-settings.php with CloneOption::get() #956
  • Fix: Little typo changed effect to affect #963
  • Fix: Made node_modules dir to be only excluded from WP Staging's Plugins #963
  • Fix: Fix UPDATE and RESET for old wpstg clones which are without appended underscore db prefix #958
Download this release

Release Info

Developer ReneHermi
Plugin Icon 128x128 WP Staging – DB & File Duplicator & Migration
Version 2.8.4
Comparing to
See all releases

Code changes from version 2.8.3 to 2.8.4

Files changed (102) hide show
  1. Backend/Administrator.php +115 -21
  2. Backend/Modules/Jobs/Cleaners/WpContentCleaner.php +4 -11
  3. Backend/Modules/Jobs/Cloning.php +40 -25
  4. Backend/Modules/Jobs/Data.php +0 -5
  5. Backend/Modules/Jobs/Database.php +42 -8
  6. Backend/Modules/Jobs/Delete.php +1 -1
  7. Backend/Modules/Jobs/Directories.php +96 -40
  8. Backend/Modules/Jobs/Files.php +10 -8
  9. Backend/Modules/Jobs/Job.php +5 -5
  10. Backend/Modules/Jobs/PreserveDataFirstStep.php +39 -5
  11. Backend/Modules/Jobs/PreserveDataSecondStep.php +70 -9
  12. Backend/Modules/Jobs/ProcessLock.php +26 -1
  13. Backend/Modules/Jobs/Scan.php +198 -123
  14. Backend/Modules/Jobs/SearchReplace.php +7 -15
  15. Backend/Modules/Jobs/Updating.php +92 -62
  16. Backend/Modules/Views/Forms/Settings.php +12 -0
  17. Backend/views/clone/ajax/exclude-settings.php +37 -0
  18. Backend/views/clone/ajax/scan.php +3 -63
  19. Backend/views/selections/database-tables.php +43 -0
  20. Backend/views/selections/files.php +104 -0
  21. Backend/views/settings/tabs/general.php +19 -0
  22. Backend/views/settings/tabs/mail-settings.php +1 -4
  23. Backend/views/templates/exclude-filters/dir-name-exclude-filter.php +29 -0
  24. Backend/views/templates/exclude-filters/file-ext-exclude-filter.php +18 -0
  25. Backend/views/templates/exclude-filters/file-name-exclude-filter.php +29 -0
  26. Backend/views/templates/exclude-filters/file-size-exclude-filter.php +34 -0
  27. Core/CoreServiceProvider.php +51 -0
  28. Core/DTO/Settings.php +31 -2
  29. Core/Forms/Elements/Color.php +29 -0
  30. Core/WPStaging.php +12 -9
  31. Core/thirdParty/thirdPartyCompatibility.php +0 -35
  32. Framework/Adapter/Database/InterfaceDatabaseClient.php +21 -0
  33. Framework/Adapter/Database/MysqlAdapter.php +18 -0
  34. Framework/Adapter/Database/MysqliAdapter.php +16 -0
  35. Framework/Adapter/Maintenance.php +1 -1
  36. Framework/Assets/Assets.php +81 -18
  37. Framework/BackgroundProcessing/Action.php +309 -0
  38. Framework/BackgroundProcessing/BackgroundProcessingServiceProvider.php +181 -0
  39. Framework/BackgroundProcessing/Demo.php +38 -0
  40. Framework/BackgroundProcessing/Exceptions/QueueException.php +21 -0
  41. Framework/BackgroundProcessing/FeatureDetection.php +183 -0
  42. Framework/BackgroundProcessing/Queue.php +1075 -0
  43. Framework/BackgroundProcessing/QueueProcessor.php +222 -0
  44. Framework/BackgroundProcessing/WithQueueAwareness.php +123 -0
  45. Framework/CloningProcess/Data/DBCloningService.php +10 -0
  46. Framework/CloningProcess/Data/MultisiteUpdateTablePrefix.php +0 -32
  47. Framework/CloningProcess/Data/UpdateStagingOptionsTable.php +10 -3
  48. Framework/CloningProcess/Data/UpdateTablePrefix.php +0 -10
  49. Framework/CloningProcess/ExcludedPlugins.php +20 -12
  50. Framework/Database/ExcludedTables.php +85 -0
  51. Framework/Database/TableService.php +2 -1
  52. Framework/Exceptions/IOException.php +8 -0
  53. Framework/Filesystem/Filesystem.php +52 -232
  54. Framework/Filesystem/FilterableDirectoryIterator.php +73 -4
  55. Framework/Filesystem/Filters/ExcludeFilter.php +143 -0
  56. Framework/Filesystem/Filters/FileSizeFilter.php +71 -0
  57. Framework/Filesystem/Filters/PathExcludeFilter.php +44 -7
  58. Framework/Filesystem/Filters/PathFilterHelper.php +262 -0
  59. Framework/Filesystem/Filters/RecursiveFileSizeFilter.php +75 -0
  60. Framework/Filesystem/Filters/RecursivePathExcludeFilter.php +56 -7
  61. Framework/Filesystem/Scanning/ScanConst.php +12 -0
  62. Framework/Filesystem/WpUploadsFolderSymlinker.php +53 -8
  63. Framework/Traits/DbRowsGeneratorTrait.php +2 -2
  64. Framework/Traits/ExcludeFilterTrait.php +0 -141
  65. Framework/Traits/FileScanToCacheTrait.php +8 -39
  66. Framework/Traits/PropertyConstructor.php +33 -0
  67. Framework/Utils/Cache/AbstractCache.php +1 -1
  68. Framework/Utils/Cache/BufferedCache.php +1 -1
  69. Framework/Utils/SlashMode.php +35 -0
  70. {vendor_wpstg/symfony/finder → Framework/Utils/ThirdParty}/Glob.php +4 -8
  71. Framework/Utils/WpDefaultDirectories.php +68 -100
  72. README.md +6 -0
  73. assets/css/{src → dist}/wpstg-admin-feedback.css +2 -1
  74. assets/css/dist/wpstg-admin-feedback.css.map +1 -0
  75. assets/css/dist/wpstg-admin-feedback.min.css +2 -0
  76. assets/css/dist/wpstg-admin-feedback.min.css.map +1 -0
  77. assets/css/{src → dist}/wpstg-admin.css +410 -55
  78. assets/css/dist/wpstg-admin.css.map +1 -0
  79. assets/css/dist/wpstg-admin.min.css +2 -0
  80. assets/css/dist/wpstg-admin.min.css.map +1 -0
  81. assets/css/src/frontend/wpstg-admin-bar.css +0 -3
  82. assets/css/src/wpstg-admin-bar.css +0 -3
  83. assets/img/spinner.gif +0 -0
  84. assets/img/wpstaging-icon.png +0 -0
  85. assets/js/dist/wpstg-admin-beta.js +18 -12
  86. assets/js/dist/wpstg-admin-beta.js.map +1 -0
  87. assets/js/dist/wpstg-admin-beta.min.js +2 -0
  88. assets/js/dist/wpstg-admin-beta.min.js.map +1 -0
  89. assets/js/dist/wpstg-admin-plugins.js +70 -65
  90. assets/js/dist/wpstg-admin-plugins.js.map +1 -0
  91. assets/js/dist/wpstg-admin-plugins.min.js +2 -0
  92. assets/js/dist/wpstg-admin-plugins.min.js.map +1 -0
  93. assets/js/dist/wpstg-admin-poll.js +19 -13
  94. assets/js/dist/wpstg-admin-poll.js.map +1 -0
  95. assets/js/dist/wpstg-admin-poll.min.js +2 -0
  96. assets/js/dist/wpstg-admin-poll.min.js.map +1 -0
  97. assets/js/dist/wpstg-admin-rating.js +118 -133
  98. assets/js/dist/wpstg-admin-rating.js.map +1 -0
  99. assets/js/dist/wpstg-admin-rating.min.js +2 -0
  100. assets/js/dist/wpstg-admin-rating.min.js.map +1 -0
  101. assets/js/dist/wpstg-admin.js +3505 -2429
  102. assets/js/dist/wpstg-admin.js.map +1 -0
Backend/Administrator.php CHANGED
@@ -2,13 +2,7 @@
2
 
3
  namespace WPStaging\Backend;
4
 
5
- // No Direct Access
6
- if (!defined("WPINC")) {
7
- die;
8
- }
9
-
10
  use WPStaging\Core\WPStaging;
11
- use WPStaging\Core\Utils\Cache;
12
  use WPStaging\Framework\Assets\Assets;
13
  use WPStaging\Framework\Database\DbInfo;
14
  use WPStaging\Framework\SiteInfo;
@@ -35,6 +29,8 @@ use WPStaging\Backend\Feedback;
35
  use WPStaging\Backend\Pro\Modules\Jobs\Processing;
36
  use WPStaging\Backend\Pluginmeta\Pluginmeta;
37
  use WPStaging\Core\DTO\Settings;
 
 
38
  use WPStaging\Pro\Database\CompareExternalDatabase;
39
 
40
  /**
@@ -162,6 +158,9 @@ class Administrator
162
  add_action("wp_ajax_wpstg_send_feedback", [$this, "sendFeedback"]);
163
  add_action("wp_ajax_wpstg_hide_disabled_items_notice", [$this, "ajaxHideDisabledItemsNotice"]);
164
  add_action("wp_ajax_wpstg_enable_staging_cloning", [$this, "ajaxEnableStagingCloning"]);
 
 
 
165
 
166
 
167
  // Ajax hooks pro Version
@@ -224,7 +223,7 @@ class Administrator
224
  $error = false;
225
  // is_array() is required otherwise new clone will fail.
226
  if ($this->siteInfo->isStaging() && is_array($data)) {
227
- $isStagingCloneable = $data['isStagingSiteCloneable'];
228
  unset($data['isStagingSiteCloneable']);
229
  $error = !$this->toggleStagingSiteCloning($isStagingCloneable === 'true');
230
  }
@@ -582,23 +581,51 @@ class Administrator
582
  }
583
 
584
  // Check first if there is already a process running
585
- $processLock = new ProcessLock();
586
- $processLock->isRunning();
 
 
 
 
 
587
 
588
  $db = WPStaging::getInstance()->get('wpdb');
589
 
590
  // Scan
591
  $scan = new Scan();
 
592
  $scan->start();
593
 
594
  // Get Options
595
  $options = $scan->getOptions();
596
-
597
  require_once "{$this->path}views/clone/ajax/scan.php";
598
 
599
  wp_die();
600
  }
601
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
602
  /**
603
  * Ajax Check Clone Name
604
  */
@@ -664,11 +691,6 @@ class Administrator
664
  return;
665
  }
666
 
667
- // TODO: inject this using DI
668
- // remove clone options cache before initializing reset clone process
669
- $cache = new Cache(-1, WPStaging::getContentDir());
670
- $cache->delete("clone_options");
671
-
672
  $cloning = new Updating();
673
  $cloning->setMainJob(Updating::RESET_UPDATE);
674
  if (!$cloning->save()) {
@@ -914,8 +936,11 @@ class Administrator
914
  return false;
915
  }
916
 
 
 
 
917
  $scan = new Scan();
918
- return $scan->hasFreeDiskSpace();
919
  }
920
 
921
  /**
@@ -1107,6 +1132,13 @@ class Administrator
1107
  $database = !empty($args['databaseDatabase']) ? $args['databaseDatabase'] : '';
1108
  $server = !empty($args['databaseServer']) ? $args['databaseServer'] : 'localhost';
1109
  $prefix = !empty($args['databasePrefix']) ? $args['databasePrefix'] : 'wp_';
 
 
 
 
 
 
 
1110
  // ensure tables with the given prefix exist, default false
1111
  $ensurePrefixTableExist = !empty($args['databaseEnsurePrefixTableExist']) ? filter_var($args['databaseEnsurePrefixTableExist'], FILTER_VALIDATE_BOOLEAN) : false;
1112
 
@@ -1128,6 +1160,12 @@ class Administrator
1128
  exit;
1129
  }
1130
 
 
 
 
 
 
 
1131
  // used in edit and update of clone
1132
  if ($existingTables === null && $ensurePrefixTableExist) {
1133
  echo json_encode(['success' => 'true', 'errors' => __('Tables with prefix "' . $prefix . '" not exist in database. Make sure it exists.', 'wp-staging')]);
@@ -1137,18 +1175,18 @@ class Administrator
1137
  // get production db
1138
  $productionDb = WPStaging::getInstance()->get('wpdb');
1139
 
1140
- $queryToFindAddress = "SELECT SUBSTRING_INDEX(host,':',1) AS 'ip' FROM information_schema.processlist WHERE ID=connection_id();";
1141
  $queryToFindPort = "SHOW VARIABLES WHERE Variable_name = 'port';";
1142
 
1143
- $stagingSiteAddress = $wpdb->get_var($wpdb->prepare($queryToFindAddress));
1144
- $productionSiteAddress = $productionDb->get_var($productionDb->prepare($queryToFindAddress));
1145
  if ($stagingSiteAddress === null || $productionSiteAddress === null) {
1146
  echo json_encode(['success' => 'false', 'errors' => __('Unable to find database server hostname of the staging or the production site.', 'wp-staging')]);
1147
  exit;
1148
  }
1149
 
1150
  $isSameAddress = $productionSiteAddress === $stagingSiteAddress;
1151
- $isSamePort = $wpdb->get_var($wpdb->prepare($queryToFindPort)) === $productionDb->get_var($productionDb->prepare($queryToFindPort));
1152
 
1153
  $isSameServer = ($isSameAddress && $isSamePort) || $server === DB_HOST;
1154
 
@@ -1162,7 +1200,63 @@ class Administrator
1162
  }
1163
 
1164
  /**
1165
- * Connect to external database for testing correct credentials
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1166
  */
1167
  public function ajaxDatabaseVerification()
1168
  {
2
 
3
  namespace WPStaging\Backend;
4
 
 
 
 
 
 
5
  use WPStaging\Core\WPStaging;
 
6
  use WPStaging\Framework\Assets\Assets;
7
  use WPStaging\Framework\Database\DbInfo;
8
  use WPStaging\Framework\SiteInfo;
29
  use WPStaging\Backend\Pro\Modules\Jobs\Processing;
30
  use WPStaging\Backend\Pluginmeta\Pluginmeta;
31
  use WPStaging\Core\DTO\Settings;
32
+ use WPStaging\Framework\Filesystem\Filters\ExcludeFilter;
33
+ use WPStaging\Framework\TemplateEngine\TemplateEngine;
34
  use WPStaging\Pro\Database\CompareExternalDatabase;
35
 
36
  /**
158
  add_action("wp_ajax_wpstg_send_feedback", [$this, "sendFeedback"]);
159
  add_action("wp_ajax_wpstg_hide_disabled_items_notice", [$this, "ajaxHideDisabledItemsNotice"]);
160
  add_action("wp_ajax_wpstg_enable_staging_cloning", [$this, "ajaxEnableStagingCloning"]);
161
+ add_action("wp_ajax_wpstg_clone_excludes_settings", [$this, "ajaxCloneExcludesSettings"]);
162
+ add_action("wp_ajax_wpstg_fetch_dir_childrens", [$this, "ajaxFetchDirChildrens"]);
163
+ add_action("wp_ajax_wpstg_modal_error", [$this, "ajaxModalError"]);
164
 
165
 
166
  // Ajax hooks pro Version
223
  $error = false;
224
  // is_array() is required otherwise new clone will fail.
225
  if ($this->siteInfo->isStaging() && is_array($data)) {
226
+ $isStagingCloneable = isset($data['isStagingSiteCloneable']) ? $data['isStagingSiteCloneable'] : 'false';
227
  unset($data['isStagingSiteCloneable']);
228
  $error = !$this->toggleStagingSiteCloning($isStagingCloneable === 'true');
229
  }
581
  }
582
 
583
  // Check first if there is already a process running
584
+ $response = (new ProcessLock())->ajaxIsRunning();
585
+ if ($response !== false)
586
+ {
587
+ echo $response;
588
+
589
+ exit();
590
+ }
591
 
592
  $db = WPStaging::getInstance()->get('wpdb');
593
 
594
  // Scan
595
  $scan = new Scan();
596
+ $scan->setGifLoaderPath($this->assets->getAssetsUrl('img/spinner.gif'));
597
  $scan->start();
598
 
599
  // Get Options
600
  $options = $scan->getOptions();
601
+ $excludeUtils = new ExcludeFilter();
602
  require_once "{$this->path}views/clone/ajax/scan.php";
603
 
604
  wp_die();
605
  }
606
 
607
+ /**
608
+ * Fetch children of the given directory
609
+ */
610
+ public function ajaxFetchDirChildrens()
611
+ {
612
+ if (!$this->isAuthenticated()) {
613
+ wp_send_json(['success' => false]);
614
+ return;
615
+ }
616
+
617
+ $isChecked = isset($_POST['isChecked']) ? $_POST['isChecked'] === 'true' : false;
618
+ $forceDefault = isset($_POST['forceDefault']) ? $_POST['forceDefault'] === 'true' : false;
619
+ $path = isset($_POST['dirPath']) ? $_POST['dirPath'] : "";
620
+ $path = ABSPATH . $path;
621
+ $scan = new Scan($path);
622
+ $scan->setGifLoaderPath($this->assets->getAssetsUrl('img/spinner.gif'));
623
+ wp_send_json([
624
+ "success" => true,
625
+ "directoryListing" => json_encode($scan->directoryListing($isChecked, $forceDefault)),
626
+ ]);
627
+ }
628
+
629
  /**
630
  * Ajax Check Clone Name
631
  */
691
  return;
692
  }
693
 
 
 
 
 
 
694
  $cloning = new Updating();
695
  $cloning->setMainJob(Updating::RESET_UPDATE);
696
  if (!$cloning->save()) {
936
  return false;
937
  }
938
 
939
+ $excludedDirectories = isset($_POST["excludedDirectories"]) ? $_POST["excludedDirectories"] : '';
940
+ $extraDirectories = isset($_POST["extraDirectories"]) ? $_POST["extraDirectories"] : '';
941
+
942
  $scan = new Scan();
943
+ return $scan->hasFreeDiskSpace($excludedDirectories, $extraDirectories);
944
  }
945
 
946
  /**
1132
  $database = !empty($args['databaseDatabase']) ? $args['databaseDatabase'] : '';
1133
  $server = !empty($args['databaseServer']) ? $args['databaseServer'] : 'localhost';
1134
  $prefix = !empty($args['databasePrefix']) ? $args['databasePrefix'] : 'wp_';
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']) ? filter_var($args['databaseEnsurePrefixTableExist'], FILTER_VALIDATE_BOOLEAN) : false;
1144
 
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')]);
1175
  // get production db
1176
  $productionDb = WPStaging::getInstance()->get('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
 
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']) ? $_POST['type'] : null;
1214
+ if ($type === 'processLock') {
1215
+ $process = new ProcessLock();
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
+ $response = (new ProcessLock())->ajaxIsRunning();
1232
+ if ($response !== false)
1233
+ {
1234
+ echo $response;
1235
+
1236
+ exit();
1237
+ }
1238
+
1239
+ $templateEngine = new TemplateEngine();
1240
+
1241
+ // Scan
1242
+ $scan = new Scan();
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' => new ExcludeFilter(),
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
  {
Backend/Modules/Jobs/Cleaners/WpContentCleaner.php CHANGED
@@ -4,6 +4,7 @@ namespace WPStaging\Backend\Modules\Jobs\Cleaners;
4
 
5
  use WPStaging\Backend\Modules\Jobs\Files;
6
  use WPStaging\Framework\Utils\WpDefaultDirectories;
 
7
  use WPStaging\Framework\Filesystem\Filesystem;
8
  use WPStaging\Core\Utils\Logger;
9
 
@@ -90,21 +91,13 @@ class WpContentCleaner
90
  }
91
 
92
  $excludePaths = [
93
- trailingslashit($directory . $wpDirectories->getRelativePluginPath()) . "wp-staging",
94
- trailingslashit($directory . $wpDirectories->getRelativePluginPath()) . "wp-staging_1",
95
- trailingslashit($directory . $wpDirectories->getRelativePluginPath()) . "wp-staging_2",
96
- trailingslashit($directory . $wpDirectories->getRelativePluginPath()) . "wp-staging-pro",
97
- trailingslashit($directory . $wpDirectories->getRelativePluginPath()) . "wp-staging-pro_1",
98
- trailingslashit($directory . $wpDirectories->getRelativePluginPath()) . "wp-staging-pro_2",
99
- trailingslashit($directory . $wpDirectories->getRelativePluginPath()) . "wp-staging-dev",
100
- trailingslashit($directory . $wpDirectories->getRelativePluginPath()) . 'wp-staging-hooks',
101
- trailingslashit($directory . $wpDirectories->getRelativePluginPath()) . 'wp-staging-hooks_1',
102
- trailingslashit($directory . $wpDirectories->getRelativePluginPath()) . 'wp-staging-hooks_2',
103
- trailingslashit($directory . $wpDirectories->getRelativeUploadPath()) . 'wp-staging', // exclude wp-staging from uploads dir too.
104
  ];
105
  $fs = (new Filesystem())
106
  ->setShouldStop([$this->job, 'isOverThreshold'])
107
  ->setExcludePaths($excludePaths)
 
108
  ->setRecursive();
109
  try {
110
  if (!$fs->deletePaths($paths)) {
4
 
5
  use WPStaging\Backend\Modules\Jobs\Files;
6
  use WPStaging\Framework\Utils\WpDefaultDirectories;
7
+ use WPStaging\Framework\Utils\SlashMode;
8
  use WPStaging\Framework\Filesystem\Filesystem;
9
  use WPStaging\Core\Utils\Logger;
10
 
91
  }
92
 
93
  $excludePaths = [
94
+ $wpDirectories->getRelativePluginPath(SlashMode::BOTH_SLASHES) . "wp-staging*",
95
+ $wpDirectories->getRelativeUploadPath(SlashMode::BOTH_SLASHES) . 'wp-staging', // exclude wp-staging from uploads dir too.
 
 
 
 
 
 
 
 
 
96
  ];
97
  $fs = (new Filesystem())
98
  ->setShouldStop([$this->job, 'isOverThreshold'])
99
  ->setExcludePaths($excludePaths)
100
+ ->setWpRootPath($directory)
101
  ->setRecursive();
102
  try {
103
  if (!$fs->deletePaths($paths)) {
Backend/Modules/Jobs/Cloning.php CHANGED
@@ -5,7 +5,9 @@ namespace WPStaging\Backend\Modules\Jobs;
5
  use WPStaging\Backend\Modules\Jobs\Exceptions\JobNotFoundException;
6
  use WPStaging\Core\Utils\Helper;
7
  use WPStaging\Core\WPStaging;
 
8
  use WPStaging\Framework\Security\AccessToken;
 
9
  use WPStaging\Framework\Utils\WpDefaultDirectories;
10
 
11
  /**
@@ -20,12 +22,18 @@ class Cloning extends Job
20
  */
21
  private $db;
22
 
 
 
 
 
 
23
  /**
24
  * Initialize is called in \Job
25
  */
26
  public function initialize()
27
  {
28
  $this->db = WPStaging::getInstance()->get("wpdb");
 
29
  }
30
 
31
 
@@ -64,10 +72,11 @@ class Cloning extends Job
64
  '.wp-staging', // Determines if a site is a staging site
65
  '.wp-staging-cloneable', // File which make staging site to be cloneable
66
  ];
 
67
  $this->options->excludedFilesFullPath = [
68
- 'wp-content' . DIRECTORY_SEPARATOR . 'db.php',
69
- 'wp-content' . DIRECTORY_SEPARATOR . 'object-cache.php',
70
- 'wp-content' . DIRECTORY_SEPARATOR . 'advanced-cache.php'
71
  ];
72
  $this->options->currentStep = 0;
73
 
@@ -95,41 +104,41 @@ class Cloning extends Job
95
  $this->options->tables = [];
96
  }
97
 
 
 
 
 
 
 
 
 
 
 
 
 
98
  $this->options->uploadsSymlinked = isset($_POST['uploadsSymlinked']) && $_POST['uploadsSymlinked'] === 'true';
99
 
100
- // Excluded Directories TOTAL
101
- // Do not copy these folders and plugins
 
 
102
  $excludedDirectories = [
103
- WPStaging::getWPpath() . 'wp-content' . DIRECTORY_SEPARATOR . 'cache',
104
- WPStaging::getWPpath() . 'wp-content' . DIRECTORY_SEPARATOR . 'plugins' . DIRECTORY_SEPARATOR . 'wps-hide-login',
105
- WPStaging::getWPpath() . 'wp-content' . DIRECTORY_SEPARATOR . 'plugins' . DIRECTORY_SEPARATOR . 'wp-super-cache',
106
- WPStaging::getWPpath() . 'wp-content' . DIRECTORY_SEPARATOR . 'plugins' . DIRECTORY_SEPARATOR . 'peters-login-redirect',
107
- WPStaging::getWPpath() . 'wp-content' . DIRECTORY_SEPARATOR . 'plugins' . DIRECTORY_SEPARATOR . 'wp-spamshield',
108
  ];
109
 
110
  // Add upload folder to list of excluded directories for push if symlink option is enabled
111
  if ($this->options->uploadsSymlinked) {
112
- $wpUploadsFolder = (new WpDefaultDirectories())->getUploadsPath();
113
- $excludedDirectories[] = rtrim($wpUploadsFolder, '/\\');
114
  }
115
 
116
- $this->options->excludedDirectories = $excludedDirectories;
117
-
118
- $this->options->areDirectoriesIncluded = isset($_POST['areDirectoriesIncluded']) && $_POST['areDirectoriesIncluded'] === 'true';
119
 
120
- $directories = '';
121
- // Included Directories
122
- if ($this->options->areDirectoriesIncluded) {
123
- $directories = isset($_POST["includedDirectories"]) ? $_POST["includedDirectories"] : '';
124
- } else { // Get Included Directories from Excluded Directories
125
- $directories = isset($_POST["excludedDirectories"]) ? $_POST["excludedDirectories"] : '';
126
- }
127
-
128
- $this->options->includedDirectories = (new WpDefaultDirectories())->getSelectedDirectories($directories, $this->options->areDirectoriesIncluded);
129
 
130
  // Extra Directories
131
  if (isset($_POST["extraDirectories"])) {
132
- $this->options->extraDirectories = wpstg_urldecode(explode(Scan::DIRECTORIES_SEPARATOR, $_POST["extraDirectories"]));
133
  }
134
 
135
  $this->options->databaseServer = 'localhost';
@@ -222,6 +231,11 @@ class Cloning extends Job
222
  "emailsAllowed" => (bool)$this->options->emailsAllowed,
223
  "uploadsSymlinked" => (bool)$this->options->uploadsSymlinked,
224
  "ownerId" => $this->options->ownerId,
 
 
 
 
 
225
  ];
226
 
227
  if (update_option("wpstg_existing_clones_beta", $this->options->existingClones) === false) {
@@ -366,6 +380,7 @@ class Cloning extends Job
366
  return $response;
367
  }
368
 
 
369
  $this->options->currentJob = $nextJob;
370
  $this->options->currentStep = 0;
371
  $this->options->totalSteps = 0;
5
  use WPStaging\Backend\Modules\Jobs\Exceptions\JobNotFoundException;
6
  use WPStaging\Core\Utils\Helper;
7
  use WPStaging\Core\WPStaging;
8
+ use WPStaging\Framework\Filesystem\Scanning\ScanConst;
9
  use WPStaging\Framework\Security\AccessToken;
10
+ use WPStaging\Framework\Utils\SlashMode;
11
  use WPStaging\Framework\Utils\WpDefaultDirectories;
12
 
13
  /**
22
  */
23
  private $db;
24
 
25
+ /**
26
+ * @var WpDefaultDirectories
27
+ */
28
+ private $dirUtils;
29
+
30
  /**
31
  * Initialize is called in \Job
32
  */
33
  public function initialize()
34
  {
35
  $this->db = WPStaging::getInstance()->get("wpdb");
36
+ $this->dirUtils = new WpDefaultDirectories();
37
  }
38
 
39
 
72
  '.wp-staging', // Determines if a site is a staging site
73
  '.wp-staging-cloneable', // File which make staging site to be cloneable
74
  ];
75
+
76
  $this->options->excludedFilesFullPath = [
77
+ $this->dirUtils->getRelativeWpContentPath(SlashMode::TRAILING_SLASH) . 'db.php',
78
+ $this->dirUtils->getRelativeWpContentPath(SlashMode::TRAILING_SLASH) . 'object-cache.php',
79
+ $this->dirUtils->getRelativeWpContentPath(SlashMode::TRAILING_SLASH) . 'advanced-cache.php'
80
  ];
81
  $this->options->currentStep = 0;
82
 
104
  $this->options->tables = [];
105
  }
106
 
107
+ // Exclude File Size Rules
108
+ $this->options->excludeSizeRules = [];
109
+ if (isset($_POST["excludeSizeRules"]) && !empty($_POST["excludeSizeRules"])) {
110
+ $this->options->excludeSizeRules = explode(',', wpstg_urldecode($_POST["excludeSizeRules"]));
111
+ }
112
+
113
+ // Exclude Glob Rules
114
+ $this->options->excludeGlobRules = [];
115
+ if (isset($_POST["excludeGlobRules"]) && !empty($_POST["excludeGlobRules"])) {
116
+ $this->options->excludeGlobRules = explode(',', wpstg_urldecode($_POST["excludeGlobRules"]));
117
+ }
118
+
119
  $this->options->uploadsSymlinked = isset($_POST['uploadsSymlinked']) && $_POST['uploadsSymlinked'] === 'true';
120
 
121
+ /**
122
+ * @see /WPStaging/Framework/CloningProcess/ExcludedPlugins.php to exclude plugins
123
+ * Only add other directories here
124
+ */
125
  $excludedDirectories = [
126
+ $this->dirUtils->getRelativeWpContentPath(SlashMode::BOTH_SLASHES) . 'cache',
 
 
 
 
127
  ];
128
 
129
  // Add upload folder to list of excluded directories for push if symlink option is enabled
130
  if ($this->options->uploadsSymlinked) {
131
+ $excludedDirectories[] = $this->dirUtils->getRelativeUploadPath(SlashMode::LEADING_SLASH);
 
132
  }
133
 
134
+ $excludedDirectoriesRequest = isset($_POST["excludedDirectories"]) ? $_POST["excludedDirectories"] : '';
135
+ $excludedDirectoriesRequest = $this->dirUtils->getExcludedDirectories($excludedDirectoriesRequest);
 
136
 
137
+ $this->options->excludedDirectories = array_merge($excludedDirectories, $excludedDirectoriesRequest);
 
 
 
 
 
 
 
 
138
 
139
  // Extra Directories
140
  if (isset($_POST["extraDirectories"])) {
141
+ $this->options->extraDirectories = explode(ScanConst::DIRECTORIES_SEPARATOR, wpstg_urldecode($_POST["extraDirectories"]));
142
  }
143
 
144
  $this->options->databaseServer = 'localhost';
231
  "emailsAllowed" => (bool)$this->options->emailsAllowed,
232
  "uploadsSymlinked" => (bool)$this->options->uploadsSymlinked,
233
  "ownerId" => $this->options->ownerId,
234
+ "includedTables" => $this->options->tables,
235
+ "excludeSizeRules" => $this->options->excludeSizeRules,
236
+ "excludeGlobRules" => $this->options->excludeGlobRules,
237
+ "excludedDirectories" => $this->options->excludedDirectories,
238
+ "extraDirectories" => $this->options->extraDirectories,
239
  ];
240
 
241
  if (update_option("wpstg_existing_clones_beta", $this->options->existingClones) === false) {
380
  return $response;
381
  }
382
 
383
+ $this->options->job = new \stdClass();
384
  $this->options->currentJob = $nextJob;
385
  $this->options->currentStep = 0;
386
  $this->options->totalSteps = 0;
Backend/Modules/Jobs/Data.php CHANGED
@@ -6,7 +6,6 @@ use WPStaging\Framework\CloningProcess\Data\DataCloningDto;
6
  use WPStaging\Framework\CloningProcess\Data\CopyWpConfig;
7
  use WPStaging\Framework\CloningProcess\Data\MultisiteAddNetworkAdministrators;
8
  use WPStaging\Framework\CloningProcess\Data\MultisiteUpdateActivePlugins;
9
- use WPStaging\Framework\CloningProcess\Data\MultisiteUpdateTablePrefix;
10
  use WPStaging\Framework\CloningProcess\Data\ResetIndexPhp;
11
  use WPStaging\Framework\CloningProcess\Data\UpdateSiteUrlAndHome;
12
  use WPStaging\Framework\CloningProcess\Data\UpdateTablePrefix;
@@ -225,10 +224,6 @@ class Data extends CloningProcess
225
  */
226
  protected function step3()
227
  {
228
- if ($this->isMultisiteAndPro()) {
229
- return (new MultisiteUpdateTablePrefix($this->getCloningDto(3)))->execute();
230
- }
231
-
232
  return (new UpdateTablePrefix($this->getCloningDto(3)))->execute();
233
  }
234
 
6
  use WPStaging\Framework\CloningProcess\Data\CopyWpConfig;
7
  use WPStaging\Framework\CloningProcess\Data\MultisiteAddNetworkAdministrators;
8
  use WPStaging\Framework\CloningProcess\Data\MultisiteUpdateActivePlugins;
 
9
  use WPStaging\Framework\CloningProcess\Data\ResetIndexPhp;
10
  use WPStaging\Framework\CloningProcess\Data\UpdateSiteUrlAndHome;
11
  use WPStaging\Framework\CloningProcess\Data\UpdateTablePrefix;
224
  */
225
  protected function step3()
226
  {
 
 
 
 
227
  return (new UpdateTablePrefix($this->getCloningDto(3)))->execute();
228
  }
229
 
Backend/Modules/Jobs/Database.php CHANGED
@@ -33,6 +33,7 @@ class Database extends CloningProcess
33
  {
34
  $this->initializeDbObjects();
35
  $this->abortIfDirectoryNotEmpty();
 
36
  if (!$this->isExternalDatabase()) {
37
  $this->abortIfStagingPrefixEqualsProdPrefix();
38
  } else {
@@ -170,6 +171,7 @@ class Database extends CloningProcess
170
  private function isTableExist($name)
171
  {
172
  $old = $this->stagingDb->get_var($this->stagingDb->prepare("SHOW TABLES LIKE %s", $name));
 
173
  return (
174
  $old === $name &&
175
  (
@@ -216,7 +218,9 @@ class Database extends CloningProcess
216
  if (defined('WPSTGPRO_VERSION')) {
217
  return false;
218
  }
 
219
  $this->returnException(__("This staging site is located in another database and needs to be edited with <a href='https://wp-staging.com' target='_blank'>WP STAGING Pro</a>", "wp-staging"));
 
220
  return true;
221
  }
222
 
@@ -266,8 +270,8 @@ class Database extends CloningProcess
266
  }
267
  }
268
 
269
- if ($this->shouldAbortIfTableExist($newTableName)) {
270
- $this->returnException(sprintf(__("Can not proceed. Tables beginning with the prefix '%s' already exist in the database. Choose another table prefix and try again.", "wp-staging"), $this->getStagingPrefix()));
271
  return true;
272
  }
273
 
@@ -287,16 +291,12 @@ class Database extends CloningProcess
287
  }
288
 
289
  /**
290
- * Is table excluded from search replace processing?
291
  * @param string $table
292
  * @return boolean
293
  */
294
  private function isExcludedTable($table)
295
  {
296
- $excludedCustomTables = apply_filters('wpstg_clone_database_tables_exclude', []);
297
- $excludedCoreTables = ['blogs', 'blog_versions'];
298
-
299
- $excludedtables = array_merge($excludedCustomTables, $excludedCoreTables);
300
 
301
  if (
302
  in_array(
@@ -305,12 +305,13 @@ class Database extends CloningProcess
305
  function ($tableName) {
306
  return $this->options->prefix . $tableName;
307
  },
308
- $excludedtables
309
  )
310
  )
311
  ) {
312
  return true;
313
  }
 
314
  return false;
315
  }
316
 
@@ -325,6 +326,7 @@ class Database extends CloningProcess
325
  if ($this->isExcludedTable($new)) {
326
  return false;
327
  }
 
328
  if ($this->options->job->start != 0) {
329
  return true;
330
  }
@@ -332,6 +334,7 @@ class Database extends CloningProcess
332
  if ($this->databaseCloningService->tableIsMissing($old)) {
333
  return true;
334
  }
 
335
  try {
336
  $this->options->job->total = 0;
337
  $this->options->job->total = $this->databaseCloningService->createTable($new, $old);
@@ -339,10 +342,14 @@ class Database extends CloningProcess
339
  $this->returnException($e->getMessage());
340
  return true;
341
  }
 
342
  if ($this->options->job->total == 0) {
343
  $this->finishStep();
344
  return false;
345
  }
 
 
 
346
  return true;
347
  }
348
 
@@ -358,6 +365,7 @@ class Database extends CloningProcess
358
  $this->options->tables[] = $this->productionDb->prefix . 'users';
359
  $this->saveOptions();
360
  }
 
361
  if (!in_array($this->productionDb->prefix . 'usermeta', $this->options->tables)) {
362
  $this->options->tables[] = $this->productionDb->prefix . 'usermeta';
363
  $this->saveOptions();
@@ -404,6 +412,32 @@ class Database extends CloningProcess
404
  $this->returnException(" Can not continue for security purposes. Directory {$path} is not empty! Use FTP or a file manager plugin and make sure it does not contain any files. ");
405
  return true;
406
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
407
  return false;
408
  }
 
 
 
 
 
 
 
 
 
409
  }
33
  {
34
  $this->initializeDbObjects();
35
  $this->abortIfDirectoryNotEmpty();
36
+ $this->abortIfPrefixContainsInvalidCharacter();
37
  if (!$this->isExternalDatabase()) {
38
  $this->abortIfStagingPrefixEqualsProdPrefix();
39
  } else {
171
  private function isTableExist($name)
172
  {
173
  $old = $this->stagingDb->get_var($this->stagingDb->prepare("SHOW TABLES LIKE %s", $name));
174
+
175
  return (
176
  $old === $name &&
177
  (
218
  if (defined('WPSTGPRO_VERSION')) {
219
  return false;
220
  }
221
+
222
  $this->returnException(__("This staging site is located in another database and needs to be edited with <a href='https://wp-staging.com' target='_blank'>WP STAGING Pro</a>", "wp-staging"));
223
+
224
  return true;
225
  }
226
 
270
  }
271
  }
272
 
273
+ if (!$this->isCopyProcessStarted() && $this->shouldAbortIfTableExist($newTableName)) {
274
+ $this->returnException(sprintf(__("Can not proceed. Tables beginning with the prefix '%s' already exist in the database i.e. %s. Choose another table prefix and try again.", "wp-staging"), $this->getStagingPrefix(), $newTableName));
275
  return true;
276
  }
277
 
291
  }
292
 
293
  /**
294
+ * Is table excluded from database copying processing?
295
  * @param string $table
296
  * @return boolean
297
  */
298
  private function isExcludedTable($table)
299
  {
 
 
 
 
300
 
301
  if (
302
  in_array(
305
  function ($tableName) {
306
  return $this->options->prefix . $tableName;
307
  },
308
+ $this->excludedTableService->getExcludedTables()
309
  )
310
  )
311
  ) {
312
  return true;
313
  }
314
+
315
  return false;
316
  }
317
 
326
  if ($this->isExcludedTable($new)) {
327
  return false;
328
  }
329
+
330
  if ($this->options->job->start != 0) {
331
  return true;
332
  }
334
  if ($this->databaseCloningService->tableIsMissing($old)) {
335
  return true;
336
  }
337
+
338
  try {
339
  $this->options->job->total = 0;
340
  $this->options->job->total = $this->databaseCloningService->createTable($new, $old);
342
  $this->returnException($e->getMessage());
343
  return true;
344
  }
345
+
346
  if ($this->options->job->total == 0) {
347
  $this->finishStep();
348
  return false;
349
  }
350
+
351
+ $this->options->job->copyProcessStarted = true;
352
+ $this->saveOptions();
353
  return true;
354
  }
355
 
365
  $this->options->tables[] = $this->productionDb->prefix . 'users';
366
  $this->saveOptions();
367
  }
368
+
369
  if (!in_array($this->productionDb->prefix . 'usermeta', $this->options->tables)) {
370
  $this->options->tables[] = $this->productionDb->prefix . 'usermeta';
371
  $this->saveOptions();
412
  $this->returnException(" Can not continue for security purposes. Directory {$path} is not empty! Use FTP or a file manager plugin and make sure it does not contain any files. ");
413
  return true;
414
  }
415
+
416
+ return false;
417
+ }
418
+
419
+ /**
420
+ * Stop cloning if database prefix contains hypen
421
+ * @return boolean
422
+ */
423
+ private function abortIfPrefixContainsInvalidCharacter()
424
+ {
425
+ // make sure prefix doesn't contains any invalid character
426
+ // same condition as in WordPress wpdb::set_prefix() method
427
+ if (preg_match('|[^a-z0-9_]|i', $this->options->databasePrefix)) {
428
+ $this->returnException(__("Table prefix contains invalid character(s). Use different prefix with valid characters.", 'wp-staging'));
429
+ return true;
430
+ }
431
+
432
  return false;
433
  }
434
+
435
+ /**
436
+ * Check if the copy process started or not.
437
+ * @return boolean
438
+ */
439
+ private function isCopyProcessStarted()
440
+ {
441
+ return isset($this->options->job) && isset($this->options->job->copyProcessStarted) && $this->options->job->copyProcessStarted === true;
442
+ }
443
  }
Backend/Modules/Jobs/Delete.php CHANGED
@@ -404,7 +404,7 @@ class Delete extends Job
404
  ->setShouldStop([$this, 'isOverThreshold'])
405
  ->setRecursive();
406
  try {
407
- if (!$fs->deleteNew($this->deleteDir)) {
408
  return;
409
  }
410
  } catch (\RuntimeException $ex) {
404
  ->setShouldStop([$this, 'isOverThreshold'])
405
  ->setRecursive();
406
  try {
407
+ if (!$fs->delete($this->deleteDir)) {
408
  return;
409
  }
410
  } catch (\RuntimeException $ex) {
Backend/Modules/Jobs/Directories.php CHANGED
@@ -5,7 +5,9 @@ namespace WPStaging\Backend\Modules\Jobs;
5
  use Exception;
6
  use WPStaging\Core\WPStaging;
7
  use WPStaging\Framework\CloningProcess\ExcludedPlugins;
 
8
  use WPStaging\Framework\Traits\FileScanToCacheTrait;
 
9
  use WPStaging\Framework\Utils\Strings;
10
  use WPStaging\Framework\Utils\WpDefaultDirectories;
11
 
@@ -34,12 +36,24 @@ class Directories extends JobExecutable
34
  */
35
  private $filename;
36
 
 
 
 
 
 
 
 
 
 
 
37
  /**
38
  * Initialize
39
  */
40
  public function initialize()
41
  {
42
  $this->filename = $this->cache->getCacheDir() . "files_to_copy." . $this->cache->getCacheExtension();
 
 
43
  }
44
 
45
  /**
@@ -112,27 +126,25 @@ class Directories extends JobExecutable
112
  $relativeDirectory = str_replace(ABSPATH, '', $directory);
113
  $this->log("Scanning " . $relativeDirectory . " for its sub-directories and files");
114
 
115
- $paths = $this->filteredSelectedDirectories($directory, $this->options->includedDirectories);
116
-
117
  $excludePaths = [
118
- trailingslashit(WP_CONTENT_DIR) . 'uploads/sites',
119
- trailingslashit(WP_CONTENT_DIR) . 'cache',
120
- rtrim(WPStaging::getContentDir(), '/'),
121
- '**/node_modules',
122
  ];
123
- // add excluded plugins defined by WP Staging
124
- $excludePaths = array_merge((new ExcludedPlugins())->getPluginsToExcludeWithAbsolutePaths(), $excludePaths);
125
- $excludePaths = array_merge($this->options->excludedDirectories, $excludePaths);
126
- if ($this->isMultisiteAndPro()) {
127
- $excludePaths = apply_filters('wpstg_clone_mu_excl_folders', $excludePaths);
128
  } else {
129
- $excludePaths = apply_filters('wpstg_clone_excl_folders', $excludePaths);
130
  }
131
 
 
 
 
 
 
132
  try {
133
- foreach ($paths as $path) {
134
- $this->options->totalFiles += $this->scanToCacheFile($files, $path->path, $path->flag === Scan::IS_RECURSIVE, $excludePaths);
135
- }
136
  } catch (Exception $e) {
137
  $this->returnException('Error: ' . $e->getMessage());
138
  }
@@ -161,11 +173,8 @@ class Directories extends JobExecutable
161
  $relativeDirectory = str_replace(ABSPATH, '', $directory);
162
  $this->log("Scanning " . $relativeDirectory . " for its sub-directories and files");
163
 
164
- $paths = $this->filteredSelectedDirectories($directory, $this->options->includedDirectories);
165
  try {
166
- foreach ($paths as $path) {
167
- $this->options->totalFiles += $this->scanToCacheFile($files, $path->path, $path->flag === Scan::IS_RECURSIVE);
168
- }
169
  } catch (Exception $e) {
170
  $this->returnException('Error: ' . $e->getMessage());
171
  }
@@ -194,11 +203,8 @@ class Directories extends JobExecutable
194
  $relativeDirectory = str_replace(ABSPATH, '', $directory);
195
  $this->log("Scanning " . $relativeDirectory . " for its sub-directories and files");
196
 
197
- $paths = $this->filteredSelectedDirectories($directory, $this->options->includedDirectories);
198
  try {
199
- foreach ($paths as $path) {
200
- $this->options->totalFiles += $this->scanToCacheFile($files, $path->path, $path->flag === Scan::IS_RECURSIVE);
201
- }
202
  } catch (Exception $e) {
203
  $this->returnException('Error: ' . $e->getMessage());
204
  }
@@ -225,7 +231,7 @@ class Directories extends JobExecutable
225
  }
226
 
227
  // Absolute path to uploads folder
228
- $directory = (new WpDefaultDirectories())->getUploadsPath();
229
 
230
  // Skip it
231
  if (!is_dir($directory)) {
@@ -244,12 +250,14 @@ class Directories extends JobExecutable
244
  $files = $this->open($this->filename, 'a');
245
 
246
  $excludePaths = [
 
247
  '**/node_modules',
248
  ];
249
- $excludePaths = array_merge($this->options->excludedDirectories, $excludePaths);
 
250
 
251
  try {
252
- $this->options->totalFiles += $this->scanToCacheFile($files, $directory, true, $excludePaths);
253
  } catch (Exception $e) {
254
  $this->returnException('Error: ' . $e->getMessage());
255
  }
@@ -269,18 +277,21 @@ class Directories extends JobExecutable
269
  */
270
  private function getExtraFiles($folder)
271
  {
 
 
 
272
 
273
- if (!is_dir($folder)) {
 
274
  return true;
275
  }
276
 
277
  // open file handle and attach data to end of file
278
  $files = $this->open($this->filename, 'a');
279
- $strUtil = new Strings();
280
- $this->log("Scanning {$strUtil->getLastElemAfterString( '/', $folder )} for its sub-directories and files");
281
 
282
  try {
283
- $this->options->totalFiles += $this->scanToCacheFile($files, $folder, true, []);
284
  } catch (Exception $e) {
285
  $this->returnException('Error: ' . $e->getMessage());
286
  }
@@ -445,18 +456,63 @@ class Directories extends JobExecutable
445
  */
446
  protected function isDirectoryExcluded($directory)
447
  {
448
- $directory = (new Strings())->sanitizeDirectorySeparator($directory);
449
- // check if directory is in selected included directory
450
- foreach ($this->options->includedDirectories as $includedDirectory) {
451
- $includedDirectory = trim($includedDirectory, ' ');
452
- $directoryPath = explode(Scan::DIRECTORY_PATH_FLAG_SEPARATOR, $includedDirectory)[0];
453
- $directoryPath = trim($directoryPath, ' ');
454
- $directoryPath = (new Strings())->sanitizeDirectorySeparator($directoryPath);
455
- if (strpos(trailingslashit($directoryPath), trailingslashit($directory)) === 0) {
456
- return false;
 
 
457
  }
458
  }
459
 
460
- return true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
461
  }
462
  }
5
  use Exception;
6
  use WPStaging\Core\WPStaging;
7
  use WPStaging\Framework\CloningProcess\ExcludedPlugins;
8
+ use WPStaging\Framework\Filesystem\Filters\ExcludeFilter;
9
  use WPStaging\Framework\Traits\FileScanToCacheTrait;
10
+ use WPStaging\Framework\Utils\SlashMode;
11
  use WPStaging\Framework\Utils\Strings;
12
  use WPStaging\Framework\Utils\WpDefaultDirectories;
13
 
36
  */
37
  private $filename;
38
 
39
+ /**
40
+ * @var WpDefaultDirectories
41
+ */
42
+ private $wpDirectories;
43
+
44
+ /**
45
+ * @var Strings
46
+ */
47
+ private $strUtils;
48
+
49
  /**
50
  * Initialize
51
  */
52
  public function initialize()
53
  {
54
  $this->filename = $this->cache->getCacheDir() . "files_to_copy." . $this->cache->getCacheExtension();
55
+ $this->wpDirectories = new WpDefaultDirectories();
56
+ $this->strUtils = new Strings();
57
  }
58
 
59
  /**
126
  $relativeDirectory = str_replace(ABSPATH, '', $directory);
127
  $this->log("Scanning " . $relativeDirectory . " for its sub-directories and files");
128
 
 
 
129
  $excludePaths = [
130
+ $this->wpDirectories->getRelativeWpContentPath(SlashMode::BOTH_SLASHES) . 'cache',
131
+ '/' . str_replace(ABSPATH, '', rtrim(WPStaging::getContentDir(), '/')),
132
+ '**/wp-staging*/**/node_modules', // only exclude node modules in WP Staging's plugins
 
133
  ];
134
+
135
+ if (is_multisite() && !is_main_site()) {
136
+ $excludePaths[] = $this->wpDirectories->getRelativeUploadPath(SlashMode::LEADING_SLASH);
 
 
137
  } else {
138
+ $excludePaths[] = $this->wpDirectories->getRelativeUploadPath(SlashMode::BOTH_SLASHES) . 'sites';
139
  }
140
 
141
+ // add excluded plugins defined by WP Staging
142
+ $excludePaths = array_merge((new ExcludedPlugins())->getPluginsToExcludeWithRelativePath(), $excludePaths);
143
+
144
+ $excludePaths = array_merge($this->getFilteredExcludedPaths(), $excludePaths);
145
+
146
  try {
147
+ $this->options->totalFiles += $this->scanToCacheFile($files, $directory, true, $excludePaths, $this->getFilteredExcludedFileSizes());
 
 
148
  } catch (Exception $e) {
149
  $this->returnException('Error: ' . $e->getMessage());
150
  }
173
  $relativeDirectory = str_replace(ABSPATH, '', $directory);
174
  $this->log("Scanning " . $relativeDirectory . " for its sub-directories and files");
175
 
 
176
  try {
177
+ $this->options->totalFiles += $this->scanToCacheFile($files, $directory, true);
 
 
178
  } catch (Exception $e) {
179
  $this->returnException('Error: ' . $e->getMessage());
180
  }
203
  $relativeDirectory = str_replace(ABSPATH, '', $directory);
204
  $this->log("Scanning " . $relativeDirectory . " for its sub-directories and files");
205
 
 
206
  try {
207
+ $this->options->totalFiles += $this->scanToCacheFile($files, $directory, true);
 
 
208
  } catch (Exception $e) {
209
  $this->returnException('Error: ' . $e->getMessage());
210
  }
231
  }
232
 
233
  // Absolute path to uploads folder
234
+ $directory = $this->wpDirectories->getUploadsPath();
235
 
236
  // Skip it
237
  if (!is_dir($directory)) {
250
  $files = $this->open($this->filename, 'a');
251
 
252
  $excludePaths = [
253
+ '/' . str_replace(ABSPATH, ' ', rtrim(WPStaging::getContentDir(), '/')),
254
  '**/node_modules',
255
  ];
256
+
257
+ $excludePaths = array_merge($this->getFilteredExcludedPaths(), $excludePaths);
258
 
259
  try {
260
+ $this->options->totalFiles += $this->scanToCacheFile($files, $directory, true, $excludePaths, $this->getFilteredExcludedFileSizes());
261
  } catch (Exception $e) {
262
  $this->returnException('Error: ' . $e->getMessage());
263
  }
277
  */
278
  private function getExtraFiles($folder)
279
  {
280
+ if (empty($folder)) {
281
+ return true;
282
+ }
283
 
284
+ $absoluteExtraPath = ABSPATH . $folder;
285
+ if (!is_dir($absoluteExtraPath)) {
286
  return true;
287
  }
288
 
289
  // open file handle and attach data to end of file
290
  $files = $this->open($this->filename, 'a');
291
+ $this->log("Scanning {$folder} for its sub-directories and files");
 
292
 
293
  try {
294
+ $this->options->totalFiles += $this->scanToCacheFile($files, $absoluteExtraPath, true, $this->getFilteredExcludedPaths(), $this->getFilteredExcludedFileSizes());
295
  } catch (Exception $e) {
296
  $this->returnException('Error: ' . $e->getMessage());
297
  }
456
  */
457
  protected function isDirectoryExcluded($directory)
458
  {
459
+ $directory = $this->strUtils->sanitizeDirectorySeparator($directory);
460
+ foreach ($this->options->excludedDirectories as $excludedDirectory) {
461
+ $excludedDirectory = $this->strUtils->sanitizeDirectorySeparator($excludedDirectory);
462
+ // Check whether directory is itself is a part of excluded directories
463
+ if ($excludedDirectory === $directory) {
464
+ return true;
465
+ }
466
+
467
+ // Check whether directory a child of any excluded directories
468
+ if ($this->strUtils->startsWith($directory, $excludedDirectory . '/')) {
469
+ return true;
470
  }
471
  }
472
 
473
+ return false;
474
+ }
475
+
476
+ /**
477
+ * Return List of all user defined file size excludes from hooks and through UI
478
+ * @return array
479
+ */
480
+ private function getFilteredExcludedFileSizes()
481
+ {
482
+ return apply_filters('wpstg_clone_file_size_exclude', $this->options->excludeSizeRules);
483
+ }
484
+
485
+ /**
486
+ * Return list of all exclude rules and exclude paths,
487
+ * Defined by user in hooks or through UI
488
+ * Defined by WP Staging i.e. cache or some plugins.
489
+ * @return array
490
+ */
491
+ private function getFilteredExcludedPaths()
492
+ {
493
+ $excludePaths = [];
494
+ $abspath = $this->strUtils->sanitizeDirectorySeparator(ABSPATH);
495
+ foreach ($this->options->excludedDirectories as $excludedDirectory) {
496
+ $directory = $this->strUtils->sanitizeDirectorySeparator($excludedDirectory);
497
+ if ($this->strUtils->startsWith($directory, $abspath)) {
498
+ $excludePaths[] = '/' . str_replace($abspath, '', $directory);
499
+ continue;
500
+ }
501
+
502
+ $excludePaths[] = $excludedDirectory;
503
+ }
504
+
505
+ if ($this->isMultisiteAndPro()) {
506
+ $excludePaths = apply_filters('wpstg_clone_mu_excl_folders', $excludePaths);
507
+ } else {
508
+ $excludePaths = apply_filters('wpstg_clone_excl_folders', $excludePaths);
509
+ }
510
+
511
+ $excludeFilters = new ExcludeFilter();
512
+ $excludeGlobRules = array_map(function ($rule) use ($excludeFilters) {
513
+ return $excludeFilters->mapExclude($rule);
514
+ }, $this->options->excludeGlobRules);
515
+
516
+ return array_merge($excludePaths, $excludeGlobRules);
517
  }
518
  }
Backend/Modules/Jobs/Files.php CHANGED
@@ -148,10 +148,6 @@ class Files extends JobExecutable
148
  throw new \Exception('Can not delete directory: ' . $this->destination . ' This seems to be the root directory. Exclude this directory from deleting and try again.');
149
  }
150
 
151
- // Make sure destination is inside WordPress
152
- $wpRoot = (new Strings())->sanitizeDirectorySeparator(ABSPATH);
153
- $this->destination = $wpRoot . str_replace($wpRoot, '', $this->destination);
154
-
155
  // Finished or path does not exist
156
  if (empty($this->destination) || !is_dir($this->destination)) {
157
  if (defined('WPSTG_DEBUG') && WPSTG_DEBUG) {
@@ -180,7 +176,7 @@ class Files extends JobExecutable
180
  ->setShouldStop([$this, 'isOverThreshold'])
181
  ->setRecursive(true);
182
  try {
183
- if (!$fs->deleteNew($this->destination)) {
184
  return false;
185
  }
186
  } catch (\RuntimeException $ex) {
@@ -292,17 +288,17 @@ class Files extends JobExecutable
292
  }
293
 
294
  if (!$this->options->uploadsSymlinked) {
295
- $this->log("Skipped symlinking Wp Uploads Folder");
296
  return true;
297
  }
298
 
299
  $symlinker = new WpUploadsFolderSymlinker($this->options->destinationDir);
300
  if ($symlinker->trySymlink()) {
301
- $this->log("Uploads Folder symlinked with the production site");
302
  return true;
303
  }
304
 
305
- $this->returnException('Unable to symlink uploads folder. Maybe a file, folder or a link exists in the symlink path.');
306
  return false;
307
  }
308
 
@@ -624,6 +620,12 @@ class Files extends JobExecutable
624
  $directory = $this->sanitizeDirectorySeparator($directory);
625
 
626
  foreach ($this->options->extraDirectories as $extraDirectory) {
 
 
 
 
 
 
627
  if (strpos($directory, $this->sanitizeDirectorySeparator($extraDirectory)) === 0) {
628
  return true;
629
  }
148
  throw new \Exception('Can not delete directory: ' . $this->destination . ' This seems to be the root directory. Exclude this directory from deleting and try again.');
149
  }
150
 
 
 
 
 
151
  // Finished or path does not exist
152
  if (empty($this->destination) || !is_dir($this->destination)) {
153
  if (defined('WPSTG_DEBUG') && WPSTG_DEBUG) {
176
  ->setShouldStop([$this, 'isOverThreshold'])
177
  ->setRecursive(true);
178
  try {
179
+ if (!$fs->delete($this->destination)) {
180
  return false;
181
  }
182
  } catch (\RuntimeException $ex) {
288
  }
289
 
290
  if (!$this->options->uploadsSymlinked) {
291
+ $this->log(__("Skipped symlinking Wp Uploads Folder", 'wp-staging'));
292
  return true;
293
  }
294
 
295
  $symlinker = new WpUploadsFolderSymlinker($this->options->destinationDir);
296
  if ($symlinker->trySymlink()) {
297
+ $this->log(__("Uploads Folder symlinked with the production site", 'wp-staging'));
298
  return true;
299
  }
300
 
301
+ $this->returnException($symlinker->getError());
302
  return false;
303
  }
304
 
620
  $directory = $this->sanitizeDirectorySeparator($directory);
621
 
622
  foreach ($this->options->extraDirectories as $extraDirectory) {
623
+ $extraDirectory = trim($extraDirectory);
624
+
625
+ if (empty($extraDirectory)) {
626
+ continue;
627
+ }
628
+
629
  if (strpos($directory, $this->sanitizeDirectorySeparator($extraDirectory)) === 0) {
630
  return true;
631
  }
Backend/Modules/Jobs/Job.php CHANGED
@@ -10,10 +10,10 @@ if (!defined("WPINC")) {
10
  use DateInterval;
11
  use DateTime;
12
  use Exception;
13
- use WPStaging\Core\thirdParty\thirdPartyCompatibility;
14
  use WPStaging\Core\Utils\Cache;
15
  use WPStaging\Core\Utils\Logger;
16
  use WPStaging\Core\WPStaging;
 
17
  use WPStaging\Framework\Interfaces\ShutdownableInterface;
18
  use WPStaging\Framework\Traits\ResourceTrait;
19
 
@@ -57,10 +57,9 @@ abstract class Job implements ShutdownableInterface
57
  protected $baseUrl;
58
 
59
  /**
60
- *
61
- * @var object
62
  */
63
- protected $thirdParty;
64
 
65
  /**
66
  * Job constructor.
@@ -68,7 +67,8 @@ abstract class Job implements ShutdownableInterface
68
  */
69
  public function __construct()
70
  {
71
- $this->thirdParty = new thirdPartyCompatibility();
 
72
 
73
  // Services
74
  $this->cache = new Cache(-1, WPStaging::getContentDir());
10
  use DateInterval;
11
  use DateTime;
12
  use Exception;
 
13
  use WPStaging\Core\Utils\Cache;
14
  use WPStaging\Core\Utils\Logger;
15
  use WPStaging\Core\WPStaging;
16
+ use WPStaging\Framework\Database\ExcludedTables;
17
  use WPStaging\Framework\Interfaces\ShutdownableInterface;
18
  use WPStaging\Framework\Traits\ResourceTrait;
19
 
57
  protected $baseUrl;
58
 
59
  /**
60
+ * @var ExcludedTables
 
61
  */
62
+ protected $excludedTableService;
63
 
64
  /**
65
  * Job constructor.
67
  */
68
  public function __construct()
69
  {
70
+ // TODO: inject using DI
71
+ $this->excludedTableService = new ExcludedTables();
72
 
73
  // Services
74
  $this->cache = new Cache(-1, WPStaging::getContentDir());
Backend/Modules/Jobs/PreserveDataFirstStep.php CHANGED
@@ -4,6 +4,7 @@ namespace WPStaging\Backend\Modules\Jobs;
4
 
5
  use WPStaging\Core\WPStaging;
6
  use WPStaging\Framework\Adapter\SourceDatabase;
 
7
 
8
  /**
9
  * Preserve staging sites in wpstg_existing_clones_beta in staging database while updating a site
@@ -80,24 +81,46 @@ class PreserveDataFirstStep extends JobExecutable
80
  }
81
 
82
  // Get wpstg_existing_clones_beta from staging database
83
- $result = $this->stagingDb->get_var(
84
  $this->stagingDb->prepare(
85
  "SELECT `option_value` FROM " . $this->stagingPrefix . "options WHERE `option_name` = %s",
86
  "wpstg_existing_clones_beta"
87
  )
88
  );
89
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
  // Nothing to do
91
- if (!$result) {
92
  return true;
93
  }
94
 
95
- // Insert wpstg_existing_clones_beta into wpstg_tmp_data in production database
 
 
 
 
 
 
96
  $insert = $this->productionDb->query(
97
  $this->productionDb->prepare(
98
  "INSERT INTO `" . $this->productionDb->prefix . "options` ( `option_id`, `option_name`, `option_value`, `autoload` ) VALUES ( NULL , %s, %s, %s )",
99
  "wpstg_tmp_data",
100
- $result,
101
  "no"
102
  )
103
  );
@@ -105,12 +128,23 @@ class PreserveDataFirstStep extends JobExecutable
105
  if ($delete === false) {
106
  $this->log("Preserve Data: Failed to delete wpstg_tmp_data");
107
  }
108
- if ($result === false) {
 
109
  $this->log("Preserve Data: Failed to get wpstg_existing_clones_beta");
110
  }
 
 
 
 
 
 
 
 
 
111
  if ($insert === false) {
112
  $this->log("Preserve Data: Failed to insert wpstg_existing_clones_beta to wpstg_tmp_data");
113
  }
 
114
  return true;
115
  }
116
 
4
 
5
  use WPStaging\Core\WPStaging;
6
  use WPStaging\Framework\Adapter\SourceDatabase;
7
+ use WPStaging\Framework\Staging\CloneOptions;
8
 
9
  /**
10
  * Preserve staging sites in wpstg_existing_clones_beta in staging database while updating a site
81
  }
82
 
83
  // Get wpstg_existing_clones_beta from staging database
84
+ $stagingSites = $this->stagingDb->get_var(
85
  $this->stagingDb->prepare(
86
  "SELECT `option_value` FROM " . $this->stagingPrefix . "options WHERE `option_name` = %s",
87
  "wpstg_existing_clones_beta"
88
  )
89
  );
90
 
91
+ // Get wpstg_settings from staging database
92
+ $settings = $this->stagingDb->get_var(
93
+ $this->stagingDb->prepare(
94
+ "SELECT `option_value` FROM " . $this->stagingPrefix . "options WHERE `option_name` = %s",
95
+ "wpstg_settings"
96
+ )
97
+ );
98
+
99
+ // Get wpstg_clone_options from staging database
100
+ $cloneOptions = $this->stagingDb->get_var(
101
+ $this->stagingDb->prepare(
102
+ "SELECT `option_value` FROM " . $this->stagingPrefix . "options WHERE `option_name` = %s",
103
+ CloneOptions::WPSTG_CLONE_SETTINGS_KEY
104
+ )
105
+ );
106
+
107
  // Nothing to do
108
+ if (!$stagingSites && !$settings && !$cloneOptions) {
109
  return true;
110
  }
111
 
112
+ $tmpData = serialize((object) [
113
+ 'stagingSites' => $stagingSites,
114
+ 'settings' => $settings,
115
+ 'cloneOptions' => $cloneOptions,
116
+ ]);
117
+
118
+ // Insert staging site preserved data into wpstg_tmp_data in production database
119
  $insert = $this->productionDb->query(
120
  $this->productionDb->prepare(
121
  "INSERT INTO `" . $this->productionDb->prefix . "options` ( `option_id`, `option_name`, `option_value`, `autoload` ) VALUES ( NULL , %s, %s, %s )",
122
  "wpstg_tmp_data",
123
+ $tmpData,
124
  "no"
125
  )
126
  );
128
  if ($delete === false) {
129
  $this->log("Preserve Data: Failed to delete wpstg_tmp_data");
130
  }
131
+
132
+ if ($stagingSites === false) {
133
  $this->log("Preserve Data: Failed to get wpstg_existing_clones_beta");
134
  }
135
+
136
+ if ($settings === false) {
137
+ $this->log("Preserve Data: Failed to get wpstg_settings");
138
+ }
139
+
140
+ if ($cloneOptions === false) {
141
+ $this->log("Preserve Data: Failed to get wpstg_clone_options");
142
+ }
143
+
144
  if ($insert === false) {
145
  $this->log("Preserve Data: Failed to insert wpstg_existing_clones_beta to wpstg_tmp_data");
146
  }
147
+
148
  return true;
149
  }
150
 
Backend/Modules/Jobs/PreserveDataSecondStep.php CHANGED
@@ -4,6 +4,7 @@ namespace WPStaging\Backend\Modules\Jobs;
4
 
5
  use WPStaging\Core\WPStaging;
6
  use WPStaging\Framework\Adapter\SourceDatabase;
 
7
 
8
  /**
9
  * Copy wpstg_tmp_data back to wpstg_existing_clones_beta after cloning with class::PreserveDataSecondStep
@@ -80,30 +81,90 @@ class PreserveDataSecondStep extends JobExecutable
80
  return true;
81
  }
82
 
83
- // Delete wpstg_tmp_data
84
- $delete = $this->stagingDb->query(
 
 
 
 
 
85
  $this->stagingDb->prepare("DELETE FROM " . $this->stagingPrefix . "options WHERE `option_name` = %s", "wpstg_existing_clones_beta")
86
  );
87
 
 
 
 
 
 
 
 
 
 
 
 
 
88
  // Insert wpstg_existing_clones_beta in staging database
89
- $insert = $this->stagingDb->query(
90
  $this->stagingDb->prepare(
91
  "INSERT INTO `" . $this->stagingPrefix . "options` ( `option_id`, `option_name`, `option_value`, `autoload` ) VALUES ( NULL , %s, %s, %s )",
92
  "wpstg_existing_clones_beta",
93
- $result,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
  "no"
95
  )
96
  );
97
 
98
- if ($delete === false) {
99
- $this->log("Preserve Data Second Step: Failed to delete wpstg_tmp_data");
 
 
 
 
 
 
 
 
 
 
 
 
100
  }
 
101
  if ($result === false) {
102
- $this->log("Preserve Data Second Step: Failed to get wpstg_existing_clones_beta");
 
 
 
 
103
  }
104
- if ($insert === false) {
105
- $this->log("Preserve Data Second Step: Failed to insert wpstg_tmp_data to wpstg_existing_clones_beta");
 
 
 
 
 
106
  }
 
107
  return true;
108
  }
109
  }
4
 
5
  use WPStaging\Core\WPStaging;
6
  use WPStaging\Framework\Adapter\SourceDatabase;
7
+ use WPStaging\Framework\Staging\CloneOptions;
8
 
9
  /**
10
  * Copy wpstg_tmp_data back to wpstg_existing_clones_beta after cloning with class::PreserveDataSecondStep
81
  return true;
82
  }
83
 
84
+ // Delete wpstg_tmp_data from the production site
85
+ $deleteTmpData = $this->productionDb->query(
86
+ $this->productionDb->prepare("DELETE FROM " . $this->productionDb->prefix . "options WHERE `option_name` = %s", "wpstg_tmp_data")
87
+ );
88
+
89
+ // Delete wpstg_existing_clones_beta from the staging site
90
+ $deleteStagingSites = $this->stagingDb->query(
91
  $this->stagingDb->prepare("DELETE FROM " . $this->stagingPrefix . "options WHERE `option_name` = %s", "wpstg_existing_clones_beta")
92
  );
93
 
94
+ // Delete wpstg_settings from the staging site
95
+ $deleteSettings = $this->stagingDb->query(
96
+ $this->stagingDb->prepare("DELETE FROM " . $this->stagingPrefix . "options WHERE `option_name` = %s", "wpstg_settings")
97
+ );
98
+
99
+ // Delete wpstg_clone_options from the staging site
100
+ $deleteCloneOptions = $this->stagingDb->query(
101
+ $this->stagingDb->prepare("DELETE FROM " . $this->stagingPrefix . "options WHERE `option_name` = %s", CloneOptions::WPSTG_CLONE_SETTINGS_KEY)
102
+ );
103
+
104
+ $tempData = maybe_unserialize($result);
105
+
106
  // Insert wpstg_existing_clones_beta in staging database
107
+ $insertStagingSites = $this->stagingDb->query(
108
  $this->stagingDb->prepare(
109
  "INSERT INTO `" . $this->stagingPrefix . "options` ( `option_id`, `option_name`, `option_value`, `autoload` ) VALUES ( NULL , %s, %s, %s )",
110
  "wpstg_existing_clones_beta",
111
+ $tempData->stagingSites,
112
+ "no"
113
+ )
114
+ );
115
+
116
+ // Insert wpstg_settings in staging database
117
+ $insertSettings = $this->stagingDb->query(
118
+ $this->stagingDb->prepare(
119
+ "INSERT INTO `" . $this->stagingPrefix . "options` ( `option_id`, `option_name`, `option_value`, `autoload` ) VALUES ( NULL , %s, %s, %s )",
120
+ "wpstg_settings",
121
+ $tempData->settings,
122
+ "no"
123
+ )
124
+ );
125
+
126
+ // Insert wpstg_clone_options in staging database
127
+ $insertCloneOptions = $this->stagingDb->query(
128
+ $this->stagingDb->prepare(
129
+ "INSERT INTO `" . $this->stagingPrefix . "options` ( `option_id`, `option_name`, `option_value`, `autoload` ) VALUES ( NULL , %s, %s, %s )",
130
+ CloneOptions::WPSTG_CLONE_SETTINGS_KEY,
131
+ $tempData->cloneOptions,
132
  "no"
133
  )
134
  );
135
 
136
+ if ($deleteTmpData === false) {
137
+ $this->log("Preserve Data Second Step: Failed to delete wpstg_tmp_data from the production site");
138
+ }
139
+
140
+ if ($deleteStagingSites === false) {
141
+ $this->log("Preserve Data Second Step: Failed to delete wpstg_existing_clones_beta from the staging site");
142
+ }
143
+
144
+ if ($deleteSettings === false) {
145
+ $this->log("Preserve Data Second Step: Failed to delete wpstg_settings from the staging site");
146
+ }
147
+
148
+ if ($deleteCloneOptions === false) {
149
+ $this->log("Preserve Data Second Step: Failed to delete wpstg_clone_options from the staging site");
150
  }
151
+
152
  if ($result === false) {
153
+ $this->log("Preserve Data Second Step: Failed to get wpstg_tmp_data from the production site");
154
+ }
155
+
156
+ if ($insertStagingSites === false) {
157
+ $this->log("Preserve Data Second Step: Failed to insert preserved existing clones into wpstg_existing_clones_beta of the staging site");
158
  }
159
+
160
+ if ($insertSettings === false) {
161
+ $this->log("Preserve Data Second Step: Failed to insert preserved settings into wpstg_settings of the staging site");
162
+ }
163
+
164
+ if ($insertCloneOptions === false) {
165
+ $this->log("Preserve Data Second Step: Failed to insert preserved clone options into wpstg_settings of the staging site");
166
  }
167
+
168
  return true;
169
  }
170
  }
Backend/Modules/Jobs/ProcessLock.php CHANGED
@@ -23,7 +23,7 @@ class ProcessLock extends JobExecutable
23
  if (parent::isRunning()) {
24
  $this->log("Another process is running");
25
 
26
- $message = __('Hold on, another WP Staging process is already running...', 'wp-staging');
27
 
28
  require_once WPSTG_PLUGIN_DIR . "Backend/views/clone/ajax/process-lock.php";
29
 
@@ -34,6 +34,31 @@ class ProcessLock extends JobExecutable
34
  return false;
35
  }
36
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
  /**
38
  * remove process lock value
39
  */
23
  if (parent::isRunning()) {
24
  $this->log("Another process is running");
25
 
26
+ $message = __('Hold on, another WP STAGING process is already running...', 'wp-staging');
27
 
28
  require_once WPSTG_PLUGIN_DIR . "Backend/views/clone/ajax/process-lock.php";
29
 
34
  return false;
35
  }
36
 
37
+ /**
38
+ * Check if any process is already running, if running return a json encoded response for Swal Modal,
39
+ * Otherwise return false
40
+ *
41
+ * @return boolean|string
42
+ */
43
+ public function ajaxIsRunning()
44
+ {
45
+ if (parent::isRunning()) {
46
+ return json_encode([
47
+ 'success' => false,
48
+ 'type' => 'processLock',
49
+ // TODO: Create a Swal Response Class and Js library to handle that response or, Implement own Swal alternative
50
+ 'swalOptions' => [
51
+ 'title' => __('Error!', 'wp-staging'),
52
+ 'html' => __('Hold on, another WP Staging process is already running...', 'wp-staging'),
53
+ 'confirmButtonText' => __('Stop other process', 'wp-staging'),
54
+ 'showCancelButton' => true,
55
+ ],
56
+ ]);
57
+ }
58
+
59
+ return false;
60
+ }
61
+
62
  /**
63
  * remove process lock value
64
  */
Backend/Modules/Jobs/Scan.php CHANGED
@@ -11,12 +11,12 @@ use Countable;
11
  use DirectoryIterator;
12
  use Exception;
13
  use WPStaging\Backend\Optimizer\Optimizer;
14
- use WPStaging\Core\Iterators;
15
  use WPStaging\Core\Utils\Directories as DirectoriesUtil;
16
  use WPStaging\Core\WPStaging;
17
  use WPStaging\Framework\Database\LegacyDatabaseInfo;
18
- use WPStaging\Framework\Utils\WpDefaultDirectories;
19
  use WPStaging\Framework\Utils\Strings;
 
20
 
21
  /**
22
  * Class Scan
@@ -26,35 +26,58 @@ use WPStaging\Framework\Utils\Strings;
26
  */
27
  class Scan extends Job
28
  {
 
29
  /**
30
- * separator to separate directory path and its is scanned flag
 
 
31
  * @var string
32
  */
33
- const DIRECTORY_PATH_FLAG_SEPARATOR = '::';
34
 
35
  /**
36
- * separator to separate directories
 
 
37
  * @var string
38
  */
39
- const DIRECTORIES_SEPARATOR = ',';
 
 
 
 
 
 
40
 
41
  /**
42
- * const to use when directory is scanned
43
- * @var int
44
  */
45
- const IS_RECURSIVE = '1';
46
 
47
  /**
48
- * const to use when directory is not scanned
49
- * @var int
50
  */
51
- const IS_NON_RECURSIVE = '0';
52
 
53
- /** @var array */
54
- private $directories = [];
 
 
 
 
 
 
55
 
56
- /** @var DirectoriesUtil */
57
- private $objDirectories;
 
 
 
 
 
 
 
 
58
 
59
  /**
60
  * Upon class initialization
@@ -63,6 +86,11 @@ class Scan extends Job
63
  {
64
  $this->objDirectories = new DirectoriesUtil();
65
 
 
 
 
 
 
66
  $this->getTables();
67
 
68
  $this->getDirectories();
@@ -84,6 +112,7 @@ class Scan extends Job
84
 
85
  if (isset($_POST["clone"]) && array_key_exists($_POST["clone"], $this->options->existingClones)) {
86
  $this->options->current = $_POST["clone"];
 
87
  }
88
 
89
  // Tables
@@ -109,8 +138,14 @@ class Scan extends Job
109
 
110
  // Define mainJob to differentiate between cloning, updating and pushing
111
  $this->options->mainJob = 'cloning';
 
 
 
 
112
 
113
- if ($this->options->current !== null) {
 
 
114
  $this->options->mainJob = 'updating';
115
  }
116
 
@@ -154,19 +189,30 @@ class Scan extends Job
154
  }
155
 
156
  /**
157
- * @param null|array $directories
158
- * @param bool $forceDisabled
 
 
 
159
  * @return string
 
 
160
  */
161
- public function directoryListing($directories = null, $forceDisabled = false)
162
  {
163
- if ($directories == null) {
164
- $directories = $this->directories;
165
- }
166
-
167
  // Sort results
168
  uksort($directories, 'strcasecmp');
169
 
 
 
 
 
 
 
 
 
 
170
  $output = '';
171
  foreach ($directories as $name => $directory) {
172
  // Not a directory, possibly a symlink, therefore we will skip it
@@ -178,17 +224,13 @@ class Scan extends Job
178
  $data = reset($directory);
179
  unset($directory[key($directory)]);
180
 
181
-
182
- $isChecked = (
183
- empty($this->options->includedDirectories) ||
184
- in_array($data["path"], $this->options->includedDirectories)
185
- );
186
-
187
  $dataPath = isset($data["path"]) ? $data["path"] : '';
188
  $dataSize = isset($data["size"]) ? $data["size"] : '';
189
  $strUtils = new Strings();
190
- $path = $strUtils->sanitizeDirectorySeparator($dataPath);
191
- $wpRoot = $strUtils->sanitizeDirectorySeparator(ABSPATH);
 
 
192
 
193
  // Select all wp core folders and their sub dirs.
194
  // Unselect all other folders (default setting)
@@ -200,41 +242,47 @@ class Scan extends Job
200
  strpos(strrev($path), strrev($wpRoot . "wp-includes")) === false &&
201
  strpos(strrev($path), strrev($wpRoot . "wp-content")) === false;
202
 
203
- // Extra class to differentiate between wp core and non core folders
204
- $class = !$isDisabled ? 'wpstg-root' : 'wpstg-extra';
 
 
 
 
 
 
 
 
205
 
206
  $output .= "<div class='wpstg-dir'>";
207
  $output .= "<input type='checkbox' class='wpstg-check-dir " . $class . "'";
208
 
209
- if ($isChecked && !$isDisabled && !$forceDisabled) {
210
- $output .= " checked";
 
 
 
211
  }
212
 
213
- // append recursive flag to dataPath value for only wp root directories
214
- $isScanned = !empty($directory);
215
- $dirPath = $dataPath;
216
- if ($class === 'wpstg-root') {
217
- $dirPath = $this->appendRecursiveFlag($dirPath, $isScanned);
218
  }
219
 
220
- $output .= " name='selectedDirectories[]' value='{$dirPath}'>";
 
 
 
 
221
 
222
  $output .= "<a href='#' class='wpstg-expand-dirs ";
223
- if (!$isChecked || $isDisabled) {
224
  $output .= " disabled";
225
  }
226
 
227
  $output .= "'>{$name}";
228
  $output .= "</a>";
 
229
  $output .= "<span class='wpstg-size-info'>{$this->formatSize( $dataSize )}</span>";
230
  $output .= isset($this->settings->debugMode) ? "<span class='wpstg-size-info'> {$dataPath}</span>" : "";
231
-
232
- if ($isScanned) {
233
- $output .= "<div class='wpstg-dir wpstg-subdir'>";
234
- $output .= $this->directoryListing($directory, $isDisabled);
235
- $output .= "</div>";
236
- }
237
-
238
  $output .= "</div>";
239
  }
240
 
@@ -242,19 +290,44 @@ class Scan extends Job
242
  }
243
 
244
  /**
245
- * Checks if there is enough free disk space to create staging site
246
  * Returns null when can't run disk_free_space function one way or another
 
 
 
247
  * @return bool|null
248
  */
249
- public function hasFreeDiskSpace()
250
  {
251
  if (!function_exists("disk_free_space")) {
252
  return null;
253
  }
254
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
255
 
256
  $data = [
257
- 'usedspace' => $this->formatSize($this->getDirectorySizeInclSubdirs(WPStaging::getWPpath()))
258
  ];
259
 
260
  echo json_encode($data);
@@ -299,12 +372,16 @@ class Scan extends Job
299
  }
300
 
301
  /**
302
- * Get directories and main meta data about'em recursively
 
303
  */
304
- protected function getDirectories()
305
  {
 
 
 
306
 
307
- $directories = new Iterators\RecursiveDirectoryIterator(WPStaging::getWPpath());
308
 
309
  foreach ($directories as $directory) {
310
  // Not a valid directory
@@ -312,54 +389,18 @@ class Scan extends Job
312
  continue;
313
  }
314
 
315
- $this->handleDirectory($path);
316
-
317
- // Get Sub-directories
318
- $this->getSubDirectories($directory->getRealPath());
319
- }
320
-
321
- // Gather Plugins
322
- $this->getSubDirectories(WP_PLUGIN_DIR);
323
-
324
- // Gather Themes
325
- $this->getSubDirectories(WP_CONTENT_DIR . DIRECTORY_SEPARATOR . "themes");
326
-
327
- // Gather Custom Uploads Folder if there is one
328
- $this->getSubDirectories((new WpDefaultDirectories())->getSiteUploadsPath());
329
- }
330
-
331
- /**
332
- * @param string $path
333
- * @return bool
334
- */
335
- protected function getSubDirectories($path)
336
- {
337
-
338
- if (!is_readable($path)) {
339
- return false;
340
- }
341
-
342
- if (!is_dir($path)) {
343
- return false;
344
- }
345
-
346
- // IMPORTANT: This is necessary if directory does not belongs to current php user
347
- // DirectoryIterator() will throw a fatal error which can not be catched with is_readable()
348
- if (!opendir($path)) {
349
- return false;
350
- }
351
-
352
- $directories = new DirectoryIterator($path);
353
-
354
- foreach ($directories as $directory) {
355
- // Not a valid directory
356
- if (($path = $this->getPath($directory)) === false) {
357
  continue;
358
  }
359
 
360
- $this->handleDirectory($path);
 
 
 
 
 
 
361
  }
362
- return false;
363
  }
364
 
365
  /**
@@ -369,16 +410,15 @@ class Scan extends Job
369
  */
370
  protected function getPath($directory)
371
  {
372
-
373
  /*
374
  * Do not follow root path like src/web/..
375
  * This must be done before \SplFileInfo->isDir() is used!
376
  * Prevents open base dir restriction fatal errors
377
  */
378
-
379
  if (strpos($directory->getRealPath(), WPStaging::getWPpath()) !== 0) {
380
  return false;
381
  }
 
382
  $path = str_replace(WPStaging::getWPpath(), null, $directory->getRealPath());
383
  // Using strpos() for symbolic links as they could create nasty stuff in nix stuff for directory structures
384
  if (!$directory->isDir() || strlen($path) < 1) {
@@ -443,40 +483,75 @@ class Scan extends Job
443
  /**
444
  * Get total size of a directory including all its subdirectories
445
  * @param string $dir
 
446
  * @return int
447
  */
448
- protected function getDirectorySizeInclSubdirs($dir)
449
  {
450
  $size = 0;
451
  foreach (glob(rtrim($dir, '/') . '/*', GLOB_NOSORT) as $each) {
452
- $size += is_file($each) ? filesize($each) : $this->getDirectorySizeInclSubdirs($each);
 
 
 
 
 
 
 
 
 
453
  }
 
454
  return $size;
455
  }
456
 
457
  /**
458
- * Append recursive flag to directoryPath
459
- * If directory is scanned then there is no need to recursively scan it,
460
- * since all its direct child directories will be in the list already,
461
- * so append IS_NON_RECURSIVE flag i.e. 0 to it.
462
- * And we only need IS_RECURSIVE flag i.e. 1 for non scanned directories
463
- * to custom recursive iterator over all it sub directories.
464
- * Also remove wp root path from the directory path.
465
- * @param string $directoryPath
466
- * @param bool $isScanned
467
- * @return string
468
  */
469
- protected function appendRecursiveFlag($directoryPath, $isScanned)
470
  {
471
- // use relative path for core directories
472
- $filteredPath["directoryPath"] = str_replace(ABSPATH, '', $directoryPath);
473
- $filteredPath["isRecursive"] = self::IS_RECURSIVE;
474
- // no need to recursively iterate in directory job if already scanned
475
- if ($isScanned) {
476
- $filteredPath["isRecursive"] = self::IS_NON_RECURSIVE;
477
  }
478
 
479
- // Don't use json_encode as it will increase the size of post request
480
- return implode(self::DIRECTORY_PATH_FLAG_SEPARATOR, $filteredPath);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
481
  }
482
  }
11
  use DirectoryIterator;
12
  use Exception;
13
  use WPStaging\Backend\Optimizer\Optimizer;
 
14
  use WPStaging\Core\Utils\Directories as DirectoriesUtil;
15
  use WPStaging\Core\WPStaging;
16
  use WPStaging\Framework\Database\LegacyDatabaseInfo;
17
+ use WPStaging\Framework\Filesystem\Scanning\ScanConst;
18
  use WPStaging\Framework\Utils\Strings;
19
+ use WPStaging\Framework\Utils\WpDefaultDirectories;
20
 
21
  /**
22
  * Class Scan
26
  */
27
  class Scan extends Job
28
  {
29
+
30
  /**
31
+ * Class to use for WordPress core directories like wp-content, wp-admin, wp-includes
32
+ * This doesn't contains class selector prefix
33
+ *
34
  * @var string
35
  */
36
+ const WP_CORE_DIR = "wpstg-wp-core-dir";
37
 
38
  /**
39
+ * Class to use for WordPress non core directories
40
+ * This doesn't contains class selector prefix
41
+ *
42
  * @var string
43
  */
44
+ const WP_NON_CORE_DIR = "wpstg-wp-non-core-dir";
45
+
46
+ /** @var array */
47
+ private $directories = [];
48
+
49
+ /** @var DirectoriesUtil */
50
+ private $objDirectories;
51
 
52
  /**
53
+ * @var string
 
54
  */
55
+ private $directoryToScanOnly;
56
 
57
  /**
58
+ * @var string Path to gif loader for directory loading
 
59
  */
60
+ private $gifLoaderPath;
61
 
62
+ public function __construct($directoryToScanOnly = null)
63
+ {
64
+ // Accept both the absolute path or relative path with respect to wp root
65
+ // Santized the path to make comparing works for windows platform too.
66
+ $this->directoryToScanOnly = null;
67
+ if ($directoryToScanOnly !== null) {
68
+ $this->directoryToScanOnly = $directoryToScanOnly;
69
+ }
70
 
71
+ parent::__construct();
72
+ }
73
+
74
+ /**
75
+ * @param $string $gifLoaderPath
76
+ */
77
+ public function setGifLoaderPath($gifLoaderPath)
78
+ {
79
+ $this->gifLoaderPath = $gifLoaderPath;
80
+ }
81
 
82
  /**
83
  * Upon class initialization
86
  {
87
  $this->objDirectories = new DirectoriesUtil();
88
 
89
+ if ($this->directoryToScanOnly !== null) {
90
+ $this->getDirectories($this->directoryToScanOnly);
91
+ return;
92
+ }
93
+
94
  $this->getTables();
95
 
96
  $this->getDirectories();
112
 
113
  if (isset($_POST["clone"]) && array_key_exists($_POST["clone"], $this->options->existingClones)) {
114
  $this->options->current = $_POST["clone"];
115
+ $this->options->currentClone = $this->options->existingClones[$this->options->current];
116
  }
117
 
118
  // Tables
138
 
139
  // Define mainJob to differentiate between cloning, updating and pushing
140
  $this->options->mainJob = 'cloning';
141
+ $job = '';
142
+ if (isset($_POST["job"])) {
143
+ $job = $_POST['job'];
144
+ }
145
 
146
+ if ($this->options->current !== null && $job === 'resetting') {
147
+ $this->options->mainJob = 'resetting';
148
+ } elseif ($this->options->current !== null) {
149
  $this->options->mainJob = 'updating';
150
  }
151
 
189
  }
190
 
191
  /**
192
+ * @param null|bool $parentChecked Is parent folder selected
193
+ * @param bool $forceDefault Default false. Set it to true,
194
+ * when default button on ui is clicked,
195
+ * to ignore previous selected option for UPDATE and RESET process.
196
+ *
197
  * @return string
198
+ *
199
+ * @todo create a template for ui
200
  */
201
+ public function directoryListing($parentChecked = null, $forceDefault = false)
202
  {
203
+ $directories = $this->directories;
 
 
 
204
  // Sort results
205
  uksort($directories, 'strcasecmp');
206
 
207
+ $excludedDirectories = [];
208
+ $extraDirectories = [];
209
+
210
+ if ($this->isUpdateOrResetJob()) {
211
+ $currentClone = json_decode(json_encode($this->options->currentClone));
212
+ $excludedDirectories = isset($currentClone->excludedDirectories) ? $currentClone->excludedDirectories : [];
213
+ $extraDirectories = isset($currentClone->extraDirectories) ? $currentClone->extraDirectories : [];
214
+ }
215
+
216
  $output = '';
217
  foreach ($directories as $name => $directory) {
218
  // Not a directory, possibly a symlink, therefore we will skip it
224
  $data = reset($directory);
225
  unset($directory[key($directory)]);
226
 
 
 
 
 
 
 
227
  $dataPath = isset($data["path"]) ? $data["path"] : '';
228
  $dataSize = isset($data["size"]) ? $data["size"] : '';
229
  $strUtils = new Strings();
230
+ $path = $strUtils->sanitizeDirectorySeparator($dataPath);
231
+ $wpRoot = $strUtils->sanitizeDirectorySeparator(ABSPATH);
232
+ $relPath = str_replace($wpRoot, '', $path);
233
+ $dirPath = '/' . $relPath;
234
 
235
  // Select all wp core folders and their sub dirs.
236
  // Unselect all other folders (default setting)
242
  strpos(strrev($path), strrev($wpRoot . "wp-includes")) === false &&
243
  strpos(strrev($path), strrev($wpRoot . "wp-content")) === false;
244
 
245
+ // make only wp-includes and wp-admin dirs not navigateable
246
+ $isNavigateable = true;
247
+ if ($strUtils->startsWith($path, $wpRoot . "wp-admin") !== false || $strUtils->startsWith($path, $wpRoot . "wp-includes") !== false) {
248
+ $isNavigateable = false;
249
+ }
250
+
251
+ $isNavigateable = $isNavigateable ? 'true' : 'false';
252
+
253
+ // class to differentiate between wp core and non core folders
254
+ $class = !$isDisabled ? self::WP_CORE_DIR : self::WP_NON_CORE_DIR;
255
 
256
  $output .= "<div class='wpstg-dir'>";
257
  $output .= "<input type='checkbox' class='wpstg-check-dir " . $class . "'";
258
 
259
+ $shouldBeChecked = $parentChecked !== null ? $parentChecked : !$isDisabled;
260
+ if (!$forceDefault && $this->isUpdateOrResetJob() && (!$this->isPathInDirectories($dirPath, $excludedDirectories))) {
261
+ $shouldBeChecked = true;
262
+ } elseif (!$forceDefault && $this->isUpdateOrResetJob()) {
263
+ $shouldBeChecked = false;
264
  }
265
 
266
+ if (!$forceDefault && $this->isUpdateOrResetJob() && $class === self::WP_NON_CORE_DIR && !$this->isPathInDirectories($relPath, $extraDirectories)) {
267
+ $shouldBeChecked = false;
 
 
 
268
  }
269
 
270
+ if ($shouldBeChecked && ($parentChecked !== false)) {
271
+ $output .= " checked";
272
+ }
273
+
274
+ $output .= " name='selectedDirectories[]' value='{$relPath}' data-scanned='false' data-navigateable='{$isNavigateable}'>";
275
 
276
  $output .= "<a href='#' class='wpstg-expand-dirs ";
277
+ if ($isDisabled) {
278
  $output .= " disabled";
279
  }
280
 
281
  $output .= "'>{$name}";
282
  $output .= "</a>";
283
+ $output .= ($this->gifLoaderPath !== '' && $isNavigateable === 'true') ? "<img src='{$this->gifLoaderPath}' class='wpstg-is-dir-loading' alt='loading' />" : "";
284
  $output .= "<span class='wpstg-size-info'>{$this->formatSize( $dataSize )}</span>";
285
  $output .= isset($this->settings->debugMode) ? "<span class='wpstg-size-info'> {$dataPath}</span>" : "";
 
 
 
 
 
 
 
286
  $output .= "</div>";
287
  }
288
 
290
  }
291
 
292
  /**
293
+ * Checks if there is enough free disk space to create staging site according to selected directories
294
  * Returns null when can't run disk_free_space function one way or another
295
+ * @param string $excludedDirectories
296
+ * @param string $extraDirectories
297
+ *
298
  * @return bool|null
299
  */
300
+ public function hasFreeDiskSpace($excludedDirectories, $extraDirectories)
301
  {
302
  if (!function_exists("disk_free_space")) {
303
  return null;
304
  }
305
 
306
+ $dirUtils = new WpDefaultDirectories();
307
+ $selectedDirectories = $dirUtils->getWpCoreDirectories();
308
+ $excludedDirectories = $dirUtils->getExcludedDirectories($excludedDirectories);
309
+
310
+ $size = 0;
311
+ // Scan WP Root path for size (only files)
312
+ $size += $this->getDirectorySizeExcludingSubdirs(ABSPATH);
313
+ // Scan selected directories for size (wp-core)
314
+ foreach ($selectedDirectories as $directory) {
315
+ if ($this->isPathInDirectories($directory, $excludedDirectories)) {
316
+ continue;
317
+ }
318
+
319
+ $size += $this->getDirectorySizeInclSubdirs($directory, $excludedDirectories);
320
+ }
321
+
322
+ if (!empty($extraDirectories) && $extraDirectories !== '') {
323
+ $extraDirectories = wpstg_urldecode(explode(ScanConst::DIRECTORIES_SEPARATOR, $extraDirectories));
324
+ foreach ($extraDirectories as $directory) {
325
+ $size += $this->getDirectorySizeInclSubdirs(ABSPATH . $directory, $excludedDirectories);
326
+ }
327
+ }
328
 
329
  $data = [
330
+ 'usedspace' => $this->formatSize($size)
331
  ];
332
 
333
  echo json_encode($data);
372
  }
373
 
374
  /**
375
+ * Get directories and main meta data about given directory path
376
+ * @param string $dirPath - Optional - Default ABSPATH
377
  */
378
+ protected function getDirectories($dirPath = ABSPATH)
379
  {
380
+ if (!is_dir($dirPath)) {
381
+ return;
382
+ }
383
 
384
+ $directories = new DirectoryIterator($dirPath);
385
 
386
  foreach ($directories as $directory) {
387
  // Not a valid directory
389
  continue;
390
  }
391
 
392
+ if ($directory->isDot()) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
393
  continue;
394
  }
395
 
396
+ $fullPath = WPStaging::getWPpath() . $path;
397
+ $size = $this->getDirectorySize($fullPath);
398
+
399
+ $this->directories[$directory->getFilename()]['metaData'] = [
400
+ "size" => $size,
401
+ "path" => $fullPath,
402
+ ];
403
  }
 
404
  }
405
 
406
  /**
410
  */
411
  protected function getPath($directory)
412
  {
 
413
  /*
414
  * Do not follow root path like src/web/..
415
  * This must be done before \SplFileInfo->isDir() is used!
416
  * Prevents open base dir restriction fatal errors
417
  */
 
418
  if (strpos($directory->getRealPath(), WPStaging::getWPpath()) !== 0) {
419
  return false;
420
  }
421
+
422
  $path = str_replace(WPStaging::getWPpath(), null, $directory->getRealPath());
423
  // Using strpos() for symbolic links as they could create nasty stuff in nix stuff for directory structures
424
  if (!$directory->isDir() || strlen($path) < 1) {
483
  /**
484
  * Get total size of a directory including all its subdirectories
485
  * @param string $dir
486
+ * @param array $excludedDirectories
487
  * @return int
488
  */
489
+ protected function getDirectorySizeInclSubdirs($dir, $excludedDirectories)
490
  {
491
  $size = 0;
492
  foreach (glob(rtrim($dir, '/') . '/*', GLOB_NOSORT) as $each) {
493
+ if (is_file($each)) {
494
+ $size += filesize($each);
495
+ continue;
496
+ }
497
+
498
+ if ($this->isPathInDirectories($each, $excludedDirectories)) {
499
+ continue;
500
+ }
501
+
502
+ $size += $this->getDirectorySizeInclSubdirs($each, $excludedDirectories);
503
  }
504
+
505
  return $size;
506
  }
507
 
508
  /**
509
+ * Get total size of a directory excluding all its subdirectories
510
+ * @param string $dir
511
+ * @return int
 
 
 
 
 
 
 
512
  */
513
+ protected function getDirectorySizeExcludingSubdirs($dir)
514
  {
515
+ $size = 0;
516
+ foreach (glob(rtrim($dir, '/') . '/*', GLOB_NOSORT) as $each) {
517
+ $size += is_file($each) ? filesize($each) : 0;
 
 
 
518
  }
519
 
520
+ return $size;
521
+ }
522
+
523
+ /**
524
+ * Is the path present is given list of directories
525
+ * @param string $path
526
+ * @param array $directories
527
+ *
528
+ * @return boolean
529
+ */
530
+ protected function isPathInDirectories($path, $directories)
531
+ {
532
+ // Check whether directory is itself is a part of excluded directories
533
+ if (in_array($path, $directories)) {
534
+ return true;
535
+ }
536
+
537
+ // Check whether directory a child of any excluded directories
538
+ $strUtils = new Strings();
539
+ foreach ($directories as $directory) {
540
+ if ($strUtils->startsWith($path, $directory . '/')) {
541
+ return true;
542
+ }
543
+ }
544
+
545
+ return false;
546
+ }
547
+
548
+ /**
549
+ * Is the current main job UPDATE or RESET
550
+ *
551
+ * @return boolean
552
+ */
553
+ protected function isUpdateOrResetJob()
554
+ {
555
+ return isset($this->options->mainJob) && ($this->options->mainJob === 'updating' || $this->options->mainJob === 'resetting');
556
  }
557
  }
Backend/Modules/Jobs/SearchReplace.php CHANGED
@@ -230,8 +230,7 @@ class SearchReplace extends CloningProcess
230
 
231
  /**
232
  * Start search replace job
233
- * @param string $new
234
- * @param string $old
235
  */
236
  private function startReplace($table)
237
  {
@@ -333,7 +332,7 @@ class SearchReplace extends CloningProcess
333
  $limit = $this->settings->querySRLimit;
334
 
335
  /// DEBUG
336
- $this->logDebug(
337
  sprintf(
338
  'SearchReplace-beforeRowsGenerator: max-memory-limit=%s; script-memory-limit=%s; memory-usage=%s; execution-time-limit=%s; running-time=%s; is-threshold=%s',
339
  $this->getMaxMemoryLimit(),
@@ -343,7 +342,7 @@ class SearchReplace extends CloningProcess
343
  $this->getRunningTime(),
344
  ($this->isThreshold() ? 'yes' : 'no')
345
  )
346
- );
347
  /// DEBUG
348
 
349
  if (defined('WPSTG_DISABLE_SEARCH_REPLACE_GENERATOR') && WPSTG_DISABLE_SEARCH_REPLACE_GENERATOR) {
@@ -466,7 +465,7 @@ class SearchReplace extends CloningProcess
466
 
467
  if (
468
  !defined('WPSTG_DISABLE_SEARCH_REPLACE_GENERATOR') ||
469
- defined('WPSTG_DISABLE_SEARCH_REPLACE_GENERATOR') && !WPSTG_DISABLE_SEARCH_REPLACE_GENERATOR
470
  ) {
471
  $this->updateJobStart($processed, $this->stagingDb, $table);
472
  }
@@ -535,26 +534,19 @@ class SearchReplace extends CloningProcess
535
  */
536
  private function isExcludedTable($table)
537
  {
538
- $excludedCustomTables = apply_filters('wpstg_clone_searchreplace_tables_exclude', []);
539
 
540
- $excludedDefaultTables = ['blogs'];
541
-
542
- // @todo remove isSearchReplaceExcluded() if SearchReplace() is made DRY and provide a simple list of excluded table names
543
- if ($this->thirdParty->isSearchReplaceExcluded($table)) {
544
- $excludedDefaultTables[] = str_replace($this->options->prefix, '', $table);
545
- }
546
-
547
- $tables = array_merge($excludedCustomTables, $excludedDefaultTables);
548
 
549
  $excludedAllTables = [];
550
  foreach ($tables as $key => $value) {
551
- $excludedAllTables[] = $this->options->prefix . $value;
552
  }
553
 
554
  if (in_array($table, $excludedAllTables)) {
555
  $this->log("DB Search & Replace: Table {$table} excluded by WP STAGING", Logger::TYPE_INFO);
556
  return true;
557
  }
 
558
  return false;
559
  }
560
 
230
 
231
  /**
232
  * Start search replace job
233
+ * @param string $table
 
234
  */
235
  private function startReplace($table)
236
  {
332
  $limit = $this->settings->querySRLimit;
333
 
334
  /// DEBUG
335
+ /* $this->logDebug(
336
  sprintf(
337
  'SearchReplace-beforeRowsGenerator: max-memory-limit=%s; script-memory-limit=%s; memory-usage=%s; execution-time-limit=%s; running-time=%s; is-threshold=%s',
338
  $this->getMaxMemoryLimit(),
342
  $this->getRunningTime(),
343
  ($this->isThreshold() ? 'yes' : 'no')
344
  )
345
+ );*/
346
  /// DEBUG
347
 
348
  if (defined('WPSTG_DISABLE_SEARCH_REPLACE_GENERATOR') && WPSTG_DISABLE_SEARCH_REPLACE_GENERATOR) {
465
 
466
  if (
467
  !defined('WPSTG_DISABLE_SEARCH_REPLACE_GENERATOR') ||
468
+ (defined('WPSTG_DISABLE_SEARCH_REPLACE_GENERATOR') && !WPSTG_DISABLE_SEARCH_REPLACE_GENERATOR)
469
  ) {
470
  $this->updateJobStart($processed, $this->stagingDb, $table);
471
  }
534
  */
535
  private function isExcludedTable($table)
536
  {
 
537
 
538
+ $tables = $this->excludedTableService->getExcludedTablesForSearchReplace();
 
 
 
 
 
 
 
539
 
540
  $excludedAllTables = [];
541
  foreach ($tables as $key => $value) {
542
+ $excludedAllTables[] = $this->options->prefix . ltrim($value, '_');
543
  }
544
 
545
  if (in_array($table, $excludedAllTables)) {
546
  $this->log("DB Search & Replace: Table {$table} excluded by WP STAGING", Logger::TYPE_INFO);
547
  return true;
548
  }
549
+
550
  return false;
551
  }
552
 
Backend/Modules/Jobs/Updating.php CHANGED
@@ -5,7 +5,9 @@ namespace WPStaging\Backend\Modules\Jobs;
5
  use WPStaging\Core\WPStaging;
6
  use WPStaging\Core\Utils\Helper;
7
  use WPStaging\Framework\Adapter\Database as DatabaseAdapter;
 
8
  use WPStaging\Framework\Database\TableService;
 
9
  use WPStaging\Framework\Utils\WpDefaultDirectories;
10
 
11
  /**
@@ -40,6 +42,11 @@ class Updating extends Job
40
  */
41
  private $mainJob;
42
 
 
 
 
 
 
43
  /**
44
  * Initialize is called in \Job
45
  */
@@ -47,6 +54,7 @@ class Updating extends Job
47
  {
48
  $this->db = WPStaging::getInstance()->get("wpdb");
49
  $this->mainJob = self::NORMAL_UPDATE;
 
50
  }
51
 
52
  /**
@@ -86,6 +94,8 @@ class Updating extends Job
86
  $this->options->includedDirectories = [];
87
  $this->options->excludedDirectories = [];
88
  $this->options->extraDirectories = [];
 
 
89
  $this->options->excludedFiles = [
90
  '.htaccess',
91
  '.DS_Store',
@@ -101,9 +111,9 @@ class Updating extends Job
101
  ];
102
 
103
  $this->options->excludedFilesFullPath = [
104
- 'wp-content' . DIRECTORY_SEPARATOR . 'db.php',
105
- 'wp-content' . DIRECTORY_SEPARATOR . 'object-cache.php',
106
- 'wp-content' . DIRECTORY_SEPARATOR . 'advanced-cache.php'
107
  ];
108
 
109
  // Define mainJob to differentiate between cloning, updating and pushing
@@ -112,11 +122,6 @@ class Updating extends Job
112
  // Job
113
  $this->options->job = new \stdClass();
114
 
115
- // This is required for reset job because Jobs/Scan was not run for reset
116
- if ($this->mainJob === self::RESET_UPDATE) {
117
- $this->options->existingClones = get_option("wpstg_existing_clones_beta", []);
118
- }
119
-
120
  // Check if clone data already exists and use that one
121
  if (isset($this->options->existingClones[$this->options->clone])) {
122
  $this->options->cloneNumber = $this->options->existingClones[$this->options->clone]['number'];
@@ -143,51 +148,32 @@ class Updating extends Job
143
 
144
  $this->isExternalDb = !(empty($this->options->databaseUser) && empty($this->options->databasePassword));
145
 
146
- // Excluded Directories TOTAL
147
- // Do not copy these folders and plugins
 
 
148
  $excludedDirectories = [
149
- WPStaging::getWPpath() . 'wp-content' . DIRECTORY_SEPARATOR . 'cache',
150
- WPStaging::getWPpath() . 'wp-content' . DIRECTORY_SEPARATOR . 'plugins' . DIRECTORY_SEPARATOR . 'wps-hide-login',
151
- WPStaging::getWPpath() . 'wp-content' . DIRECTORY_SEPARATOR . 'plugins' . DIRECTORY_SEPARATOR . 'wp-super-cache',
152
- WPStaging::getWPpath() . 'wp-content' . DIRECTORY_SEPARATOR . 'plugins' . DIRECTORY_SEPARATOR . 'peters-login-redirect',
153
  ];
154
 
155
  // Add upload folder to list of excluded directories for push if symlink option is enabled
156
  if ($this->options->uploadsSymlinked) {
157
- $wpUploadsFolder = (new WpDefaultDirectories())->getUploadsPath();
158
- $excludedDirectories[] = rtrim($wpUploadsFolder, '/\\');
159
  }
160
 
161
  $this->options->excludedDirectories = $excludedDirectories;
162
 
163
- if ($this->mainJob === self::RESET_UPDATE) {
164
- $this->setTablesForResetJob();
165
- $this->options->includedDirectories = (new WpDefaultDirectories())->getWpCoreDirectories();
166
- // Files
167
- $this->options->totalFiles = 0;
168
- $this->options->totalFileSize = 0;
169
- $this->options->copiedFiles = 0;
170
- // Job
171
- $this->options->currentJob = "PreserveDataFirstStep";
172
- $this->options->currentStep = 0;
173
- $this->options->totalSteps = 0;
174
- } else {
175
- $this->setTablesForUpdateJob();
176
- $this->setDirectoriesForUpdateJob();
177
- // Make sure it is always enabled for free version
178
- $this->options->emailsAllowed = true;
179
- if (defined('WPSTGPRO_VERSION')) {
180
- $this->options->emailsAllowed = isset($_POST['emailsAllowed']) && $_POST['emailsAllowed'] !== "false";
181
- }
182
- }
183
 
184
- $this->options->cloneDir = '';
185
- if (isset($_POST["cloneDir"]) && !empty($_POST["cloneDir"])) {
186
- $this->options->cloneDir = wpstg_urldecode(trailingslashit($_POST["cloneDir"]));
 
187
  }
188
 
 
189
  $this->options->destinationDir = $this->getDestinationDir();
190
-
191
  $this->options->cloneHostname = $this->options->destinationHostname;
192
 
193
  // Process lock state
@@ -210,22 +196,36 @@ class Updating extends Job
210
 
211
  private function setDirectoriesForUpdateJob()
212
  {
213
- $this->options->areDirectoriesIncluded = isset($_POST['areDirectoriesIncluded']) && $_POST['areDirectoriesIncluded'] === 'true';
214
-
215
- $directories = '';
216
- // Included Directories
217
- if ($this->options->areDirectoriesIncluded) {
218
- $directories = isset($_POST["includedDirectories"]) ? $_POST["includedDirectories"] : '';
219
- } else { // Get Included Directories from Excluded Directories
220
- $directories = isset($_POST["excludedDirectories"]) ? $_POST["excludedDirectories"] : '';
221
  }
222
 
223
- $this->options->includedDirectories = (new WpDefaultDirectories())->getSelectedDirectories($directories, $this->options->areDirectoriesIncluded);
 
 
 
 
224
 
 
 
 
 
225
  // Extra Directories
226
  if (isset($_POST["extraDirectories"])) {
227
- $this->options->extraDirectories = wpstg_urldecode(explode(Scan::DIRECTORIES_SEPARATOR, $_POST["extraDirectories"]));
228
  }
 
 
 
 
 
 
 
 
 
 
229
  }
230
 
231
  private function setTablesForUpdateJob()
@@ -236,25 +236,55 @@ class Updating extends Job
236
  } else {
237
  $this->options->tables = [];
238
  }
 
239
 
240
- // delete uploads folder before copying if uploads is not symlinked
241
- $this->options->deleteUploadsFolder = !$this->options->uploadsSymlinked && isset($_POST['cleanUploadsDir']) && $_POST['cleanUploadsDir'] === 'true';
242
- // should not backup uploads during update process
243
- $this->options->backupUploadsFolder = false;
244
- // clean plugins and themes dir before updating
245
- $this->options->deletePluginsAndThemes = isset($_POST['cleanPluginsThemes']) && $_POST['cleanPluginsThemes'] === 'true';
246
- // set default statuses for backup of uploads dir and cleaning of uploads, themes and plugins dirs
247
- $this->options->statusBackupUploadsDir = 'skipped';
248
- $this->options->statusContentCleaner = 'pending';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
249
  }
250
 
251
- private function setTablesForResetJob()
 
 
 
252
  {
253
  $tableService = new TableService(new DatabaseAdapter());
254
  $tables = $tableService->findTableStatusStartsWith();
255
  $tables = $tableService->getTablesName($tables->toArray());
256
- $this->options->tables = $tables;
257
- $this->options->excludedTables = [];
 
 
 
 
 
 
 
 
 
 
258
  }
259
 
260
  /**
5
  use WPStaging\Core\WPStaging;
6
  use WPStaging\Core\Utils\Helper;
7
  use WPStaging\Framework\Adapter\Database as DatabaseAdapter;
8
+ use WPStaging\Framework\Filesystem\Scanning\ScanConst;
9
  use WPStaging\Framework\Database\TableService;
10
+ use WPStaging\Framework\Utils\SlashMode;
11
  use WPStaging\Framework\Utils\WpDefaultDirectories;
12
 
13
  /**
42
  */
43
  private $mainJob;
44
 
45
+ /**
46
+ * @var WpDefaultDirectories
47
+ */
48
+ private $dirUtils;
49
+
50
  /**
51
  * Initialize is called in \Job
52
  */
54
  {
55
  $this->db = WPStaging::getInstance()->get("wpdb");
56
  $this->mainJob = self::NORMAL_UPDATE;
57
+ $this->dirUtils = new WpDefaultDirectories();
58
  }
59
 
60
  /**
94
  $this->options->includedDirectories = [];
95
  $this->options->excludedDirectories = [];
96
  $this->options->extraDirectories = [];
97
+ $this->options->excludeGlobRules = [];
98
+ $this->options->excludeSizeRules = [];
99
  $this->options->excludedFiles = [
100
  '.htaccess',
101
  '.DS_Store',
111
  ];
112
 
113
  $this->options->excludedFilesFullPath = [
114
+ $this->dirUtils->getRelativeWpContentPath(SlashMode::TRAILING_SLASH) . 'db.php',
115
+ $this->dirUtils->getRelativeWpContentPath(SlashMode::TRAILING_SLASH) . 'object-cache.php',
116
+ $this->dirUtils->getRelativeWpContentPath(SlashMode::TRAILING_SLASH) . 'advanced-cache.php'
117
  ];
118
 
119
  // Define mainJob to differentiate between cloning, updating and pushing
122
  // Job
123
  $this->options->job = new \stdClass();
124
 
 
 
 
 
 
125
  // Check if clone data already exists and use that one
126
  if (isset($this->options->existingClones[$this->options->clone])) {
127
  $this->options->cloneNumber = $this->options->existingClones[$this->options->clone]['number'];
148
 
149
  $this->isExternalDb = !(empty($this->options->databaseUser) && empty($this->options->databasePassword));
150
 
151
+ /**
152
+ * @see /WPStaging/Framework/CloningProcess/ExcludedPlugins.php to exclude plugins
153
+ * Only add other directories here
154
+ */
155
  $excludedDirectories = [
156
+ $this->dirUtils->getRelativeWpContentPath(SlashMode::BOTH_SLASHES) . 'cache',
 
 
 
157
  ];
158
 
159
  // Add upload folder to list of excluded directories for push if symlink option is enabled
160
  if ($this->options->uploadsSymlinked) {
161
+ $excludedDirectories[] = $this->dirUtils->getRelativeUploadPath(SlashMode::LEADING_SLASH);
 
162
  }
163
 
164
  $this->options->excludedDirectories = $excludedDirectories;
165
 
166
+ $this->setTablesForUpdateJob();
167
+ $this->setDirectoriesForUpdateJob();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
168
 
169
+ // Make sure it is always enabled for free version
170
+ $this->options->emailsAllowed = true;
171
+ if (defined('WPSTGPRO_VERSION')) {
172
+ $this->options->emailsAllowed = isset($_POST['emailsAllowed']) && $_POST['emailsAllowed'] !== "false";
173
  }
174
 
175
+ $this->options->cloneDir = $this->options->existingClones[$this->options->clone]['path'];
176
  $this->options->destinationDir = $this->getDestinationDir();
 
177
  $this->options->cloneHostname = $this->options->destinationHostname;
178
 
179
  // Process lock state
196
 
197
  private function setDirectoriesForUpdateJob()
198
  {
199
+ // Exclude Glob Rules
200
+ $this->options->excludeGlobRules = [];
201
+ if (isset($_POST["excludeGlobRules"]) && !empty($_POST["excludeGlobRules"])) {
202
+ $this->options->excludeGlobRules = wpstg_urldecode(explode(',', $_POST["excludeGlobRules"]));
 
 
 
 
203
  }
204
 
205
+ // Exclude File Size Rules
206
+ $this->options->excludeSizeRules = [];
207
+ if (isset($_POST["excludeSizeRules"]) && !empty($_POST["excludeSizeRules"])) {
208
+ $this->options->excludeSizeRules = wpstg_urldecode(explode(',', $_POST["excludeSizeRules"]));
209
+ }
210
 
211
+ // Excluded Directories
212
+ $excludedDirectoriesRequest = isset($_POST["excludedDirectories"]) ? $_POST["excludedDirectories"] : '';
213
+ $excludedDirectoriesRequest = $this->dirUtils->getExcludedDirectories($excludedDirectoriesRequest);
214
+ $this->options->excludedDirectories = array_merge($this->options->excludedDirectories, $excludedDirectoriesRequest);
215
  // Extra Directories
216
  if (isset($_POST["extraDirectories"])) {
217
+ $this->options->extraDirectories = explode(ScanConst::DIRECTORIES_SEPARATOR, wpstg_urldecode($_POST["extraDirectories"]));
218
  }
219
+
220
+ // delete uploads folder before copying if uploads is not symlinked
221
+ $this->options->deleteUploadsFolder = !$this->options->uploadsSymlinked && isset($_POST['cleanUploadsDir']) && $_POST['cleanUploadsDir'] === 'true';
222
+ // should not backup uploads during update process
223
+ $this->options->backupUploadsFolder = false;
224
+ // clean plugins and themes dir before updating
225
+ $this->options->deletePluginsAndThemes = isset($_POST['cleanPluginsThemes']) && $_POST['cleanPluginsThemes'] === 'true';
226
+ // set default statuses for backup of uploads dir and cleaning of uploads, themes and plugins dirs
227
+ $this->options->statusBackupUploadsDir = 'skipped';
228
+ $this->options->statusContentCleaner = 'pending';
229
  }
230
 
231
  private function setTablesForUpdateJob()
236
  } else {
237
  $this->options->tables = [];
238
  }
239
+ }
240
 
241
+ /**
242
+ * @param bool $preserveExcludes
243
+ */
244
+ private function setDirectoriesForResetJob($preserveExcludes = false)
245
+ {
246
+ $wpDirectories = new WpDefaultDirectories();
247
+ $coreDirectories = $wpDirectories->getWpCoreDirectories();
248
+
249
+ if ($preserveExcludes) {
250
+ $this->options->includedDirectories = $coreDirectories;
251
+ return;
252
+ }
253
+
254
+ $existingClone = $this->options->existingClones[$this->options->clone];
255
+ $this->options->includedDirectories = [];
256
+ foreach ($coreDirectories as $coreDir) {
257
+ if (in_array($coreDir, $existingClone['includedDirectories'])) {
258
+ $this->options->includedDirectories[] = $coreDir;
259
+ }
260
+ }
261
+
262
+ $this->options->excludedDirectories = $existingClone['excludedDirectories'];
263
+ $this->options->excludeSizeRules = $existingClone['excludeSizeRules'];
264
+ // should preserve extra directories?
265
+ // $this->options->extraDirectories = $existingClone['extraDirectories'];
266
  }
267
 
268
+ /**
269
+ * @param bool $preserveExcludes
270
+ */
271
+ private function setTablesForResetJob($preserveExcludes = false)
272
  {
273
  $tableService = new TableService(new DatabaseAdapter());
274
  $tables = $tableService->findTableStatusStartsWith();
275
  $tables = $tableService->getTablesName($tables->toArray());
276
+ if ($preserveExcludes) {
277
+ $this->options->tables = $tables;
278
+ return;
279
+ }
280
+
281
+ $selectedTables = $this->options->existingClones[$this->options->clone]["includedTables"];
282
+ $this->options->tables = [];
283
+ foreach ($tables as $table) {
284
+ if (in_array($table, $selectedTables)) {
285
+ $this->options->tables[] = $table;
286
+ }
287
+ }
288
  }
289
 
290
  /**
Backend/Modules/Views/Forms/Settings.php CHANGED
@@ -3,12 +3,14 @@
3
  namespace WPStaging\Backend\Modules\Views\Forms;
4
 
5
  use WPStaging\Core\Forms\Elements\Check;
 
6
  use WPStaging\Core\Forms\Elements\Numerical;
7
  use WPStaging\Core\Forms\Elements\Select;
8
  use WPStaging\Core\Forms\Elements\SelectMultiple;
9
  use WPStaging\Core\Forms\Elements\Text;
10
  use WPStaging\Core\Forms\Form;
11
  use WPStaging\Backend\Modules\Views\Tabs\Tabs;
 
12
 
13
  /**
14
  * Class Settings
@@ -252,6 +254,16 @@ class Settings
252
  ->setDefault(isset($settings->usersWithStagingAccess) ? $settings->usersWithStagingAccess : '')
253
  );
254
  }
 
 
 
 
 
 
 
 
 
 
255
  }
256
 
257
  /**
3
  namespace WPStaging\Backend\Modules\Views\Forms;
4
 
5
  use WPStaging\Core\Forms\Elements\Check;
6
+ use WPStaging\Core\Forms\Elements\Color;
7
  use WPStaging\Core\Forms\Elements\Numerical;
8
  use WPStaging\Core\Forms\Elements\Select;
9
  use WPStaging\Core\Forms\Elements\SelectMultiple;
10
  use WPStaging\Core\Forms\Elements\Text;
11
  use WPStaging\Core\Forms\Form;
12
  use WPStaging\Backend\Modules\Views\Tabs\Tabs;
13
+ use WPStaging\Framework\Assets\Assets;
14
 
15
  /**
16
  * Class Settings
254
  ->setDefault(isset($settings->usersWithStagingAccess) ? $settings->usersWithStagingAccess : '')
255
  );
256
  }
257
+
258
+ $element = new Color(
259
+ "wpstg_settings[adminBarColor]",
260
+ []
261
+ );
262
+
263
+ $this->form["general"]->add(
264
+ $element->setLabel(__("Admin Bar Background Color", "wp-staging"))
265
+ ->setDefault((isset($settings->adminBarColor)) ? $settings->adminBarColor : Assets::DEFAULT_ADMIN_BAR_BG)
266
+ );
267
  }
268
 
269
  /**
Backend/views/clone/ajax/exclude-settings.php ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ <?php
3
+ /**
4
+ * @see \WPStaging\Backend\Administrator::ajaxCloneExcludeSettings Context where this is included.
5
+ *
6
+ * @var stdClass $options
7
+ *
8
+ * @see \WPStaging\Backend\Modules\Jobs\Scan::start For details on $options.
9
+ */
10
+ ?>
11
+
12
+
13
+ <div>
14
+ <h1 class="wpstg-m-0 wpstg-mt-10px"><?php _e('RESET CLONE'); ?></h1>
15
+ <p><?php _e('Do you really want to reset this staging site with the current state of the production site? The original selection for tables and files have been preselected. You can adjust and verify them before starting the reset.', 'wp-staging'); ?></p>
16
+ <p class="wpstg--modal--process--msg--critical"><?php _e('This will delete all your modifications!', 'wp-staging'); ?></p>
17
+ <div class="wpstg-tabs-wrapper" style="text-align: left;">
18
+ <a href="#" class="wpstg-tab-header wpstg-reset-exclude-tab" data-id="#wpstg-reset-excluded-tables" data-collapsed="true">
19
+ <span class="wpstg-tab-triangle">&#9658;</span>
20
+ <?php _e("Selected Tables", "wp-staging") ?>
21
+ </a>
22
+
23
+ <fieldset class="wpstg-tab-section" id="wpstg-reset-excluded-tables">
24
+ <?php require(WPSTG_PLUGIN_DIR . 'Backend/views/selections/database-tables.php'); ?>
25
+ </fieldset>
26
+
27
+ <a href="#" class="wpstg-tab-header wpstg-reset-exclude-tab" data-id="#wpstg-reset-excluded-files" data-collapsed="true">
28
+ <span class="wpstg-tab-triangle">&#9658;</span>
29
+ <?php _e("Selected Files", "wp-staging") ?>
30
+ </a>
31
+
32
+ <fieldset class="wpstg-tab-section" id="wpstg-reset-excluded-files">
33
+ <?php require(WPSTG_PLUGIN_DIR . 'Backend/views/selections/files.php'); ?>
34
+ </fieldset>
35
+ </div>
36
+ </div>
37
+
Backend/views/clone/ajax/scan.php CHANGED
@@ -5,6 +5,7 @@
5
  *
6
  * @var \WPStaging\Backend\Modules\Jobs\Scan $scan
7
  * @var stdClass $options
 
8
  *
9
  * @see \WPStaging\Backend\Modules\Jobs\Scan::start For details on $options.
10
  */
@@ -33,37 +34,7 @@
33
  </a>
34
 
35
  <fieldset class="wpstg-tab-section" id="wpstg-scanning-db">
36
- <?php do_action("wpstg_scanning_db") ?>
37
- <h4 style="margin:0">
38
- <p><?php printf(__("Select the tables to copy. Tables beginning with the prefix '%s' have already been selected.", "wp-staging"), $db->prefix); ?></p>
39
- <p></p>
40
- <?php
41
- echo __(
42
- "Select multiple tables by pressing left mouse button and moving or by pressing STRG+Left Mouse button. (Mac ⌘+Left Mouse Button)",
43
- "wp-staging"
44
- );
45
- ?>
46
- </h4>
47
- <div style="margin-top:10px;margin-bottom:10px;">
48
- <a href="#" class="wpstg-button-unselect button"><?php _e('Unselect All', 'wp-staging'); ?></a>
49
- <a href="#" class="wpstg-button-select button"> <?php _e(WPStaging\Core\WPStaging::getTablePrefix(), 'wp-staging'); ?> </a>
50
- </div>
51
- <select multiple="multiple" id="wpstg_select_tables_cloning">
52
- <?php
53
- foreach ($options->tables as $table) :
54
- $attributes = !in_array($table->name, $options->excludedTables) && (strpos($table->name, $db->prefix) === 0) ? "selected='selected'" : "";
55
- $attributes .= in_array($table->name, $options->clonedTables) ? "disabled" : '';
56
- ?>
57
- <option class="wpstg-db-table" value="<?php echo $table->name ?>" name="<?php echo $table->name ?>" <?php echo $attributes ?>>
58
- <?php echo $table->name ?> - <?php echo $scan->formatSize($table->size) ?>
59
- </option>
60
- <?php endforeach ?>
61
- </select>
62
-
63
- <div style="margin-top:10px;">
64
- <a href="#" class="wpstg-button-unselect button"> <?php _e('Unselect All', 'wp-staging'); ?> </a>
65
- <a href="#" class="wpstg-button-select button"> <?php _e(WPStaging\Core\WPStaging::getTablePrefix(), 'wp-staging'); ?> </a>
66
- </div>
67
  </fieldset>
68
 
69
  <a href="#" class="wpstg-tab-header" data-id="#wpstg-scanning-files">
@@ -72,38 +43,7 @@
72
  </a>
73
 
74
  <fieldset class="wpstg-tab-section" id="wpstg-scanning-files">
75
- <h4 style="margin:0">
76
- <?php echo __("Select folders to copy. Click on folder name to list subfolders!", "wp-staging") ?>
77
- </h4>
78
-
79
- <?php echo $scan->directoryListing() ?>
80
-
81
- <h4 style="margin:10px 0 10px 0">
82
- <?php echo __("Extra directories to copy", "wp-staging") ?>
83
- </h4>
84
-
85
- <textarea id="wpstg_extraDirectories" name="wpstg_extraDirectories" style="width:100%;height:100px;"></textarea>
86
- <p>
87
- <span>
88
- <?php
89
- echo __(
90
- "Enter one folder path per line.<br>" .
91
- "Folders must start with absolute path: " . $options->root,
92
- "wp-staging"
93
- )
94
- ?>
95
- </span>
96
- </p>
97
-
98
- <p>
99
- <span>
100
- <?php
101
- if (isset($options->clone)) {
102
- echo __("All files will be copied to: ", "wp-staging") . $options->root . $options->clone;
103
- }
104
- ?>
105
- </span>
106
- </p>
107
  </fieldset>
108
 
109
  <a href="#" class="wpstg-tab-header" data-id="#wpstg-advanced-settings">
5
  *
6
  * @var \WPStaging\Backend\Modules\Jobs\Scan $scan
7
  * @var stdClass $options
8
+ * @var \WPStaging\Framework\Filesystem\Filters\ExcludeFilter $excludeUtils
9
  *
10
  * @see \WPStaging\Backend\Modules\Jobs\Scan::start For details on $options.
11
  */
34
  </a>
35
 
36
  <fieldset class="wpstg-tab-section" id="wpstg-scanning-db">
37
+ <?php require(WPSTG_PLUGIN_DIR . 'Backend/views/selections/database-tables.php'); ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
  </fieldset>
39
 
40
  <a href="#" class="wpstg-tab-header" data-id="#wpstg-scanning-files">
43
  </a>
44
 
45
  <fieldset class="wpstg-tab-section" id="wpstg-scanning-files">
46
+ <?php require(WPSTG_PLUGIN_DIR . 'Backend/views/selections/files.php'); ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  </fieldset>
48
 
49
  <a href="#" class="wpstg-tab-header" data-id="#wpstg-advanced-settings">
Backend/views/selections/database-tables.php ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @var stdClass $options
4
+ *
5
+ * @see \WPStaging\Backend\Modules\Jobs\Scan::start For details on $options.
6
+ */
7
+ ?>
8
+ <?php
9
+ do_action("wpstg_scanning_db");
10
+ $dbPrefix = WPStaging\Core\WPStaging::getTablePrefix();
11
+ ?>
12
+ <h4 class="wpstg-m-0">
13
+ <?php printf(__("Select the tables to copy. Tables beginning with the prefix '%s' have been preselected.", "wp-staging"), $dbPrefix); ?>
14
+ </h4>
15
+ <p>
16
+ <?php _e("All selected tables will be copied/replaced with the tables from the production site.", "wp-staging"); ?>
17
+ </p>
18
+ <div class="wpstg-my-10px">
19
+ <a href="#" class="wpstg-button-unselect button"><?php _e('Unselect All', 'wp-staging'); ?></a>
20
+ <a href="#" class="wpstg-button-select button"> <?php echo $dbPrefix ?> </a>
21
+ </div>
22
+ <select multiple="multiple" id="wpstg_select_tables_cloning">
23
+ <?php
24
+ foreach ($options->tables as $table) :
25
+ $attributes = !in_array($table->name, $options->excludedTables) && (strpos($table->name, $dbPrefix) === 0) ? "selected='selected'" : "";
26
+ if (($options->mainJob === 'updating' || $options->mainJob === 'resetting') && isset($options->currentClone['includedTables'])) {
27
+ $attributes = !in_array($table->name, $options->excludedTables) && in_array($table->name, $options->currentClone['includedTables']) ? "selected='selected'" : "";
28
+ }
29
+
30
+ $attributes .= in_array($table->name, $options->clonedTables) ? "disabled" : '';
31
+ ?>
32
+ <option class="wpstg-db-table" value="<?php echo $table->name ?>" name="<?php echo $table->name ?>" <?php echo $attributes ?>>
33
+ <?php echo $table->name ?> - <?php echo size_format($table->size, 2) ?>
34
+ </option>
35
+ <?php endforeach ?>
36
+ </select>
37
+ <div class="wpstg-mt-10px">
38
+ <a href="#" class="wpstg-button-unselect button"> <?php _e('Unselect All', 'wp-staging'); ?> </a>
39
+ <a href="#" class="wpstg-button-select button"> <?php echo $dbPrefix; ?> </a>
40
+ </div>
41
+ <p>
42
+ <?php _e("You can select multiple tables by pressing left mouse button and moving or by pressing STRG+Left Mouse button. (Mac ⌘+Left Mouse Button)", "wp-staging"); ?>
43
+ </p>
Backend/views/selections/files.php ADDED
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @var stdClass $options
4
+ *
5
+ * @see \WPStaging\Backend\Modules\Jobs\Scan::start For details on $options.
6
+ */
7
+ ?>
8
+ <h4>
9
+ <?php _e("Select folders to copy. Click on a folder to expand subfolders!", "wp-staging") ?>
10
+ </h4>
11
+ <div id="wpstg-directories-listing" data-existing-excludes="<?php echo (($options->mainJob === 'updating' || $options->mainJob === 'resetting') && isset($options->currentClone['excludedDirectories'])) ? esc_html(implode(',', $options->currentClone['excludedDirectories'])) : '' ?>">
12
+ <div class="wpstg-mb-8px">
13
+ <button type="button" class="wpstg-unselect-dirs button"><?php _e('Unselect All', 'wp-staging'); ?></button>
14
+ <button type="button" class="wpstg-select-dirs-default button"> <?php _e('Select Default', 'wp-staging'); ?></button>
15
+ </div>
16
+ <?php echo $scan->directoryListing() ?>
17
+ </div>
18
+ <!-- Exclusion Rules Table -->
19
+ <div class="wpstg-excluded-filters-container" id="wpstg-exclude-filters-container">
20
+ <table>
21
+ <tbody>
22
+ <?php
23
+ $hasRules = false;
24
+ if ($options->mainJob === 'updating' || $options->mainJob === 'resetting') :
25
+ foreach ($options->currentClone['excludeSizeRules'] as $rule) :
26
+ $hasRules = true;
27
+ echo $excludeUtils->renderSizeExclude($rule);
28
+ endforeach;
29
+ foreach ($options->currentClone['excludeGlobRules'] as $rule) :
30
+ $hasRules = true;
31
+ echo $excludeUtils->renderGlobExclude($rule);
32
+ endforeach;
33
+ endif; ?>
34
+ </tbody>
35
+ </table>
36
+ <p <?php echo !$hasRules ? 'style="display: none;"' : '' ?> class="wpstg-has-exclude-rules"><b><?php _e('Note', 'wp-staging'); ?>:</b> <?php _e('These rules will not affect wp-admin and wp-includes directories!', 'wp-staging')?></p>
37
+ <div class="wpstg-exclude-filters-foot">
38
+ <div class="wpstg-dropdown wpstg-exclude-filter-dropdown">
39
+ <button class="wpstg-dropdown-toggler transparent">
40
+ <?php _e("Add Exclude Rule", "wp-staging"); ?> <span class="wpstg-dropdown-symbol">+</span>
41
+ </button>
42
+ <div class="wpstg-dropdown-menu wpstg-menu-dropup">
43
+ <button class="wpstg-dropdown-action wpstg-file-size-rule"><?php _e('File Size', 'wp-staging'); ?></button>
44
+ <button class="wpstg-dropdown-action wpstg-file-ext-rule"><?php _e('File Extension', 'wp-staging'); ?></button>
45
+ <button class="wpstg-dropdown-action wpstg-file-name-rule"><?php _e('File Name', 'wp-staging'); ?></button>
46
+ <button class="wpstg-dropdown-action wpstg-dir-name-rule"><?php _e('Folder Name', 'wp-staging'); ?></button>
47
+ </div>
48
+ </div>
49
+ <button <?php echo !$hasRules ? 'style="display: none;"' : '' ?> class="wpstg-ml-8px wpstg-button wpstg-clear-all-rules danger wpstg-has-exclude-rules">
50
+ <?php _e("Clear All Rules", "wp-staging"); ?>
51
+ </button>
52
+ </div>
53
+ </div>
54
+ <?php
55
+ if ($options->current !== null && $options->mainJob === 'updating') {
56
+ echo '<p>' . __("Applying an exclude rule will not effect existing files on the staging site if you don't clean up the wp-content folder before updating. Existing files will not be deleted afterwards automatically!", 'wp-staging') . '</p>';
57
+ }
58
+ ?>
59
+ <!-- End Exclusion Rules Table -->
60
+
61
+ <!-- Templates for exclusion filters. These will never be rendered until added to exclusion rule table -->
62
+ <?php unset($rule); ?>
63
+ <template id="wpstg-file-ext-exclude-filter-template">
64
+ <?php require(WPSTG_PLUGIN_DIR . 'Backend/views/templates/exclude-filters/file-ext-exclude-filter.php') ?>
65
+ </template>
66
+ <template id="wpstg-file-size-exclude-filter-template">
67
+ <?php require(WPSTG_PLUGIN_DIR . 'Backend/views/templates/exclude-filters/file-size-exclude-filter.php') ?>
68
+ </template>
69
+ <template id="wpstg-file-name-exclude-filter-template">
70
+ <?php require(WPSTG_PLUGIN_DIR . 'Backend/views/templates/exclude-filters/file-name-exclude-filter.php') ?>
71
+ </template>
72
+ <template id="wpstg-dir-name-exclude-filter-template">
73
+ <?php require(WPSTG_PLUGIN_DIR . 'Backend/views/templates/exclude-filters/dir-name-exclude-filter.php') ?>
74
+ </template>
75
+ <!-- End - Templates for exclusion filters -->
76
+
77
+ <?php if (defined('WPSTG_ALLOW_EXTRA_DIRECTORIES') && WPSTG_ALLOW_EXTRA_DIRECTORIES) { ?>
78
+ <h4 style="margin:10px 0 10px 0">
79
+ <?php echo __("Extra directories to copy", "wp-staging") ?>
80
+ </h4>
81
+
82
+ <textarea id="wpstg_extraDirectories" name="wpstg_extraDirectories" style="width:100%;height:100px;"></textarea>
83
+ <p>
84
+ <span>
85
+ <?php
86
+ echo __(
87
+ "Enter one folder path per line.<br>" .
88
+ "Folders must be relative to the path: " . $options->root,
89
+ "wp-staging"
90
+ )
91
+ ?>
92
+ </span>
93
+ </p>
94
+ <?php } ?>
95
+
96
+ <p>
97
+ <span>
98
+ <?php
99
+ if (isset($options->clone)) {
100
+ echo __("All files will be copied to: ", "wp-staging") . $options->root . $options->clone;
101
+ }
102
+ ?>
103
+ </span>
104
+ </p>
Backend/views/settings/tabs/general.php CHANGED
@@ -383,6 +383,25 @@
383
  echo $form->render("wpstg_settings[usersWithStagingAccess]") ?>
384
  </td>
385
  </tr>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
386
  <?php
387
  }
388
  ?>
383
  echo $form->render("wpstg_settings[usersWithStagingAccess]") ?>
384
  </td>
385
  </tr>
386
+ <tr class="row">
387
+ <td class="row th">
388
+ <div class="col-title">
389
+ <?php
390
+ echo $form->label("wpstg_settings[adminBarColor]") ?>
391
+ <span class="description">
392
+ <?php
393
+ _e(
394
+ 'Specify the color of staging site admin bar.</strong>',
395
+ 'wp-staging'
396
+ ); ?>
397
+ </span>
398
+ </div>
399
+ </td>
400
+ <td>
401
+ <?php
402
+ echo $form->render("wpstg_settings[adminBarColor]") ?>
403
+ </td>
404
+ </tr>
405
  <?php
406
  }
407
  ?>
Backend/views/settings/tabs/mail-settings.php CHANGED
@@ -1,20 +1,17 @@
1
  <form class="wpstg-mail-settings-form" method="post">
2
- <?php $emailsAllowed = !((bool)wpstgGetCloneSettings(\WPStaging\Framework\Staging\FirstRun::MAILS_DISABLED_KEY)); ?>
3
  <p>
4
  <strong class="wpstg-fs-14"> <?php _e('Mail Delivery Setting', 'wp-staging'); ?></strong>
5
  <br/>
6
  <?php _e('Toggle mails sending for this staging site', 'wp-staging'); ?>
7
  </p>
8
-
9
  <div class="wpstg-form-group">
10
  <label class="wpstg-checkbox" for="wpstg_allow_emails">
11
  <?php _e('Allow Mails Sending:', 'wp-staging'); ?> <input type="checkbox" name="wpstg_allow_emails" id="wpstg_allow_emails" <?php echo $emailsAllowed === true ? 'checked' : '' ?>>
12
  </label>
13
  </div>
14
-
15
  <p>
16
  <b><?php _e('Note', 'wp-staging') ?>: </b> <?php echo sprintf(__('Some plugins might still be able to send out mails if they don\'t depend upon %s.', 'wp-staging'), '<code>wp_mail()</code>', '<code>wp_mail()</code>', '<strong>WP STAGING</strong>'); ?>
17
  </p>
18
-
19
  <button type="button" id="wpstg-update-mail-settings" class="wpstg-link-btn wpstg-blue-primary"><?php _e("Update Settings", "wp-staging") ?></button>
20
  </form>
1
  <form class="wpstg-mail-settings-form" method="post">
2
+ <?php $emailsAllowed = !((bool)(new \WPStaging\Framework\Staging\CloneOptions())->get((\WPStaging\Framework\Staging\FirstRun::MAILS_DISABLED_KEY))); ?>
3
  <p>
4
  <strong class="wpstg-fs-14"> <?php _e('Mail Delivery Setting', 'wp-staging'); ?></strong>
5
  <br/>
6
  <?php _e('Toggle mails sending for this staging site', 'wp-staging'); ?>
7
  </p>
 
8
  <div class="wpstg-form-group">
9
  <label class="wpstg-checkbox" for="wpstg_allow_emails">
10
  <?php _e('Allow Mails Sending:', 'wp-staging'); ?> <input type="checkbox" name="wpstg_allow_emails" id="wpstg_allow_emails" <?php echo $emailsAllowed === true ? 'checked' : '' ?>>
11
  </label>
12
  </div>
 
13
  <p>
14
  <b><?php _e('Note', 'wp-staging') ?>: </b> <?php echo sprintf(__('Some plugins might still be able to send out mails if they don\'t depend upon %s.', 'wp-staging'), '<code>wp_mail()</code>', '<code>wp_mail()</code>', '<strong>WP STAGING</strong>'); ?>
15
  </p>
 
16
  <button type="button" id="wpstg-update-mail-settings" class="wpstg-link-btn wpstg-blue-primary"><?php _e("Update Settings", "wp-staging") ?></button>
17
  </form>
Backend/views/templates/exclude-filters/dir-name-exclude-filter.php ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use WPStaging\Framework\Filesystem\Filters\ExcludeFilter;
4
+
5
+ /**
6
+ * @var string $rule
7
+ * @var string $name
8
+ *
9
+ * @see \WPStaging\Framework\Filesystem\Filters\ExcludeFilter::renderExclude For details on $rule and $name.
10
+ */
11
+ ?>
12
+ <tr>
13
+ <td class="wpstg-exclude-filter-name-column"><?php _e('Folder Name', 'wp-staging') ?></td>
14
+ <td class="wpstg-exclude-filter-exclusion-column">
15
+ <select class="wpstg-exclude-rule-input wpstg-path-exclude-select" name="wpstgDirNameExcludeRulePos[]">
16
+ <option value="<?php echo ExcludeFilter::NAME_BEGINS_WITH ?>" <?php echo isset($rule) && $rule === ExcludeFilter::NAME_BEGINS_WITH ? 'selected' : '' ?>><?php _e('BEGINS WITH', 'wp-staging') ?></option>
17
+ <option value="<?php echo ExcludeFilter::NAME_ENDS_WITH ?>" <?php echo isset($rule) && $rule === ExcludeFilter::NAME_ENDS_WITH ? 'selected' : '' ?>><?php _e('ENDS WITH', 'wp-staging') ?></option>
18
+ <option value="<?php echo ExcludeFilter::NAME_EXACT_MATCHES ?>" <?php echo isset($rule) && $rule === ExcludeFilter::NAME_EXACT_MATCHES ? 'selected' : '' ?>><?php _e('EXACT MATCHES', 'wp-staging') ?></option>
19
+ <option value="<?php echo ExcludeFilter::NAME_CONTAINS ?>" <?php echo isset($rule) && $rule === ExcludeFilter::NAME_CONTAINS ? 'selected' : '' ?>><?php _e('CONTAINS', 'wp-staging') ?></option>
20
+ </select>
21
+ <input type="text" class="wpstg-exclude-rule-input" name="wpstgDirNameExcludeRulePath[]" value="<?php echo isset($name) ? $name : '' ?>" />
22
+ <div class="wpstg-popover">
23
+ <button class="wpstg-exclusion-rule-info" type="button">i</button>
24
+ <p class="wpstg-code-block wpstg-rule-info"><?php echo sprintf(__('Exclude folders by name. For example to exclude all folder with name node_modules, select %s and type %s in the input box.', 'wp-staging'), '<code class="wpstg-code">' . __('EXACT MATCHES', 'wp-staging') . '</code>', '<code class="wpstg-code">node_modules</code>') ?>
25
+ </p>
26
+ </div>
27
+ </td>
28
+ <td class="wpstg-exclude-filter-action-column"><button class="wpstg-remove-exclude-rule">×</button></td>
29
+ </tr>
Backend/views/templates/exclude-filters/file-ext-exclude-filter.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @var string $extension
4
+ *
5
+ * @see \WPStaging\Framework\Filesystem\Filters\ExcludeFilter::renderExclude For details on $extension.
6
+ */
7
+ ?>
8
+ <tr>
9
+ <td class="wpstg-exclude-filter-name-column"><?php _e('File Extension', 'wp-staging') ?></td>
10
+ <td class="wpstg-exclude-filter-exclusion-column">
11
+ <input type="text" name='wpstgFileExtExcludeRule[]' class="wpstg-exclude-rule-input file-ext" value="<?php echo isset($extension) ? $extension : '' ?>" />
12
+ <div class="wpstg-popover">
13
+ <button class="wpstg-exclusion-rule-info" type="button">i</button>
14
+ <p class="wpstg-code-block wpstg-rule-info"><?php echo sprintf(__('Exclude files by extension. For example to exclude zip files, type %s to exclude all zip files.', 'wp-staging'), '<code class="wpstg-code">zip</code>') ?> </p>
15
+ </div>
16
+ </td>
17
+ <td class="wpstg-exclude-filter-action-column"><button class="wpstg-remove-exclude-rule">×</button></td>
18
+ </tr>
Backend/views/templates/exclude-filters/file-name-exclude-filter.php ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use WPStaging\Framework\Filesystem\Filters\ExcludeFilter;
4
+
5
+ /**
6
+ * @var string $rule
7
+ * @var string $name
8
+ *
9
+ * @see \WPStaging\Framework\Filesystem\Filters\ExcludeFilter::renderExclude For details on $rule and $name.
10
+ */
11
+ ?>
12
+ <tr>
13
+ <td class="wpstg-exclude-filter-name-column"><?php _e('File Name', 'wp-staging') ?></td>
14
+ <td class="wpstg-exclude-filter-exclusion-column">
15
+ <select class="wpstg-exclude-rule-input wpstg-path-exclude-select" name="wpstgFileNameExcludeRulePos[]">
16
+ <option value="<?php echo ExcludeFilter::NAME_BEGINS_WITH ?>" <?php echo isset($rule) && $rule === ExcludeFilter::NAME_BEGINS_WITH ? 'selected' : '' ?>><?php _e('BEGINS WITH', 'wp-staging') ?></option>
17
+ <option value="<?php echo ExcludeFilter::NAME_ENDS_WITH ?>" <?php echo isset($rule) && $rule === ExcludeFilter::NAME_ENDS_WITH ? 'selected' : '' ?>><?php _e('ENDS WITH', 'wp-staging') ?></option>
18
+ <option value="<?php echo ExcludeFilter::NAME_EXACT_MATCHES ?>" <?php echo isset($rule) && $rule === ExcludeFilter::NAME_EXACT_MATCHES ? 'selected' : '' ?>><?php _e('EXACT MATCHES', 'wp-staging') ?></option>
19
+ <option value="<?php echo ExcludeFilter::NAME_CONTAINS ?>" <?php echo isset($rule) && $rule === ExcludeFilter::NAME_CONTAINS ? 'selected' : '' ?>><?php _e('CONTAINS', 'wp-staging') ?></option>
20
+ </select>
21
+ <input type="text" class="wpstg-exclude-rule-input" name="wpstgFileNameExcludeRulePath[]" value="<?php echo isset($name) ? $name : '' ?>" />
22
+ <div class="wpstg-popover">
23
+ <button class="wpstg-exclusion-rule-info" type="button">i</button>
24
+ <p class="wpstg-code-block wpstg-rule-info"><?php echo sprintf(__('Exclude files by name. For example to exclude all files which have %s at the end of the name, select %s and type %s in the input box.', 'wp-staging'), '<code class="wpstg-code">-class</code>', '<code class="wpstg-code">' . __('ENDS WITH', 'wp-staging') . '</code>', '<code class="wpstg-code">-class</code>') ?>
25
+ </p>
26
+ </div>
27
+ </td>
28
+ <td class="wpstg-exclude-filter-action-column"><button class="wpstg-remove-exclude-rule">×</button></td>
29
+ </tr>
Backend/views/templates/exclude-filters/file-size-exclude-filter.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use WPStaging\Framework\Filesystem\Filters\ExcludeFilter;
4
+
5
+ /**
6
+ * @var string $comparison
7
+ * @var int $bytes
8
+ * @var string $size
9
+ *
10
+ * @see \WPStaging\Framework\Filesystem\Filters\ExcludeFilter::renderSizeExclude For details on $comparison, $size and $bytes.
11
+ */
12
+ ?>
13
+ <tr>
14
+ <td class="wpstg-exclude-filter-name-column"><?php _e('File Size', 'wp-staging') ?></td>
15
+ <td class="wpstg-exclude-filter-exclusion-column">
16
+ <select class="wpstg-exclude-rule-input wpstg-file-size-exclude-select" name="wpstgFileSizeExcludeRuleCompare[]">
17
+ <option value="<?php echo ExcludeFilter::SIZE_LESS_THAN ?>" <?php echo isset($comparison) && $comparison === ExcludeFilter::SIZE_LESS_THAN ? "selected" : '' ?>><?php _e('LESS THAN', 'wp-staging') ?></option>
18
+ <option value="<?php echo ExcludeFilter::SIZE_GREATER_THAN ?>" <?php echo isset($comparison) && $comparison === ExcludeFilter::SIZE_GREATER_THAN ? "selected" : '' ?>><?php _e('GREATER THAN', 'wp-staging') ?></option>
19
+ <option value="<?php echo ExcludeFilter::SIZE_EQUAL_TO ?>" <?php echo isset($comparison) && $comparison === ExcludeFilter::SIZE_EQUAL_TO ? "selected" : '' ?>><?php _e('EXACT', 'wp-staging') ?></option>
20
+ </select>
21
+ <input type="number" class="wpstg-exclude-rule-input wpstg-file-size-exclude-input" name="wpstgFileSizeExcludeRuleSize[]" <?php echo isset($bytes) ? "value='$bytes'" : '' ?> />
22
+ <select class="wpstg-exclude-rule-input wpstg-file-size-exclude-select-small" name="wpstgFileSizeExcludeRuleByte[]">
23
+ <option value="<?php echo ExcludeFilter::SIZE_KB ?>" <?php echo isset($size) && strpos($size, ExcludeFilter::SIZE_KB) !== false ? "selected" : '' ?>>KB</option>
24
+ <option value="<?php echo ExcludeFilter::SIZE_MB ?>" <?php echo isset($size) && strpos($size, ExcludeFilter::SIZE_MB) !== false ? "selected" : '' ?>>MB</option>
25
+ <option value="<?php echo ExcludeFilter::SIZE_GB ?>" <?php echo isset($size) && strpos($size, ExcludeFilter::SIZE_GB) !== false ? "selected" : '' ?>>GB</option>
26
+ </select>
27
+ <div class="wpstg-popover">
28
+ <button class="wpstg-exclusion-rule-info" type="button">i</button>
29
+ <p class="wpstg-code-block wpstg-rule-info"><?php echo sprintf(__('Exclude files by size. For example to exclude files greater than 10 MB, select %s and type %s in next input box and select %s.', 'wp-staging'), '<code class="wpstg-code">' . __('GREATER THAN', 'wp-staging') . '</code>', '<code class="wpstg-code">10</code>', '<code class="wpstg-code">MB</code>') ?>
30
+ </p>
31
+ </div>
32
+ </td>
33
+ <td class="wpstg-exclude-filter-action-column"><button class="wpstg-remove-exclude-rule">×</button></td>
34
+ </tr>
Core/CoreServiceProvider.php ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Handles the registration of the plugin Core services.
5
+ *
6
+ * @package WPStaging\Core
7
+ */
8
+
9
+ namespace WPStaging\Core;
10
+
11
+ use WPStaging\Vendor\Psr\Log\LoggerInterface;
12
+ use WPStaging\Core\Utils\Logger;
13
+ use WPStaging\Framework\BackgroundProcessing\BackgroundProcessingServiceProvider;
14
+ use WPStaging\Framework\DI\ServiceProvider;
15
+
16
+ /**
17
+ * Class CoreServiceProvider
18
+ *
19
+ * @package WPStaging\Core
20
+ */
21
+ class CoreServiceProvider extends ServiceProvider
22
+ {
23
+ /**
24
+ * Register the plugin core Services.
25
+ *
26
+ * @since TBD
27
+ *
28
+ */
29
+ public function register()
30
+ {
31
+ $this->registerEarlyBindings();
32
+ }
33
+
34
+ /**
35
+ * Registers a set of bindings and service providers that could be required before
36
+ * booting the service provider.
37
+ */
38
+ private function registerEarlyBindings()
39
+ {
40
+ $this->container->bind(LoggerInterface::class, Logger::class);
41
+ }
42
+
43
+
44
+ /**
45
+ * Binds and sets up implementations at boot time.
46
+ */
47
+ public function boot()
48
+ {
49
+ $this->container->register(BackgroundProcessingServiceProvider::class);
50
+ }
51
+ }
Core/DTO/Settings.php CHANGED
@@ -83,6 +83,12 @@ class Settings
83
  */
84
  protected $usersWithStagingAccess = "";
85
 
 
 
 
 
 
 
86
  /**
87
  * Settings constructor.
88
  */
@@ -177,7 +183,9 @@ class Settings
177
  return $this->cpuLoad;
178
  }
179
 
180
-
 
 
181
  public function getDelayRequests()
182
  {
183
  return $this->delayRequests;
@@ -272,14 +280,35 @@ class Settings
272
  $this->debugMode = $debugMode;
273
  }
274
 
275
-
 
 
276
  public function setUserRoles($userRoles)
277
  {
278
  $this->userRoles = $userRoles;
279
  }
280
 
 
 
 
281
  public function setUsersWithStagingAccess($usersWithStagingAccess)
282
  {
283
  $this->usersWithStagingAccess = $usersWithStagingAccess;
284
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
285
  }
83
  */
84
  protected $usersWithStagingAccess = "";
85
 
86
+ /**
87
+ * Color of the admin bar in hexadecimal format
88
+ * @var string
89
+ */
90
+ protected $adminBarColor = "";
91
+
92
  /**
93
  * Settings constructor.
94
  */
183
  return $this->cpuLoad;
184
  }
185
 
186
+ /**
187
+ * @return int
188
+ */
189
  public function getDelayRequests()
190
  {
191
  return $this->delayRequests;
280
  $this->debugMode = $debugMode;
281
  }
282
 
283
+ /**
284
+ * @param array $userRoles
285
+ */
286
  public function setUserRoles($userRoles)
287
  {
288
  $this->userRoles = $userRoles;
289
  }
290
 
291
+ /**
292
+ * @param string $usersWithStagingAccess
293
+ */
294
  public function setUsersWithStagingAccess($usersWithStagingAccess)
295
  {
296
  $this->usersWithStagingAccess = $usersWithStagingAccess;
297
  }
298
+
299
+ /**
300
+ * @param string $adminBarColor
301
+ */
302
+ public function setAdminBarColor($adminBarColor)
303
+ {
304
+ $this->adminBarColor = $adminBarColor;
305
+ }
306
+
307
+ /**
308
+ * @return string
309
+ */
310
+ public function getAdminBarColor()
311
+ {
312
+ return $this->adminBarColor;
313
+ }
314
  }
Core/Forms/Elements/Color.php ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPStaging\Core\Forms\Elements;
4
+
5
+ use WPStaging\Core\Forms\Elements;
6
+
7
+ /**
8
+ * Class Color
9
+ * @package WPStaging\Core\Forms\Elements
10
+ */
11
+ class Color extends Elements
12
+ {
13
+
14
+ /**
15
+ * @return string
16
+ */
17
+ protected function prepareOutput()
18
+ {
19
+ return "<input id='{$this->getId()}' name='{$this->getName()}' type='color' {$this->prepareAttributes()} value='{$this->default}' />";
20
+ }
21
+
22
+ /**
23
+ * @return string
24
+ */
25
+ public function render()
26
+ {
27
+ return ($this->renderFile) ? @file_get_contents($this->renderFile) : $this->prepareOutput();
28
+ }
29
+ }
Core/WPStaging.php CHANGED
@@ -2,18 +2,18 @@
2
 
3
  namespace WPStaging\Core;
4
 
5
- use WPStaging\Framework\AssetServiceProvider;
6
- use WPStaging\Framework\Filesystem\DirectoryListing;
7
- use WPStaging\Framework\Filesystem\Filesystem;
8
- use WPStaging\Vendor\Psr\Log\LoggerInterface;
9
- use WPStaging\Framework\DI\Container;
10
  use WPStaging\Backend\Administrator;
11
- use WPStaging\Frontend\Frontend;
12
  use WPStaging\Core\Utils\Cache;
13
  use WPStaging\Core\Utils\Logger;
 
 
 
 
14
  use WPStaging\Framework\Permalinks\PermalinksPurge;
15
- use WPStaging\Core\Cron\Cron;
16
  use WPStaging\Framework\Staging\FirstRun;
 
 
17
 
18
  /**
19
  * Class WPStaging
@@ -56,10 +56,13 @@ final class WPStaging
56
 
57
  $this->startTime = microtime(true);
58
 
59
- // Todo: Move this to a common service Provider for both Free and Pro. Do not register anything else here.
60
- $this->container->bind(LoggerInterface::class, Logger::class);
61
 
62
  $this->loadDependencies();
 
 
 
 
63
  $this->container->register(AssetServiceProvider::class);
64
  $this->initCron();
65
  $this->cloneSiteFirstRun();
2
 
3
  namespace WPStaging\Core;
4
 
 
 
 
 
 
5
  use WPStaging\Backend\Administrator;
6
+ use WPStaging\Core\Cron\Cron;
7
  use WPStaging\Core\Utils\Cache;
8
  use WPStaging\Core\Utils\Logger;
9
+ use WPStaging\Framework\AssetServiceProvider;
10
+ use WPStaging\Framework\DI\Container;
11
+ use WPStaging\Framework\Filesystem\DirectoryListing;
12
+ use WPStaging\Framework\Filesystem\Filesystem;
13
  use WPStaging\Framework\Permalinks\PermalinksPurge;
 
14
  use WPStaging\Framework\Staging\FirstRun;
15
+ use WPStaging\Frontend\Frontend;
16
+ use WPStaging\Vendor\Psr\Log\LoggerInterface;
17
 
18
  /**
19
  * Class WPStaging
56
 
57
  $this->startTime = microtime(true);
58
 
59
+ $this->container->register(CoreServiceProvider::class);
 
60
 
61
  $this->loadDependencies();
62
+
63
+ // Boot the container after dependencies are loaded.
64
+ $this->container->boot();
65
+
66
  $this->container->register(AssetServiceProvider::class);
67
  $this->initCron();
68
  $this->cloneSiteFirstRun();
Core/thirdParty/thirdPartyCompatibility.php DELETED
@@ -1,35 +0,0 @@
1
- <?php
2
-
3
- namespace WPStaging\Core\thirdParty;
4
-
5
- /**
6
- * Methods to use for third party plugin compatibility
7
- *
8
- * @todo remove this method when src/Backend/Modules/Jobs/SearchReplace.php and
9
- * src/Backend/Pro/Modules/Jobs/SearchReplace.php are made DRY
10
- *
11
- */
12
- class thirdPartyCompatibility {
13
-
14
- /**
15
- * Define a list of tables which should not run through search & replace method
16
- * @param string table name e.g. wpsptg1_cerber_files or wpstgtmp_4_cerber_files
17
- * @return boolean
18
- */
19
- public function isSearchReplaceExcluded( $table ) {
20
- $excludedTables = [
21
- '_cerber_files', // Cerber Security Plugin
22
- '_cerber_sets', // Cerber Security Plugin
23
- ];
24
-
25
- $excludedTables = apply_filters( 'wpstg_searchreplace_excl_tables', $excludedTables );
26
-
27
- foreach ( $excludedTables as $excludedTable ) {
28
- if( strpos( $table, $excludedTable ) !== false ) {
29
- return true;
30
- }
31
- }
32
- return false;
33
- }
34
-
35
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Framework/Adapter/Database/InterfaceDatabaseClient.php CHANGED
@@ -68,4 +68,25 @@ interface InterfaceDatabaseClient
68
  * @return void
69
  */
70
  public function freeResult($result);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
  }
68
  * @return void
69
  */
70
  public function freeResult($result);
71
+
72
+ /**
73
+ * Returns the AUTO-INCREMENT value of the last insterted row.
74
+ *
75
+ * @return int The value of the auto-increment column of the last
76
+ * inserted row.
77
+ */
78
+ public function insertId();
79
+
80
+ /**
81
+ * Returns the number of rows found in the last query before a
82
+ * limit is applied to it.
83
+ *
84
+ * Note: this method uses the `FOUND_ROWS()` MySQL function to retrieve
85
+ * this information: read the MySQL function documentation to understand
86
+ * the result and the conditions applying to it.
87
+ *
88
+ * @return int The number of rows found in the last query before any limit
89
+ * is applied to it.
90
+ */
91
+ public function foundRows();
92
  }
Framework/Adapter/Database/MysqlAdapter.php CHANGED
@@ -112,4 +112,22 @@ class MysqlAdapter implements InterfaceDatabaseClient
112
 
113
  return null;
114
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115
  }
112
 
113
  return null;
114
  }
115
+
116
+ /**
117
+ * {@inheritdoc}
118
+ */
119
+ public function insertId()
120
+ {
121
+ // phpcs:ignore PHPCompatibility.Extensions.RemovedExtensions.mysql_DeprecatedRemoved
122
+ return mysql_insert_id($this->link);
123
+ }
124
+
125
+ /**
126
+ * {@inheritdoc}
127
+ */
128
+ public function foundRows()
129
+ {
130
+ // phpcs:ignore PHPCompatibility.Extensions.RemovedExtensions.mysql_DeprecatedRemoved
131
+ return mysql_affected_rows($this->link);
132
+ }
133
  }
Framework/Adapter/Database/MysqliAdapter.php CHANGED
@@ -110,4 +110,20 @@ class MysqliAdapter implements InterfaceDatabaseClient
110
 
111
  return null;
112
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113
  }
110
 
111
  return null;
112
  }
113
+
114
+ /**
115
+ * {@inheritdoc}
116
+ */
117
+ public function insertId()
118
+ {
119
+ return mysqli_insert_id($this->link);
120
+ }
121
+
122
+ /**
123
+ * {@inheritdoc}
124
+ */
125
+ public function foundRows()
126
+ {
127
+ return mysqli_affected_rows($this->link);
128
+ }
129
  }
Framework/Adapter/Maintenance.php CHANGED
@@ -11,7 +11,7 @@ class Maintenance
11
 
12
  public function isMaintenance()
13
  {
14
- return (new Filesystem())->exists($this->findMaintenanceFilePath());
15
  }
16
 
17
  public function enableMaintenance($isMaintenance)
11
 
12
  public function isMaintenance()
13
  {
14
+ return file_exists($this->findMaintenanceFilePath());
15
  }
16
 
17
  public function enableMaintenance($isMaintenance)
Framework/Assets/Assets.php CHANGED
@@ -2,14 +2,21 @@
2
 
3
  namespace WPStaging\Framework\Assets;
4
 
5
- use WPStaging\Backend\Modules\Jobs\Scan;
6
  use WPStaging\Core\DTO\Settings;
7
  use WPStaging\Core\WPStaging;
 
 
8
  use WPStaging\Framework\Security\AccessToken;
9
  use WPStaging\Framework\Security\Nonce;
10
 
11
  class Assets
12
  {
 
 
 
 
 
 
13
  private $accessToken;
14
 
15
  private $settings;
@@ -65,7 +72,8 @@ class Assets
65
  */
66
  public function getAssetsVersion($assetsFile, $assetsVersion = '')
67
  {
68
- $filemtime = @filemtime($this->getAssetsPath($assetsFile));
 
69
 
70
  if ($filemtime !== false) {
71
  return $filemtime;
@@ -80,20 +88,21 @@ class Assets
80
  */
81
  public function enqueueElements($hook)
82
  {
 
83
  // Load this css file on frontend and backend on all pages if current site is a staging site
84
  if (wpstg_is_stagingsite()) {
85
- $asset = 'css/src/frontend/wpstg-admin-bar.css';
86
- wp_enqueue_style(
87
- "wpstg-admin-bar",
88
- $this->getAssetsUrl($asset),
89
- [],
90
- $this->getAssetsVersion($asset)
91
- );
92
  }
93
 
94
  // Load js file on page plugins.php in free version only
95
  if (!defined('WPSTGPRO_VERSION') && $this->isPluginsPage()) {
96
- $asset = 'js/dist/wpstg-admin-plugins.js';
 
 
 
 
97
  wp_enqueue_script(
98
  "wpstg-admin-script",
99
  $this->getAssetsUrl($asset),
@@ -102,7 +111,11 @@ class Assets
102
  false
103
  );
104
 
105
- $asset = 'css/src/wpstg-admin-feedback.css';
 
 
 
 
106
  wp_enqueue_style(
107
  "wpstg-admin-feedback",
108
  $this->getAssetsUrl($asset),
@@ -116,7 +129,11 @@ class Assets
116
  }
117
 
118
  // Load admin js files
119
- $asset = 'js/dist/wpstg-admin.js';
 
 
 
 
120
  wp_enqueue_script(
121
  "wpstg-admin-script",
122
  $this->getAssetsUrl($asset),
@@ -126,7 +143,11 @@ class Assets
126
  );
127
 
128
  // Load admin js files
129
- $asset = 'js/dist/wpstg-legacy-database.js';
 
 
 
 
130
  wp_enqueue_script(
131
  "wpstg-legacy-database",
132
  $this->getAssetsUrl($asset),
@@ -172,7 +193,11 @@ class Assets
172
 
173
  // Load admin js pro files
174
  if (defined('WPSTGPRO_VERSION')) {
175
- $asset = 'js/dist/pro/wpstg-admin-pro.js';
 
 
 
 
176
  wp_enqueue_script(
177
  "wpstg-admin-pro-script",
178
  $this->getAssetsUrl($asset),
@@ -183,7 +208,11 @@ class Assets
183
  }
184
 
185
  // Load admin css files
186
- $asset = 'css/src/wpstg-admin.css';
 
 
 
 
187
  wp_enqueue_style(
188
  "wpstg-admin",
189
  $this->getAssetsUrl($asset),
@@ -196,21 +225,27 @@ class Assets
196
 
197
  wp_localize_script("wpstg-admin-script", "wpstg", [
198
  "delayReq" => $this->getDelay(),
 
199
  "settings" => (object)[
200
- "directorySeparator" => Scan::DIRECTORIES_SEPARATOR,
201
  ],
202
  "tblprefix" => WPStaging::getTablePrefix(),
203
  "isMultisite" => is_multisite(),
204
  AccessToken::REQUEST_KEY => (string)$this->accessToken->getToken() ?: (string)$this->accessToken->generateNewToken(),
205
  'nonce' => wp_create_nonce(Nonce::WPSTG_NONCE),
206
  'ajaxUrl' => admin_url('admin-ajax.php'),
 
207
  // TODO: handle i18n translations through Class/Service Provider?
208
  'i18n' => [
209
  'dbConnectionSuccess' => esc_html__('Database Connection - Success', 'wp-staging'),
210
  'dbConnectionFailed' => esc_html__('Database Connection - Failed', 'wp-staging'),
211
  'somethingWentWrong' => esc_html__('Something went wrong.', 'wp-staging'),
212
- 'noImportFileFound' => esc_html__('No import file found.', 'wp-staging'),
213
- 'selectFileToImport' => esc_html__('Select file to import.', 'wp-staging'),
 
 
 
 
214
  ],
215
  ]);
216
  }
@@ -310,6 +345,11 @@ class Assets
310
  return $delay;
311
  }
312
 
 
 
 
 
 
313
  public function makeScriptsES6($tag, $handle, $source)
314
  {
315
  if ($handle === 'wpstg-admin-pro-script' || $handle === 'wpstg-admin-script') {
@@ -318,4 +358,27 @@ class Assets
318
 
319
  return $tag;
320
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
321
  }
2
 
3
  namespace WPStaging\Framework\Assets;
4
 
 
5
  use WPStaging\Core\DTO\Settings;
6
  use WPStaging\Core\WPStaging;
7
+ use WPStaging\Framework\Filesystem\Scanning\ScanConst;
8
+ use WPStaging\Framework\Filesystem\Filters\ExcludeFilter;
9
  use WPStaging\Framework\Security\AccessToken;
10
  use WPStaging\Framework\Security\Nonce;
11
 
12
  class Assets
13
  {
14
+ /**
15
+ * Default admin bar background color for staging site
16
+ * @var string
17
+ */
18
+ const DEFAULT_ADMIN_BAR_BG = "#ff8d00";
19
+
20
  private $accessToken;
21
 
22
  private $settings;
72
  */
73
  public function getAssetsVersion($assetsFile, $assetsVersion = '')
74
  {
75
+ $filename = $this->getAssetsPath($assetsFile);
76
+ $filemtime = file_exists($filename) ? @filemtime($filename) : false;
77
 
78
  if ($filemtime !== false) {
79
  return $filemtime;
88
  */
89
  public function enqueueElements($hook)
90
  {
91
+
92
  // Load this css file on frontend and backend on all pages if current site is a staging site
93
  if (wpstg_is_stagingsite()) {
94
+ wp_register_style('wpstg-admin-bar', false);
95
+ wp_enqueue_style('wpstg-admin-bar');
96
+ wp_add_inline_style('wpstg-admin-bar', $this->getStagingAdminBarColor());
 
 
 
 
97
  }
98
 
99
  // Load js file on page plugins.php in free version only
100
  if (!defined('WPSTGPRO_VERSION') && $this->isPluginsPage()) {
101
+ $asset = 'js/dist/wpstg-admin-plugins.min.js';
102
+ if ($this->isDebugOrDevMode()) {
103
+ $asset = 'js/dist/wpstg-admin-plugins.js';
104
+ }
105
+
106
  wp_enqueue_script(
107
  "wpstg-admin-script",
108
  $this->getAssetsUrl($asset),
111
  false
112
  );
113
 
114
+ $asset = 'css/dist/wpstg-admin-feedback.min.css';
115
+ if ($this->isDebugOrDevMode()) {
116
+ $asset = 'css/dist/wpstg-admin-feedback.css';
117
+ }
118
+
119
  wp_enqueue_style(
120
  "wpstg-admin-feedback",
121
  $this->getAssetsUrl($asset),
129
  }
130
 
131
  // Load admin js files
132
+ $asset = 'js/dist/wpstg-admin.min.js';
133
+ if ($this->isDebugOrDevMode()) {
134
+ $asset = 'js/dist/wpstg-admin.js';
135
+ }
136
+
137
  wp_enqueue_script(
138
  "wpstg-admin-script",
139
  $this->getAssetsUrl($asset),
143
  );
144
 
145
  // Load admin js files
146
+ $asset = 'js/dist/wpstg-legacy-database.min.js';
147
+ if ($this->isDebugOrDevMode()) {
148
+ $asset = 'js/dist/wpstg-legacy-database.js';
149
+ }
150
+
151
  wp_enqueue_script(
152
  "wpstg-legacy-database",
153
  $this->getAssetsUrl($asset),
193
 
194
  // Load admin js pro files
195
  if (defined('WPSTGPRO_VERSION')) {
196
+ $asset = 'js/dist/pro/wpstg-admin-pro.min.js';
197
+ if ($this->isDebugOrDevMode()) {
198
+ $asset = 'js/dist/pro/wpstg-admin-pro.js';
199
+ }
200
+
201
  wp_enqueue_script(
202
  "wpstg-admin-pro-script",
203
  $this->getAssetsUrl($asset),
208
  }
209
 
210
  // Load admin css files
211
+ $asset = 'css/dist/wpstg-admin.min.css';
212
+ if ($this->isDebugOrDevMode()) {
213
+ $asset = 'css/dist/wpstg-admin.css';
214
+ }
215
+
216
  wp_enqueue_style(
217
  "wpstg-admin",
218
  $this->getAssetsUrl($asset),
225
 
226
  wp_localize_script("wpstg-admin-script", "wpstg", [
227
  "delayReq" => $this->getDelay(),
228
+ // TODO: move directorySeparator to consts?
229
  "settings" => (object)[
230
+ "directorySeparator" => ScanConst::DIRECTORIES_SEPARATOR
231
  ],
232
  "tblprefix" => WPStaging::getTablePrefix(),
233
  "isMultisite" => is_multisite(),
234
  AccessToken::REQUEST_KEY => (string)$this->accessToken->getToken() ?: (string)$this->accessToken->generateNewToken(),
235
  'nonce' => wp_create_nonce(Nonce::WPSTG_NONCE),
236
  'ajaxUrl' => admin_url('admin-ajax.php'),
237
+ 'wpstgIcon' => $this->getAssetsUrl('img/wpstaging-icon.png'),
238
  // TODO: handle i18n translations through Class/Service Provider?
239
  'i18n' => [
240
  'dbConnectionSuccess' => esc_html__('Database Connection - Success', 'wp-staging'),
241
  'dbConnectionFailed' => esc_html__('Database Connection - Failed', 'wp-staging'),
242
  'somethingWentWrong' => esc_html__('Something went wrong.', 'wp-staging'),
243
+ 'noImportFileFound' => esc_html__('No import file found.', 'wp-staging'),
244
+ 'selectFileToImport' => esc_html__('Select file to import.', 'wp-staging'),
245
+ 'cloneResetComplete' => esc_html__('Clone Reset Complete!', 'wp-staging'),
246
+ 'cloneUpdateComplete' => esc_html__('Clone Update Complete!', 'wp-staging'),
247
+ 'success' => esc_html__('Success', 'wp-staging'),
248
+ 'resetClone' => esc_html__('Reset Clone', 'wp-staging'),
249
  ],
250
  ]);
251
  }
345
  return $delay;
346
  }
347
 
348
+ /**
349
+ * @param string $tag
350
+ * @param string $handle
351
+ * @param string $source
352
+ */
353
  public function makeScriptsES6($tag, $handle, $source)
354
  {
355
  if ($handle === 'wpstg-admin-pro-script' || $handle === 'wpstg-admin-script') {
358
 
359
  return $tag;
360
  }
361
+
362
+ /**
363
+ * @return string
364
+ */
365
+ public function getStagingAdminBarColor()
366
+ {
367
+ $barColor = $this->settings->getAdminBarColor();
368
+ if (!preg_match("/#([a-f0-9]{3}){1,2}\b/i", $barColor)) {
369
+ $barColor = self::DEFAULT_ADMIN_BAR_BG;
370
+ }
371
+
372
+ return "#wpadminbar { background-color: {$barColor} !important; }";
373
+ }
374
+
375
+ /**
376
+ * Check whether app is in debug mode or in dev mode
377
+ *
378
+ * @return boolean
379
+ */
380
+ private function isDebugOrDevMode()
381
+ {
382
+ return ($this->settings->isDebugMode() || (defined('WPSTG_DEV') && WPSTG_DEV === true));
383
+ }
384
  }
Framework/BackgroundProcessing/Action.php ADDED
@@ -0,0 +1,309 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Models the information about an Action stored in the Queue.
5
+ *
6
+ * @package WPStaging\Framework\BackgroundProcessing
7
+ */
8
+
9
+ namespace WPStaging\Framework\BackgroundProcessing;
10
+
11
+ use BadMethodCallException;
12
+ use WPStaging\Framework\BackgroundProcessing\Exceptions\QueueException;
13
+
14
+ /**
15
+ * Class Action
16
+ *
17
+ * @package WPStaging\Framework\BackgroundProcessing
18
+ *
19
+ * @property int $id The Action id, the unique, auto-increment value identifying its row.
20
+ * @property string $action The action name.
21
+ * @property string $jobId The Job the action belongs to.
22
+ * @property int $priority The Action priority, lower is executed first (like WP Filters API).
23
+ * @property array $args A set of arguments for the action.
24
+ * @property string $status The current Action status in the context of the Queue.
25
+ * @property string $claimedAt The date and time, in the site timezone, the Action was last claimed for processing.
26
+ * @property string $updatedAt The date and time, in the site timezone, the Action was last updated.
27
+ */
28
+ class Action
29
+ {
30
+ use WithQueueAwareness;
31
+
32
+ /**
33
+ * The Action id, the unique, auto-increment value identifying its row.
34
+ *
35
+ * @var int
36
+ */
37
+ private $id;
38
+
39
+ /**
40
+ * The action name, it can be a string that will be processed as a WordPress action or
41
+ * another type of callable that will be called directly.
42
+ *
43
+ * @var string
44
+ */
45
+ private $action;
46
+
47
+ /**
48
+ * The name of teh Job, or Group, the Action belongs to.
49
+ *
50
+ * @var string
51
+ */
52
+ private $jobId;
53
+
54
+ /**
55
+ * The Action priority, works like the WordPress Filter API priority where
56
+ * lower values are processed first.
57
+ *
58
+ * @var int
59
+ */
60
+ private $priority;
61
+
62
+ /**
63
+ * An optional array of arguments that will be passed to either the WordPress
64
+ * action fired by the Queue or as parameters for the invoked callable.
65
+ *
66
+ * @var array<mixed>
67
+ */
68
+ private $args;
69
+
70
+ /**
71
+ * A string representing the Action status in the context of the Queue, e.g. ready
72
+ * or processing.
73
+ *
74
+ * @var string|null
75
+ */
76
+ private $status;
77
+
78
+ /**
79
+ * The string representing the date and time, in the site timezone, the Action was
80
+ * last claimed for processing.
81
+ *
82
+ * @var string|null
83
+ */
84
+ private $claimedAt;
85
+
86
+ /**
87
+ * The string representing the date and time, in the site timezone, the Action was
88
+ * last updated in any way.
89
+ *
90
+ * @var string|null
91
+ */
92
+ private $updatedAt;
93
+
94
+ /**
95
+ * Action constructor.
96
+ *
97
+ * @param int $id The Action id, its unique identifier in the Queue; `0` is a valid id
98
+ * for provisional Actions.
99
+ * @param string $action The Action name, it could be a string that will be used to fire a WP
100
+ * action, or a string in the format `<class>::<static-method>` that will
101
+ * cause that static method to be invoked directly with the Action arguments.
102
+ * @param array<mixed> $args An optional set of arguments for the Action that will either be passed to the
103
+ * invoked WP action, or to the specified static method as parameters.
104
+ * @param string $jobId The Job, or Group, the Action belongs to.
105
+ * @param int $priority The Action priority in the context of the Queue, it works like the priority of
106
+ * filters in the WordPress Filter API: lower values are processed first.
107
+ * @param string|null $status The Action status in the context of the Queue, e.g. ready or processing.
108
+ * @param string|null $claimedAt The string representing the date and time, in the site timezone, the Action was last claimed
109
+ * for processing.
110
+ * @param string|null $updatedAt The string representing the date and time, in the site timezone, the Action was last updated.
111
+ *
112
+ * @throws QueueException If any value used to build the Action is not valid.
113
+ */
114
+ public function __construct(
115
+ $id,
116
+ $action,
117
+ array $args = [],
118
+ $jobId = 'default',
119
+ $priority = 0,
120
+ $status = null,
121
+ $claimedAt = null,
122
+ $updatedAt = null
123
+ ) {
124
+ if (!is_numeric($id) && absint($id) == $id) {
125
+ throw new QueueException('Id MUST be a positive integer.');
126
+ }
127
+
128
+ if ((string)$action === '') {
129
+ throw new QueueException('Action MUST be a non-empty string.');
130
+ }
131
+
132
+ if ((string)$jobId === '') {
133
+ throw new QueueException('Job ID MUST be a non-empty string.');
134
+ }
135
+
136
+ $priority = is_numeric($priority) && (int)$priority == $priority ?
137
+ (int)$priority
138
+ : $this->getDefaultPriority();
139
+
140
+ $this->id = $id;
141
+ $this->action = $action;
142
+ $this->args = $args;
143
+ $this->jobId = $jobId;
144
+ $this->priority = $priority;
145
+ $this->status = $status;
146
+ $this->claimedAt = $claimedAt;
147
+ $this->updatedAt = $updatedAt;
148
+ }
149
+
150
+ /**
151
+ * Builds, and returns, an Action instance from the raw data found in a database row.
152
+ *
153
+ * @param array<string,mixed> $dbRow The database row, as an associative array.
154
+ *
155
+ * @return Action A reference to an Action instance built on the row data.
156
+ *
157
+ * @throws QueueException If there's any issue validating any one of the row fields.
158
+ */
159
+ public static function fromDbRow(array $dbRow)
160
+ {
161
+ $id = (int)$dbRow['id'];
162
+ $action = (string)$dbRow['action'];
163
+ $jobId = isset($dbRow['jobId']) ? (string)($dbRow['jobId']) : null;
164
+ $priority = isset($dbRow['priority']) ? (int)$dbRow['priority'] : self::getDefaultPriority();
165
+ $args = isset($dbRow['args']) ? (array)maybe_unserialize($dbRow['args']) : [];
166
+ $status = isset($dbRow['status']) ? (string)$dbRow['status'] : Queue::STATUS_READY;
167
+ $claimedAt = isset($dbRow['claimed_at']) ? (string)$dbRow['claimed_at'] : null;
168
+ $updatedAt = isset($dbRow['updated_at']) ? (string)$dbRow['updated_at'] : null;
169
+
170
+ return new self($id, $action, $args, $jobId, $priority, $status, $claimedAt, $updatedAt);
171
+ }
172
+
173
+ /**
174
+ * Overrides the magic method to get private properties with a read-only API.
175
+ *
176
+ * @param string $name The name of the property to get.
177
+ *
178
+ * @return mixed The property value.
179
+ *
180
+ * @throws BadMethodCallException If the Action does not define the property.
181
+ */
182
+ public function __get($name)
183
+ {
184
+ if (!property_exists($this, $name)) {
185
+ throw new BadMethodCallException("The Action object does not have an accessible property '{$name}'.");
186
+ }
187
+
188
+ return isset($this->{$name}) ? $this->{$name} : null;
189
+ }
190
+
191
+ /**
192
+ * Overrides the magic method to clearly signal the immutable nature of the Action object.
193
+ *
194
+ * @param string $name The name of the property to set.
195
+ * @param mixed $value The value that should be assigned to the property.
196
+ *
197
+ * @throws BadMethodCallException As Actions are immutable.
198
+ */
199
+ public function __set($name, $value)
200
+ {
201
+ throw new BadMethodCallException("The Action object is immutable: its properties can be set only when building it.");
202
+ }
203
+
204
+ /**
205
+ * Returns whether two Actions are the same in regards to relevant properties.
206
+ *
207
+ * @param Action $toCompare A reference to the Action instance this one should
208
+ * be compared to.
209
+ * @param array<string> $compareFieldsExclude A list of Action fields that should not be used in the
210
+ * comparison; by default all the Action properties will
211
+ * be used
212
+ *
213
+ * @return bool Whether this Action and the one it's being compared to are equals
214
+ * or not.
215
+ */
216
+ public function equals(Action $toCompare, array $compareFieldsExclude = [])
217
+ {
218
+ $compareFields = array_diff(
219
+ ['id', 'action', 'jobId', 'priority', 'args','status'],
220
+ $compareFieldsExclude
221
+ );
222
+
223
+ foreach ($compareFields as $prop) {
224
+ if (!$this->{$prop} == $toCompare->{$prop}) {
225
+ return false;
226
+ }
227
+ }
228
+
229
+ return true;
230
+ }
231
+
232
+ /**
233
+ * Returns the associative array representation of the Action.
234
+ *
235
+ * @return array<string,string|int|array> A map from the Action current properties
236
+ * to their current values.
237
+ */
238
+ public function toArray()
239
+ {
240
+ return [
241
+ 'id' => $this->id,
242
+ 'action' => $this->action,
243
+ 'jobId' => $this->jobId,
244
+ 'priority' => $this->priority,
245
+ 'args' => $this->args,
246
+ 'status' => $this->status,
247
+ 'claimedAt' => $this->claimedAt,
248
+ 'updatedAt' => $this->updatedAt,
249
+ ];
250
+ }
251
+
252
+ /**
253
+ * Alters the Action instance with a set of alterations. Since the Action is immutable
254
+ * alteration will produce, in fact, a clone of it that will be returned.
255
+ *
256
+ * @param array<string,mixed> $alterations An map from the alteration keys to their
257
+ * values.
258
+ *
259
+ * @return Action A reference to a modified clone of the current Action.
260
+ */
261
+ public function alter(array $alterations)
262
+ {
263
+ $clone = clone $this;
264
+
265
+ foreach ($alterations as $key => $value) {
266
+ $clone->{$key} = $value;
267
+ }
268
+
269
+ return $clone;
270
+ }
271
+
272
+ /**
273
+ * Utility method to sort Action in functions or methods accepting
274
+ * sorting callbacks like `usort`.
275
+ *
276
+ * The method will sort Actions by priority, action and jobId, in
277
+ * ascending order.
278
+ *
279
+ * @param array<string,mixed>|Action $actionOne Either an Action instance
280
+ * or the array representation of an
281
+ * Action.
282
+ * @param array<string,mixed>|Action $actionTwo Either an Action instance
283
+ * or the array representation of an
284
+ * Action.
285
+ *
286
+ * @return int An integer sticking with `usort` expected value that will return `-1`
287
+ * if the first Action comes before the second, `0` if they are equal
288
+ * in all regards and `1` if the second Action comes before the first.
289
+ */
290
+ public static function sort($actionOne, $actionTwo)
291
+ {
292
+ $objectOne = (object)$actionOne;
293
+ $objectTwo = (object)$actionTwo;
294
+
295
+ if ($objectOne->priority !== $objectTwo->priority) {
296
+ return (int)($objectOne->priority > $objectTwo->priority);
297
+ }
298
+
299
+ if ($objectOne->action !== $objectTwo->action) {
300
+ return (int)($objectOne->action > $objectTwo->action);
301
+ }
302
+
303
+ if ($objectOne->jobId !== $objectTwo->jobId) {
304
+ return (int)($objectOne->jobId > $objectTwo->jobId);
305
+ }
306
+
307
+ return 0;
308
+ }
309
+ }
Framework/BackgroundProcessing/BackgroundProcessingServiceProvider.php ADDED
@@ -0,0 +1,181 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Manages the registration and hooking of the Background Processing support feature.
5
+ *
6
+ * @package WPStaging\Framework\BackgroundProcessing
7
+ */
8
+
9
+ namespace WPStaging\Framework\BackgroundProcessing;
10
+
11
+ use WPStaging\Framework\DI\FeatureServiceProvider;
12
+
13
+ /**
14
+ * Class BackgroundProcessingServiceProvider
15
+ *
16
+ * @property \tad_DI52_Container container
17
+ * @package WPStaging\Framework\BackgroundProcessing
18
+ */
19
+ class BackgroundProcessingServiceProvider extends FeatureServiceProvider
20
+ {
21
+ /**
22
+ * {@inheritdoc}
23
+ */
24
+ public static function getFeatureTrigger()
25
+ {
26
+ return 'WPSTG_FEATURE_ENABLE_BACKGROUND_PROCESSING';
27
+ }
28
+
29
+ /**
30
+ * Registers the required Cron actions and the classes used by the feature provider.
31
+ *
32
+ * @return bool Whether the feature registration was actually done or not.
33
+ */
34
+ public function register()
35
+ {
36
+ if (!static::isEnabled()) {
37
+ return false;
38
+ }
39
+
40
+ // For caching purposes, have one single instance of the Queue around.
41
+ $this->container->singleton(Queue::class, Queue::class);
42
+ // For concurrency purposes, have one single instance of the Queue processor around.
43
+ $this->container->singleton(QueueProcessor::class, QueueProcessor::class);
44
+
45
+ $this->registerFeatureDetection();
46
+ $this->scheduleQueueMaintenance();
47
+ $this->setupQueueProcessingEntrypoints();
48
+
49
+ /// Demo -- will be removed on release.
50
+ if (isset($_REQUEST['wpstg_q_demo'])) {
51
+ $count = (max(100, (int)filter_var($_REQUEST['wpstg_q_demo'], FILTER_SANITIZE_NUMBER_INT)));
52
+ (new Demo())->run($count);
53
+ }
54
+ /// End Demo
55
+
56
+ return true;
57
+ }
58
+
59
+ /**
60
+ * Runs the Queue maintenance routines.
61
+ *
62
+ * @return void The method will not return any value.
63
+ */
64
+ public function runQueueMaintenance()
65
+ {
66
+ /** @var Queue $queue */
67
+ $queue = $this->container->make(Queue::class);
68
+
69
+ // Mark all dangling Actions as Failed.
70
+ $queue->markDanglingAs(Queue::STATUS_FAILED);
71
+ // Remove old Actions.
72
+ $queue->cleanup();
73
+ }
74
+
75
+ /**
76
+ * Schedules the Queue mainteance by means of the Cron. The Cron is not
77
+ * a really reliable method to execute timely tasks in WordPress, especially
78
+ * if not powered by a real cron, but it's fine for addressin the maintenance
79
+ * operations of the Queue that do not require to be timely and are fine happening
80
+ * when possible.
81
+ *
82
+ * @since TBD
83
+ *
84
+ */
85
+ private function scheduleQueueMaintenance()
86
+ {
87
+ // Once a day fire an action to run the Queue maintenance routines.
88
+ if (!wp_next_scheduled('wpstg_queue_maintain')) {
89
+ wp_schedule_event(time(), 'daily', 'wpstg_queue_maintain');
90
+ }
91
+
92
+ // When the action fires, run the maintenance routines.
93
+ add_action('wpstg_queue_maintain', [$this, 'runQueueMaintenance']);
94
+ }
95
+
96
+ /**
97
+ * Sets up the Queue processing entry points.
98
+ *
99
+ * The Queue, when loaded with Actions, has the potential to soak resources.
100
+ * The Queue Processor will have safeguards in place to avoid this, but we should
101
+ * be careful about the entrypoints of the queue processing to make sure it will
102
+ * process Actions only when doing that will not compromise the user experience.
103
+ * This is why we rely on side-processes that we can trigger while the main PHP process
104
+ * that is handling the user interaction with the site stays fast and snappy.
105
+ *
106
+ * @return void The method does not return any value.
107
+ */
108
+ private function setupQueueProcessingEntrypoints()
109
+ {
110
+ /**
111
+ * This is the core of how the Queue works: when the `wpstg_queue_process`, or the AJAX version of it, fires, we'll process some
112
+ * Actions.
113
+ * Setting up how we make these WordPress actions fire is what we take care of next.
114
+ */
115
+ $wpActions = [
116
+ QueueProcessor::QUEUE_PROCESS_ACTION,
117
+ 'wp_ajax_nopriv_' . QueueProcessor::QUEUE_PROCESS_ACTION,
118
+ 'wp_ajax_' . QueueProcessor::QUEUE_PROCESS_ACTION,
119
+ ];
120
+ $queueProcessorProcess = $this->container->callback(QueueProcessor::class, 'process');
121
+
122
+ foreach ($wpActions as $wpAction) {
123
+ if (!has_action($wpAction, $queueProcessorProcess)) {
124
+ add_action($wpAction, $queueProcessorProcess);
125
+ }
126
+ }
127
+
128
+ /*
129
+ * The first way we trigger the action that will make the Queue Processor process Actions is a Cron schedule.
130
+ * With full-knowledge of the fact that it will not be reliable, we still try to get some work done
131
+ * on Cron calls.
132
+ * Once every hour (kinda, it's Cron), fire the `wpstg_queue_process` action.
133
+ */
134
+ if (!wp_next_scheduled('wpstg_queue_process')) {
135
+ wp_schedule_event(time(), 'hourly', QueueProcessor::QUEUE_PROCESS_ACTION);
136
+ }
137
+
138
+ /*
139
+ * This is currently deactivated while we decide if supporting this is something we would like to do at all.
140
+ if (is_admin() && !wp_doing_ajax()) {
141
+ $ajaxAvailable = $this->container->make(FeatureDetection::class)->isAjaxAvailable(false);
142
+
143
+ if (!$ajaxAvailable) {
144
+ // add_action('shutdown', $queueProcessorProcess, -10000);
145
+ }
146
+ }
147
+ */
148
+ }
149
+
150
+ /**
151
+ * Registers the two actions that will be called by the AJAX support
152
+ * feature detection.
153
+ *
154
+ * @since TBD
155
+ */
156
+ private function registerFeatureDetection()
157
+ {
158
+ // Register the method that will handle the AJAX check.
159
+ $updateOption = $this->container->callback(FeatureDetection::class, 'updateAjaxTestOption');
160
+ // Hook on authenticated AJAX endpoint to handle the check.
161
+ add_action('wp_ajax_' . FeatureDetection::AJAX_TEST_ACTION, $updateOption);
162
+
163
+ // Once a week re-run the check.
164
+ if (!wp_next_scheduled('wpstg_q_ajax_support_feature_detection')) {
165
+ wp_schedule_event(time(), 'weekly', 'wpstg_q_ajax_support_feature_detection');
166
+ }
167
+
168
+ $runAjaxFeatureTest = $this->container->callback(FeatureDetection::class, 'runAjaxFeatureTest');
169
+ add_action('wpstg_ajax_support_feature_detection', $runAjaxFeatureTest);
170
+
171
+ // Run the test again if requested by link, e.g. from the notice.
172
+ if (
173
+ is_admin()
174
+ && filter_input(INPUT_GET, FeatureDetection::AJAX_REQUEST_QUERY_VAR, FILTER_SANITIZE_NUMBER_INT)
175
+ ) {
176
+ $runAjaxFeatureTest();
177
+ wp_redirect(remove_query_arg(FeatureDetection::AJAX_REQUEST_QUERY_VAR));
178
+ die();
179
+ }
180
+ }
181
+ }
Framework/BackgroundProcessing/Demo.php ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Runs a Queue Background Processing Demo from the browser.
5
+ *
6
+ * Go to https:<site>/?wpstg_q_demo to run the demo queueing 100 actions and close all browser windows on the site.
7
+ *
8
+ * Go to https:<site>/?wpstg_q_demo=<n> to run the demo queueing <n> actions and close all browser windows on the site.
9
+ *
10
+ * @since TBD
11
+ *
12
+ * @package WPStaging\Framework\BackgroundProcessing
13
+ */
14
+
15
+ namespace WPStaging\Framework\BackgroundProcessing;
16
+
17
+ use WPStaging\Core\WPStaging;
18
+
19
+ class Demo
20
+ {
21
+ public function run($count)
22
+ {
23
+ $queue = WPStaging::getInstance()->getContainer()->make(Queue::class);
24
+
25
+ foreach (range(1, $count) as $k) {
26
+ $queue->enqueueAction(self::class . '::' . 'writeToLog', [$k]);
27
+ error_log("Enqueued Action {$k}");
28
+ }
29
+ }
30
+
31
+ public function writeToLog($k)
32
+ {
33
+ $interval = mt_rand(0, 2);
34
+ sleep($interval);
35
+ $pid = getmypid();
36
+ error_log("Action {$k} done [PID {$pid}]!");
37
+ }
38
+ }
Framework/BackgroundProcessing/Exceptions/QueueException.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Models an exception thrown in the context of a Queue scheduling or processing.
5
+ *
6
+ * @package WPStaging\Framework\BackgroundProcessing\Exceptions
7
+ */
8
+
9
+ namespace WPStaging\Framework\BackgroundProcessing\Exceptions;
10
+
11
+ use Exception;
12
+
13
+ /**
14
+ * Class QueueException
15
+ *
16
+ * @package WPStaging\Framework\BackgroundProcessing\Exceptions
17
+ */
18
+ class QueueException extends Exception
19
+ {
20
+
21
+ }
Framework/BackgroundProcessing/FeatureDetection.php ADDED
@@ -0,0 +1,183 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Provides feature detection for the Queue system.
5
+ *
6
+ * @package WPStaging\Framework\BackgroundProcessing
7
+ */
8
+
9
+ namespace WPStaging\Framework\BackgroundProcessing;
10
+
11
+ use WP_Error;
12
+
13
+ /**
14
+ * Class FeatureDetection
15
+ *
16
+ * @package WPStaging\Framework\BackgroundProcessing
17
+ */
18
+ class FeatureDetection
19
+ {
20
+ const AJAX_TEST_ACTION = 'wpstg_ajax_test_action';
21
+ const AJAX_OPTION_NAME = 'wpstg_q_feature_detection_ajax_available';
22
+ const AJAX_REQUEST_QUERY_VAR = 'wpstg_q_ajax_check';
23
+
24
+ /**
25
+ * A cache property to store the result of the AJAX support check.
26
+ *
27
+ * @var bool
28
+ */
29
+ protected $isAjaxAvailableCache;
30
+
31
+ /**
32
+ * Returns whether the AJAX based queue processing system is available or not.
33
+ *
34
+ * @param bool $showAdminNotice Whether to show an admin notice on missing support or not.
35
+ *
36
+ * @return bool Whether the AJAX based queue processing system is available or not.
37
+ */
38
+ public function isAjaxAvailable($showAdminNotice = true)
39
+ {
40
+ if ($this->isAjaxAvailableCache === null) {
41
+ // Run this check only on Admin UI and on PHP initial state.
42
+ $notRightContext = wp_installing() || (defined('REST_REQUEST') && REST_REQUEST) || wp_doing_ajax()
43
+ || wp_doing_cron() || !is_admin();
44
+
45
+ if ($notRightContext) {
46
+ // Default to say that it's supported if we cannot exclude it.
47
+ return true;
48
+ }
49
+
50
+ $availableOptionValue = get_option(self::AJAX_OPTION_NAME, null);
51
+
52
+ if (!in_array($availableOptionValue, ['y', 'n'], true)) {
53
+ $available = $this->runAjaxFeatureTest();
54
+ $availableOptionValue = $available ? 'y' : 'n';
55
+ update_option(self::AJAX_OPTION_NAME, $availableOptionValue);
56
+ }
57
+
58
+ $this->isAjaxAvailableCache = $availableOptionValue === 'y';
59
+ }
60
+
61
+ if (!$this->isAjaxAvailableCache && $showAdminNotice) {
62
+ add_action('admin_notices', [$this, 'ajaxSupportMissingAdminNotice']);
63
+ }
64
+
65
+ return $this->isAjaxAvailableCache;
66
+ }
67
+
68
+ /**
69
+ * Runs the AJAX support feature detection test.
70
+ *
71
+ * This method will fire a non-blocking POST request
72
+ * to the `admin-ajax` endpoint.
73
+ * In response, the `updateAjaxTestOption` will udpate
74
+ * the flag option value and set it to `y` or not set it at all.
75
+ * This method will wait for some time for its counter-part, the
76
+ * `updateAjaxTestOption` running in the other request, to update
77
+ * the option. If the time runs out and the option is not there,
78
+ * the we know AJAX is either not working or not reliable enough.
79
+ * The method uses an option, and not a transient, as flag value to
80
+ * be able to force re-fetch it from the database.
81
+ *
82
+ * @return bool Whether the AJAX-based system is supported or not.
83
+ *
84
+ * @see FeatureDetection::updateAjaxTestOption()
85
+ */
86
+ public function runAjaxFeatureTest()
87
+ {
88
+ $ajaxUrl = add_query_arg([
89
+ 'action' => self::AJAX_TEST_ACTION,
90
+ '_ajax_nonce' => wp_create_nonce(self::AJAX_TEST_ACTION)
91
+ ], admin_url('admin-ajax.php'));
92
+
93
+ $hash = md5(uniqid(__CLASS__, true));
94
+
95
+ $response = wp_remote_post(esc_url_raw($ajaxUrl), [
96
+ 'headers' => [
97
+ 'X-WPSTG-Request' => self::AJAX_TEST_ACTION
98
+ ],
99
+ 'blocking' => false,
100
+ 'timeout' => 0.01,
101
+ 'cookies' => isset($_COOKIE) ? $_COOKIE : [],
102
+ 'sslverify' => apply_filters('https_local_ssl_verify', false),
103
+ 'body' => [self::AJAX_OPTION_NAME => $hash],
104
+ ]);
105
+
106
+ if ($response instanceof WP_Error) {
107
+ return false;
108
+ }
109
+
110
+ $test = static function () use ($hash) {
111
+ // Run a direct query to force the re-fetch and not hit the cache.
112
+ global $wpdb;
113
+ $fetched = $wpdb->get_var(
114
+ $wpdb->prepare(
115
+ "SELECT option_value from {$wpdb->options} WHERE option_name = %s AND option_value = 'y'",
116
+ self::AJAX_OPTION_NAME
117
+ )
118
+ );
119
+
120
+ return $fetched === 'y';
121
+ };
122
+
123
+ $waited = 0;
124
+ $waitStep = .5;
125
+ $timeout = 10;
126
+
127
+ do {
128
+ $waited += $waitStep;
129
+ sleep($waitStep);
130
+
131
+ if ($test()) {
132
+ // Look no further, it worked.
133
+ return true;
134
+ }
135
+ } while ($waited <= $timeout);
136
+
137
+ // We waited enough: either the AJAX system is not available or is not reliable.
138
+ return false;
139
+ }
140
+
141
+ /**
142
+ * Writes `y` to the feature detection option.
143
+ *
144
+ * This method will be called in response to the AJAX request
145
+ * fired by the `runAjaxFeatureTest` method.
146
+ * That method will wait, in its PHP process, for this method to
147
+ * udpate the option value and deem the AJAX support as "working".
148
+ *
149
+ * @return void The method does not return any value and will have the
150
+ * side effect of updating the option.
151
+ *
152
+ * @see FeatureDetection::runAjaxFeatureTest()
153
+ */
154
+ public function updateAjaxTestOption()
155
+ {
156
+ update_option(self::AJAX_OPTION_NAME, 'y');
157
+ }
158
+
159
+ /**
160
+ * Displays a dismissible admin notice to let the user know the BG Processing system will not
161
+ * perform at its best due to lack of AJAX support.
162
+ *
163
+ * @return void The method will have the side effect of echoing HTML to the page.
164
+ */
165
+ public function ajaxSupportMissingAdminNotice()
166
+ {
167
+ $message = __(
168
+ 'WP STAGING Background Processing system cannot use AJAX: this will prevent it from performing at its best.',
169
+ 'wp-staging'
170
+ );
171
+ $checkLink = sprintf(
172
+ '<a href="%s">%s</a>',
173
+ esc_url(admin_url('/?' . self::AJAX_REQUEST_QUERY_VAR . '=1')),
174
+ __('Click here to check again now.', 'wp-staging')
175
+ );
176
+ ?>
177
+ <div class="notice notice-warning is-dismissible wpstg__notice wpstg__notice--warning">
178
+ <p><?php echo wp_kses_post($message); ?></p>
179
+ <p><?php echo wp_kses_post($checkLink); ?></p>
180
+ </div>
181
+ <?php
182
+ }
183
+ }
Framework/BackgroundProcessing/Queue.php ADDED
@@ -0,0 +1,1075 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /** @noinspection ForgottenDebugOutputInspection */
4
+
5
+ /**
6
+ * Models the Queue of Steps to execute in background.
7
+ *
8
+ * @package WPStaging\Framework\BackgroundProcessing
9
+ */
10
+
11
+ namespace WPStaging\Framework\BackgroundProcessing;
12
+
13
+ use DateTimeImmutable;
14
+ use Exception;
15
+ use WPStaging\Core\Utils\Logger;
16
+ use WPStaging\Core\WPStaging;
17
+ use WPStaging\Framework\Adapter\Database as DatabaseAdapter;
18
+ use WPStaging\Framework\Adapter\Database\InterfaceDatabaseClient as Database;
19
+ use WPStaging\Framework\BackgroundProcessing\Exceptions\QueueException;
20
+
21
+ /**
22
+ * Class Queue
23
+ *
24
+ * @package WPStaging\Framework\BackgroundProcessing
25
+ */
26
+ class Queue
27
+ {
28
+ use WithQueueAwareness;
29
+
30
+ /**
31
+ * A set of constants that are used internally to detect the
32
+ * state of the custom table used by the class to persist and
33
+ * manage its information.
34
+ */
35
+ const TABLE_NOT_EXIST = -1;
36
+ const TABLE_EXISTS = 0;
37
+ const TABLE_CREATED = 1;
38
+
39
+ /**
40
+ * A set of constants that are used to normalize the possible status
41
+ * of an action in the context of the queue.
42
+ */
43
+ const STATUS_READY = 'ready';
44
+ const STATUS_PROCESSING = 'processing';
45
+ const STATUS_COMPLETED = 'completed';
46
+ const STATUS_FAILED = 'failed';
47
+ const STATUS_ANY = 'any';
48
+ const STATUS_CANCELED = 'canceled';
49
+ /**
50
+ * A reference to te current Background Processing Feature detection service.
51
+ *
52
+ * @var FeatureDetection
53
+ */
54
+ protected $featureDetection;
55
+
56
+ /**
57
+ * The current table state, or `null` if the current table state has never been
58
+ * assessed before.
59
+ *
60
+ * @var string|null
61
+ */
62
+ private $tableState;
63
+
64
+ /**
65
+ * A reference to the current Logger instance.
66
+ *
67
+ * @var Logger
68
+ */
69
+ private $logger;
70
+
71
+ /**
72
+ * A set of action stati that will be autoloaded in cache by the queue by default.
73
+ *
74
+ * @var array<string>
75
+ */
76
+ private $defaultHydrateStati = [self::STATUS_READY];
77
+
78
+ /**
79
+ * A map from cached actions IDs to their action fields.
80
+ *
81
+ * @var array<int,array<string,mixed>>
82
+ */
83
+ private $actionCaches = [];
84
+
85
+ /**
86
+ * A reference to the database adapter instance the class should use to interact
87
+ * with the database.
88
+ *
89
+ * @var Database
90
+ */
91
+ private $database;
92
+
93
+ /**
94
+ * Queue constructor.
95
+ *
96
+ * @param Database|null $database A reference to the database adapter instance the class
97
+ * should use to interact wit the database, or `null` to use
98
+ * the one globally provided by the Service Locator.
99
+ */
100
+ public function __construct(Database $database = null)
101
+ {
102
+ $services = WPStaging::getInstance()->getContainer();
103
+ $this->database = $database ?: $services->make(DatabaseAdapter::class)->getClient();
104
+ $this->logger = $services->make('logger');
105
+ $this->featureDetection = $services->make(FeatureDetection::class);
106
+ }
107
+
108
+ /**
109
+ * Enqueue an action to run one time, as soon as possible
110
+ *
111
+ * This is like saying, in plain English, "do_action later".
112
+ *
113
+ * @param string $action The hook to trigger, this will be the name of the
114
+ * action triggered, in the following request, by the
115
+ * WordPress `do_action` function.
116
+ * @param array<string|int,mixed>|null $args Optional arguments to pass when the hook triggers.
117
+ * @param string $jobId The ID of the Job that is enqueueing the step.
118
+ * @param int $priority The priority to enqueue the action at; this works
119
+ * exactly like WordPres filter priority: lower values, negative
120
+ * values are supported, will be executed first.
121
+ *
122
+ * @return int|false The action ID, or `false` if the action could not be queued in the
123
+ * table.
124
+ *
125
+ * @throws QueueException If there's any issue scheduling the action in the queue.
126
+ */
127
+ public function enqueueAction($action, array $args = [], $jobId = 'default', $priority = 0)
128
+ {
129
+ // We're enqueuing an Action and this is a good moment to let the user know whether AJAX works or not.
130
+ $this->featureDetection->isAjaxAvailable(true);
131
+
132
+ // Create the Action with an id of 0 until it's actually persisted.
133
+ $actionObject = new Action(0, $action, $args, $jobId, $priority);
134
+
135
+ if ($this->checkTable() === static::TABLE_NOT_EXIST) {
136
+ // The table does not exist and cannot be created, bail.
137
+ return false;
138
+ }
139
+
140
+ $assignments = [
141
+ 'action' => $actionObject->action,
142
+ 'jobId' => (string)$actionObject->jobId,
143
+ 'status' => self::STATUS_READY,
144
+ 'priority' => (int)$actionObject->priority,
145
+ 'args' => $actionObject->args,
146
+ ];
147
+
148
+ $assignmentsList = $this->buildAssignmentsList($assignments);
149
+
150
+ $tableName = self::getTableName();
151
+ $query = "INSERT INTO {$tableName} SET {$assignmentsList}";
152
+
153
+ $result = $this->database->query($query, true);
154
+
155
+ if (empty($result)) {
156
+ error_log(json_encode([
157
+ 'root' => 'Error while trying insert Action information.',
158
+ 'class' => get_class($this),
159
+ 'query' => $query,
160
+ 'error' => $this->database->error(),
161
+ ]));
162
+
163
+ return false;
164
+ }
165
+
166
+ $id = $this->database->insertId();
167
+
168
+ if (empty($id)) {
169
+ error_log(json_encode([
170
+ 'root' => 'Error while trying to fetch last inserted Action ID.',
171
+ 'class' => get_class($this),
172
+ 'query' => $query,
173
+ 'error' => $this->database->error(),
174
+ ]));
175
+
176
+ return false;
177
+ }
178
+
179
+ $actionObject = $actionObject->alter(['id' => $id, 'status' => self::STATUS_READY]);
180
+ $this->actionCaches[$id] = $actionObject->toArray();
181
+
182
+ if (!has_action('shutdown', [$this, 'maybeFireAjaxAction'])) {
183
+ add_action('shutdown', [$this, 'maybeFireAjaxAction']);
184
+ }
185
+
186
+ return (int)$id;
187
+ }
188
+
189
+ /**
190
+ * Checks and reports the state of the table.
191
+ *
192
+ * If the table does not exist, then the method will try to create or update it.
193
+ *
194
+ * @param false $force Whether to force the check on the table or trust the state
195
+ * cached from a previous check.
196
+ *
197
+ * @return int The value of one of the `TABLE` class constants to indicate the
198
+ * table status.
199
+ */
200
+ private function checkTable($force = false)
201
+ {
202
+ if (!$force && $this->tableState !== null) {
203
+ return $this->tableState;
204
+ }
205
+
206
+ $this->tableState = self::TABLE_NOT_EXIST;
207
+
208
+ $options = get_option('wpstg_settings', []);
209
+ $currentTableVersion = isset($options['queue-table-version']) ? $options['queue-table-version'] : '0.0.0';
210
+
211
+ // Trigger an update or creation if either the table should be update, or it does not exist.
212
+ if (version_compare($currentTableVersion, $this->getLatestTableVersion(), '<') || !$this->tableExists()) {
213
+ $tableState = $this->updateTable();
214
+
215
+ if ($tableState === self::TABLE_EXISTS) {
216
+ // The table now exists.
217
+ $this->tableState = self::TABLE_EXISTS;
218
+ // Just created.
219
+ return self::TABLE_CREATED;
220
+ }
221
+ }
222
+
223
+ $this->tableState = $this->tableExists() ? self::TABLE_EXISTS : self::TABLE_NOT_EXIST;
224
+
225
+ return $this->tableState;
226
+ }
227
+
228
+ /**
229
+ * Returns the latest table version.
230
+ *
231
+ * @return string The latest table version, in semantic format.
232
+ */
233
+ private function getLatestTableVersion()
234
+ {
235
+ if (defined('WPSTGPRO_VERSION')) {
236
+ return WPSTGPRO_VERSION;
237
+ }
238
+
239
+ return '1.0.0';
240
+ }
241
+
242
+ /**
243
+ * Updates the Queue table schema to the latest version, non destructively.
244
+ *
245
+ * The use of the `dbDelta` method will ensure the table is updated non-destructively
246
+ * and only if required.
247
+ *
248
+ * @return int The value of one of the `TABLE` constants to indicate the result of the
249
+ * update.
250
+ */
251
+ private function updateTable()
252
+ {
253
+ global $wpdb;
254
+ $tableSql = $this->getCreateTableSql();
255
+
256
+ require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
257
+
258
+ $lastError = $wpdb->last_error;
259
+
260
+ // If the table creation fails, then a db error will be thrown by WordPress.
261
+ dbDelta($tableSql);
262
+
263
+ if ($lastError !== $wpdb->last_error) {
264
+ return self::TABLE_NOT_EXIST;
265
+ }
266
+
267
+ $this->updateTableVersionOption($this->getLatestTableVersion());
268
+
269
+ return self::TABLE_EXISTS;
270
+ }
271
+
272
+ /**
273
+ * Returns the name of the table used by the Queue to store the actions and their state.
274
+ *
275
+ * @return string The prefixed name of the table used by the Queue to store the actions
276
+ * and their state.
277
+ */
278
+ public static function getTableName()
279
+ {
280
+ global $wpdb;
281
+
282
+ return $wpdb->prefix . 'wpstg_queue';
283
+ }
284
+
285
+ /**
286
+ * Updates the version of the table in the plugin options to make sure
287
+ * it will not be updated on next check.
288
+ *
289
+ * @param string $tableVersion A semantic version format representing the
290
+ * table version to write to the plugin options.
291
+ *
292
+ * @return void The method does not return any value and will have the
293
+ * side-effect of updating the plugin options.
294
+ */
295
+ private function updateTableVersionOption($tableVersion)
296
+ {
297
+ $options = get_option('wpstg_settings', []);
298
+ $options['queue-table-version'] = $tableVersion;
299
+ update_option('wpstg_settings', $options);
300
+ }
301
+
302
+ /**
303
+ * Checks whether the table exists or not.
304
+ *
305
+ * @return bool Whether the table exists or not.
306
+ */
307
+ private function tableExists()
308
+ {
309
+ $tableName = self::getTableName();
310
+ $this->database->query("SELECT 1 from {$tableName} LIMIT 1");
311
+
312
+ return $this->database->foundRows() === 1;
313
+ }
314
+
315
+ /**
316
+ * Returns a specific field of an action data.
317
+ *
318
+ * @param int $actionId The action ID.
319
+ * @param string $field The action field to return.
320
+ *
321
+ * @return mixed Either the action field from the specified action, or `null` if the
322
+ * action or the field cannot be found.
323
+ */
324
+ public function getActionField($actionId, $field)
325
+ {
326
+ if (empty($this->actionCaches[$actionId])) {
327
+ // Maybe this is an action that is not autoloaded due to its status.
328
+ $this->hydrateActionCaches([$actionId]);
329
+ }
330
+
331
+ return isset($this->actionCaches[$actionId][$field]) ?
332
+ $this->actionCaches[$actionId][$field]
333
+ : null;
334
+ }
335
+
336
+ /**
337
+ * Hydrates the action cache using a set of action IDs as models for the status of the
338
+ * actions to load into cache.
339
+ *
340
+ * By default, the class will hydrate the caches for actions that are running or to-run,
341
+ * skipping actions that have failed or completed.
342
+ * If a request comes in to fetch an action with a non-default status, then the cache
343
+ * for all actions with that status will be hydrated.
344
+ *
345
+ * @param array<int> $actionIds An optional set of actions to use as "mode" to
346
+ * hydrate the actions cache for all actions with that
347
+ * same type.
348
+ *
349
+ * @return void The method does not return any value and will just hydrate the class caches.
350
+ */
351
+ private function hydrateActionCaches(array $actionIds = [])
352
+ {
353
+ $tableState = $this->checkTable();
354
+
355
+ if ($tableState === self::TABLE_CREATED || $tableState === false) {
356
+ // No point in trying to fetch anything.
357
+ return;
358
+ }
359
+
360
+ $queueTable = self::getTableName();
361
+
362
+ /**
363
+ * Action arguments have the potential to be pretty huge in size.
364
+ * To avoid over-loading the database, we fetch actions from it in
365
+ * batches until we find either all the actions we're looking for, or
366
+ * all the actions of a specific type.
367
+ */
368
+
369
+ $offset = 0;
370
+ $limit = 100;
371
+ $inputActionIdsCount = count($actionIds);
372
+ $totalResultsCount = 0;
373
+
374
+ do {
375
+ $offsetAndLimit = sprintf('%d, %d', $offset, $limit);
376
+
377
+ if ($inputActionIdsCount > 0) {
378
+ $ids = implode(',', array_filter(array_map('absint', $actionIds)));
379
+ $query = "SELECT * FROM {$queueTable} q JOIN {$queueTable} q1 ON q.status = q1.status WHERE q1.id IN ({$ids}) LIMIT {$offsetAndLimit}";
380
+ } else {
381
+ $stati = implode(',', array_map(function ($status) {
382
+ return "'{$this->database->escape($status)}'";
383
+ }, $this->defaultHydrateStati));
384
+ $query = "SELECT * FROM {$queueTable} WHERE status IN ({$stati}) LIMIT {$offsetAndLimit}";
385
+ }
386
+
387
+ $result = $this->database->query($query);
388
+
389
+ if (false === $result) {
390
+ error_log(json_encode([
391
+ 'root' => 'Error while trying to fetch Actions information.',
392
+ 'class' => get_class($this),
393
+ 'query' => $query,
394
+ 'error' => $this->database->error(),
395
+ ]));
396
+
397
+ // There has been an error fetching the results, bail.
398
+ return;
399
+ }
400
+
401
+ $preparedActions = [];
402
+ while ($actionRow = $this->database->fetchAssoc($result)) {
403
+ $totalResultsCount++;
404
+ $preparedActions[$actionRow['id']] = $this->convertDbRowToData($actionRow);
405
+ }
406
+
407
+ $found = count(array_diff_key($preparedActions, array_flip($actionIds))) === $inputActionIdsCount;
408
+
409
+ if (!isset($foundRows)) {
410
+ $foundRows = max(0, (int)$this->database->foundRows());
411
+ }
412
+
413
+ $offset += $limit;
414
+ } while (!$found && $totalResultsCount < $foundRows);
415
+
416
+ $this->actionCaches = array_replace($this->actionCaches, $preparedActions);
417
+ }
418
+
419
+ /**
420
+ * Converts the data from the format it's stored with in the database to
421
+ * the typed format used to retrieve the action data.
422
+ *
423
+ * @param array<string,mixed> $actionRow The data, as fetched from the database.
424
+ *
425
+ * @return array<string,mixed> The typed and prepared action data.
426
+ */
427
+ private function convertDbRowToData(array $actionRow)
428
+ {
429
+ return Action::fromDbRow($actionRow)->toArray();
430
+ }
431
+
432
+ /**
433
+ * Tries to lock and get the next available action in the queue, in ascending
434
+ * priority order.
435
+ *
436
+ * @return Action|null Either a reference to an object representing the locked
437
+ * action, or `null` if there are no actions to process or
438
+ * no lock could be acquired on the available ones.
439
+ */
440
+ public function getNextAvailable()
441
+ {
442
+ if ($this->checkTable() !== self::TABLE_EXISTS) {
443
+ // No actions if the table either does nto exist or has just been created.
444
+ return null;
445
+ }
446
+
447
+ $processing = self::STATUS_PROCESSING;
448
+ $ready = self::STATUS_READY;
449
+ $tableName = self::getTableName();
450
+ $now = date('Y-m-d H:i:s');
451
+
452
+ /*
453
+ * Find the first available row that is ready, update its status to processing.
454
+ * Do this with an "atomic" query that will either fully accomplish its goal
455
+ * or will completely fail.
456
+ */
457
+ $claimQuery = "UPDATE {$tableName}
458
+ SET status='{$processing}', claimed_at='{$now}'
459
+ WHERE id=(
460
+ SELECT id FROM {$tableName}
461
+ WHERE status='{$ready}'
462
+ ORDER BY priority, action, jobId ASC
463
+ LIMIT 1
464
+ )
465
+ AND LAST_INSERT_ID(id);";
466
+ $claimed = $this->database->query($claimQuery, true);
467
+
468
+ if (!$claimed) {
469
+ // This is NOT a failure: it just means the process could not lock the row.
470
+ return null;
471
+ }
472
+
473
+ /*
474
+ * This we get from the `LAST_INSERT_ID(id)` statement in the atomic query.
475
+ * LAST_INSERT_ID will NOT only apply to INSERTions, but to UPDATEs too.
476
+ */
477
+ $claimedActionId = $this->database->insertId();
478
+
479
+ if (empty($claimedActionId)) {
480
+ /*
481
+ * The previous query might succeed while NOT acquiring the lock, depending
482
+ * on the db. If we have not acquired a lock, let's bail.
483
+ */
484
+ return null;
485
+ }
486
+
487
+ // Invalidate this Action cache and re-fetch the information.
488
+ unset($this->actionCaches[$claimedActionId]);
489
+ $actionObject = $this->getAction($claimedActionId);
490
+
491
+ if ($actionObject instanceof Action) {
492
+ $this->actionCaches[$claimedActionId] = $actionObject->toArray();
493
+ }
494
+
495
+ return $actionObject;
496
+ }
497
+
498
+ /**
499
+ * Counts, with a query, and returns the number of Actions currently in the Queue.
500
+ *
501
+ * @param string|array<string>|null $status An optional status, or list of stati,
502
+ * to count Actions by. If not specified, then
503
+ * the returned value will be that of all Actions
504
+ * in any status.
505
+ * @param string|array<string> $jobId An optional Job Identifier, or a list of job identifiers,
506
+ * to narrow the count by; if not provided, then
507
+ * Actions from all Jobs will be counted.
508
+ *
509
+ * @return int The number of Actions currently in the Queue, or the number of Actions
510
+ * in the Queue with a specified status.
511
+ */
512
+ public function count($status = null, $jobId = null)
513
+ {
514
+ $tableName = self::getTableName();
515
+
516
+ $jobClause = '';
517
+ if (isset($jobId)) {
518
+ $jobIdsInterval = $this->escapeInterval((array)$jobId);
519
+ $jobClause = "AND jobId IN ({$jobIdsInterval})";
520
+ }
521
+
522
+ if (empty($status) || $status === Queue::STATUS_ANY) {
523
+ $countQuery = "SELECT COUNT(id) FROM {$tableName} WHERE 1=1 {$jobClause}";
524
+ } else {
525
+ $stati = $this->escapeInterval((array)$status);
526
+ $countQuery = "SELECT COUNT(id) FROM {$tableName} WHERE status IN ({$stati}) {$jobClause}";
527
+ }
528
+
529
+ $countResult = $this->database->query($countQuery);
530
+
531
+ if ($countResult === false) {
532
+ $error = $this->database->error();
533
+
534
+ if (!empty($error)) {
535
+ error_log(json_encode([
536
+ 'root' => 'Error while trying to count Actions.',
537
+ 'class' => get_class($this),
538
+ 'query' => $countQuery,
539
+ 'error' => $error,
540
+ ]));
541
+ }
542
+
543
+ // For all intent and purposes, the Queue cannot be counted now.
544
+ return 0;
545
+ }
546
+
547
+ $count = $this->database->fetchRow($countResult);
548
+
549
+ return (array_sum((array)$count));
550
+ }
551
+
552
+ /**
553
+ * Updates an Action status in the Queue table.
554
+ *
555
+ * Updating the Action status to Processing will mark the Action as claimed the very
556
+ * moment the operation is performed.
557
+ *
558
+ * @param int|Action $action Either an action id, or a reference to an Action object.
559
+ * @param string $newStatus The status to update the Action status to.
560
+ * @param bool $unsafely If the status update is to the Processing one, then we require
561
+ * the developer to do it with full understanding that it's NOT
562
+ * the correct way to do it.
563
+ *
564
+ * @return false|int Either the updated action id, or `false` to indicate the status
565
+ * update failed.
566
+ *
567
+ * @throws QueueException If the status to update the Action to is the Processing one and
568
+ * the client code is not owning the unsafety of it.
569
+ */
570
+ public function updateActionStatus($action, $newStatus, $unsafely = false)
571
+ {
572
+ $actionId = absint($action instanceof Action ? $action->id : (int)$action);
573
+ $tableName = self::getTableName();
574
+ $status = $this->database->escape($newStatus);
575
+ $now = date('Y-m-d H:m:s');
576
+
577
+ if ($status !== self::STATUS_PROCESSING) {
578
+ // Any status update that is not to the processing status, will clean the `claimed_at` column.
579
+ $statusUpdateQuery = "UPDATE {$tableName} SET status='{$status}', claimed_at=NULL, updated_at='{$now}' WHERE id={$actionId}";
580
+ } else {
581
+ if (!$unsafely) {
582
+ // This is a developer mistake: it should be immediately signaled as such.
583
+ throw new QueueException('Marking actions as Processing should only be done using the getNextAvailable method!');
584
+ }
585
+
586
+ // If the status update is to the Processing status, then the Action should be marked as claimed.
587
+ $statusUpdateQuery = "UPDATE {$tableName} SET status='{$status}', claimed_at='{$now}', updated_at='{$now}' WHERE id={$actionId} ";
588
+ }
589
+
590
+ $updated = $this->database->query($statusUpdateQuery, true);
591
+
592
+ if (!$updated) {
593
+ error_log(json_encode([
594
+ 'root' => 'Error while trying to update Action status.',
595
+ 'class' => get_class($this),
596
+ 'query' => $statusUpdateQuery,
597
+ 'error' => $this->database->error(),
598
+ ]));
599
+
600
+ return false;
601
+ }
602
+
603
+ // Force a refresh on next action fetch.
604
+ unset($this->actionCaches[$actionId]);
605
+
606
+ return $actionId;
607
+ }
608
+
609
+ /**
610
+ * Return the Queue table creation SQL code.
611
+ *
612
+ * @return string The Queue table creation SQL code.
613
+ */
614
+ private function getCreateTableSql()
615
+ {
616
+ global $wpdb;
617
+ $collate = $wpdb->collate;
618
+ $queueTable = self::getTableName();
619
+ $tableSql = "CREATE TABLE {$queueTable} (
620
+ id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
621
+ action VARCHAR(1000) NOT NULL,
622
+ jobId VARCHAR(1000) DEFAULT NULL,
623
+ status CHAR(20) NOT NULL DEFAULT 'ready',
624
+ priority BIGINT(20) NOT NULL DEFAULT 0,
625
+ args LONGTEXT DEFAULT NULL,
626
+ claimed_at DATETIME DEFAULT NULL,
627
+ updated_at DATETIME DEFAULT NULL,
628
+ PRIMARY KEY (id)
629
+ ) COLLATE {$collate}";
630
+ return $tableSql;
631
+ }
632
+
633
+ /**
634
+ * Drops the custom table used by the Queue to store actions.
635
+ *
636
+ * Dropping the table means, implicitly, also losing all the Actions
637
+ * stored there.
638
+ *
639
+ * @return bool Whether the table dropping was successful or not.
640
+ */
641
+ public function dropTable()
642
+ {
643
+ $tableName = self::getTableName();
644
+ $query = "DROP TABLE {$tableName}";
645
+ $this->database->query($query, true);
646
+
647
+ return !$this->tableExists();
648
+ }
649
+
650
+ /**
651
+ * Returns the last logged error provided by the underlying database adapter.
652
+ *
653
+ * @return string The last error as logged by the database adapter, or an empty
654
+ * string if there are no errors.
655
+ */
656
+ public function lastError()
657
+ {
658
+ if ($this->database === null) {
659
+ return '';
660
+ }
661
+ return (string)$this->database->error();
662
+ }
663
+
664
+ /**
665
+ * Fetches an Action row from the database.
666
+ *
667
+ * @param int $actionId The id of the Action to fetch.
668
+ *
669
+ * @return array<string,mixed>|null Either a map from the action columns to
670
+ * their respective values, or `null` to indicate
671
+ * the Action row could not be fetched.
672
+ */
673
+ private function fetchActionRow($actionId)
674
+ {
675
+ $actionId = absint($actionId);
676
+
677
+ if (empty($actionId)) {
678
+ return null;
679
+ }
680
+
681
+ $tableName = self::getTableName();
682
+ $fetchQuery = "SELECT * FROM {$tableName} WHERE id={$actionId}";
683
+ $fetchResult = $this->database->query($fetchQuery);
684
+
685
+ if ($fetchResult === false) {
686
+ // This is NOT an error, the query might be for a no-more existing Action.
687
+ return null;
688
+ }
689
+
690
+ $row = $this->database->fetchAssoc($fetchResult);
691
+
692
+ return is_array($row) ? $row : null;
693
+ }
694
+
695
+ /**
696
+ * Fetches an action information from the database and returns a reference to
697
+ * its object representation.
698
+ *
699
+ * @param int $actionId The id of the Action to fetch.
700
+ * @param bool $force Whether to force the refetch of the Action data from the database
701
+ * or not.
702
+ *
703
+ * @return Action|null A reference to the Action object built from the input action id,
704
+ * or `null` to indicate the Action data could not be fetched or does
705
+ * not exist.
706
+ *
707
+ * @throws QueueException If there's any issue while building and validating the Action.
708
+ */
709
+ public function getAction($actionId, $force = false)
710
+ {
711
+ if ($force || empty($this->actionCaches[$actionId])) {
712
+ $row = $this->fetchActionRow($actionId);
713
+
714
+ if ($row !== null) {
715
+ $this->actionCaches[$actionId] = $row;
716
+ }
717
+ }
718
+
719
+ return isset($this->actionCaches[$actionId]) ?
720
+ Action::fromDbRow($this->actionCaches[$actionId])
721
+ : null;
722
+ }
723
+
724
+ /**
725
+ * Returns a list of stati in which an Action could be.
726
+ *
727
+ * While nothing is preventing other code from assigning different
728
+ * stati to the Actions, these are the ones the Queue is actually
729
+ * equipped to handle.
730
+ *
731
+ * @return array<string> A list of the possible stati an Action could
732
+ * be in.
733
+ */
734
+ public function getSupportedActionStati()
735
+ {
736
+ return [
737
+ self::STATUS_PROCESSING,
738
+ self::STATUS_READY,
739
+ self::STATUS_COMPLETED,
740
+ ];
741
+ }
742
+
743
+ /**
744
+ * Returns an immutable Date Object representing the breakpoint date and time
745
+ * that should be used to mark an Action that has been claimed before that point
746
+ * in date and time as dangling if still processing.
747
+ *
748
+ * @return DateTimeImmutable A reference to an immutable date time object representing
749
+ * the dangling breakpoint.
750
+ */
751
+ public function getDanglingBreakpointDate()
752
+ {
753
+ return $this->getBreakpointDate(HOUR_IN_SECONDS);
754
+ }
755
+
756
+ /**
757
+ * Assigns a new status to any dangling Action.
758
+ *
759
+ * A dangling Action is one that was claimed for processing too long ago.
760
+ * Where "too long ago" is defined by the Dangling Action breakpoint date.
761
+ * Actions updated using this method will have their `claimed_at` column entry
762
+ * cleared.
763
+ *
764
+ * @param string $newStatus The new status that should be assigned to the Actions.
765
+ * The method will NOT check the status to make sure it's
766
+ * one of the supported ones, this is by design to allow
767
+ * the queue to be used in a more flexible way.
768
+ *
769
+ * @return int The number of updated Actions.
770
+ */
771
+ public function markDanglingAs($newStatus)
772
+ {
773
+ if ($this->checkTable() === static::TABLE_NOT_EXIST) {
774
+ // The table does not exist so there is nothing to update.
775
+ return 0;
776
+ }
777
+
778
+ $tableName = self::getTableName();
779
+ $newStatus = $this->database->escape($newStatus);
780
+ $danglingBreakpoint = $this->getDanglingBreakpointDate()->format('Y-m-d H:i:s');
781
+ $markQuery = "UPDATE {$tableName}
782
+ SET status='{$newStatus}', claimed_at=NULL
783
+ WHERE claimed_at IS NOT NULL
784
+ AND claimed_at < '{$danglingBreakpoint}'";
785
+ $markResult = $this->database->query($markQuery, true);
786
+
787
+ if ($markResult === false) {
788
+ error_log(json_encode([
789
+ 'root' => 'Error while trying to mark dangling Actions.',
790
+ 'class' => get_class($this),
791
+ 'query' => $markQuery,
792
+ 'error' => $this->database->error(),
793
+ ]));
794
+
795
+ return 0;
796
+ }
797
+
798
+ if (isset($this->database->link->affected_rows)) {
799
+ $marked = $this->database->link->affected_rows;
800
+ } else {
801
+ $marked = 0;
802
+ }
803
+
804
+ return (int)$marked;
805
+ }
806
+
807
+ /**
808
+ * Hooked on the `shutdown` action, this method will make sure the Queue
809
+ * will keep processing if there are ready Actions.
810
+ *
811
+ * @return bool Whether the AJAX action was correctly fired or not. Note that
812
+ * a `false` return value might indicate both that there was no
813
+ * need to fire the AJAX action or that the firing failed.
814
+ */
815
+ public function maybeFireAjaxAction()
816
+ {
817
+ if (!$this->count(self::STATUS_READY)) {
818
+ return false;
819
+ }
820
+
821
+ return $this->fireAjaxAction();
822
+ }
823
+
824
+ /**
825
+ * Escapes a set of values to be used in a IN clause.
826
+ *
827
+ * @param array<string> $values The set of values to escape.
828
+ *
829
+ * @return string The values escaped and concatenated in a string suitable
830
+ * to be used in a IN clause.
831
+ */
832
+ private function escapeInterval(array $values)
833
+ {
834
+ return implode(',', array_map(function ($value) {
835
+ return "'" . $this->database->escape($value) . "'";
836
+ }, (array)$values));
837
+ }
838
+
839
+ /**
840
+ * Cancels all the Actions for a Job or a list of Jobs.
841
+ *
842
+ * @param string|array<string> $jobId A Job ID, or a list of Job IDs to cancel
843
+ * all Actions for.
844
+ *
845
+ * @return int
846
+ * @since TBD
847
+ *
848
+ */
849
+ public function cancelJob($jobId)
850
+ {
851
+ if ($this->checkTable() === static::TABLE_NOT_EXIST) {
852
+ // The table does not exist so there is nothing to cancel.
853
+ return 0;
854
+ }
855
+
856
+ $tableName = self::getTableName();
857
+ $newStatus = self::STATUS_CANCELED;
858
+ $jobIds = (array)$jobId;
859
+ $jobIdsInterval = $this->escapeInterval($jobIds);
860
+ $now = date('Y-m-d H:m:s');
861
+ $cancelQuery = "UPDATE {$tableName}
862
+ SET status='{$newStatus}', claimed_at=NULL, updated_at='{$now}'
863
+ WHERE jobId in (${jobIdsInterval})";
864
+ $cancelResult = $this->database->query($cancelQuery, true);
865
+
866
+ if ($cancelResult === false) {
867
+ error_log(json_encode([
868
+ 'root' => 'Error while trying to cancel Actions.',
869
+ 'class' => get_class($this),
870
+ 'query' => $cancelQuery,
871
+ 'error' => $this->database->error(),
872
+ ]));
873
+
874
+ return 0;
875
+ }
876
+
877
+ if (isset($this->database->link->affected_rows)) {
878
+ $canceled = $this->database->link->affected_rows;
879
+ } else {
880
+ $canceled = 0;
881
+ }
882
+
883
+ $this->invalidateActionCachesByJobId($jobIds);
884
+
885
+ return (int)$canceled;
886
+ }
887
+
888
+ /**
889
+ * Invalidates cached Action values by Job Id.
890
+ *
891
+ * @param array<string> $jobIds A list of Job IDs to invalidate the Actions by.
892
+ *
893
+ * @return void The method does not return any value and will invalidate the Actions
894
+ * caches by Job ID as a side effect.
895
+ */
896
+ private function invalidateActionCachesByJobId(array $jobIds)
897
+ {
898
+ array_walk($this->actionCaches, static function (&$cachedAction) use ($jobIds) {
899
+ if (!empty($cachedAction['jobId']) && in_array($cachedAction['jobId'], $jobIds, true)) {
900
+ $cachedAction = null;
901
+ }
902
+ });
903
+ }
904
+
905
+ /**
906
+ * Allows updating an Action field directly.
907
+ *
908
+ * This method has the potential of disrupting the Queue functions: with great power comes great
909
+ * responsibility.
910
+ *
911
+ * @param Action|int $action The Action ID or a reference to the Action instance.
912
+ * @param array<string,mixed> $updates A map from the updates keys to the updates value.
913
+ * @param bool $unsafely We require the developer to do it with full understanding that it's
914
+ * NOT the correct way to do it.
915
+ *
916
+ * @return false|int Either the ID of the updated action, or `false` to indicate the update failed.
917
+ *
918
+ * @throws QueueException If the `$unsafely` parameter is not set to `true` or the field
919
+ * to be updated is the Action ID one.
920
+ *
921
+ * @internal This method has the potential of disrupting the Queue system and should not
922
+ * be used without full knowledge of what is being done.
923
+ */
924
+ public function updateActionFields($action, array $updates, $unsafely = false)
925
+ {
926
+ if (!$unsafely) {
927
+ // This is a developer mistake: it should be immediately signaled as such.
928
+ throw new QueueException(
929
+ 'Updating Action fields has the potential of disrupting the Queue functions.'
930
+ );
931
+ }
932
+
933
+ if (isset($updates['id'])) {
934
+ // This is a developer mistake: it should be immediately signaled as such.
935
+ throw new QueueException(
936
+ 'Updating an Action ID is never allowed.'
937
+ );
938
+ }
939
+
940
+ $actionId = absint($action instanceof Action ? $action->id : (int)$action);
941
+ $tableName = self::getTableName();
942
+
943
+ $assignmentsList = $this->buildAssignmentsList($updates);
944
+ $statusUpdateQuery = "UPDATE {$tableName} SET {$assignmentsList} WHERE id={$actionId}";
945
+
946
+ $updated = $this->database->query($statusUpdateQuery, true);
947
+
948
+ if (!$updated) {
949
+ error_log(json_encode([
950
+ 'root' => 'Error while trying to update Action field.',
951
+ 'class' => get_class($this),
952
+ 'query' => $statusUpdateQuery,
953
+ 'error' => $this->database->error(),
954
+ ]));
955
+
956
+ return false;
957
+ }
958
+
959
+ // Force a refresh on next action fetch.
960
+ unset($this->actionCaches[$actionId]);
961
+
962
+ return $actionId;
963
+ }
964
+
965
+ /**
966
+ * Compiles a map of values to a SET assignment list suitable to use in INSERT and UPDATE
967
+ * statements.
968
+ *
969
+ * @param array<string,mixed> $assignments A map from the assignments keys to the values.
970
+ *
971
+ * @return string The compiled assignments list.
972
+ */
973
+ private function buildAssignmentsList(array $assignments)
974
+ {
975
+ $assignmentList = [];
976
+
977
+ array_walk($assignments, function ($value, $key) use (&$assignmentList) {
978
+ if ($value === '') {
979
+ // Empty string values should be skipped to let the database default value kick in.
980
+ return;
981
+ }
982
+
983
+ $escapedKey = $this->database->escape($key);
984
+
985
+ if ($key === 'priority') {
986
+ // Keep the numeric value.
987
+ $escapedValue = (int)$value;
988
+ $assignmentList[] = "{$escapedKey}={$escapedValue}";
989
+ } elseif ($key === 'args') {
990
+ $escapedValue = serialize($value);
991
+ $assignmentList[] = "{$escapedKey}='{$escapedValue}'";
992
+ } else {
993
+ $escapedValue = $this->database->escape($value);
994
+ $assignmentList[] = "{$escapedKey}='{$escapedValue}'";
995
+ }
996
+ });
997
+
998
+ return implode(', ', $assignmentList);
999
+ }
1000
+
1001
+ /**
1002
+ * Returns an immutable Date Object representing the breakpoint date and time
1003
+ * that should be used to cleanup Actions.
1004
+ *
1005
+ * @return DateTimeImmutable A reference to an immutable date time object representing
1006
+ * the dangling breakpoint.
1007
+ */
1008
+ public function getCleanupBreakpointDate()
1009
+ {
1010
+ return $this->getBreakpointDate(WEEK_IN_SECONDS);
1011
+ }
1012
+
1013
+ /**
1014
+ * Builds and returns a breakpoint date.
1015
+ *
1016
+ * @param int $interval The amount, in seconds, to apply to the current date
1017
+ * and time to build the breakpoint date.
1018
+ *
1019
+ * @return DateTimeImmutable A reference to the breakpoint date immutable instance.
1020
+ */
1021
+ private function getBreakpointDate($interval)
1022
+ {
1023
+ try {
1024
+ $breakpointDate = new DateTimeImmutable(date('Y-m-d H:i:s'));
1025
+ $breakpointDate = $breakpointDate->setTimestamp($breakpointDate->getTimestamp() - $interval);
1026
+ } catch (Exception $e) {
1027
+ /*
1028
+ * On failure, return a date very far in the past, before this is written, to make sure no
1029
+ * Action will be modified.
1030
+ */
1031
+ $breakpointDate = new DateTimeImmutable('2020-01-01 00:00:00');
1032
+ }
1033
+
1034
+ return $breakpointDate;
1035
+ }
1036
+
1037
+ public function cleanup()
1038
+ {
1039
+ if ($this->checkTable() === static::TABLE_NOT_EXIST) {
1040
+ // The table does not exist so there is nothing to update.
1041
+ return 0;
1042
+ }
1043
+
1044
+ $tableName = self::getTableName();
1045
+ $cleanupBreakpoint = $this->getCleanupBreakpointDate()->format('Y-m-d H:i:s');
1046
+ $cleanableStati = $this->escapeInterval([
1047
+ self::STATUS_READY,
1048
+ self::STATUS_COMPLETED,
1049
+ self::STATUS_FAILED,
1050
+ self::STATUS_CANCELED
1051
+ ]);
1052
+ $clenupQuery = "DELETE FROM {$tableName}
1053
+ WHERE updated_at < '{$cleanupBreakpoint}'
1054
+ AND status in ({$cleanableStati})";
1055
+ $cleanupResult = $this->database->query($clenupQuery, true);
1056
+
1057
+ if ($cleanupResult === false) {
1058
+ error_log(json_encode([
1059
+ 'root' => 'Error while trying to cleanup Actions.',
1060
+ 'class' => get_class($this),
1061
+ 'query' => $clenupQuery,
1062
+ 'error' => $this->database->error(),
1063
+ ]));
1064
+
1065
+ return 0;
1066
+ }
1067
+ if (isset($this->database->link->affected_rows)) {
1068
+ $removed = $this->database->link->affected_rows;
1069
+ } else {
1070
+ $removed = 0;
1071
+ }
1072
+
1073
+ return $removed;
1074
+ }
1075
+ }
Framework/BackgroundProcessing/QueueProcessor.php ADDED
@@ -0,0 +1,222 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Processes Actions from the Queue, dispatching the correct Actions and methods with
5
+ * awareness of the available resources.
6
+ *
7
+ * @package WPStaging\Framework\BackgroundProcessing
8
+ */
9
+
10
+ namespace WPStaging\Framework\BackgroundProcessing;
11
+
12
+ use ReflectionMethod;
13
+ use WPStaging\Core\Utils\Logger;
14
+ use WPStaging\Core\WPStaging;
15
+ use WPStaging\Framework\Traits\ResourceTrait;
16
+
17
+ /**
18
+ * Class QueueProcessor
19
+ *
20
+ * @package WPStaging\Framework\BackgroundProcessing
21
+ */
22
+ class QueueProcessor
23
+ {
24
+ use ResourceTrait;
25
+ use WithQueueAwareness;
26
+
27
+ const QUEUE_PROCESS_ACTION = 'wpstg_queue_process';
28
+
29
+ /**
30
+ * A flag property indicating whether the Queue Processor
31
+ * should actually process Actions or not.
32
+ *
33
+ * @var bool
34
+ */
35
+ private $doProcess = true;
36
+
37
+ /**
38
+ * A reference to the Queue instance the Processor should use to access and run low-level
39
+ * operations on the Queue.
40
+ *
41
+ * @var Queue
42
+ */
43
+ private $queue;
44
+
45
+ /**
46
+ * QueueProcessor constructor.
47
+ *
48
+ * @param Queue $queue A reference to the Queue instance the Processor should use to access
49
+ * and run low-level operations on the Queue.
50
+ */
51
+ public function __construct(Queue $queue)
52
+ {
53
+ $this->queue = $queue;
54
+ }
55
+
56
+ /**
57
+ * Runs the next available Actions until either they are finished or the resources available
58
+ * are depleted.
59
+ *
60
+ * @return int The number of processed Actions. Processed does NOT mean Completed, it just means
61
+ * the Processor took hold of the Actions and dispatched them where required.
62
+ */
63
+ public function process()
64
+ {
65
+ if (!$this->doProcess) {
66
+ return 0;
67
+ }
68
+
69
+ $processed = 0;
70
+
71
+ while (!$this->isThreshold()) {
72
+ $action = $this->queue->getNextAvailable();
73
+
74
+ if (!$action instanceof Action) {
75
+ // No Actions to process or failed to acquire lock, bail.
76
+ break;
77
+ }
78
+
79
+ $processed++;
80
+
81
+ $this->dispatch($action);
82
+ }
83
+
84
+ if ($this->queue->count(Queue::STATUS_READY)) {
85
+ // If there are more Actions to process, then keep processing.
86
+ $this->fireAjaxAction();
87
+ }
88
+
89
+ return $processed;
90
+ }
91
+
92
+ /**
93
+ * Depending on the Action nature, dispatch the Action correctly.
94
+ *
95
+ * Note that a successful dispatch means that the execution
96
+ * of the WordPress action, function or method did not raise
97
+ * Exceptions, and not that it did what was required correctly.
98
+ * The task of assessing success, and acting on that information
99
+ * to, maybe, queue the Action again (retry) is a task better performed
100
+ * by the code that is fired, NOT the Queue Processor.
101
+ *
102
+ * @param Action $action A reference to the Action to dispatch.
103
+ *
104
+ * @return bool A value that will indicate whether the Action was
105
+ * dispatched without raising Exceptions or not.
106
+ *
107
+ * @throws Exceptions\QueueException
108
+ */
109
+ public function dispatch(Action $action)
110
+ {
111
+ /*
112
+ * What is this?
113
+ * It's a Closure that will mark this Action as failed.
114
+ * We hook this Closure on the `shutdown` hook.
115
+ * When the Closure is called, either in the context of the `shutdown` hook,
116
+ * it will unhook itself from the `shutdown` hook to have a call-at-most-once
117
+ * Closure.
118
+ */
119
+ $markFailed = function () use ($action, &$markFailed) {
120
+ remove_action('shutdown', $markFailed);
121
+ $this->queue->updateActionStatus($action, Queue::STATUS_FAILED);
122
+ };
123
+
124
+ // If the request dies in the next lines, the Action failed.
125
+ add_action('shutdown', $markFailed);
126
+
127
+ $originalUpdateTime = $action->updatedAt;
128
+
129
+ try {
130
+ $actionCallback = $action->action;
131
+
132
+ if (is_callable($actionCallback)) {
133
+ // Function, static or instance method.
134
+ if (function_exists($actionCallback)) {
135
+ // Function, just call it.
136
+ call_user_func_array($actionCallback, $action->args);
137
+ } else {
138
+ /*
139
+ * Static or instance methods: different versions of PHP will mark `Class::method` as
140
+ * callable even when it's an instance method, so we have to check if it's static or
141
+ * not.
142
+ */
143
+ list($class, $method) = explode('::', $actionCallback, 2);
144
+ $methodReflection = new ReflectionMethod($class, $method);
145
+ if ($methodReflection->isStatic()) {
146
+ // Static method, just call it.
147
+ call_user_func_array($actionCallback, $action->args);
148
+ } else {
149
+ // Instance method: build the instance using the Service Locator, then call the method on it.
150
+ $instance = WPStaging::getInstance()->getContainer()->make($class);
151
+ call_user_func_array([$instance, $method], $action->args);
152
+ }
153
+ }
154
+ } else {
155
+ // If nothing of the above, then treat it as a WP action.
156
+ do_action_ref_array($actionCallback, $action->args);
157
+ }
158
+ } catch (\Throwable $e) {
159
+ /*
160
+ * This is a PHP 7.0+ interface. But since PHP will NOT check this for existence,
161
+ * the same way it will not check `instanceof`, this allows us to catch fatals
162
+ * and keep going if we're on PHP 7.0+.
163
+ */
164
+ $markFailed();
165
+
166
+ return false;
167
+ } catch (\Exception $e) {
168
+ /*
169
+ * If we're not on PHP 7.0+, then this is the next best option: there
170
+ * was an error we could catch, and we did. If the request dies due to
171
+ * a fatal, then we'll handle that in the `shutdown` hook.
172
+ */
173
+ $markFailed();
174
+
175
+ return false;
176
+ }
177
+
178
+ // All fine, we survived.
179
+ remove_action('shutdown', $markFailed);
180
+
181
+ // Re-fetch the Action to check if it was updated during dispatch.
182
+ $updatedAt = $this->queue->getAction($action->id, true)->updatedAt;
183
+ $updatedDuringDispatch = $originalUpdateTime === $updatedAt;
184
+
185
+ if (!$updatedDuringDispatch) {
186
+ // If an Action was updated during dispatch, we'll avoid re-setting its status to another value.
187
+ return true;
188
+ }
189
+
190
+ $this->queue->updateActionStatus($action, Queue::STATUS_COMPLETED);
191
+
192
+ return true;
193
+ }
194
+
195
+ /**
196
+ * Suspends the Queue Processer operations. Any call to the
197
+ * `process` method will be a no-op that will not process and
198
+ * dispatch any action.
199
+ *
200
+ * @since TBD
201
+ *
202
+ * @return bool Whether the Queue Processor was correctly suspended or not.
203
+ */
204
+ public function stopProcessing()
205
+ {
206
+ $this->doProcess = false;
207
+ return true;
208
+ }
209
+
210
+ /**
211
+ * Resumes the Queue Processor processing of Actions, if stopped.
212
+ *
213
+ * @since TBD
214
+ *
215
+ * @return bool Whether the Queue Processor did correctly resume or not.
216
+ */
217
+ public function resumeProcessing()
218
+ {
219
+ $this->doProcess = true;
220
+ return true;
221
+ }
222
+ }
Framework/BackgroundProcessing/WithQueueAwareness.php ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Provides methods to be aware of the queue system and its inner workings.
5
+ *
6
+ * @package WPStaging\Framework\BackgroundProcessing
7
+ */
8
+
9
+ namespace WPStaging\Framework\BackgroundProcessing;
10
+
11
+ use WP_Error;
12
+
13
+ /**
14
+ * Trait WithQueueAwareness
15
+ *
16
+ * @package WPStaging\Framework\BackgroundProcessing
17
+ */
18
+ trait WithQueueAwareness
19
+ {
20
+
21
+ /**
22
+ * Whether this Queue instance did fire the AJAX action request or not.
23
+ *
24
+ * @var bool
25
+ */
26
+ private $didFireAjaxAction = false;
27
+
28
+ /**
29
+ * Returns the Queue default priority that will be used to schedule actions when the
30
+ * priority is not specified or is specified as an invalid value.
31
+ *
32
+ * @return int The Queue default priority.
33
+ */
34
+ public static function getDefaultPriority()
35
+ {
36
+ return 0;
37
+ }
38
+
39
+
40
+ /**
41
+ * Fires a non-blocking request to the WordPress admin AJAX endpoint that will,
42
+ * in turn, trigger the procesing of more Actions.
43
+ *
44
+ * @param mixed|null $bodyData An optional set of data to customize the processing request
45
+ * for. If not provided, then the request will be fired for the
46
+ * next available Actions (normal operations).
47
+ *
48
+ * @return bool A value that will indicate whether the request was correctly dispathed
49
+ * or not.
50
+ */
51
+ public function fireAjaxAction($bodyData = null)
52
+ {
53
+ if ($this->didFireAjaxAction) {
54
+ // Let's not fire the AJAX request more than once per HTTP request, per Queue.
55
+ return false;
56
+ }
57
+
58
+ $ajaxUrl = add_query_arg([
59
+ 'action' => QueueProcessor::QUEUE_PROCESS_ACTION,
60
+ '_ajax_nonce' => wp_create_nonce(QueueProcessor::QUEUE_PROCESS_ACTION)
61
+ ], admin_url('admin-ajax.php'));
62
+
63
+ $response = wp_remote_post(esc_url_raw($ajaxUrl), [
64
+ 'headers' => [
65
+ 'X-WPSTG-Request' => QueueProcessor::QUEUE_PROCESS_ACTION,
66
+ ],
67
+ 'blocking' => false,
68
+ 'timeout' => 0.01,
69
+ 'cookies' => isset($_COOKIE) ? $_COOKIE : [],
70
+ 'sslverify' => apply_filters('https_local_ssl_verify', false),
71
+ 'body' => $this->normalizeAjaxRequestBody($bodyData),
72
+ ]);
73
+
74
+ /*
75
+ * A non-blocking request will either return a WP_Error instance, or
76
+ * a mock response. The response is a mock as we cannot really build
77
+ * a good response without waiting for it to be processed from the server.
78
+ */
79
+ if ($response instanceof WP_Error) {
80
+ error_log(json_encode([
81
+ 'root' => 'Queue processing admin-ajax request failed.',
82
+ 'class' => get_class($this),
83
+ 'code' => $response->get_error_code(),
84
+ 'message' => $response->get_error_message(),
85
+ 'data' => $response->get_error_data()
86
+ ], JSON_PRETTY_PRINT));
87
+
88
+ return false;
89
+ }
90
+
91
+ $this->didFireAjaxAction = true;
92
+
93
+ /**
94
+ * Fires an Action to indicate the Queue did fire the AJAX request that will
95
+ * trigger side-processing in another PHP process.
96
+ *
97
+ * @param Queue $this A reference to the instance of the Queue that actually fired
98
+ * the AJAX request.
99
+ */
100
+ do_action('wpstg_queue_fire_ajax_request', $this);
101
+
102
+ return true;
103
+ }
104
+
105
+ /**
106
+ * Normalizes the data to be sent along the non-blocking AJAX request
107
+ * that will trigger the Queue processing of an Action.
108
+ *
109
+ * @param mixed|null $bodyData The data to normlize to a format suitable for
110
+ * the remote request.
111
+ *
112
+ * @return array The normalized body data to be sent along the non-blocking
113
+ * AJAX request.
114
+ */
115
+ private function normalizeAjaxRequestBody($bodyData)
116
+ {
117
+ $normalized = (array)$bodyData;
118
+
119
+ $normalized['_referer'] = __CLASS__;
120
+
121
+ return $normalized;
122
+ }
123
+ }
Framework/CloningProcess/Data/DBCloningService.php CHANGED
@@ -41,6 +41,16 @@ abstract class DBCloningService extends CloningService
41
  // @see WPStaging/Backend/Modules/Jobs/Cloning.php#L293
42
  // code below solves this issue https://github.com/WP-Staging/wp-staging-pro/issues/385
43
  $prefix = rtrim($this->dto->getPrefix(), '_') . '_';
 
 
 
 
 
 
 
 
 
 
44
  // Skip - Table does not exist
45
  if (!$this->tableExists($prefix . $table)) {
46
  $this->log("Table " . $prefix . $table . ' not found. Skipping');
41
  // @see WPStaging/Backend/Modules/Jobs/Cloning.php#L293
42
  // code below solves this issue https://github.com/WP-Staging/wp-staging-pro/issues/385
43
  $prefix = rtrim($this->dto->getPrefix(), '_') . '_';
44
+
45
+ // But if the the clone was created with old WP STAGING version where we were not forcing underscore in prefix,
46
+ // this could to let to unwanted results. As we are force copying users and usermeta table into the staging site,
47
+ // It will be good to check against users that without forced appending underscore
48
+ // Code below solves this issue https://github.com/WP-Staging/wp-staging-pro/issues/925
49
+ // If the main job is UPDATE or RESET and users table without post underscore exists then use prefix without post underscore
50
+ if ($this->dto->getMainJob() !== 'cloning' && $this->tableExists($this->dto->getPrefix() . 'users')) {
51
+ $prefix = $this->dto->getPrefix();
52
+ }
53
+
54
  // Skip - Table does not exist
55
  if (!$this->tableExists($prefix . $table)) {
56
  $this->log("Table " . $prefix . $table . ' not found. Skipping');
Framework/CloningProcess/Data/MultisiteUpdateTablePrefix.php DELETED
@@ -1,32 +0,0 @@
1
- <?php
2
-
3
- namespace WPStaging\Framework\CloningProcess\Data;
4
-
5
- class MultisiteUpdateTablePrefix extends UpdateTablePrefix
6
- {
7
- /**
8
- * Changes the base table prefix of the main network site
9
- */
10
- protected function updateBaseTablePrefix()
11
- {
12
- $prefix = $this->dto->getPrefix();
13
- $db = $this->dto->getStagingDb();
14
- $productionDb = $this->dto->getProductionDb();
15
-
16
- $this->debugLog("SQL: UPDATE {$prefix}usermeta SET meta_key = replace(meta_key, {$productionDb->base_prefix}, {$prefix}) WHERE meta_key LIKE {$productionDb->base_prefix}_%");
17
- $update = $db->query(
18
- $db->prepare(
19
- "UPDATE {$prefix}usermeta SET meta_key = replace(meta_key, %s, %s) WHERE meta_key LIKE %s",
20
- $productionDb->base_prefix,
21
- $prefix,
22
- $productionDb->base_prefix . "_%"
23
- )
24
- );
25
-
26
- if ($update === false) {
27
- $this->log("Failed updating {$prefix}usermeta meta_key database base_prefix {$db->last_error}");
28
- } else {
29
- //$this->log("Done");
30
- }
31
- }
32
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Framework/CloningProcess/Data/UpdateStagingOptionsTable.php CHANGED
@@ -24,15 +24,21 @@ class UpdateStagingOptionsTable extends DBCloningService
24
  'wpstg_rmpermalinks_executed' => ' ',
25
  'blog_public' => 0,
26
  FirstRun::FIRST_RUN_KEY => 'true',
27
- CloneOptions::WPSTG_CLONE_SETTINGS_KEY => serialize((object) [
 
 
 
 
28
  FirstRun::MAILS_DISABLED_KEY => !((bool) $this->dto->getJob()->getOptions()->emailsAllowed),
29
  ExcludedPlugins::EXCLUDED_PLUGINS_KEY => (new ExcludedPlugins())->getFilteredPluginsToExclude(),
30
- ]),
31
- ];
 
32
  if (!$this->keepPermalinks()) {
33
  $updateOrInsert['rewrite_rules'] = null;
34
  $updateOrInsert['permalink_structure'] = ' ';
35
  }
 
36
  $this->updateOrInsertOptions($updateOrInsert);
37
 
38
  $update = [
@@ -42,6 +48,7 @@ class UpdateStagingOptionsTable extends DBCloningService
42
  if ($this->dto->getMainJob() !== 'updating') {
43
  $update['wpstg_existing_clones_beta'] = serialize([]);
44
  }
 
45
  $this->updateOptions($update);
46
 
47
  return true;
24
  'wpstg_rmpermalinks_executed' => ' ',
25
  'blog_public' => 0,
26
  FirstRun::FIRST_RUN_KEY => 'true',
27
+ ];
28
+ // only insert or update clone option if job is not updating
29
+ // during update this data will be preserved
30
+ if ($this->dto->getMainJob() !== 'updating') {
31
+ $update[CloneOptions::WPSTG_CLONE_SETTINGS_KEY] = serialize((object) [
32
  FirstRun::MAILS_DISABLED_KEY => !((bool) $this->dto->getJob()->getOptions()->emailsAllowed),
33
  ExcludedPlugins::EXCLUDED_PLUGINS_KEY => (new ExcludedPlugins())->getFilteredPluginsToExclude(),
34
+ ]);
35
+ }
36
+
37
  if (!$this->keepPermalinks()) {
38
  $updateOrInsert['rewrite_rules'] = null;
39
  $updateOrInsert['permalink_structure'] = ' ';
40
  }
41
+
42
  $this->updateOrInsertOptions($updateOrInsert);
43
 
44
  $update = [
48
  if ($this->dto->getMainJob() !== 'updating') {
49
  $update['wpstg_existing_clones_beta'] = serialize([]);
50
  }
51
+
52
  $this->updateOptions($update);
53
 
54
  return true;
Framework/CloningProcess/Data/UpdateTablePrefix.php CHANGED
@@ -22,8 +22,6 @@ class UpdateTablePrefix extends DBCloningService
22
  return true;
23
  }
24
 
25
- $this->updateBaseTablePrefix();
26
-
27
  $this->debugLog("SQL: UPDATE {$prefix}usermeta SET meta_key = replace(meta_key, {$productionDb->prefix}, {$prefix}) WHERE meta_key LIKE {$productionDb->prefix}%");
28
 
29
  $update = $db->query(
@@ -41,12 +39,4 @@ class UpdateTablePrefix extends DBCloningService
41
 
42
  return true;
43
  }
44
-
45
- /**
46
- * This function is overwritten for the multisite service
47
- */
48
- protected function updateBaseTablePrefix()
49
- {
50
- //Do nothing since this is the single-site class
51
- }
52
  }
22
  return true;
23
  }
24
 
 
 
25
  $this->debugLog("SQL: UPDATE {$prefix}usermeta SET meta_key = replace(meta_key, {$productionDb->prefix}, {$prefix}) WHERE meta_key LIKE {$productionDb->prefix}%");
26
 
27
  $update = $db->query(
39
 
40
  return true;
41
  }
 
 
 
 
 
 
 
 
42
  }
Framework/CloningProcess/ExcludedPlugins.php CHANGED
@@ -3,6 +3,7 @@
3
  namespace WPStaging\Framework\CloningProcess;
4
 
5
  use WPStaging\Framework\Staging\CloneOptions;
 
6
 
7
  /**
8
  * Add here the list of excluded plugins to make sure code remain DRY
@@ -19,11 +20,18 @@ class ExcludedPlugins
19
  */
20
  private $excludedPlugins;
21
 
 
 
 
 
 
22
  public function __construct()
23
  {
24
- // list of excluded plugins defined by WP Staging
25
  $this->excludedPlugins = [
26
- 'wps-hide-login'
 
 
 
27
  ];
28
  }
29
 
@@ -45,14 +53,14 @@ class ExcludedPlugins
45
  }
46
 
47
  /**
48
- * Get list of excluded plugins with absolute path to them
49
  *
50
  * @return array
51
  */
52
- public function getPluginsToExcludeWithAbsolutePaths()
53
  {
54
  return array_map(function ($plugin) {
55
- return trailingslashit(WP_PLUGIN_DIR) . $plugin;
56
  }, $this->excludedPlugins);
57
  }
58
 
@@ -67,9 +75,9 @@ class ExcludedPlugins
67
  {
68
  // Apply filter
69
  if (is_multisite()) {
70
- $filteredExcludedPlugins = apply_filters('wpstg_clone_mu_excl_folders', $this->getPluginsToExcludeWithAbsolutePaths());
71
  } else {
72
- $filteredExcludedPlugins = apply_filters('wpstg_clone_excl_folders', $this->getPluginsToExcludeWithAbsolutePaths());
73
  }
74
 
75
  if ($installedPlugins === []) {
@@ -80,7 +88,7 @@ class ExcludedPlugins
80
  // Remove all paths other than plugins not in installed plugins
81
  $filteredExcludedPlugins = array_filter($filteredExcludedPlugins, function ($path) use ($installedPlugins) {
82
  foreach ($installedPlugins as $plugin) {
83
- $plugin = trailingslashit(WP_PLUGIN_DIR) . explode('/', $plugin)[0];
84
  if (strpos($path, $plugin) !== false) {
85
  return true;
86
  }
@@ -94,12 +102,12 @@ class ExcludedPlugins
94
  /*
95
  * Remove plugins dir from the paths and
96
  * only return plugin dir if inside directory otherwise return file
97
- * path/to/site/wp-content/plugins/some-plugin/some-plugin.php will return some-plugin
98
- * path/to/site/wp-content/plugins/single-file-plugin.php will return single-file-plugin.php
99
- * path/to/site/wp-content/plugins/plugin-dir will return plugin-dir
100
  */
101
  return array_map(function ($path) {
102
- $plugin = str_replace(trailingslashit(WP_PLUGIN_DIR), '', $path);
103
  return explode('/', $plugin)[0];
104
  }, $filteredExcludedPlugins);
105
  }
3
  namespace WPStaging\Framework\CloningProcess;
4
 
5
  use WPStaging\Framework\Staging\CloneOptions;
6
+ use WPStaging\Framework\Utils\WpDefaultDirectories;
7
 
8
  /**
9
  * Add here the list of excluded plugins to make sure code remain DRY
20
  */
21
  private $excludedPlugins;
22
 
23
+ /**
24
+ * Place below the list of plugins to exclude
25
+ * If any of these below plugins are installed in user site they will be skipped during cloning
26
+ * And a message will be shown to them about their exclusion
27
+ */
28
  public function __construct()
29
  {
 
30
  $this->excludedPlugins = [
31
+ 'wps-hide-login',
32
+ 'wp-super-cache',
33
+ 'peters-login-redirect',
34
+ 'wp-spamshield',
35
  ];
36
  }
37
 
53
  }
54
 
55
  /**
56
+ * Get list of excluded plugins with relative path to wp root
57
  *
58
  * @return array
59
  */
60
+ public function getPluginsToExcludeWithRelativePath()
61
  {
62
  return array_map(function ($plugin) {
63
+ return '/' . trailingslashit((new WpDefaultDirectories())->getRelativePluginPath()) . $plugin;
64
  }, $this->excludedPlugins);
65
  }
66
 
75
  {
76
  // Apply filter
77
  if (is_multisite()) {
78
+ $filteredExcludedPlugins = apply_filters('wpstg_clone_mu_excl_folders', $this->getPluginsToExcludeWithRelativePath());
79
  } else {
80
+ $filteredExcludedPlugins = apply_filters('wpstg_clone_excl_folders', $this->getPluginsToExcludeWithRelativePath());
81
  }
82
 
83
  if ($installedPlugins === []) {
88
  // Remove all paths other than plugins not in installed plugins
89
  $filteredExcludedPlugins = array_filter($filteredExcludedPlugins, function ($path) use ($installedPlugins) {
90
  foreach ($installedPlugins as $plugin) {
91
+ $plugin = '/' . trailingslashit((new WpDefaultDirectories())->getRelativePluginPath()) . explode('/', $plugin)[0];
92
  if (strpos($path, $plugin) !== false) {
93
  return true;
94
  }
102
  /*
103
  * Remove plugins dir from the paths and
104
  * only return plugin dir if inside directory otherwise return file
105
+ * /wp-content/plugins/some-plugin/some-plugin.php will return some-plugin
106
+ * /wp-content/plugins/single-file-plugin.php will return single-file-plugin.php
107
+ * /wp-content/plugins/plugin-dir will return plugin-dir
108
  */
109
  return array_map(function ($path) {
110
+ $plugin = str_replace('/' . trailingslashit((new WpDefaultDirectories())->getRelativePluginPath()), '', $path);
111
  return explode('/', $plugin)[0];
112
  }, $filteredExcludedPlugins);
113
  }
Framework/Database/ExcludedTables.php ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPStaging\Framework\Database;
4
+
5
+ use WPStaging\Framework\BackgroundProcessing\Queue;
6
+
7
+ /**
8
+ * Provide list of table excluded from Database Copy and SearchReplace Job
9
+ */
10
+ class ExcludedTables
11
+ {
12
+ /**
13
+ * @var string
14
+ */
15
+ const CLONE_DATABASE_TABLES_EXCLUDE_FILTER = 'wpstg_clone_database_tables_exclude';
16
+
17
+ /**
18
+ * @var string
19
+ */
20
+ const CLONE_SEARCH_REPLACE_TABLES_EXCLUDE_FILTER = 'wpstg_clone_searchreplace_tables_exclude';
21
+
22
+ /**
23
+ * @var string
24
+ */
25
+ const SEARCH_REPLACE_TABLES_EXCLUDE_FILTER = 'wpstg_searchreplace_excl_tables';
26
+
27
+ /**
28
+ * @var array
29
+ */
30
+ private $excludedTables;
31
+
32
+ /**
33
+ * @var array
34
+ */
35
+ private $excludedTablesSearchReplaceOnly;
36
+
37
+ public function __construct()
38
+ {
39
+ $this->excludedTables = [
40
+ 'blogs',
41
+ 'blog_version',
42
+ Queue::getTableName(),
43
+ ];
44
+
45
+ $this->excludedTablesSearchReplaceOnly = [
46
+ '_cerber_files', // Cerber Security Plugin
47
+ '_cerber_sets', // Cerber Security Plugin
48
+ ];
49
+ }
50
+
51
+ /**
52
+ * Get List of excluded tables for database copy
53
+ *
54
+ * @return array
55
+ */
56
+ public function getExcludedTables()
57
+ {
58
+ $excludedCustomTables = apply_filters(self::CLONE_DATABASE_TABLES_EXCLUDE_FILTER, []);
59
+ return array_merge($this->excludedTables, $excludedCustomTables);
60
+ }
61
+
62
+ /**
63
+ * Get List of excluded tables for search replace cloning process job
64
+ * This also includes list of tables excluded through filters for cloning database copy process
65
+ *
66
+ * @return array
67
+ */
68
+ public function getExcludedTablesForSearchReplace()
69
+ {
70
+ $excludedCustomCloneTables = apply_filters(self::CLONE_SEARCH_REPLACE_TABLES_EXCLUDE_FILTER, []);
71
+ $excludedCustomClonePushTables = apply_filters(self::SEARCH_REPLACE_TABLES_EXCLUDE_FILTER, $this->excludedTablesSearchReplaceOnly);
72
+ $searchReplaceExcludedTables = array_merge($excludedCustomCloneTables, $excludedCustomClonePushTables);
73
+ return array_merge($this->getExcludedTables(), $searchReplaceExcludedTables);
74
+ }
75
+
76
+ /**
77
+ * Get List of excluded tables for search replace push process job
78
+ *
79
+ * @return array
80
+ */
81
+ public function getExcludedTablesForSearchReplacePushOnly()
82
+ {
83
+ return apply_filters(self::SEARCH_REPLACE_TABLES_EXCLUDE_FILTER, $this->excludedTablesSearchReplaceOnly);
84
+ }
85
+ }
Framework/Database/TableService.php CHANGED
@@ -63,7 +63,8 @@ class TableService
63
  */
64
  public function findTableStatusStartsWith($prefix = null)
65
  {
66
- $tables = $this->database->find('SHOW TABLE STATUS LIKE "' . $this->provideSqlPrefix($prefix) . '%"');
 
67
  if (!$tables) {
68
  return null;
69
  }
63
  */
64
  public function findTableStatusStartsWith($prefix = null)
65
  {
66
+ // eg: SHOW TABLE STATUS LIKE 'wp\_%';
67
+ $tables = $this->database->find("SHOW TABLE STATUS LIKE '{$this->provideSqlPrefix($prefix)}%'");
68
  if (!$tables) {
69
  return null;
70
  }
Framework/Exceptions/IOException.php ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPStaging\Framework\Exceptions;
4
+
5
+ class IOException extends \Exception
6
+ {
7
+
8
+ }
Framework/Filesystem/Filesystem.php CHANGED
@@ -6,8 +6,6 @@ use WPStaging\Backend\Notices\Notices;
6
  use WPStaging\Core\WPStaging;
7
  use WPStaging\Vendor\Psr\Log\LoggerInterface;
8
  use RuntimeException;
9
- use WPStaging\Vendor\Symfony\Component\Filesystem\Filesystem as SymfonyFilesystem;
10
- use WPStaging\Vendor\Symfony\Component\Finder\Finder;
11
 
12
  class Filesystem extends FilterableDirectoryIterator
13
  {
@@ -17,9 +15,6 @@ class Filesystem extends FilterableDirectoryIterator
17
  /** @var callable|null */
18
  private $shouldStop;
19
 
20
- /** @var string[]|array|null */
21
- private $notPath;
22
-
23
  /** @var int|null */
24
  private $depth;
25
 
@@ -29,39 +24,6 @@ class Filesystem extends FilterableDirectoryIterator
29
  /** @var LoggerInterface|null */
30
  private $logger;
31
 
32
- /**
33
- * @param string|null $directory
34
- * @return Finder
35
- */
36
- public function findFiles($directory = null)
37
- {
38
- $finder = (new Finder())
39
- ->ignoreUnreadableDirs()
40
- ->files()
41
- ->in($this->findPath($directory))
42
- ;
43
-
44
- if ($this->depth !== null) {
45
- $finder = $finder->depth((string) $this->depth);
46
- }
47
-
48
- foreach ($this->getNotPath() as $exclude) {
49
- $finder->notPath(untrailingslashit($exclude));
50
- }
51
-
52
- foreach ($this->getFileNames() as $fileName) {
53
- $finder->name(untrailingslashit($fileName));
54
- }
55
-
56
- $finder_has_results = count($finder) > 0;
57
-
58
- if (!$finder_has_results) {
59
- return null;
60
- }
61
-
62
- return $finder;
63
- }
64
-
65
  /**
66
  * Safe path makes sure given path is within WP root directory
67
  * @param string $fullPath
@@ -78,71 +40,9 @@ class Filesystem extends FilterableDirectoryIterator
78
  return $safePath;
79
  }
80
 
81
- /**
82
- * Checks given file or directory exists
83
- * @param string $fullPath
84
- * @return bool
85
- */
86
- public function exists($fullPath)
87
- {
88
- return (new SymfonyFilesystem())->exists($fullPath);
89
- }
90
-
91
- /**
92
- * @param string $newPath
93
- * @return bool
94
- */
95
- public function rename($newPath)
96
- {
97
- // Target doesn't exist, just use rename
98
- if (!$this->exists($newPath)) {
99
- return rename($this->getPath(), $newPath);
100
- }
101
-
102
- // Get all files and dirs
103
- $finder = (new Finder())->ignoreUnreadableDirs()->in($this->getPath());
104
- if ($this->getNotPath()) {
105
- foreach ($this->getNotPath() as $notPath) {
106
- $finder->notPath($notPath);
107
- }
108
- }
109
-
110
- $basePath = trailingslashit($newPath);
111
- foreach ($finder as $item) {
112
- if (!$this->exists($item->getPathname())) {
113
- $this->log('Failed to move directory. Directory does not exists' . $item->getPathname());
114
- continue;
115
- }
116
-
117
- // RelativePathname is relative to $this->path
118
- $destination = $basePath . $item->getRelativePathname();
119
-
120
- // It is not a directory, use built-in rename instead
121
- if (!$item->isDir()) {
122
- $this->renameDirect($item->getPathname(), $destination);
123
- continue;
124
- }
125
-
126
- // If it doesn't exist, use built-in rename instead
127
- if (!$this->exists($destination)) {
128
- $this->renameDirect($item->getPathname(), $destination);
129
- continue;
130
- }
131
-
132
- if ($this->shouldStop) {
133
- return false;
134
- }
135
- }
136
-
137
- // Due to rename, all files should be deleted so just empty directories left, make sure all of them are deleted.
138
- // Due to setting shouldStop, this might return false till everything is deleted.
139
- // This might not be just empty dirs as we can exclude some directories using notPath()
140
- return $this->delete(null, false);
141
- }
142
-
143
  /**
144
  * Move content from one path to another
145
- * This is better than $this->rename() method as this use custom fileiterator and $this->deleteNew()
146
  * @param string $source
147
  * @param string $target
148
  *
@@ -207,7 +107,7 @@ class Filesystem extends FilterableDirectoryIterator
207
  $deleteSelf = false;
208
  }
209
 
210
- return $this->deleteNew($source, $deleteSelf);
211
  }
212
 
213
  /**
@@ -219,7 +119,7 @@ class Filesystem extends FilterableDirectoryIterator
219
  public function renameDirect($source, $target)
220
  {
221
  $dir = dirname($target);
222
- if (!$this->exists($dir)) {
223
  $this->mkdir($dir);
224
  }
225
 
@@ -267,23 +167,6 @@ class Filesystem extends FilterableDirectoryIterator
267
  return trailingslashit($path);
268
  }
269
 
270
- /**
271
- * Copy file
272
- *
273
- * @param string $source
274
- * @param string $destination
275
- * @return boolean
276
- *
277
- * @todo update this to allow copying big files
278
- */
279
- public function copy($source, $destination)
280
- {
281
- $fs = new SymfonyFilesystem();
282
- // TODO perhaps use stream_set_chunk_size()?
283
- $fs->copy($source, $destination);
284
- return $fs->exists($destination);
285
- }
286
-
287
  /**
288
  * The new copy method which works for files, links and directories
289
  *
@@ -291,11 +174,12 @@ class Filesystem extends FilterableDirectoryIterator
291
  * @param string $target
292
  * @return boolean
293
  */
294
- public function copyNew($source, $target)
295
  {
296
  // if $source is link or file, move it and stop execution
297
  if (is_link($source) || is_file($source)) {
298
- return $this->copy($source, $target);
 
299
  }
300
 
301
  // if $source is empty dir
@@ -333,7 +217,8 @@ class Filesystem extends FilterableDirectoryIterator
333
  if ($item->isDir()) {
334
  $result = wp_mkdir_p($destination);
335
  } else { // if file or link
336
- $result = $this->copy($item->getPathname(), $destination);
 
337
  }
338
 
339
  if (!$result || !is_callable($this->shouldStop)) {
@@ -348,15 +233,6 @@ class Filesystem extends FilterableDirectoryIterator
348
  return true;
349
  }
350
 
351
- /**
352
- * @param string
353
- * @return bool
354
- */
355
- public function isWritableDir($fullPath)
356
- {
357
- return is_dir($fullPath) && is_writable($fullPath);
358
- }
359
-
360
  /**
361
  * Check if directory exists and is not empty
362
  * @param string $dir
@@ -372,83 +248,25 @@ class Filesystem extends FilterableDirectoryIterator
372
  }
373
 
374
  /**
375
- * Delete single file or entire folder including all subfolders and containing files
376
- * @param null $path
377
- * @param bool $isUseNotPath
378
- * @return bool
379
- * @todo Make it deprecated and switch it with $this->>deleteNew() as it is more performant and unit tested
 
 
 
 
380
  */
381
- public function delete($path = null, $isUseNotPath = true)
382
  {
383
  $path = $this->findPath($path);
384
- if (!$path) {
385
- $this->log('You need to define path to delete');
386
- throw new RuntimeException('You need to define path to delete');
387
- }
388
 
389
  if ($path === ABSPATH) {
390
  $this->log('You can not delete WP Root directory');
391
  throw new RuntimeException('You can not delete WP Root directory');
392
  }
393
 
394
- if (is_link($path) || is_file($path)) {
395
- return unlink($path);
396
- }
397
-
398
- if (!is_dir($path)) {
399
- return true;
400
- }
401
-
402
- $iterator = (new Finder())
403
- ->ignoreUnreadableDirs()
404
- ->ignoreDotFiles(false)
405
- ->in($this->findPath($path))
406
- ;
407
-
408
- if ($this->getShouldStop()) {
409
- $iterator->depth('0');
410
- }
411
-
412
- if ($isUseNotPath) {
413
- foreach ($this->getNotPath() as $exclude) {
414
- $iterator->notPath(untrailingslashit($exclude));
415
- }
416
- }
417
-
418
- foreach ($this->getFileNames() as $fileName) {
419
- $iterator->name(untrailingslashit($fileName));
420
- }
421
-
422
- $iteratorHasResults = count($iterator) > 0;
423
-
424
- if (is_dir($path) && !$iteratorHasResults && $this->isEmptyDir($path)) {
425
- return rmdir($path);
426
- }
427
-
428
- foreach ($iterator as $file) {
429
- $this->delete($file->getPathname(), $isUseNotPath);
430
- if ($this->shouldStop) {
431
- return false;
432
- }
433
- }
434
-
435
- if (is_dir($path)) {
436
- return rmdir($path);
437
- }
438
- }
439
-
440
- /**
441
- * Delete a whole directory including all sub directories or a file.
442
- * A new faster method than $this->delete()
443
- * $this->delete() uses the finder method which seems to be very slow compared to native RecursiveIteratorIterator!
444
- * @todo replace $this->>delete() with this method if this can fulfill all requirements
445
- *
446
- * @param string $path
447
- * @param bool $deleteSelf making it optional to delete the parent itself, useful during file and dir exclusion
448
- * @return bool True if folder or file is deleted or file is empty ($deleteSelf = false); Return False if folder is not empty and execution should be continued
449
- */
450
- public function deleteNew($path, $deleteSelf = true, $throw = false)
451
- {
452
  // if $path is link or file, delete it and stop execution
453
  if (is_link($path) || is_file($path)) {
454
  if (!unlink($path)) {
@@ -479,17 +297,28 @@ class Filesystem extends FilterableDirectoryIterator
479
  return true;
480
  }
481
 
482
-
483
  $this->setDirectory($path);
484
- $iterator = null;
485
  try {
 
 
 
 
 
 
 
 
 
 
486
  $iterator = $this->setIteratorMode(\RecursiveIteratorIterator::CHILD_FIRST)->get();
487
  } catch (FilesystemExceptions $e) {
488
  $this->log('Permission Error: Can not create recursive iterator for ' . $path);
489
  if ($throw) {
 
490
  // This allows us to know that Filesystem FAILED and should not continue;
491
  throw $e;
492
  } else {
 
493
  return false;
494
  }
495
  }
@@ -501,17 +330,20 @@ class Filesystem extends FilterableDirectoryIterator
501
  }
502
 
503
  if (call_user_func($this->shouldStop)) {
 
504
  return false;
505
  }
506
  }
507
 
508
  // Don't delete the parent main dir itself and finish execution
509
  if (!$deleteSelf) {
 
510
  return true;
511
  }
512
 
513
  // Folder is not empty. Return false and continue execution if requested
514
  if (!$this->isEmptyDir($path)) {
 
515
  return false;
516
  }
517
 
@@ -522,6 +354,7 @@ class Filesystem extends FilterableDirectoryIterator
522
  }
523
  }
524
 
 
525
  return true;
526
  }
527
 
@@ -616,7 +449,7 @@ class Filesystem extends FilterableDirectoryIterator
616
  }
617
 
618
  // force to not delete the parent path itself
619
- if (!$this->deleteNew($path, false)) {
620
  return false;
621
  }
622
  }
@@ -669,34 +502,6 @@ class Filesystem extends FilterableDirectoryIterator
669
  return $this;
670
  }
671
 
672
- /**
673
- * @return array
674
- */
675
- public function getNotPath()
676
- {
677
- return $this->notPath ?: [];
678
- }
679
-
680
- /**
681
- * @param array $notPath
682
- * @return self
683
- */
684
- public function setNotPath(array $notPath = [])
685
- {
686
- $this->notPath = $notPath;
687
- return $this;
688
- }
689
-
690
- /**
691
- * @param string $notPath
692
- * @return self
693
- */
694
- public function addNotPath($notPath)
695
- {
696
- $this->notPath[] = $notPath;
697
- return $this;
698
- }
699
-
700
  /**
701
  * @return int|null
702
  */
@@ -766,7 +571,7 @@ class Filesystem extends FilterableDirectoryIterator
766
  $this->log('Permission Error: Can not delete link ' . $perms);
767
 
768
  if ($item->isLink()) {
769
- if (!unlink($path)) {
770
  $this->log('Permission Error: Can not delete link ' . $path);
771
  throw new RuntimeException('Permission Error: Can not delete link ' . $path);
772
  }
@@ -796,6 +601,21 @@ class Filesystem extends FilterableDirectoryIterator
796
  return true;
797
  }
798
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
799
  /**
800
  * @param $string
801
  */
6
  use WPStaging\Core\WPStaging;
7
  use WPStaging\Vendor\Psr\Log\LoggerInterface;
8
  use RuntimeException;
 
 
9
 
10
  class Filesystem extends FilterableDirectoryIterator
11
  {
15
  /** @var callable|null */
16
  private $shouldStop;
17
 
 
 
 
18
  /** @var int|null */
19
  private $depth;
20
 
24
  /** @var LoggerInterface|null */
25
  private $logger;
26
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  /**
28
  * Safe path makes sure given path is within WP root directory
29
  * @param string $fullPath
40
  return $safePath;
41
  }
42
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  /**
44
  * Move content from one path to another
45
+ * This is better than $this->rename() method as this use custom fileiterator and $this->delete()
46
  * @param string $source
47
  * @param string $target
48
  *
107
  $deleteSelf = false;
108
  }
109
 
110
+ return $this->delete($source, $deleteSelf);
111
  }
112
 
113
  /**
119
  public function renameDirect($source, $target)
120
  {
121
  $dir = dirname($target);
122
+ if (!file_exists($dir)) {
123
  $this->mkdir($dir);
124
  }
125
 
167
  return trailingslashit($path);
168
  }
169
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
170
  /**
171
  * The new copy method which works for files, links and directories
172
  *
174
  * @param string $target
175
  * @return boolean
176
  */
177
+ public function copy($source, $target)
178
  {
179
  // if $source is link or file, move it and stop execution
180
  if (is_link($source) || is_file($source)) {
181
+ $this->mkdir(dirname($target));
182
+ return copy($source, $target);
183
  }
184
 
185
  // if $source is empty dir
217
  if ($item->isDir()) {
218
  $result = wp_mkdir_p($destination);
219
  } else { // if file or link
220
+ $this->mkdir(dirname($destination));
221
+ $result = copy($item->getPathname(), $destination);
222
  }
223
 
224
  if (!$result || !is_callable($this->shouldStop)) {
233
  return true;
234
  }
235
 
 
 
 
 
 
 
 
 
 
236
  /**
237
  * Check if directory exists and is not empty
238
  * @param string $dir
248
  }
249
 
250
  /**
251
+ * Deletes a directory recursively or not.
252
+ *
253
+ * @see \WPStaging\Framework\Filesystem\FilterableDirectoryIterator::setRecursive To control whether this function should delete recursively.
254
+ *
255
+ * @param string $path
256
+ * @param bool $deleteSelf Whether to delete the target folder after deleting it's contents.
257
+ * @throws FilesystemExceptions Only if $throw is true.
258
+ *
259
+ * @return bool True if target was completely deleted, false if file not deleted or folder still have contents.
260
  */
261
+ public function delete($path = null, $deleteSelf = true, $throw = false)
262
  {
263
  $path = $this->findPath($path);
 
 
 
 
264
 
265
  if ($path === ABSPATH) {
266
  $this->log('You can not delete WP Root directory');
267
  throw new RuntimeException('You can not delete WP Root directory');
268
  }
269
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
270
  // if $path is link or file, delete it and stop execution
271
  if (is_link($path) || is_file($path)) {
272
  if (!unlink($path)) {
297
  return true;
298
  }
299
 
 
300
  $this->setDirectory($path);
301
+ $originalIsRecursive = (bool)$this->isIteratorRecursive();
302
  try {
303
+ /*
304
+ * For historical reasons, this function will run as Recursive Mode by default.
305
+ * To minimize any side-effects of calling this method on an existing instance
306
+ * of Filesystem, we will store the original isRecursive, and set it to the
307
+ * original value before returning.
308
+ */
309
+ if ($this->isIteratorRecursive() === null) {
310
+ $this->setRecursive();
311
+ }
312
+
313
  $iterator = $this->setIteratorMode(\RecursiveIteratorIterator::CHILD_FIRST)->get();
314
  } catch (FilesystemExceptions $e) {
315
  $this->log('Permission Error: Can not create recursive iterator for ' . $path);
316
  if ($throw) {
317
+ $this->setRecursive($originalIsRecursive);
318
  // This allows us to know that Filesystem FAILED and should not continue;
319
  throw $e;
320
  } else {
321
+ $this->setRecursive($originalIsRecursive);
322
  return false;
323
  }
324
  }
330
  }
331
 
332
  if (call_user_func($this->shouldStop)) {
333
+ $this->setRecursive($originalIsRecursive);
334
  return false;
335
  }
336
  }
337
 
338
  // Don't delete the parent main dir itself and finish execution
339
  if (!$deleteSelf) {
340
+ $this->setRecursive($originalIsRecursive);
341
  return true;
342
  }
343
 
344
  // Folder is not empty. Return false and continue execution if requested
345
  if (!$this->isEmptyDir($path)) {
346
+ $this->setRecursive($originalIsRecursive);
347
  return false;
348
  }
349
 
354
  }
355
  }
356
 
357
+ $this->setRecursive($originalIsRecursive);
358
  return true;
359
  }
360
 
449
  }
450
 
451
  // force to not delete the parent path itself
452
+ if (!$this->delete($path, false)) {
453
  return false;
454
  }
455
  }
502
  return $this;
503
  }
504
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
505
  /**
506
  * @return int|null
507
  */
571
  $this->log('Permission Error: Can not delete link ' . $perms);
572
 
573
  if ($item->isLink()) {
574
+ if (!$this->removeSymlink($path)) {
575
  $this->log('Permission Error: Can not delete link ' . $path);
576
  throw new RuntimeException('Permission Error: Can not delete link ' . $path);
577
  }
601
  return true;
602
  }
603
 
604
+ /**
605
+ * Remove symlink for both windows and other OSes
606
+ * @param string $path Path to the link
607
+ * @return boolean
608
+ */
609
+ protected function removeSymlink($path)
610
+ {
611
+ // remove symlink using rmdir if OS is windows
612
+ if (PHP_SHLIB_SUFFIX === 'dll') {
613
+ return rmdir($path);
614
+ }
615
+
616
+ return unlink($path);
617
+ }
618
+
619
  /**
620
  * @param $string
621
  */
Framework/Filesystem/FilterableDirectoryIterator.php CHANGED
@@ -10,9 +10,17 @@ use RecursiveIteratorIterator;
10
  use WPStaging\Framework\Filesystem\Filters\DirectoryDotFilter;
11
  use WPStaging\Framework\Filesystem\Filters\PathExcludeFilter;
12
  use WPStaging\Framework\Filesystem\Filters\RecursivePathExcludeFilter;
 
 
13
 
14
  class FilterableDirectoryIterator
15
  {
 
 
 
 
 
 
16
  /**
17
  * The directory to iterate
18
  * @var string
@@ -25,11 +33,17 @@ class FilterableDirectoryIterator
25
  */
26
  private $paths = [];
27
 
 
 
 
 
 
 
28
  /**
29
  * Iterator recursively including sub folders or only items located in root of $this->$directory
30
- * @var bool
31
  */
32
- private $isRecursive = false;
33
 
34
  /**
35
  * skip dot in non recursive iterator depending on value
@@ -51,6 +65,25 @@ class FilterableDirectoryIterator
51
  public function __construct()
52
  {
53
  $this->iteratorMode = RecursiveIteratorIterator::LEAVES_ONLY;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54
  }
55
 
56
  /**
@@ -135,6 +168,34 @@ class FilterableDirectoryIterator
135
  return $this;
136
  }
137
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
138
  /**
139
  * @return int
140
  */
@@ -182,8 +243,12 @@ class FilterableDirectoryIterator
182
 
183
  $iterator = new RecursiveDirectoryIterator($this->directory, FilesystemIterator::SKIP_DOTS);
184
 
 
 
 
 
185
  if (count($this->paths) !== 0) {
186
- $iterator = new RecursivePathExcludeFilter($iterator, $this->paths);
187
  }
188
 
189
  $iterator = new RecursiveIteratorIterator($iterator, $this->iteratorMode);
@@ -203,8 +268,12 @@ class FilterableDirectoryIterator
203
  $iterator = new DirectoryDotFilter($iterator);
204
  }
205
 
 
 
 
 
206
  if (count($this->paths) !== 0) {
207
- $iterator = new PathExcludeFilter($iterator, $this->paths);
208
  }
209
 
210
  $iterator = new IteratorIterator($iterator);
10
  use WPStaging\Framework\Filesystem\Filters\DirectoryDotFilter;
11
  use WPStaging\Framework\Filesystem\Filters\PathExcludeFilter;
12
  use WPStaging\Framework\Filesystem\Filters\RecursivePathExcludeFilter;
13
+ use WPStaging\Framework\Filesystem\Filters\FileSizeFilter;
14
+ use WPStaging\Framework\Filesystem\Filters\RecursiveFileSizeFilter;
15
 
16
  class FilterableDirectoryIterator
17
  {
18
+ /**
19
+ * Root path of WP
20
+ * @var string
21
+ */
22
+ private $wpRootPath;
23
+
24
  /**
25
  * The directory to iterate
26
  * @var string
33
  */
34
  private $paths = [];
35
 
36
+ /**
37
+ * list of files sizes exclude rules
38
+ * @var array
39
+ */
40
+ private $sizes = [];
41
+
42
  /**
43
  * Iterator recursively including sub folders or only items located in root of $this->$directory
44
+ * @var bool|null
45
  */
46
+ private $isRecursive = null;
47
 
48
  /**
49
  * skip dot in non recursive iterator depending on value
65
  public function __construct()
66
  {
67
  $this->iteratorMode = RecursiveIteratorIterator::LEAVES_ONLY;
68
+ $this->wpRootPath = ABSPATH;
69
+ }
70
+
71
+ /**
72
+ * @return string
73
+ */
74
+ public function getWpRootPath()
75
+ {
76
+ return $this->wpRootPath;
77
+ }
78
+
79
+ /**
80
+ * @param string $wpRootPath
81
+ * @return self
82
+ */
83
+ public function setWpRootPath($wpRootPath)
84
+ {
85
+ $this->wpRootPath = $wpRootPath;
86
+ return $this;
87
  }
88
 
89
  /**
168
  return $this;
169
  }
170
 
171
+ /**
172
+ * @return array
173
+ */
174
+ public function getExcludeSizeRules()
175
+ {
176
+ return $this->sizes;
177
+ }
178
+
179
+ /**
180
+ * @param array $rules
181
+ * @return self
182
+ */
183
+ public function setExcludeSizeRules($rules)
184
+ {
185
+ $this->sizes = $rules;
186
+ return $this;
187
+ }
188
+
189
+ /**
190
+ * @param string $rule
191
+ * @return self
192
+ */
193
+ public function addExcludeSizeRule($rule)
194
+ {
195
+ $this->sizes[] = $rule;
196
+ return $this;
197
+ }
198
+
199
  /**
200
  * @return int
201
  */
243
 
244
  $iterator = new RecursiveDirectoryIterator($this->directory, FilesystemIterator::SKIP_DOTS);
245
 
246
+ if (count($this->sizes) !== 0) {
247
+ $iterator = new RecursiveFileSizeFilter($iterator, $this->sizes);
248
+ }
249
+
250
  if (count($this->paths) !== 0) {
251
+ $iterator = new RecursivePathExcludeFilter($iterator, $this->paths, $this->wpRootPath);
252
  }
253
 
254
  $iterator = new RecursiveIteratorIterator($iterator, $this->iteratorMode);
268
  $iterator = new DirectoryDotFilter($iterator);
269
  }
270
 
271
+ if (count($this->sizes) !== 0) {
272
+ $iterator = new FileSizeFilter($iterator, $this->sizes);
273
+ }
274
+
275
  if (count($this->paths) !== 0) {
276
+ $iterator = new PathExcludeFilter($iterator, $this->paths, $this->wpRootPath);
277
  }
278
 
279
  $iterator = new IteratorIterator($iterator);
Framework/Filesystem/Filters/ExcludeFilter.php ADDED
@@ -0,0 +1,143 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPStaging\Framework\Filesystem\Filters;
4
+
5
+ use WPStaging\Framework\TemplateEngine\TemplateEngine;
6
+ use WPStaging\Framework\Utils\Strings;
7
+
8
+ class ExcludeFilter
9
+ {
10
+ const NAME_BEGINS_WITH = 'name_begins_with';
11
+ const NAME_ENDS_WITH = 'name_ends_with';
12
+ const NAME_EXACT_MATCHES = 'name_exact_matches';
13
+ const NAME_CONTAINS = 'name_contains';
14
+
15
+ const SIZE_KB = 'kb';
16
+ const SIZE_MB = 'mb';
17
+ const SIZE_GB = 'gb';
18
+
19
+ const SIZE_GREATER_THAN = 'size_greater_than';
20
+ const SIZE_LESS_THAN = 'size_less_than';
21
+ const SIZE_EQUAL_TO = 'size_equal_to';
22
+
23
+ /**
24
+ * @var Strings
25
+ */
26
+ private $strUtils;
27
+
28
+ /**
29
+ * @var TemplateEngine
30
+ */
31
+ private $templateEngine;
32
+
33
+ public function __construct()
34
+ {
35
+ $this->strUtils = new Strings();
36
+ $this->templateEngine = new TemplateEngine();
37
+ }
38
+
39
+ /**
40
+ * Convert wpstg exclude rule to glob rule
41
+ *
42
+ * @param string $rule
43
+ * @return string
44
+ */
45
+ public function mapExclude($rule)
46
+ {
47
+ if ($this->strUtils->startsWith($rule, 'ext:')) {
48
+ return '/**/*.' . trim(substr($rule, 4));
49
+ }
50
+
51
+ $nameRule = $rule;
52
+ if ($this->strUtils->startsWith($rule, 'file:')) {
53
+ $nameRule = trim(substr($rule, 5));
54
+ } elseif ($this->strUtils->startsWith($rule, 'dir:')) {
55
+ $nameRule = trim(substr($rule, 4));
56
+ }
57
+
58
+ $globRule = $this->convertToNameGlob($nameRule);
59
+ if ($this->strUtils->startsWith($rule, 'file:')) {
60
+ return $globRule . '.*';
61
+ }
62
+
63
+ return $globRule . '/**';
64
+ }
65
+
66
+ /**
67
+ * Return rendered exclude template as output for the wpstg exclude filter size rule
68
+ *
69
+ * @param string $rule
70
+ *
71
+ * @return string
72
+ */
73
+ public function renderSizeExclude($rule)
74
+ {
75
+ list($comparison, $size) = explode(' ', $rule);
76
+ $bytes = (int)$size;
77
+ return $this->templateEngine->render("Backend/views/templates/exclude-filters/file-size-exclude-filter.php", [
78
+ "comparison" => trim($comparison),
79
+ "bytes" => trim($bytes),
80
+ "size" => trim($size)
81
+ ]);
82
+ }
83
+
84
+ /**
85
+ * Return rendered exclude template as output for the wpstg exclude filter glob rule
86
+ *
87
+ * @param string $rule
88
+ *
89
+ * @return string
90
+ */
91
+ public function renderGlobExclude($rule)
92
+ {
93
+ if ($this->strUtils->startsWith($rule, 'ext:')) {
94
+ return $this->templateEngine->render("Backend/views/templates/exclude-filters/file-ext-exclude-filter.php", [
95
+ "extension" => trim(substr($rule, 4)),
96
+ ]);
97
+ }
98
+
99
+ if ($this->strUtils->startsWith($rule, 'file:')) {
100
+ list($rule, $name) = explode(' ', trim(substr($rule, 5)));
101
+ return $this->templateEngine->render("Backend/views/templates/exclude-filters/file-name-exclude-filter.php", [
102
+ "rule" => trim($rule),
103
+ "name" => trim($name),
104
+ ]);
105
+ }
106
+
107
+ if ($this->strUtils->startsWith($rule, 'dir:')) {
108
+ list($rule, $name) = explode(' ', trim(substr($rule, 4)));
109
+ return $this->templateEngine->render("Backend/views/templates/exclude-filters/dir-name-exclude-filter.php", [
110
+ "rule" => trim($rule),
111
+ "name" => trim($name),
112
+ ]);
113
+ }
114
+
115
+ return '';
116
+ }
117
+
118
+ /**
119
+ * Convert wpstg name rule to glob rule
120
+ *
121
+ * @return $string
122
+ */
123
+ private function convertToNameGlob($rule)
124
+ {
125
+ if ($this->strUtils->startsWith($rule, self::NAME_BEGINS_WITH)) {
126
+ $len = strlen(self::NAME_BEGINS_WITH);
127
+ return '/**/' . trim(substr($rule, $len)) . "*";
128
+ }
129
+
130
+ if ($this->strUtils->startsWith($rule, self::NAME_ENDS_WITH)) {
131
+ $len = strlen(self::NAME_ENDS_WITH);
132
+ return '/**/*' . trim(substr($rule, $len));
133
+ }
134
+
135
+ if ($this->strUtils->startsWith($rule, self::NAME_EXACT_MATCHES)) {
136
+ $len = strlen(self::NAME_EXACT_MATCHES);
137
+ return '/**/' . trim(substr($rule, $len));
138
+ }
139
+
140
+ $len = strlen(self::NAME_CONTAINS);
141
+ return '/**/*' . trim(substr($rule, $len)) . "*";
142
+ }
143
+ }
Framework/Filesystem/Filters/FileSizeFilter.php ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPStaging\Framework\Filesystem\Filters;
4
+
5
+ use Iterator;
6
+ use FilterIterator;
7
+
8
+ class FileSizeFilter extends FilterIterator
9
+ {
10
+ private $sizeFilters = [];
11
+ public function __construct(Iterator $iterator, $sizeFilters = [])
12
+ {
13
+ parent::__construct($iterator);
14
+ $this->sizeFilters = $sizeFilters;
15
+ }
16
+
17
+ public function accept()
18
+ {
19
+ $current = $this->current();
20
+
21
+ // return true of not file
22
+ if (!$current->isFile()) {
23
+ return true;
24
+ }
25
+
26
+ $fileSize = $current->getSize();
27
+ foreach ($this->sizeFilters as $sizeFilter) {
28
+ $sizeComparator = explode(' ', $sizeFilter);
29
+ if (count($sizeComparator) !== 2) {
30
+ continue;
31
+ }
32
+
33
+ if ($this->compareBytes($fileSize, $sizeComparator[1], $sizeComparator[0])) {
34
+ return false;
35
+ }
36
+ }
37
+
38
+ return true;
39
+ }
40
+
41
+ /**
42
+ * Compare Bytes
43
+ *
44
+ * @param string|int $compare
45
+ * @param string|int $compareWith
46
+ * @param string $comparator
47
+ * @return bool
48
+ */
49
+ public function compareBytes($compare, $compareWith, $comparator = '=')
50
+ {
51
+ $compare = wp_convert_hr_to_bytes($compare);
52
+ $compareWith = wp_convert_hr_to_bytes($compareWith);
53
+
54
+ // comparison for equal to
55
+ if (($comparator === '=' || $comparator === ExcludeFilter::SIZE_EQUAL_TO) && ($compare == $compareWith)) {
56
+ return true;
57
+ }
58
+
59
+ // comparison for greater than
60
+ if (($comparator === '>' || $comparator === ExcludeFilter::SIZE_GREATER_THAN) && ($compare > $compareWith)) {
61
+ return true;
62
+ }
63
+
64
+ // comparison for less than
65
+ if (($comparator === '<' || $comparator === ExcludeFilter::SIZE_LESS_THAN) && ($compare < $compareWith)) {
66
+ return true;
67
+ }
68
+
69
+ return false;
70
+ }
71
+ }
Framework/Filesystem/Filters/PathExcludeFilter.php CHANGED
@@ -4,25 +4,62 @@ namespace WPStaging\Framework\Filesystem\Filters;
4
 
5
  use FilterIterator;
6
  use Iterator;
7
- use WPStaging\Framework\Traits\ExcludeFilterTrait;
8
 
9
  class PathExcludeFilter extends FilterIterator
10
  {
11
- use ExcludeFilterTrait;
 
 
 
12
 
13
- protected $exclude = [];
 
 
 
14
 
15
- public function __construct(Iterator $iterator, $exclude = [])
16
  {
17
  parent::__construct($iterator);
18
- $this->exclude = $exclude;
19
- $this->categorizeExcludes($exclude);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  }
21
 
22
  public function accept()
23
  {
24
  // Get the current SplFileInfo object
25
  $fileInfo = $this->getInnerIterator()->current();
26
- return !$this->isExcluded($fileInfo);
 
 
 
 
 
 
 
 
27
  }
28
  }
4
 
5
  use FilterIterator;
6
  use Iterator;
7
+ use WPStaging\Framework\Filesystem\Filters\PathFilterHelper;
8
 
9
  class PathExcludeFilter extends FilterIterator
10
  {
11
+ /**
12
+ * @var PathFilterHelper
13
+ */
14
+ protected $excludeFilter;
15
 
16
+ /**
17
+ * @var PathFilterHelper
18
+ */
19
+ protected $includeFilter;
20
 
21
+ public function __construct(Iterator $iterator, $exclude = [], $wpRootPath = ABSPATH)
22
  {
23
  parent::__construct($iterator);
24
+ $this->excludeFilter = new PathFilterHelper();
25
+ $this->excludeFilter->setWpRootPath($wpRootPath);
26
+ $this->excludeFilter->categorizeRules($exclude);
27
+ $this->includeFilter = new PathFilterHelper(true);
28
+ $this->includeFilter->setWpRootPath($wpRootPath);
29
+ $this->includeFilter->categorizeRules($exclude);
30
+ }
31
+
32
+ /**
33
+ * Set the WP Root Path
34
+ * @param string $wpRootPath
35
+ */
36
+ public function setWpRootPath($wpRootPath)
37
+ {
38
+ $this->excludeFilter->setWpRootPath($wpRootPath);
39
+ $this->includeFilter->setWpRootPath($wpRootPath);
40
+ }
41
+
42
+ /**
43
+ * Get the WP Root Path
44
+ * @return string
45
+ */
46
+ public function getWpRootPath()
47
+ {
48
+ return $this->excludeFilter->getWpRootPath();
49
  }
50
 
51
  public function accept()
52
  {
53
  // Get the current SplFileInfo object
54
  $fileInfo = $this->getInnerIterator()->current();
55
+ if ($this->includeFilter->isMatched($fileInfo)) {
56
+ return true;
57
+ }
58
+
59
+ if ($fileInfo->isDir() && $this->includeFilter->hasRules()) {
60
+ return true;
61
+ }
62
+
63
+ return !$this->excludeFilter->isMatched($fileInfo);
64
  }
65
  }
Framework/Filesystem/Filters/PathFilterHelper.php ADDED
@@ -0,0 +1,262 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPStaging\Framework\Filesystem\Filters;
4
+
5
+ use SplFileInfo;
6
+ use WPStaging\Framework\Utils\Strings;
7
+ use WPStaging\Framework\Utils\ThirdParty\Glob;
8
+
9
+ /**
10
+ * This helper is used in both RecursivePathExcludeFilter and PathExcludeFilter
11
+ * This will help in keeping the code DRY
12
+ */
13
+ class PathFilterHelper
14
+ {
15
+ /**
16
+ * @var array
17
+ */
18
+ private $absolutePathRules;
19
+
20
+ /**
21
+ * @var array
22
+ */
23
+ private $globRules;
24
+
25
+ /**
26
+ * @var string
27
+ */
28
+ private $wpRootPath;
29
+
30
+ /**
31
+ * @var Strings
32
+ */
33
+ private $strUtils;
34
+
35
+ /**
36
+ * @var boolean
37
+ */
38
+ private $isInclude;
39
+
40
+ /**
41
+ * @var int
42
+ */
43
+ private $rulesCount;
44
+
45
+ public function __construct($isInclude = false)
46
+ {
47
+ $this->isInclude = $isInclude;
48
+ $this->strUtils = new Strings();
49
+ $this->setWpRootPath(ABSPATH);
50
+ }
51
+
52
+ /**
53
+ * Set the WP Root Path
54
+ * Use this method for staging site or mocking
55
+ * @param string $wpRootPath
56
+ */
57
+ public function setWpRootPath($wpRootPath)
58
+ {
59
+ $this->wpRootPath = $this->strUtils->sanitizeDirectorySeparator($wpRootPath);
60
+ $this->wpRootPath = rtrim($this->wpRootPath, '/');
61
+ }
62
+
63
+ /**
64
+ * Get the WP Root Path
65
+ * @return string
66
+ */
67
+ public function getWpRootPath()
68
+ {
69
+ return $this->wpRootPath;
70
+ }
71
+
72
+ /**
73
+ * Categories Rules
74
+ *
75
+ * @param array $excludes
76
+ */
77
+ public function categorizeRules($rules)
78
+ {
79
+ $this->absolutePathRules = [];
80
+ $this->globRules = [];
81
+ $this->rulesCount = 0;
82
+ foreach ($rules as $rule) {
83
+ if (empty($rule) || $rule === '') {
84
+ continue;
85
+ }
86
+
87
+ // Skip if include rule but helper is for exclude
88
+ if (!$this->isInclude && $this->strUtils->startsWith($rule, '!')) {
89
+ continue;
90
+ }
91
+
92
+ // Skip if exclude rule but helper is for include
93
+ if ($this->isInclude && !$this->strUtils->startsWith($rule, '!')) {
94
+ continue;
95
+ }
96
+
97
+ if ($this->isInclude) {
98
+ $rule = ltrim($rule, '!');
99
+ }
100
+
101
+ // If the rule starts with / and doesn't have any glob character add it to absoluate path array and move to next rule
102
+ if ($this->strUtils->startsWith($rule, '/') && !$this->isGlobPattern($rule)) {
103
+ $this->absolutePathRules[] = $rule;
104
+ $this->rulesCount++;
105
+ continue;
106
+ }
107
+
108
+ // *. is to check whether the exclude is extension exclude or not,
109
+ // If it is extension exclude then convert to glob pattern
110
+ if ($this->strUtils->startsWith($rule, '*.')) {
111
+ $rule = '/**/' . $rule;
112
+ }
113
+
114
+ // **/ is to check whether the exclude is anywhere/wildcard exclude or not,
115
+ // If it is anywhere exclude then convert to glob pattern
116
+ if ($this->strUtils->startsWith($rule, '**/')) {
117
+ $rule = '/' . $rule;
118
+ }
119
+
120
+ // convert path to wildcard glob path if it doesn't have any glob character
121
+ if (!$this->isGlobPattern($rule)) {
122
+ $rule = '/**/' . $rule;
123
+ }
124
+
125
+ // make exclude works for its children if it is for directory
126
+ if ($this->isChildrenMatchingAllow($rule)) {
127
+ $this->globRules[] = $this->wildcardGlobToRegex(Glob::toRegex($rule . '/**'));
128
+ $this->rulesCount++;
129
+ }
130
+
131
+ // If the exclude doesn't matches extension or anywhere exclude treat it as glob exclude
132
+ $this->globRules[] = $this->wildcardGlobToRegex(Glob::toRegex($rule));
133
+ $this->rulesCount++;
134
+ }
135
+ }
136
+
137
+ /**
138
+ * Check whether the file meets any of the exclude criteria
139
+ * @param SplFileInfo $fileInfo
140
+ *
141
+ * @return boolean
142
+ */
143
+ public function isMatched($fileInfo)
144
+ {
145
+ $path = $fileInfo->getPathname();
146
+ $path = $this->strUtils->sanitizeDirectorySeparator($path);
147
+ $relpath = str_replace($this->wpRootPath, '', $path);
148
+
149
+ // Check absolute path
150
+ if ($this->isAbsolutePathMatched($relpath)) {
151
+ return true;
152
+ }
153
+
154
+ // Check glob pattern but only check against in relative path to wordpress installation
155
+ if ($this->isGlobPatternMatched($relpath)) {
156
+ return true;
157
+ }
158
+
159
+ return false;
160
+ }
161
+
162
+ /**
163
+ * Determine whether there is any rule or not.
164
+ *
165
+ * @return boolean
166
+ */
167
+ public function hasRules()
168
+ {
169
+ return $this->rulesCount > 0;
170
+ }
171
+
172
+ /**
173
+ * Check whether the given path satisfy any absolute path exclusion
174
+ *
175
+ * @param string $path
176
+ * @return boolean
177
+ */
178
+ protected function isAbsolutePathMatched($path)
179
+ {
180
+ // will check if path matches
181
+ if (in_array($path, $this->absolutePathRules)) {
182
+ return true;
183
+ }
184
+
185
+ // will check if path children match
186
+ foreach ($this->absolutePathRules as $rule) {
187
+ if ($this->strUtils->startsWith($path, $rule . '/')) {
188
+ return true;
189
+ }
190
+ }
191
+
192
+ return false;
193
+ }
194
+
195
+ /**
196
+ * Check whether the given path satisfy any glob pattern
197
+ *
198
+ * @param string $path
199
+ * @return boolean
200
+ */
201
+ protected function isGlobPatternMatched($path)
202
+ {
203
+ foreach ($this->globRules as $rule) {
204
+ if (preg_match($rule, $path)) {
205
+ return true;
206
+ }
207
+ }
208
+
209
+ return false;
210
+ }
211
+
212
+ /**
213
+ * Check whether the path is glob pattern
214
+ *
215
+ * @param string $pattern
216
+ * @return boolean
217
+ */
218
+ protected function isGlobPattern($pattern)
219
+ {
220
+ return false !== strpos($pattern, '*') || false !== strpos($pattern, '{') || false !== strpos($pattern, '?') || false !== strpos($pattern, '[');
221
+ }
222
+
223
+ /**
224
+ * Convert symfony glob pattern converted regex to support wildcard path regex
225
+ *
226
+ * @param string $pattern
227
+ * @return string
228
+ */
229
+ protected function wildcardGlobToRegex($pattern)
230
+ {
231
+ // Make /**/ to work as anywhere exclude for Symfony Glob
232
+ if (strpos($pattern, '/(?=[^\.])[^/]*[^/]*/(?=[^\.])') !== false) {
233
+ $pattern = str_replace('/(?=[^\.])[^/]*[^/]*/(?=[^\.])', '/([^/]+/)*', $pattern);
234
+ }
235
+
236
+ // Make /** to allow exclude/include children as well
237
+ if (strpos($pattern, '/(?=[^\.])[^/]*[^/]*') !== false) {
238
+ $pattern = str_replace('/(?=[^\.])[^/]*[^/]*', '/(.*)', $pattern);
239
+ }
240
+
241
+ return $pattern;
242
+ }
243
+
244
+ /**
245
+ * Is /** be appended to allow matching of children
246
+ *
247
+ * @param string $rule
248
+ * @return boolean
249
+ */
250
+ protected function isChildrenMatchingAllow($rule)
251
+ {
252
+ $rule = rtrim($rule, '/');
253
+ $segments = explode('/', $rule);
254
+ $lastSegment = $segments[count($segments) - 1];
255
+ // Already allowed
256
+ if ($lastSegment === '**') {
257
+ return false;
258
+ }
259
+
260
+ return (strpos($lastSegment, '.') === false);
261
+ }
262
+ }
Framework/Filesystem/Filters/RecursiveFileSizeFilter.php ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPStaging\Framework\Filesystem\Filters;
4
+
5
+ use RecursiveFilterIterator;
6
+ use RecursiveDirectoryIterator;
7
+
8
+ class RecursiveFileSizeFilter extends RecursiveFilterIterator
9
+ {
10
+ private $sizeFilters = [];
11
+ public function __construct(RecursiveDirectoryIterator $iterator, $sizeFilters = [])
12
+ {
13
+ parent::__construct($iterator);
14
+ $this->sizeFilters = $sizeFilters;
15
+ }
16
+
17
+ public function accept()
18
+ {
19
+ $current = $this->current();
20
+
21
+ if (!$current->isFile()) {
22
+ return true;
23
+ }
24
+
25
+ $fileSize = $current->getSize();
26
+ foreach ($this->sizeFilters as $sizeFilter) {
27
+ $sizeComparator = explode(' ', $sizeFilter);
28
+ if (count($sizeComparator) !== 2) {
29
+ continue;
30
+ }
31
+
32
+ if ($this->compareBytes($fileSize, $sizeComparator[1], $sizeComparator[0])) {
33
+ return false;
34
+ }
35
+ }
36
+
37
+ return true;
38
+ }
39
+
40
+ /**
41
+ * Compare Bytes
42
+ *
43
+ * @param string|int $compare
44
+ * @param string|int $compareWith
45
+ * @param string $comparator
46
+ * @return bool
47
+ */
48
+ public function compareBytes($compare, $compareWith, $comparator = '=')
49
+ {
50
+ $compare = wp_convert_hr_to_bytes($compare);
51
+ $compareWith = wp_convert_hr_to_bytes($compareWith);
52
+
53
+ // comparison for equal to
54
+ if (($comparator === '=' || $comparator === ExcludeFilter::SIZE_EQUAL_TO) && ($compare == $compareWith)) {
55
+ return true;
56
+ }
57
+
58
+ // comparison for greater than
59
+ if (($comparator === '>' || $comparator === ExcludeFilter::SIZE_GREATER_THAN) && ($compare > $compareWith)) {
60
+ return true;
61
+ }
62
+
63
+ // comparison for less than
64
+ if (($comparator === '<' || $comparator === ExcludeFilter::SIZE_LESS_THAN) && ($compare < $compareWith)) {
65
+ return true;
66
+ }
67
+
68
+ return false;
69
+ }
70
+
71
+ public function getChildren()
72
+ {
73
+ return new self($this->getInnerIterator()->getChildren(), $this->sizeFilters);
74
+ }
75
+ }
Framework/Filesystem/Filters/RecursivePathExcludeFilter.php CHANGED
@@ -4,30 +4,79 @@ namespace WPStaging\Framework\Filesystem\Filters;
4
 
5
  use RecursiveFilterIterator;
6
  use RecursiveDirectoryIterator;
7
- use WPStaging\Framework\Traits\ExcludeFilterTrait;
8
 
9
  class RecursivePathExcludeFilter extends RecursiveFilterIterator
10
  {
11
- use ExcludeFilterTrait;
12
-
 
13
  protected $excludePaths = [];
14
 
15
- public function __construct(RecursiveDirectoryIterator $iterator, $excludePaths = [])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  {
17
  parent::__construct($iterator);
18
  $this->excludePaths = $excludePaths;
19
- $this->categorizeExcludes($excludePaths);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  }
21
 
22
  public function accept()
23
  {
24
  // Get the current SplFileInfo object
25
  $fileInfo = $this->getInnerIterator()->current();
26
- return !$this->isExcluded($fileInfo);
 
 
 
 
 
 
 
 
 
 
27
  }
28
 
29
  public function getChildren()
30
  {
31
- return new self($this->getInnerIterator()->getChildren(), $this->excludePaths);
32
  }
33
  }
4
 
5
  use RecursiveFilterIterator;
6
  use RecursiveDirectoryIterator;
 
7
 
8
  class RecursivePathExcludeFilter extends RecursiveFilterIterator
9
  {
10
+ /**
11
+ * @var array
12
+ */
13
  protected $excludePaths = [];
14
 
15
+ /**
16
+ * @var PathFilterHelper
17
+ */
18
+ protected $excludeFilter;
19
+
20
+ /**
21
+ * @var PathFilterHelper
22
+ */
23
+ protected $includeFilter;
24
+
25
+ /**
26
+ * @var string
27
+ */
28
+ protected $wpRootPath = ABSPATH;
29
+
30
+ public function __construct(RecursiveDirectoryIterator $iterator, $excludePaths = [], $wpRootPath = ABSPATH)
31
  {
32
  parent::__construct($iterator);
33
  $this->excludePaths = $excludePaths;
34
+ $this->excludeFilter = new PathFilterHelper();
35
+ $this->includeFilter = new PathFilterHelper(true);
36
+ $this->setWpRootPath($wpRootPath);
37
+ $this->excludeFilter->categorizeRules($excludePaths);
38
+ $this->includeFilter->categorizeRules($excludePaths);
39
+ }
40
+
41
+ /**
42
+ * Set the WP Root Path
43
+ * @param string $wpRootPath
44
+ */
45
+ public function setWpRootPath($wpRootPath)
46
+ {
47
+ $this->wpRootPath = $wpRootPath;
48
+ $this->excludeFilter->setWpRootPath($wpRootPath);
49
+ $this->includeFilter->setWpRootPath($wpRootPath);
50
+ }
51
+
52
+ /**
53
+ * Get the WP Root Path
54
+ * @return string
55
+ */
56
+ public function getWpRootPath()
57
+ {
58
+ return $this->wpRootPath;
59
  }
60
 
61
  public function accept()
62
  {
63
  // Get the current SplFileInfo object
64
  $fileInfo = $this->getInnerIterator()->current();
65
+ if ($this->includeFilter->hasRules()) {
66
+ if ($this->includeFilter->isMatched($fileInfo)) {
67
+ return true;
68
+ }
69
+
70
+ if ($fileInfo->isDir()) {
71
+ return true;
72
+ }
73
+ }
74
+
75
+ return !$this->excludeFilter->isMatched($fileInfo);
76
  }
77
 
78
  public function getChildren()
79
  {
80
+ return new self($this->getInnerIterator()->getChildren(), $this->excludePaths, $this->getWpRootPath());
81
  }
82
  }
Framework/Filesystem/Scanning/ScanConst.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPStaging\Framework\Filesystem\Scanning;
4
+
5
+ class ScanConst
6
+ {
7
+ /**
8
+ * separator to separate directories
9
+ * @var string
10
+ */
11
+ const DIRECTORIES_SEPARATOR = ',';
12
+ }
Framework/Filesystem/WpUploadsFolderSymlinker.php CHANGED
@@ -49,26 +49,25 @@ class WpUploadsFolderSymlinker
49
  public function trySymlink()
50
  {
51
  if (is_link($this->stagingUploadPath)) {
52
- $this->error = "Link already exists";
53
  return false;
54
  }
55
 
56
  if (file_exists($this->stagingUploadPath)) {
57
- $this->error = "Directory already exists";
58
  return false;
59
  }
60
 
61
- $uploadPath = $this->wpDirectories->getUploadsPath();
62
 
63
  (new Filesystem())->mkdir(dirname($this->stagingUploadPath));
64
 
65
- if (!symlink($uploadPath, $this->stagingUploadPath)) {
66
- $this->error = "Can not symlink " . $uploadPath . "to " . $this->stagingUploadPath;
67
- return false;
68
  }
69
 
70
- $this->error = "";
71
- return true;
72
  }
73
 
74
  /**
@@ -78,4 +77,50 @@ class WpUploadsFolderSymlinker
78
  {
79
  return $this->error;
80
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
  }
49
  public function trySymlink()
50
  {
51
  if (is_link($this->stagingUploadPath)) {
52
+ $this->error = __("Link already exists", 'wp-staging');
53
  return false;
54
  }
55
 
56
  if (file_exists($this->stagingUploadPath)) {
57
+ $this->error = __("Path exists at link path", 'wp-staging');
58
  return false;
59
  }
60
 
61
+ $uploadPath = rtrim($this->wpDirectories->getUploadsPath(), '/\\');
62
 
63
  (new Filesystem())->mkdir(dirname($this->stagingUploadPath));
64
 
65
+ // try symlink with exec(ln) if exec is enabled and user is on windows
66
+ if ((stripos(PHP_OS, 'WIN') === 0) && $this->isExecEnabled()) {
67
+ return $this->linkWithExec($uploadPath, $this->stagingUploadPath);
68
  }
69
 
70
+ return $this->link($uploadPath, $this->stagingUploadPath);
 
71
  }
72
 
73
  /**
77
  {
78
  return $this->error;
79
  }
80
+
81
+ /**
82
+ * Try symlinking with exec
83
+ *
84
+ * @param string $source
85
+ * @param string $destination
86
+ * @return boolean
87
+ */
88
+ private function linkWithExec($source, $destination)
89
+ {
90
+ try {
91
+ exec('ln -s ' . $source . ' ' . $destination);
92
+ return true;
93
+ } catch (FatalException $ex) {
94
+ $this->error = sprintf(__("Can not symlink %s. Error: ", 'wp-staging'), $destination, $ex->getMessage());
95
+ return false;
96
+ }
97
+ }
98
+
99
+ /**
100
+ * Try symlinking with php function
101
+ *
102
+ * @param string $source
103
+ * @param string $destination
104
+ * @return boolean
105
+ */
106
+ private function link($source, $destination)
107
+ {
108
+ try {
109
+ symlink($source, $destination);
110
+ return true;
111
+ } catch (FatalException $ex) {
112
+ $this->error = sprintf(__("Can not symlink %s. Error: ", 'wp-staging'), $destination, $ex->getMessage());
113
+ return false;
114
+ }
115
+ }
116
+
117
+ private function isExecEnabled()
118
+ {
119
+ if (!function_exists('exec')) {
120
+ return false;
121
+ }
122
+
123
+ $disabled = explode(',', ini_get('disable_functions'));
124
+ return !in_array('exec', $disabled);
125
+ }
126
  }
Framework/Traits/DbRowsGeneratorTrait.php CHANGED
@@ -38,7 +38,7 @@ trait DbRowsGeneratorTrait
38
  */
39
  protected function rowsGenerator($table, $offset, $limit, \wpdb $db = null)
40
  {
41
- if (defined('WPSTG_DEBUG') && WPSTG_DEBUG) {
42
  error_log(
43
  sprintf(
44
  'DbRowsGeneratorTrait: max-memory-limit=%s; script-memory-limit=%s; memory-usage=%s; execution-time-limit=%s; running-time=%s; is-threshold=%s',
@@ -50,7 +50,7 @@ trait DbRowsGeneratorTrait
50
  ($this->isThreshold() ? 'yes' : 'no')
51
  )
52
  );
53
- }
54
 
55
 
56
  if (null === $db) {
38
  */
39
  protected function rowsGenerator($table, $offset, $limit, \wpdb $db = null)
40
  {
41
+ /* if (defined('WPSTG_DEBUG') && WPSTG_DEBUG) {
42
  error_log(
43
  sprintf(
44
  'DbRowsGeneratorTrait: max-memory-limit=%s; script-memory-limit=%s; memory-usage=%s; execution-time-limit=%s; running-time=%s; is-threshold=%s',
50
  ($this->isThreshold() ? 'yes' : 'no')
51
  )
52
  );
53
+ }*/
54
 
55
 
56
  if (null === $db) {
Framework/Traits/ExcludeFilterTrait.php DELETED
@@ -1,141 +0,0 @@
1
- <?php
2
-
3
- namespace WPStaging\Framework\Traits;
4
-
5
- use WPStaging\Framework\Utils\Strings;
6
-
7
- /**
8
- * This trait is used in both RecursivePathExcludeFilter and PathExcludeFilter
9
- * This will help in keeping the code DRY
10
- */
11
- trait ExcludeFilterTrait
12
- {
13
- /**
14
- * @var array
15
- */
16
- private $extensionExcludes;
17
-
18
- /**
19
- * @var array
20
- */
21
- private $absolutePathExcludes;
22
-
23
- /**
24
- * @var array
25
- */
26
- private $anywherePathExcludes;
27
-
28
- /**
29
- * Categories Exclude in array
30
- *
31
- * @param array $excludes
32
- */
33
- protected function categorizeExcludes($excludes)
34
- {
35
- $this->extensionExcludes = [];
36
- $this->absolutePathExcludes = [];
37
- $this->anywherePathExcludes = [];
38
- $strUtils = new Strings();
39
- foreach ($excludes as $exclude) {
40
- // *. is to check whether the exclude is extension exclude or not,
41
- // If it is extension exclude then add to extension exclude array and move to next exclude
42
- if ($strUtils->startsWith($exclude, '*.')) {
43
- $this->extensionExcludes[] = $exclude;
44
- continue;
45
- }
46
-
47
- // **/ is to check whether the exclude is anywhere/wildcard exclude or not,
48
- // If it is anywhere exclude then add to anywhere exclude array and move to next exclude
49
- if ($strUtils->startsWith($exclude, '**/')) {
50
- $this->anywherePathExcludes[] = $exclude;
51
- continue;
52
- }
53
-
54
- // If the exclude doesn't matches extension or anywhere exclude treat it as absolute path exclude
55
- $this->absolutePathExcludes[] = $exclude;
56
- }
57
- }
58
-
59
- /**
60
- * Check whether the file extension satisfy any extension exclusion
61
- *
62
- * @param string $fileExt
63
- * @return boolean
64
- */
65
- protected function isExcludedExtension($fileExt)
66
- {
67
- $fileExt = '*.' . $fileExt;
68
- return in_array($fileExt, $this->extensionExcludes);
69
- }
70
-
71
- /**
72
- * Check whether the given path satisfy any absolute path exclusion
73
- *
74
- * @param string $path
75
- * @return boolean
76
- */
77
- protected function isExcludedAbsolutePath($path)
78
- {
79
- foreach ($this->absolutePathExcludes as $exclude) {
80
- if ((new Strings())->startsWith($path, $exclude)) {
81
- return true;
82
- }
83
- }
84
-
85
- return false;
86
- }
87
-
88
- /**
89
- * Check whether the given path satisfy any anywhere path exclusion
90
- *
91
- * @param string $path
92
- * @return boolean
93
- */
94
- protected function isExcludedAnywherePath($path)
95
- {
96
- if (is_dir($path)) {
97
- $path = trailingslashit($path);
98
- }
99
-
100
- foreach ($this->anywherePathExcludes as $exclude) {
101
- $exclude = ltrim($exclude, '**');
102
- if (is_dir($path)) {
103
- $exclude = trailingslashit($exclude);
104
- }
105
-
106
- if (strpos($path, $exclude) !== false) {
107
- return true;
108
- }
109
- }
110
-
111
- return false;
112
- }
113
-
114
- /**
115
- * Check whether the file meets any of the exclude criteria
116
- * @param SplFileInfo $fileInfo
117
- *
118
- * @return boolean
119
- */
120
- protected function isExcluded($fileInfo)
121
- {
122
- $path = $fileInfo->getPathname();
123
-
124
- // Check extension
125
- if ($this->isExcludedExtension($fileInfo->getExtension())) {
126
- return true;
127
- }
128
-
129
- // Check absolute path
130
- if ($this->isExcludedAbsolutePath($path)) {
131
- return true;
132
- }
133
-
134
- // Check anywhere path
135
- if ($this->isExcludedAnywherePath($path)) {
136
- return true;
137
- }
138
-
139
- return false;
140
- }
141
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Framework/Traits/FileScanToCacheTrait.php CHANGED
@@ -4,7 +4,7 @@ namespace WPStaging\Framework\Traits;
4
 
5
  use Exception;
6
  use stdClass;
7
- use WPStaging\Backend\Modules\Jobs\Scan;
8
  use WPStaging\Framework\Filesystem\FilterableDirectoryIterator;
9
  use WPStaging\Framework\Utils\Strings;
10
 
@@ -27,11 +27,12 @@ trait FileScanToCacheTrait
27
  * @param string $path
28
  * @param bool $isRecursive
29
  * @param array $excludePaths absolute path of dir/files to exclude
 
30
  * @param string $wpRootPath
31
  *
32
  * @return int count of files path written to cache file
33
  */
34
- public function scanToCacheFile($filesHandle, $path, $isRecursive = false, $excludePaths = [], $wpRootPath = ABSPATH)
35
  {
36
  if (is_link($path)) {
37
  return 0;
@@ -53,7 +54,11 @@ trait FileScanToCacheTrait
53
  ->setRecursive(false)
54
  ->setDotSkip()
55
  ->setExcludePaths($excludePaths)
 
 
56
  ->get();
 
 
57
  foreach ($iterator as $item) {
58
  // Always check link first otherwise it may be treated as directory
59
  if ($item->isLink()) {
@@ -61,7 +66,7 @@ trait FileScanToCacheTrait
61
  }
62
 
63
  if ($isRecursive && $item->isDir()) {
64
- $filesWrittenToCache += $this->scanToCacheFile($filesHandle, $item->getPathname(), $isRecursive, $excludePaths, $wpRootPath);
65
  }
66
 
67
  if ($item->isFile()) {
@@ -74,40 +79,4 @@ trait FileScanToCacheTrait
74
 
75
  return $filesWrittenToCache;
76
  }
77
-
78
- /**
79
- * Filtered directories according to the directory given
80
- * @param string $directoryPath
81
- * @param array $directories list of selected directories in the form of directoryPath . separatorConst . scanFlag e.g. /var/www/wp-content/plugins/::1
82
- *
83
- * @return array
84
- */
85
- public function filteredSelectedDirectories($directoryPath, $directories)
86
- {
87
- $strUtil = new Strings();
88
- $directoryPath = $strUtil->sanitizeDirectorySeparator($directoryPath);
89
- return array_filter($this->mapSelectedDirectories($directories), function ($directory) use ($directoryPath, $strUtil) {
90
- if ($strUtil->startsWith($strUtil->sanitizeDirectorySeparator($directory->path), $directoryPath)) {
91
- return true;
92
- }
93
- });
94
- }
95
-
96
- /**
97
- * Map included directories to object
98
- * @param array $directories list of selected directories in the form of directoryPath . separatorConst . scanFlag
99
- *
100
- * @return array array of objects which contains information about directory path and whether it is scanned or not
101
- */
102
- protected function mapSelectedDirectories($directories)
103
- {
104
- return array_map(function ($directory) {
105
- $directory = trim($directory, ' ');
106
- list($directoryPath, $flag) = explode(Scan::DIRECTORY_PATH_FLAG_SEPARATOR, $directory);
107
- $directoryInfo = new stdClass();
108
- $directoryInfo->path = trim($directoryPath, ' ');
109
- $directoryInfo->flag = trim($flag, ' ');
110
- return $directoryInfo;
111
- }, $directories);
112
- }
113
  }
4
 
5
  use Exception;
6
  use stdClass;
7
+ use WPStaging\Framework\Filesystem\Scanning\ScanConst;
8
  use WPStaging\Framework\Filesystem\FilterableDirectoryIterator;
9
  use WPStaging\Framework\Utils\Strings;
10
 
27
  * @param string $path
28
  * @param bool $isRecursive
29
  * @param array $excludePaths absolute path of dir/files to exclude
30
+ * @param array $excludeSizeRules exclude files by different size comparing rules
31
  * @param string $wpRootPath
32
  *
33
  * @return int count of files path written to cache file
34
  */
35
+ public function scanToCacheFile($filesHandle, $path, $isRecursive = false, $excludePaths = [], $excludeSizeRules = [], $wpRootPath = ABSPATH)
36
  {
37
  if (is_link($path)) {
38
  return 0;
54
  ->setRecursive(false)
55
  ->setDotSkip()
56
  ->setExcludePaths($excludePaths)
57
+ ->setExcludeSizeRules($excludeSizeRules)
58
+ ->setWpRootPath($wpRootPath)
59
  ->get();
60
+
61
+ $strUtil = new Strings();
62
  foreach ($iterator as $item) {
63
  // Always check link first otherwise it may be treated as directory
64
  if ($item->isLink()) {
66
  }
67
 
68
  if ($isRecursive && $item->isDir()) {
69
+ $filesWrittenToCache += $this->scanToCacheFile($filesHandle, $item->getPathname(), $isRecursive, $excludePaths, $excludeSizeRules, $wpRootPath);
70
  }
71
 
72
  if ($item->isFile()) {
79
 
80
  return $filesWrittenToCache;
81
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82
  }
Framework/Traits/PropertyConstructor.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Provides methods to build a value object from a map of values that will be mapped
5
+ * to the object properties.
6
+ *
7
+ * @package WPStaging\Framework\Traits
8
+ */
9
+
10
+ namespace WPStaging\Framework\Traits;
11
+
12
+ /**
13
+ * Trait PropertyConstructor
14
+ *
15
+ * @package WPStaging\Framework\Traits
16
+ */
17
+ trait PropertyConstructor
18
+ {
19
+
20
+ /**
21
+ * JobArguments constructor.
22
+ *
23
+ * @param array<string,mixed> $props A map from the property names to their values.
24
+ */
25
+ public function __construct(array $props = [])
26
+ {
27
+ foreach ($props as $prop => $value) {
28
+ if (property_exists($this, $prop)) {
29
+ $this->{$prop} = $value;
30
+ }
31
+ }
32
+ }
33
+ }
Framework/Utils/Cache/AbstractCache.php CHANGED
@@ -7,7 +7,7 @@
7
  namespace WPStaging\Framework\Utils\Cache;
8
 
9
  use WPStaging\Framework\Filesystem\Filesystem;
10
- use WPStaging\Vendor\Symfony\Component\Filesystem\Exception\IOException;
11
  use WPStaging\Framework\Adapter\Directory;
12
 
13
  abstract class AbstractCache
7
  namespace WPStaging\Framework\Utils\Cache;
8
 
9
  use WPStaging\Framework\Filesystem\Filesystem;
10
+ use WPStaging\Framework\Exceptions\IOException;
11
  use WPStaging\Framework\Adapter\Directory;
12
 
13
  abstract class AbstractCache
Framework/Utils/Cache/BufferedCache.php CHANGED
@@ -8,7 +8,7 @@ namespace WPStaging\Framework\Utils\Cache;
8
 
9
  use LimitIterator;
10
  use SplFileObject;
11
- use WPStaging\Vendor\Symfony\Component\Filesystem\Exception\IOException;
12
  use WPStaging\Framework\Filesystem\File;
13
  use WPStaging\Framework\Filesystem\Filesystem;
14
 
8
 
9
  use LimitIterator;
10
  use SplFileObject;
11
+ use WPStaging\Framework\Exceptions\IOException;
12
  use WPStaging\Framework\Filesystem\File;
13
  use WPStaging\Framework\Filesystem\Filesystem;
14
 
Framework/Utils/SlashMode.php ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // TODO PHP7.x; declare(strict_types=1);
4
+ namespace WPStaging\Framework\Utils;
5
+
6
+ // TODO PHP7.1; constant visibility
7
+ /**
8
+ * This class is mainly used as a enum to provide SLASH MODE
9
+ */
10
+ class SlashMode
11
+ {
12
+ /**
13
+ * Make path have no leading and trailing slashes
14
+ * @var int
15
+ */
16
+ const NO_SLASH = 0;
17
+
18
+ /**
19
+ * Make path have only leading slash but no trailing slash
20
+ * @var int
21
+ */
22
+ const LEADING_SLASH = -1;
23
+
24
+ /**
25
+ * Make path have only trailing slash but no leading slash
26
+ * @var int
27
+ */
28
+ const TRAILING_SLASH = 1;
29
+
30
+ /**
31
+ * Make path have both slashes i.e. trailing slash and leading slash
32
+ * @var int
33
+ */
34
+ const BOTH_SLASHES = 2;
35
+ }
{vendor_wpstg/symfony/finder → Framework/Utils/ThirdParty}/Glob.php RENAMED
@@ -1,14 +1,10 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of the Symfony package.
5
- *
6
- * (c) Fabien Potencier <fabien@symfony.com>
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
  */
11
- namespace WPStaging\Vendor\Symfony\Component\Finder;
12
 
13
  /**
14
  * Glob matches globbing patterns against text.
1
  <?php
2
 
3
+ namespace WPStaging\Framework\Utils\ThirdParty;
4
+
5
+ /**
6
+ * This is a port of Symfony\Component\Finder\Glob.
 
 
 
7
  */
 
8
 
9
  /**
10
  * Glob matches globbing patterns against text.
Framework/Utils/WpDefaultDirectories.php CHANGED
@@ -5,7 +5,8 @@
5
  namespace WPStaging\Framework\Utils;
6
 
7
  use DirectoryIterator;
8
- use WPStaging\Backend\Modules\Jobs\Scan;
 
9
 
10
  // TODO PHP7.1; constant visibility
11
  class WpDefaultDirectories
@@ -64,15 +65,21 @@ class WpDefaultDirectories
64
  * `wp-content/uploads`
65
  * `wp-content/uploads/sites/2`
66
  *
67
- * Result will not have any appending or prepending slashes! Directory separator will be forward slash always for Microsoft IIS compatibility
 
 
 
 
 
 
68
  *
69
  * @return string
70
  */
71
- public function getRelativeUploadPath()
72
  {
73
  $relPath = str_replace($this->wpRoot, null, $this->getUploadsPath());
74
 
75
- return trim($relPath, '/');
76
  }
77
 
78
  /*
@@ -126,41 +133,57 @@ class WpDefaultDirectories
126
 
127
  /**
128
  * Get the relative path of wp content directory
 
 
 
 
 
129
  * @return string
130
  */
131
- public function getRelativeWpContentPath()
132
  {
133
  $wpContentDir = $this->strUtils->sanitizeDirectorySeparator(WP_CONTENT_DIR);
134
  $relPath = str_replace($this->wpRoot, null, $wpContentDir);
135
 
136
- return trim($relPath, '/');
137
  }
138
 
139
  /**
140
  * Get the relative path of plugins directory
 
 
 
 
 
141
  * @return string
142
  */
143
- public function getRelativePluginPath()
144
  {
145
  $wpPluginDir = $this->strUtils->sanitizeDirectorySeparator(WP_PLUGIN_DIR);
146
  $relPath = str_replace($this->wpRoot, null, $wpPluginDir);
147
 
148
- return trim($relPath, '/');
149
  }
150
 
151
  /**
152
  * Get the relative path of themes directory
 
 
 
 
 
153
  * @return string
154
  */
155
- public function getRelativeThemePath()
156
  {
157
- $relWpContentPath = $this->getRelativeWpContentPath();
158
- return trailingslashit($relWpContentPath) . "themes";
 
159
  }
160
 
161
  /**
162
- * Get array of wp core directories and their one level sub dir with flag 0|1
163
- * i.e. wp-content, wp-admin, wp-includes, plugins etc
164
  *
165
  * @return array
166
  */
@@ -190,115 +213,60 @@ class WpDefaultDirectories
190
  continue;
191
  }
192
 
193
- $this->handleSelfAndSubDirs($path);
 
194
  }
195
 
196
- // Gather Plugins
197
- $pluginsDir = $this->wpRoot . $this->getRelativePluginPath();
198
- $this->handleSelfAndSubDirs($pluginsDir);
199
-
200
- // Gather Themes
201
- $themesDir = $this->wpRoot . $this->getRelativeThemePath();
202
- $this->handleSelfAndSubDirs($themesDir);
203
-
204
- // Gather Uploads
205
- $this->handleSelfAndSubDirs($this->getUploadsPath());
206
-
207
  return $this->coreDirectories;
208
  }
209
 
210
  /**
211
- * Add directory and it subdirectories to included directory list if not already added
212
  *
213
- * @param string $path
214
- */
215
- protected function handleSelfAndSubDirs($path)
216
- {
217
- $this->addDirectoryToList($path, Scan::IS_NON_RECURSIVE);
218
- $directories = new DirectoryIterator($path);
219
- foreach ($directories as $directory) {
220
- if ($directory->isDot() || $directory->isFile() || $directory->isLink()) {
221
- continue;
222
- }
223
-
224
- $this->addDirectoryToList($directory->getPathname(), Scan::IS_RECURSIVE);
225
- }
226
- }
227
-
228
- /**
229
- * Add directory if not already exist
230
- * Override the flag value with scanned only if directory already present and was scanned
231
  *
232
- * @param string $path
233
- * @param int $flag
234
  */
235
- protected function addDirectoryToList($path, $flag)
236
  {
237
- $path = untrailingslashit($this->strUtils->sanitizeDirectorySeparator($path));
238
- $dirInfo = $path . Scan::DIRECTORY_PATH_FLAG_SEPARATOR . $flag;
239
-
240
- if (in_array($dirInfo, $this->coreDirectories)) {
241
- return;
242
- }
243
-
244
- if (in_array($path . Scan::DIRECTORY_PATH_FLAG_SEPARATOR . Scan::IS_NON_RECURSIVE, $this->coreDirectories)) {
245
- return;
246
  }
247
 
248
- if ($flag === Scan::IS_NON_RECURSIVE) {
249
- for ($i = 0, $iMax = count($this->coreDirectories); $i < $iMax; $i++) {
250
- if ($this->coreDirectories[$i] === $path . Scan::DIRECTORY_PATH_FLAG_SEPARATOR . Scan::IS_RECURSIVE) {
251
- $this->coreDirectories[$i] = $dirInfo;
252
- return;
253
- }
254
- }
255
- }
256
 
257
- $this->coreDirectories[] = $dirInfo;
258
  }
259
 
260
  /**
261
- * Get selected directories according to the flag and filter them
262
- *
263
- * @param string $directoriesRequest
264
- * @param boolean $areDirectoriesIncluded default false
265
- * @return array
266
- *
267
- * @todo find a better place
 
268
  */
269
- public function getSelectedDirectories($directoriesRequest, $areDirectoriesIncluded = false)
270
  {
271
- $directories = $this->getWpCoreDirectories();
272
- if (empty($directoriesRequest) || $directoriesRequest === '') {
273
- return $directories;
274
  }
275
 
276
- if ($areDirectoriesIncluded) {
277
- $directories = wpstg_urldecode(explode(Scan::DIRECTORIES_SEPARATOR, $directoriesRequest));
278
- $directories = array_map(function ($directory) {
279
- return $this->wpRoot . $directory;
280
- }, $directories);
281
-
282
- return $directories;
283
  }
284
 
285
- $excludedDirectories = wpstg_urldecode(explode(Scan::DIRECTORIES_SEPARATOR, $directoriesRequest));
286
- $excludedDirectories = array_map(function ($directory) {
287
- return $this->wpRoot . $directory;
288
- }, $excludedDirectories);
289
-
290
- $directories = array_filter($directories, function ($directory) use ($excludedDirectories) {
291
- $directory = explode(Scan::DIRECTORY_PATH_FLAG_SEPARATOR, $directory)[0];
292
- foreach ($excludedDirectories as $excludedDirectory) {
293
- $excludedDirectory = explode(Scan::DIRECTORY_PATH_FLAG_SEPARATOR, $excludedDirectory)[0];
294
- if ($directory === $excludedDirectory) {
295
- return false;
296
- }
297
- }
298
-
299
- return true;
300
- });
301
 
302
- return array_values($directories);
303
  }
304
  }
5
  namespace WPStaging\Framework\Utils;
6
 
7
  use DirectoryIterator;
8
+ use WPStaging\Framework\Filesystem\Scanning\ScanConst;
9
+ use WPStaging\Framework\Utils\SlashMode;
10
 
11
  // TODO PHP7.1; constant visibility
12
  class WpDefaultDirectories
65
  * `wp-content/uploads`
66
  * `wp-content/uploads/sites/2`
67
  *
68
+ * Directory separator will be forward slash always for Microsoft IIS compatibility
69
+ *
70
+ * @param int $mode Optional. Slash Mode. Default SlashMode::NO_SLASH.
71
+ * Use SlashMode::NO_SLASH, if you don't want trailing and leading slash.
72
+ * Use SlashMode::TRAILING_SLASH, if you want trailing forward slash.
73
+ * Use SlashMode::LEADING_SLASH, if you want leading forward slash.
74
+ * Use SlashMode::BOTH_SLASHES, if you want both trailing and leading forward slash.
75
  *
76
  * @return string
77
  */
78
+ public function getRelativeUploadPath($mode = SlashMode::NO_SLASH)
79
  {
80
  $relPath = str_replace($this->wpRoot, null, $this->getUploadsPath());
81
 
82
+ return $this->slashit($relPath, $mode);
83
  }
84
 
85
  /*
133
 
134
  /**
135
  * Get the relative path of wp content directory
136
+ * @param int $mode Optional. Slash Mode. Default SlashMode::NO_SLASH.
137
+ * Use SlashMode::NO_SLASH, if you don't want trailing and leading slash.
138
+ * Use SlashMode::TRAILING_SLASH, if you want trailing forward slash.
139
+ * Use SlashMode::LEADING_SLASH, if you want leading forward slash.
140
+ * Use SlashMode::BOTH_SLASHES, if you want both trailing and leading forward slash.
141
  * @return string
142
  */
143
+ public function getRelativeWpContentPath($mode = SlashMode::NO_SLASH)
144
  {
145
  $wpContentDir = $this->strUtils->sanitizeDirectorySeparator(WP_CONTENT_DIR);
146
  $relPath = str_replace($this->wpRoot, null, $wpContentDir);
147
 
148
+ return $this->slashit($relPath, $mode);
149
  }
150
 
151
  /**
152
  * Get the relative path of plugins directory
153
+ * @param int $mode Optional. Slash Mode. Default SlashMode::NO_SLASH.
154
+ * Use SlashMode::NO_SLASH, if you don't want trailing and leading slash.
155
+ * Use SlashMode::TRAILING_SLASH, if you want trailing forward slash.
156
+ * Use SlashMode::LEADING_SLASH, if you want leading forward slash.
157
+ * Use SlashMode::BOTH_SLASHES, if you want both trailing and leading forward slash.
158
  * @return string
159
  */
160
+ public function getRelativePluginPath($mode = SlashMode::NO_SLASH)
161
  {
162
  $wpPluginDir = $this->strUtils->sanitizeDirectorySeparator(WP_PLUGIN_DIR);
163
  $relPath = str_replace($this->wpRoot, null, $wpPluginDir);
164
 
165
+ return $this->slashit($relPath, $mode);
166
  }
167
 
168
  /**
169
  * Get the relative path of themes directory
170
+ * @param int $mode Optional. Slash Mode. Default SlashMode::NO_SLASH.
171
+ * Use SlashMode::NO_SLASH, if you don't want trailing and leading slash.
172
+ * Use SlashMode::TRAILING_SLASH, if you want trailing forward slash.
173
+ * Use SlashMode::LEADING_SLASH, if you want leading forward slash.
174
+ * Use SlashMode::BOTH_SLASHES, if you want both trailing and leading forward slash.
175
  * @return string
176
  */
177
+ public function getRelativeThemePath($mode = SlashMode::NO_SLASH)
178
  {
179
+ $relPath = $this->getRelativeWpContentPath() . '/themes';
180
+
181
+ return $this->slashit($relPath, $mode);
182
  }
183
 
184
  /**
185
+ * Get array of wp core directories with flag 0|1
186
+ * i.e. wp-content, wp-admin, wp-includes
187
  *
188
  * @return array
189
  */
213
  continue;
214
  }
215
 
216
+ $path = untrailingslashit($this->strUtils->sanitizeDirectorySeparator($path));
217
+ $this->coreDirectories[] = $path;
218
  }
219
 
 
 
 
 
 
 
 
 
 
 
 
220
  return $this->coreDirectories;
221
  }
222
 
223
  /**
224
+ * Get excluded directories and map it to array
225
  *
226
+ * @param string $directoriesRequest
227
+ * @return array
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
228
  *
229
+ * @todo find a better place
 
230
  */
231
+ public function getExcludedDirectories($directoriesRequest)
232
  {
233
+ if ((empty($directoriesRequest) || $directoriesRequest === '')) {
234
+ return [];
 
 
 
 
 
 
 
235
  }
236
 
237
+ $excludedDirectories = explode(ScanConst::DIRECTORIES_SEPARATOR, wpstg_urldecode($directoriesRequest));
238
+ $excludedDirectories = array_map(function ($directory) {
239
+ return $this->slashit($directory, SlashMode::LEADING_SLASH);
240
+ }, $excludedDirectories);
 
 
 
 
241
 
242
+ return $excludedDirectories;
243
  }
244
 
245
  /**
246
+ * Different slash mode for path
247
+ * @param string $path
248
+ * @param int $mode Optional. Slash Mode. Default SlashMode::NO_SLASH.
249
+ * Use SlashMode::NO_SLASH, if you don't want trailing and leading slash.
250
+ * Use SlashMode::TRAILING_SLASH, if you want trailing forward slash.
251
+ * Use SlashMode::LEADING_SLASH, if you want leading forward slash.
252
+ * Use SlashMode::BOTH_SLASHES, if you want both trailing and leading forward slash.
253
+ * @return string
254
  */
255
+ private function slashit($path, $mode = SlashMode::NO_SLASH)
256
  {
257
+ $path = trim(trim($path, '\\'), '/');
258
+ if ($mode === SlashMode::BOTH_SLASHES) {
259
+ return '/' . $path . '/';
260
  }
261
 
262
+ if ($mode === SlashMode::TRAILING_SLASH) {
263
+ return $path . '/';
 
 
 
 
 
264
  }
265
 
266
+ if ($mode === SlashMode::LEADING_SLASH) {
267
+ return '/' . $path;
268
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
269
 
270
+ return $path;
271
  }
272
  }
README.md CHANGED
@@ -6,6 +6,12 @@
6
 
7
  This is the latest release of WP STAGING BASIC for WordPress that you can find on [wordpress.org](https://wordpress.org/plugins/wp-staging/)
8
 
 
 
 
 
 
 
9
  ## Bugs ##
10
  If you find an issue, let us know [here](https://github.com/WP-Staging/wp-staging/issues?state=open)!
11
 
6
 
7
  This is the latest release of WP STAGING BASIC for WordPress that you can find on [wordpress.org](https://wordpress.org/plugins/wp-staging/)
8
 
9
+ ## About This Repository ##
10
+
11
+ This is the repository for WPSTAGING Basic. It is **generated automatically** as part of a build process that happens in the private repository of WPSTAGING Pro, where the real development happens.
12
+
13
+ In the real repository, we run thousands of quality tests using GitHub actions during development, such as code style (PHPCS), static code analysis checks (PHPSTAN), and automated unit tests (PHPUnit) and webdriver tests (Selenium), powered by wp-browser.
14
+
15
  ## Bugs ##
16
  If you find an issue, let us know [here](https://github.com/WP-Staging/wp-staging/issues?state=open)!
17
 
assets/css/{src → dist}/wpstg-admin-feedback.css RENAMED
@@ -37,4 +37,5 @@
37
  padding:0px;
38
  padding-bottom:50px;
39
  }
40
- }
 
37
  padding:0px;
38
  padding-bottom:50px;
39
  }
40
+ }
41
+ /*# sourceMappingURL=wpstg-admin-feedback.css.map */
assets/css/dist/wpstg-admin-feedback.css.map ADDED
@@ -0,0 +1 @@
 
1
+ {"version":3,"sources":["wpstg-admin-feedback.css"],"names":[],"mappings":"AAAA;;CAEC;AACD;IACI,gFAAgF;IAChF,YAAY;IACZ,WAAW;IACX,eAAe,EAAE,kBAAkB;IACnC,cAAc,EAAE,eAAe;IAC/B,OAAO;IACP,MAAM;IACN,kCAAkC,EAAE,yBAAyB;IAC7D,kCAAkC,EAAE,oBAAoB;AAC5D;AACA;IACI,kBAAkB;IAClB,QAAQ,EAAE,qBAAqB;IAC/B,YAAY;IACZ,eAAe;IACf,YAAY;IACZ,gBAAgB,EAAE,+EAA+E;IACjG,eAAe;IACf,aAAa;IACb,sBAAsB;IACtB,gBAAgB;AACpB;AACA;6CAC6C,YAAY,CAAC,UAAU,EAAE;AACtE,iCAAiC,cAAc,EAAE,iBAAiB,EAAE;;AAEpE;IACI,UAAU;AACd;;AAEA;IACI;QACI,WAAW;QACX,mBAAmB;IACvB;AACJ","file":"wpstg-admin-feedback.css","sourcesContent":["/**\n PLUGINS ADMIN PAGE\n*/\n#wpstg-feedback-overlay {\n /* Height & width depends on how you want to reveal the overlay (see JS below) */ \n height: 100%;\n width: 100%;\n position: fixed; /* Stay in place */\n z-index: 10000; /* Sit on top */\n left: 0;\n top: 0;\n background-color: rgb(120,120,120); /* Black fallback color */\n background-color: rgba(0,0,0, 0.5); /* Black w/opacity */\n}\n#wpstg-feedback-content {\n position: relative;\n top: 25%; /* 25% from the top */\n width: 500px;\n max-width: 100%;\n margin: auto;\n margin-top: 30px; /* 30px top margin to avoid conflict with the close button on smaller screens */\n max-height: 50%;\n padding: 20px;\n background-color: #fff;\n overflow-y: auto;\n}\n#wpstg-feedback-content textarea,\n#wpstg-feedback-content input[type=\"text\"] { display:none;width:100%; }\n.wpstg-feedback-not-deactivate { display: block; text-align: right; }\n\n#wpstg-feedback-content h3{\n margin:5px;\n}\n\n@media screen and (max-width:400px){\n #wpstg-feedback-content {\n padding:0px;\n padding-bottom:50px;\n }\n}"]}
assets/css/dist/wpstg-admin-feedback.min.css ADDED
@@ -0,0 +1,2 @@
 
 
1
+ #wpstg-feedback-overlay{background-color:#787878;background-color:rgba(0,0,0,.5);height:100%;left:0;position:fixed;top:0;width:100%;z-index:10000}#wpstg-feedback-content{background-color:#fff;margin:30px auto auto;max-height:50%;max-width:100%;overflow-y:auto;padding:20px;position:relative;top:25%;width:500px}#wpstg-feedback-content input[type=text],#wpstg-feedback-content textarea{display:none;width:100%}.wpstg-feedback-not-deactivate{display:block;text-align:right}#wpstg-feedback-content h3{margin:5px}@media screen and (max-width:400px){#wpstg-feedback-content{padding:0 0 50px}}
2
+ /*# sourceMappingURL=wpstg-admin-feedback.min.css.map */
assets/css/dist/wpstg-admin-feedback.min.css.map ADDED
@@ -0,0 +1 @@
 
1
+ {"version":3,"sources":["wpstg-admin-feedback.css"],"names":[],"mappings":"AAGA,wBAQI,wBAAkC,CAClC,+BAAkC,CAPlC,WAAY,CAIZ,MAAO,CAFP,cAAe,CAGf,KAAM,CAJN,UAAW,CAEX,aAKJ,CACA,wBASI,qBAAsB,CAHtB,qBAAgB,CAChB,cAAe,CAHf,cAAe,CAMf,eAAgB,CAFhB,YAAa,CAPb,iBAAkB,CAClB,OAAQ,CACR,WAQJ,CACA,0EAC6C,YAAY,CAAC,UAAY,CACtE,+BAAiC,aAAc,CAAE,gBAAmB,CAEpE,2BACI,UACJ,CAEA,oCACI,wBAEI,gBACJ,CACJ","file":"wpstg-admin-feedback.min.css","sourcesContent":["/**\n PLUGINS ADMIN PAGE\n*/\n#wpstg-feedback-overlay {\n /* Height & width depends on how you want to reveal the overlay (see JS below) */ \n height: 100%;\n width: 100%;\n position: fixed; /* Stay in place */\n z-index: 10000; /* Sit on top */\n left: 0;\n top: 0;\n background-color: rgb(120,120,120); /* Black fallback color */\n background-color: rgba(0,0,0, 0.5); /* Black w/opacity */\n}\n#wpstg-feedback-content {\n position: relative;\n top: 25%; /* 25% from the top */\n width: 500px;\n max-width: 100%;\n margin: auto;\n margin-top: 30px; /* 30px top margin to avoid conflict with the close button on smaller screens */\n max-height: 50%;\n padding: 20px;\n background-color: #fff;\n overflow-y: auto;\n}\n#wpstg-feedback-content textarea,\n#wpstg-feedback-content input[type=\"text\"] { display:none;width:100%; }\n.wpstg-feedback-not-deactivate { display: block; text-align: right; }\n\n#wpstg-feedback-content h3{\n margin:5px;\n}\n\n@media screen and (max-width:400px){\n #wpstg-feedback-content {\n padding:0px;\n padding-bottom:50px;\n }\n}"]}
assets/css/{src → dist}/wpstg-admin.css RENAMED
@@ -3,7 +3,7 @@
3
  *
4
  * @package WPSTG
5
  * @subpackage Admin CSS
6
- * @copyright Copyright (c) 2015, René Hermenau
7
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
8
  */
9
 
@@ -156,14 +156,12 @@
156
 
157
  #wpstg-clonepage-wrapper {
158
  margin-bottom: 20px;
159
- /*max-width: 690px;*/
160
  }
161
 
162
  @media screen and (min-width: 1090px) {
163
  #wpstg-clonepage-wrapper {
164
  float: left;
165
  margin-bottom: 20px;
166
- /*width: 690px;*/
167
  }
168
  .wpstg-sidebar {
169
  display: none;
@@ -253,7 +251,7 @@
253
 
254
  .wpstg-clone-actions {
255
  display: flex;
256
- align-items: right;
257
  }
258
 
259
  .wpstg-dropdown {
@@ -279,6 +277,11 @@
279
  position: relative;
280
  }
281
 
 
 
 
 
 
282
  .wpstg-dropdown>.wpstg-dropdown-menu {
283
  background: #fff;
284
  display: none;
@@ -293,11 +296,18 @@
293
  z-index: 1000;
294
  }
295
 
 
 
 
 
 
 
296
  .wpstg-dropdown>.wpstg-dropdown-menu.shown {
297
  display: flex;
298
  }
299
 
300
- .wpstg-clone-action {
 
301
  color: #002648;
302
  padding: 5px 8px;
303
  border-radius: 3px;
@@ -306,10 +316,19 @@
306
  transition: color .2s ease-in-out;
307
  }
308
 
309
- .wpstg-clone-action:hover {
 
310
  background: rgba(0,0,0,0.05);
311
  }
312
 
 
 
 
 
 
 
 
 
313
  .wpstg-remove-clone:hover {
314
  color: #ef6d6d;
315
  }
@@ -412,11 +431,8 @@
412
  content: "Finished";
413
  background-color: #00c89a;
414
  color: white;
415
- padding-left: 10px;
416
- padding-right: 10px;
417
- padding-top: 2px;
418
- padding-bottom: 2px;
419
- margin-top: 0px;
420
  border-radius: 3px;
421
  }
422
 
@@ -513,16 +529,11 @@
513
  #wpstg-new-clone {
514
  background: #25a1f0;
515
  border-color: #2188c9;
516
- /*box-shadow: inset 0 2px 0 #006799;*/
517
- background-color: #25a1f0;
518
  }
519
 
520
  #wpstg-new-clone:hover {
521
  background: #259be6;
522
  border-color: #2188c9;
523
- /*border-width: 2px;*/
524
- /*box-shadow: inset 0 2px 0 #006799;*/
525
- background-color: #259be6;
526
  }
527
 
528
  #wpstg-clone-path {
@@ -620,9 +631,9 @@
620
  }
621
 
622
  .wpstg-tab-triangle {
623
- font-family: arial;
624
  display: inline-block;
625
  margin-right: 10px;
 
626
  }
627
 
628
  .wpstg-tab-header:focus {
@@ -752,7 +763,7 @@
752
  }
753
 
754
  .wpstg-share-button-container p {
755
- margin: 0px 0 10px 0;
756
  }
757
 
758
  .wpstg-share-button {
@@ -778,8 +789,6 @@
778
  display: inline;
779
  font-size: 12px;
780
  padding: 4px 8px;
781
- /* will be overided due to display: inline
782
- width: 40px; */
783
  }
784
 
785
  .wpstg-share-button-twitter .wpstg-share {
@@ -858,7 +867,7 @@
858
  }
859
 
860
  .wpstg-h2 {
861
- margin-top: 0px;
862
  margin-bottom: 1.2rem;
863
  font-size: 30px;
864
  line-height: 2.5rem;
@@ -877,13 +886,16 @@
877
  }
878
 
879
  .wpstg-h1 {
880
- font-size: 2.75em;
881
  margin-bottom: 1.35rem;
882
  font-size: 2.5em;
883
  line-height: 3.68rem;
884
  letter-spacing: normal;
885
  }
886
 
 
 
 
 
887
  #wpstg-welcome h2 {
888
  margin: 0 0 15px;
889
  }
@@ -896,9 +908,6 @@
896
 
897
  #wpstg-footer {
898
  clear: both;
899
- padding-top: 20px;
900
- clear: both;
901
- padding-top: 20px;
902
  background-color: white;
903
  padding: 20px;
904
  margin-top: 20px;
@@ -930,14 +939,14 @@
930
  #wpstg-processing-status {
931
  margin-top: 5px;
932
  font-size: 13px;
933
- font-weight: 400px;
934
  float: left;
935
  }
936
 
937
  #wpstg-processing-timer {
938
  margin-top: 5px;
939
  font-size: 13px;
940
- font-weight: 400px;
941
  float: right;
942
  }
943
 
@@ -996,9 +1005,7 @@
996
  box-sizing: border-box;
997
  background: #25a1f0;
998
  border-color: #2188c9;
999
- /*box-shadow: 0 1px 0 #006799;*/
1000
  color: #fff;
1001
- text-decoration: none;
1002
  text-shadow: 0 -1px 1px #006799, 1px 0 1px #006799, 0 1px 1px #006799, -1px 0 1px #006799;
1003
  }
1004
 
@@ -1011,14 +1018,12 @@
1011
  z-index: 9999;
1012
  width: 300px;
1013
  background-color: #fff;
1014
- margin: 6px 0 0;
1015
  padding: 15px 15px 10px;
1016
  border: 1px solid #e8e8e8;
1017
  border-radius: 3px;
1018
  box-shadow: 0 1px 0 0 #fff inset;
1019
  display: none;
1020
- margin-top: 67px;
1021
- margin-left: 123px;
1022
  }
1023
 
1024
  .wpstg-report-show {
@@ -1064,7 +1069,7 @@
1064
 
1065
  .wpstg-buttons .spinner {
1066
  float: none;
1067
- margin: 0px 0px 0px 5px;
1068
  }
1069
 
1070
  .wpstg-message {
@@ -1101,8 +1106,7 @@
1101
  padding: 10px;
1102
  background-color: #ffb804;
1103
  color: #ffffff;
1104
- margin: 10px;
1105
- margin-left: 0px;
1106
  }
1107
 
1108
  .wpstg-warning a {
@@ -1116,8 +1120,7 @@
1116
  padding: 10px;
1117
  background-color: #fe6501;
1118
  color: #ffffff;
1119
- margin: 10px;
1120
- margin-left: 0px;
1121
  }
1122
 
1123
  .wpstg-error a {
@@ -1209,7 +1212,6 @@
1209
  cursor: pointer;
1210
  display: inline-block;
1211
  padding: 1em 1.25em;
1212
- border-bottom: .5em solid transparent;
1213
  border: solid 1px;
1214
  }
1215
 
@@ -1253,9 +1255,9 @@
1253
  border-radius: 3px;
1254
  position: absolute;
1255
  z-index: 1;
1256
- -webkit-box-shadow: -1px 1px 5px 0px rgba(0, 0, 0, 0.75);
1257
- -moz-box-shadow: -1px 1px 5px 0px rgba(0, 0, 0, 0.75);
1258
- box-shadow: -1px 1px 5px 0px rgba(0, 0, 0, 0.75);
1259
  }
1260
 
1261
  .wpstg--tooltip:hover .wpstg--tooltiptext {
@@ -1341,7 +1343,6 @@ Tooltip top arrow
1341
  margin-top: 1em;
1342
  display: none;
1343
  padding: 1em;
1344
- overflow-x: hidden;
1345
  overflow-x: auto;
1346
  text-align: justify;
1347
  }
@@ -1520,10 +1521,6 @@ span.wpstg--drag-or-upload {
1520
  position: absolute;
1521
  width: 185px;
1522
  background: #25a1f0;
1523
- border-top: .2em solid #25a1f0;
1524
- border-bottom: .25em solid #25a1f0;
1525
- border-left: .25em solid #25a1f0;
1526
- border-right: .25em solid #25a1f0;
1527
  box-sizing: border-box;
1528
  border-radius: 0 0 3px 3px;
1529
  border-width: 1px;
@@ -1533,7 +1530,7 @@ span.wpstg--drag-or-upload {
1533
 
1534
  .wpstg--backup--import--options.wpstg--show-options ul li {
1535
  border-bottom: .1em solid #25a1f0;
1536
- margin: 0px;
1537
  }
1538
 
1539
  .wpstg--backup--import--options.wpstg--show-options ul li:hover {
@@ -1584,7 +1581,7 @@ span.wpstg--drag-or-upload {
1584
  }
1585
 
1586
  .wpstg--import--advanced-options--button {
1587
- border: 0px;
1588
  border-radius: 3px;
1589
  font-size: 18px;
1590
  text-shadow: 0 -1px 1px #006799, 1px 0 1px #006799, 0 1px 1px #006799, -1px 0 1px #006799;
@@ -1881,13 +1878,22 @@ span.wpstg--drag-or-upload {
1881
  }
1882
 
1883
  .wpstg-m-0 {
1884
- margin: 0px;
1885
  }
1886
 
1887
  .wpstg-mt-16 {
1888
  margin-top: 16px;
1889
  }
1890
 
 
 
 
 
 
 
 
 
 
1891
  .wpstg-w-100 {
1892
  width: 100%;
1893
  }
@@ -1905,8 +1911,7 @@ span.wpstg--drag-or-upload {
1905
  background-color: #59a7f7;
1906
  color: white;
1907
  padding: 10px;
1908
- margin: 10px;
1909
- margin-left: 0px;
1910
  }
1911
 
1912
  .wpstg-bold-text {
@@ -2025,10 +2030,16 @@ span.wpstg--drag-or-upload {
2025
  background-color: #378cc9;
2026
  }
2027
 
2028
- .wpstg-issue-resubmit-confirmation.swal2-container {
 
2029
  z-index: 10500;
2030
  }
2031
 
 
 
 
 
 
2032
  body.toplevel_page_wpstg_clone .swal2-container .swal2-content {
2033
  z-index:2;
2034
  }
@@ -2157,11 +2168,355 @@ ul.wpstg-import-backup-more-info li {
2157
 
2158
  .wpstg-settings-form-group > .wpstg-settings-message {
2159
  width: 30%;
2160
- padding: 0px;
2161
- margin: 0px;
2162
- margin-top: 7px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2163
  }
2164
 
2165
  .wpstg-swal-push-container.swal2-container {
2166
  z-index: 9995;
2167
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  *
4
  * @package WPSTG
5
  * @subpackage Admin CSS
6
+ * @copyright Copyright (c) 2021, René Hermenau
7
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
8
  */
9
 
156
 
157
  #wpstg-clonepage-wrapper {
158
  margin-bottom: 20px;
 
159
  }
160
 
161
  @media screen and (min-width: 1090px) {
162
  #wpstg-clonepage-wrapper {
163
  float: left;
164
  margin-bottom: 20px;
 
165
  }
166
  .wpstg-sidebar {
167
  display: none;
251
 
252
  .wpstg-clone-actions {
253
  display: flex;
254
+ /*align-items: right;*/
255
  }
256
 
257
  .wpstg-dropdown {
277
  position: relative;
278
  }
279
 
280
+ .wpstg-dropdown-symbol {
281
+ font-size: 14px;
282
+ margin-left: 4px;
283
+ }
284
+
285
  .wpstg-dropdown>.wpstg-dropdown-menu {
286
  background: #fff;
287
  display: none;
296
  z-index: 1000;
297
  }
298
 
299
+ .wpstg-dropdown>.wpstg-dropdown-menu.wpstg-menu-dropup {
300
+ top: auto;
301
+ bottom: 100%;
302
+ transform: translate3d(0px, -3px, 0px);
303
+ }
304
+
305
  .wpstg-dropdown>.wpstg-dropdown-menu.shown {
306
  display: flex;
307
  }
308
 
309
+ .wpstg-clone-action,
310
+ .wpstg-dropdown-action {
311
  color: #002648;
312
  padding: 5px 8px;
313
  border-radius: 3px;
316
  transition: color .2s ease-in-out;
317
  }
318
 
319
+ .wpstg-clone-action:hover,
320
+ .wpstg-dropdown-action:hover {
321
  background: rgba(0,0,0,0.05);
322
  }
323
 
324
+ .wpstg-dropdown-action {
325
+ color: #333;
326
+ background: transparent;
327
+ border: 0 solid black;
328
+ outline: none;
329
+ box-shadow: none;
330
+ }
331
+
332
  .wpstg-remove-clone:hover {
333
  color: #ef6d6d;
334
  }
431
  content: "Finished";
432
  background-color: #00c89a;
433
  color: white;
434
+ padding: 2px 10px;
435
+ margin-top: 0;
 
 
 
436
  border-radius: 3px;
437
  }
438
 
529
  #wpstg-new-clone {
530
  background: #25a1f0;
531
  border-color: #2188c9;
 
 
532
  }
533
 
534
  #wpstg-new-clone:hover {
535
  background: #259be6;
536
  border-color: #2188c9;
 
 
 
537
  }
538
 
539
  #wpstg-clone-path {
631
  }
632
 
633
  .wpstg-tab-triangle {
 
634
  display: inline-block;
635
  margin-right: 10px;
636
+ animation: transform 0.5s;
637
  }
638
 
639
  .wpstg-tab-header:focus {
763
  }
764
 
765
  .wpstg-share-button-container p {
766
+ margin: 0 0 10px 0;
767
  }
768
 
769
  .wpstg-share-button {
789
  display: inline;
790
  font-size: 12px;
791
  padding: 4px 8px;
 
 
792
  }
793
 
794
  .wpstg-share-button-twitter .wpstg-share {
867
  }
868
 
869
  .wpstg-h2 {
870
+ margin-top: 0;
871
  margin-bottom: 1.2rem;
872
  font-size: 30px;
873
  line-height: 2.5rem;
886
  }
887
 
888
  .wpstg-h1 {
 
889
  margin-bottom: 1.35rem;
890
  font-size: 2.5em;
891
  line-height: 3.68rem;
892
  letter-spacing: normal;
893
  }
894
 
895
+ .swal2-content h1 {
896
+ color:#444;
897
+ }
898
+
899
  #wpstg-welcome h2 {
900
  margin: 0 0 15px;
901
  }
908
 
909
  #wpstg-footer {
910
  clear: both;
 
 
 
911
  background-color: white;
912
  padding: 20px;
913
  margin-top: 20px;
939
  #wpstg-processing-status {
940
  margin-top: 5px;
941
  font-size: 13px;
942
+ font-weight: 400;
943
  float: left;
944
  }
945
 
946
  #wpstg-processing-timer {
947
  margin-top: 5px;
948
  font-size: 13px;
949
+ font-weight: 400;
950
  float: right;
951
  }
952
 
1005
  box-sizing: border-box;
1006
  background: #25a1f0;
1007
  border-color: #2188c9;
 
1008
  color: #fff;
 
1009
  text-shadow: 0 -1px 1px #006799, 1px 0 1px #006799, 0 1px 1px #006799, -1px 0 1px #006799;
1010
  }
1011
 
1018
  z-index: 9999;
1019
  width: 300px;
1020
  background-color: #fff;
 
1021
  padding: 15px 15px 10px;
1022
  border: 1px solid #e8e8e8;
1023
  border-radius: 3px;
1024
  box-shadow: 0 1px 0 0 #fff inset;
1025
  display: none;
1026
+ margin: 67px 0 0 123px;
 
1027
  }
1028
 
1029
  .wpstg-report-show {
1069
 
1070
  .wpstg-buttons .spinner {
1071
  float: none;
1072
+ margin: 0 0 0 5px;
1073
  }
1074
 
1075
  .wpstg-message {
1106
  padding: 10px;
1107
  background-color: #ffb804;
1108
  color: #ffffff;
1109
+ margin: 10px 10px 10px 0;
 
1110
  }
1111
 
1112
  .wpstg-warning a {
1120
  padding: 10px;
1121
  background-color: #fe6501;
1122
  color: #ffffff;
1123
+ margin: 10px 10px 10px 0;
 
1124
  }
1125
 
1126
  .wpstg-error a {
1212
  cursor: pointer;
1213
  display: inline-block;
1214
  padding: 1em 1.25em;
 
1215
  border: solid 1px;
1216
  }
1217
 
1255
  border-radius: 3px;
1256
  position: absolute;
1257
  z-index: 1;
1258
+ -webkit-box-shadow: -1px 1px 5px 0 rgba(0, 0, 0, 0.75);
1259
+ -moz-box-shadow: -1px 1px 5px 0 rgba(0, 0, 0, 0.75);
1260
+ box-shadow: -1px 1px 5px 0 rgba(0, 0, 0, 0.75);
1261
  }
1262
 
1263
  .wpstg--tooltip:hover .wpstg--tooltiptext {
1343
  margin-top: 1em;
1344
  display: none;
1345
  padding: 1em;
 
1346
  overflow-x: auto;
1347
  text-align: justify;
1348
  }
1521
  position: absolute;
1522
  width: 185px;
1523
  background: #25a1f0;
 
 
 
 
1524
  box-sizing: border-box;
1525
  border-radius: 0 0 3px 3px;
1526
  border-width: 1px;
1530
 
1531
  .wpstg--backup--import--options.wpstg--show-options ul li {
1532
  border-bottom: .1em solid #25a1f0;
1533
+ margin: 0;
1534
  }
1535
 
1536
  .wpstg--backup--import--options.wpstg--show-options ul li:hover {
1581
  }
1582
 
1583
  .wpstg--import--advanced-options--button {
1584
+ border: 0;
1585
  border-radius: 3px;
1586
  font-size: 18px;
1587
  text-shadow: 0 -1px 1px #006799, 1px 0 1px #006799, 0 1px 1px #006799, -1px 0 1px #006799;
1878
  }
1879
 
1880
  .wpstg-m-0 {
1881
+ margin: 0;
1882
  }
1883
 
1884
  .wpstg-mt-16 {
1885
  margin-top: 16px;
1886
  }
1887
 
1888
+ .wpstg-mt-10px {
1889
+ margin-top: 10px;
1890
+ }
1891
+
1892
+ .wpstg-my-10px {
1893
+ margin-top: 10px;
1894
+ margin-bottom: 10px;
1895
+ }
1896
+
1897
  .wpstg-w-100 {
1898
  width: 100%;
1899
  }
1911
  background-color: #59a7f7;
1912
  color: white;
1913
  padding: 10px;
1914
+ margin: 10px 10px 10px 0;
 
1915
  }
1916
 
1917
  .wpstg-bold-text {
2030
  background-color: #378cc9;
2031
  }
2032
 
2033
+ .wpstg-issue-resubmit-confirmation.swal2-container,
2034
+ .wpstg-swal2-container.swal2-container {
2035
  z-index: 10500;
2036
  }
2037
 
2038
+ .wpstg-swal2-container.wpstg-swal2-loading .swal2-actions,
2039
+ .wpstg-swal2-container.wpstg-swal2-loading .swal2-header {
2040
+ display: none;
2041
+ }
2042
+
2043
  body.toplevel_page_wpstg_clone .swal2-container .swal2-content {
2044
  z-index:2;
2045
  }
2168
 
2169
  .wpstg-settings-form-group > .wpstg-settings-message {
2170
  width: 30%;
2171
+ padding: 0;
2172
+ margin: 7px 0 0;
2173
+ }
2174
+
2175
+ /**
2176
+ * WP STAGING EXCLUSION RULES TABLE LAYOUT
2177
+ */
2178
+
2179
+ .wpstg-excluded-filters-container {
2180
+ padding: 0;
2181
+ margin-top: 10px;
2182
+ margin-bottom: 10px;
2183
+ max-width: 100%;
2184
+ width: 100%;
2185
+ }
2186
+
2187
+ .wpstg-excluded-filters-container > table {
2188
+ width: 100%;
2189
+ border-collapse: collapse;
2190
+ border-color: transparent;
2191
+ }
2192
+
2193
+ .wpstg-excluded-filters-container td {
2194
+ padding-top: 4px;
2195
+ padding-bottom: 4px;
2196
+ height: 20px;
2197
+ }
2198
+
2199
+ .wpstg-excluded-filters-container h4 {
2200
+ margin: 0;
2201
+ }
2202
+
2203
+ /*.wpstg-excluded-filters-container tbody {
2204
+ background: #fff !important;
2205
+ }*/
2206
+
2207
+ .wpstg-exclude-filters-foot {
2208
+ display: flex;
2209
+ justify-content: flex-start;
2210
+ padding: 0;
2211
+ }
2212
+
2213
+ .wpstg-excluded-filters-container .wpstg-exclude-filter-name-column {
2214
+ width: 100px;
2215
+ max-width: 100px !important;
2216
+ padding-left: 10px;
2217
+ }
2218
+
2219
+ .wpstg-excluded-filters-container .wpstg-exclude-filter-action-column {
2220
+ width: 50px;
2221
+ max-width: 50px;
2222
+ text-align: right !important;
2223
+ padding-right: 10px;
2224
+ }
2225
+
2226
+ .wpstg-excluded-filters-container .wpstg-exclude-filter-exclusion-column {
2227
+ width: 320px;
2228
+ position: relative;
2229
+ }
2230
+
2231
+ /**
2232
+ * WP STAGING EXCLUSION RULE DROPDOWN STYLE
2233
+ */
2234
+
2235
+ .wpstg-exclude-filter-dropdown > button {
2236
+ background: #25A0F1;
2237
+ border: 1px solid #25A0F1;
2238
+ color: #fff;
2239
+ padding: 1px 5px;
2240
+ display: inline-block;
2241
+ font-weight: 400;
2242
+ line-height: 1.5;
2243
+ text-align: center;
2244
+ border-radius: 0;
2245
+ outline: none;
2246
+ box-shadow: none;
2247
+ cursor: pointer;
2248
+ height: 24px;
2249
+ }
2250
+
2251
+ .wpstg-exclude-filter-dropdown > button:hover {
2252
+ background: #135e96;;
2253
+ border: 1px solid #135e96;;
2254
+ }
2255
+
2256
+ .wpstg-exclude-filter-dropdown > .wpstg-dropdown-menu {
2257
+ width: 128px;
2258
+ }
2259
+
2260
+ .wpstg-remove-exclude-rule {
2261
+ color: #fff !important;
2262
+ background-color: #dc3545;
2263
+ border: 1px solid #dc3545;
2264
+ width: 20px;
2265
+ height: 20px;
2266
+ border-radius: 10px;
2267
+ font-size: 24px;
2268
+ padding: 0;
2269
+ display: inline-flex;
2270
+ justify-content: center;
2271
+ outline: none;
2272
+ box-shadow: none;
2273
+ font-weight: 400;
2274
+ line-height: 0.7;
2275
+ margin-top: 5px;
2276
+ cursor: pointer;
2277
+ }
2278
+
2279
+ .wpstg-remove-exclude-rule:hover {
2280
+ background-color: #bb2d3b;
2281
+ border-color: #bb2d3b;
2282
+ }
2283
+
2284
+ /**
2285
+ * WP STAGING POPOVER EXCLUSION RULES INFO
2286
+ */
2287
+
2288
+ .wpstg-popover {
2289
+ display: inline-block;
2290
+ position: relative;
2291
+ }
2292
+
2293
+ .wpstg-popover button + p {
2294
+ position: absolute;
2295
+ top: 18px;
2296
+ right: -150px;
2297
+ display: none;
2298
+ width: 320px;
2299
+ z-index: 1024;
2300
+ padding: 10px !important;
2301
+ box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);
2302
+ }
2303
+
2304
+ .wpstg-popover button:hover + p {
2305
+ display: block;
2306
+ }
2307
+
2308
+ .wpstg-code-block {
2309
+ margin-top: 4px;
2310
+ font-size: 1.2em;
2311
+ background: #f8f8f8;
2312
+ border-radius: 2px;
2313
+ }
2314
+
2315
+ .wpstg-rule-info {
2316
+ background: #f8f8f8 !important;
2317
+ }
2318
+
2319
+ code.wpstg-code {
2320
+ display: inline-block;
2321
+ font-size: 11px;
2322
+ border: 1px solid #aaa;
2323
+ background: #fff;
2324
+ padding: 2px 4px;
2325
+ margin-bottom: 1px;
2326
+ color: #ff6666;
2327
+ }
2328
+
2329
+ .wpstg-exclusion-rule-info {
2330
+ color: #fff !important;
2331
+ background-color: #ffc107;
2332
+ border: 1px solid #ffc107;
2333
+ width: 14px;
2334
+ height: 14px;
2335
+ border-radius: 7px;
2336
+ font-size: 14px;
2337
+ padding: 0;
2338
+ display: inline-flex;
2339
+ justify-content: center;
2340
+ align-items: center;
2341
+ outline: none;
2342
+ box-shadow: none;
2343
+ font-weight: 400;
2344
+ vertical-align: middle;
2345
+ }
2346
+
2347
+ .wpstg-exclusion-rule-info:hover {
2348
+ background-color: #ffba0c;
2349
+ border: 1px solid #ffba0c;
2350
+ }
2351
+
2352
+ /**
2353
+ * WP STAGING INPUTS EXCLUSION RULES
2354
+ */
2355
+
2356
+ .wpstg-exclude-rule-input {
2357
+ font-size: 12px !important;
2358
+ padding: 2px 6px;
2359
+ box-shadow: none;
2360
+ outline: none !important;
2361
+ display: inline-block;
2362
+ font-weight: 400;
2363
+ line-height: 1.5;
2364
+ color: #222;
2365
+ border-radius: 0 !important;
2366
+ background-color: #fff;
2367
+ border: 1px solid #bbb;
2368
+ min-height: 24px !important;
2369
+ margin-top: 4px;
2370
+ margin-left: 4px;
2371
+ vertical-align: baseline !important;
2372
+ transition: all 0.3s cubic-bezier(.25,.8,.25,1);
2373
+ width: 135px;
2374
+ }
2375
+
2376
+ .wpstg-excluded-filters-container tbody > tr:last-child .wpstg-exclude-rule-input {
2377
+ margin-bottom: 4px;
2378
+ }
2379
+
2380
+ .wpstg-exclude-rule-input:hover {
2381
+ border: 1px solid #999;
2382
+ }
2383
+
2384
+ .wpstg-exclude-rule-input:focus {
2385
+ border: 1px solid #25A0F1 !important;
2386
+ box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24) !important;
2387
+ }
2388
+
2389
+ .wpstg-file-size-exclude-select,
2390
+ .wpstg-path-exclude-select {
2391
+ width: 135px;
2392
+ }
2393
+
2394
+ .wpstg-file-size-exclude-select-small {
2395
+ width: 52px;
2396
+ }
2397
+
2398
+ .wpstg-file-size-exclude-input {
2399
+ width: 75px;
2400
+ }
2401
+
2402
+ .wpstg-staging-option-title {
2403
+ margin: 15px 0 0;
2404
  }
2405
 
2406
  .wpstg-swal-push-container.swal2-container {
2407
  z-index: 9995;
2408
  }
2409
+
2410
+ #wpstg-scanning-files {
2411
+ padding-bottom: 5px;
2412
+ }
2413
+
2414
+ #wpstg-scanning-files.wpstg-tab-section{
2415
+ padding-top:0;
2416
+ }
2417
+
2418
+ .wpstg-reset-excludes-container {
2419
+ margin: 10px 0;
2420
+ }
2421
+
2422
+ .wpstg-swal2-ajax-loader {
2423
+ width: 100%;
2424
+ height: 150px;
2425
+ overflow: hidden;
2426
+ display: flex;
2427
+ justify-content: center;
2428
+ align-items: center;
2429
+ }
2430
+
2431
+ @keyframes wpstg-loading-icon-anim {
2432
+ 0% {
2433
+ transform: rotate(0);
2434
+ }
2435
+ 100% {
2436
+ transform: rotate(360deg);
2437
+ }
2438
+ }
2439
+
2440
+ .wpstg-swal2-ajax-loader > img {
2441
+ width: 64px;
2442
+ height: 64px;
2443
+ animation: wpstg-loading-icon-anim 1s infinite linear;
2444
+ -webkit-animation: wpstg-loading-icon-anim 1s infinite linear;
2445
+ }
2446
+
2447
+ .wpstg-swal2-container .wpstg-tab-section {
2448
+ width: auto !important;
2449
+ }
2450
+
2451
+ .wpstg-is-dir-loading {
2452
+ position: absolute;
2453
+ margin-top: -2px;
2454
+ margin-left: 8px;
2455
+ display: none;
2456
+ }
2457
+
2458
+ .wpstg-ml-8px {
2459
+ margin-left: 8px;
2460
+ }
2461
+
2462
+ .wpstg-mb-8px {
2463
+ margin-bottom: 8px;
2464
+ }
2465
+
2466
+ .wpstg-button.danger {
2467
+ display: inline-block;
2468
+ text-decoration: none;
2469
+ text-align: center;
2470
+ text-transform: inherit;
2471
+ background-color: #e74c3c;
2472
+ color: white;
2473
+ border-radius: 0px;
2474
+ border-color: transparent;
2475
+ }
2476
+
2477
+ .wpstg-button.danger:hover {
2478
+ background-color: #c0392b;
2479
+ }
2480
+
2481
+ .wpstg-swal2-container.wpstg-swal2-loading > .swal2-modal {
2482
+ height: 200px;
2483
+ }
2484
+
2485
+ .wpstg-reset-confirmation.wpstg-swal2-container:not(.wpstg-swal2-loading) > .swal2-modal {
2486
+ max-width: 480px;
2487
+ }
2488
+
2489
+ .wpstg-reset-confirmation.wpstg-swal2-container .swal2-header {
2490
+ display: none;
2491
+ }
2492
+
2493
+ .wpstg-reset-confirmation.wpstg-swal2-container .swal2-content {
2494
+ height: auto;
2495
+ }
2496
+
2497
+ .wpstg-reset-confirmation.wpstg-swal2-container > .swal2-modal > .swal2-content .wpstg-tabs-wrapper {
2498
+ overflow-y: auto;
2499
+ height: auto !important;
2500
+ }
2501
+
2502
+ .wpstg-reset-confirmation.wpstg-swal2-container > .swal2-modal > .swal2-content {
2503
+ font-size: 13px;
2504
+ }
2505
+
2506
+ .wpstg-reset-confirmation.wpstg-swal2-container > .swal2-modal > .swal2-content .wpstg-dir {
2507
+ margin-bottom: 4px;
2508
+ }
2509
+
2510
+ .wpstg-reset-confirmation.wpstg-swal2-container > .swal2-modal > .swal2-content .wpstg-subdir {
2511
+ margin-top: 4px;
2512
+ }
2513
+
2514
+ .wpstg-reset-confirmation.wpstg-swal2-container.has-collapsible-open .swal2-modal {
2515
+ height: calc(100vh - 70px);
2516
+ }
2517
+
2518
+ .wpstg-reset-confirmation.wpstg-swal2-container.has-collapsible-open > .swal2-modal > .swal2-content .wpstg-tabs-wrapper {
2519
+ height: calc(100vh - 350px) !important;
2520
+ }
2521
+
2522
+ /*# sourceMappingURL=wpstg-admin.css.map */
assets/css/dist/wpstg-admin.css.map ADDED
@@ -0,0 +1 @@
 
1
+ {"version":3,"sources":["wpstg-admin.css"],"names":[],"mappings":"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","file":"wpstg-admin.css","sourcesContent":["/**\n * WPSTG Admin CSS\n *\n * @package WPSTG\n * @subpackage Admin CSS\n * @copyright Copyright (c) 2021, René Hermenau\n * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License\n*/\n\n\n/* CSS for Tabs */\n\n#wpstg-tab-container ul {\n /*height: 200px;*/\n list-style: none;\n margin: 0;\n padding: 0;\n background: #f1f1f1;\n float: left;\n /*list-style-type: square;*/\n}\n\n#wpstg-tab-container ul li:first-child.selected-tab {\n border-top: none;\n}\n\n#wpstg-tab-container ul li a.selected-tab {\n font-weight: bold;\n text-decoration: none;\n}\n\n#wpstg-tab-container .row {\n padding-top: 10px;\n padding-bottom: 12px;\n}\n\n.wpstg-tabs-container .nav-tab-wrapper {\n padding: 0;\n}\n\n#wpstg-tab-container .row label strong,\n#wpstg-tab-container .row strong {\n font-weight: bold;\n}\n\n.wpstg-tabs a {\n padding: 5px;\n}\n\n#wpstg-tab-container>ul>li.wpstg-tabs.active {\n background-color: white;\n}\n\n#wpstg_settingsgeneral_header .row:nth-child(3),\n#wpstg_settingsgeneral_header .row:nth-child(4) {\n display: none;\n}\n\n#wpstg-tab-container .wpstg-settings-panel {\n padding: 0 20px 20px 20px;\n overflow: auto;\n}\n\n#wpstg-tab-container .wpstg-form-table th {\n vertical-align: top;\n text-align: left;\n padding: 20px 10px 20px 0;\n line-height: 1.3;\n font-weight: bold;\n font-size: 14px;\n color: #484848;\n width: 30%;\n}\n\n#wpstg-tab-container .wpstg-form-table tr {\n border-bottom: 1px solid #E7E7E7;\n}\n\n#wpstg-tab-container span.description {\n display: block;\n font-weight: 400;\n font-style: normal;\n font-size: 13px;\n margin-top: 7px;\n color: #484848;\n}\n\n#wpstg-tab-container .col-title {\n color: #484848;\n}\n\n@media only screen and (max-width: 680px) {\n #wpstg-tab-container ul {\n float: none;\n }\n #wpstg-tab-container .wpstg-form-table tr>th {\n width: 100%;\n }\n #wpstg-tab-container span.description {\n font-size: 14px;\n }\n #wpstg-tab-container .wpstg-form-table tr>th,\n #wpstg-tab-container .wpstg-form-table tr>td {\n padding: 10px;\n }\n}\n\n#wpstg-tab-container ul li {\n margin-bottom: 0;\n}\n\n#wpstg-tab-container ul li a {\n display: block;\n padding: 10px 4px 10px 14px;\n border-width: 1px 0;\n border-style: solid;\n border-top-color: white;\n border-bottom-color: #e7e7e7;\n text-decoration: none;\n color: #0097DF;\n font-weight: bold;\n}\n\n#wpstg-tab-container ul li a:hover {\n background-color: #e5e5e5;\n color: #777777;\n}\n\n.wpstg-logo {\n display: block;\n font-size: 16px;\n padding-top: 20px;\n width: 220px;\n float: left;\n}\n\n.wpstg-version {\n display: block;\n padding-top: 29px\n}\n\n.wpstg_admin .nav-tab {\n color: #3C3C3C;\n}\n\n#wpstg-tab-container table tbody tr:nth-child(1)>th>div {\n font-size: 20px;\n}\n\n.wpstg_hidden {\n display: none;\n}\n\n\n/* Cloning workflow */\n\n#wpstg-clonepage-wrapper {\n margin-bottom: 20px;\n}\n\n@media screen and (min-width: 1090px) {\n #wpstg-clonepage-wrapper {\n float: left;\n margin-bottom: 20px;\n }\n .wpstg-sidebar {\n display: none;\n margin-left: 700px;\n margin-top: 138px;\n }\n}\n\n.wpstg-sidebar {\n display: none;\n padding: 10px;\n border: 1px solid #DFDFDF;\n max-width: 250px;\n height: 250px;\n}\n\n#wpstg-steps {\n margin-top: 30px;\n}\n\n#wpstg-steps li {\n color: #444;\n line-height: 20px;\n padding-right: 10px;\n float: left;\n}\n\n.wpstg-step-num {\n border: 1px solid #444;\n border-radius: 3px;\n display: inline-block;\n width: 20px;\n height: 20px;\n text-align: center;\n margin-right: 5px;\n}\n\n.wpstg-current-step {\n font-weight: bold;\n}\n\n.wpstg-current-step .wpstg-step-num {\n background: #444;\n color: #eee;\n}\n\n.wpstg-box {\n margin: 10px 0;\n padding: 10px;\n position: relative;\n overflow: hidden;\n transition: border-color .2s ease-in-out;\n}\n\n.wpstg-clone {\n margin-bottom: 3px;\n padding: 16px;\n position: relative;\n transition: border-color .2s ease-in-out;\n background-color: #25a1f0;\n border-radius: .25rem;\n box-shadow: 0 0 1px rgba(0,0,0,.125), 0 1px 3px rgba(0,0,0,.2);\n}\n\n.wpstg-clone.active {\n border-color: #1d94cf;\n}\n\n.wpstg-clone-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n\n.wpstg-clone-title {\n display: inline-block;\n font-size: 15px;\n max-width: 300px;\n text-decoration: none;\n font-weight: bold;\n color: white;\n}\n\n.wpstg-clone-title:hover {\n color: #f1f1f1;\n}\n\n.wpstg-clone-actions {\n display: flex;\n /*align-items: right;*/\n}\n\n.wpstg-dropdown {\n position: relative;\n}\n\n.wpstg-clone-actions .wpstg-dropdown-toggler {\n text-decoration: none;\n background: #fff;\n padding: 4px 10px;\n border-radius: 2px;\n font-size: 14px;\n box-shadow: 0 0 1px rgba(0,0,0,.125), 0 1px 3px rgba(0,0,0,.2);\n color: #002648;\n}\n\n.wpstg-clone-actions .wpstg-dropdown-toggler:hover {\n background: #002648;\n color: white;\n}\n\n.wpstg-dropdown {\n position: relative;\n}\n\n.wpstg-dropdown-symbol {\n font-size: 14px;\n margin-left: 4px;\n}\n\n.wpstg-dropdown>.wpstg-dropdown-menu {\n background: #fff;\n display: none;\n flex-direction: column;\n position: absolute;\n right: 0;\n top: calc(100% + 4px);\n padding: 8px;\n border-radius: 2px;\n width: 100px;\n box-shadow: 0 0 1px rgba(0,0,0,.125), 0 1px 3px rgba(0,0,0,.2);\n z-index: 1000;\n}\n\n.wpstg-dropdown>.wpstg-dropdown-menu.wpstg-menu-dropup {\n top: auto;\n bottom: 100%;\n transform: translate3d(0px, -3px, 0px);\n}\n\n.wpstg-dropdown>.wpstg-dropdown-menu.shown {\n display: flex;\n}\n\n.wpstg-clone-action,\n.wpstg-dropdown-action {\n color: #002648;\n padding: 5px 8px;\n border-radius: 3px;\n text-decoration: none;\n position: relative;\n transition: color .2s ease-in-out;\n}\n\n.wpstg-clone-action:hover,\n.wpstg-dropdown-action:hover {\n background: rgba(0,0,0,0.05);\n}\n\n.wpstg-dropdown-action {\n color: #333;\n background: transparent;\n border: 0 solid black;\n outline: none;\n box-shadow: none;\n}\n\n.wpstg-remove-clone:hover {\n color: #ef6d6d;\n}\n\n.wpstg-clone-action:last-child {\n border: none;\n}\n\n.wpstg-clone:hover .wpstg-clone-action {\n display: inline-block;\n}\n\n#wpstg-show-error-details:focus,\n#wpstg-workflow .wpstg-clone-action {\n outline: none;\n box-shadow: none;\n}\n\n.wpstg-link-btn {\n background: #45a1c9;\n color: #fff;\n display: inline-block;\n padding: 5px 10px;\n text-decoration: none;\n vertical-align: baseline;\n transition: all .2s ease-in-out;\n}\n\n.wpstg-link-btn:hover,\n.wpstg-link-btn:focus {\n color: #fff;\n outline: none;\n box-shadow: none;\n}\n\n#wpstg-workflow .wpstg-link-btn:active {\n vertical-align: baseline;\n}\n\n.wpstg-link-btn[disabled] {\n background: #777 !important;\n pointer-events: none;\n}\n\n#wpstg-cancel-cloning,\n#wpstg-cancel-cloning-update {\n background: #ff3428;\n border-color: #e72f24;\n margin-top: 5px;\n}\n\n#wpstg-cancel-cloning.success,\n#wpstg-cancel-cloning.success {\n background: #64dd58;\n border-color: #54bd4a;\n}\n\n#wpstg-error-wrapper,\n#wpstg-error-details {\n display: none;\n padding-top: 10px;\n font-size: 13px;\n clear: both;\n}\n\n#wpstg-show-error-details {\n display: inline-block;\n margin-left: 5px;\n color: #555;\n text-decoration: none;\n transition: color .2s ease-in-out;\n}\n\n#wpstg-show-error-details:hover {\n color: #1d94cf;\n}\n\n#wpstg-error-details {\n border-left: 5px solid #ef6d6d;\n padding: 10px;\n width: 500px;\n}\n\n#wpstg-try-again {\n display: none;\n}\n\n#wpstg-home-link {\n float: right;\n}\n\n.wpstg-loader {\n content: url('../../img/loading.gif');\n margin-top: 5px;\n display: none;\n}\n\n.wpstg-loader.wpstg-finished {\n display: block;\n content: \"Finished\";\n background-color: #00c89a;\n color: white;\n padding: 2px 10px;\n margin-top: 0;\n border-radius: 3px;\n}\n\n#wpstg-workflow {\n max-width: 650px;\n position: relative;\n clear: both;\n padding-top: 20px;\n float: left;\n min-width: 500px;\n /*border-right: 1px solid #DFDFDF;*/\n min-height: 380px;\n padding-right: 20px;\n padding-bottom: 20px;\n}\n\n#wpstg-sidebar {\n float: left;\n max-width: 400px;\n display: block;\n margin-left: 10px;\n}\n\n@media screen and (max-width: 1150px) {\n #wpstg-sidebar img {\n margin-top: 30px;\n }\n}\n\n#wpstg-workflow.loading::after,\n#wpstg-removing-clone.loading::after {\n background: rgba(255, 255, 255, .7);\n content: 'Loading... may take a while for huge websites';\n display: block;\n width: 100%;\n height: 100%;\n font-size: 20px;\n padding-top: 100px;\n text-align: center;\n position: absolute;\n top: 0;\n left: 0;\n z-index: 99;\n}\n\n#wpstg-removing-clone.loading::after {\n content: 'REMOVING' !important;\n}\n\n#wpstg-existing-clones,\n#wpstg-removing-clone {\n position: relative;\n}\n\n#wpstg-removing-clone .wpstg-tab-section {\n display: block;\n}\n\n.wpstg-progress-bar {\n max-width: 900px;\n height: 27px;\n padding: 0;\n background-color: #d6d8d7;\n}\n\n.wpstg-progress {\n float: left;\n background: #3fa5ee;\n width: 0;\n height: 100%;\n transition: width .6s ease;\n color: white;\n line-height: 25px;\n text-align: center;\n overflow: hidden;\n}\n\n.wpstg-progress-files {\n background: #16b4f0;\n width: 0;\n height: 100%;\n transition: width .6s ease;\n color: white;\n line-height: 25px;\n text-align: center;\n}\n\n#wpstg-new-clone-id.wpstg-error-input,\n#wpstg-clone-path.wpstg-error-input {\n border: 1px solid #ff4235;\n box-shadow: 0 0 2px rgba(255, 66, 53, .8);\n}\n\n#wpstg-new-clone {\n background: #25a1f0;\n border-color: #2188c9;\n}\n\n#wpstg-new-clone:hover {\n background: #259be6;\n border-color: #2188c9;\n}\n\n#wpstg-clone-path {\n margin-left: 10px;\n width: 350px;\n}\n\n.wpstg-error-msg {\n color: #ff4235;\n}\n\n#wpstg-clone-id-error {\n display: block;\n background-color: #f0f8ff;\n padding: 10px;\n margin: 20px;\n}\n\n#wpstg-start-cloning+.wpstg-error-msg {\n display: block;\n margin-top: 5px;\n}\n\n.wpstg-size-info {\n color: #999;\n font-weight: normal;\n position: relative;\n left: 2px;\n}\n\n.wpstg-db-table .wpstg-size-info {\n top: 2px;\n}\n\n.wpstg-db-table:hover {\n background-color: #f0f8ff;\n}\n\n#wpstg-workflow #wpstg-start-cloning {\n display: inline-block;\n margin-left: 5px;\n font-size: 14px;\n vertical-align: baseline;\n}\n\n\n/* Tabs */\n\n.wpstg-tabs-wrapper {\n max-width: 640px;\n margin: 10px 0;\n}\n\n#wpstg-path-wrapper {\n border-bottom: 2px dashed #ccc;\n padding-bottom: 10px;\n margin-bottom: 10px;\n}\n\n\n/* unused class should be removed or commented\n.wpstg-tabs-wrapper {\n border: 1px solid #ddd;\n border-right: none;\n border-left: none;\n}\n*/\n\n.wpstg-tab-section {\n border-bottom: 1px solid #ddd;\n border-right: none;\n border-left: none;\n display: none;\n width: 100%;\n padding: 20px;\n}\n\n.wpstg-tab-section::after {\n display: block;\n content: '';\n clear: both;\n}\n\n.wpstg-tab-header {\n border-bottom: 1px solid #ddd;\n border-right: none;\n border-left: none;\n color: #444;\n font-size: 16px;\n font-weight: bolder;\n display: block;\n padding: 10px;\n ;\n text-decoration: none;\n}\n\n.wpstg-tab-triangle {\n display: inline-block;\n margin-right: 10px;\n animation: transform 0.5s;\n}\n\n.wpstg-tab-header:focus {\n color: #444;\n outline: none;\n box-shadow: none;\n}\n\n#wpstg-large-files {\n display: none;\n border: 1px dashed #ccc;\n /*float: right;*/\n padding: 10px 10px 10px;\n margin-top: 20px;\n position: relative;\n font-size: 12px;\n}\n\n#wpstg-large-files h3 {\n background: #fff;\n margin: 0;\n padding: 0 5px;\n position: absolute;\n top: -10px;\n left: 5px;\n}\n\n\n/* tmp */\n\n.wpstg-subdir {\n display: none;\n margin-left: 20px;\n}\n\n.wpstg-subdir.wpstg-push {\n display: block;\n margin-left: 20px;\n}\n\n.wpstg-dir a.disabled {\n color: #888;\n cursor: default;\n text-decoration: none;\n}\n\n.wpstg-check-subdirs {\n display: inline-block;\n margin-left: 10px;\n}\n\n.wpstg-notice-alert {\n display: block;\n background-color: #FFD0D0;\n padding: 20px;\n border-radius: 6px;\n border: 1px solid #FFAAAA;\n max-width: 600px;\n margin-top: 10px;\n}\n\n.wpstg-header {\n font-weight: 400;\n line-height: 1.6em;\n font-size: 19px;\n border-bottom: 1px solid #DFDFDF;\n clear: both;\n}\n\n#wpstg-clone-label {\n font-size: 14px;\n font-weight: bold;\n}\n\n.wpstg-log-details {\n height: 300px;\n overflow: scroll;\n max-width: 650px;\n font-family: monospace;\n font-size: 12px;\n line-height: 15px;\n border: 1px solid #FFF;\n background-color: black;\n color: #c0c0c0;\n padding: 3px;\n white-space: nowrap;\n margin-top: 15px;\n}\n\n#wpstg-finished-result {\n display: none;\n}\n\n#wpstg-remove-cloning {\n background: #ff3428;\n border-color: #e72f24;\n margin-top: 5px;\n}\n\n#wpstg-success-notice {\n padding: 10px;\n background-color: white;\n max-width: 900px;\n border: 1px solid #ccc;\n margin-top: 20px;\n}\n\n.wpstg_beta_notice {\n margin-bottom: 20px;\n}\n\n.wpstg-sysinfo {\n width: 700px;\n height: 700px;\n}\n\n.wpstg-form-table .col-title label {\n font-weight: 600;\n}\n\n.wpstg-form-table td:first-child {\n width: 30%;\n}\n\n.wpstg-share-button-container {\n margin: 5px 0;\n}\n\n.wpstg-share-button-container p {\n margin: 0 0 10px 0;\n}\n\n.wpstg-share-button {\n display: inline-block;\n}\n\n.wpstg-share-button a {\n text-decoration: none;\n}\n\n.wpstg-share-button .wpstg-share {\n font-family: sans-serif;\n font-weight: bold;\n text-decoration: none;\n text-align: center;\n}\n\n.wpstg-share-button .wpstg-share {\n -webkit-border-radius: 2px;\n -moz-border-radius: 2px;\n border-radius: 2px;\n color: #FFF;\n display: inline;\n font-size: 12px;\n padding: 4px 8px;\n}\n\n.wpstg-share-button-twitter .wpstg-share {\n background-color: #00ABF0;\n}\n\n.wpstg-share-button-facebook .wpstg-share {\n background-color: #3b5998;\n}\n\n.wpstg-share-button-googleplus .wpstg-share {\n background-color: #F53424;\n}\n\n.wpstg-share-button-twitter .share:active,\n.wpstg-share-button-facebook .share:active,\n.wpstg-share-button-googleplus .share:active {\n background-color: #353535;\n}\n\n#wpstg-check-space {\n margin-left: 8px;\n}\n\n\n/* welcome screen */\n\n.wpstg-button.green {\n display: inline-block;\n padding: 10px;\n min-width: 170px;\n font-size: 16px;\n text-decoration: none;\n text-align: center;\n margin-top: 20px;\n background-color: #83c11f;\n color: white;\n}\n\n.wpstg-button.green:hover {\n background-color: #8ed122;\n}\n\n.wpstg-button.wpstg-save {\n background-color: #1687A7;\n color: white;\n}\n\n.wpstg-button.wpstg-save:hover {\n background-color: #276678;\n}\n\n.wpstg-button.wpstg-bordered {\n border-radius:3px;\n font-size: 14px;\n border: 1px solid white;\n}\n\n#wpstg-welcome li {\n font-size: 18px;\n line-height: 29px;\n position: relative;\n padding-left: 23px;\n list-style: none !important;\n}\n\n#wpstg-welcome {\n margin-top: 20px;\n margin-right: 20px;\n background-color: white;\n}\n\n.wpstg-heading-pro {\n color: #0080ff;\n font-weight: bold;\n}\n\n.wpstg-h2 {\n margin-top: 0;\n margin-bottom: 1.2rem;\n font-size: 30px;\n line-height: 2.5rem;\n}\n\n#wpstg-welcome li:before {\n width: 1em;\n height: 100%;\n background: url(data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%2377B227%22%20d%3D%22M1671%20566q0%2040%2D28%2068l%2D724%20724%2D136%20136q%2D28%2028%2D68%2028t%2D68%2D28l%2D136%2D136%2D362%2D362q%2D28%2D28%2D28%2D68t28%2D68l136%2D136q28%2D28%2068%2D28t68%2028l294%20295%20656%2D657q28%2D28%2068%2D28t68%2028l136%20136q28%2028%2028%2068z%22%2F%3E%3C%2Fsvg%3E) left .4em no-repeat;\n background-size: contain;\n content: \"\";\n position: absolute;\n top: 0;\n left: 0;\n color: #77b227;\n}\n\n.wpstg-h1 {\n margin-bottom: 1.35rem;\n font-size: 2.5em;\n line-height: 3.68rem;\n letter-spacing: normal;\n}\n\n.swal2-content h1 {\n color:#444;\n}\n\n#wpstg-welcome h2 {\n margin: 0 0 15px;\n}\n\n#wpstg-welcome .wpstg-footer {\n clear: both;\n margin-top: 20px;\n font-style: italic;\n}\n\n#wpstg-footer {\n clear: both;\n background-color: white;\n padding: 20px;\n margin-top: 20px;\n margin-right: 10px;\n}\n\n#wpstg-footer a {\n text-decoration: none;\n}\n\n.wpstg-staging-info {\n margin-top: 8px;\n color: white;\n font-size: 12px;\n}\n\n.wpstg-staging-info a {\n color: white;\n}\n\n.wpstg-staging-info li {\n margin-bottom: 2px;\n}\n\n.wpstg-bold {\n font-weight: 600;\n}\n\n#wpstg-processing-status {\n margin-top: 5px;\n font-size: 13px;\n font-weight: 400;\n float: left;\n}\n\n#wpstg-processing-timer {\n margin-top: 5px;\n font-size: 13px;\n font-weight: 400;\n float: right;\n}\n\n#wpstg-report-issue-button {\n margin-left: 50px;\n border: 1px solid #ef5a4b;\n color: #ef5a4b;\n background-color: white;\n}\n\n#wpstg-report-issue-button:hover {\n background-color: #e74c3c;\n color: #fff;\n}\n\n.wpstg-button {\n display: inline-block;\n background-color: transparent;\n color: #95a5a6;\n border-radius: 3px;\n cursor: pointer;\n padding: 2px 10px 2px 10px;\n text-transform: uppercase;\n font-weight: 500;\n outline: 0;\n transition: background-color .1s ease-in;\n text-decoration: none;\n}\n\n.wpstg-button.wpstg-button-light {\n background-color: #f8f8f8;\n border: 1px solid #eee;\n color: #333;\n animation: background-color 0.3s;\n}\n\n.wpstg-button.wpstg-button-light:hover {\n background-color: #e0e0e0;\n border: 1px solid #e0e0e0;\n}\n\n.wpstg-blue-primary {\n display: inline-block;\n text-decoration: none;\n font-size: 13px;\n line-height: 26px;\n height: 28px;\n margin: 0;\n padding: 0 10px 1px;\n cursor: pointer;\n border-width: 1px;\n border-style: solid;\n -webkit-appearance: none;\n border-radius: 3px;\n white-space: nowrap;\n box-sizing: border-box;\n background: #25a1f0;\n border-color: #2188c9;\n color: #fff;\n text-shadow: 0 -1px 1px #006799, 1px 0 1px #006799, 0 1px 1px #006799, -1px 0 1px #006799;\n}\n\n.wpstg-blue-primary:hover {\n background-color: #259be6;\n}\n\n.wpstg-report-issue-form {\n position: absolute;\n z-index: 9999;\n width: 300px;\n background-color: #fff;\n padding: 15px 15px 10px;\n border: 1px solid #e8e8e8;\n border-radius: 3px;\n box-shadow: 0 1px 0 0 #fff inset;\n display: none;\n margin: 67px 0 0 123px;\n}\n\n.wpstg-report-show {\n display: block;\n}\n\n.wpstg-field input[type=text],\n.wpstg-field textarea {\n width: 100%;\n font-weight: 400;\n line-height: 1.4;\n margin-bottom: 4px;\n}\n\n.wpstg-report-email,\n.wpstg-report-hosting-provider {\n width: 100%;\n font-weight: 400;\n font-size: .8rem;\n height: 2.3rem;\n line-height: 2.3rem;\n border-radius: 3px;\n margin-bottom: 4px;\n padding: 0 10px;\n}\n\n.wpstg-report-description {\n border-radius: 3px;\n font-size: .8rem;\n padding: 6px 10px;\n resize: none;\n}\n\n.wpstg-report-privacy-policy {\n font-size: 12px;\n margin-bottom: 15px;\n}\n\n#wpstg-report-cancel {\n float: right;\n margin-right: 5px;\n}\n\n.wpstg-buttons .spinner {\n float: none;\n margin: 0 0 0 5px;\n}\n\n.wpstg-message {\n box-sizing: border-box;\n -moz-box-sizing: border-box;\n background-color: #f5e0de;\n border-radius: 3px;\n color: rgba(0, 0, 0, .6);\n height: auto;\n margin: 10px 0;\n min-height: 18px;\n padding: 6px 10px;\n position: relative;\n}\n\n.wpstg-message.wpstg-error-message {\n background-color: #f5e0de;\n color: #b65147;\n font-size: 12px;\n}\n\n.wpstg-message.wpstg-success-message {\n background-color: #d7f8e0;\n color: #515151;\n}\n\n.wpstg-message p {\n margin: 3px 0;\n font-size: 13px;\n}\n\n.wpstg-warning {\n display: block;\n padding: 10px;\n background-color: #ffb804;\n color: #ffffff;\n margin: 10px 10px 10px 0;\n}\n\n.wpstg-warning a {\n color: #ffffff;\n font-weight: bold;\n text-decoration: underline;\n}\n\n.wpstg-error {\n display: block;\n padding: 10px;\n background-color: #fe6501;\n color: #ffffff;\n margin: 10px 10px 10px 0;\n}\n\n.wpstg-error a {\n color: #ffffff;\n font-weight: bold;\n text-decoration: underline;\n}\n\n#wpstg-resume-cloning {\n display: none;\n}\n\n#wpstg-external-db th {\n text-align: left;\n width: 120px;\n}\n\n#wpstg-db-connect {\n font-weight: normal;\n}\n\n#wpstg-db-status {\n display: block;\n margin-top: 5px;\n padding: 5px;\n margin-bottom: 20px;\n border: 1px solid transparent;\n border-radius: 4px;\n text-decoration: none;\n text-align: center;\n}\n\n.wpstg-text-field>#wpstg-db-status {\n margin-top: 8px;\n margin-left: 25%;\n min-width: 350px;\n}\n\n.wpstg-success {\n color: #3c763d;\n background-color: #dff0d8;\n border-color: #d6e9c6;\n}\n\n.wpstg-failed {\n color: #a94442;\n background-color: #f2dede;\n border-color: #ebccd1;\n}\n\n#wpstg_select_tables_cloning {\n height: 600px;\n font-size: 13px;\n}\n\n#wpstg-update-notify {\n background-color: #fe6501;\n font-size: 14px;\n color: #ffffff;\n line-height: normal;\n padding: 10px;\n margin-right: 10px;\n}\n\n#wpstg-update-notify a {\n color: #ffffff;\n font-weight: bold;\n}\n\n.wpstg-pointer {\n cursor: pointer;\n}\n\n.wpstg--tab--header ul {\n display: flex;\n}\n\n.wpstg--tab--header ul li {\n margin-right: 1em;\n}\n\n.wpstg--tab--header ul li:last-child {\n margin-right: 0;\n}\n\n.wpstg--tab--header a {\n min-width: 150px;\n text-align: center;\n cursor: pointer;\n display: inline-block;\n padding: 1em 1.25em;\n border: solid 1px;\n}\n\n.wpstg--tab--header a.wpstg--tab--active {\n border-bottom: .5em solid #25A1F0;\n color: #25A1F0;\n}\n\n.wpstg--tab--content {\n display: none;\n}\n\n.wpstg--tab--active {\n display: block;\n}\n\n.wpstg--text--strong,\n.wpstg--text--strong * {\n font-weight: bold !important;\n}\n\n.wpstg--text--danger {\n color: #a94442;\n}\n\n.wpstg--tooltip {\n position: relative;\n display: inline-block;\n border-bottom: 1px dotted black;\n margin-left: 10px;\n}\n\n.wpstg--tooltip .wpstg--tooltiptext {\n visibility: hidden;\n width: 300px;\n background-color: #ffffff;\n color: #505050;\n text-align: left;\n padding: 20px;\n border: 1px solid #e8e8e8;\n border-radius: 3px;\n position: absolute;\n z-index: 1;\n -webkit-box-shadow: -1px 1px 5px 0 rgba(0, 0, 0, 0.75);\n -moz-box-shadow: -1px 1px 5px 0 rgba(0, 0, 0, 0.75);\n box-shadow: -1px 1px 5px 0 rgba(0, 0, 0, 0.75);\n}\n\n.wpstg--tooltip:hover .wpstg--tooltiptext {\n visibility: visible;\n}\n\n.wpstg--tooltiptext-backups {\n width: 120px;\n top: 100%;\n left: -150%;\n margin-left: -60px;\n /* Use half of the width (120/2 = 60), to center the tooltip */\n margin-top: 10px;\n}\n\n\n/**\nTooltip top arrow\n */\n\n.wpstg--tooltip .wpstg--tooltiptext-backups::after {\n content: \" \";\n position: absolute;\n bottom: 100%;\n /* At the top of the tooltip */\n left: 50%;\n margin-left: 25px;\n border-width: 5px;\n border-style: solid;\n border-color: transparent transparent white transparent;\n}\n\n.wpstg--snaphot-restore-table tr {\n line-height: 12px;\n}\n\n.wpstg-float-left {\n float: left;\n}\n\n.wpstg-beta-notice {\n background-color: #b0e8b0;\n border-radius: 3px;\n padding: 7px;\n margin-bottom: 20px;\n}\n\n#wpstg-backup-name {\n font-size: 1.875em;\n font-weight: 600;\n}\n\n#wpstg_select_tables_cloning option:checked {\n /* Cannot use background color here because Chrome and Firefox ignore it even if set to !important */\n -webkit-appearance: menulist-button;\n background-image: linear-gradient(0deg, #1e90ff 0%, #1e90ff 100%);\n}\n\n.wpstg--btn--cancel {\n background: #ff3428;\n border-color: #e72f24;\n color: #fff;\n height: auto;\n line-height: normal;\n font-size: 16px;\n padding: .5em;\n margin-bottom: 1.5em;\n}\n\n.wpstg--btn--cancel:hover {\n background: #ff3428;\n border-color: #e72f24;\n}\n\n.wpstg--process--content>.swal2-html-container {\n padding: 4em 2em !important;\n}\n\n.wpstg--modal--process--logs,\n.wpstg--modal--error--logs {\n background: black;\n height: 300px;\n margin-top: 1em;\n display: none;\n padding: 1em;\n overflow-x: auto;\n text-align: justify;\n}\n\n.wpstg--modal--error--logs {\n height: auto;\n max-height: 300px;\n}\n\n.wpstg--modal--process--logs>p,\n.wpstg--modal--error--logs>p {\n text-align: left;\n font-size: 14px;\n}\n\n.wpstg--modal--process--logs p,\n.wpstg--modal--error--logs p {\n margin: .3em 0;\n}\n\n.wpstg--modal--process--msg--error {\n color: darkred;\n}\n\n.wpstg--modal--process--msg--critical {\n color: red;\n}\n\n.wpstg--modal--process--msg--warning {\n color: darkorange;\n}\n\n.wpstg--modal--process--msg-found {\n color: #f56363;\n}\n\nbody.toplevel_page_wpstg_clone .swal2-modal .swal2-cancel.wpstg--btn--cancel {\n margin-bottom: 0;\n}\n\nbody.toplevel_page_wpstg_clone .swal2-modal .swal2-confirm.wpstg--btn--confirm {\n font-size: 16px;\n padding: .5em;\n line-height: normal;\n height: auto;\n margin-right: 10px;\n}\n\nbody.toplevel_page_wpstg_clone .swal2-modal .wpstg-loader {\n display: inline-block !important;\n}\n\n.wpstg--modal--process--generic-problem {\n display: none;\n border-left: 5px solid #ef6d6d;\n margin: .5em 0;\n}\n\n.wpstg--modal--process--logs--tail {\n color: #a8a8a8;\n background: none;\n border: none;\n cursor: pointer;\n}\n\n.wpstg--modal--backup--import--upload--title {\n color: #505050;\n}\n\n.wpstg--modal--backup--import--filesystem,\n.wpstg--modal--backup--import--configure,\n.wpstg--modal--backup--import--upload--status,\n.wpstg--modal--backup--import--upload--container input[type=\"file\"] {\n display: none;\n}\n\n#wpstg--backups--import--file-list {\n font-size: 14px;\n font-weight: bold;\n}\n\n#wpstg--backups--import--file-list-empty {\n color: red;\n}\n\n.wpstg--modal--backup--import--filesystem label {\n font-size: 14px;\n}\n\n.wpstg--modal--backup--import--filesystem button {\n margin-bottom: 20px;\n}\n\n.wpstg--modal--backup--import--upload,\n.wpstg--modal--backup--import--filesystem {\n color: #505050;\n}\n\n.wpstg--modal--backup--import--upload--container {\n position: relative;\n border-radius: 1em;\n margin: .5em;\n padding: 1em .5em;\n border: .4em dashed #dedede;\n display: flex;\n flex-direction: column;\n}\n\n.wpstg--modal--backup--import--upload--container .wpstg--uploader {\n display: flex;\n flex-direction: column;\n}\n\n.wpstg--modal--backup--import--upload--container.wpstg--has-dragover {\n background-color: #9a9a9a;\n color: white;\n}\n\n.wpstg--modal--backup--import--upload--container span.wpstg--drop,\n.wpstg--modal--backup--import--upload--container.wpstg--has-dragover span.wpstg--drag,\nspan.wpstg--backup--import--selected-file,\nspan.wpstg--drag-or-upload {\n display: none;\n}\n\n.wpstg--modal--backup--import--upload--container.wpstg--has-dragover span.wpstg--drop {\n display: inline-block;\n}\n\n.wpstg--modal--backup--import--upload--container input[type='file'] {\n display: none;\n}\n\n.wpstg--modal--backup--import--upload--container img {\n width: 4em;\n align-self: center;\n border: none;\n}\n\n.wpstg--modal--backup--import--upload--container span {\n margin-top: 1em;\n}\n\n.wpstg--backup--import--options>button {\n margin-top: 1em;\n padding: 1em;\n align-self: center;\n width: 185px;\n height: auto;\n line-height: normal;\n}\n\n\n/*.wpstg--backup--import--options.wpstg--show-options > button {\n background: white;\n border-radius: 3px 3px 0 0;\n border: .25em solid #25a1f0;\n text-shadow: none;\n color: #2e3436;\n}*/\n\n.wpstg--backup--import--options {\n position: relative;\n display: flex;\n justify-content: center;\n}\n\n.wpstg--backup--import--options ul {\n display: none;\n}\n\n.wpstg--backup--import--options.wpstg--show-options ul {\n padding: 0;\n margin: 54px 0 0 0;\n display: block;\n position: absolute;\n width: 185px;\n background: #25a1f0;\n box-sizing: border-box;\n border-radius: 0 0 3px 3px;\n border-width: 1px;\n border-color: #2188c9;\n text-shadow: 0 -1px 1px #006799, 1px 0 1px #006799, 0 1px 1px #006799, -1px 0 1px #006799;\n}\n\n.wpstg--backup--import--options.wpstg--show-options ul li {\n border-bottom: .1em solid #25a1f0;\n margin: 0;\n}\n\n.wpstg--backup--import--options.wpstg--show-options ul li:hover {\n background-color: #25a1f0;\n}\n\n.wpstg--backup--import--options.wpstg--show-options ul li:last-child {\n border-bottom: none;\n}\n\n.wpstg--backup--import--options ul li button {\n cursor: pointer;\n background: none;\n border: none;\n margin: 0;\n width: 100%;\n color: white;\n height: 40px;\n line-height: 40px;\n}\n\n.wpstg--backup--import--options ul li button:hover {\n background-color: #259be6;\n}\n\n.wpstg--modal--backup--import--search-replace--info {\n margin: 1em 0;\n display: flex;\n flex-direction: row;\n}\n\n.wpstg--modal--backup--import--info p {\n text-align: left;\n margin: 0;\n}\n\n\n/* unused class should be removed or commented\n.wpstg--modal--backup--import--search-replace--wrapper {\n display: flex;\n flex-direction: row;\n padding: 0 5em;\n}\n*/\n\n.wpstg--modal--backup--import--search-replace--wrapper button {\n align-self: center;\n}\n\n.wpstg--import--advanced-options--button {\n border: 0;\n border-radius: 3px;\n font-size: 18px;\n text-shadow: 0 -1px 1px #006799, 1px 0 1px #006799, 0 1px 1px #006799, -1px 0 1px #006799;\n cursor: pointer;\n}\n\n.wpstg--modal--backup--import--search-replace--new {\n color: white;\n background-color: #25a1f0;\n}\n\n.wpstg--modal--backup--import--search-replace--remove {\n color: white;\n background-color: #25a1f0;\n width: 22px;\n height: 22px;\n margin-left:5px;\n}\n\n.wpstg--modal--backup--import--search-replace--input-group:first-child button {\n display: none;\n}\n\n.wpstg--modal--backup--import--search-replace--input--container {\n flex: 1;\n display: flex;\n flex-direction: column;\n}\n\n.wpstg--modal--backup--import--search-replace--input-group {\n width: 100%;\n border-bottom: 6px solid #f1f1f1;\n margin-bottom: 10px;\n}\n\n.wpstg--modal--backup--import--search-replace--input-group input {\n min-width: 250px;\n width: calc(50% - 4px - 11px - 5px); /* -4px is half of the padding; -11px is half of the button; -5 is the margin left of the button */\n display: inline-block;\n line-height: 10px;\n border: 1px solid #dedede;\n border-radius: 3px;\n color: #666;\n padding: 8px;\n margin-bottom: 12px;\n}\n\n.wpstg--modal--import--upload--process {\n display: none;\n position: absolute;\n /*display: flex;*/\n width: 100%;\n height: 100%;\n top: 0;\n left: 0;\n text-indent: 1em;\n white-space: nowrap;\n overflow: hidden;\n color: #898989;\n mix-blend-mode: difference;\n justify-content: center;\n align-items: center;\n}\n\n.wpstg--modal--import--upload--progress {\n position: absolute;\n background: #dedede;\n color: white;\n width: 0;\n height: 100%;\n border-radius: 1em;\n left: -1px;\n top: 0;\n}\n\n.wpstg--modal--import--upload--progress--title {\n z-index: 9;\n}\n\n.wpstg-fieldset:disabled {\n opacity: 0.8;\n border-top: 1px solid white;\n margin-top: 20px;\n}\n\n.wpstg-fs-14 {\n font-size: 14px;\n}\n\n.wpstg-light-alert {\n font-weight: bold;\n background-color: #e6e6e6;\n padding: 15px;\n border-top: 1px solid white;\n margin-top: 20px;\n}\n\n.wpstg-form-group {\n display: flex;\n flex-wrap: wrap;\n width: 100%;\n margin-bottom: 8px;\n}\n\n.wpstg-form-group>label {\n display: inline-block;\n font-weight: 700;\n min-width: 25%;\n width: 25%;\n}\n\n.wpstg-text-field>input {\n width: 350px;\n display: inline-block;\n}\n\n.wpstg-code-segment {\n display: block;\n}\n\n.wpstg-text-field>.wpstg-code-segment {\n margin-top: 4px;\n margin-left: 25%;\n min-width: 350px;\n}\n\n.wpstg-form-group>.wpstg-checkbox {\n min-width: 100%;\n width: 100%;\n position: relative;\n}\n\n.wpstg-form-group>.wpstg-checkbox>input[type='checkbox'] {\n left: 25%;\n}\n\n.wpstg-rounded {\n border-radius: 3px;\n}\n\n.wpstg-white-border {\n border: 1px solid white !important;\n}\n\n.wpstg-mt-16 {\n margin-top: 16px;\n}\n\n.wpstg-w-100pc {\n width: 100%;\n}\n\n#wpstg-confirm-backup-restore-data {\n margin: 40px;\n text-align: left;\n}\n\n#wpstg-confirm-backup-restore-wrapper {\n margin: 30px;\n}\n\n#wpstg-confirm-backup-restore-wrapper h3 {\n color: #f56363;\n}\n\n#swal2-content h2 {\n color: #a8a8a8;\n}\n\n#wpstg_allow_emails {\n margin-left: 10px;\n}\n\n#wpstg-advanced-settings hr {\n margin: 20px 0;\n}\n\n.wpstg-form-row {\n display: block;\n}\n\n.wpstg-form-row label,\n.wpstg-form-row input {\n display: table-cell;\n padding-left: 5px;\n padding-right: 5px;\n margin-top: 3px;\n margin-bottom: 3px;\n}\n\n.wpstg-form-row input {\n width: 400px;\n}\n\n.wpstg-form-row label {\n font-weight: bold;\n width: 1px;\n white-space: nowrap;\n}\n\n#wpstg-db-connect-output #wpstg-db-status {\n width: 390px;\n}\n\n#wpstg_symlink_upload {\n margin-left: 10px;\n}\n\n.wpstg-fieldset:disabled {\n opacity: 0.8;\n border-top: 1px solid white;\n margin-top: 20px;\n}\n\n.wpstg-fs-14 {\n font-size: 14px;\n}\n\n.wpstg-light-alert {\n font-weight: bold;\n background-color: #e6e6e6;\n padding: 15px;\n border-top: 1px solid white;\n margin-top: 20px;\n}\n\n.wpstg-form-group {\n display: flex;\n flex-wrap: wrap;\n width: 100%;\n margin-bottom: 8px;\n}\n\n.wpstg-form-group>label {\n display: inline-block;\n font-weight: 700;\n min-width: 25%;\n width: 25%;\n}\n\n.wpstg-text-field>input {\n width: 350px;\n display: inline-block;\n}\n\n.wpstg-code-segment {\n display: block;\n}\n\n.wpstg-text-field>.wpstg-code-segment {\n margin-top: 4px;\n margin-left: 25%;\n min-width: 350px;\n}\n\n.wpstg-form-group>.wpstg-checkbox {\n min-width: 100%;\n width: 100%;\n}\n\n.wpstg-form-group>.wpstg-checkbox>input[type='checkbox'] {\n margin-left: 10px;\n}\n\n@media only screen and (max-width: 768px) {\n .wpstg-form-group {\n display: block;\n }\n .wpstg-form-group>label {\n display: block;\n min-width: auto;\n width: auto;\n }\n .wpstg-text-field>input {\n width: 100%;\n display: block;\n }\n .wpstg-text-field>.wpstg-code-segment {\n margin-left: 0;\n min-width: 100%;\n }\n .wpstg-tab-section {\n width: calc(100vw - 60px);\n max-width: calc(100vw - 60px);\n }\n}\n\n.wpstg-rounded {\n border-radius: 3px;\n}\n\n.wpstg-white-border {\n border: 1px solid white !important;\n}\n\n.wpstg-m-0 {\n margin: 0;\n}\n\n.wpstg-mt-16 {\n margin-top: 16px;\n}\n\n.wpstg-mt-10px {\n margin-top: 10px;\n}\n\n.wpstg-my-10px {\n margin-top: 10px;\n margin-bottom: 10px;\n}\n\n.wpstg-w-100 {\n width: 100%;\n}\n\n.wpstg-box-shadow {\n box-shadow: 0 1px 1px 0 rgba(0, 0, 0, .1);\n}\n\n.wpstg-float-left {\n float: left;\n}\n\n.wpstg-fivestar {\n border-left: none;\n background-color: #59a7f7;\n color: white;\n padding: 10px;\n margin: 10px 10px 10px 0;\n}\n\n.wpstg-bold-text {\n font-weight: bold;\n}\n\n.wpstg-rating-link {\n font-weight: normal;\n color: white;\n}\n\n.wpstg-warning.notice {\n border-left: 4px solid #ffba00;\n}\n\n.wpstg-confirmation-label {\n background-color: #5b9dd9;\n color: #fff;\n padding: 2px;\n border-radius: 3px;\n}\n\n.wpstg-my-6px {\n margin-bottom: 6px;\n margin-top: 6px;\n}\n\n.wpstg-mb-10px {\n margin-bottom: 10px;\n}\n\n.wpstg-opacity-80 {\n opacity: 0.8;\n}\n\n.wpstg-clear-both {\n clear: both;\n}\n\n.wpstg-fs-10px {\n font-size: 10px;\n}\n\n.wpstg-font-italic {\n font-style: italic;\n}\n\n.wpstg-mt-20px {\n margin-top: 20px;\n}\n\n.wpstg-welcome-container {\n border: 2px solid white;\n padding: 20px;\n margin-bottom: 20px;\n}\n\n.wpstg-ml-30px {\n margin-left: 30px;\n}\n\n.wpstg-text-center {\n text-align: center;\n}\n\n.wpstg-feedback-link {\n text-decoration: none;\n color: #abc116\n}\n\n.wpstg-feedback-span {\n display: block;\n margin-bottom: 20px;\n color: #abc116;\n}\n\n#wpstg-confirm-backup-restore-data {\n margin: 40px;\n text-align: left;\n}\n\n#wpstg-confirm-backup-restore-wrapper {\n margin: 30px;\n}\n\n#wpstg-confirm-backup-restore-wrapper h3 {\n color: #f56363;\n}\n\n#wpstg-footer {\n clear: both;\n padding-top: 20px;\n}\n\n#swal2-content h2 {\n color: #a8a8a8;\n}\n\n#wpstg-progress-db,\n#wpstg-progress-backup {\n background-color: #3fa5ee;\n}\n\n#wpstg-progress-sr,\n#wpstg-progress-files.wpstg-pro {\n background-color: #3c9ee4;\n}\n\n#wpstg-progress-dirs,\n#wpstg-progress-data {\n background-color: #3a96d7;\n}\n\n#wpstg-progress-files:not(.wpstg-pro),\n#wpstg-progress-finishing {\n background-color: #378cc9;\n}\n\n.wpstg-issue-resubmit-confirmation.swal2-container, \n.wpstg-swal2-container.swal2-container {\n z-index: 10500;\n}\n\n.wpstg-swal2-container.wpstg-swal2-loading .swal2-actions,\n.wpstg-swal2-container.wpstg-swal2-loading .swal2-header {\n display: none;\n}\n\nbody.toplevel_page_wpstg_clone .swal2-container .swal2-content {\n z-index:2;\n}\n\ndiv#exportUploadsWithoutDatabaseWarning {\n font-style: italic;\n font-size: 0.9rem;\n margin: 10px;\n padding: 10px;\n border: 1px solid #e3e3e3;\n border-radius: 5px;\n text-align: center;\n background-color: #fafafa;\n}\n\n.wpstg-advanced-options-dropdown-wrapper {\n display: none; /* ENABLE WHEN WE HAVE ADVANCED OPTIONS FOR EXPORTING */\n margin-top: 20px;\n}\n\n.wpstg--modal--backup--import--search-replace--wrapper {\n text-align: left;\n margin-top: 20px;\n}\n\n.wpstg--modal--backup--import--search-replace--new--wrapper {\n text-align: center;\n}\n\n.wpstg-import-backup-contains li {\n display: inline-block;\n}\n\n.wpstg-import-backup-contains li .dashicons{\n border-radius: 3px;\n color: #979797;\n background-color: #e3e3e3;\n border: 1px solid #c2c2c2;\n width: 17px;\n height: 17px;\n font-size: 17px;\n}\n\n.wpstg-import-backup-contains.wpstg-listing-single-backup li .dashicons{\n padding: 2px;\n color: #ffffff;\n background-color: #2896dd;\n border: 1px solid #0c75b8;\n}\n\n.wpstg-import-backup-contains .wpstg--tooltiptext {\n width: 50px;\n font-size: x-small;\n padding: 5px;\n left: -25px;\n text-align: center;\n}\n\n.wpstg-import-backup-contains-title {\n display: inline-block;\n}\n\nul.wpstg-import-backup-contains {\n display: inline-block;\n}\n\n.wpstg-import-backup-name {\n display: inline-block;\n font-weight: bold;\n}\n\n.wpstg-backup-more-info-toggle {\n font-size: x-small;\n display: inline-block;\n font-style: italic;\n cursor:pointer;\n}\n\n.wpstg-backup-more-info-toggle::selection {\n background:none;\n}\n\nul.wpstg-import-backup-more-info {\n font-size: 14px;\n text-align: left;\n margin-bottom: 30px;\n margin-top: 10px;\n background-color: #f6f6f6;\n border: 1px solid #878787;\n border-radius: 3px;\n padding: 7px;\n cursor: pointer;\n}\n\nul.wpstg-import-backup-more-info:hover {\n background-color: #def2ff;\n border: 1px solid #25a1f0;\n}\n\nul.wpstg-import-backup-more-info li {\n height: 20px;\n}\n\n.wpstg-backup-list ul ul {\n margin-block-start: 1em;\n margin-block-end: 1em;\n}\n\n.wpstg-push-confirmation-message {\n text-align: justify;\n}\n\n.wpstg-settings-row {\n padding-top: 10px;\n padding-bottom: 10px;\n}\n\n.wpstg-settings-title {\n font-weight: 600;\n}\n\n.wpstg-settings-form-group {\n display: flex;\n align-items: center;\n}\n\n.wpstg-settings-form-group > .wpstg-settings-message {\n width: 30%;\n padding: 0;\n margin: 7px 0 0;\n}\n\n/**\n * WP STAGING EXCLUSION RULES TABLE LAYOUT\n */\n\n.wpstg-excluded-filters-container {\n padding: 0;\n\tmargin-top: 10px;\n margin-bottom: 10px;\n\tmax-width: 100%;\n width: 100%;\n}\n\n.wpstg-excluded-filters-container > table {\n width: 100%;\n border-collapse: collapse;\n border-color: transparent;\n}\n\n.wpstg-excluded-filters-container td {\n padding-top: 4px;\n padding-bottom: 4px;\n height: 20px;\n}\n\n.wpstg-excluded-filters-container h4 {\n margin: 0;\n}\n\n/*.wpstg-excluded-filters-container tbody {\n\tbackground: #fff !important;\n}*/\n\n.wpstg-exclude-filters-foot {\n display: flex;\n justify-content: flex-start;\n padding: 0;\n}\n\n.wpstg-excluded-filters-container .wpstg-exclude-filter-name-column {\n width: 100px;\n max-width: 100px !important;\n padding-left: 10px;\n}\n\n.wpstg-excluded-filters-container .wpstg-exclude-filter-action-column {\n width: 50px;\n max-width: 50px;\n\ttext-align: right !important;\n padding-right: 10px;\n}\n\n.wpstg-excluded-filters-container .wpstg-exclude-filter-exclusion-column {\n width: 320px;\n position: relative;\n}\n\n/**\n * WP STAGING EXCLUSION RULE DROPDOWN STYLE\n */\n\n.wpstg-exclude-filter-dropdown > button {\n background: #25A0F1;\n border: 1px solid #25A0F1;\n color: #fff;\n padding: 1px 5px;\n display: inline-block;\n font-weight: 400;\n line-height: 1.5;\n text-align: center;\n border-radius: 0;\n outline: none;\n box-shadow: none;\n cursor: pointer;\n height: 24px;\n}\n\n.wpstg-exclude-filter-dropdown > button:hover {\n background: #135e96;;\n border: 1px solid #135e96;;\n}\n\n.wpstg-exclude-filter-dropdown > .wpstg-dropdown-menu {\n width: 128px;\n}\n\n.wpstg-remove-exclude-rule {\n color: #fff !important;\n background-color: #dc3545;\n border: 1px solid #dc3545;\n width: 20px;\n\theight: 20px;\n\tborder-radius: 10px;\n\tfont-size: 24px;\n\tpadding: 0;\n\tdisplay: inline-flex;\n\tjustify-content: center;\n outline: none;\n box-shadow: none;\n font-weight: 400;\n line-height: 0.7;\n margin-top: 5px;\n cursor: pointer;\n}\n\n.wpstg-remove-exclude-rule:hover {\n background-color: #bb2d3b;\n border-color: #bb2d3b;\n}\n\n/**\n * WP STAGING POPOVER EXCLUSION RULES INFO\n */\n\n .wpstg-popover {\n\tdisplay: inline-block;\n\tposition: relative;\n}\n\n.wpstg-popover button + p {\n\tposition: absolute;\n\ttop: 18px;\n\tright: -150px;\n\tdisplay: none;\n\twidth: 320px;\n\tz-index: 1024;\n\tpadding: 10px !important;\n\tbox-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);\n}\n\n.wpstg-popover button:hover + p {\n\tdisplay: block;\n}\n\n.wpstg-code-block {\n\tmargin-top: 4px;\n\tfont-size: 1.2em;\n\tbackground: #f8f8f8;\n\tborder-radius: 2px;\n}\n\n.wpstg-rule-info {\n background: #f8f8f8 !important;\n}\n\ncode.wpstg-code {\n display: inline-block;\n font-size: 11px;\n\tborder: 1px solid #aaa;\n\tbackground: #fff;\n\tpadding: 2px 4px;\n margin-bottom: 1px;\n color: #ff6666;\n}\n\n.wpstg-exclusion-rule-info {\n color: #fff !important;\n background-color: #ffc107;\n border: 1px solid #ffc107;\n width: 14px;\n\theight: 14px;\n\tborder-radius: 7px;\n\tfont-size: 14px;\n\tpadding: 0;\n\tdisplay: inline-flex;\n\tjustify-content: center;\n align-items: center;\n outline: none;\n box-shadow: none;\n font-weight: 400;\n vertical-align: middle;\n}\n\n.wpstg-exclusion-rule-info:hover {\n background-color: #ffba0c;\n border: 1px solid #ffba0c;\n}\n\n/**\n * WP STAGING INPUTS EXCLUSION RULES\n */\n\n .wpstg-exclude-rule-input {\n font-size: 12px !important;\n padding: 2px 6px;\n box-shadow: none;\n outline: none !important;\n display: inline-block;\n font-weight: 400;\n line-height: 1.5;\n color: #222;\n border-radius: 0 !important;\n background-color: #fff;\n border: 1px solid #bbb;\n min-height: 24px !important;\n margin-top: 4px;\n margin-left: 4px;\n vertical-align: baseline !important;\n transition: all 0.3s cubic-bezier(.25,.8,.25,1);\n width: 135px;\n}\n\n.wpstg-excluded-filters-container tbody > tr:last-child .wpstg-exclude-rule-input {\n\tmargin-bottom: 4px;\n}\n\n.wpstg-exclude-rule-input:hover {\n border: 1px solid #999;\n}\n\n.wpstg-exclude-rule-input:focus {\n border: 1px solid #25A0F1 !important;\n box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24) !important;\n}\n\n.wpstg-file-size-exclude-select,\n.wpstg-path-exclude-select {\n width: 135px;\n}\n\n.wpstg-file-size-exclude-select-small {\n width: 52px;\n}\n\n.wpstg-file-size-exclude-input {\n width: 75px;\n}\n\n.wpstg-staging-option-title {\n margin: 15px 0 0;\n}\n\n.wpstg-swal-push-container.swal2-container {\n z-index: 9995;\n}\n\n#wpstg-scanning-files {\n padding-bottom: 5px;\n}\n\n#wpstg-scanning-files.wpstg-tab-section{\n padding-top:0;\n}\n\n.wpstg-reset-excludes-container {\n margin: 10px 0;\n}\n\n.wpstg-swal2-ajax-loader {\n width: 100%;\n height: 150px;\n overflow: hidden;\n display: flex;\n justify-content: center;\n align-items: center;\n}\n\n@keyframes wpstg-loading-icon-anim {\n\t0% {\n\t\ttransform: rotate(0);\n\t}\n\t100% {\n\t\ttransform: rotate(360deg);\n\t}\n}\n\n.wpstg-swal2-ajax-loader > img {\n width: 64px;\n height: 64px;\n animation: wpstg-loading-icon-anim 1s infinite linear;\n -webkit-animation: wpstg-loading-icon-anim 1s infinite linear;\n}\n\n.wpstg-swal2-container .wpstg-tab-section {\n width: auto !important;\n}\n\n.wpstg-is-dir-loading {\n position: absolute;\n margin-top: -2px;\n margin-left: 8px;\n display: none;\n}\n\n.wpstg-ml-8px {\n margin-left: 8px;\n}\n\n.wpstg-mb-8px {\n margin-bottom: 8px;\n}\n\n.wpstg-button.danger {\n display: inline-block;\n text-decoration: none;\n text-align: center;\n text-transform: inherit;\n background-color: #e74c3c;\n color: white;\n border-radius: 0px;\n border-color: transparent;\n}\n\n.wpstg-button.danger:hover {\n background-color: #c0392b;\n}\n\n.wpstg-swal2-container.wpstg-swal2-loading > .swal2-modal {\n height: 200px;\n}\n\n.wpstg-reset-confirmation.wpstg-swal2-container:not(.wpstg-swal2-loading) > .swal2-modal {\n max-width: 480px;\n}\n\n.wpstg-reset-confirmation.wpstg-swal2-container .swal2-header {\n display: none;\n}\n\n.wpstg-reset-confirmation.wpstg-swal2-container .swal2-content {\n height: auto;\n}\n\n.wpstg-reset-confirmation.wpstg-swal2-container > .swal2-modal > .swal2-content .wpstg-tabs-wrapper {\n overflow-y: auto;\n height: auto !important;\n}\n\n.wpstg-reset-confirmation.wpstg-swal2-container > .swal2-modal > .swal2-content {\n font-size: 13px;\n}\n\n.wpstg-reset-confirmation.wpstg-swal2-container > .swal2-modal > .swal2-content .wpstg-dir {\n margin-bottom: 4px;\n}\n\n.wpstg-reset-confirmation.wpstg-swal2-container > .swal2-modal > .swal2-content .wpstg-subdir {\n margin-top: 4px;\n}\n\n.wpstg-reset-confirmation.wpstg-swal2-container.has-collapsible-open .swal2-modal {\n height: calc(100vh - 70px);\n}\n\n.wpstg-reset-confirmation.wpstg-swal2-container.has-collapsible-open > .swal2-modal > .swal2-content .wpstg-tabs-wrapper {\n height: calc(100vh - 350px) !important;\n}\n"]}
assets/css/dist/wpstg-admin.min.css ADDED
@@ -0,0 +1,2 @@
 
 
1
+ #wpstg-tab-container ul{background:#f1f1f1;float:left;list-style:none;margin:0;padding:0}#wpstg-tab-container ul li:first-child.selected-tab{border-top:none}#wpstg-tab-container ul li a.selected-tab{font-weight:700;text-decoration:none}#wpstg-tab-container .row{padding-bottom:12px;padding-top:10px}.wpstg-tabs-container .nav-tab-wrapper{padding:0}#wpstg-tab-container .row label strong,#wpstg-tab-container .row strong{font-weight:700}.wpstg-tabs a{padding:5px}#wpstg-tab-container>ul>li.wpstg-tabs.active{background-color:#fff}#wpstg_settingsgeneral_header .row:nth-child(3),#wpstg_settingsgeneral_header .row:nth-child(4){display:none}#wpstg-tab-container .wpstg-settings-panel{overflow:auto;padding:0 20px 20px}#wpstg-tab-container .wpstg-form-table th{color:#484848;font-size:14px;font-weight:700;line-height:1.3;padding:20px 10px 20px 0;text-align:left;vertical-align:top;width:30%}#wpstg-tab-container .wpstg-form-table tr{border-bottom:1px solid #e7e7e7}#wpstg-tab-container span.description{color:#484848;display:block;font-size:13px;font-style:normal;font-weight:400;margin-top:7px}#wpstg-tab-container .col-title{color:#484848}@media only screen and (max-width:680px){#wpstg-tab-container ul{float:none}#wpstg-tab-container .wpstg-form-table tr>th{width:100%}#wpstg-tab-container span.description{font-size:14px}#wpstg-tab-container .wpstg-form-table tr>td,#wpstg-tab-container .wpstg-form-table tr>th{padding:10px}}#wpstg-tab-container ul li{margin-bottom:0}#wpstg-tab-container ul li a{border-bottom:1px solid #e7e7e7;border-left-style:solid;border-left-width:0;border-right-style:solid;border-right-width:0;border-top:1px solid #fff;color:#0097df;display:block;font-weight:700;padding:10px 4px 10px 14px;text-decoration:none}#wpstg-tab-container ul li a:hover{background-color:#e5e5e5;color:#777}.wpstg-logo{display:block;float:left;font-size:16px;padding-top:20px;width:220px}.wpstg-version{display:block;padding-top:29px}.wpstg_admin .nav-tab{color:#3c3c3c}#wpstg-tab-container table tbody tr:first-child>th>div{font-size:20px}.wpstg_hidden{display:none}#wpstg-clonepage-wrapper{margin-bottom:20px}@media screen and (min-width:1090px){#wpstg-clonepage-wrapper{float:left;margin-bottom:20px}.wpstg-sidebar{display:none;margin-left:700px;margin-top:138px}}.wpstg-sidebar{border:1px solid #dfdfdf;display:none;height:250px;max-width:250px;padding:10px}#wpstg-steps{margin-top:30px}#wpstg-steps li{color:#444;float:left;line-height:20px;padding-right:10px}.wpstg-step-num{border:1px solid #444;border-radius:3px;display:inline-block;height:20px;margin-right:5px;text-align:center;width:20px}.wpstg-current-step{font-weight:700}.wpstg-current-step .wpstg-step-num{background:#444;color:#eee}.wpstg-box{margin:10px 0;overflow:hidden;padding:10px}.wpstg-box,.wpstg-clone{position:relative;transition:border-color .2s ease-in-out}.wpstg-clone{background-color:#25a1f0;border-radius:.25rem;box-shadow:0 0 1px rgba(0,0,0,.125),0 1px 3px rgba(0,0,0,.2);margin-bottom:3px;padding:16px}.wpstg-clone.active{border-color:#1d94cf}.wpstg-clone-header{align-items:center;display:flex;justify-content:space-between}.wpstg-clone-title{color:#fff;display:inline-block;font-size:15px;font-weight:700;max-width:300px;text-decoration:none}.wpstg-clone-title:hover{color:#f1f1f1}.wpstg-clone-actions{display:flex}.wpstg-clone-actions .wpstg-dropdown-toggler{background:#fff;border-radius:2px;box-shadow:0 0 1px rgba(0,0,0,.125),0 1px 3px rgba(0,0,0,.2);color:#002648;font-size:14px;padding:4px 10px;text-decoration:none}.wpstg-clone-actions .wpstg-dropdown-toggler:hover{background:#002648;color:#fff}.wpstg-dropdown{position:relative}.wpstg-dropdown-symbol{font-size:14px;margin-left:4px}.wpstg-dropdown>.wpstg-dropdown-menu{background:#fff;border-radius:2px;box-shadow:0 0 1px rgba(0,0,0,.125),0 1px 3px rgba(0,0,0,.2);display:none;flex-direction:column;padding:8px;position:absolute;right:0;top:calc(100% + 4px);width:100px;z-index:1000}.wpstg-dropdown>.wpstg-dropdown-menu.wpstg-menu-dropup{bottom:100%;top:auto;transform:translate3d(0,-3px,0)}.wpstg-dropdown>.wpstg-dropdown-menu.shown{display:flex}.wpstg-clone-action,.wpstg-dropdown-action{border-radius:3px;color:#002648;padding:5px 8px;position:relative;text-decoration:none;transition:color .2s ease-in-out}.wpstg-clone-action:hover,.wpstg-dropdown-action:hover{background:rgba(0,0,0,.05)}.wpstg-dropdown-action{background:transparent;border:0 solid #000;box-shadow:none;color:#333;outline:none}.wpstg-remove-clone:hover{color:#ef6d6d}.wpstg-clone-action:last-child{border:none}.wpstg-clone:hover .wpstg-clone-action{display:inline-block}#wpstg-show-error-details:focus,#wpstg-workflow .wpstg-clone-action{box-shadow:none;outline:none}.wpstg-link-btn{background:#45a1c9;color:#fff;display:inline-block;padding:5px 10px;text-decoration:none;transition:all .2s ease-in-out;vertical-align:baseline}.wpstg-link-btn:focus,.wpstg-link-btn:hover{box-shadow:none;color:#fff;outline:none}#wpstg-workflow .wpstg-link-btn:active{vertical-align:baseline}.wpstg-link-btn[disabled]{background:#777!important;pointer-events:none}#wpstg-cancel-cloning,#wpstg-cancel-cloning-update{background:#ff3428;border-color:#e72f24;margin-top:5px}#wpstg-cancel-cloning.success{background:#64dd58;border-color:#54bd4a}#wpstg-error-details,#wpstg-error-wrapper{clear:both;display:none;font-size:13px;padding-top:10px}#wpstg-show-error-details{color:#555;display:inline-block;margin-left:5px;text-decoration:none;transition:color .2s ease-in-out}#wpstg-show-error-details:hover{color:#1d94cf}#wpstg-error-details{border-left:5px solid #ef6d6d;padding:10px;width:500px}#wpstg-try-again{display:none}#wpstg-home-link{float:right}.wpstg-loader{content:url(../../img/loading.gif);display:none;margin-top:5px}.wpstg-loader.wpstg-finished{background-color:#00c89a;border-radius:3px;color:#fff;content:"Finished";display:block;margin-top:0;padding:2px 10px}#wpstg-workflow{clear:both;float:left;max-width:650px;min-height:380px;min-width:500px;padding-bottom:20px;padding-right:20px;padding-top:20px;position:relative}#wpstg-sidebar{display:block;float:left;margin-left:10px;max-width:400px}@media screen and (max-width:1150px){#wpstg-sidebar img{margin-top:30px}}#wpstg-removing-clone.loading:after,#wpstg-workflow.loading:after{background:hsla(0,0%,100%,.7);content:"Loading... may take a while for huge websites";display:block;font-size:20px;height:100%;left:0;padding-top:100px;position:absolute;text-align:center;top:0;width:100%;z-index:99}#wpstg-removing-clone.loading:after{content:"REMOVING"!important}#wpstg-existing-clones,#wpstg-removing-clone{position:relative}#wpstg-removing-clone .wpstg-tab-section{display:block}.wpstg-progress-bar{background-color:#d6d8d7;height:27px;max-width:900px;padding:0}.wpstg-progress{background:#3fa5ee;float:left;overflow:hidden}.wpstg-progress,.wpstg-progress-files{color:#fff;height:100%;line-height:25px;text-align:center;transition:width .6s ease;width:0}.wpstg-progress-files{background:#16b4f0}#wpstg-clone-path.wpstg-error-input,#wpstg-new-clone-id.wpstg-error-input{border:1px solid #ff4235;box-shadow:0 0 2px rgba(255,66,53,.8)}#wpstg-new-clone{background:#25a1f0;border-color:#2188c9}#wpstg-new-clone:hover{background:#259be6;border-color:#2188c9}#wpstg-clone-path{margin-left:10px;width:350px}.wpstg-error-msg{color:#ff4235}#wpstg-clone-id-error{background-color:#f0f8ff;display:block;margin:20px;padding:10px}#wpstg-start-cloning+.wpstg-error-msg{display:block;margin-top:5px}.wpstg-size-info{color:#999;font-weight:400;left:2px;position:relative}.wpstg-db-table .wpstg-size-info{top:2px}.wpstg-db-table:hover{background-color:#f0f8ff}#wpstg-workflow #wpstg-start-cloning{display:inline-block;font-size:14px;margin-left:5px;vertical-align:baseline}.wpstg-tabs-wrapper{margin:10px 0;max-width:640px}#wpstg-path-wrapper{border-bottom:2px dashed #ccc;margin-bottom:10px;padding-bottom:10px}.wpstg-tab-section{border-bottom:1px solid #ddd;border-left:none;border-right:none;display:none;padding:20px;width:100%}.wpstg-tab-section:after{clear:both;content:"";display:block}.wpstg-tab-header{border-bottom:1px solid #ddd;border-left:none;border-right:none;color:#444;display:block;font-size:16px;font-weight:bolder;padding:10px;text-decoration:none}.wpstg-tab-triangle{animation:transform .5s;display:inline-block;margin-right:10px}.wpstg-tab-header:focus{box-shadow:none;color:#444;outline:none}#wpstg-large-files{border:1px dashed #ccc;display:none;font-size:12px;margin-top:20px;padding:10px;position:relative}#wpstg-large-files h3{background:#fff;left:5px;margin:0;padding:0 5px;position:absolute;top:-10px}.wpstg-subdir{display:none;margin-left:20px}.wpstg-subdir.wpstg-push{display:block;margin-left:20px}.wpstg-dir a.disabled{color:#888;cursor:default;text-decoration:none}.wpstg-check-subdirs{display:inline-block;margin-left:10px}.wpstg-notice-alert{background-color:#ffd0d0;border:1px solid #faa;border-radius:6px;display:block;margin-top:10px;max-width:600px;padding:20px}.wpstg-header{border-bottom:1px solid #dfdfdf;clear:both;font-size:19px;font-weight:400;line-height:1.6em}#wpstg-clone-label{font-size:14px;font-weight:700}.wpstg-log-details{background-color:#000;border:1px solid #fff;color:silver;font-family:monospace;font-size:12px;height:300px;line-height:15px;margin-top:15px;max-width:650px;overflow:scroll;padding:3px;white-space:nowrap}#wpstg-finished-result{display:none}#wpstg-remove-cloning{background:#ff3428;border-color:#e72f24;margin-top:5px}#wpstg-success-notice{background-color:#fff;border:1px solid #ccc;margin-top:20px;max-width:900px;padding:10px}.wpstg_beta_notice{margin-bottom:20px}.wpstg-sysinfo{height:700px;width:700px}.wpstg-form-table .col-title label{font-weight:600}.wpstg-form-table td:first-child{width:30%}.wpstg-share-button-container{margin:5px 0}.wpstg-share-button-container p{margin:0 0 10px}.wpstg-share-button{display:inline-block}.wpstg-share-button a{text-decoration:none}.wpstg-share-button .wpstg-share{-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px;color:#fff;display:inline;font-family:sans-serif;font-size:12px;font-weight:700;padding:4px 8px;text-align:center;text-decoration:none}.wpstg-share-button-twitter .wpstg-share{background-color:#00abf0}.wpstg-share-button-facebook .wpstg-share{background-color:#3b5998}.wpstg-share-button-googleplus .wpstg-share{background-color:#f53424}.wpstg-share-button-facebook .share:active,.wpstg-share-button-googleplus .share:active,.wpstg-share-button-twitter .share:active{background-color:#353535}#wpstg-check-space{margin-left:8px}.wpstg-button.green{background-color:#83c11f;color:#fff;display:inline-block;font-size:16px;margin-top:20px;min-width:170px;padding:10px;text-align:center;text-decoration:none}.wpstg-button.green:hover{background-color:#8ed122}.wpstg-button.wpstg-save{background-color:#1687a7;color:#fff}.wpstg-button.wpstg-save:hover{background-color:#276678}.wpstg-button.wpstg-bordered{border:1px solid #fff;border-radius:3px;font-size:14px}#wpstg-welcome li{font-size:18px;line-height:29px;list-style:none!important;padding-left:23px;position:relative}#wpstg-welcome{background-color:#fff;margin-right:20px;margin-top:20px}.wpstg-heading-pro{color:#0080ff;font-weight:700}.wpstg-h2{font-size:30px;line-height:2.5rem;margin-bottom:1.2rem;margin-top:0}#wpstg-welcome li:before{background:url(data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%2377B227%22%20d%3D%22M1671%20566q0%2040%2D28%2068l%2D724%20724%2D136%20136q%2D28%2028%2D68%2028t%2D68%2D28l%2D136%2D136%2D362%2D362q%2D28%2D28%2D28%2D68t28%2D68l136%2D136q28%2D28%2068%2D28t68%2028l294%20295%20656%2D657q28%2D28%2068%2D28t68%2028l136%20136q28%2028%2028%2068z%22%2F%3E%3C%2Fsvg%3E) left .4em no-repeat;background-size:contain;color:#77b227;content:"";height:100%;left:0;position:absolute;top:0;width:1em}.wpstg-h1{font-size:2.5em;letter-spacing:normal;line-height:3.68rem;margin-bottom:1.35rem}.swal2-content h1{color:#444}#wpstg-welcome h2{margin:0 0 15px}#wpstg-welcome .wpstg-footer{clear:both;font-style:italic;margin-top:20px}#wpstg-footer{background-color:#fff;margin-right:10px;margin-top:20px;padding:20px}#wpstg-footer a{text-decoration:none}.wpstg-staging-info{color:#fff;font-size:12px;margin-top:8px}.wpstg-staging-info a{color:#fff}.wpstg-staging-info li{margin-bottom:2px}.wpstg-bold{font-weight:600}#wpstg-processing-status{float:left;font-size:13px;font-weight:400;margin-top:5px}#wpstg-processing-timer{float:right;font-size:13px;font-weight:400;margin-top:5px}#wpstg-report-issue-button{background-color:#fff;border:1px solid #ef5a4b;color:#ef5a4b;margin-left:50px}#wpstg-report-issue-button:hover{background-color:#e74c3c;color:#fff}.wpstg-button{background-color:transparent;border-radius:3px;color:#95a5a6;cursor:pointer;display:inline-block;font-weight:500;outline:0;padding:2px 10px;text-decoration:none;text-transform:uppercase;transition:background-color .1s ease-in}.wpstg-button.wpstg-button-light{animation:background-color .3s;background-color:#f8f8f8;border:1px solid #eee;color:#333}.wpstg-button.wpstg-button-light:hover{background-color:#e0e0e0;border:1px solid #e0e0e0}.wpstg-blue-primary{-webkit-appearance:none;background:#25a1f0;border:1px solid #2188c9;border-radius:3px;box-sizing:border-box;color:#fff;cursor:pointer;display:inline-block;font-size:13px;height:28px;line-height:26px;margin:0;padding:0 10px 1px;text-decoration:none;text-shadow:0 -1px 1px #006799,1px 0 1px #006799,0 1px 1px #006799,-1px 0 1px #006799;white-space:nowrap}.wpstg-blue-primary:hover{background-color:#259be6}.wpstg-report-issue-form{background-color:#fff;border:1px solid #e8e8e8;border-radius:3px;box-shadow:inset 0 1px 0 0 #fff;display:none;margin:67px 0 0 123px;padding:15px 15px 10px;position:absolute;width:300px;z-index:9999}.wpstg-report-show{display:block}.wpstg-field input[type=text],.wpstg-field textarea{font-weight:400;line-height:1.4;margin-bottom:4px;width:100%}.wpstg-report-email,.wpstg-report-hosting-provider{border-radius:3px;font-size:.8rem;font-weight:400;height:2.3rem;line-height:2.3rem;margin-bottom:4px;padding:0 10px;width:100%}.wpstg-report-description{border-radius:3px;font-size:.8rem;padding:6px 10px;resize:none}.wpstg-report-privacy-policy{font-size:12px;margin-bottom:15px}#wpstg-report-cancel{float:right;margin-right:5px}.wpstg-buttons .spinner{float:none;margin:0 0 0 5px}.wpstg-message{background-color:#f5e0de;border-radius:3px;box-sizing:border-box;-moz-box-sizing:border-box;color:rgba(0,0,0,.6);height:auto;margin:10px 0;min-height:18px;padding:6px 10px;position:relative}.wpstg-message.wpstg-error-message{background-color:#f5e0de;color:#b65147;font-size:12px}.wpstg-message.wpstg-success-message{background-color:#d7f8e0;color:#515151}.wpstg-message p{font-size:13px;margin:3px 0}.wpstg-warning{background-color:#ffb804;color:#fff;display:block;margin:10px 10px 10px 0;padding:10px}.wpstg-warning a{color:#fff;font-weight:700;text-decoration:underline}.wpstg-error{background-color:#fe6501;color:#fff;display:block;margin:10px 10px 10px 0;padding:10px}.wpstg-error a{color:#fff;font-weight:700;text-decoration:underline}#wpstg-resume-cloning{display:none}#wpstg-external-db th{text-align:left;width:120px}#wpstg-db-connect{font-weight:400}#wpstg-db-status{border:1px solid transparent;border-radius:4px;display:block;margin-bottom:20px;margin-top:5px;padding:5px;text-align:center;text-decoration:none}.wpstg-text-field>#wpstg-db-status{margin-left:25%;margin-top:8px;min-width:350px}.wpstg-success{background-color:#dff0d8;border-color:#d6e9c6;color:#3c763d}.wpstg-failed{background-color:#f2dede;border-color:#ebccd1;color:#a94442}#wpstg_select_tables_cloning{font-size:13px;height:600px}#wpstg-update-notify{background-color:#fe6501;color:#fff;font-size:14px;line-height:normal;margin-right:10px;padding:10px}#wpstg-update-notify a{color:#fff;font-weight:700}.wpstg-pointer{cursor:pointer}.wpstg--tab--header ul{display:flex}.wpstg--tab--header ul li{margin-right:1em}.wpstg--tab--header ul li:last-child{margin-right:0}.wpstg--tab--header a{border:1px solid;cursor:pointer;display:inline-block;min-width:150px;padding:1em 1.25em;text-align:center}.wpstg--tab--header a.wpstg--tab--active{border-bottom:.5em solid #25a1f0;color:#25a1f0}.wpstg--tab--content{display:none}.wpstg--tab--active{display:block}.wpstg--text--strong,.wpstg--text--strong *{font-weight:700!important}.wpstg--text--danger{color:#a94442}.wpstg--tooltip{border-bottom:1px dotted #000;display:inline-block;margin-left:10px;position:relative}.wpstg--tooltip .wpstg--tooltiptext{background-color:#fff;border:1px solid #e8e8e8;border-radius:3px;-webkit-box-shadow:-1px 1px 5px 0 rgba(0,0,0,.75);-moz-box-shadow:-1px 1px 5px 0 rgba(0,0,0,.75);box-shadow:-1px 1px 5px 0 rgba(0,0,0,.75);color:#505050;padding:20px;position:absolute;text-align:left;visibility:hidden;width:300px;z-index:1}.wpstg--tooltip:hover .wpstg--tooltiptext{visibility:visible}.wpstg--tooltiptext-backups{left:-150%;margin-left:-60px;margin-top:10px;top:100%;width:120px}.wpstg--tooltip .wpstg--tooltiptext-backups:after{border:5px solid transparent;border-bottom-color:#fff;bottom:100%;content:" ";left:50%;margin-left:25px;position:absolute}.wpstg--snaphot-restore-table tr{line-height:12px}.wpstg-beta-notice{background-color:#b0e8b0;border-radius:3px;margin-bottom:20px;padding:7px}#wpstg-backup-name{font-size:1.875em;font-weight:600}#wpstg_select_tables_cloning option:checked{-webkit-appearance:menulist-button;background-image:linear-gradient(0deg,#1e90ff,#1e90ff)}.wpstg--btn--cancel{color:#fff;font-size:16px;height:auto;line-height:normal;margin-bottom:1.5em;padding:.5em}.wpstg--btn--cancel,.wpstg--btn--cancel:hover{background:#ff3428;border-color:#e72f24}.wpstg--process--content>.swal2-html-container{padding:4em 2em!important}.wpstg--modal--error--logs,.wpstg--modal--process--logs{background:#000;display:none;height:300px;margin-top:1em;overflow-x:auto;padding:1em;text-align:justify}.wpstg--modal--error--logs{height:auto;max-height:300px}.wpstg--modal--error--logs>p,.wpstg--modal--process--logs>p{font-size:14px;text-align:left}.wpstg--modal--error--logs p,.wpstg--modal--process--logs p{margin:.3em 0}.wpstg--modal--process--msg--error{color:#8b0000}.wpstg--modal--process--msg--critical{color:red}.wpstg--modal--process--msg--warning{color:#ff8c00}.wpstg--modal--process--msg-found{color:#f56363}body.toplevel_page_wpstg_clone .swal2-modal .swal2-cancel.wpstg--btn--cancel{margin-bottom:0}body.toplevel_page_wpstg_clone .swal2-modal .swal2-confirm.wpstg--btn--confirm{font-size:16px;height:auto;line-height:normal;margin-right:10px;padding:.5em}body.toplevel_page_wpstg_clone .swal2-modal .wpstg-loader{display:inline-block!important}.wpstg--modal--process--generic-problem{border-left:5px solid #ef6d6d;display:none;margin:.5em 0}.wpstg--modal--process--logs--tail{background:none;border:none;color:#a8a8a8;cursor:pointer}.wpstg--modal--backup--import--upload--title{color:#505050}.wpstg--modal--backup--import--configure,.wpstg--modal--backup--import--filesystem,.wpstg--modal--backup--import--upload--container input[type=file],.wpstg--modal--backup--import--upload--status{display:none}#wpstg--backups--import--file-list{font-size:14px;font-weight:700}#wpstg--backups--import--file-list-empty{color:red}.wpstg--modal--backup--import--filesystem label{font-size:14px}.wpstg--modal--backup--import--filesystem button{margin-bottom:20px}.wpstg--modal--backup--import--filesystem,.wpstg--modal--backup--import--upload{color:#505050}.wpstg--modal--backup--import--upload--container{border:.4em dashed #dedede;border-radius:1em;display:flex;flex-direction:column;margin:.5em;padding:1em .5em;position:relative}.wpstg--modal--backup--import--upload--container .wpstg--uploader{display:flex;flex-direction:column}.wpstg--modal--backup--import--upload--container.wpstg--has-dragover{background-color:#9a9a9a;color:#fff}.wpstg--modal--backup--import--upload--container.wpstg--has-dragover span.wpstg--drag,.wpstg--modal--backup--import--upload--container span.wpstg--drop,span.wpstg--backup--import--selected-file,span.wpstg--drag-or-upload{display:none}.wpstg--modal--backup--import--upload--container.wpstg--has-dragover span.wpstg--drop{display:inline-block}.wpstg--modal--backup--import--upload--container input[type=file]{display:none}.wpstg--modal--backup--import--upload--container img{align-self:center;border:none;width:4em}.wpstg--modal--backup--import--upload--container span{margin-top:1em}.wpstg--backup--import--options>button{align-self:center;height:auto;line-height:normal;margin-top:1em;padding:1em;width:185px}.wpstg--backup--import--options{display:flex;justify-content:center;position:relative}.wpstg--backup--import--options ul{display:none}.wpstg--backup--import--options.wpstg--show-options ul{background:#25a1f0;border-color:#2188c9;border-radius:0 0 3px 3px;border-width:1px;box-sizing:border-box;display:block;margin:54px 0 0;padding:0;position:absolute;text-shadow:0 -1px 1px #006799,1px 0 1px #006799,0 1px 1px #006799,-1px 0 1px #006799;width:185px}.wpstg--backup--import--options.wpstg--show-options ul li{border-bottom:.1em solid #25a1f0;margin:0}.wpstg--backup--import--options.wpstg--show-options ul li:hover{background-color:#25a1f0}.wpstg--backup--import--options.wpstg--show-options ul li:last-child{border-bottom:none}.wpstg--backup--import--options ul li button{background:none;border:none;color:#fff;cursor:pointer;height:40px;line-height:40px;margin:0;width:100%}.wpstg--backup--import--options ul li button:hover{background-color:#259be6}.wpstg--modal--backup--import--search-replace--info{display:flex;flex-direction:row;margin:1em 0}.wpstg--modal--backup--import--info p{margin:0;text-align:left}.wpstg--modal--backup--import--search-replace--wrapper button{align-self:center}.wpstg--import--advanced-options--button{border:0;border-radius:3px;cursor:pointer;font-size:18px;text-shadow:0 -1px 1px #006799,1px 0 1px #006799,0 1px 1px #006799,-1px 0 1px #006799}.wpstg--modal--backup--import--search-replace--new{background-color:#25a1f0;color:#fff}.wpstg--modal--backup--import--search-replace--remove{background-color:#25a1f0;color:#fff;height:22px;margin-left:5px;width:22px}.wpstg--modal--backup--import--search-replace--input-group:first-child button{display:none}.wpstg--modal--backup--import--search-replace--input--container{display:flex;flex:1;flex-direction:column}.wpstg--modal--backup--import--search-replace--input-group{border-bottom:6px solid #f1f1f1;margin-bottom:10px;width:100%}.wpstg--modal--backup--import--search-replace--input-group input{border:1px solid #dedede;border-radius:3px;color:#666;display:inline-block;line-height:10px;margin-bottom:12px;min-width:250px;padding:8px;width:calc(50% - 20px)}.wpstg--modal--import--upload--process{align-items:center;color:#898989;display:none;height:100%;justify-content:center;left:0;mix-blend-mode:difference;overflow:hidden;position:absolute;text-indent:1em;top:0;white-space:nowrap;width:100%}.wpstg--modal--import--upload--progress{background:#dedede;border-radius:1em;color:#fff;height:100%;left:-1px;position:absolute;top:0;width:0}.wpstg--modal--import--upload--progress--title{z-index:9}.wpstg-form-group>.wpstg-checkbox{position:relative}.wpstg-form-group>.wpstg-checkbox>input[type=checkbox]{left:25%}.wpstg-w-100pc{width:100%}#wpstg_allow_emails{margin-left:10px}#wpstg-advanced-settings hr{margin:20px 0}.wpstg-form-row{display:block}.wpstg-form-row input,.wpstg-form-row label{display:table-cell;margin-bottom:3px;margin-top:3px;padding-left:5px;padding-right:5px}.wpstg-form-row input{width:400px}.wpstg-form-row label{font-weight:700;white-space:nowrap;width:1px}#wpstg-db-connect-output #wpstg-db-status{width:390px}#wpstg_symlink_upload{margin-left:10px}.wpstg-fieldset:disabled{border-top:1px solid #fff;margin-top:20px;opacity:.8}.wpstg-fs-14{font-size:14px}.wpstg-light-alert{background-color:#e6e6e6;border-top:1px solid #fff;font-weight:700;margin-top:20px;padding:15px}.wpstg-form-group{display:flex;flex-wrap:wrap;margin-bottom:8px;width:100%}.wpstg-form-group>label{display:inline-block;font-weight:700;min-width:25%;width:25%}.wpstg-text-field>input{display:inline-block;width:350px}.wpstg-code-segment{display:block}.wpstg-text-field>.wpstg-code-segment{margin-left:25%;margin-top:4px;min-width:350px}.wpstg-form-group>.wpstg-checkbox{min-width:100%;width:100%}.wpstg-form-group>.wpstg-checkbox>input[type=checkbox]{margin-left:10px}@media only screen and (max-width:768px){.wpstg-form-group{display:block}.wpstg-form-group>label{display:block;min-width:auto;width:auto}.wpstg-text-field>input{display:block;width:100%}.wpstg-text-field>.wpstg-code-segment{margin-left:0;min-width:100%}.wpstg-tab-section{max-width:calc(100vw - 60px);width:calc(100vw - 60px)}}.wpstg-rounded{border-radius:3px}.wpstg-white-border{border:1px solid #fff!important}.wpstg-m-0{margin:0}.wpstg-mt-16{margin-top:16px}.wpstg-mt-10px,.wpstg-my-10px{margin-top:10px}.wpstg-my-10px{margin-bottom:10px}.wpstg-w-100{width:100%}.wpstg-box-shadow{box-shadow:0 1px 1px 0 rgba(0,0,0,.1)}.wpstg-float-left{float:left}.wpstg-fivestar{background-color:#59a7f7;border-left:none;color:#fff;margin:10px 10px 10px 0;padding:10px}.wpstg-bold-text{font-weight:700}.wpstg-rating-link{color:#fff;font-weight:400}.wpstg-warning.notice{border-left:4px solid #ffba00}.wpstg-confirmation-label{background-color:#5b9dd9;border-radius:3px;color:#fff;padding:2px}.wpstg-my-6px{margin-bottom:6px;margin-top:6px}.wpstg-mb-10px{margin-bottom:10px}.wpstg-opacity-80{opacity:.8}.wpstg-clear-both{clear:both}.wpstg-fs-10px{font-size:10px}.wpstg-font-italic{font-style:italic}.wpstg-mt-20px{margin-top:20px}.wpstg-welcome-container{border:2px solid #fff;margin-bottom:20px;padding:20px}.wpstg-ml-30px{margin-left:30px}.wpstg-text-center{text-align:center}.wpstg-feedback-link{color:#abc116;text-decoration:none}.wpstg-feedback-span{color:#abc116;display:block;margin-bottom:20px}#wpstg-confirm-backup-restore-data{margin:40px;text-align:left}#wpstg-confirm-backup-restore-wrapper{margin:30px}#wpstg-confirm-backup-restore-wrapper h3{color:#f56363}#wpstg-footer{clear:both;padding-top:20px}#swal2-content h2{color:#a8a8a8}#wpstg-progress-backup,#wpstg-progress-db{background-color:#3fa5ee}#wpstg-progress-files.wpstg-pro,#wpstg-progress-sr{background-color:#3c9ee4}#wpstg-progress-data,#wpstg-progress-dirs{background-color:#3a96d7}#wpstg-progress-files:not(.wpstg-pro),#wpstg-progress-finishing{background-color:#378cc9}.wpstg-issue-resubmit-confirmation.swal2-container,.wpstg-swal2-container.swal2-container{z-index:10500}.wpstg-swal2-container.wpstg-swal2-loading .swal2-actions,.wpstg-swal2-container.wpstg-swal2-loading .swal2-header{display:none}body.toplevel_page_wpstg_clone .swal2-container .swal2-content{z-index:2}div#exportUploadsWithoutDatabaseWarning{background-color:#fafafa;border:1px solid #e3e3e3;border-radius:5px;font-size:.9rem;font-style:italic;margin:10px;padding:10px;text-align:center}.wpstg-advanced-options-dropdown-wrapper{display:none;margin-top:20px}.wpstg--modal--backup--import--search-replace--wrapper{margin-top:20px;text-align:left}.wpstg--modal--backup--import--search-replace--new--wrapper{text-align:center}.wpstg-import-backup-contains li{display:inline-block}.wpstg-import-backup-contains li .dashicons{background-color:#e3e3e3;border:1px solid #c2c2c2;border-radius:3px;color:#979797;font-size:17px;height:17px;width:17px}.wpstg-import-backup-contains.wpstg-listing-single-backup li .dashicons{background-color:#2896dd;border:1px solid #0c75b8;color:#fff;padding:2px}.wpstg-import-backup-contains .wpstg--tooltiptext{font-size:x-small;left:-25px;padding:5px;text-align:center;width:50px}.wpstg-import-backup-contains-title,ul.wpstg-import-backup-contains{display:inline-block}.wpstg-import-backup-name{display:inline-block;font-weight:700}.wpstg-backup-more-info-toggle{cursor:pointer;display:inline-block;font-size:x-small;font-style:italic}.wpstg-backup-more-info-toggle::selection{background:none}ul.wpstg-import-backup-more-info{background-color:#f6f6f6;border:1px solid #878787;border-radius:3px;cursor:pointer;font-size:14px;margin-bottom:30px;margin-top:10px;padding:7px;text-align:left}ul.wpstg-import-backup-more-info:hover{background-color:#def2ff;border:1px solid #25a1f0}ul.wpstg-import-backup-more-info li{height:20px}.wpstg-backup-list ul ul{margin-block-end:1em;margin-block-start:1em}.wpstg-push-confirmation-message{text-align:justify}.wpstg-settings-row{padding-bottom:10px;padding-top:10px}.wpstg-settings-title{font-weight:600}.wpstg-settings-form-group{align-items:center;display:flex}.wpstg-settings-form-group>.wpstg-settings-message{margin:7px 0 0;padding:0;width:30%}.wpstg-excluded-filters-container{margin-bottom:10px;margin-top:10px;max-width:100%;padding:0;width:100%}.wpstg-excluded-filters-container>table{border-collapse:collapse;border-color:transparent;width:100%}.wpstg-excluded-filters-container td{height:20px;padding-bottom:4px;padding-top:4px}.wpstg-excluded-filters-container h4{margin:0}.wpstg-exclude-filters-foot{display:flex;justify-content:flex-start;padding:0}.wpstg-excluded-filters-container .wpstg-exclude-filter-name-column{max-width:100px!important;padding-left:10px;width:100px}.wpstg-excluded-filters-container .wpstg-exclude-filter-action-column{max-width:50px;padding-right:10px;text-align:right!important;width:50px}.wpstg-excluded-filters-container .wpstg-exclude-filter-exclusion-column{position:relative;width:320px}.wpstg-exclude-filter-dropdown>button{background:#25a0f1;border:1px solid #25a0f1;border-radius:0;box-shadow:none;color:#fff;cursor:pointer;display:inline-block;font-weight:400;height:24px;line-height:1.5;outline:none;padding:1px 5px;text-align:center}.wpstg-exclude-filter-dropdown>button:hover{background:#135e96;border:1px solid #135e96}.wpstg-exclude-filter-dropdown>.wpstg-dropdown-menu{width:128px}.wpstg-remove-exclude-rule{background-color:#dc3545;border:1px solid #dc3545;border-radius:10px;box-shadow:none;color:#fff!important;cursor:pointer;display:inline-flex;font-size:24px;font-weight:400;height:20px;justify-content:center;line-height:.7;margin-top:5px;outline:none;padding:0;width:20px}.wpstg-remove-exclude-rule:hover{background-color:#bb2d3b;border-color:#bb2d3b}.wpstg-popover{display:inline-block;position:relative}.wpstg-popover button+p{box-shadow:0 1px 3px rgba(0,0,0,.12),0 1px 2px rgba(0,0,0,.24);display:none;padding:10px!important;position:absolute;right:-150px;top:18px;width:320px;z-index:1024}.wpstg-popover button:hover+p{display:block}.wpstg-code-block{background:#f8f8f8;border-radius:2px;font-size:1.2em;margin-top:4px}.wpstg-rule-info{background:#f8f8f8!important}code.wpstg-code{background:#fff;border:1px solid #aaa;color:#f66;display:inline-block;font-size:11px;margin-bottom:1px;padding:2px 4px}.wpstg-exclusion-rule-info{align-items:center;background-color:#ffc107;border:1px solid #ffc107;border-radius:7px;box-shadow:none;color:#fff!important;display:inline-flex;font-size:14px;font-weight:400;height:14px;justify-content:center;outline:none;padding:0;vertical-align:middle;width:14px}.wpstg-exclusion-rule-info:hover{background-color:#ffba0c;border:1px solid #ffba0c}.wpstg-exclude-rule-input{background-color:#fff;border:1px solid #bbb;border-radius:0!important;box-shadow:none;color:#222;display:inline-block;font-size:12px!important;font-weight:400;line-height:1.5;margin-left:4px;margin-top:4px;min-height:24px!important;outline:none!important;padding:2px 6px;transition:all .3s cubic-bezier(.25,.8,.25,1);vertical-align:baseline!important;width:135px}.wpstg-excluded-filters-container tbody>tr:last-child .wpstg-exclude-rule-input{margin-bottom:4px}.wpstg-exclude-rule-input:hover{border:1px solid #999}.wpstg-exclude-rule-input:focus{border:1px solid #25a0f1!important;box-shadow:0 1px 3px rgba(0,0,0,.12),0 1px 2px rgba(0,0,0,.24)!important}.wpstg-file-size-exclude-select,.wpstg-path-exclude-select{width:135px}.wpstg-file-size-exclude-select-small{width:52px}.wpstg-file-size-exclude-input{width:75px}.wpstg-staging-option-title{margin:15px 0 0}.wpstg-swal-push-container.swal2-container{z-index:9995}#wpstg-scanning-files{padding-bottom:5px}#wpstg-scanning-files.wpstg-tab-section{padding-top:0}.wpstg-reset-excludes-container{margin:10px 0}.wpstg-swal2-ajax-loader{align-items:center;display:flex;height:150px;justify-content:center;overflow:hidden;width:100%}@keyframes wpstg-loading-icon-anim{0%{transform:rotate(0)}to{transform:rotate(1turn)}}.wpstg-swal2-ajax-loader>img{animation:wpstg-loading-icon-anim 1s linear infinite;-webkit-animation:wpstg-loading-icon-anim 1s linear infinite;height:64px;width:64px}.wpstg-swal2-container .wpstg-tab-section{width:auto!important}.wpstg-is-dir-loading{display:none;margin-left:8px;margin-top:-2px;position:absolute}.wpstg-ml-8px{margin-left:8px}.wpstg-mb-8px{margin-bottom:8px}.wpstg-button.danger{background-color:#e74c3c;border-color:transparent;border-radius:0;color:#fff;display:inline-block;text-align:center;text-decoration:none;text-transform:inherit}.wpstg-button.danger:hover{background-color:#c0392b}.wpstg-swal2-container.wpstg-swal2-loading>.swal2-modal{height:200px}.wpstg-reset-confirmation.wpstg-swal2-container:not(.wpstg-swal2-loading)>.swal2-modal{max-width:480px}.wpstg-reset-confirmation.wpstg-swal2-container .swal2-header{display:none}.wpstg-reset-confirmation.wpstg-swal2-container .swal2-content{height:auto}.wpstg-reset-confirmation.wpstg-swal2-container>.swal2-modal>.swal2-content .wpstg-tabs-wrapper{height:auto!important;overflow-y:auto}.wpstg-reset-confirmation.wpstg-swal2-container>.swal2-modal>.swal2-content{font-size:13px}.wpstg-reset-confirmation.wpstg-swal2-container>.swal2-modal>.swal2-content .wpstg-dir{margin-bottom:4px}.wpstg-reset-confirmation.wpstg-swal2-container>.swal2-modal>.swal2-content .wpstg-subdir{margin-top:4px}.wpstg-reset-confirmation.wpstg-swal2-container.has-collapsible-open .swal2-modal{height:calc(100vh - 70px)}.wpstg-reset-confirmation.wpstg-swal2-container.has-collapsible-open>.swal2-modal>.swal2-content .wpstg-tabs-wrapper{height:calc(100vh - 350px)!important}
2
+ /*# sourceMappingURL=wpstg-admin.min.css.map */
assets/css/dist/wpstg-admin.min.css.map ADDED
@@ -0,0 +1 @@
 
1
+ {"version":3,"sources":["wpstg-admin.css"],"names":[],"mappings":"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","file":"wpstg-admin.min.css","sourcesContent":["/**\n * WPSTG Admin CSS\n *\n * @package WPSTG\n * @subpackage Admin CSS\n * @copyright Copyright (c) 2021, René Hermenau\n * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License\n*/\n\n\n/* CSS for Tabs */\n\n#wpstg-tab-container ul {\n /*height: 200px;*/\n list-style: none;\n margin: 0;\n padding: 0;\n background: #f1f1f1;\n float: left;\n /*list-style-type: square;*/\n}\n\n#wpstg-tab-container ul li:first-child.selected-tab {\n border-top: none;\n}\n\n#wpstg-tab-container ul li a.selected-tab {\n font-weight: bold;\n text-decoration: none;\n}\n\n#wpstg-tab-container .row {\n padding-top: 10px;\n padding-bottom: 12px;\n}\n\n.wpstg-tabs-container .nav-tab-wrapper {\n padding: 0;\n}\n\n#wpstg-tab-container .row label strong,\n#wpstg-tab-container .row strong {\n font-weight: bold;\n}\n\n.wpstg-tabs a {\n padding: 5px;\n}\n\n#wpstg-tab-container>ul>li.wpstg-tabs.active {\n background-color: white;\n}\n\n#wpstg_settingsgeneral_header .row:nth-child(3),\n#wpstg_settingsgeneral_header .row:nth-child(4) {\n display: none;\n}\n\n#wpstg-tab-container .wpstg-settings-panel {\n padding: 0 20px 20px 20px;\n overflow: auto;\n}\n\n#wpstg-tab-container .wpstg-form-table th {\n vertical-align: top;\n text-align: left;\n padding: 20px 10px 20px 0;\n line-height: 1.3;\n font-weight: bold;\n font-size: 14px;\n color: #484848;\n width: 30%;\n}\n\n#wpstg-tab-container .wpstg-form-table tr {\n border-bottom: 1px solid #E7E7E7;\n}\n\n#wpstg-tab-container span.description {\n display: block;\n font-weight: 400;\n font-style: normal;\n font-size: 13px;\n margin-top: 7px;\n color: #484848;\n}\n\n#wpstg-tab-container .col-title {\n color: #484848;\n}\n\n@media only screen and (max-width: 680px) {\n #wpstg-tab-container ul {\n float: none;\n }\n #wpstg-tab-container .wpstg-form-table tr>th {\n width: 100%;\n }\n #wpstg-tab-container span.description {\n font-size: 14px;\n }\n #wpstg-tab-container .wpstg-form-table tr>th,\n #wpstg-tab-container .wpstg-form-table tr>td {\n padding: 10px;\n }\n}\n\n#wpstg-tab-container ul li {\n margin-bottom: 0;\n}\n\n#wpstg-tab-container ul li a {\n display: block;\n padding: 10px 4px 10px 14px;\n border-width: 1px 0;\n border-style: solid;\n border-top-color: white;\n border-bottom-color: #e7e7e7;\n text-decoration: none;\n color: #0097DF;\n font-weight: bold;\n}\n\n#wpstg-tab-container ul li a:hover {\n background-color: #e5e5e5;\n color: #777777;\n}\n\n.wpstg-logo {\n display: block;\n font-size: 16px;\n padding-top: 20px;\n width: 220px;\n float: left;\n}\n\n.wpstg-version {\n display: block;\n padding-top: 29px\n}\n\n.wpstg_admin .nav-tab {\n color: #3C3C3C;\n}\n\n#wpstg-tab-container table tbody tr:nth-child(1)>th>div {\n font-size: 20px;\n}\n\n.wpstg_hidden {\n display: none;\n}\n\n\n/* Cloning workflow */\n\n#wpstg-clonepage-wrapper {\n margin-bottom: 20px;\n}\n\n@media screen and (min-width: 1090px) {\n #wpstg-clonepage-wrapper {\n float: left;\n margin-bottom: 20px;\n }\n .wpstg-sidebar {\n display: none;\n margin-left: 700px;\n margin-top: 138px;\n }\n}\n\n.wpstg-sidebar {\n display: none;\n padding: 10px;\n border: 1px solid #DFDFDF;\n max-width: 250px;\n height: 250px;\n}\n\n#wpstg-steps {\n margin-top: 30px;\n}\n\n#wpstg-steps li {\n color: #444;\n line-height: 20px;\n padding-right: 10px;\n float: left;\n}\n\n.wpstg-step-num {\n border: 1px solid #444;\n border-radius: 3px;\n display: inline-block;\n width: 20px;\n height: 20px;\n text-align: center;\n margin-right: 5px;\n}\n\n.wpstg-current-step {\n font-weight: bold;\n}\n\n.wpstg-current-step .wpstg-step-num {\n background: #444;\n color: #eee;\n}\n\n.wpstg-box {\n margin: 10px 0;\n padding: 10px;\n position: relative;\n overflow: hidden;\n transition: border-color .2s ease-in-out;\n}\n\n.wpstg-clone {\n margin-bottom: 3px;\n padding: 16px;\n position: relative;\n transition: border-color .2s ease-in-out;\n background-color: #25a1f0;\n border-radius: .25rem;\n box-shadow: 0 0 1px rgba(0,0,0,.125), 0 1px 3px rgba(0,0,0,.2);\n}\n\n.wpstg-clone.active {\n border-color: #1d94cf;\n}\n\n.wpstg-clone-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n\n.wpstg-clone-title {\n display: inline-block;\n font-size: 15px;\n max-width: 300px;\n text-decoration: none;\n font-weight: bold;\n color: white;\n}\n\n.wpstg-clone-title:hover {\n color: #f1f1f1;\n}\n\n.wpstg-clone-actions {\n display: flex;\n /*align-items: right;*/\n}\n\n.wpstg-dropdown {\n position: relative;\n}\n\n.wpstg-clone-actions .wpstg-dropdown-toggler {\n text-decoration: none;\n background: #fff;\n padding: 4px 10px;\n border-radius: 2px;\n font-size: 14px;\n box-shadow: 0 0 1px rgba(0,0,0,.125), 0 1px 3px rgba(0,0,0,.2);\n color: #002648;\n}\n\n.wpstg-clone-actions .wpstg-dropdown-toggler:hover {\n background: #002648;\n color: white;\n}\n\n.wpstg-dropdown {\n position: relative;\n}\n\n.wpstg-dropdown-symbol {\n font-size: 14px;\n margin-left: 4px;\n}\n\n.wpstg-dropdown>.wpstg-dropdown-menu {\n background: #fff;\n display: none;\n flex-direction: column;\n position: absolute;\n right: 0;\n top: calc(100% + 4px);\n padding: 8px;\n border-radius: 2px;\n width: 100px;\n box-shadow: 0 0 1px rgba(0,0,0,.125), 0 1px 3px rgba(0,0,0,.2);\n z-index: 1000;\n}\n\n.wpstg-dropdown>.wpstg-dropdown-menu.wpstg-menu-dropup {\n top: auto;\n bottom: 100%;\n transform: translate3d(0px, -3px, 0px);\n}\n\n.wpstg-dropdown>.wpstg-dropdown-menu.shown {\n display: flex;\n}\n\n.wpstg-clone-action,\n.wpstg-dropdown-action {\n color: #002648;\n padding: 5px 8px;\n border-radius: 3px;\n text-decoration: none;\n position: relative;\n transition: color .2s ease-in-out;\n}\n\n.wpstg-clone-action:hover,\n.wpstg-dropdown-action:hover {\n background: rgba(0,0,0,0.05);\n}\n\n.wpstg-dropdown-action {\n color: #333;\n background: transparent;\n border: 0 solid black;\n outline: none;\n box-shadow: none;\n}\n\n.wpstg-remove-clone:hover {\n color: #ef6d6d;\n}\n\n.wpstg-clone-action:last-child {\n border: none;\n}\n\n.wpstg-clone:hover .wpstg-clone-action {\n display: inline-block;\n}\n\n#wpstg-show-error-details:focus,\n#wpstg-workflow .wpstg-clone-action {\n outline: none;\n box-shadow: none;\n}\n\n.wpstg-link-btn {\n background: #45a1c9;\n color: #fff;\n display: inline-block;\n padding: 5px 10px;\n text-decoration: none;\n vertical-align: baseline;\n transition: all .2s ease-in-out;\n}\n\n.wpstg-link-btn:hover,\n.wpstg-link-btn:focus {\n color: #fff;\n outline: none;\n box-shadow: none;\n}\n\n#wpstg-workflow .wpstg-link-btn:active {\n vertical-align: baseline;\n}\n\n.wpstg-link-btn[disabled] {\n background: #777 !important;\n pointer-events: none;\n}\n\n#wpstg-cancel-cloning,\n#wpstg-cancel-cloning-update {\n background: #ff3428;\n border-color: #e72f24;\n margin-top: 5px;\n}\n\n#wpstg-cancel-cloning.success,\n#wpstg-cancel-cloning.success {\n background: #64dd58;\n border-color: #54bd4a;\n}\n\n#wpstg-error-wrapper,\n#wpstg-error-details {\n display: none;\n padding-top: 10px;\n font-size: 13px;\n clear: both;\n}\n\n#wpstg-show-error-details {\n display: inline-block;\n margin-left: 5px;\n color: #555;\n text-decoration: none;\n transition: color .2s ease-in-out;\n}\n\n#wpstg-show-error-details:hover {\n color: #1d94cf;\n}\n\n#wpstg-error-details {\n border-left: 5px solid #ef6d6d;\n padding: 10px;\n width: 500px;\n}\n\n#wpstg-try-again {\n display: none;\n}\n\n#wpstg-home-link {\n float: right;\n}\n\n.wpstg-loader {\n content: url('../../img/loading.gif');\n margin-top: 5px;\n display: none;\n}\n\n.wpstg-loader.wpstg-finished {\n display: block;\n content: \"Finished\";\n background-color: #00c89a;\n color: white;\n padding: 2px 10px;\n margin-top: 0;\n border-radius: 3px;\n}\n\n#wpstg-workflow {\n max-width: 650px;\n position: relative;\n clear: both;\n padding-top: 20px;\n float: left;\n min-width: 500px;\n /*border-right: 1px solid #DFDFDF;*/\n min-height: 380px;\n padding-right: 20px;\n padding-bottom: 20px;\n}\n\n#wpstg-sidebar {\n float: left;\n max-width: 400px;\n display: block;\n margin-left: 10px;\n}\n\n@media screen and (max-width: 1150px) {\n #wpstg-sidebar img {\n margin-top: 30px;\n }\n}\n\n#wpstg-workflow.loading::after,\n#wpstg-removing-clone.loading::after {\n background: rgba(255, 255, 255, .7);\n content: 'Loading... may take a while for huge websites';\n display: block;\n width: 100%;\n height: 100%;\n font-size: 20px;\n padding-top: 100px;\n text-align: center;\n position: absolute;\n top: 0;\n left: 0;\n z-index: 99;\n}\n\n#wpstg-removing-clone.loading::after {\n content: 'REMOVING' !important;\n}\n\n#wpstg-existing-clones,\n#wpstg-removing-clone {\n position: relative;\n}\n\n#wpstg-removing-clone .wpstg-tab-section {\n display: block;\n}\n\n.wpstg-progress-bar {\n max-width: 900px;\n height: 27px;\n padding: 0;\n background-color: #d6d8d7;\n}\n\n.wpstg-progress {\n float: left;\n background: #3fa5ee;\n width: 0;\n height: 100%;\n transition: width .6s ease;\n color: white;\n line-height: 25px;\n text-align: center;\n overflow: hidden;\n}\n\n.wpstg-progress-files {\n background: #16b4f0;\n width: 0;\n height: 100%;\n transition: width .6s ease;\n color: white;\n line-height: 25px;\n text-align: center;\n}\n\n#wpstg-new-clone-id.wpstg-error-input,\n#wpstg-clone-path.wpstg-error-input {\n border: 1px solid #ff4235;\n box-shadow: 0 0 2px rgba(255, 66, 53, .8);\n}\n\n#wpstg-new-clone {\n background: #25a1f0;\n border-color: #2188c9;\n}\n\n#wpstg-new-clone:hover {\n background: #259be6;\n border-color: #2188c9;\n}\n\n#wpstg-clone-path {\n margin-left: 10px;\n width: 350px;\n}\n\n.wpstg-error-msg {\n color: #ff4235;\n}\n\n#wpstg-clone-id-error {\n display: block;\n background-color: #f0f8ff;\n padding: 10px;\n margin: 20px;\n}\n\n#wpstg-start-cloning+.wpstg-error-msg {\n display: block;\n margin-top: 5px;\n}\n\n.wpstg-size-info {\n color: #999;\n font-weight: normal;\n position: relative;\n left: 2px;\n}\n\n.wpstg-db-table .wpstg-size-info {\n top: 2px;\n}\n\n.wpstg-db-table:hover {\n background-color: #f0f8ff;\n}\n\n#wpstg-workflow #wpstg-start-cloning {\n display: inline-block;\n margin-left: 5px;\n font-size: 14px;\n vertical-align: baseline;\n}\n\n\n/* Tabs */\n\n.wpstg-tabs-wrapper {\n max-width: 640px;\n margin: 10px 0;\n}\n\n#wpstg-path-wrapper {\n border-bottom: 2px dashed #ccc;\n padding-bottom: 10px;\n margin-bottom: 10px;\n}\n\n\n/* unused class should be removed or commented\n.wpstg-tabs-wrapper {\n border: 1px solid #ddd;\n border-right: none;\n border-left: none;\n}\n*/\n\n.wpstg-tab-section {\n border-bottom: 1px solid #ddd;\n border-right: none;\n border-left: none;\n display: none;\n width: 100%;\n padding: 20px;\n}\n\n.wpstg-tab-section::after {\n display: block;\n content: '';\n clear: both;\n}\n\n.wpstg-tab-header {\n border-bottom: 1px solid #ddd;\n border-right: none;\n border-left: none;\n color: #444;\n font-size: 16px;\n font-weight: bolder;\n display: block;\n padding: 10px;\n ;\n text-decoration: none;\n}\n\n.wpstg-tab-triangle {\n display: inline-block;\n margin-right: 10px;\n animation: transform 0.5s;\n}\n\n.wpstg-tab-header:focus {\n color: #444;\n outline: none;\n box-shadow: none;\n}\n\n#wpstg-large-files {\n display: none;\n border: 1px dashed #ccc;\n /*float: right;*/\n padding: 10px 10px 10px;\n margin-top: 20px;\n position: relative;\n font-size: 12px;\n}\n\n#wpstg-large-files h3 {\n background: #fff;\n margin: 0;\n padding: 0 5px;\n position: absolute;\n top: -10px;\n left: 5px;\n}\n\n\n/* tmp */\n\n.wpstg-subdir {\n display: none;\n margin-left: 20px;\n}\n\n.wpstg-subdir.wpstg-push {\n display: block;\n margin-left: 20px;\n}\n\n.wpstg-dir a.disabled {\n color: #888;\n cursor: default;\n text-decoration: none;\n}\n\n.wpstg-check-subdirs {\n display: inline-block;\n margin-left: 10px;\n}\n\n.wpstg-notice-alert {\n display: block;\n background-color: #FFD0D0;\n padding: 20px;\n border-radius: 6px;\n border: 1px solid #FFAAAA;\n max-width: 600px;\n margin-top: 10px;\n}\n\n.wpstg-header {\n font-weight: 400;\n line-height: 1.6em;\n font-size: 19px;\n border-bottom: 1px solid #DFDFDF;\n clear: both;\n}\n\n#wpstg-clone-label {\n font-size: 14px;\n font-weight: bold;\n}\n\n.wpstg-log-details {\n height: 300px;\n overflow: scroll;\n max-width: 650px;\n font-family: monospace;\n font-size: 12px;\n line-height: 15px;\n border: 1px solid #FFF;\n background-color: black;\n color: #c0c0c0;\n padding: 3px;\n white-space: nowrap;\n margin-top: 15px;\n}\n\n#wpstg-finished-result {\n display: none;\n}\n\n#wpstg-remove-cloning {\n background: #ff3428;\n border-color: #e72f24;\n margin-top: 5px;\n}\n\n#wpstg-success-notice {\n padding: 10px;\n background-color: white;\n max-width: 900px;\n border: 1px solid #ccc;\n margin-top: 20px;\n}\n\n.wpstg_beta_notice {\n margin-bottom: 20px;\n}\n\n.wpstg-sysinfo {\n width: 700px;\n height: 700px;\n}\n\n.wpstg-form-table .col-title label {\n font-weight: 600;\n}\n\n.wpstg-form-table td:first-child {\n width: 30%;\n}\n\n.wpstg-share-button-container {\n margin: 5px 0;\n}\n\n.wpstg-share-button-container p {\n margin: 0 0 10px 0;\n}\n\n.wpstg-share-button {\n display: inline-block;\n}\n\n.wpstg-share-button a {\n text-decoration: none;\n}\n\n.wpstg-share-button .wpstg-share {\n font-family: sans-serif;\n font-weight: bold;\n text-decoration: none;\n text-align: center;\n}\n\n.wpstg-share-button .wpstg-share {\n -webkit-border-radius: 2px;\n -moz-border-radius: 2px;\n border-radius: 2px;\n color: #FFF;\n display: inline;\n font-size: 12px;\n padding: 4px 8px;\n}\n\n.wpstg-share-button-twitter .wpstg-share {\n background-color: #00ABF0;\n}\n\n.wpstg-share-button-facebook .wpstg-share {\n background-color: #3b5998;\n}\n\n.wpstg-share-button-googleplus .wpstg-share {\n background-color: #F53424;\n}\n\n.wpstg-share-button-twitter .share:active,\n.wpstg-share-button-facebook .share:active,\n.wpstg-share-button-googleplus .share:active {\n background-color: #353535;\n}\n\n#wpstg-check-space {\n margin-left: 8px;\n}\n\n\n/* welcome screen */\n\n.wpstg-button.green {\n display: inline-block;\n padding: 10px;\n min-width: 170px;\n font-size: 16px;\n text-decoration: none;\n text-align: center;\n margin-top: 20px;\n background-color: #83c11f;\n color: white;\n}\n\n.wpstg-button.green:hover {\n background-color: #8ed122;\n}\n\n.wpstg-button.wpstg-save {\n background-color: #1687A7;\n color: white;\n}\n\n.wpstg-button.wpstg-save:hover {\n background-color: #276678;\n}\n\n.wpstg-button.wpstg-bordered {\n border-radius:3px;\n font-size: 14px;\n border: 1px solid white;\n}\n\n#wpstg-welcome li {\n font-size: 18px;\n line-height: 29px;\n position: relative;\n padding-left: 23px;\n list-style: none !important;\n}\n\n#wpstg-welcome {\n margin-top: 20px;\n margin-right: 20px;\n background-color: white;\n}\n\n.wpstg-heading-pro {\n color: #0080ff;\n font-weight: bold;\n}\n\n.wpstg-h2 {\n margin-top: 0;\n margin-bottom: 1.2rem;\n font-size: 30px;\n line-height: 2.5rem;\n}\n\n#wpstg-welcome li:before {\n width: 1em;\n height: 100%;\n background: url(data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%2377B227%22%20d%3D%22M1671%20566q0%2040%2D28%2068l%2D724%20724%2D136%20136q%2D28%2028%2D68%2028t%2D68%2D28l%2D136%2D136%2D362%2D362q%2D28%2D28%2D28%2D68t28%2D68l136%2D136q28%2D28%2068%2D28t68%2028l294%20295%20656%2D657q28%2D28%2068%2D28t68%2028l136%20136q28%2028%2028%2068z%22%2F%3E%3C%2Fsvg%3E) left .4em no-repeat;\n background-size: contain;\n content: \"\";\n position: absolute;\n top: 0;\n left: 0;\n color: #77b227;\n}\n\n.wpstg-h1 {\n margin-bottom: 1.35rem;\n font-size: 2.5em;\n line-height: 3.68rem;\n letter-spacing: normal;\n}\n\n.swal2-content h1 {\n color:#444;\n}\n\n#wpstg-welcome h2 {\n margin: 0 0 15px;\n}\n\n#wpstg-welcome .wpstg-footer {\n clear: both;\n margin-top: 20px;\n font-style: italic;\n}\n\n#wpstg-footer {\n clear: both;\n background-color: white;\n padding: 20px;\n margin-top: 20px;\n margin-right: 10px;\n}\n\n#wpstg-footer a {\n text-decoration: none;\n}\n\n.wpstg-staging-info {\n margin-top: 8px;\n color: white;\n font-size: 12px;\n}\n\n.wpstg-staging-info a {\n color: white;\n}\n\n.wpstg-staging-info li {\n margin-bottom: 2px;\n}\n\n.wpstg-bold {\n font-weight: 600;\n}\n\n#wpstg-processing-status {\n margin-top: 5px;\n font-size: 13px;\n font-weight: 400;\n float: left;\n}\n\n#wpstg-processing-timer {\n margin-top: 5px;\n font-size: 13px;\n font-weight: 400;\n float: right;\n}\n\n#wpstg-report-issue-button {\n margin-left: 50px;\n border: 1px solid #ef5a4b;\n color: #ef5a4b;\n background-color: white;\n}\n\n#wpstg-report-issue-button:hover {\n background-color: #e74c3c;\n color: #fff;\n}\n\n.wpstg-button {\n display: inline-block;\n background-color: transparent;\n color: #95a5a6;\n border-radius: 3px;\n cursor: pointer;\n padding: 2px 10px 2px 10px;\n text-transform: uppercase;\n font-weight: 500;\n outline: 0;\n transition: background-color .1s ease-in;\n text-decoration: none;\n}\n\n.wpstg-button.wpstg-button-light {\n background-color: #f8f8f8;\n border: 1px solid #eee;\n color: #333;\n animation: background-color 0.3s;\n}\n\n.wpstg-button.wpstg-button-light:hover {\n background-color: #e0e0e0;\n border: 1px solid #e0e0e0;\n}\n\n.wpstg-blue-primary {\n display: inline-block;\n text-decoration: none;\n font-size: 13px;\n line-height: 26px;\n height: 28px;\n margin: 0;\n padding: 0 10px 1px;\n cursor: pointer;\n border-width: 1px;\n border-style: solid;\n -webkit-appearance: none;\n border-radius: 3px;\n white-space: nowrap;\n box-sizing: border-box;\n background: #25a1f0;\n border-color: #2188c9;\n color: #fff;\n text-shadow: 0 -1px 1px #006799, 1px 0 1px #006799, 0 1px 1px #006799, -1px 0 1px #006799;\n}\n\n.wpstg-blue-primary:hover {\n background-color: #259be6;\n}\n\n.wpstg-report-issue-form {\n position: absolute;\n z-index: 9999;\n width: 300px;\n background-color: #fff;\n padding: 15px 15px 10px;\n border: 1px solid #e8e8e8;\n border-radius: 3px;\n box-shadow: 0 1px 0 0 #fff inset;\n display: none;\n margin: 67px 0 0 123px;\n}\n\n.wpstg-report-show {\n display: block;\n}\n\n.wpstg-field input[type=text],\n.wpstg-field textarea {\n width: 100%;\n font-weight: 400;\n line-height: 1.4;\n margin-bottom: 4px;\n}\n\n.wpstg-report-email,\n.wpstg-report-hosting-provider {\n width: 100%;\n font-weight: 400;\n font-size: .8rem;\n height: 2.3rem;\n line-height: 2.3rem;\n border-radius: 3px;\n margin-bottom: 4px;\n padding: 0 10px;\n}\n\n.wpstg-report-description {\n border-radius: 3px;\n font-size: .8rem;\n padding: 6px 10px;\n resize: none;\n}\n\n.wpstg-report-privacy-policy {\n font-size: 12px;\n margin-bottom: 15px;\n}\n\n#wpstg-report-cancel {\n float: right;\n margin-right: 5px;\n}\n\n.wpstg-buttons .spinner {\n float: none;\n margin: 0 0 0 5px;\n}\n\n.wpstg-message {\n box-sizing: border-box;\n -moz-box-sizing: border-box;\n background-color: #f5e0de;\n border-radius: 3px;\n color: rgba(0, 0, 0, .6);\n height: auto;\n margin: 10px 0;\n min-height: 18px;\n padding: 6px 10px;\n position: relative;\n}\n\n.wpstg-message.wpstg-error-message {\n background-color: #f5e0de;\n color: #b65147;\n font-size: 12px;\n}\n\n.wpstg-message.wpstg-success-message {\n background-color: #d7f8e0;\n color: #515151;\n}\n\n.wpstg-message p {\n margin: 3px 0;\n font-size: 13px;\n}\n\n.wpstg-warning {\n display: block;\n padding: 10px;\n background-color: #ffb804;\n color: #ffffff;\n margin: 10px 10px 10px 0;\n}\n\n.wpstg-warning a {\n color: #ffffff;\n font-weight: bold;\n text-decoration: underline;\n}\n\n.wpstg-error {\n display: block;\n padding: 10px;\n background-color: #fe6501;\n color: #ffffff;\n margin: 10px 10px 10px 0;\n}\n\n.wpstg-error a {\n color: #ffffff;\n font-weight: bold;\n text-decoration: underline;\n}\n\n#wpstg-resume-cloning {\n display: none;\n}\n\n#wpstg-external-db th {\n text-align: left;\n width: 120px;\n}\n\n#wpstg-db-connect {\n font-weight: normal;\n}\n\n#wpstg-db-status {\n display: block;\n margin-top: 5px;\n padding: 5px;\n margin-bottom: 20px;\n border: 1px solid transparent;\n border-radius: 4px;\n text-decoration: none;\n text-align: center;\n}\n\n.wpstg-text-field>#wpstg-db-status {\n margin-top: 8px;\n margin-left: 25%;\n min-width: 350px;\n}\n\n.wpstg-success {\n color: #3c763d;\n background-color: #dff0d8;\n border-color: #d6e9c6;\n}\n\n.wpstg-failed {\n color: #a94442;\n background-color: #f2dede;\n border-color: #ebccd1;\n}\n\n#wpstg_select_tables_cloning {\n height: 600px;\n font-size: 13px;\n}\n\n#wpstg-update-notify {\n background-color: #fe6501;\n font-size: 14px;\n color: #ffffff;\n line-height: normal;\n padding: 10px;\n margin-right: 10px;\n}\n\n#wpstg-update-notify a {\n color: #ffffff;\n font-weight: bold;\n}\n\n.wpstg-pointer {\n cursor: pointer;\n}\n\n.wpstg--tab--header ul {\n display: flex;\n}\n\n.wpstg--tab--header ul li {\n margin-right: 1em;\n}\n\n.wpstg--tab--header ul li:last-child {\n margin-right: 0;\n}\n\n.wpstg--tab--header a {\n min-width: 150px;\n text-align: center;\n cursor: pointer;\n display: inline-block;\n padding: 1em 1.25em;\n border: solid 1px;\n}\n\n.wpstg--tab--header a.wpstg--tab--active {\n border-bottom: .5em solid #25A1F0;\n color: #25A1F0;\n}\n\n.wpstg--tab--content {\n display: none;\n}\n\n.wpstg--tab--active {\n display: block;\n}\n\n.wpstg--text--strong,\n.wpstg--text--strong * {\n font-weight: bold !important;\n}\n\n.wpstg--text--danger {\n color: #a94442;\n}\n\n.wpstg--tooltip {\n position: relative;\n display: inline-block;\n border-bottom: 1px dotted black;\n margin-left: 10px;\n}\n\n.wpstg--tooltip .wpstg--tooltiptext {\n visibility: hidden;\n width: 300px;\n background-color: #ffffff;\n color: #505050;\n text-align: left;\n padding: 20px;\n border: 1px solid #e8e8e8;\n border-radius: 3px;\n position: absolute;\n z-index: 1;\n -webkit-box-shadow: -1px 1px 5px 0 rgba(0, 0, 0, 0.75);\n -moz-box-shadow: -1px 1px 5px 0 rgba(0, 0, 0, 0.75);\n box-shadow: -1px 1px 5px 0 rgba(0, 0, 0, 0.75);\n}\n\n.wpstg--tooltip:hover .wpstg--tooltiptext {\n visibility: visible;\n}\n\n.wpstg--tooltiptext-backups {\n width: 120px;\n top: 100%;\n left: -150%;\n margin-left: -60px;\n /* Use half of the width (120/2 = 60), to center the tooltip */\n margin-top: 10px;\n}\n\n\n/**\nTooltip top arrow\n */\n\n.wpstg--tooltip .wpstg--tooltiptext-backups::after {\n content: \" \";\n position: absolute;\n bottom: 100%;\n /* At the top of the tooltip */\n left: 50%;\n margin-left: 25px;\n border-width: 5px;\n border-style: solid;\n border-color: transparent transparent white transparent;\n}\n\n.wpstg--snaphot-restore-table tr {\n line-height: 12px;\n}\n\n.wpstg-float-left {\n float: left;\n}\n\n.wpstg-beta-notice {\n background-color: #b0e8b0;\n border-radius: 3px;\n padding: 7px;\n margin-bottom: 20px;\n}\n\n#wpstg-backup-name {\n font-size: 1.875em;\n font-weight: 600;\n}\n\n#wpstg_select_tables_cloning option:checked {\n /* Cannot use background color here because Chrome and Firefox ignore it even if set to !important */\n -webkit-appearance: menulist-button;\n background-image: linear-gradient(0deg, #1e90ff 0%, #1e90ff 100%);\n}\n\n.wpstg--btn--cancel {\n background: #ff3428;\n border-color: #e72f24;\n color: #fff;\n height: auto;\n line-height: normal;\n font-size: 16px;\n padding: .5em;\n margin-bottom: 1.5em;\n}\n\n.wpstg--btn--cancel:hover {\n background: #ff3428;\n border-color: #e72f24;\n}\n\n.wpstg--process--content>.swal2-html-container {\n padding: 4em 2em !important;\n}\n\n.wpstg--modal--process--logs,\n.wpstg--modal--error--logs {\n background: black;\n height: 300px;\n margin-top: 1em;\n display: none;\n padding: 1em;\n overflow-x: auto;\n text-align: justify;\n}\n\n.wpstg--modal--error--logs {\n height: auto;\n max-height: 300px;\n}\n\n.wpstg--modal--process--logs>p,\n.wpstg--modal--error--logs>p {\n text-align: left;\n font-size: 14px;\n}\n\n.wpstg--modal--process--logs p,\n.wpstg--modal--error--logs p {\n margin: .3em 0;\n}\n\n.wpstg--modal--process--msg--error {\n color: darkred;\n}\n\n.wpstg--modal--process--msg--critical {\n color: red;\n}\n\n.wpstg--modal--process--msg--warning {\n color: darkorange;\n}\n\n.wpstg--modal--process--msg-found {\n color: #f56363;\n}\n\nbody.toplevel_page_wpstg_clone .swal2-modal .swal2-cancel.wpstg--btn--cancel {\n margin-bottom: 0;\n}\n\nbody.toplevel_page_wpstg_clone .swal2-modal .swal2-confirm.wpstg--btn--confirm {\n font-size: 16px;\n padding: .5em;\n line-height: normal;\n height: auto;\n margin-right: 10px;\n}\n\nbody.toplevel_page_wpstg_clone .swal2-modal .wpstg-loader {\n display: inline-block !important;\n}\n\n.wpstg--modal--process--generic-problem {\n display: none;\n border-left: 5px solid #ef6d6d;\n margin: .5em 0;\n}\n\n.wpstg--modal--process--logs--tail {\n color: #a8a8a8;\n background: none;\n border: none;\n cursor: pointer;\n}\n\n.wpstg--modal--backup--import--upload--title {\n color: #505050;\n}\n\n.wpstg--modal--backup--import--filesystem,\n.wpstg--modal--backup--import--configure,\n.wpstg--modal--backup--import--upload--status,\n.wpstg--modal--backup--import--upload--container input[type=\"file\"] {\n display: none;\n}\n\n#wpstg--backups--import--file-list {\n font-size: 14px;\n font-weight: bold;\n}\n\n#wpstg--backups--import--file-list-empty {\n color: red;\n}\n\n.wpstg--modal--backup--import--filesystem label {\n font-size: 14px;\n}\n\n.wpstg--modal--backup--import--filesystem button {\n margin-bottom: 20px;\n}\n\n.wpstg--modal--backup--import--upload,\n.wpstg--modal--backup--import--filesystem {\n color: #505050;\n}\n\n.wpstg--modal--backup--import--upload--container {\n position: relative;\n border-radius: 1em;\n margin: .5em;\n padding: 1em .5em;\n border: .4em dashed #dedede;\n display: flex;\n flex-direction: column;\n}\n\n.wpstg--modal--backup--import--upload--container .wpstg--uploader {\n display: flex;\n flex-direction: column;\n}\n\n.wpstg--modal--backup--import--upload--container.wpstg--has-dragover {\n background-color: #9a9a9a;\n color: white;\n}\n\n.wpstg--modal--backup--import--upload--container span.wpstg--drop,\n.wpstg--modal--backup--import--upload--container.wpstg--has-dragover span.wpstg--drag,\nspan.wpstg--backup--import--selected-file,\nspan.wpstg--drag-or-upload {\n display: none;\n}\n\n.wpstg--modal--backup--import--upload--container.wpstg--has-dragover span.wpstg--drop {\n display: inline-block;\n}\n\n.wpstg--modal--backup--import--upload--container input[type='file'] {\n display: none;\n}\n\n.wpstg--modal--backup--import--upload--container img {\n width: 4em;\n align-self: center;\n border: none;\n}\n\n.wpstg--modal--backup--import--upload--container span {\n margin-top: 1em;\n}\n\n.wpstg--backup--import--options>button {\n margin-top: 1em;\n padding: 1em;\n align-self: center;\n width: 185px;\n height: auto;\n line-height: normal;\n}\n\n\n/*.wpstg--backup--import--options.wpstg--show-options > button {\n background: white;\n border-radius: 3px 3px 0 0;\n border: .25em solid #25a1f0;\n text-shadow: none;\n color: #2e3436;\n}*/\n\n.wpstg--backup--import--options {\n position: relative;\n display: flex;\n justify-content: center;\n}\n\n.wpstg--backup--import--options ul {\n display: none;\n}\n\n.wpstg--backup--import--options.wpstg--show-options ul {\n padding: 0;\n margin: 54px 0 0 0;\n display: block;\n position: absolute;\n width: 185px;\n background: #25a1f0;\n box-sizing: border-box;\n border-radius: 0 0 3px 3px;\n border-width: 1px;\n border-color: #2188c9;\n text-shadow: 0 -1px 1px #006799, 1px 0 1px #006799, 0 1px 1px #006799, -1px 0 1px #006799;\n}\n\n.wpstg--backup--import--options.wpstg--show-options ul li {\n border-bottom: .1em solid #25a1f0;\n margin: 0;\n}\n\n.wpstg--backup--import--options.wpstg--show-options ul li:hover {\n background-color: #25a1f0;\n}\n\n.wpstg--backup--import--options.wpstg--show-options ul li:last-child {\n border-bottom: none;\n}\n\n.wpstg--backup--import--options ul li button {\n cursor: pointer;\n background: none;\n border: none;\n margin: 0;\n width: 100%;\n color: white;\n height: 40px;\n line-height: 40px;\n}\n\n.wpstg--backup--import--options ul li button:hover {\n background-color: #259be6;\n}\n\n.wpstg--modal--backup--import--search-replace--info {\n margin: 1em 0;\n display: flex;\n flex-direction: row;\n}\n\n.wpstg--modal--backup--import--info p {\n text-align: left;\n margin: 0;\n}\n\n\n/* unused class should be removed or commented\n.wpstg--modal--backup--import--search-replace--wrapper {\n display: flex;\n flex-direction: row;\n padding: 0 5em;\n}\n*/\n\n.wpstg--modal--backup--import--search-replace--wrapper button {\n align-self: center;\n}\n\n.wpstg--import--advanced-options--button {\n border: 0;\n border-radius: 3px;\n font-size: 18px;\n text-shadow: 0 -1px 1px #006799, 1px 0 1px #006799, 0 1px 1px #006799, -1px 0 1px #006799;\n cursor: pointer;\n}\n\n.wpstg--modal--backup--import--search-replace--new {\n color: white;\n background-color: #25a1f0;\n}\n\n.wpstg--modal--backup--import--search-replace--remove {\n color: white;\n background-color: #25a1f0;\n width: 22px;\n height: 22px;\n margin-left:5px;\n}\n\n.wpstg--modal--backup--import--search-replace--input-group:first-child button {\n display: none;\n}\n\n.wpstg--modal--backup--import--search-replace--input--container {\n flex: 1;\n display: flex;\n flex-direction: column;\n}\n\n.wpstg--modal--backup--import--search-replace--input-group {\n width: 100%;\n border-bottom: 6px solid #f1f1f1;\n margin-bottom: 10px;\n}\n\n.wpstg--modal--backup--import--search-replace--input-group input {\n min-width: 250px;\n width: calc(50% - 4px - 11px - 5px); /* -4px is half of the padding; -11px is half of the button; -5 is the margin left of the button */\n display: inline-block;\n line-height: 10px;\n border: 1px solid #dedede;\n border-radius: 3px;\n color: #666;\n padding: 8px;\n margin-bottom: 12px;\n}\n\n.wpstg--modal--import--upload--process {\n display: none;\n position: absolute;\n /*display: flex;*/\n width: 100%;\n height: 100%;\n top: 0;\n left: 0;\n text-indent: 1em;\n white-space: nowrap;\n overflow: hidden;\n color: #898989;\n mix-blend-mode: difference;\n justify-content: center;\n align-items: center;\n}\n\n.wpstg--modal--import--upload--progress {\n position: absolute;\n background: #dedede;\n color: white;\n width: 0;\n height: 100%;\n border-radius: 1em;\n left: -1px;\n top: 0;\n}\n\n.wpstg--modal--import--upload--progress--title {\n z-index: 9;\n}\n\n.wpstg-fieldset:disabled {\n opacity: 0.8;\n border-top: 1px solid white;\n margin-top: 20px;\n}\n\n.wpstg-fs-14 {\n font-size: 14px;\n}\n\n.wpstg-light-alert {\n font-weight: bold;\n background-color: #e6e6e6;\n padding: 15px;\n border-top: 1px solid white;\n margin-top: 20px;\n}\n\n.wpstg-form-group {\n display: flex;\n flex-wrap: wrap;\n width: 100%;\n margin-bottom: 8px;\n}\n\n.wpstg-form-group>label {\n display: inline-block;\n font-weight: 700;\n min-width: 25%;\n width: 25%;\n}\n\n.wpstg-text-field>input {\n width: 350px;\n display: inline-block;\n}\n\n.wpstg-code-segment {\n display: block;\n}\n\n.wpstg-text-field>.wpstg-code-segment {\n margin-top: 4px;\n margin-left: 25%;\n min-width: 350px;\n}\n\n.wpstg-form-group>.wpstg-checkbox {\n min-width: 100%;\n width: 100%;\n position: relative;\n}\n\n.wpstg-form-group>.wpstg-checkbox>input[type='checkbox'] {\n left: 25%;\n}\n\n.wpstg-rounded {\n border-radius: 3px;\n}\n\n.wpstg-white-border {\n border: 1px solid white !important;\n}\n\n.wpstg-mt-16 {\n margin-top: 16px;\n}\n\n.wpstg-w-100pc {\n width: 100%;\n}\n\n#wpstg-confirm-backup-restore-data {\n margin: 40px;\n text-align: left;\n}\n\n#wpstg-confirm-backup-restore-wrapper {\n margin: 30px;\n}\n\n#wpstg-confirm-backup-restore-wrapper h3 {\n color: #f56363;\n}\n\n#swal2-content h2 {\n color: #a8a8a8;\n}\n\n#wpstg_allow_emails {\n margin-left: 10px;\n}\n\n#wpstg-advanced-settings hr {\n margin: 20px 0;\n}\n\n.wpstg-form-row {\n display: block;\n}\n\n.wpstg-form-row label,\n.wpstg-form-row input {\n display: table-cell;\n padding-left: 5px;\n padding-right: 5px;\n margin-top: 3px;\n margin-bottom: 3px;\n}\n\n.wpstg-form-row input {\n width: 400px;\n}\n\n.wpstg-form-row label {\n font-weight: bold;\n width: 1px;\n white-space: nowrap;\n}\n\n#wpstg-db-connect-output #wpstg-db-status {\n width: 390px;\n}\n\n#wpstg_symlink_upload {\n margin-left: 10px;\n}\n\n.wpstg-fieldset:disabled {\n opacity: 0.8;\n border-top: 1px solid white;\n margin-top: 20px;\n}\n\n.wpstg-fs-14 {\n font-size: 14px;\n}\n\n.wpstg-light-alert {\n font-weight: bold;\n background-color: #e6e6e6;\n padding: 15px;\n border-top: 1px solid white;\n margin-top: 20px;\n}\n\n.wpstg-form-group {\n display: flex;\n flex-wrap: wrap;\n width: 100%;\n margin-bottom: 8px;\n}\n\n.wpstg-form-group>label {\n display: inline-block;\n font-weight: 700;\n min-width: 25%;\n width: 25%;\n}\n\n.wpstg-text-field>input {\n width: 350px;\n display: inline-block;\n}\n\n.wpstg-code-segment {\n display: block;\n}\n\n.wpstg-text-field>.wpstg-code-segment {\n margin-top: 4px;\n margin-left: 25%;\n min-width: 350px;\n}\n\n.wpstg-form-group>.wpstg-checkbox {\n min-width: 100%;\n width: 100%;\n}\n\n.wpstg-form-group>.wpstg-checkbox>input[type='checkbox'] {\n margin-left: 10px;\n}\n\n@media only screen and (max-width: 768px) {\n .wpstg-form-group {\n display: block;\n }\n .wpstg-form-group>label {\n display: block;\n min-width: auto;\n width: auto;\n }\n .wpstg-text-field>input {\n width: 100%;\n display: block;\n }\n .wpstg-text-field>.wpstg-code-segment {\n margin-left: 0;\n min-width: 100%;\n }\n .wpstg-tab-section {\n width: calc(100vw - 60px);\n max-width: calc(100vw - 60px);\n }\n}\n\n.wpstg-rounded {\n border-radius: 3px;\n}\n\n.wpstg-white-border {\n border: 1px solid white !important;\n}\n\n.wpstg-m-0 {\n margin: 0;\n}\n\n.wpstg-mt-16 {\n margin-top: 16px;\n}\n\n.wpstg-mt-10px {\n margin-top: 10px;\n}\n\n.wpstg-my-10px {\n margin-top: 10px;\n margin-bottom: 10px;\n}\n\n.wpstg-w-100 {\n width: 100%;\n}\n\n.wpstg-box-shadow {\n box-shadow: 0 1px 1px 0 rgba(0, 0, 0, .1);\n}\n\n.wpstg-float-left {\n float: left;\n}\n\n.wpstg-fivestar {\n border-left: none;\n background-color: #59a7f7;\n color: white;\n padding: 10px;\n margin: 10px 10px 10px 0;\n}\n\n.wpstg-bold-text {\n font-weight: bold;\n}\n\n.wpstg-rating-link {\n font-weight: normal;\n color: white;\n}\n\n.wpstg-warning.notice {\n border-left: 4px solid #ffba00;\n}\n\n.wpstg-confirmation-label {\n background-color: #5b9dd9;\n color: #fff;\n padding: 2px;\n border-radius: 3px;\n}\n\n.wpstg-my-6px {\n margin-bottom: 6px;\n margin-top: 6px;\n}\n\n.wpstg-mb-10px {\n margin-bottom: 10px;\n}\n\n.wpstg-opacity-80 {\n opacity: 0.8;\n}\n\n.wpstg-clear-both {\n clear: both;\n}\n\n.wpstg-fs-10px {\n font-size: 10px;\n}\n\n.wpstg-font-italic {\n font-style: italic;\n}\n\n.wpstg-mt-20px {\n margin-top: 20px;\n}\n\n.wpstg-welcome-container {\n border: 2px solid white;\n padding: 20px;\n margin-bottom: 20px;\n}\n\n.wpstg-ml-30px {\n margin-left: 30px;\n}\n\n.wpstg-text-center {\n text-align: center;\n}\n\n.wpstg-feedback-link {\n text-decoration: none;\n color: #abc116\n}\n\n.wpstg-feedback-span {\n display: block;\n margin-bottom: 20px;\n color: #abc116;\n}\n\n#wpstg-confirm-backup-restore-data {\n margin: 40px;\n text-align: left;\n}\n\n#wpstg-confirm-backup-restore-wrapper {\n margin: 30px;\n}\n\n#wpstg-confirm-backup-restore-wrapper h3 {\n color: #f56363;\n}\n\n#wpstg-footer {\n clear: both;\n padding-top: 20px;\n}\n\n#swal2-content h2 {\n color: #a8a8a8;\n}\n\n#wpstg-progress-db,\n#wpstg-progress-backup {\n background-color: #3fa5ee;\n}\n\n#wpstg-progress-sr,\n#wpstg-progress-files.wpstg-pro {\n background-color: #3c9ee4;\n}\n\n#wpstg-progress-dirs,\n#wpstg-progress-data {\n background-color: #3a96d7;\n}\n\n#wpstg-progress-files:not(.wpstg-pro),\n#wpstg-progress-finishing {\n background-color: #378cc9;\n}\n\n.wpstg-issue-resubmit-confirmation.swal2-container, \n.wpstg-swal2-container.swal2-container {\n z-index: 10500;\n}\n\n.wpstg-swal2-container.wpstg-swal2-loading .swal2-actions,\n.wpstg-swal2-container.wpstg-swal2-loading .swal2-header {\n display: none;\n}\n\nbody.toplevel_page_wpstg_clone .swal2-container .swal2-content {\n z-index:2;\n}\n\ndiv#exportUploadsWithoutDatabaseWarning {\n font-style: italic;\n font-size: 0.9rem;\n margin: 10px;\n padding: 10px;\n border: 1px solid #e3e3e3;\n border-radius: 5px;\n text-align: center;\n background-color: #fafafa;\n}\n\n.wpstg-advanced-options-dropdown-wrapper {\n display: none; /* ENABLE WHEN WE HAVE ADVANCED OPTIONS FOR EXPORTING */\n margin-top: 20px;\n}\n\n.wpstg--modal--backup--import--search-replace--wrapper {\n text-align: left;\n margin-top: 20px;\n}\n\n.wpstg--modal--backup--import--search-replace--new--wrapper {\n text-align: center;\n}\n\n.wpstg-import-backup-contains li {\n display: inline-block;\n}\n\n.wpstg-import-backup-contains li .dashicons{\n border-radius: 3px;\n color: #979797;\n background-color: #e3e3e3;\n border: 1px solid #c2c2c2;\n width: 17px;\n height: 17px;\n font-size: 17px;\n}\n\n.wpstg-import-backup-contains.wpstg-listing-single-backup li .dashicons{\n padding: 2px;\n color: #ffffff;\n background-color: #2896dd;\n border: 1px solid #0c75b8;\n}\n\n.wpstg-import-backup-contains .wpstg--tooltiptext {\n width: 50px;\n font-size: x-small;\n padding: 5px;\n left: -25px;\n text-align: center;\n}\n\n.wpstg-import-backup-contains-title {\n display: inline-block;\n}\n\nul.wpstg-import-backup-contains {\n display: inline-block;\n}\n\n.wpstg-import-backup-name {\n display: inline-block;\n font-weight: bold;\n}\n\n.wpstg-backup-more-info-toggle {\n font-size: x-small;\n display: inline-block;\n font-style: italic;\n cursor:pointer;\n}\n\n.wpstg-backup-more-info-toggle::selection {\n background:none;\n}\n\nul.wpstg-import-backup-more-info {\n font-size: 14px;\n text-align: left;\n margin-bottom: 30px;\n margin-top: 10px;\n background-color: #f6f6f6;\n border: 1px solid #878787;\n border-radius: 3px;\n padding: 7px;\n cursor: pointer;\n}\n\nul.wpstg-import-backup-more-info:hover {\n background-color: #def2ff;\n border: 1px solid #25a1f0;\n}\n\nul.wpstg-import-backup-more-info li {\n height: 20px;\n}\n\n.wpstg-backup-list ul ul {\n margin-block-start: 1em;\n margin-block-end: 1em;\n}\n\n.wpstg-push-confirmation-message {\n text-align: justify;\n}\n\n.wpstg-settings-row {\n padding-top: 10px;\n padding-bottom: 10px;\n}\n\n.wpstg-settings-title {\n font-weight: 600;\n}\n\n.wpstg-settings-form-group {\n display: flex;\n align-items: center;\n}\n\n.wpstg-settings-form-group > .wpstg-settings-message {\n width: 30%;\n padding: 0;\n margin: 7px 0 0;\n}\n\n/**\n * WP STAGING EXCLUSION RULES TABLE LAYOUT\n */\n\n.wpstg-excluded-filters-container {\n padding: 0;\n\tmargin-top: 10px;\n margin-bottom: 10px;\n\tmax-width: 100%;\n width: 100%;\n}\n\n.wpstg-excluded-filters-container > table {\n width: 100%;\n border-collapse: collapse;\n border-color: transparent;\n}\n\n.wpstg-excluded-filters-container td {\n padding-top: 4px;\n padding-bottom: 4px;\n height: 20px;\n}\n\n.wpstg-excluded-filters-container h4 {\n margin: 0;\n}\n\n/*.wpstg-excluded-filters-container tbody {\n\tbackground: #fff !important;\n}*/\n\n.wpstg-exclude-filters-foot {\n display: flex;\n justify-content: flex-start;\n padding: 0;\n}\n\n.wpstg-excluded-filters-container .wpstg-exclude-filter-name-column {\n width: 100px;\n max-width: 100px !important;\n padding-left: 10px;\n}\n\n.wpstg-excluded-filters-container .wpstg-exclude-filter-action-column {\n width: 50px;\n max-width: 50px;\n\ttext-align: right !important;\n padding-right: 10px;\n}\n\n.wpstg-excluded-filters-container .wpstg-exclude-filter-exclusion-column {\n width: 320px;\n position: relative;\n}\n\n/**\n * WP STAGING EXCLUSION RULE DROPDOWN STYLE\n */\n\n.wpstg-exclude-filter-dropdown > button {\n background: #25A0F1;\n border: 1px solid #25A0F1;\n color: #fff;\n padding: 1px 5px;\n display: inline-block;\n font-weight: 400;\n line-height: 1.5;\n text-align: center;\n border-radius: 0;\n outline: none;\n box-shadow: none;\n cursor: pointer;\n height: 24px;\n}\n\n.wpstg-exclude-filter-dropdown > button:hover {\n background: #135e96;;\n border: 1px solid #135e96;;\n}\n\n.wpstg-exclude-filter-dropdown > .wpstg-dropdown-menu {\n width: 128px;\n}\n\n.wpstg-remove-exclude-rule {\n color: #fff !important;\n background-color: #dc3545;\n border: 1px solid #dc3545;\n width: 20px;\n\theight: 20px;\n\tborder-radius: 10px;\n\tfont-size: 24px;\n\tpadding: 0;\n\tdisplay: inline-flex;\n\tjustify-content: center;\n outline: none;\n box-shadow: none;\n font-weight: 400;\n line-height: 0.7;\n margin-top: 5px;\n cursor: pointer;\n}\n\n.wpstg-remove-exclude-rule:hover {\n background-color: #bb2d3b;\n border-color: #bb2d3b;\n}\n\n/**\n * WP STAGING POPOVER EXCLUSION RULES INFO\n */\n\n .wpstg-popover {\n\tdisplay: inline-block;\n\tposition: relative;\n}\n\n.wpstg-popover button + p {\n\tposition: absolute;\n\ttop: 18px;\n\tright: -150px;\n\tdisplay: none;\n\twidth: 320px;\n\tz-index: 1024;\n\tpadding: 10px !important;\n\tbox-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);\n}\n\n.wpstg-popover button:hover + p {\n\tdisplay: block;\n}\n\n.wpstg-code-block {\n\tmargin-top: 4px;\n\tfont-size: 1.2em;\n\tbackground: #f8f8f8;\n\tborder-radius: 2px;\n}\n\n.wpstg-rule-info {\n background: #f8f8f8 !important;\n}\n\ncode.wpstg-code {\n display: inline-block;\n font-size: 11px;\n\tborder: 1px solid #aaa;\n\tbackground: #fff;\n\tpadding: 2px 4px;\n margin-bottom: 1px;\n color: #ff6666;\n}\n\n.wpstg-exclusion-rule-info {\n color: #fff !important;\n background-color: #ffc107;\n border: 1px solid #ffc107;\n width: 14px;\n\theight: 14px;\n\tborder-radius: 7px;\n\tfont-size: 14px;\n\tpadding: 0;\n\tdisplay: inline-flex;\n\tjustify-content: center;\n align-items: center;\n outline: none;\n box-shadow: none;\n font-weight: 400;\n vertical-align: middle;\n}\n\n.wpstg-exclusion-rule-info:hover {\n background-color: #ffba0c;\n border: 1px solid #ffba0c;\n}\n\n/**\n * WP STAGING INPUTS EXCLUSION RULES\n */\n\n .wpstg-exclude-rule-input {\n font-size: 12px !important;\n padding: 2px 6px;\n box-shadow: none;\n outline: none !important;\n display: inline-block;\n font-weight: 400;\n line-height: 1.5;\n color: #222;\n border-radius: 0 !important;\n background-color: #fff;\n border: 1px solid #bbb;\n min-height: 24px !important;\n margin-top: 4px;\n margin-left: 4px;\n vertical-align: baseline !important;\n transition: all 0.3s cubic-bezier(.25,.8,.25,1);\n width: 135px;\n}\n\n.wpstg-excluded-filters-container tbody > tr:last-child .wpstg-exclude-rule-input {\n\tmargin-bottom: 4px;\n}\n\n.wpstg-exclude-rule-input:hover {\n border: 1px solid #999;\n}\n\n.wpstg-exclude-rule-input:focus {\n border: 1px solid #25A0F1 !important;\n box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24) !important;\n}\n\n.wpstg-file-size-exclude-select,\n.wpstg-path-exclude-select {\n width: 135px;\n}\n\n.wpstg-file-size-exclude-select-small {\n width: 52px;\n}\n\n.wpstg-file-size-exclude-input {\n width: 75px;\n}\n\n.wpstg-staging-option-title {\n margin: 15px 0 0;\n}\n\n.wpstg-swal-push-container.swal2-container {\n z-index: 9995;\n}\n\n#wpstg-scanning-files {\n padding-bottom: 5px;\n}\n\n#wpstg-scanning-files.wpstg-tab-section{\n padding-top:0;\n}\n\n.wpstg-reset-excludes-container {\n margin: 10px 0;\n}\n\n.wpstg-swal2-ajax-loader {\n width: 100%;\n height: 150px;\n overflow: hidden;\n display: flex;\n justify-content: center;\n align-items: center;\n}\n\n@keyframes wpstg-loading-icon-anim {\n\t0% {\n\t\ttransform: rotate(0);\n\t}\n\t100% {\n\t\ttransform: rotate(360deg);\n\t}\n}\n\n.wpstg-swal2-ajax-loader > img {\n width: 64px;\n height: 64px;\n animation: wpstg-loading-icon-anim 1s infinite linear;\n -webkit-animation: wpstg-loading-icon-anim 1s infinite linear;\n}\n\n.wpstg-swal2-container .wpstg-tab-section {\n width: auto !important;\n}\n\n.wpstg-is-dir-loading {\n position: absolute;\n margin-top: -2px;\n margin-left: 8px;\n display: none;\n}\n\n.wpstg-ml-8px {\n margin-left: 8px;\n}\n\n.wpstg-mb-8px {\n margin-bottom: 8px;\n}\n\n.wpstg-button.danger {\n display: inline-block;\n text-decoration: none;\n text-align: center;\n text-transform: inherit;\n background-color: #e74c3c;\n color: white;\n border-radius: 0px;\n border-color: transparent;\n}\n\n.wpstg-button.danger:hover {\n background-color: #c0392b;\n}\n\n.wpstg-swal2-container.wpstg-swal2-loading > .swal2-modal {\n height: 200px;\n}\n\n.wpstg-reset-confirmation.wpstg-swal2-container:not(.wpstg-swal2-loading) > .swal2-modal {\n max-width: 480px;\n}\n\n.wpstg-reset-confirmation.wpstg-swal2-container .swal2-header {\n display: none;\n}\n\n.wpstg-reset-confirmation.wpstg-swal2-container .swal2-content {\n height: auto;\n}\n\n.wpstg-reset-confirmation.wpstg-swal2-container > .swal2-modal > .swal2-content .wpstg-tabs-wrapper {\n overflow-y: auto;\n height: auto !important;\n}\n\n.wpstg-reset-confirmation.wpstg-swal2-container > .swal2-modal > .swal2-content {\n font-size: 13px;\n}\n\n.wpstg-reset-confirmation.wpstg-swal2-container > .swal2-modal > .swal2-content .wpstg-dir {\n margin-bottom: 4px;\n}\n\n.wpstg-reset-confirmation.wpstg-swal2-container > .swal2-modal > .swal2-content .wpstg-subdir {\n margin-top: 4px;\n}\n\n.wpstg-reset-confirmation.wpstg-swal2-container.has-collapsible-open .swal2-modal {\n height: calc(100vh - 70px);\n}\n\n.wpstg-reset-confirmation.wpstg-swal2-container.has-collapsible-open > .swal2-modal > .swal2-content .wpstg-tabs-wrapper {\n height: calc(100vh - 350px) !important;\n}\n"]}
assets/css/src/frontend/wpstg-admin-bar.css DELETED
@@ -1,3 +0,0 @@
1
- #wpadminbar{
2
- background-color: #ff8d00 !important;
3
- }
 
 
 
assets/css/src/wpstg-admin-bar.css DELETED
@@ -1,3 +0,0 @@
1
- #wpadminbar{
2
- background-color: #ff8d00 !important;
3
- }
 
 
 
assets/img/spinner.gif ADDED
Binary file
assets/img/wpstaging-icon.png ADDED
Binary file
assets/js/dist/wpstg-admin-beta.js CHANGED
@@ -1,15 +1,21 @@
1
- jQuery(document).ready(function ($) {
2
- $('.wpstg_hide_beta').on('click', function (e) {
3
- e.preventDefault();
4
- window.WPStaging.ajax({
5
- action: 'wpstg_hide_beta'
6
- }, function (response) {
7
- if (true === response) {
8
- $('.wpstg_beta_notice').slideUp('slow');
9
- return true;
10
- }
11
 
12
- alert('Unexpected message received. This might mean the data was not saved ' + 'and you might see this message again');
 
 
 
 
 
 
 
 
 
 
 
 
13
  });
14
  });
15
- });
 
 
1
+ (function () {
2
+ 'use strict';
 
 
 
 
 
 
 
 
3
 
4
+ jQuery(document).ready(function ($) {
5
+ $('.wpstg_hide_beta').on('click', function (e) {
6
+ e.preventDefault();
7
+ window.WPStaging.ajax({
8
+ action: 'wpstg_hide_beta'
9
+ }, function (response) {
10
+ if (true === response) {
11
+ $('.wpstg_beta_notice').slideUp('slow');
12
+ return true;
13
+ }
14
+
15
+ alert('Unexpected message received. This might mean the data was not saved ' + 'and you might see this message again');
16
+ });
17
  });
18
  });
19
+
20
+ }());
21
+ //# sourceMappingURL=wpstg-admin-beta.js.map
assets/js/dist/wpstg-admin-beta.js.map ADDED
@@ -0,0 +1 @@
 
1
+ {"version":3,"file":"wpstg-admin-beta.js","sources":["../src/wpstg-admin-beta.js"],"sourcesContent":["jQuery(document).ready(function($) {\n $('.wpstg_hide_beta').on('click', function(e) {\n e.preventDefault();\n\n window.WPStaging.ajax(\n {action: 'wpstg_hide_beta'},\n function(response) {\n if (true === response) {\n $('.wpstg_beta_notice').slideUp('slow');\n return true;\n }\n\n alert(\n 'Unexpected message received. This might mean the data was not saved ' +\n 'and you might see this message again',\n );\n },\n );\n });\n});\n"],"names":["jQuery","document","ready","$","on","e","preventDefault","window","WPStaging","ajax","action","response","slideUp","alert"],"mappings":";;;EAAAA,MAAM,CAACC,QAAD,CAAN,CAAiBC,KAAjB,CAAuB,UAASC,CAAT,EAAY;EACjCA,EAAAA,CAAC,CAAC,kBAAD,CAAD,CAAsBC,EAAtB,CAAyB,OAAzB,EAAkC,UAASC,CAAT,EAAY;EAC5CA,IAAAA,CAAC,CAACC,cAAF;EAEAC,IAAAA,MAAM,CAACC,SAAP,CAAiBC,IAAjB,CACI;EAACC,MAAAA,MAAM,EAAE;EAAT,KADJ,EAEI,UAASC,QAAT,EAAmB;EACjB,UAAI,SAASA,QAAb,EAAuB;EACrBR,QAAAA,CAAC,CAAC,oBAAD,CAAD,CAAwBS,OAAxB,CAAgC,MAAhC;EACA,eAAO,IAAP;EACD;;EAEDC,MAAAA,KAAK,CACD,yEACM,sCAFL,CAAL;EAID,KAZL;EAcD,GAjBD;EAkBD,CAnBD;;;;;;"}
assets/js/dist/wpstg-admin-beta.min.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ !function(){"use strict";jQuery(document).ready((function(e){e(".wpstg_hide_beta").on("click",(function(t){t.preventDefault(),window.WPStaging.ajax({action:"wpstg_hide_beta"},(function(t){if(!0===t)return e(".wpstg_beta_notice").slideUp("slow"),!0;alert("Unexpected message received. This might mean the data was not saved and you might see this message again")}))}))}))}();
2
+ //# sourceMappingURL=wpstg-admin-beta.min.js.map
assets/js/dist/wpstg-admin-beta.min.js.map ADDED
@@ -0,0 +1 @@
 
1
+ {"version":3,"file":"wpstg-admin-beta.min.js","sources":["../src/wpstg-admin-beta.js"],"sourcesContent":["jQuery(document).ready(function($) {\n $('.wpstg_hide_beta').on('click', function(e) {\n e.preventDefault();\n\n window.WPStaging.ajax(\n {action: 'wpstg_hide_beta'},\n function(response) {\n if (true === response) {\n $('.wpstg_beta_notice').slideUp('slow');\n return true;\n }\n\n alert(\n 'Unexpected message received. This might mean the data was not saved ' +\n 'and you might see this message again',\n );\n },\n );\n });\n});\n"],"names":["jQuery","document","ready","$","on","e","preventDefault","window","WPStaging","ajax","action","response","slideUp","alert"],"mappings":"yBAAAA,OAAOC,UAAUC,OAAM,SAASC,GAC9BA,EAAE,oBAAoBC,GAAG,SAAS,SAASC,GACzCA,EAAEC,iBAEFC,OAAOC,UAAUC,KACb,CAACC,OAAQ,oBACT,SAASC,OACH,IAASA,SACXR,EAAE,sBAAsBS,QAAQ,SACzB,EAGTC,MACI"}
assets/js/dist/wpstg-admin-plugins.js CHANGED
@@ -1,77 +1,82 @@
1
- var strict;
2
- jQuery(document).ready(function ($) {
3
- /**
4
- * DEACTIVATION FEEDBACK FORM
5
- */
6
- // show overlay when clicked on "deactivate"
7
- wpstg_deactivate_link = $('.wp-admin.plugins-php tr[data-slug="wp-staging"] .row-actions .deactivate a');
8
- wpstg_deactivate_link_url = wpstg_deactivate_link.attr('href');
9
- wpstg_deactivate_link.on('click', function (e) {
10
- e.preventDefault(); // only show feedback form once per 30 days
11
 
12
- var c_value = wpstg_admin_get_cookie('wpstg_hide_feedback');
 
 
 
 
 
 
 
 
13
 
14
- if (c_value === undefined) {
15
- $('#wpstg-feedback-overlay').show();
16
- } else {
17
- // click on the link
18
- window.location.href = wpstg_deactivate_link_url;
19
- }
20
- }); // show text fields
21
 
22
- $('#wpstg-feedback-content input[type="radio"]').on('click', function () {
23
- // show text field if there is one
24
- $(this).parents('li').next('li').children('input[type="text"], textarea').show();
25
- }); // send form or close it
 
 
 
26
 
27
- $('#wpstg-feedback-content .button').on('click', function (e) {
28
- e.preventDefault(); // set cookie for 30 days
 
 
29
 
30
- var exdate = new Date();
31
- exdate.setSeconds(exdate.getSeconds() + 2592000);
32
- document.cookie = 'wpstg_hide_feedback=1; expires=' + exdate.toUTCString() + '; path=/';
33
- $('#wpstg-feedback-overlay').hide();
34
 
35
- if ('wpstg-feedback-submit' === this.id) {
36
- // Send form data
37
- $.ajax({
38
- type: 'POST',
39
- url: ajaxurl,
40
- dataType: 'json',
41
- data: {
42
- action: 'wpstg_send_feedback',
43
- data: $('#wpstg-feedback-content form').serialize()
44
- },
45
- complete: function complete(MLHttpRequest, textStatus, errorThrown) {
46
- // deactivate the plugin and close the popup
47
- $('#wpstg-feedback-overlay').remove();
48
- window.location.href = wpstg_deactivate_link_url;
49
- }
50
- });
51
- } else {
52
- $('#wpstg-feedback-overlay').remove();
53
- window.location.href = wpstg_deactivate_link_url;
54
- }
55
- }); // close form without doing anything
56
 
57
- $('.wpstg-feedback-not-deactivate').on('click', function (e) {
58
- $('#wpstg-feedback-overlay').hide();
59
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
 
61
- function wpstg_admin_get_cookie(name) {
62
- var i;
63
- var x;
64
- var y;
65
- var wpstg_cookies = document.cookie.split(';');
66
 
67
- for (i = 0; i < wpstg_cookies.length; i++) {
68
- x = wpstg_cookies[i].substr(0, wpstg_cookies[i].indexOf('='));
69
- y = wpstg_cookies[i].substr(wpstg_cookies[i].indexOf('=') + 1);
70
- x = x.replace(/^\s+|\s+$/g, '');
71
 
72
- if (x === name) {
73
- return unescape(y);
 
74
  }
75
  }
76
- }
77
- });
 
 
1
+ (function () {
2
+ 'use strict';
 
 
 
 
 
 
 
 
3
 
4
+ jQuery(document).ready(function ($) {
5
+ /**
6
+ * DEACTIVATION FEEDBACK FORM
7
+ */
8
+ // show overlay when clicked on "deactivate"
9
+ wpstg_deactivate_link = $('.wp-admin.plugins-php tr[data-slug="wp-staging"] .row-actions .deactivate a');
10
+ wpstg_deactivate_link_url = wpstg_deactivate_link.attr('href');
11
+ wpstg_deactivate_link.on('click', function (e) {
12
+ e.preventDefault(); // only show feedback form once per 30 days
13
 
14
+ var c_value = wpstg_admin_get_cookie('wpstg_hide_feedback');
 
 
 
 
 
 
15
 
16
+ if (c_value === undefined) {
17
+ $('#wpstg-feedback-overlay').show();
18
+ } else {
19
+ // click on the link
20
+ window.location.href = wpstg_deactivate_link_url;
21
+ }
22
+ }); // show text fields
23
 
24
+ $('#wpstg-feedback-content input[type="radio"]').on('click', function () {
25
+ // show text field if there is one
26
+ $(this).parents('li').next('li').children('input[type="text"], textarea').show();
27
+ }); // send form or close it
28
 
29
+ $('#wpstg-feedback-content .button').on('click', function (e) {
30
+ e.preventDefault(); // set cookie for 30 days
 
 
31
 
32
+ var exdate = new Date();
33
+ exdate.setSeconds(exdate.getSeconds() + 2592000);
34
+ document.cookie = 'wpstg_hide_feedback=1; expires=' + exdate.toUTCString() + '; path=/';
35
+ $('#wpstg-feedback-overlay').hide();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
 
37
+ if ('wpstg-feedback-submit' === this.id) {
38
+ // Send form data
39
+ $.ajax({
40
+ type: 'POST',
41
+ url: ajaxurl,
42
+ dataType: 'json',
43
+ data: {
44
+ action: 'wpstg_send_feedback',
45
+ data: $('#wpstg-feedback-content form').serialize()
46
+ },
47
+ complete: function complete(MLHttpRequest, textStatus, errorThrown) {
48
+ // deactivate the plugin and close the popup
49
+ $('#wpstg-feedback-overlay').remove();
50
+ window.location.href = wpstg_deactivate_link_url;
51
+ }
52
+ });
53
+ } else {
54
+ $('#wpstg-feedback-overlay').remove();
55
+ window.location.href = wpstg_deactivate_link_url;
56
+ }
57
+ }); // close form without doing anything
58
+
59
+ $('.wpstg-feedback-not-deactivate').on('click', function (e) {
60
+ $('#wpstg-feedback-overlay').hide();
61
+ });
62
 
63
+ function wpstg_admin_get_cookie(name) {
64
+ var i;
65
+ var x;
66
+ var y;
67
+ var wpstg_cookies = document.cookie.split(';');
68
 
69
+ for (i = 0; i < wpstg_cookies.length; i++) {
70
+ x = wpstg_cookies[i].substr(0, wpstg_cookies[i].indexOf('='));
71
+ y = wpstg_cookies[i].substr(wpstg_cookies[i].indexOf('=') + 1);
72
+ x = x.replace(/^\s+|\s+$/g, '');
73
 
74
+ if (x === name) {
75
+ return unescape(y);
76
+ }
77
  }
78
  }
79
+ });
80
+
81
+ }());
82
+ //# sourceMappingURL=wpstg-admin-plugins.js.map
assets/js/dist/wpstg-admin-plugins.js.map ADDED
@@ -0,0 +1 @@
 
1
+ {"version":3,"file":"wpstg-admin-plugins.js","sources":["../src/wpstg-admin-plugins.js"],"sourcesContent":["let strict;\n\njQuery(document).ready(function($) {\n /**\n * DEACTIVATION FEEDBACK FORM\n */\n // show overlay when clicked on \"deactivate\"\n wpstg_deactivate_link = $('.wp-admin.plugins-php tr[data-slug=\"wp-staging\"] .row-actions .deactivate a');\n wpstg_deactivate_link_url = wpstg_deactivate_link.attr('href');\n\n wpstg_deactivate_link.on('click', function(e) {\n e.preventDefault();\n\n // only show feedback form once per 30 days\n const c_value = wpstg_admin_get_cookie('wpstg_hide_feedback');\n\n if (c_value === undefined) {\n $('#wpstg-feedback-overlay').show();\n } else {\n // click on the link\n window.location.href = wpstg_deactivate_link_url;\n }\n });\n // show text fields\n $('#wpstg-feedback-content input[type=\"radio\"]').on('click', function() {\n // show text field if there is one\n $(this).parents('li').next('li').children('input[type=\"text\"], textarea').show();\n });\n // send form or close it\n $('#wpstg-feedback-content .button').on('click', function(e) {\n e.preventDefault();\n // set cookie for 30 days\n const exdate = new Date();\n exdate.setSeconds(exdate.getSeconds() + 2592000);\n document.cookie = 'wpstg_hide_feedback=1; expires=' + exdate.toUTCString() + '; path=/';\n\n $('#wpstg-feedback-overlay').hide();\n if ('wpstg-feedback-submit' === this.id) {\n // Send form data\n $.ajax({\n type: 'POST',\n url: ajaxurl,\n dataType: 'json',\n data: {\n action: 'wpstg_send_feedback',\n data: $('#wpstg-feedback-content form').serialize(),\n },\n complete: function(MLHttpRequest, textStatus, errorThrown) {\n // deactivate the plugin and close the popup\n $('#wpstg-feedback-overlay').remove();\n window.location.href = wpstg_deactivate_link_url;\n },\n });\n } else {\n $('#wpstg-feedback-overlay').remove();\n window.location.href = wpstg_deactivate_link_url;\n }\n });\n // close form without doing anything\n $('.wpstg-feedback-not-deactivate').on('click', function(e) {\n $('#wpstg-feedback-overlay').hide();\n });\n\n function wpstg_admin_get_cookie(name) {\n let i; let x; let y; const wpstg_cookies = document.cookie.split( ';' );\n for (i = 0; i < wpstg_cookies.length; i++) {\n x = wpstg_cookies[i].substr( 0, wpstg_cookies[i].indexOf( '=' ) );\n y = wpstg_cookies[i].substr( wpstg_cookies[i].indexOf( '=' ) + 1 );\n x = x.replace( /^\\s+|\\s+$/g, '' );\n if (x === name) {\n return unescape( y );\n }\n }\n }\n});\n"],"names":["jQuery","document","ready","$","wpstg_deactivate_link","wpstg_deactivate_link_url","attr","on","e","preventDefault","c_value","wpstg_admin_get_cookie","undefined","show","window","location","href","parents","next","children","exdate","Date","setSeconds","getSeconds","cookie","toUTCString","hide","id","ajax","type","url","ajaxurl","dataType","data","action","serialize","complete","MLHttpRequest","textStatus","errorThrown","remove","name","i","x","y","wpstg_cookies","split","length","substr","indexOf","replace","unescape"],"mappings":"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"}
assets/js/dist/wpstg-admin-plugins.min.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ !function(){"use strict";jQuery(document).ready((function(e){wpstg_deactivate_link=e('.wp-admin.plugins-php tr[data-slug="wp-staging"] .row-actions .deactivate a'),wpstg_deactivate_link_url=wpstg_deactivate_link.attr("href"),wpstg_deactivate_link.on("click",(function(t){t.preventDefault(),void 0===function(e){var t,a,n,i=document.cookie.split(";");for(t=0;t<i.length;t++)if(a=i[t].substr(0,i[t].indexOf("=")),n=i[t].substr(i[t].indexOf("=")+1),(a=a.replace(/^\s+|\s+$/g,""))===e)return unescape(n)}("wpstg_hide_feedback")?e("#wpstg-feedback-overlay").show():window.location.href=wpstg_deactivate_link_url})),e('#wpstg-feedback-content input[type="radio"]').on("click",(function(){e(this).parents("li").next("li").children('input[type="text"], textarea').show()})),e("#wpstg-feedback-content .button").on("click",(function(t){t.preventDefault();var a=new Date;a.setSeconds(a.getSeconds()+2592e3),document.cookie="wpstg_hide_feedback=1; expires="+a.toUTCString()+"; path=/",e("#wpstg-feedback-overlay").hide(),"wpstg-feedback-submit"===this.id?e.ajax({type:"POST",url:ajaxurl,dataType:"json",data:{action:"wpstg_send_feedback",data:e("#wpstg-feedback-content form").serialize()},complete:function(t,a,n){e("#wpstg-feedback-overlay").remove(),window.location.href=wpstg_deactivate_link_url}}):(e("#wpstg-feedback-overlay").remove(),window.location.href=wpstg_deactivate_link_url)})),e(".wpstg-feedback-not-deactivate").on("click",(function(t){e("#wpstg-feedback-overlay").hide()}))}))}();
2
+ //# sourceMappingURL=wpstg-admin-plugins.min.js.map
assets/js/dist/wpstg-admin-plugins.min.js.map ADDED
@@ -0,0 +1 @@
 
1
+ {"version":3,"file":"wpstg-admin-plugins.min.js","sources":["../src/wpstg-admin-plugins.js"],"sourcesContent":["let strict;\n\njQuery(document).ready(function($) {\n /**\n * DEACTIVATION FEEDBACK FORM\n */\n // show overlay when clicked on \"deactivate\"\n wpstg_deactivate_link = $('.wp-admin.plugins-php tr[data-slug=\"wp-staging\"] .row-actions .deactivate a');\n wpstg_deactivate_link_url = wpstg_deactivate_link.attr('href');\n\n wpstg_deactivate_link.on('click', function(e) {\n e.preventDefault();\n\n // only show feedback form once per 30 days\n const c_value = wpstg_admin_get_cookie('wpstg_hide_feedback');\n\n if (c_value === undefined) {\n $('#wpstg-feedback-overlay').show();\n } else {\n // click on the link\n window.location.href = wpstg_deactivate_link_url;\n }\n });\n // show text fields\n $('#wpstg-feedback-content input[type=\"radio\"]').on('click', function() {\n // show text field if there is one\n $(this).parents('li').next('li').children('input[type=\"text\"], textarea').show();\n });\n // send form or close it\n $('#wpstg-feedback-content .button').on('click', function(e) {\n e.preventDefault();\n // set cookie for 30 days\n const exdate = new Date();\n exdate.setSeconds(exdate.getSeconds() + 2592000);\n document.cookie = 'wpstg_hide_feedback=1; expires=' + exdate.toUTCString() + '; path=/';\n\n $('#wpstg-feedback-overlay').hide();\n if ('wpstg-feedback-submit' === this.id) {\n // Send form data\n $.ajax({\n type: 'POST',\n url: ajaxurl,\n dataType: 'json',\n data: {\n action: 'wpstg_send_feedback',\n data: $('#wpstg-feedback-content form').serialize(),\n },\n complete: function(MLHttpRequest, textStatus, errorThrown) {\n // deactivate the plugin and close the popup\n $('#wpstg-feedback-overlay').remove();\n window.location.href = wpstg_deactivate_link_url;\n },\n });\n } else {\n $('#wpstg-feedback-overlay').remove();\n window.location.href = wpstg_deactivate_link_url;\n }\n });\n // close form without doing anything\n $('.wpstg-feedback-not-deactivate').on('click', function(e) {\n $('#wpstg-feedback-overlay').hide();\n });\n\n function wpstg_admin_get_cookie(name) {\n let i; let x; let y; const wpstg_cookies = document.cookie.split( ';' );\n for (i = 0; i < wpstg_cookies.length; i++) {\n x = wpstg_cookies[i].substr( 0, wpstg_cookies[i].indexOf( '=' ) );\n y = wpstg_cookies[i].substr( wpstg_cookies[i].indexOf( '=' ) + 1 );\n x = x.replace( /^\\s+|\\s+$/g, '' );\n if (x === name) {\n return unescape( y );\n }\n }\n }\n});\n"],"names":["jQuery","document","ready","$","wpstg_deactivate_link","wpstg_deactivate_link_url","attr","on","e","preventDefault","undefined","name","i","x","y","wpstg_cookies","cookie","split","length","substr","indexOf","replace","unescape","wpstg_admin_get_cookie","show","window","location","href","this","parents","next","children","exdate","Date","setSeconds","getSeconds","toUTCString","hide","id","ajax","type","url","ajaxurl","dataType","data","action","serialize","complete","MLHttpRequest","textStatus","errorThrown","remove"],"mappings":"yBAEAA,OAAOC,UAAUC,OAAM,SAASC,GAK9BC,sBAAwBD,EAAE,+EAC1BE,0BAA4BD,sBAAsBE,KAAK,QAEvDF,sBAAsBG,GAAG,SAAS,SAASC,GACzCA,EAAEC,sBAKcC,aA+CcC,OAC1BC,EAAOC,EAAOC,EAASC,EAAgBd,SAASe,OAAOC,MAAO,SAC7DL,EAAI,EAAGA,EAAIG,EAAcG,OAAQN,OACpCC,EAAIE,EAAcH,GAAGO,OAAQ,EAAGJ,EAAcH,GAAGQ,QAAS,MAC1DN,EAAIC,EAAcH,GAAGO,OAAQJ,EAAcH,GAAGQ,QAAS,KAAQ,IAC/DP,EAAIA,EAAEQ,QAAS,aAAc,OACnBV,SACDW,SAAUR,GAxDLS,CAAuB,uBAGrCpB,EAAE,2BAA2BqB,OAG7BC,OAAOC,SAASC,KAAOtB,6BAI3BF,EAAE,+CAA+CI,GAAG,SAAS,WAE3DJ,EAAEyB,MAAMC,QAAQ,MAAMC,KAAK,MAAMC,SAAS,gCAAgCP,UAG5ErB,EAAE,mCAAmCI,GAAG,SAAS,SAASC,GACxDA,EAAEC,qBAEIuB,EAAS,IAAIC,KACnBD,EAAOE,WAAWF,EAAOG,aAAe,QACxClC,SAASe,OAAS,kCAAoCgB,EAAOI,cAAgB,WAE7EjC,EAAE,2BAA2BkC,OACzB,0BAA4BT,KAAKU,GAEnCnC,EAAEoC,KAAK,CACLC,KAAM,OACNC,IAAKC,QACLC,SAAU,OACVC,KAAM,CACJC,OAAQ,sBACRD,KAAMzC,EAAE,gCAAgC2C,aAE1CC,SAAU,SAASC,EAAeC,EAAYC,GAE5C/C,EAAE,2BAA2BgD,SAC7B1B,OAAOC,SAASC,KAAOtB,8BAI3BF,EAAE,2BAA2BgD,SAC7B1B,OAAOC,SAASC,KAAOtB,8BAI3BF,EAAE,kCAAkCI,GAAG,SAAS,SAASC,GACvDL,EAAE,2BAA2BkC"}
assets/js/dist/wpstg-admin-poll.js CHANGED
@@ -1,15 +1,21 @@
1
- jQuery(document).ready(function ($) {
2
- $('.wpstg_hide_poll').on('click', function (e) {
3
- e.preventDefault();
4
- window.WPStaging.ajax({
5
- action: 'wpstg_hide_poll'
6
- }, function (response) {
7
- if (true === response) {
8
- $('.wpstg_poll').slideUp('fast');
9
- return true;
10
- } else {
11
- alert('Unexpected message received. This might mean the data was not saved ' + 'and you might see this message again.');
12
- }
 
 
 
 
13
  });
14
  });
15
- });
 
 
1
+ (function () {
2
+ 'use strict';
3
+
4
+ jQuery(document).ready(function ($) {
5
+ $('.wpstg_hide_poll').on('click', function (e) {
6
+ e.preventDefault();
7
+ window.WPStaging.ajax({
8
+ action: 'wpstg_hide_poll'
9
+ }, function (response) {
10
+ if (true === response) {
11
+ $('.wpstg_poll').slideUp('fast');
12
+ return true;
13
+ } else {
14
+ alert('Unexpected message received. This might mean the data was not saved ' + 'and you might see this message again.');
15
+ }
16
+ });
17
  });
18
  });
19
+
20
+ }());
21
+ //# sourceMappingURL=wpstg-admin-poll.js.map
assets/js/dist/wpstg-admin-poll.js.map ADDED
@@ -0,0 +1 @@
 
1
+ {"version":3,"file":"wpstg-admin-poll.js","sources":["../src/wpstg-admin-poll.js"],"sourcesContent":["jQuery(document).ready(function($) {\n $('.wpstg_hide_poll').on('click', function(e) {\n e.preventDefault();\n\n window.WPStaging.ajax(\n {action: 'wpstg_hide_poll'},\n function(response) {\n if (true === response) {\n $('.wpstg_poll').slideUp('fast');\n return true;\n } else {\n alert(\n 'Unexpected message received. This might mean the data was not saved ' +\n 'and you might see this message again.',\n );\n }\n },\n );\n });\n});\n"],"names":["jQuery","document","ready","$","on","e","preventDefault","window","WPStaging","ajax","action","response","slideUp","alert"],"mappings":";;;EAAAA,MAAM,CAACC,QAAD,CAAN,CAAiBC,KAAjB,CAAuB,UAASC,CAAT,EAAY;EACjCA,EAAAA,CAAC,CAAC,kBAAD,CAAD,CAAsBC,EAAtB,CAAyB,OAAzB,EAAkC,UAASC,CAAT,EAAY;EAC5CA,IAAAA,CAAC,CAACC,cAAF;EAEAC,IAAAA,MAAM,CAACC,SAAP,CAAiBC,IAAjB,CACI;EAACC,MAAAA,MAAM,EAAE;EAAT,KADJ,EAEI,UAASC,QAAT,EAAmB;EACjB,UAAI,SAASA,QAAb,EAAuB;EACrBR,QAAAA,CAAC,CAAC,aAAD,CAAD,CAAiBS,OAAjB,CAAyB,MAAzB;EACA,eAAO,IAAP;EACD,OAHD,MAGO;EACLC,QAAAA,KAAK,CACD,yEACQ,uCAFP,CAAL;EAID;EACF,KAZL;EAcD,GAjBD;EAkBD,CAnBD;;;;;;"}
assets/js/dist/wpstg-admin-poll.min.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ !function(){"use strict";jQuery(document).ready((function(e){e(".wpstg_hide_poll").on("click",(function(t){t.preventDefault(),window.WPStaging.ajax({action:"wpstg_hide_poll"},(function(t){if(!0===t)return e(".wpstg_poll").slideUp("fast"),!0;alert("Unexpected message received. This might mean the data was not saved and you might see this message again.")}))}))}))}();
2
+ //# sourceMappingURL=wpstg-admin-poll.min.js.map
assets/js/dist/wpstg-admin-poll.min.js.map ADDED
@@ -0,0 +1 @@
 
1
+ {"version":3,"file":"wpstg-admin-poll.min.js","sources":["../src/wpstg-admin-poll.js"],"sourcesContent":["jQuery(document).ready(function($) {\n $('.wpstg_hide_poll').on('click', function(e) {\n e.preventDefault();\n\n window.WPStaging.ajax(\n {action: 'wpstg_hide_poll'},\n function(response) {\n if (true === response) {\n $('.wpstg_poll').slideUp('fast');\n return true;\n } else {\n alert(\n 'Unexpected message received. This might mean the data was not saved ' +\n 'and you might see this message again.',\n );\n }\n },\n );\n });\n});\n"],"names":["jQuery","document","ready","$","on","e","preventDefault","window","WPStaging","ajax","action","response","slideUp","alert"],"mappings":"yBAAAA,OAAOC,UAAUC,OAAM,SAASC,GAC9BA,EAAE,oBAAoBC,GAAG,SAAS,SAASC,GACzCA,EAAEC,iBAEFC,OAAOC,UAAUC,KACb,CAACC,OAAQ,oBACT,SAASC,OACH,IAASA,SACXR,EAAE,eAAeS,QAAQ,SAClB,EAEPC,MACI"}
assets/js/dist/wpstg-admin-rating.js CHANGED
@@ -1,153 +1,138 @@
1
- var wpstgTimesWaited = 0;
2
- /*
3
- Let's wait for jQuery to be available to show the rating.
4
- We need it to dispatch AJAX requests.
5
- */
6
 
7
- var wpstgWaitForJQuery = setInterval(function () {
8
- if (wpstgTimesWaited > 100) {
9
- // Give up waiting.
10
- clearInterval(wpstgWaitForJQuery);
11
- }
12
 
13
- if (typeof jQuery != 'undefined') {
14
- wpstgRegisterRatingEvents();
15
- clearInterval(wpstgWaitForJQuery);
16
- }
 
17
 
18
- wpstgTimesWaited = wpstgTimesWaited + 1;
19
- }, 100);
 
 
20
 
21
- function wpstgRegisterRatingEvents() {
22
- // Show the rating once jQuery is loaded.
23
- jQuery('.wpstg_fivestar').show();
24
- /**
25
- * Dispatch the request to hide the video after user clicks to rate the plugin.
26
- */
27
 
28
- jQuery(document).on('click', '#wpstg_clicked_deserved_it', function (e) {
29
- jQuery.ajax({
30
- url: ajaxurl,
31
- type: 'POST',
32
- data: {
33
- action: 'wpstg_hide_rating'
34
- },
35
- error: function error(xhr, textStatus, errorThrown) {
36
- console.log(xhr.status + ' ' + xhr.statusText + '---' + textStatus);
37
- console.log(textStatus);
38
- alert('Unknown error. Please get in contact with us to solve it support@wp-staging.com');
39
- },
40
- success: function success(data) {
41
- jQuery('.wpstg_fivestar').slideUp('fast');
42
- return true;
43
- },
44
- statusCode: {
45
- 404: function _() {
46
- alert('Something went wrong; can\'t find ajax request URL! Please get in contact with us to solve it support@wp-staging.com');
 
 
 
47
  },
48
- 500: function _() {
49
- alert('Something went wrong; internal server error while processing the request! Please get in contact with us to solve it support@wp-staging.com');
 
 
 
 
 
50
  }
51
- }
52
  });
53
- });
54
- jQuery('.wpstg_hide_rating').on('click', function (e) {
55
- e.preventDefault();
56
- jQuery.ajax({
57
- url: ajaxurl,
58
- type: 'POST',
59
- data: {
60
- action: 'wpstg_hide_rating'
61
- },
62
- error: function error(xhr, textStatus, errorThrown) {
63
- console.log(xhr.status + ' ' + xhr.statusText + '---' + textStatus);
64
- console.log(textStatus);
65
- alert('Unknown error. Please get in contact with us to solve it support@wp-staging.com');
66
- },
67
- success: function success(data) {
68
- jQuery('.wpstg_fivestar').slideUp('fast');
69
- return true;
70
- },
71
- statusCode: {
72
- 404: function _() {
73
- alert('Something went wrong; can\'t find ajax request URL! Please get in contact with us to solve it support@wp-staging.com');
74
  },
75
- 500: function _() {
76
- alert('Something went wrong; internal server error while processing the request! Please get in contact with us to solve it support@wp-staging.com');
 
 
 
 
 
 
 
 
 
77
  }
78
- }
79
  });
80
- });
81
- jQuery('.wpstg_rate_later').on('click', function (e) {
82
- e.preventDefault();
83
- jQuery.ajax({
84
- url: ajaxurl,
85
- type: 'POST',
86
- data: {
87
- action: 'wpstg_hide_later'
88
- },
89
- error: function error(xhr, textStatus, errorThrown) {
90
- console.log(xhr.status + ' ' + xhr.statusText + '---' + textStatus);
91
- console.log(textStatus);
92
- alert('Unknown error. Please get in contact with us to solve it support@wp-staging.com');
93
- },
94
- success: function success(data) {
95
- jQuery('.wpstg_fivestar').slideUp('fast');
96
- return true;
97
- },
98
- statusCode: {
99
- 404: function _() {
100
- alert('Something went wrong; can\'t find ajax request URL! Please get in contact with us to solve it support@wp-staging.com');
101
  },
102
- 500: function _() {
103
- alert('Something went wrong; internal server error while processing the request! Please get in contact with us to solve it support@wp-staging.com');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104
  }
105
- }
106
  });
107
- });
108
- }
109
 
110
- document.styleSheets[0].insertRule('@media only screen and (max-width:600px){.wpstg-welcome-box{display:block !important}.wpstg-welcome-video-container{width:100% !important;height:auto !important}.wpstg-welcome-text{padding-left:8px !important}}', '');
111
- document.addEventListener('DOMContentLoaded', function () {
112
- var player;
113
- var accepted = wpstgYouTubeConfig.accepted;
114
- var playerPlaceholder = document.getElementById('welcomeNoticeFree');
115
- playerPlaceholder.addEventListener('click', function () {
116
- if (!accepted) {
117
- var message = wpstgYouTubeConfig.message + '\n \n' + wpstgYouTubeConfig.regards;
118
- var conf = confirm(message);
119
 
120
- if (conf) {
121
- accepted = true;
122
- wpstgFetchVideo();
 
123
  }
124
- }
125
  });
126
- });
127
-
128
- function wpstgFetchVideo() {
129
- var tag = document.createElement('script');
130
- tag.src = 'https://www.youtube.com/iframe_api';
131
- var firstScriptTag = document.getElementsByTagName('script')[0];
132
- firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
133
- }
134
 
135
- function onYouTubeIframeAPIReady() {
136
- player = new YT.Player('welcomeNoticeFree', {
137
- height: '225',
138
- width: '400',
139
- videoId: 'fsC9ZvbRQ5Y',
140
- playerVars: {
141
- rel: 0,
142
- showinfo: 0,
143
- ecver: 2
144
- },
145
- events: {
146
- 'onReady': onPlayerReady
147
- }
148
- });
149
- }
150
 
151
- function onPlayerReady(event) {
152
- event.target.playVideo();
153
- }
1
+ (function () {
2
+ 'use strict';
 
 
 
3
 
4
+ var wpstgTimesWaited = 0;
5
+ /*
6
+ Let's wait for jQuery to be available to show the rating.
7
+ We need it to dispatch AJAX requests.
8
+ */
9
 
10
+ var wpstgWaitForJQuery = setInterval(function () {
11
+ if (wpstgTimesWaited > 100) {
12
+ // Give up waiting.
13
+ clearInterval(wpstgWaitForJQuery);
14
+ }
15
 
16
+ if (typeof jQuery != 'undefined') {
17
+ wpstgRegisterRatingEvents();
18
+ clearInterval(wpstgWaitForJQuery);
19
+ }
20
 
21
+ wpstgTimesWaited = wpstgTimesWaited + 1;
22
+ }, 100);
 
 
 
 
23
 
24
+ function wpstgRegisterRatingEvents() {
25
+ // Show the rating once jQuery is loaded.
26
+ jQuery('.wpstg_fivestar').show();
27
+ /**
28
+ * Dispatch the request to hide the video after user clicks to rate the plugin.
29
+ */
30
+
31
+ jQuery(document).on('click', '#wpstg_clicked_deserved_it', function (e) {
32
+ jQuery.ajax({
33
+ url: ajaxurl,
34
+ type: 'POST',
35
+ data: {
36
+ action: 'wpstg_hide_rating'
37
+ },
38
+ error: function error(xhr, textStatus, errorThrown) {
39
+ console.log(xhr.status + ' ' + xhr.statusText + '---' + textStatus);
40
+ console.log(textStatus);
41
+ alert('Unknown error. Please get in contact with us to solve it support@wp-staging.com');
42
+ },
43
+ success: function success(data) {
44
+ jQuery('.wpstg_fivestar').slideUp('fast');
45
+ return true;
46
  },
47
+ statusCode: {
48
+ 404: function _() {
49
+ alert('Something went wrong; can\'t find ajax request URL! Please get in contact with us to solve it support@wp-staging.com');
50
+ },
51
+ 500: function _() {
52
+ alert('Something went wrong; internal server error while processing the request! Please get in contact with us to solve it support@wp-staging.com');
53
+ }
54
  }
55
+ });
56
  });
57
+ jQuery('.wpstg_hide_rating').on('click', function (e) {
58
+ e.preventDefault();
59
+ jQuery.ajax({
60
+ url: ajaxurl,
61
+ type: 'POST',
62
+ data: {
63
+ action: 'wpstg_hide_rating'
64
+ },
65
+ error: function error(xhr, textStatus, errorThrown) {
66
+ console.log(xhr.status + ' ' + xhr.statusText + '---' + textStatus);
67
+ console.log(textStatus);
68
+ alert('Unknown error. Please get in contact with us to solve it support@wp-staging.com');
 
 
 
 
 
 
 
 
 
69
  },
70
+ success: function success(data) {
71
+ jQuery('.wpstg_fivestar').slideUp('fast');
72
+ return true;
73
+ },
74
+ statusCode: {
75
+ 404: function _() {
76
+ alert('Something went wrong; can\'t find ajax request URL! Please get in contact with us to solve it support@wp-staging.com');
77
+ },
78
+ 500: function _() {
79
+ alert('Something went wrong; internal server error while processing the request! Please get in contact with us to solve it support@wp-staging.com');
80
+ }
81
  }
82
+ });
83
  });
84
+ jQuery('.wpstg_rate_later').on('click', function (e) {
85
+ e.preventDefault();
86
+ jQuery.ajax({
87
+ url: ajaxurl,
88
+ type: 'POST',
89
+ data: {
90
+ action: 'wpstg_hide_later'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
  },
92
+ error: function error(xhr, textStatus, errorThrown) {
93
+ console.log(xhr.status + ' ' + xhr.statusText + '---' + textStatus);
94
+ console.log(textStatus);
95
+ alert('Unknown error. Please get in contact with us to solve it support@wp-staging.com');
96
+ },
97
+ success: function success(data) {
98
+ jQuery('.wpstg_fivestar').slideUp('fast');
99
+ return true;
100
+ },
101
+ statusCode: {
102
+ 404: function _() {
103
+ alert('Something went wrong; can\'t find ajax request URL! Please get in contact with us to solve it support@wp-staging.com');
104
+ },
105
+ 500: function _() {
106
+ alert('Something went wrong; internal server error while processing the request! Please get in contact with us to solve it support@wp-staging.com');
107
+ }
108
  }
109
+ });
110
  });
111
+ }
 
112
 
113
+ document.styleSheets[0].insertRule('@media only screen and (max-width:600px){.wpstg-welcome-box{display:block !important}.wpstg-welcome-video-container{width:100% !important;height:auto !important}.wpstg-welcome-text{padding-left:8px !important}}', '');
114
+ document.addEventListener('DOMContentLoaded', function () {
115
+ var accepted = wpstgYouTubeConfig.accepted;
116
+ var playerPlaceholder = document.getElementById('welcomeNoticeFree');
117
+ playerPlaceholder.addEventListener('click', function () {
118
+ if (!accepted) {
119
+ var message = wpstgYouTubeConfig.message + '\n \n' + wpstgYouTubeConfig.regards;
120
+ var conf = confirm(message);
 
121
 
122
+ if (conf) {
123
+ accepted = true;
124
+ wpstgFetchVideo();
125
+ }
126
  }
127
+ });
128
  });
 
 
 
 
 
 
 
 
129
 
130
+ function wpstgFetchVideo() {
131
+ var tag = document.createElement('script');
132
+ tag.src = 'https://www.youtube.com/iframe_api';
133
+ var firstScriptTag = document.getElementsByTagName('script')[0];
134
+ firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
135
+ }
 
 
 
 
 
 
 
 
 
136
 
137
+ }());
138
+ //# sourceMappingURL=wpstg-admin-rating.js.map
 
assets/js/dist/wpstg-admin-rating.js.map ADDED
@@ -0,0 +1 @@
 
1
+ {"version":3,"file":"wpstg-admin-rating.js","sources":["../src/wpstg-admin-rating.js"],"sourcesContent":["let wpstgTimesWaited = 0;\n\n/*\nLet's wait for jQuery to be available to show the rating.\nWe need it to dispatch AJAX requests.\n */\nvar wpstgWaitForJQuery = setInterval(function() {\n if (wpstgTimesWaited > 100) {\n // Give up waiting.\n clearInterval(wpstgWaitForJQuery);\n }\n if (typeof jQuery != 'undefined') {\n wpstgRegisterRatingEvents();\n\n clearInterval(wpstgWaitForJQuery);\n }\n wpstgTimesWaited = wpstgTimesWaited + 1;\n}, 100);\n\nfunction wpstgRegisterRatingEvents() {\n // Show the rating once jQuery is loaded.\n jQuery('.wpstg_fivestar').show();\n\n /**\n * Dispatch the request to hide the video after user clicks to rate the plugin.\n */\n jQuery(document).on('click', '#wpstg_clicked_deserved_it', function(e) {\n jQuery.ajax({\n url: ajaxurl,\n type: 'POST',\n data: {action: 'wpstg_hide_rating'},\n error: function(xhr, textStatus, errorThrown) {\n console.log(xhr.status + ' ' + xhr.statusText + '---' + textStatus);\n console.log(textStatus);\n\n alert(\n 'Unknown error. Please get in contact with us to solve it support@wp-staging.com',\n );\n },\n success: function(data) {\n jQuery('.wpstg_fivestar').slideUp('fast');\n return true;\n },\n statusCode: {\n 404: function() {\n alert('Something went wrong; can\\'t find ajax request URL! Please get in contact with us to solve it support@wp-staging.com');\n },\n 500: function() {\n alert('Something went wrong; internal server error while processing the request! Please get in contact with us to solve it support@wp-staging.com');\n },\n },\n });\n });\n\n jQuery('.wpstg_hide_rating').on('click', function(e) {\n e.preventDefault();\n\n jQuery.ajax({\n url: ajaxurl,\n type: 'POST',\n data: {action: 'wpstg_hide_rating'},\n error: function(xhr, textStatus, errorThrown) {\n console.log(xhr.status + ' ' + xhr.statusText + '---' + textStatus);\n console.log(textStatus);\n\n alert(\n 'Unknown error. Please get in contact with us to solve it support@wp-staging.com',\n );\n },\n success: function(data) {\n jQuery('.wpstg_fivestar').slideUp('fast');\n return true;\n },\n statusCode: {\n 404: function() {\n alert('Something went wrong; can\\'t find ajax request URL! Please get in contact with us to solve it support@wp-staging.com');\n },\n 500: function() {\n alert('Something went wrong; internal server error while processing the request! Please get in contact with us to solve it support@wp-staging.com');\n },\n },\n });\n });\n\n jQuery('.wpstg_rate_later').on('click', function(e) {\n e.preventDefault();\n\n jQuery.ajax({\n url: ajaxurl,\n type: 'POST',\n data: {action: 'wpstg_hide_later'},\n error: function(xhr, textStatus, errorThrown) {\n console.log(xhr.status + ' ' + xhr.statusText + '---' + textStatus);\n console.log(textStatus);\n\n alert(\n 'Unknown error. Please get in contact with us to solve it support@wp-staging.com',\n );\n },\n success: function(data) {\n jQuery('.wpstg_fivestar').slideUp('fast');\n return true;\n },\n statusCode: {\n 404: function() {\n alert('Something went wrong; can\\'t find ajax request URL! Please get in contact with us to solve it support@wp-staging.com');\n },\n 500: function() {\n alert('Something went wrong; internal server error while processing the request! Please get in contact with us to solve it support@wp-staging.com');\n },\n },\n });\n });\n}\n\ndocument.styleSheets[0].insertRule('@media only screen and (max-width:600px){.wpstg-welcome-box{display:block !important}.wpstg-welcome-video-container{width:100% !important;height:auto !important}.wpstg-welcome-text{padding-left:8px !important}}', '');\n\ndocument.addEventListener('DOMContentLoaded', function() {\n let player;\n let accepted = wpstgYouTubeConfig.accepted;\n const playerPlaceholder = document.getElementById('welcomeNoticeFree');\n playerPlaceholder.addEventListener('click', function() {\n if (!accepted) {\n const message = wpstgYouTubeConfig.message + '\\n \\n' + wpstgYouTubeConfig.regards;\n const conf = confirm(message);\n if (conf) {\n accepted = true;\n wpstgFetchVideo();\n }\n }\n });\n});\n\nfunction wpstgFetchVideo() {\n const tag = document.createElement('script');\n\n tag.src = 'https://www.youtube.com/iframe_api';\n const firstScriptTag = document.getElementsByTagName('script')[0];\n firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);\n}\n\nfunction onYouTubeIframeAPIReady() {\n player = new YT.Player('welcomeNoticeFree', {\n height: '225',\n width: '400',\n videoId: 'fsC9ZvbRQ5Y',\n playerVars: {\n rel: 0,\n showinfo: 0,\n ecver: 2,\n },\n events: {\n 'onReady': onPlayerReady,\n },\n });\n}\n\nfunction onPlayerReady(event) {\n event.target.playVideo();\n}\n"],"names":["wpstgTimesWaited","wpstgWaitForJQuery","setInterval","clearInterval","jQuery","wpstgRegisterRatingEvents","show","document","on","e","ajax","url","ajaxurl","type","data","action","error","xhr","textStatus","errorThrown","console","log","status","statusText","alert","success","slideUp","statusCode","preventDefault","styleSheets","insertRule","addEventListener","accepted","wpstgYouTubeConfig","playerPlaceholder","getElementById","message","regards","conf","confirm","wpstgFetchVideo","tag","createElement","src","firstScriptTag","getElementsByTagName","parentNode","insertBefore"],"mappings":"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"}
assets/js/dist/wpstg-admin-rating.min.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ !function(){"use strict";var t=0,e=setInterval((function(){t>100&&clearInterval(e),"undefined"!=typeof jQuery&&(jQuery(".wpstg_fivestar").show(),jQuery(document).on("click","#wpstg_clicked_deserved_it",(function(t){jQuery.ajax({url:ajaxurl,type:"POST",data:{action:"wpstg_hide_rating"},error:function(t,e,n){console.log(t.status+" "+t.statusText+"---"+e),console.log(e),alert("Unknown error. Please get in contact with us to solve it support@wp-staging.com")},success:function(t){return jQuery(".wpstg_fivestar").slideUp("fast"),!0},statusCode:{404:function(){alert("Something went wrong; can't find ajax request URL! Please get in contact with us to solve it support@wp-staging.com")},500:function(){alert("Something went wrong; internal server error while processing the request! Please get in contact with us to solve it support@wp-staging.com")}}})})),jQuery(".wpstg_hide_rating").on("click",(function(t){t.preventDefault(),jQuery.ajax({url:ajaxurl,type:"POST",data:{action:"wpstg_hide_rating"},error:function(t,e,n){console.log(t.status+" "+t.statusText+"---"+e),console.log(e),alert("Unknown error. Please get in contact with us to solve it support@wp-staging.com")},success:function(t){return jQuery(".wpstg_fivestar").slideUp("fast"),!0},statusCode:{404:function(){alert("Something went wrong; can't find ajax request URL! Please get in contact with us to solve it support@wp-staging.com")},500:function(){alert("Something went wrong; internal server error while processing the request! Please get in contact with us to solve it support@wp-staging.com")}}})})),jQuery(".wpstg_rate_later").on("click",(function(t){t.preventDefault(),jQuery.ajax({url:ajaxurl,type:"POST",data:{action:"wpstg_hide_later"},error:function(t,e,n){console.log(t.status+" "+t.statusText+"---"+e),console.log(e),alert("Unknown error. Please get in contact with us to solve it support@wp-staging.com")},success:function(t){return jQuery(".wpstg_fivestar").slideUp("fast"),!0},statusCode:{404:function(){alert("Something went wrong; can't find ajax request URL! Please get in contact with us to solve it support@wp-staging.com")},500:function(){alert("Something went wrong; internal server error while processing the request! Please get in contact with us to solve it support@wp-staging.com")}}})})),clearInterval(e)),t+=1}),100);document.styleSheets[0].insertRule("@media only screen and (max-width:600px){.wpstg-welcome-box{display:block !important}.wpstg-welcome-video-container{width:100% !important;height:auto !important}.wpstg-welcome-text{padding-left:8px !important}}",""),document.addEventListener("DOMContentLoaded",(function(){var t=wpstgYouTubeConfig.accepted;document.getElementById("welcomeNoticeFree").addEventListener("click",(function(){if(!t){var e=wpstgYouTubeConfig.message+"\n \n"+wpstgYouTubeConfig.regards;confirm(e)&&(t=!0,function(){var t=document.createElement("script");t.src="https://www.youtube.com/iframe_api";var e=document.getElementsByTagName("script")[0];e.parentNode.insertBefore(t,e)}())}}))}))}();
2
+ //# sourceMappingURL=wpstg-admin-rating.min.js.map
assets/js/dist/wpstg-admin-rating.min.js.map ADDED
@@ -0,0 +1 @@
 
1
+ {"version":3,"file":"wpstg-admin-rating.min.js","sources":["../src/wpstg-admin-rating.js"],"sourcesContent":["let wpstgTimesWaited = 0;\n\n/*\nLet's wait for jQuery to be available to show the rating.\nWe need it to dispatch AJAX requests.\n */\nvar wpstgWaitForJQuery = setInterval(function() {\n if (wpstgTimesWaited > 100) {\n // Give up waiting.\n clearInterval(wpstgWaitForJQuery);\n }\n if (typeof jQuery != 'undefined') {\n wpstgRegisterRatingEvents();\n\n clearInterval(wpstgWaitForJQuery);\n }\n wpstgTimesWaited = wpstgTimesWaited + 1;\n}, 100);\n\nfunction wpstgRegisterRatingEvents() {\n // Show the rating once jQuery is loaded.\n jQuery('.wpstg_fivestar').show();\n\n /**\n * Dispatch the request to hide the video after user clicks to rate the plugin.\n */\n jQuery(document).on('click', '#wpstg_clicked_deserved_it', function(e) {\n jQuery.ajax({\n url: ajaxurl,\n type: 'POST',\n data: {action: 'wpstg_hide_rating'},\n error: function(xhr, textStatus, errorThrown) {\n console.log(xhr.status + ' ' + xhr.statusText + '---' + textStatus);\n console.log(textStatus);\n\n alert(\n 'Unknown error. Please get in contact with us to solve it support@wp-staging.com',\n );\n },\n success: function(data) {\n jQuery('.wpstg_fivestar').slideUp('fast');\n return true;\n },\n statusCode: {\n 404: function() {\n alert('Something went wrong; can\\'t find ajax request URL! Please get in contact with us to solve it support@wp-staging.com');\n },\n 500: function() {\n alert('Something went wrong; internal server error while processing the request! Please get in contact with us to solve it support@wp-staging.com');\n },\n },\n });\n });\n\n jQuery('.wpstg_hide_rating').on('click', function(e) {\n e.preventDefault();\n\n jQuery.ajax({\n url: ajaxurl,\n type: 'POST',\n data: {action: 'wpstg_hide_rating'},\n error: function(xhr, textStatus, errorThrown) {\n console.log(xhr.status + ' ' + xhr.statusText + '---' + textStatus);\n console.log(textStatus);\n\n alert(\n 'Unknown error. Please get in contact with us to solve it support@wp-staging.com',\n );\n },\n success: function(data) {\n jQuery('.wpstg_fivestar').slideUp('fast');\n return true;\n },\n statusCode: {\n 404: function() {\n alert('Something went wrong; can\\'t find ajax request URL! Please get in contact with us to solve it support@wp-staging.com');\n },\n 500: function() {\n alert('Something went wrong; internal server error while processing the request! Please get in contact with us to solve it support@wp-staging.com');\n },\n },\n });\n });\n\n jQuery('.wpstg_rate_later').on('click', function(e) {\n e.preventDefault();\n\n jQuery.ajax({\n url: ajaxurl,\n type: 'POST',\n data: {action: 'wpstg_hide_later'},\n error: function(xhr, textStatus, errorThrown) {\n console.log(xhr.status + ' ' + xhr.statusText + '---' + textStatus);\n console.log(textStatus);\n\n alert(\n 'Unknown error. Please get in contact with us to solve it support@wp-staging.com',\n );\n },\n success: function(data) {\n jQuery('.wpstg_fivestar').slideUp('fast');\n return true;\n },\n statusCode: {\n 404: function() {\n alert('Something went wrong; can\\'t find ajax request URL! Please get in contact with us to solve it support@wp-staging.com');\n },\n 500: function() {\n alert('Something went wrong; internal server error while processing the request! Please get in contact with us to solve it support@wp-staging.com');\n },\n },\n });\n });\n}\n\ndocument.styleSheets[0].insertRule('@media only screen and (max-width:600px){.wpstg-welcome-box{display:block !important}.wpstg-welcome-video-container{width:100% !important;height:auto !important}.wpstg-welcome-text{padding-left:8px !important}}', '');\n\ndocument.addEventListener('DOMContentLoaded', function() {\n let player;\n let accepted = wpstgYouTubeConfig.accepted;\n const playerPlaceholder = document.getElementById('welcomeNoticeFree');\n playerPlaceholder.addEventListener('click', function() {\n if (!accepted) {\n const message = wpstgYouTubeConfig.message + '\\n \\n' + wpstgYouTubeConfig.regards;\n const conf = confirm(message);\n if (conf) {\n accepted = true;\n wpstgFetchVideo();\n }\n }\n });\n});\n\nfunction wpstgFetchVideo() {\n const tag = document.createElement('script');\n\n tag.src = 'https://www.youtube.com/iframe_api';\n const firstScriptTag = document.getElementsByTagName('script')[0];\n firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);\n}\n\nfunction onYouTubeIframeAPIReady() {\n player = new YT.Player('welcomeNoticeFree', {\n height: '225',\n width: '400',\n videoId: 'fsC9ZvbRQ5Y',\n playerVars: {\n rel: 0,\n showinfo: 0,\n ecver: 2,\n },\n events: {\n 'onReady': onPlayerReady,\n },\n });\n}\n\nfunction onPlayerReady(event) {\n event.target.playVideo();\n}\n"],"names":["wpstgTimesWaited","wpstgWaitForJQuery","setInterval","clearInterval","jQuery","show","document","on","e","ajax","url","ajaxurl","type","data","action","error","xhr","textStatus","errorThrown","console","log","status","statusText","alert","success","slideUp","statusCode","preventDefault","styleSheets","insertRule","addEventListener","accepted","wpstgYouTubeConfig","getElementById","message","regards","confirm","tag","createElement","src","firstScriptTag","getElementsByTagName","parentNode","insertBefore","wpstgFetchVideo"],"mappings":"yBAAA,IAAIA,EAAmB,EAMnBC,EAAqBC,aAAY,WAC/BF,EAAmB,KAErBG,cAAcF,GAEK,oBAAVG,SAUXA,OAAO,mBAAmBC,OAK1BD,OAAOE,UAAUC,GAAG,QAAS,8BAA8B,SAASC,GAClEJ,OAAOK,KAAK,CACVC,IAAKC,QACLC,KAAM,OACNC,KAAM,CAACC,OAAQ,qBACfC,MAAO,SAASC,EAAKC,EAAYC,GAC/BC,QAAQC,IAAIJ,EAAIK,OAAS,IAAML,EAAIM,WAAa,MAAQL,GACxDE,QAAQC,IAAIH,GAEZM,MACI,oFAGNC,QAAS,SAASX,UAChBT,OAAO,mBAAmBqB,QAAQ,SAC3B,GAETC,WAAY,KACL,WACHH,MAAM,4HAEH,WACHA,MAAM,qJAMdnB,OAAO,sBAAsBG,GAAG,SAAS,SAASC,GAChDA,EAAEmB,iBAEFvB,OAAOK,KAAK,CACVC,IAAKC,QACLC,KAAM,OACNC,KAAM,CAACC,OAAQ,qBACfC,MAAO,SAASC,EAAKC,EAAYC,GAC/BC,QAAQC,IAAIJ,EAAIK,OAAS,IAAML,EAAIM,WAAa,MAAQL,GACxDE,QAAQC,IAAIH,GAEZM,MACI,oFAGNC,QAAS,SAASX,UAChBT,OAAO,mBAAmBqB,QAAQ,SAC3B,GAETC,WAAY,KACL,WACHH,MAAM,4HAEH,WACHA,MAAM,qJAMdnB,OAAO,qBAAqBG,GAAG,SAAS,SAASC,GAC/CA,EAAEmB,iBAEFvB,OAAOK,KAAK,CACVC,IAAKC,QACLC,KAAM,OACNC,KAAM,CAACC,OAAQ,oBACfC,MAAO,SAASC,EAAKC,EAAYC,GAC/BC,QAAQC,IAAIJ,EAAIK,OAAS,IAAML,EAAIM,WAAa,MAAQL,GACxDE,QAAQC,IAAIH,GAEZM,MACI,oFAGNC,QAAS,SAASX,UAChBT,OAAO,mBAAmBqB,QAAQ,SAC3B,GAETC,WAAY,KACL,WACHH,MAAM,4HAEH,WACHA,MAAM,qJA9FZpB,cAAcF,IAEhBD,GAAsC,IACrC,KAkGHM,SAASsB,YAAY,GAAGC,WAAW,qNAAsN,IAEzPvB,SAASwB,iBAAiB,oBAAoB,eAExCC,EAAWC,mBAAmBD,SACRzB,SAAS2B,eAAe,qBAChCH,iBAAiB,SAAS,eACrCC,EAAU,KACPG,EAAUF,mBAAmBE,QAAU,QAAUF,mBAAmBG,QAC7DC,QAAQF,KAEnBH,GAAW,EAOnB,eACQM,EAAM/B,SAASgC,cAAc,UAEnCD,EAAIE,IAAM,yCACJC,EAAiBlC,SAASmC,qBAAqB,UAAU,GAC/DD,EAAeE,WAAWC,aAAaN,EAAKG,GAXtCI"}
assets/js/dist/wpstg-admin.js CHANGED
@@ -1,2837 +1,3913 @@
1
- function _createForOfIteratorHelperLoose(o, allowArrayLike) { var it; if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; return function () { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } it = o[Symbol.iterator](); return it.next.bind(it); }
2
-
3
- function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
4
-
5
- function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
 
 
 
 
 
 
6
 
7
- function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
 
 
 
 
 
8
 
9
- function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
 
 
 
 
 
10
 
11
- import WpstgCloneStaging from './wpstg-clone-staging.js';
 
 
12
 
13
- var WPStaging = function ($) {
14
- var that = {
15
- isCancelled: false,
16
- isFinished: false,
17
- getLogs: false,
18
- time: 1,
19
- executionTime: false,
20
- progressBar: 0
21
- };
22
- var cache = {
23
- elements: []
24
- };
25
- var timeout;
26
- var ajaxSpinner;
27
- /**
28
- * Get / Set Cache for Selector
29
- * @param {String} selector
30
- * @return {*}
31
- */
32
 
33
- cache.get = function (selector) {
34
- // It is already cached!
35
- if ($.inArray(selector, cache.elements) !== -1) {
36
- return cache.elements[selector];
37
- } // Create cache and return
38
 
 
 
 
 
39
 
40
- cache.elements[selector] = jQuery(selector);
41
- return cache.elements[selector];
42
- };
43
- /**
44
- * Refreshes given cache
45
- * @param {String} selector
46
- */
47
 
 
 
48
 
49
- cache.refresh = function (selector) {
50
- selector.elements[selector] = jQuery(selector);
51
- };
52
- /**
53
- * Show and Log Error Message
54
- * @param {String} message
55
- */
56
 
 
 
 
 
 
 
 
 
57
 
58
- var showError = function showError(message) {
59
- cache.get('#wpstg-try-again').css('display', 'inline-block');
60
- cache.get('#wpstg-cancel-cloning').text('Reset');
61
- cache.get('#wpstg-resume-cloning').show();
62
- cache.get('#wpstg-error-wrapper').show();
63
- cache.get('#wpstg-error-details').show().html(message);
64
- cache.get('#wpstg-removing-clone').removeClass('loading');
65
- cache.get('.wpstg-loader').hide();
66
- $('.wpstg--modal--process--generic-problem').show().html(message);
67
- };
68
- /**
69
- * Show warning during cloning or push process when closing tab or browser, or changing page
70
- * @param {beforeunload} event
71
- * @return {null}
72
- */
73
 
 
74
 
75
- var warnIfClosingDuringProcess = function warnIfClosingDuringProcess(event) {
76
- // Only some browsers show the message below, most say something like "Changes you made may not be saved" (Chrome) or "You have unsaved changes. Exit?"
77
- event.returnValue = 'You MUST leave this window open while cloning/pushing. Please wait...';
78
- return null;
79
- };
80
- /**
81
- *
82
- * @param obj
83
- * @return {boolean}
84
- */
85
 
 
 
86
 
87
- function isEmpty(obj) {
88
- for (var prop in obj) {
89
- if (obj.hasOwnProperty(prop)) {
90
- return false;
 
 
 
 
 
 
 
 
 
91
  }
 
 
92
  }
93
 
94
- return true;
 
95
  }
 
96
  /**
97
- *
98
- * @param response the error object
99
- * @param prependMessage Overwrite default error message at beginning
100
- * @param appendMessage Overwrite default error message at end
101
- * @returns void
102
- */
103
 
 
 
 
 
 
 
 
 
 
 
 
104
 
105
- var showAjaxFatalError = function showAjaxFatalError(response, prependMessage, appendMessage) {
106
- prependMessage = prependMessage ? prependMessage + '<br/><br/>' : 'Something went wrong! <br/><br/>';
107
- appendMessage = appendMessage ? appendMessage + '<br/><br/>' : '<br/><br/>Please try the <a href=\'https://wp-staging.com/docs/wp-staging-settings-for-small-servers/\' target=\'_blank\'>WP Staging Small Server Settings</a> or submit an error report and contact us.';
 
 
 
108
 
109
- if (response === false) {
110
- showError(prependMessage + ' Error: No response.' + appendMessage);
111
- window.removeEventListener('beforeunload', warnIfClosingDuringProcess);
112
- return;
 
 
 
 
 
 
113
  }
114
 
115
- if (typeof response.error !== 'undefined' && response.error) {
116
- console.error(response.message);
117
- showError(prependMessage + ' Error: ' + response.message + appendMessage);
118
- window.removeEventListener('beforeunload', warnIfClosingDuringProcess);
119
- return;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
  }
121
- };
122
- /**
123
- *
124
- * @param response
125
- * @return {{ok}|*}
126
- */
127
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
128
 
129
- var handleFetchErrors = function handleFetchErrors(response) {
130
- if (!response.ok) {
131
- showError('Error: ' + response.status + ' - ' + response.statusText + '. Please try again or contact support.');
132
- }
133
 
134
- return response;
135
- };
136
- /** Hide and reset previous thrown visible errors */
 
 
137
 
 
 
 
 
 
138
 
139
- var resetErrors = function resetErrors() {
140
- cache.get('#wpstg-error-details').hide().html('');
141
- };
142
 
143
- var slugify = function slugify(url) {
144
- return url.toString().toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g, '').replace(/\s+/g, '-').replace(/&/g, '-and-').replace(/[^a-z0-9\-]/g, '').replace(/-+/g, '-').replace(/^-*/, '').replace(/-*$/, '');
145
- };
146
  /**
147
- * Common Elements
148
- */
149
 
 
 
 
 
 
150
 
151
- var elements = function elements() {
152
- var $workFlow = cache.get('#wpstg-workflow');
153
- var isAllChecked = true;
154
- var urlSpinner = ajaxurl.replace('/admin-ajax.php', '') + '/images/spinner';
155
- var timer;
156
 
157
- if (2 < window.devicePixelRatio) {
158
- urlSpinner += '-2x';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
159
  }
160
 
161
- urlSpinner += '.gif';
162
- ajaxSpinner = '<img src=\'\'' + urlSpinner + '\' alt=\'\' class=\'ajax-spinner general-spinner\' />';
163
 
164
- var getBaseValues = function getBaseValues() {
165
- var path = $('#wpstg-use-target-dir').data('base-path');
166
- var uri = $('#wpstg-use-target-hostname').data('base-uri');
167
- return {
168
- path: path
169
- };
 
 
 
 
170
  };
171
 
172
- $workFlow // Check / Un-check All Database Tables New
173
- .on('click', '.wpstg-button-unselect', function (e) {
174
- e.preventDefault();
175
 
176
- if (false === isAllChecked) {
177
- console.log('true');
178
- cache.get('#wpstg_select_tables_cloning .wpstg-db-table').prop('selected', 'selected');
179
- cache.get('.wpstg-button-unselect').text('Unselect All');
180
- cache.get('.wpstg-db-table-checkboxes').prop('checked', true);
181
- isAllChecked = true;
182
- } else {
183
- console.log('false');
184
- cache.get('#wpstg_select_tables_cloning .wpstg-db-table').prop('selected', false);
185
- cache.get('.wpstg-button-unselect').text('Select All');
186
- cache.get('.wpstg-db-table-checkboxes').prop('checked', false);
187
- isAllChecked = false;
188
- }
189
- })
190
- /**
191
- * Select tables with certain tbl prefix | NEW
192
- * @param obj e
193
- * @returns {undefined}
194
- */
195
- .on('click', '.wpstg-button-select', function (e) {
196
- e.preventDefault();
197
- $('#wpstg_select_tables_cloning .wpstg-db-table').each(function () {
198
- if (wpstg.isMultisite == 1) {
199
- if ($(this).attr('name').match('^' + wpstg.tblprefix + '([^0-9])_*')) {
200
- $(this).prop('selected', 'selected');
201
- } else {
202
- $(this).prop('selected', false);
203
- }
204
  }
205
-
206
- if (wpstg.isMultisite == 0) {
207
- if ($(this).attr('name').match('^' + wpstg.tblprefix)) {
208
- $(this).prop('selected', 'selected');
209
- } else {
210
- $(this).prop('selected', false);
211
- }
212
  }
213
- });
214
- }) // Expand Directories
215
- .on('click', '.wpstg-expand-dirs', function (e) {
216
- e.preventDefault();
217
- var $this = $(this);
218
 
219
- if (!$this.hasClass('disabled')) {
220
- $this.siblings('.wpstg-subdir').slideToggle();
221
- }
222
- }) // When a directory checkbox is Selected
223
- .on('change', 'input.wpstg-check-dir', function () {
224
- var $directory = $(this).parent('.wpstg-dir');
 
225
 
226
- if (this.checked) {
227
- $directory.parents('.wpstg-dir').children('.wpstg-check-dir').prop('checked', true);
228
- $directory.find('.wpstg-expand-dirs').removeClass('disabled');
229
- $directory.find('.wpstg-subdir .wpstg-check-dir').prop('checked', true);
230
- } else {
231
- $directory.find('.wpstg-dir .wpstg-check-dir').prop('checked', false);
232
- $directory.find('.wpstg-expand-dirs, .wpstg-check-subdirs').addClass('disabled');
233
- $directory.find('.wpstg-check-subdirs').data('action', 'check').text('check');
234
- }
235
- }) // When a directory name is Selected
236
- .on('change', 'href.wpstg-check-dir', function () {
237
- var $directory = $(this).parent('.wpstg-dir');
238
-
239
- if (this.checked) {
240
- $directory.parents('.wpstg-dir').children('.wpstg-check-dir').prop('checked', true);
241
- $directory.find('.wpstg-expand-dirs').removeClass('disabled');
242
- $directory.find('.wpstg-subdir .wpstg-check-dir').prop('checked', true);
243
- } else {
244
- $directory.find('.wpstg-dir .wpstg-check-dir').prop('checked', false);
245
- $directory.find('.wpstg-expand-dirs, .wpstg-check-subdirs').addClass('disabled');
246
- $directory.find('.wpstg-check-subdirs').data('action', 'check').text('check');
247
- }
248
- }) // Check the max length of the clone name and if the clone name already exists
249
- .on('keyup', '#wpstg-new-clone-id', function () {
250
- // Hide previous errors
251
- document.getElementById('wpstg-error-details').style.display = 'none'; // This request was already sent, clear it up!
252
 
253
- if ('number' === typeof timer) {
254
- clearInterval(timer);
255
- }
256
 
257
- var cloneID = this.value;
258
- timer = setTimeout(function () {
259
- ajax({
260
- action: 'wpstg_check_clone',
261
- accessToken: wpstg.accessToken,
262
- nonce: wpstg.nonce,
263
- cloneID: cloneID
264
- }, function (response) {
265
- if (response.status === 'success') {
266
- cache.get('#wpstg-new-clone-id').removeClass('wpstg-error-input');
267
- cache.get('#wpstg-start-cloning').removeAttr('disabled');
268
- cache.get('#wpstg-clone-id-error').text('').hide();
269
- } else {
270
- cache.get('#wpstg-new-clone-id').addClass('wpstg-error-input');
271
- cache.get('#wpstg-start-cloning').prop('disabled', true);
272
- cache.get('#wpstg-clone-id-error').text(response.message).show();
273
- }
274
- });
275
- }, 500);
276
- }) // Restart cloning process
277
- .on('click', '#wpstg-start-cloning', function () {
278
- resetErrors();
279
- that.isCancelled = false;
280
- that.getLogs = false;
281
- that.progressBar = 0;
282
- }).on('input', '#wpstg-new-clone-id', function () {
283
- if ($('#wpstg-clone-directory').length < 1) {
284
- return;
285
- }
286
 
287
- var slug = slugify(this.value);
288
- var $targetDir = $('#wpstg-use-target-dir');
289
- var $targetUri = $('#wpstg-use-target-hostname');
290
- var path = $targetDir.data('base-path');
291
- var uri = $targetUri.data('base-uri');
292
 
293
- if (path) {
294
- path = path.replace(/\/+$/g, '') + '/' + slug + '/';
295
- }
296
 
297
- if (uri) {
298
- uri = uri.replace(/\/+$/g, '') + '/' + slug;
299
- }
300
 
301
- $('.wpstg-use-target-dir--value').text(path);
302
- $('.wpstg-use-target-hostname--value').text(uri);
303
- $targetDir.attr('data-path', path);
304
- $targetUri.attr('data-uri', uri);
305
- $('#wpstg_clone_dir').attr('placeholder', path);
306
- $('#wpstg_clone_hostname').attr('placeholder', uri);
307
- }).on('input', '#wpstg_clone_hostname', function () {
308
- if ($(this).val() === '' || validateTargetHost()) {
309
- $('#wpstg_clone_hostname_error').remove();
310
- return;
311
  }
312
 
313
- if (!validateTargetHost() && !$('#wpstg_clone_hostname_error').length) {
314
- $('#wpstg-clone-directory tr:last-of-type').after('<tr><td>&nbsp;</td><td><p id="wpstg_clone_hostname_error" style="color: red;">&nbsp;Invalid host name. Please provide it in a format like http://example.com</p></td></tr>');
315
  }
316
- });
317
- cloneActions();
318
- };
319
- /* @returns {boolean} */
320
-
321
-
322
- var validateTargetHost = function validateTargetHost() {
323
- var the_domain = $('#wpstg_clone_hostname').val();
324
 
325
- if (the_domain === '') {
326
- return true;
327
- }
328
-
329
- var reg = /^http(s)?:\/\/.*$/;
330
 
331
- if (reg.test(the_domain) === false) {
332
- return false;
 
 
 
 
 
 
 
 
 
 
 
 
 
333
  }
334
 
335
- return true;
336
- };
337
- /**
338
- * Clone actions
339
- */
340
 
 
 
341
 
342
- var cloneActions = function cloneActions() {
343
- var $workFlow = cache.get('#wpstg-workflow');
344
- $workFlow // Cancel cloning
345
- .on('click', '#wpstg-cancel-cloning', function () {
346
- if (!confirm('Are you sure you want to cancel cloning process?')) {
347
- return false;
348
  }
349
 
350
- var $this = $(this);
351
- $('#wpstg-try-again, #wpstg-home-link').hide();
352
- $this.prop('disabled', true);
353
- that.isCancelled = true;
354
- that.progressBar = 0;
355
- $('#wpstg-processing-status').text('Please wait...this can take up a while.');
356
- $('.wpstg-loader, #wpstg-show-log-button').hide();
357
- $this.parent().append(ajaxSpinner);
358
- cancelCloning();
359
- }) // Resume cloning
360
- .on('click', '#wpstg-resume-cloning', function () {
361
- resetErrors();
362
- var $this = $(this);
363
- $('#wpstg-try-again, #wpstg-home-link').hide();
364
- that.isCancelled = false;
365
- $('#wpstg-processing-status').text('Try to resume cloning process...');
366
- $('#wpstg-error-details').hide();
367
- $('.wpstg-loader').show();
368
- $this.parent().append(ajaxSpinner);
369
- that.startCloning();
370
- }) // Cancel update cloning
371
- .on('click', '#wpstg-cancel-cloning-update', function () {
372
- resetErrors();
373
- var $this = $(this);
374
- $('#wpstg-try-again, #wpstg-home-link').hide();
375
- $this.prop('disabled', true);
376
- that.isCancelled = true;
377
- $('#wpstg-cloning-result').text('Please wait...this can take up a while.');
378
- $('.wpstg-loader, #wpstg-show-log-button').hide();
379
- $this.parent().append(ajaxSpinner);
380
- cancelCloningUpdate();
381
- }) // Restart cloning
382
- .on('click', '#wpstg-restart-cloning', function () {
383
- resetErrors();
384
- var $this = $(this);
385
- $('#wpstg-try-again, #wpstg-home-link').hide();
386
- $this.prop('disabled', true);
387
- that.isCancelled = true;
388
- $('#wpstg-cloning-result').text('Please wait...this can take up a while.');
389
- $('.wpstg-loader, #wpstg-show-log-button').hide();
390
- $this.parent().append(ajaxSpinner);
391
- restart();
392
- }) // Delete clone - confirmation
393
- .on('click', '.wpstg-remove-clone[data-clone]', function (e) {
394
- resetErrors();
395
- e.preventDefault();
396
- var $existingClones = cache.get('#wpstg-existing-clones');
397
- $workFlow.removeClass('active');
398
- cache.get('.wpstg-loader').show();
399
- ajax({
400
- action: 'wpstg_confirm_delete_clone',
401
- accessToken: wpstg.accessToken,
402
- nonce: wpstg.nonce,
403
- clone: $(this).data('clone')
404
- }, function (response) {
405
- cache.get('#wpstg-removing-clone').html(response);
406
- $existingClones.children('img').remove();
407
- cache.get('.wpstg-loader').hide();
408
- $('html, body').animate({
409
- // This logic is meant to be a "scrollBottom"
410
- scrollTop: $('#wpstg-remove-clone').offset().top - $(window).height() + $('#wpstg-remove-clone').height() + 50
411
- }, 100);
412
- }, 'HTML');
413
- }) // Delete clone - confirmed
414
- .on('click', '#wpstg-remove-clone', function (e) {
415
- resetErrors();
416
- e.preventDefault();
417
- cache.get('#wpstg-removing-clone').addClass('loading');
418
- cache.get('.wpstg-loader').show();
419
- deleteClone($(this).data('clone'));
420
- }) // Cancel deleting clone
421
- .on('click', '#wpstg-cancel-removing', function (e) {
422
- e.preventDefault();
423
- $('.wpstg-clone').removeClass('active');
424
- cache.get('#wpstg-removing-clone').html('');
425
- }) // Update
426
- .on('click', '.wpstg-execute-clone', function (e) {
427
- e.preventDefault();
428
- var clone = $(this).data('clone');
429
- $workFlow.addClass('loading');
430
- ajax({
431
- action: 'wpstg_scanning',
432
- clone: clone,
433
- accessToken: wpstg.accessToken,
434
- nonce: wpstg.nonce
435
- }, function (response) {
436
- if (response.length < 1) {
437
- showError('Something went wrong! Error: No response. Please try the <a href=\'https://wp-staging.com/docs/wp-staging-settings-for-small-servers/\' target=\'_blank\'>WP Staging Small Server Settings</a> or submit an error report and contact us.');
438
- }
439
-
440
- $workFlow.removeClass('loading').html(response); // register check disk space function for clone update process.
441
 
442
- checkDiskSpace();
443
- that.switchStep(2);
444
- }, 'HTML');
445
- }) // Reset Clone
446
- .on('click', '.wpstg-reset-clone', function (e) {
447
- e.preventDefault();
448
- var clone = $(this).data('clone');
449
- Swal.fire({
450
- title: '',
451
- icon: 'warning',
452
- html: 'Do you really want to reset this staging site with the current state of the production site? <br> <span style="color:red;">This will delete all your modifications!</span>',
453
- width: '650px',
454
- focusConfirm: false,
455
- customClass: {
456
- confirmButton: 'wpstg-confirm-reset-clone'
457
- },
458
- confirmButtonText: 'Reset Clone',
459
- showCancelButton: true
460
- }).then(function (result) {
461
- if (result.value) {
462
- resetClone(clone);
463
  }
464
  });
465
- return;
466
- });
467
- };
468
- /**
469
- * Ajax Requests
470
- * @param Object data
471
- * @param Function callback
472
- * @param string dataType
473
- * @param bool showErrors
474
- * @param int tryCount
475
- * @param float incrementRatio
476
- */
477
-
478
 
479
- var ajax = function ajax(data, callback, dataType, showErrors, tryCount, incrementRatio) {
480
- if (incrementRatio === void 0) {
481
- incrementRatio = null;
482
  }
 
 
 
 
 
 
 
483
 
484
- if ('undefined' === typeof dataType) {
485
- dataType = 'json';
486
- }
 
487
 
488
- if (false !== showErrors) {
489
- showErrors = true;
490
- }
491
 
492
- tryCount = 'undefined' === typeof tryCount ? 0 : tryCount;
493
- var retryLimit = 10;
494
- var retryTimeout = 10000 * tryCount;
495
- incrementRatio = parseInt(incrementRatio);
496
 
497
- if (!isNaN(incrementRatio)) {
498
- retryTimeout *= incrementRatio;
499
- }
500
 
501
- $.ajax({
502
- url: ajaxurl + '?action=wpstg_processing&_=' + Date.now() / 1000,
503
- type: 'POST',
504
- dataType: dataType,
505
- cache: false,
506
- data: data,
507
- error: function error(xhr, textStatus, errorThrown) {
508
- console.log(xhr.status + ' ' + xhr.statusText + '---' + textStatus); // try again after 10 seconds
509
 
510
- tryCount++;
 
 
511
 
512
- if (tryCount <= retryLimit) {
513
- setTimeout(function () {
514
- ajax(data, callback, dataType, showErrors, tryCount, incrementRatio);
515
- return;
516
- }, retryTimeout);
517
- } else {
518
- var errorCode = 'undefined' === typeof xhr.status ? 'Unknown' : xhr.status;
519
- showError('Fatal Error: ' + errorCode + ' Please try the <a href=\'https://wp-staging.com/docs/wp-staging-settings-for-small-servers/\' target=\'_blank\'>WP Staging Small Server Settings</a> or submit an error report and contact us.');
520
- }
521
- },
522
- success: function success(data) {
523
- if ('function' === typeof callback) {
524
- callback(data);
525
  }
526
- },
527
- statusCode: {
528
- 404: function _() {
529
- if (tryCount >= retryLimit) {
530
- showError('Error 404 - Can\'t find ajax request URL! Please try the <a href=\'https://wp-staging.com/docs/wp-staging-settings-for-small-servers/\' target=\'_blank\'>WP Staging Small Server Settings</a> or submit an error report and contact us.');
531
- }
532
- },
533
- 500: function _() {
534
- if (tryCount >= retryLimit) {
535
- showError('Fatal Error 500 - Internal server error while processing the request! Please try the <a href=\'https://wp-staging.com/docs/wp-staging-settings-for-small-servers/\' target=\'_blank\'>WP Staging Small Server Settings</a> or submit an error report and contact us.');
536
- }
537
- },
538
- 504: function _() {
539
- if (tryCount > retryLimit) {
540
- showError('Error 504 - It looks like your server is rate limiting ajax requests. Please try to resume after a minute. If this still not works try the <a href=\'https://wp-staging.com/docs/wp-staging-settings-for-small-servers/\' target=\'_blank\'>WP Staging Small Server Settings</a> or submit an error report and contact us.\n\ ');
541
- }
542
- },
543
- 502: function _() {
544
- if (tryCount >= retryLimit) {
545
- showError('Error 502 - It looks like your server is rate limiting ajax requests. Please try to resume after a minute. If this still not works try the <a href=\'https://wp-staging.com/docs/wp-staging-settings-for-small-servers/\' target=\'_blank\'>WP Staging Small Server Settings</a> or submit an error report and contact us.\n\ ');
546
- }
547
- },
548
- 503: function _() {
549
- if (tryCount >= retryLimit) {
550
- showError('Error 503 - It looks like your server is rate limiting ajax requests. Please try to resume after a minute. If this still not works try the <a href=\'https://wp-staging.com/docs/wp-staging-settings-for-small-servers/\' target=\'_blank\'>WP Staging Small Server Settings</a> or submit an error report and contact us.\n\ ');
551
- }
552
- },
553
- 429: function _() {
554
- if (tryCount >= retryLimit) {
555
- showError('Error 429 - It looks like your server is rate limiting ajax requests. Please try to resume after a minute. If this still not works try the <a href=\'https://wp-staging.com/docs/wp-staging-settings-for-small-servers/\' target=\'_blank\'>WP Staging Small Server Settings</a> or submit an error report and contact us.\n\ ');
556
- }
557
- },
558
- 403: function _() {
559
- if (tryCount >= retryLimit) {
560
- showError('Refresh page or login again! The process should be finished successfully. \n\ ');
561
- }
562
  }
563
- }
564
- });
565
- };
566
- /**
567
- * Next / Previous Step Clicks to Navigate Through Staging Job
568
- */
569
 
 
 
 
 
570
 
571
- var stepButtons = function stepButtons() {
572
- var $workFlow = cache.get('#wpstg-workflow');
573
- $workFlow // Next Button
574
- .on('click', '.wpstg-next-step-link', function (e) {
575
- e.preventDefault();
576
- var $this = $(this);
577
- var isScan = false;
578
 
579
- if ($('#wpstg_clone_hostname').length && !validateTargetHost()) {
580
- $('#wpstg_clone_hostname').focus();
581
- return false;
582
- }
583
 
584
- if ($this.data('action') === 'wpstg_update' || $this.data('action') === 'wpstg_reset') {
585
- // Update / Reset Clone - confirmed
586
- var onlyUpdateMessage = '';
587
 
588
- if ($this.data('action') === 'wpstg_update') {
589
- onlyUpdateMessage = ' \n\nExclude all tables and folders you do not want to overwrite, first! \n\nDo not cancel the updating process! This can break your staging site. \n\n\Create a backup of your staging website before you proceed.';
590
  }
591
 
592
- if (!confirm('STOP! This will overwrite your staging site with all selected data from the production site! This should be used only if you want to clone again your production site. Are you sure you want to do this?' + onlyUpdateMessage)) {
593
- return false;
 
 
594
  }
595
- } // Button is disabled
 
 
 
596
 
 
 
597
 
598
- if ($this.attr('disabled')) {
599
- return false;
600
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
601
 
602
- if ($this.data('action') === 'wpstg_cloning') {
603
- // Verify External Database If Checked and Not Skipped
604
- if ($('#wpstg-ext-db').is(':checked')) {
605
- verifyExternalDatabase($this, $workFlow);
606
- return;
607
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
608
  }
609
 
610
- proceedCloning($this, $workFlow);
611
- }) // Previous Button
612
- .on('click', '.wpstg-prev-step-link', function (e) {
613
- e.preventDefault();
614
- cache.get('.wpstg-loader').removeClass('wpstg-finished');
615
- cache.get('.wpstg-loader').hide();
616
- loadOverview();
617
- });
618
- };
619
- /**
620
- * Get Included (Checked) Database Tables
621
- * @return {Array}
622
- */
623
 
 
 
 
 
 
624
 
625
- var getIncludedTables = function getIncludedTables() {
626
- var includedTables = [];
627
- $('#wpstg_select_tables_cloning option:selected').each(function () {
628
- includedTables.push(this.value);
629
- });
630
- return includedTables;
631
- };
632
- /**
633
- * Get Excluded (Unchecked) Database Tables
634
- * Not used anymore!
635
- * @return {Array}
636
- */
637
 
 
 
 
638
 
639
- var getExcludedTables = function getExcludedTables() {
640
- var excludedTables = [];
641
- $('.wpstg-db-table input:not(:checked)').each(function () {
642
- excludedTables.push(this.name);
643
- });
644
- return excludedTables;
645
- };
646
- /**
647
- * Get Included Directories
648
- * @return {string}
649
- */
650
 
 
 
651
 
652
- var getIncludedDirectories = function getIncludedDirectories() {
653
- var includedDirectories = [];
654
- $('.wpstg-dir input:checked.wpstg-root').each(function () {
655
- var $this = $(this);
656
- includedDirectories.push(encodeURIComponent($this.val()));
657
- });
658
- return includedDirectories.join(wpstg.settings.directorySeparator);
659
- };
660
- /**
661
- * Get Excluded Directories
662
- * @return {string}
663
- */
664
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
665
 
666
- var getExcludedDirectories = function getExcludedDirectories() {
667
- var excludedDirectories = [];
668
- $('.wpstg-dir input:not(:checked).wpstg-root').each(function () {
669
- var $this = $(this);
670
- excludedDirectories.push(encodeURIComponent($this.val()));
671
- });
672
- return excludedDirectories.join(wpstg.settings.directorySeparator);
673
- };
674
  /**
675
- * Get included extra directories of the root level
676
- * All directories except wp-content, wp-admin, wp-includes
677
- * @return {string}
678
  */
679
 
 
 
 
 
 
680
 
681
- var getIncludedExtraDirectories = function getIncludedExtraDirectories() {
682
- // Add directories from the root level
683
- var extraDirectories = [];
684
- $('.wpstg-dir input:checked.wpstg-extra').each(function () {
685
- var $this = $(this);
686
- extraDirectories.push(encodeURIComponent($this.val()));
687
- }); // Add any other custom selected extra directories
688
 
689
- if (!$('#wpstg_extraDirectories').val()) {
690
- return extraDirectories.join(wpstg.settings.directorySeparator);
 
 
691
  }
692
 
693
- var extraCustomDirectories = encodeURIComponent($('#wpstg_extraDirectories').val().split(/\r?\n/));
694
- return extraDirectories.concat(extraCustomDirectories).join(wpstg.settings.directorySeparator);
695
- };
696
- /**
697
- * Verify External Database for Cloning
698
- */
699
 
 
 
700
 
701
- var verifyExternalDatabase = function verifyExternalDatabase($this, workflow) {
702
- cache.get('.wpstg-loader').show();
703
- ajax({
704
- action: 'wpstg_database_verification',
705
- accessToken: wpstg.accessToken,
706
- nonce: wpstg.nonce,
707
- databaseUser: cache.get('#wpstg_db_username').val(),
708
- databasePassword: cache.get('#wpstg_db_password').val(),
709
- databaseServer: cache.get('#wpstg_db_server').val(),
710
- databaseDatabase: cache.get('#wpstg_db_database').val()
711
- }, function (response) {
712
- // Undefined Error
713
- if (false === response) {
714
- showError('Something went wrong! Error: No response.' + 'Please try again. If that does not help, ' + '<a href=\'https://wp-staging.com/support/\' target=\'_blank\'>open a support ticket</a> ');
715
- cache.get('.wpstg-loader').hide();
716
- return;
717
- } // Throw Error
718
-
 
719
 
720
- if ('undefined' === typeof response.success) {
721
- showError('Something went wrong! Error: Invalid response.' + 'Please try again. If that does not help, ' + '<a href=\'https://wp-staging.com/support/\' target=\'_blank\'>open a support ticket</a> ');
722
- cache.get('.wpstg-loader').hide();
723
  return;
724
  }
725
 
726
- if (response.success) {
727
- cache.get('.wpstg-loader').hide();
728
- proceedCloning($this, workflow);
729
- return;
730
- }
731
 
732
- if (response.error_type === 'comparison') {
733
- cache.get('.wpstg-loader').hide();
734
- var render = '<table style="width: 100%;"><thead><tr><th>Property</th><th>Production DB</th><th>Staging DB</th><th>Status</th></tr></thead><tbody>';
735
- response.checks.forEach(function (x) {
736
- var icon = '<i style="color: #00ff00">✔</i>';
737
 
738
- if (x.production !== x.staging) {
739
- icon = '<i style="color: #ff0000">❌</i>';
740
- }
741
 
742
- render += '<tr><td>' + x.name + '</td><td>' + x.production + '</td><td>' + x.staging + '</td><td>' + icon + '</td></tr>';
743
- });
744
- render += '</tbody></table><p>Note: Some mySQL properties do not match. You may proceed but the staging site may not work as expected.</p>';
745
- Swal.fire({
746
- title: 'Different Database Properties',
747
- icon: 'warning',
748
- html: render,
749
- width: '650px',
750
- focusConfirm: false,
751
- confirmButtonText: 'Proceed Anyway',
752
- showCancelButton: true
753
- }).then(function (result) {
754
- if (result.value) {
755
- proceedCloning($this, workflow);
756
- }
 
 
757
  });
758
- return;
759
  }
 
760
 
761
- Swal.fire({
762
- title: 'Different Database Properties',
763
- icon: 'error',
764
- html: response.message,
765
- focusConfirm: true,
766
- confirmButtonText: 'Ok',
767
- showCancelButton: false
768
  });
769
- cache.get('.wpstg-loader').hide();
770
- }, 'json', false);
771
- };
772
- /**
773
- * Get Cloning Step Data
774
- */
775
 
 
 
 
 
776
 
777
- var getCloningData = function getCloningData() {
778
- if ('wpstg_cloning' !== that.data.action && 'wpstg_update' !== that.data.action && 'wpstg_reset' !== that.data.action) {
779
- return;
 
 
780
  }
 
 
 
 
 
781
 
782
- that.data.cloneID = $('#wpstg-new-clone-id').val() || new Date().getTime().toString(); // Remove this to keep &_POST[] small otherwise mod_security will throw error 404
783
- // that.data.excludedTables = getExcludedTables();
784
-
785
- var includedDirectories = getIncludedDirectories();
786
- var excludedDirectories = getExcludedDirectories(); // only send that one whose size is low
787
- // same reason as above to keep request size small
788
-
789
- if (includedDirectories.length <= excludedDirectories.length) {
790
- that.data.includedDirectories = includedDirectories;
791
- that.data.areDirectoriesIncluded = true;
792
- } else {
793
- that.data.excludedDirectories = excludedDirectories;
794
- that.data.areDirectoriesIncluded = false;
795
- }
796
 
797
- that.data.includedTables = getIncludedTables();
798
- that.data.extraDirectories = getIncludedExtraDirectories();
799
- that.data.databaseServer = $('#wpstg_db_server').val();
800
- that.data.databaseUser = $('#wpstg_db_username').val();
801
- that.data.databasePassword = $('#wpstg_db_password').val();
802
- that.data.databaseDatabase = $('#wpstg_db_database').val();
803
- that.data.databasePrefix = $('#wpstg_db_prefix').val();
804
- var cloneDir = $('#wpstg_clone_dir').val();
805
- that.data.cloneDir = encodeURIComponent($.trim(cloneDir));
806
- that.data.cloneHostname = $('#wpstg_clone_hostname').val();
807
- that.data.emailsAllowed = $('#wpstg_allow_emails').is(':checked');
808
- that.data.uploadsSymlinked = $('#wpstg_symlink_upload').is(':checked');
809
- that.data.cleanPluginsThemes = $('#wpstg-clean-plugins-themes').is(':checked');
810
- that.data.cleanUploadsDir = $('#wpstg-clean-uploads').is(':checked');
811
- };
812
-
813
- var proceedCloning = function proceedCloning($this, workflow) {
814
- // Add loading overlay
815
- workflow.addClass('loading'); // Prepare data
816
-
817
- that.data = {
818
- action: $this.data('action'),
819
- accessToken: wpstg.accessToken,
820
- nonce: wpstg.nonce
821
- }; // Cloning data
822
-
823
- getCloningData();
824
- console.log(that.data);
825
- sendCloningAjax(workflow);
826
- };
827
-
828
- var sendCloningAjax = function sendCloningAjax(workflow) {
829
- // Send ajax request
830
- ajax(that.data, function (response) {
831
- // Undefined Error
832
- if (false === response) {
833
- showError('Something went wrong!<br/><br/> Go to WP Staging > Settings and lower \'File Copy Limit\' and \'DB Query Limit\'. Also set \'CPU Load Priority to low \'' + 'and try again. If that does not help, ' + '<a href=\'https://wp-staging.com/support/\' target=\'_blank\'>open a support ticket</a> ');
834
- }
835
-
836
- if (response.length < 1) {
837
- showError('Something went wrong! No response. Go to WP Staging > Settings and lower \'File Copy Limit\' and \'DB Query Limit\'. Also set \'CPU Load Priority to low \'' + 'and try again. If that does not help, ' + '<a href=\'https://wp-staging.com/support/\' target=\'_blank\'>open a support ticket</a> ');
838
- } // Styling of elements
839
-
840
-
841
- workflow.removeClass('loading').html(response);
842
-
843
- if (that.data.action === 'wpstg_scanning') {
844
- that.switchStep(2);
845
- } else if (that.data.action === 'wpstg_cloning' || that.data.action === 'wpstg_update' || that.data.action === 'wpstg_reset') {
846
- that.switchStep(3);
847
- } // Start cloning
848
-
849
-
850
- that.startCloning();
851
- }, 'HTML');
852
- };
853
-
854
- var resetClone = function resetClone(clone) {
855
- that.data = {
856
- action: 'wpstg_reset',
857
- accessToken: wpstg.accessToken,
858
- nonce: wpstg.nonce,
859
- cloneID: clone
860
- };
861
- var $workFlow = cache.get('#wpstg-workflow');
862
- sendCloningAjax($workFlow);
863
- };
864
- /**
865
- * Loads Overview (first step) of Staging Job
866
- */
867
 
 
 
 
 
868
 
869
- var loadOverview = function loadOverview() {
870
- var $workFlow = cache.get('#wpstg-workflow');
871
- $workFlow.addClass('loading');
872
- ajax({
873
- action: 'wpstg_overview',
874
- accessToken: wpstg.accessToken,
875
- nonce: wpstg.nonce
876
- }, function (response) {
877
- if (response.length < 1) {
878
- showError('Something went wrong! No response. Please try the <a href=\'https://wp-staging.com/docs/wp-staging-settings-for-small-servers/\' target=\'_blank\'>WP Staging Small Server Settings</a> or submit an error report.');
879
  }
880
 
881
- var $currentStep = cache.get('.wpstg-current-step'); // Styling of elements
882
-
883
- $workFlow.removeClass('loading').html(response);
884
- }, 'HTML');
885
- that.switchStep(1);
886
- cache.get('.wpstg-step3-cloning').show();
887
- cache.get('.wpstg-step3-pushing').hide();
888
- };
889
- /**
890
- * Load Tabs
891
- */
892
 
 
 
 
 
 
 
893
 
894
- var tabs = function tabs() {
895
- cache.get('#wpstg-workflow').on('click', '.wpstg-tab-header', function (e) {
896
- e.preventDefault();
897
- var $this = $(this);
898
- var $section = cache.get($this.data('id'));
899
- $this.toggleClass('expand');
900
- $section.slideToggle();
901
 
902
- if ($this.hasClass('expand')) {
903
- $this.find('.wpstg-tab-triangle').html('&#9660;');
904
- } else {
905
- $this.find('.wpstg-tab-triangle').html('&#9658;');
906
  }
907
- });
908
- };
909
- /**
910
- * Delete Clone
911
- * @param {String} clone
912
- */
913
 
 
 
914
 
915
- var deleteClone = function deleteClone(clone) {
916
- var deleteDir = $('#deleteDirectory:checked').data('deletepath');
917
- ajax({
918
- action: 'wpstg_delete_clone',
919
- clone: clone,
920
- accessToken: wpstg.accessToken,
921
- nonce: wpstg.nonce,
922
- excludedTables: getExcludedTables(),
923
- deleteDir: deleteDir
924
- }, function (response) {
925
- if (response) {
926
- showAjaxFatalError(response); // Finished
927
-
928
- if ('undefined' !== typeof response["delete"] && (response["delete"] === 'finished' || response["delete"] === 'unfinished')) {
929
- cache.get('#wpstg-removing-clone').removeClass('loading').html('');
930
-
931
- if (response["delete"] === 'finished') {
932
- $('.wpstg-clone#' + clone).remove();
933
- }
934
-
935
- if ($('.wpstg-clone').length < 1) {
936
- cache.get('#wpstg-existing-clones').find('h3').text('');
937
- }
938
 
939
- cache.get('.wpstg-loader').hide();
940
- return;
941
  }
942
- } // continue
943
-
944
-
945
- if (true !== response) {
946
- deleteClone(clone);
947
- return;
948
  }
949
- });
950
- };
951
- /**
952
- * Cancel Cloning Process
953
- */
954
-
955
 
956
- var cancelCloning = function cancelCloning() {
957
- that.timer('stop');
 
 
 
 
958
 
959
- if (true === that.isFinished) {
960
- return true;
961
  }
 
 
 
 
 
 
962
 
963
- ajax({
964
- action: 'wpstg_cancel_clone',
965
- clone: that.data.cloneID,
966
- accessToken: wpstg.accessToken,
967
- nonce: wpstg.nonce
968
- }, function (response) {
969
- if (response && 'undefined' !== typeof response["delete"] && response["delete"] === 'finished') {
970
- cache.get('.wpstg-loader').hide(); // Load overview
971
-
972
- loadOverview();
973
- return;
974
- }
975
-
976
- if (true !== response) {
977
- // continue
978
- cancelCloning();
979
- return;
980
- } // Load overview
981
 
 
 
982
 
983
- loadOverview();
984
- });
985
- };
986
  /**
987
- * Cancel Cloning Process
988
  */
 
 
 
 
 
989
 
990
-
991
- var cancelCloningUpdate = function cancelCloningUpdate() {
992
- if (true === that.isFinished) {
993
- return true;
994
  }
995
 
996
- ajax({
997
- action: 'wpstg_cancel_update',
998
- clone: that.data.cloneID,
999
- accessToken: wpstg.accessToken,
1000
- nonce: wpstg.nonce
1001
- }, function (response) {
1002
- if (response && 'undefined' !== typeof response["delete"] && response["delete"] === 'finished') {
1003
- // Load overview
1004
- loadOverview();
1005
- return;
1006
- }
1007
 
1008
- if (true !== response) {
1009
- // continue
1010
- cancelCloningUpdate();
1011
- return;
1012
- } // Load overview
1013
 
 
 
 
1014
 
1015
- loadOverview();
1016
- });
1017
- };
1018
- /**
1019
- * Cancel Cloning Process
1020
- */
1021
 
 
 
 
 
 
 
1022
 
1023
- var restart = function restart() {
1024
- if (true === that.isFinished) {
1025
- return true;
1026
- }
1027
 
1028
- ajax({
1029
- action: 'wpstg_restart',
1030
- // clone: that.data.cloneID,
1031
- accessToken: wpstg.accessToken,
1032
- nonce: wpstg.nonce
1033
- }, function (response) {
1034
- if (response && 'undefined' !== typeof response["delete"] && response["delete"] === 'finished') {
1035
- // Load overview
1036
- loadOverview();
1037
- return;
1038
  }
1039
 
1040
- if (true !== response) {
1041
- // continue
1042
- cancelCloningUpdate();
1043
- return;
1044
- } // Load overview
1045
-
1046
 
1047
- loadOverview();
1048
- });
1049
- };
1050
- /**
1051
- * Scroll the window log to bottom
1052
- * @return void
1053
- */
 
 
 
 
 
 
 
 
1054
 
 
 
 
 
 
 
 
 
 
1055
 
1056
- var logscroll = function logscroll() {
1057
- var $div = cache.get('.wpstg-log-details');
1058
 
1059
- if ('undefined' !== typeof $div[0]) {
1060
- $div.scrollTop($div[0].scrollHeight);
1061
- }
1062
- };
1063
  /**
1064
- * Append the log to the logging window
1065
- * @param string log
1066
- * @return void
1067
  */
1068
 
1069
-
1070
- var getLogs = function getLogs(log) {
1071
- if (log != null && 'undefined' !== typeof log) {
1072
- if (log.constructor === Array) {
1073
- $.each(log, function (index, value) {
1074
- if (value === null) {
1075
- return;
1076
- }
1077
-
1078
- if (value.type === 'ERROR') {
1079
- cache.get('.wpstg-log-details').append('<span style="color:red;">[' + value.type + ']</span>-' + '[' + value.date + '] ' + value.message + '</br>');
1080
- } else {
1081
- cache.get('.wpstg-log-details').append('[' + value.type + ']-' + '[' + value.date + '] ' + value.message + '</br>');
1082
- }
1083
- });
1084
- } else {
1085
- cache.get('.wpstg-log-details').append('[' + log.type + ']-' + '[' + log.date + '] ' + log.message + '</br>');
1086
  }
1087
- }
1088
-
1089
- logscroll();
1090
- };
1091
- /**
1092
- * Check diskspace
1093
- * @return string json
1094
- */
1095
-
1096
-
1097
- var checkDiskSpace = function checkDiskSpace() {
1098
- cache.get('#wpstg-check-space').on('click', function (e) {
1099
- cache.get('.wpstg-loader').show();
1100
- console.log('check disk space');
1101
- ajax({
1102
- action: 'wpstg_check_disk_space',
1103
- accessToken: wpstg.accessToken,
1104
- nonce: wpstg.nonce
1105
- }, function (response) {
1106
- if (false === response) {
1107
- cache.get('#wpstg-clone-id-error').text('Can not detect required disk space').show();
1108
- cache.get('.wpstg-loader').hide();
1109
- return;
1110
- } // Show required disk space
1111
-
1112
-
1113
- cache.get('#wpstg-clone-id-error').html('Estimated necessary disk space: ' + response.usedspace + '<br> <span style="color:#444;">Before you proceed ensure your account has enough free disk space to hold the entire instance of the production site. You can check the available space from your hosting account (cPanel or similar).</span>').show();
1114
- cache.get('.wpstg-loader').hide();
1115
- }, 'json', false);
1116
- });
1117
- };
1118
 
1119
- var mainTabs = function mainTabs() {
1120
- $('.wpstg--tab--header a[data-target]').on('click', function () {
1121
- var $this = $(this);
1122
- var target = $this.attr('data-target');
1123
- var $wrapper = $this.parents('.wpstg--tab--wrapper');
1124
- var $menuItems = $wrapper.find('.wpstg--tab--header a[data-target]');
1125
- var $contents = $wrapper.find('.wpstg--tab--contents > .wpstg--tab--content');
1126
- $contents.filter('.wpstg--tab--active:not(.wpstg--tab--active' + target + ')').removeClass('wpstg--tab--active');
1127
- $menuItems.not($this).removeClass('wpstg--tab--active');
1128
- $this.addClass('wpstg--tab--active');
1129
- $(target).addClass('wpstg--tab--active');
1130
-
1131
- if ('#wpstg--tab--backup' === target) {
1132
- that.backups.init();
1133
  }
1134
 
1135
- if ('#wpstg--tab--database-backups' === target) {
1136
- window.dispatchEvent(new Event('database-backups-tab'));
1137
  }
1138
- });
1139
- };
1140
- /**
1141
- * Show or hide animated loading icon
1142
- * @param isLoading bool
1143
- */
1144
 
 
 
 
1145
 
1146
- var isLoading = function isLoading(_isLoading) {
1147
- if (!_isLoading || _isLoading === false) {
1148
- cache.get('.wpstg-loader').hide();
1149
- } else {
1150
- cache.get('.wpstg-loader').show();
 
 
 
 
 
 
1151
  }
1152
- };
1153
- /**
1154
- * Count up processing execution time
1155
- * @param string status
1156
- * @return html
1157
- */
1158
 
 
1159
 
1160
- that.timer = function (status) {
1161
- if (status === 'stop') {
1162
- var time = that.time;
1163
- that.time = 1;
1164
- clearInterval(that.executionTime);
1165
- return that.convertSeconds(time);
1166
- }
1167
-
1168
- that.executionTime = setInterval(function () {
1169
- if (null !== document.getElementById('wpstg-processing-timer')) {
1170
- document.getElementById('wpstg-processing-timer').innerHTML = 'Elapsed Time: ' + that.convertSeconds(that.time);
1171
- }
1172
 
1173
- that.time++;
1174
 
1175
- if (status === 'stop') {
1176
- that.time = 1;
1177
- clearInterval(that.executionTime);
1178
  }
1179
- }, 1000);
1180
- };
1181
- /**
1182
- * Convert seconds to hourly format
1183
- * @param int seconds
1184
- * @return string
1185
- */
1186
-
1187
-
1188
- that.convertSeconds = function (seconds) {
1189
- var date = new Date(null);
1190
- date.setSeconds(seconds); // specify value for SECONDS here
1191
-
1192
- return date.toISOString().substr(11, 8);
1193
- };
1194
- /**
1195
- * Start Cloning Process
1196
- * @type {Function}
1197
- */
1198
 
 
 
 
 
 
 
 
 
 
 
 
1199
 
1200
- that.startCloning = function () {
1201
- resetErrors(); // Register function for checking disk space
 
 
 
 
1202
 
1203
- checkDiskSpace();
 
 
1204
 
1205
- if ('wpstg_cloning' !== that.data.action && 'wpstg_update' !== that.data.action && 'wpstg_reset' !== that.data.action) {
1206
- return;
1207
- }
 
 
 
1208
 
1209
- that.isCancelled = false; // Start the process
 
 
 
 
 
1210
 
1211
- start(); // Functions
1212
- // Start
 
 
 
 
 
 
 
1213
 
1214
- function start() {
1215
- console.log('Starting cloning process...');
1216
- cache.get('.wpstg-loader').show();
1217
- cache.get('#wpstg-cancel-cloning').text('Cancel');
1218
- cache.get('#wpstg-resume-cloning').hide();
1219
- cache.get('#wpstg-error-details').hide(); // Clone Database
1220
-
1221
- setTimeout(function () {
1222
- // cloneDatabase();
1223
- window.addEventListener('beforeunload', warnIfClosingDuringProcess);
1224
- processing();
1225
- }, wpstg.delayReq);
1226
- that.timer('start');
1227
  }
1228
  /**
1229
- * Start ajax processing
1230
- * @return string
1231
  */
 
1232
 
 
 
 
 
 
 
1233
 
1234
- var processing = function processing() {
1235
- if (true === that.isCancelled) {
1236
- window.removeEventListener('beforeunload', warnIfClosingDuringProcess);
1237
- return false;
1238
- }
1239
-
1240
- isLoading(true); // Show logging window
1241
-
1242
- cache.get('.wpstg-log-details').show();
1243
- WPStaging.ajax({
1244
- action: 'wpstg_processing',
1245
- accessToken: wpstg.accessToken,
1246
- nonce: wpstg.nonce,
1247
- excludedTables: getExcludedTables(),
1248
- includedDirectories: getIncludedDirectories(),
1249
- excludedDirectories: getExcludedDirectories(),
1250
- extraDirectories: getIncludedExtraDirectories()
1251
- }, function (response) {
1252
- showAjaxFatalError(response); // Add Log messages
1253
-
1254
- if ('undefined' !== typeof response.last_msg && response.last_msg) {
1255
- getLogs(response.last_msg);
1256
- } // Continue processing
1257
-
1258
 
1259
- if (false === response.status) {
1260
- progressBar(response);
1261
- setTimeout(function () {
1262
- cache.get('.wpstg-loader').show();
1263
- processing();
1264
- }, wpstg.delayReq);
1265
- } else if (true === response.status && 'finished' !== response.status) {
1266
- cache.get('#wpstg-error-details').hide();
1267
- cache.get('#wpstg-error-wrapper').hide();
1268
- progressBar(response, true);
1269
- processing();
1270
- } else if ('finished' === response.status || 'undefined' !== typeof response.job_done && response.job_done) {
1271
- window.removeEventListener('beforeunload', warnIfClosingDuringProcess);
1272
- finish(response);
 
 
 
 
 
 
 
1273
  }
1274
 
1275
- ;
1276
- }, 'json', false);
1277
- }; // Finish
1278
-
 
 
 
 
 
 
 
 
 
 
 
 
1279
 
1280
- function finish(response) {
1281
- if (true === that.getLogs) {
1282
- getLogs();
1283
- }
 
 
 
 
 
 
 
 
1284
 
1285
- progressBar(response); // Add Log
 
 
1286
 
1287
- if ('undefined' !== typeof response.last_msg) {
1288
- getLogs(response.last_msg);
1289
- }
1290
 
1291
- console.log('Cloning process finished');
1292
- cache.get('.wpstg-loader').hide();
1293
- cache.get('#wpstg-processing-header').html('Processing Complete');
1294
- $('#wpstg-processing-status').text('Succesfully finished');
1295
- cache.get('#wpstg_staging_name').html(that.data.cloneID);
1296
- cache.get('#wpstg-finished-result').show();
1297
- cache.get('#wpstg-cancel-cloning').hide();
1298
- cache.get('#wpstg-resume-cloning').hide();
1299
- cache.get('#wpstg-cancel-cloning-update').prop('disabled', true);
1300
- var $link1 = cache.get('#wpstg-clone-url-1');
1301
- var $link = cache.get('#wpstg-clone-url');
1302
- $link1.attr('href', response.url);
1303
- $link1.html(response.url);
1304
- $link.attr('href', response.url);
1305
- cache.get('#wpstg-remove-clone').data('clone', that.data.cloneID); // Finished
1306
-
1307
- that.isFinished = true;
1308
- that.timer('stop');
1309
- cache.get('.wpstg-loader').hide();
1310
- cache.get('#wpstg-processing-header').html('Processing Complete');
1311
- return false;
1312
- }
1313
- /**
1314
- * Add percentage progress bar
1315
- * @param object response
1316
- * @return {Boolean}
1317
- */
1318
 
 
 
1319
 
1320
- var progressBar = function progressBar(response, restart) {
1321
- if ('undefined' === typeof response.percentage) {
1322
- return false;
1323
  }
1324
 
1325
- if (response.job === 'database') {
1326
- cache.get('#wpstg-progress-db').width(response.percentage * 0.2 + '%').html(response.percentage + '%');
1327
- cache.get('#wpstg-processing-status').html(response.percentage.toFixed(0) + '%' + ' - Step 1 of 4 Cloning Database Tables...');
1328
  }
1329
 
1330
- if (response.job === 'SearchReplace') {
1331
- cache.get('#wpstg-progress-db').css('background-color', '#3bc36b');
1332
- cache.get('#wpstg-progress-db').html('1. Database'); // Assumption: All previous steps are done.
1333
- // This avoids bugs where some steps are skipped and the progress bar is incomplete as a result
1334
 
1335
- cache.get('#wpstg-progress-db').width('20%');
1336
- cache.get('#wpstg-progress-sr').width(response.percentage * 0.1 + '%').html(response.percentage + '%');
1337
- cache.get('#wpstg-processing-status').html(response.percentage.toFixed(0) + '%' + ' - Step 2 of 4 Preparing Database Data...');
1338
- }
1339
-
1340
- if (response.job === 'directories') {
1341
- cache.get('#wpstg-progress-sr').css('background-color', '#3bc36b');
1342
- cache.get('#wpstg-progress-sr').html('2. Data');
1343
- cache.get('#wpstg-progress-sr').width('10%');
1344
- cache.get('#wpstg-progress-dirs').width(response.percentage * 0.1 + '%').html(response.percentage + '%');
1345
- cache.get('#wpstg-processing-status').html(response.percentage.toFixed(0) + '%' + ' - Step 3 of 4 Getting files...');
1346
  }
 
1347
 
1348
- if (response.job === 'files') {
1349
- cache.get('#wpstg-progress-dirs').css('background-color', '#3bc36b');
1350
- cache.get('#wpstg-progress-dirs').html('3. Files');
1351
- cache.get('#wpstg-progress-dirs').width('10%');
1352
- cache.get('#wpstg-progress-files').width(response.percentage * 0.6 + '%').html(response.percentage + '%');
1353
- cache.get('#wpstg-processing-status').html(response.percentage.toFixed(0) + '%' + ' - Step 4 of 4 Copy files...');
1354
- }
1355
 
1356
- if (response.job === 'finish') {
1357
- cache.get('#wpstg-progress-files').css('background-color', '#3bc36b');
1358
- cache.get('#wpstg-progress-files').html('4. Copy Files');
1359
- cache.get('#wpstg-progress-files').width('60%');
1360
- cache.get('#wpstg-processing-status').html(response.percentage.toFixed(0) + '%' + ' - Cloning Process Finished');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1361
  }
1362
  };
1363
- };
1364
 
1365
- that.switchStep = function (step) {
1366
- cache.get('.wpstg-current-step').removeClass('wpstg-current-step');
1367
- cache.get('.wpstg-step' + step).addClass('wpstg-current-step');
1368
- };
1369
- /**
1370
- * Initiation
1371
- * @type {Function}
1372
- */
1373
 
 
 
 
 
 
 
1374
 
1375
- that.init = function () {
1376
- loadOverview();
1377
- elements();
1378
- stepButtons();
1379
- tabs();
1380
- mainTabs();
1381
- new WpstgCloneStaging();
1382
- };
1383
- /**
1384
- * Ajax call
1385
- * @type {ajax}
1386
- */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1387
 
 
1388
 
1389
- that.ajax = ajax;
1390
- that.showError = showError;
1391
- that.getLogs = getLogs;
1392
- that.loadOverview = loadOverview; // TODO RPoC (too big, scattered and unorganized)
1393
-
1394
- that.backups = {
1395
- type: null,
1396
- isCancelled: false,
1397
- processInfo: {
1398
- title: null,
1399
- interval: null
1400
- },
1401
- modal: {
1402
- create: {
1403
- html: null,
1404
- confirmBtnTxt: null
1405
- },
1406
- process: {
1407
- html: null,
1408
- cancelBtnTxt: null,
1409
- modal: null
1410
- },
1411
- download: {
1412
- html: null
1413
- },
1414
- "import": {
1415
- html: null,
1416
- btnTxtNext: null,
1417
- btnTxtConfirm: null,
1418
- btnTxtCancel: null,
1419
- searchReplaceForm: null,
1420
- file: null,
1421
- containerUpload: null,
1422
- containerFilesystem: null,
1423
- setFile: function setFile(file, upload) {
1424
- if (upload === void 0) {
1425
- upload = true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1426
  }
 
1427
 
1428
- var toUnit = function toUnit(bytes) {
1429
- var i = Math.floor(Math.log(bytes) / Math.log(1024));
1430
- return (bytes / Math.pow(1024, i)).toFixed(2) * 1 + ' ' + ['B', 'kB', 'MB', 'GB', 'TB'][i];
1431
- };
1432
 
1433
- if (!file) {
1434
- return;
1435
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1436
 
1437
- that.backups.modal["import"].file = file;
1438
- that.backups.modal["import"].data.file = file.name;
1439
- console.log("File " + file.name);
1440
- $('.wpstg--backup--import--selected-file').html(file.name + " <br /> (" + toUnit(file.size) + ")").show();
1441
- $('.wpstg--drag').hide();
1442
- $('.wpstg--drag-or-upload').show();
1443
 
1444
- if (upload) {
1445
- $('.wpstg--modal--actions .swal2-confirm').prop('disabled', true);
1446
- that.backups.upload.start();
1447
- }
 
 
 
 
 
 
 
1448
  },
1449
- baseDirectory: null,
1450
- data: {
 
 
 
 
 
 
 
 
 
 
 
 
1451
  file: null,
1452
- search: [],
1453
- replace: []
1454
- }
1455
- }
1456
- },
1457
- messages: {
1458
- WARNING: 'warning',
1459
- ERROR: 'error',
1460
- INFO: 'info',
1461
- DEBUG: 'debug',
1462
- CRITICAL: 'critical',
1463
- data: {
1464
- all: [],
1465
- // TODO RPoC
1466
- info: [],
1467
- error: [],
1468
- critical: [],
1469
- warning: [],
1470
- debug: []
1471
- },
1472
- shouldWarn: function shouldWarn() {
1473
- return that.backups.messages.data.error.length > 0 || that.backups.messages.data.critical.length > 0;
1474
- },
1475
- countByType: function countByType(type) {
1476
- if (type === void 0) {
1477
- type = that.backups.messages.ERROR;
1478
- }
1479
-
1480
- return that.backups.messages.data[type].length;
1481
- },
1482
- addMessage: function addMessage(message) {
1483
- if (Array.isArray(message)) {
1484
- message.forEach(function (item) {
1485
- that.backups.messages.addMessage(item);
1486
- });
1487
- return;
1488
- }
1489
 
1490
- var type = message.type.toLowerCase() || 'info';
 
 
 
1491
 
1492
- if (!that.backups.messages.data[type]) {
1493
- that.backups.messages.data[type] = [];
1494
- }
1495
 
1496
- that.backups.messages.data.all.push(message); // TODO RPoC
 
 
 
 
1497
 
1498
- that.backups.messages.data[type].push(message);
 
 
 
 
 
 
 
 
 
 
 
1499
  },
1500
- reset: function reset() {
1501
- that.backups.messages.data = {
 
 
 
 
 
1502
  all: [],
 
1503
  info: [],
1504
  error: [],
1505
  critical: [],
1506
  warning: [],
1507
  debug: []
1508
- };
1509
- }
1510
- },
1511
- timer: {
1512
- totalSeconds: 0,
1513
- interval: null,
1514
- start: function start() {
1515
- if (null !== that.backups.timer.interval) {
1516
- return;
1517
- }
1518
-
1519
- var prettify = function prettify(seconds) {
1520
- console.log("Process running for " + seconds + " seconds"); // If potentially anything can exceed 24h execution time than that;
1521
- // const _seconds = parseInt(seconds, 10)
1522
- // const hours = Math.floor(_seconds / 3600)
1523
- // const minutes = Math.floor(_seconds / 60) % 60
1524
- // seconds = _seconds % 60
1525
- //
1526
- // return [hours, minutes, seconds]
1527
- // .map(v => v < 10 ? '0' + v : v)
1528
- // .filter((v,i) => v !== '00' || i > 0)
1529
- // .join(':')
1530
- // ;
1531
- // Are we sure we won't create anything that exceeds 24h execution time? If not then this;
1532
-
1533
- return "" + new Date(seconds * 1000).toISOString().substr(11, 8);
1534
- };
1535
 
1536
- that.backups.timer.interval = setInterval(function () {
1537
- $('.wpstg--modal--process--elapsed-time').text(prettify(that.backups.timer.totalSeconds));
1538
- that.backups.timer.totalSeconds++;
1539
- }, 1000);
1540
- },
1541
- stop: function stop() {
1542
- that.backups.timer.totalSeconds = 0;
1543
-
1544
- if (that.backups.timer.interval) {
1545
- clearInterval(that.backups.timer.interval);
1546
- that.backups.timer.interval = null;
1547
- }
1548
- }
1549
- },
1550
- upload: {
1551
- reader: null,
1552
- file: null,
1553
- iop: 1000 * 1024,
1554
- uploadInfo: function uploadInfo(isShow) {
1555
- var $containerUpload = $('.wpstg--modal--import--upload--process');
1556
- var $containerUploader = $('.wpstg--uploader');
1557
-
1558
- if (isShow) {
1559
- $containerUpload.css('display', 'flex');
1560
- $containerUploader.hide();
1561
- return;
1562
- }
1563
 
1564
- $containerUploader.css('display', 'flex');
1565
- $containerUpload.hide();
1566
- },
1567
- start: function start() {
1568
- console.log("file " + that.backups.modal["import"].data.file);
1569
- that.backups.upload.reader = new FileReader();
1570
- that.backups.upload.file = that.backups.modal["import"].file;
1571
- that.backups.upload.uploadInfo(true);
1572
- that.backups.upload.sendChunk();
1573
- },
1574
- sendChunk: function sendChunk(startsAt) {
1575
- if (startsAt === void 0) {
1576
- startsAt = 0;
1577
- }
1578
 
1579
- if (!that.backups.upload.file) {
1580
- return;
1581
- }
1582
 
1583
- var isReset = startsAt < 1;
1584
- var endsAt = startsAt + that.backups.upload.iop + 1;
1585
- var blob = that.backups.upload.file.slice(startsAt, endsAt);
1586
 
1587
- that.backups.upload.reader.onloadend = function (event) {
1588
- if (event.target.readyState !== FileReader.DONE) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1589
  return;
1590
  }
1591
 
1592
- var body = new FormData();
1593
- body.append('accessToken', wpstg.accessToken);
1594
- body.append('nonce', wpstg.nonce);
1595
- body.append('data', event.target.result);
1596
- body.append('filename', that.backups.upload.file.name);
1597
- body.append('reset', isReset ? '1' : '0');
1598
- fetch(ajaxurl + "?action=wpstg--backups--import--file-upload", {
1599
- method: 'POST',
1600
- body: body
1601
- }).then(handleFetchErrors).then(function (res) {
1602
- return res.json();
1603
- }).then(function (res) {
1604
- showAjaxFatalError(res, '', 'Submit an error report.');
1605
- var writtenBytes = startsAt + that.backups.upload.iop;
1606
- var percent = Math.floor(writtenBytes / that.backups.upload.file.size * 100);
1607
-
1608
- if (endsAt >= that.backups.upload.file.size) {
1609
- that.backups.upload.uploadInfo(false);
1610
- isLoading(false);
1611
- that.backups.switchModalToConfigure();
1612
- return;
1613
- }
1614
-
1615
- $('.wpstg--modal--import--upload--progress--title > span').text(percent);
1616
- $('.wpstg--modal--import--upload--progress').css('width', percent + "%");
1617
- that.backups.upload.sendChunk(endsAt);
1618
- })["catch"](function (e) {
1619
- return showAjaxFatalError(e, '', 'Submit an error report.');
1620
- });
1621
- };
1622
-
1623
- that.backups.upload.reader.readAsDataURL(blob);
1624
- }
1625
- },
1626
- status: {
1627
- hasResponse: null,
1628
- reTryAfter: 5000
1629
- },
1630
- init: function init() {
1631
- this.create();
1632
- this["delete"]();
1633
- this.edit(); // noinspection JSIgnoredPromiseFromCall
1634
 
1635
- that.backups.fetchListing();
1636
- $('body').on('click', '.wpstg--backup--download', function () {
1637
- var url = this.getAttribute('data-url');
 
 
 
 
1638
 
1639
- if (url.length > 0) {
1640
- window.location.href = url;
1641
- return;
 
1642
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1643
 
1644
- that.backups.downloadModal({
1645
- titleExport: this.getAttribute('data-title-export'),
1646
- title: this.getAttribute('data-title'),
1647
- id: this.getAttribute('data-id'),
1648
- btnTxtCancel: this.getAttribute('data-btn-cancel-txt'),
1649
- btnTxtConfirm: this.getAttribute('data-btn-download-txt')
1650
- });
1651
- }).on('click', '.wpstg--backup--import', function () {
1652
- // Clicked "Import" on the backup list
1653
- that.backups.importModal();
1654
- that.backups.modal["import"].data.file = this.getAttribute('data-filePath');
1655
- that.backups.switchModalToConfigure(); // $('.wpstg--modal--actions .swal2-confirm').show();
1656
- // $('.wpstg--modal--actions .swal2-confirm').prop('disabled', false);
1657
- }).off('click', '#wpstg-import-backup').on('click', '#wpstg-import-backup', function () {
1658
- that.backups.importModal();
1659
- }) // Import
1660
- .off('click', '.wpstg--backup--import--choose-option').on('click', '.wpstg--backup--import--choose-option', function () {
1661
- var $this = $(this);
1662
- var $parent = $this.parent();
1663
 
1664
- if (!$parent.hasClass('wpstg--show-options')) {
1665
- $parent.addClass('wpstg--show-options');
1666
- $this.text($this.attr('data-txtChoose'));
1667
- } else {
1668
- $parent.removeClass('wpstg--show-options');
1669
- $this.text($this.attr('data-txtOther'));
1670
- }
1671
- }).off('click', '.wpstg--modal--backup--import--search-replace--new').on('click', '.wpstg--modal--backup--import--search-replace--new', function (e) {
1672
- e.preventDefault();
1673
- var $container = $(Swal.getContainer()).find('.wpstg--modal--backup--import--search-replace--input--container');
1674
- var total = $container.find('.wpstg--modal--backup--import--search-replace--input-group').length;
1675
- $container.append(that.backups.modal["import"].searchReplaceForm.replace(/{i}/g, total));
1676
- }).off('click', '.wpstg--modal--backup--import--search-replace--remove').on('click', '.wpstg--modal--backup--import--search-replace--remove', function (e) {
1677
- e.preventDefault();
1678
- $(e.target).closest('.wpstg--modal--backup--import--search-replace--input-group').remove();
1679
- }).off('input', '.wpstg--backup--import--search').on('input', '.wpstg--backup--import--search', function () {
1680
- var index = parseInt(this.getAttribute('data-index'));
1681
 
1682
- if (!isNaN(index)) {
1683
- that.backups.modal["import"].data.search[index] = this.value;
1684
- }
1685
- }).off('input', '.wpstg--backup--import--replace').on('input', '.wpstg--backup--import--replace', function () {
1686
- var index = parseInt(this.getAttribute('data-index'));
1687
 
1688
- if (!isNaN(index)) {
1689
- that.backups.modal["import"].data.replace[index] = this.value;
1690
- }
1691
- }) // Other Options
1692
- .off('click', '.wpstg--backup--import--option[data-option]').on('click', '.wpstg--backup--import--option[data-option]', function () {
1693
- var option = this.getAttribute('data-option');
1694
 
1695
- if (option === 'file') {
1696
- $('input[type="file"][name="wpstg--backup--import--upload--file"]').trigger('click');
1697
- return;
1698
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1699
 
1700
- if (option === 'upload') {
1701
- that.backups.modal["import"].containerFilesystem.hide();
1702
- that.backups.modal["import"].containerUpload.show();
1703
- }
 
 
 
1704
 
1705
- if (option !== 'filesystem') {
1706
- return;
1707
  }
 
 
 
 
 
 
 
 
 
1708
 
1709
- that.backups.modal["import"].containerUpload.hide();
1710
- var $containerFilesystem = that.backups.modal["import"].containerFilesystem;
1711
- $containerFilesystem.show();
1712
- fetch(ajaxurl + "?action=wpstg--backups--import--file-list&_=" + Math.random() + "&accessToken=" + wpstg.accessToken + "&nonce=" + wpstg.nonce).then(handleFetchErrors).then(function (res) {
1713
- return res.json();
1714
- }).then(function (res) {
1715
- var $ul = $('.wpstg--modal--backup--import--filesystem ul');
1716
- $ul.empty();
1717
 
1718
- if (!res || isEmpty(res)) {
1719
- $ul.append("<span id=\"wpstg--backups--import--file-list-empty\">" + wpstg.i18n.noImportFileFound + "</span><br />");
1720
- $('.wpstg--modal--backup--import--search-replace--wrapper').hide();
1721
  return;
1722
  }
1723
 
1724
- $ul.append("<span id=\"wpstg--backups--import--file-list\">" + wpstg.i18n.selectFileToImport + "</span><br />");
1725
- res.forEach(function (file, index) {
1726
- $ul.append("\n<li data-filepath=\"" + file.fullPath + "\" class=\"wpstg--backups--import--file-list--sigle-item\">\n <ul class=\"wpstg-import-backup-more-info wpstg-import-backup-more-info-" + index + ("\">\n <li style=\"font-weight: bold\">" + file.backupName + "</li>\n <li>Created on: " + file.dateCreatedFormatted + "</li>\n <li>Size: " + file.size + "</li>\n <li>\n <div class=\"wpstg-import-backup-contains-title\">This backup contains:</div>\n <ul class=\"wpstg-import-backup-contains\">\n ") + (file.isExportingDatabase ? '<li><span class="dashicons dashicons-database wpstg--tooltip"><div class=\'wpstg--tooltiptext\'>Database</div></span></li>' : '') + "\n " + (file.isExportingPlugins ? '<li><span class="dashicons dashicons-admin-plugins wpstg--tooltip"><div class=\'wpstg--tooltiptext\'>Plugins</div></span></li>' : '') + "\n " + (file.isExportingMuPlugins ? '<li><span class="dashicons dashicons-plugins-checked wpstg--tooltip"><div class=\'wpstg--tooltiptext\'>Mu-plugins</div></span></li>' : '') + "\n " + (file.isExportingThemes ? '<li><span class="dashicons dashicons-layout wpstg--tooltip"><div class=\'wpstg--tooltiptext\'>Themes</div></span></li>' : '') + "\n " + (file.isExportingUploads ? '<li><span class="dashicons dashicons-images-alt wpstg--tooltip"><div class=\'wpstg--tooltiptext\'>Uploads</div></span></li>' : '') + "\n " + (file.isExportingOtherWpContentFiles ? '<li><span class="dashicons dashicons-admin-generic wpstg--tooltip"><div class=\'wpstg--tooltiptext\'>Other files in wp-content</div></span></li>' : '') + ("\n </ul>\n </li>\n <li>Filename: " + file.name + "</li>\n </ul>\n</li>\n"));
 
 
 
1727
  });
1728
- return res;
1729
- })["catch"](function (e) {
1730
- return showAjaxFatalError(e, '', 'Submit an error report.');
1731
- });
1732
- }).off('change', 'input[type="file"][name="wpstg--backup--import--upload--file"]').on('change', 'input[type="file"][name="wpstg--backup--import--upload--file"]', function () {
1733
- that.backups.modal["import"].setFile(this.files[0] || null);
1734
- }).off('change', 'input[type="radio"][name="backup_import_file"]').on('change', 'input[type="radio"][name="backup_import_file"]', function () {
1735
- $('.wpstg--modal--actions .swal2-confirm').show();
1736
- $('.wpstg--modal--actions .swal2-confirm').prop('disabled', false);
1737
- that.backups.modal["import"].data.file = this.value;
1738
- }) // Drag & Drop
1739
- .on('drag dragstart dragend dragover dragenter dragleave drop', '.wpstg--modal--backup--import--upload--container', function (e) {
1740
- e.preventDefault();
1741
- e.stopPropagation();
1742
- }).on('dragover dragenter', '.wpstg--modal--backup--import--upload--container', function () {
1743
- $(this).addClass('wpstg--has-dragover');
1744
- }).on('dragleave dragend drop', '.wpstg--modal--backup--import--upload--container', function () {
1745
- $(this).removeClass('wpstg--has-dragover');
1746
- }).on('drop', '.wpstg--modal--backup--import--upload--container', function (e) {
1747
- // Uploaded a file through the "Import Backup modal"
1748
- that.backups.modal["import"].setFile(e.originalEvent.dataTransfer.files[0] || null);
1749
- }).on('click', '.wpstg--modal--backup--import--filesystem li', function (e) {
1750
- // Selected an existing backup in the Import Backup modal
1751
- var fullPath = $(e.target).closest('.wpstg--backups--import--file-list--sigle-item').data().filepath;
1752
-
1753
- if (!fullPath.length) {
1754
- alert('Error: Could not get file path.');
1755
- return;
1756
- }
 
 
 
 
 
 
 
1757
 
1758
- that.backups.modal["import"].data.file = fullPath;
1759
- that.backups.switchModalToConfigure(); // $('.wpstg--modal--actions .swal2-confirm').prop('disabled', false);
1760
- // that.backups.modal.gotoStart();
1761
- }).on('change', '.wpstg-advanced-options-site input[type="checkbox"]', function (e) {
1762
- /*
1763
- * We use a timeout here to simulate an "afterChange" event.
1764
- * This allows us to read from the DOM whether the checkbox is checked or not,
1765
- * instead of having to read from the event, which would require a lengthier code
1766
- * to account for all elements we might want to read.
1767
- */
1768
- setTimeout(function (e) {
1769
- // Reset
1770
- document.getElementById('exportUploadsWithoutDatabaseWarning').style.display = 'none'; // Exporting Media Library without Database
1771
 
1772
- var databaseChecked = document.getElementById('includeDatabaseInBackup').checked;
1773
- var mediaLibraryChecked = document.getElementById('includeMediaLibraryInBackup').checked;
 
 
1774
 
1775
- if (mediaLibraryChecked && !databaseChecked) {
1776
- document.getElementById('exportUploadsWithoutDatabaseWarning').style.display = 'block';
 
1777
  }
1778
- }, 100);
1779
- });
1780
- },
1781
- fetchListing: function fetchListing(isResetErrors) {
1782
- if (isResetErrors === void 0) {
1783
- isResetErrors = true;
1784
- }
1785
 
1786
- isLoading(true);
 
 
1787
 
1788
- if (isResetErrors) {
1789
- resetErrors();
1790
- }
 
 
 
 
 
1791
 
1792
- return fetch(ajaxurl + "?action=wpstg--backups--listing&_=" + Math.random() + "&accessToken=" + wpstg.accessToken + "&nonce=" + wpstg.nonce).then(handleFetchErrors).then(function (res) {
1793
- return res.json();
1794
- }).then(function (res) {
1795
- showAjaxFatalError(res, '', 'Submit an error report.');
1796
- cache.get('#wpstg--tab--backup').html(res);
1797
- isLoading(false);
1798
- window.dispatchEvent(new Event('backupListingFinished'));
1799
- return res;
1800
- })["catch"](function (e) {
1801
- return showAjaxFatalError(e, '', 'Submit an error report.');
1802
- });
1803
- },
1804
- "delete": function _delete() {
1805
- $('#wpstg--tab--backup').off('click', '.wpstg-delete-backup[data-md5]').on('click', '.wpstg-delete-backup[data-md5]', function (e) {
1806
- e.preventDefault();
1807
- resetErrors();
1808
 
1809
- if (!confirm('Are you sure you want to delete this backup?')) {
1810
- return;
1811
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1812
 
1813
- isLoading(true);
1814
- cache.get('#wpstg-existing-backups').hide();
1815
- var md5 = this.getAttribute('data-md5');
1816
- that.ajax({
1817
- action: 'wpstg--backups--delete',
1818
- md5: md5,
1819
- accessToken: wpstg.accessToken,
1820
- nonce: wpstg.nonce
1821
- }, function (response) {
1822
- showAjaxFatalError(response, '', ' Please submit an error report by using the REPORT ISSUE button.');
1823
- isLoading(false);
1824
- that.backups.fetchListing();
 
 
 
 
 
 
 
 
 
1825
  });
1826
- }); // Force delete if backup tables do not exist
1827
- // TODO This is bloated, no need extra ID, use existing one?
 
 
 
1828
 
1829
- $('#wpstg-error-wrapper').off('click', '#wpstg-backup-force-delete').on('click', '#wpstg-backup-force-delete', function (e) {
1830
- e.preventDefault();
1831
- resetErrors();
1832
  isLoading(true);
1833
- var id = this.getAttribute('data-id');
1834
 
1835
- if (!confirm('Do you want to delete this backup ' + id + ' from the listed backups?')) {
1836
- isLoading(false);
1837
- return false;
1838
  }
1839
 
1840
- that.ajax({
1841
- action: 'wpstg--backups--delete',
1842
- id: id,
1843
- accessToken: wpstg.accessToken,
1844
- nonce: wpstg.nonce
1845
- }, function (response) {
1846
- showAjaxFatalError(response, '', ' Please submit an error report by using the REPORT ISSUE button.'); // noinspection JSIgnoredPromiseFromCall
1847
-
1848
- that.backups.fetchListing();
1849
  isLoading(false);
 
 
 
 
1850
  });
1851
- });
1852
- },
1853
- create: function create() {
1854
- var prepareBackup = function prepareBackup(data) {
1855
- WPStaging.ajax({
1856
- action: 'wpstg--backups--prepare-export',
1857
- accessToken: wpstg.accessToken,
1858
- nonce: wpstg.nonce,
1859
- wpstgExportData: data
1860
- }, function (response) {
1861
- if (response.success) {
1862
- that.backups.timer.start();
1863
- createBackup();
1864
- } else {
1865
- showAjaxFatalError(response.data, '', 'Submit an error report.');
1866
  }
1867
- }, 'json', false, 0, 1.25);
1868
- };
1869
 
1870
- var createBackup = function createBackup() {
1871
- resetErrors();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1872
 
1873
- if (that.backups.isCancelled) {
1874
- // Swal.close();
1875
- return;
1876
- }
 
 
 
1877
 
1878
- var statusStop = function statusStop() {
1879
- console.log('Status: Stop');
1880
- clearInterval(that.backups.processInfo.interval);
1881
- that.backups.processInfo.interval = null;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1882
  };
1883
 
1884
- var status = function status() {
1885
- if (that.backups.processInfo.interval !== null) {
 
 
 
1886
  return;
1887
  }
1888
 
1889
- console.log('Status: Start');
1890
- that.backups.processInfo.interval = setInterval(function () {
1891
- if (true === that.backups.isCancelled) {
1892
- statusStop();
1893
- return;
1894
- }
1895
 
1896
- if (that.backups.status.hasResponse === false) {
 
1897
  return;
1898
  }
1899
 
1900
- that.backups.status.hasResponse = false;
1901
- fetch(ajaxurl + "?action=wpstg--backups--status&accessToken=" + wpstg.accessToken + "&nonce=" + wpstg.nonce).then(function (res) {
1902
- return res.json();
1903
- }).then(function (res) {
1904
- that.backups.status.hasResponse = true;
1905
-
1906
- if (typeof res === 'undefined') {
1907
  statusStop();
 
1908
  }
1909
 
1910
- if (that.backups.processInfo.title === res.currentStatusTitle) {
1911
  return;
1912
  }
1913
 
1914
- that.backups.processInfo.title = res.currentStatusTitle;
1915
- var $container = $(Swal.getContainer());
1916
- $container.find('.wpstg--modal--process--title').text(res.currentStatusTitle);
1917
- $container.find('.wpstg--modal--process--percent').text('0');
1918
- })["catch"](function (e) {
1919
- that.backups.status.hasResponse = true;
1920
- showAjaxFatalError(e, '', 'Submit an error report.');
1921
- });
1922
- }, 5000);
1923
- };
1924
-
1925
- WPStaging.ajax({
1926
- action: 'wpstg--backups--export',
1927
- accessToken: wpstg.accessToken,
1928
- nonce: wpstg.nonce
1929
- }, function (response) {
1930
- console.log(response);
1931
 
1932
- if (typeof response === 'undefined') {
1933
- setTimeout(function () {
1934
- createBackup();
1935
- }, wpstg.delayReq);
1936
- return;
1937
- }
1938
 
1939
- that.backups.processResponse(response);
 
 
 
 
 
 
 
 
 
 
 
 
 
1940
 
1941
- if (!that.backups.processInfo.interval) {
1942
- status();
1943
- }
 
 
 
 
 
 
 
 
1944
 
1945
- if (response.status === false) {
1946
- createBackup();
1947
- } else if (response.status === true) {
1948
- $('#wpstg--progress--status').text('Backup successfully created!');
1949
- that.backups.type = null;
1950
 
1951
- if (that.backups.messages.shouldWarn()) {
1952
- // noinspection JSIgnoredPromiseFromCall
1953
- that.backups.fetchListing();
1954
- that.backups.logsModal();
1955
- return;
1956
  }
1957
 
1958
- statusStop();
1959
- Swal.close();
1960
- that.backups.fetchListing().then(function () {
1961
- if (!response.backupMd5) {
1962
- showError('Failed to get backup md5 from response');
 
 
 
 
 
1963
  return;
1964
- } // Wait for fetchListing to populate the DOM with the backup data that we want to read
1965
 
 
 
 
 
 
 
 
1966
 
1967
- var $el = '';
1968
- var timesWaited = 0;
1969
- var intervalWaitForBackupInDom = setInterval(function () {
1970
- timesWaited++;
1971
- $el = $(".wpstg--backup--download[data-md5=\"" + response.backupMd5 + "\"]"); // Could not find element, let's try again...
1972
 
1973
- if (!$el.length) {
1974
- if (timesWaited >= 10) {
1975
- // Bail: We tried too many times and couldn't find.
1976
- clearInterval(intervalWaitForBackupInDom);
1977
- }
1978
 
1979
- return;
1980
- } // Found it. No more need for the interval.
1981
-
1982
-
1983
- clearInterval(intervalWaitForBackupInDom);
1984
- var backupSize = response.hasOwnProperty('backupSize') ? ' (' + response.backupSize + ')' : '';
1985
- that.backups.downloadModal({
1986
- id: $el.data('id'),
1987
- url: $el.data('url'),
1988
- title: $el.data('title'),
1989
- titleExport: $el.data('title-export'),
1990
- btnTxtCancel: $el.data('btn-cancel-txt'),
1991
- btnTxtConfirm: $el.data('btn-download-txt') + backupSize
1992
- });
1993
- $('.wpstg--modal--download--logs--wrapper').show();
1994
- var $logsContainer = $('.wpstg--modal--process--logs');
1995
- that.backups.messages.data.all.forEach(function (message) {
1996
- var msgClass = "wpstg--modal--process--msg--" + message.type.toLowerCase();
1997
- $logsContainer.append("<p class=\"" + msgClass + "\">[" + message.type + "] - [" + message.date + "] - " + message.message + "</p>");
1998
- });
1999
- }, 200);
2000
- });
2001
- } else {
2002
- setTimeout(function () {
2003
- createBackup();
2004
- }, wpstg.delayReq);
2005
- }
2006
- }, 'json', false, 0, // Don't retry upon failure
2007
- 1.25);
2008
- };
2009
 
2010
- var $body = $('body');
2011
- $body.off('click', '.wpstg--tab--toggle').on('click', '.wpstg--tab--toggle', function () {
2012
- var $this = $(this);
2013
- var $target = $($this.attr('data-target'));
2014
- $target.toggle();
2015
 
2016
- if ($target.is(':visible')) {
2017
- $this.find('span').text('▼');
2018
- } else {
2019
- $this.find('span').text('►');
2020
- }
2021
- }).off('change', '[name="includedDirectories\[\]"], input#includeDatabaseInBackup, input#includeOtherFilesInWpContent').on('change', '[type="checkbox"][name="includedDirectories\[\]"], input#includeDatabaseInBackup, input#includeOtherFilesInWpContent', function () {
2022
- var isExportingAnyDir = $('[type="checkbox"][name="includedDirectories\[\]"]:checked').length > 0;
2023
- var isExportingDatabase = $('input#includeDatabaseInBackup:checked').length === 1;
2024
- var isExportingOtherFilesInWpContent = $('input#includeOtherFilesInWpContent:checked').length === 1;
2025
 
2026
- if (!isExportingAnyDir && !isExportingDatabase && !isExportingOtherFilesInWpContent) {
2027
- $('.swal2-confirm').prop('disabled', true);
2028
- } else {
2029
- $('.swal2-confirm').prop('disabled', false);
2030
- }
2031
- }); // Add backup name and notes
2032
-
2033
- $('#wpstg--tab--backup').off('click', '#wpstg-new-backup').on('click', '#wpstg-new-backup', /*#__PURE__*/function () {
2034
- var _ref = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(e) {
2035
- var $newBackupModal, html, btnTxt, _yield$Swal$fire, formValues;
2036
-
2037
- return regeneratorRuntime.wrap(function _callee$(_context) {
2038
- while (1) {
2039
- switch (_context.prev = _context.next) {
2040
- case 0:
2041
- resetErrors();
2042
- e.preventDefault();
2043
- that.backups.isCancelled = false;
2044
-
2045
- if (!that.backups.modal.create.html || !that.backups.modal.create.confirmBtnTxt) {
2046
- $newBackupModal = $('#wpstg--modal--backup--new');
2047
- html = $newBackupModal.html();
2048
- btnTxt = $newBackupModal.attr('data-confirmButtonText');
2049
- that.backups.modal.create.html = html || null;
2050
- that.backups.modal.create.confirmBtnTxt = btnTxt || null;
2051
- $newBackupModal.remove();
2052
- }
2053
-
2054
- _context.next = 6;
2055
- return Swal.fire({
2056
- title: '',
2057
- html: that.backups.modal.create.html,
2058
- focusConfirm: false,
2059
- confirmButtonText: that.backups.modal.create.confirmBtnTxt,
2060
- showCancelButton: true,
2061
- preConfirm: function preConfirm() {
2062
- var container = Swal.getContainer();
2063
- return {
2064
- name: container.querySelector('input[name="backup_name"]').value || null,
2065
- isExportingPlugins: container.querySelector('#includePluginsInBackup:checked') !== null,
2066
- isExportingMuPlugins: container.querySelector('#includeMuPluginsInBackup:checked') !== null,
2067
- isExportingThemes: container.querySelector('#includeThemesInBackup:checked') !== null,
2068
- isExportingUploads: container.querySelector('#includeMediaLibraryInBackup:checked') !== null,
2069
- isExportingOtherWpContentFiles: container.querySelector('#includeOtherFilesInWpContent:checked') !== null,
2070
- isExportingDatabase: container.querySelector('#includeDatabaseInBackup:checked') !== null
2071
- };
2072
- }
2073
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2074
 
2075
- case 6:
2076
- _yield$Swal$fire = _context.sent;
2077
- formValues = _yield$Swal$fire.value;
 
 
2078
 
2079
- if (formValues) {
2080
- _context.next = 10;
2081
- break;
2082
- }
 
 
 
 
 
2083
 
2084
- return _context.abrupt("return");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2085
 
2086
- case 10:
2087
- that.backups.process({
2088
- execute: function execute() {
2089
- that.backups.messages.reset();
2090
- prepareBackup(formValues);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2091
  }
2092
- });
2093
 
2094
- case 11:
2095
- case "end":
2096
- return _context.stop();
2097
- }
2098
- }
2099
- }, _callee);
2100
- }));
2101
 
2102
- return function (_x) {
2103
- return _ref.apply(this, arguments);
2104
- };
2105
- }());
2106
- },
2107
- switchModalToConfigure: function switchModalToConfigure() {
2108
- that.backups.modal["import"].containerUpload.hide();
2109
- that.backups.modal["import"].containerFilesystem.hide();
2110
- that.backups.modal["import"].containerConfigure.show();
2111
- },
2112
- // Edit backups name and notes
2113
- edit: function edit() {
2114
- $('#wpstg--tab--backup').off('click', '.wpstg--backup--edit[data-md5]').on('click', '.wpstg--backup--edit[data-md5]', /*#__PURE__*/function () {
2115
- var _ref2 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee2(e) {
2116
- var $this, name, notes, _yield$Swal$fire2, formValues;
2117
-
2118
- return regeneratorRuntime.wrap(function _callee2$(_context2) {
2119
- while (1) {
2120
- switch (_context2.prev = _context2.next) {
2121
- case 0:
2122
- e.preventDefault();
2123
- $this = $(this);
2124
- name = $this.data('name');
2125
- notes = $this.data('notes');
2126
- _context2.next = 6;
2127
- return Swal.fire({
2128
- title: '',
2129
- html: "\n <label id=\"wpstg-backup-edit-name\">Backup Name</label>\n <input id=\"wpstg-backup-edit-name-input\" class=\"swal2-input\" value=\"" + name + "\">\n <label>Additional Notes</label>\n <textarea id=\"wpstg-backup-edit-notes-textarea\" class=\"swal2-textarea\">" + notes + "</textarea>\n ",
2130
- focusConfirm: false,
2131
- confirmButtonText: 'Update Backup',
2132
- showCancelButton: true,
2133
- preConfirm: function preConfirm() {
2134
- return {
2135
- name: document.getElementById('wpstg-backup-edit-name-input').value || null,
2136
- notes: document.getElementById('wpstg-backup-edit-notes-textarea').value || null
2137
- };
2138
- }
2139
- });
2140
 
2141
- case 6:
2142
- _yield$Swal$fire2 = _context2.sent;
2143
- formValues = _yield$Swal$fire2.value;
2144
-
2145
- if (formValues) {
2146
- _context2.next = 10;
2147
- break;
2148
- }
2149
-
2150
- return _context2.abrupt("return");
2151
-
2152
- case 10:
2153
- that.ajax({
2154
- action: 'wpstg--backups--edit',
2155
- accessToken: wpstg.accessToken,
2156
- nonce: wpstg.nonce,
2157
- md5: $this.data('md5'),
2158
- name: formValues.name,
2159
- notes: formValues.notes
2160
- }, function (response) {
2161
- showAjaxFatalError(response, '', 'Submit an error report.'); // noinspection JSIgnoredPromiseFromCall
2162
-
2163
- that.backups.fetchListing();
2164
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2165
 
2166
- case 11:
2167
- case "end":
2168
- return _context2.stop();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2169
  }
2170
- }
2171
- }, _callee2, this);
2172
- }));
2173
-
2174
- return function (_x2) {
2175
- return _ref2.apply(this, arguments);
2176
- };
2177
- }());
2178
- },
2179
- cancel: function cancel() {
2180
- that.backups.timer.stop();
2181
- that.backups.isCancelled = true;
2182
- Swal.close();
2183
- setTimeout(function () {
2184
- return that.ajax({
2185
- action: 'wpstg--backups--cancel',
2186
- accessToken: wpstg.accessToken,
2187
- nonce: wpstg.nonce,
2188
- type: that.backups.type
2189
- }, function (response) {
2190
- showAjaxFatalError(response, '', 'Submit an error report.');
2191
- });
2192
- }, 500);
2193
- },
2194
 
2195
- /**
2196
- * If process.execute exists, process.data and process.onResponse is not used
2197
- * process = { data: {}, onResponse: (resp) => {}, onAfterClose: () => {}, execute: () => {}, isShowCancelButton: bool }
2198
- * @param {object} process
2199
- */
2200
- process: function process(_process) {
2201
- if (typeof _process.execute !== 'function' && (!_process.data || !_process.onResponse)) {
 
2202
  Swal.close();
2203
- showError('process.data and / or process.onResponse is not set');
2204
- return;
2205
- } // TODO move to backend and get the contents as xhr response?
2206
-
 
 
 
 
 
 
 
2207
 
2208
- if (!that.backups.modal.process.html || !that.backups.modal.process.cancelBtnTxt) {
2209
- var $modal = $('#wpstg--modal--backup--process');
2210
- var html = $modal.html();
2211
- var btnTxt = $modal.attr('data-cancelButtonText');
2212
- that.backups.modal.process.html = html || null;
2213
- that.backups.modal.process.cancelBtnTxt = btnTxt || null;
2214
- $modal.remove();
2215
- }
 
 
 
2216
 
2217
- $('body').off('click', '.wpstg--modal--process--logs--tail').on('click', '.wpstg--modal--process--logs--tail', function (e) {
2218
- e.preventDefault();
2219
- var container = Swal.getContainer();
2220
- var $logs = $(container).find('.wpstg--modal--process--logs');
2221
- $logs.toggle();
2222
 
2223
- if ($logs.is(':visible')) {
2224
- container.childNodes[0].style.width = '100%';
2225
- container.style['z-index'] = 9999;
2226
- } else {
2227
- container.childNodes[0].style.width = '600px';
 
 
2228
  }
2229
- });
2230
- _process.isShowCancelButton = false !== _process.isShowCancelButton;
2231
- that.backups.modal.process.modal = Swal.mixin({
2232
- customClass: {
2233
- cancelButton: 'wpstg--btn--cancel wpstg-blue-primary wpstg-link-btn',
2234
- content: 'wpstg--process--content'
2235
- },
2236
- buttonsStyling: false
2237
- }).fire({
2238
- html: that.backups.modal.process.html,
2239
- cancelButtonText: that.backups.modal.process.cancelBtnTxt,
2240
- showCancelButton: _process.isShowCancelButton,
2241
- showConfirmButton: false,
2242
- allowOutsideClick: false,
2243
- allowEscapeKey: false,
2244
- width: 600,
2245
- onRender: function onRender() {
2246
- var _btnCancel = Swal.getContainer().getElementsByClassName('swal2-cancel wpstg--btn--cancel')[0];
2247
-
2248
- var btnCancel = _btnCancel.cloneNode(true);
2249
-
2250
- _btnCancel.parentNode.replaceChild(btnCancel, _btnCancel);
2251
-
2252
- btnCancel.addEventListener('click', function (e) {
2253
- if (confirm('Are You Sure? This will cancel the process!')) {
2254
- Swal.close();
2255
- }
2256
- });
2257
 
2258
- if (typeof _process.execute === 'function') {
2259
- _process.execute();
2260
-
2261
- return;
2262
- }
2263
 
2264
- if (!_process.data || !_process.onResponse) {
2265
- Swal.close();
2266
- showError('process.data and / or process.onResponse is not set');
2267
- return;
 
2268
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2269
 
2270
- that.ajax(_process.data, _process.onResponse);
2271
- },
2272
- onAfterClose: function onAfterClose() {
2273
- return typeof _process.onAfterClose === 'function' && _process.onAfterClose();
2274
- },
2275
- onClose: function onClose() {
2276
- console.log('cancelled');
2277
- that.backups.cancel();
2278
- }
2279
- });
2280
- },
2281
- processResponse: function processResponse(response, useTitle) {
2282
- if (response === null) {
2283
- Swal.close();
2284
- showError('Invalid Response; null');
2285
- throw new Error("Invalid Response; " + response);
2286
- }
2287
-
2288
- var $container = $(Swal.getContainer());
2289
 
2290
- var title = function title() {
2291
- if ((response.title || response.statusTitle) && useTitle === true) {
2292
- $container.find('.wpstg--modal--process--title').text(response.title || response.statusTitle);
2293
- }
2294
- };
2295
 
2296
- var percentage = function percentage() {
2297
- if (response.percentage) {
2298
- $container.find('.wpstg--modal--process--percent').text(response.percentage);
2299
- }
2300
- };
2301
 
2302
- var logs = function logs() {
2303
- if (!response.messages) {
2304
- return;
2305
- }
2306
 
2307
- var $logsContainer = $container.find('.wpstg--modal--process--logs');
2308
- var stoppingTypes = [that.backups.messages.ERROR, that.backups.messages.CRITICAL];
2309
 
2310
- var appendMessage = function appendMessage(message) {
2311
- if (Array.isArray(message)) {
2312
- for (var _iterator = _createForOfIteratorHelperLoose(message), _step; !(_step = _iterator()).done;) {
2313
- var item = _step.value;
2314
- appendMessage(item);
2315
  }
2316
 
2317
- return;
 
 
 
 
 
 
2318
  }
 
 
 
 
 
 
 
 
2319
 
2320
- var msgClass = "wpstg--modal--process--msg--" + message.type.toLowerCase();
2321
- $logsContainer.append("<p class=\"" + msgClass + "\">[" + message.type + "] - [" + message.date + "] - " + message.message + "</p>");
2322
 
2323
- if (stoppingTypes.includes(message.type.toLowerCase())) {
2324
- that.backups.cancel();
2325
- setTimeout(that.backups.logsModal, 500);
2326
  }
2327
  };
2328
 
2329
- for (var _iterator2 = _createForOfIteratorHelperLoose(response.messages), _step2; !(_step2 = _iterator2()).done;) {
2330
- var message = _step2.value;
 
 
 
2331
 
2332
- if (!message) {
2333
- continue;
 
2334
  }
2335
 
2336
- that.backups.messages.addMessage(message);
2337
- appendMessage(message);
2338
- }
2339
 
2340
- if ($logsContainer.is(':visible')) {
2341
- $logsContainer.scrollTop($logsContainer[0].scrollHeight);
2342
- }
 
 
 
2343
 
2344
- if (!that.backups.messages.shouldWarn()) {
2345
- return;
2346
- }
2347
 
2348
- var $btnShowLogs = $container.find('.wpstg--modal--process--logs--tail');
2349
- $btnShowLogs.html($btnShowLogs.attr('data-txt-bad'));
2350
- $btnShowLogs.find('.wpstg--modal--logs--critical-count').text(that.backups.messages.countByType(that.backups.messages.CRITICAL));
2351
- $btnShowLogs.find('.wpstg--modal--logs--error-count').text(that.backups.messages.countByType(that.backups.messages.ERROR));
2352
- $btnShowLogs.find('.wpstg--modal--logs--warning-count').text(that.backups.messages.countByType(that.backups.messages.WARNING));
2353
- };
2354
 
2355
- title();
2356
- percentage();
2357
- logs();
 
 
2358
 
2359
- if (response.status === true && response.job_done === true) {
2360
- that.backups.timer.stop();
2361
- that.backups.isCancelled = true;
2362
- }
2363
- },
2364
- requestData: function requestData(notation, data) {
2365
- var obj = {};
2366
- var keys = notation.split('.');
2367
- var lastIndex = keys.length - 1;
2368
- keys.reduce(function (accumulated, current, index) {
2369
- return accumulated[current] = index >= lastIndex ? data : {};
2370
- }, obj);
2371
- return obj;
2372
- },
2373
- logsModal: function logsModal() {
2374
- Swal.fire({
2375
- html: "<div class=\"wpstg--modal--error--logs\" style=\"display:block\"></div><div class=\"wpstg--modal--process--logs\" style=\"display:block\"></div>",
2376
- width: '95%',
2377
- onRender: function onRender() {
2378
- var $container = $(Swal.getContainer());
2379
- $container[0].style['z-index'] = 9999;
2380
- var $logsContainer = $container.find('.wpstg--modal--process--logs');
2381
- var $errorContainer = $container.find('.wpstg--modal--error--logs');
2382
- var $translations = $('#wpstg--js--translations');
2383
- var messages = that.backups.messages;
2384
- var title = $translations.attr('data-modal-logs-title').replace('{critical}', messages.countByType(messages.CRITICAL)).replace('{errors}', messages.countByType(messages.ERROR)).replace('{warnings}', messages.countByType(messages.WARNING));
2385
- $errorContainer.before("<h3>" + title + "</h3>");
2386
- var warnings = [that.backups.messages.CRITICAL, that.backups.messages.ERROR, that.backups.messages.WARNING];
2387
 
2388
  if (!that.backups.messages.shouldWarn()) {
2389
- $errorContainer.hide();
2390
  }
2391
 
2392
- for (var _iterator3 = _createForOfIteratorHelperLoose(messages.data.all), _step3; !(_step3 = _iterator3()).done;) {
2393
- var message = _step3.value;
2394
- var msgClass = "wpstg--modal--process--msg--" + message.type.toLowerCase(); // TODO RPoC
 
 
 
2395
 
2396
- if (warnings.includes(message.type)) {
2397
- $errorContainer.append("<p class=\"" + msgClass + "\">[" + message.type + "] - [" + message.date + "] - " + message.message + "</p>");
2398
- }
2399
 
2400
- $logsContainer.append("<p class=\"" + msgClass + "\">[" + message.type + "] - [" + message.date + "] - " + message.message + "</p>");
2401
- }
2402
- },
2403
- onOpen: function onOpen(container) {
2404
- var $logsContainer = $(container).find('.wpstg--modal--process--logs');
2405
- $logsContainer.scrollTop($logsContainer[0].scrollHeight);
2406
  }
2407
- });
2408
- },
2409
- downloadModal: function downloadModal(_ref3) {
2410
- var _ref3$title = _ref3.title,
2411
- title = _ref3$title === void 0 ? null : _ref3$title,
2412
- _ref3$titleExport = _ref3.titleExport,
2413
- titleExport = _ref3$titleExport === void 0 ? null : _ref3$titleExport,
2414
- _ref3$id = _ref3.id,
2415
- id = _ref3$id === void 0 ? null : _ref3$id,
2416
- _ref3$url = _ref3.url,
2417
- url = _ref3$url === void 0 ? null : _ref3$url,
2418
- _ref3$btnTxtCancel = _ref3.btnTxtCancel,
2419
- btnTxtCancel = _ref3$btnTxtCancel === void 0 ? 'Cancel' : _ref3$btnTxtCancel,
2420
- _ref3$btnTxtConfirm = _ref3.btnTxtConfirm,
2421
- btnTxtConfirm = _ref3$btnTxtConfirm === void 0 ? 'Download' : _ref3$btnTxtConfirm;
2422
-
2423
- if (null === that.backups.modal.download.html) {
2424
- var $el = $('#wpstg--modal--backup--download');
2425
- that.backups.modal.download.html = $el.html();
2426
- $el.remove();
2427
- }
2428
-
2429
- var exportModal = function exportModal() {
2430
- return Swal.fire({
2431
- html: "<h2>" + titleExport + "</h2><span class=\"wpstg-loader\"></span>",
2432
- showCancelButton: false,
2433
- showConfirmButton: false,
2434
  onRender: function onRender() {
2435
- that.ajax({
2436
- action: 'wpstg--backups--export',
2437
- accessToken: wpstg.accessToken,
2438
- nonce: wpstg.nonce,
2439
- id: id
2440
- }, function (response) {
2441
- if (!response || !response.success || !response.data || response.data.length < 1) {
2442
- return;
 
 
 
 
 
 
 
 
 
 
 
 
2443
  }
2444
 
2445
- var a = document.createElement('a');
2446
- a.style.display = 'none';
2447
- a.href = response.data;
2448
- document.body.appendChild(a);
2449
- a.click();
2450
- document.body.removeChild(a);
2451
- Swal.close();
2452
- });
2453
  }
2454
  });
2455
- };
2456
-
2457
- Swal.mixin({
2458
- customClass: {
2459
- cancelButton: 'wpstg--btn--cancel wpstg-blue-primary wpstg-link-btn',
2460
- confirmButton: 'wpstg--btn--confirm wpstg-blue-primary wpstg-button wpstg-link-btn',
2461
- actions: 'wpstg--modal--actions'
2462
- },
2463
- buttonsStyling: false
2464
- }).fire({
2465
- icon: 'success',
2466
- html: that.backups.modal.download.html.replace('{title}', title).replace('{btnTxtLog}', 'Show Logs'),
2467
- cancelButtonText: btnTxtCancel,
2468
- confirmButtonText: btnTxtConfirm,
2469
- showCancelButton: true,
2470
- showConfirmButton: true
2471
- }).then(function (isConfirm) {
2472
- if (!isConfirm || !isConfirm.value) {
2473
- return;
2474
- }
2475
-
2476
- if (url && url.length > 0) {
2477
- window.location.href = url;
2478
- return;
2479
  }
2480
 
2481
- exportModal();
2482
- });
2483
- },
2484
- importModal: function importModal() {
2485
- var importSiteBackup = function importSiteBackup(data) {
2486
- resetErrors();
2487
-
2488
- if (that.backups.isCancelled) {
2489
- console.log('cancelled'); // Swal.close();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2490
 
2491
- return;
2492
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2493
 
2494
- that.backups.timer.start();
 
 
 
2495
 
2496
- var statusStop = function statusStop() {
2497
- console.log('Status: Stop');
2498
- clearInterval(that.backups.processInfo.interval);
2499
- that.backups.processInfo.interval = null;
2500
- };
 
2501
 
2502
- var status = function status() {
2503
- if (that.backups.processInfo.interval !== null) {
2504
  return;
2505
  }
2506
 
2507
- console.log('Status: Start');
2508
- that.backups.processInfo.interval = setInterval(function () {
2509
- if (true === that.backups.isCancelled) {
2510
- statusStop();
2511
- return;
2512
- }
2513
 
2514
- if (that.backups.status.hasResponse === false) {
 
2515
  return;
2516
  }
2517
 
2518
- that.backups.status.hasResponse = false;
2519
- fetch(ajaxurl + "?action=wpstg--backups--status&process=restore&accessToken=" + wpstg.accessToken + "&nonce=" + wpstg.nonce).then(function (res) {
2520
- return res.json();
2521
- }).then(function (res) {
2522
- that.backups.status.hasResponse = true;
2523
-
2524
- if (typeof res === 'undefined') {
2525
  statusStop();
 
2526
  }
2527
 
2528
- if (that.backups.processInfo.title === res.currentStatusTitle) {
2529
  return;
2530
  }
2531
 
2532
- that.backups.processInfo.title = res.currentStatusTitle;
2533
- var $container = $(Swal.getContainer());
2534
- $container.find('.wpstg--modal--process--title').text(res.currentStatusTitle);
2535
- $container.find('.wpstg--modal--process--percent').text('0');
2536
- })["catch"](function (e) {
2537
- that.backups.status.hasResponse = true;
2538
- showAjaxFatalError(e, '', 'Submit an error report.');
2539
- });
2540
- }, 5000);
2541
- };
2542
 
2543
- WPStaging.ajax({
2544
- action: 'wpstg--backups--import',
2545
- accessToken: wpstg.accessToken,
2546
- nonce: wpstg.nonce
2547
- }, function (response) {
2548
- if (typeof response === 'undefined') {
2549
- setTimeout(function () {
2550
- importSiteBackup(data);
2551
- }, wpstg.delayReq);
2552
- return;
2553
- }
2554
 
2555
- that.backups.processResponse(response, true);
 
 
 
 
 
 
 
 
 
 
 
 
 
2556
 
2557
- if (!that.backups.processInfo.interval) {
2558
- status();
2559
- }
 
 
 
 
 
 
 
 
2560
 
2561
- if (response.status === false) {
2562
- importSiteBackup(data);
2563
- } else if (response.status === true) {
2564
- $('#wpstg--progress--status').text('Backup successfully imported!');
2565
- that.backups.type = null;
2566
 
2567
- if (that.backups.messages.shouldWarn()) {
2568
- // noinspection JSIgnoredPromiseFromCall
2569
- that.backups.fetchListing();
2570
- that.backups.logsModal();
2571
- return;
2572
  }
2573
 
2574
- statusStop();
2575
- var logEntries = $('.wpstg--modal--process--logs').get(1).innerHTML;
2576
- var html = '<div class="wpstg--modal--process--logs">' + logEntries + '</div>';
2577
- var issueFound = html.includes('wpstg--modal--process--msg--warning') || html.includes('wpstg--modal--process--msg--error') ? 'Issues(s) found! ' : '';
2578
- console.log('errors found: ' + issueFound); // var errorMessage = html.includes('wpstg--modal--process--msg--error') ? 'Errors(s) found! ' : '';
2579
- // var Message = warningMessage + errorMessage;
2580
- // Swal.close();
2581
 
2582
- Swal.fire({
2583
- icon: 'success',
2584
- title: 'Finished',
2585
- html: 'System imported from backup. <br/><span class="wpstg--modal--process--msg-found">' + issueFound + '</span><button class="wpstg--modal--process--logs--tail" data-txt-bad="">Show Logs</button><br/>' + html
2586
- }); // noinspection JSIgnoredPromiseFromCall
 
2587
 
2588
- that.backups.fetchListing();
2589
- } else {
2590
- setTimeout(function () {
2591
- importSiteBackup(data);
2592
- }, wpstg.delayReq);
2593
- }
2594
- }, 'json', false, 0, // Don't retry upon failure
2595
- 1.25);
2596
- };
 
 
 
2597
 
2598
- if (!that.backups.modal["import"].html) {
2599
- var $modal = $('#wpstg--modal--backup--import'); // Search & Replace Form
2600
-
2601
- var $form = $modal.find('.wpstg--modal--backup--import--search-replace--input--container');
2602
- that.backups.modal["import"].searchReplaceForm = $form.html();
2603
- $form.find('.wpstg--modal--backup--import--search-replace--input-group').remove();
2604
- $form.html(that.backups.modal["import"].searchReplaceForm.replace(/{i}/g, 0));
2605
- that.backups.modal["import"].html = $modal.html();
2606
- that.backups.modal["import"].baseDirectory = $modal.attr('data-baseDirectory');
2607
- that.backups.modal["import"].btnTxtNext = $modal.attr('data-nextButtonText');
2608
- that.backups.modal["import"].btnTxtConfirm = $modal.attr('data-confirmButtonText');
2609
- that.backups.modal["import"].btnTxtCancel = $modal.attr('data-cancelButtonText');
2610
- $modal.remove();
2611
- }
2612
-
2613
- that.backups.modal["import"].data.search = [];
2614
- that.backups.modal["import"].data.replace = [];
2615
- var $btnConfirm = null;
2616
- Swal.mixin({
2617
- customClass: {
2618
- confirmButton: 'wpstg--btn--confirm wpstg-blue-primary wpstg-button wpstg-link-btn',
2619
- cancelButton: 'wpstg--btn--cancel wpstg-blue-primary wpstg-link-btn',
2620
- actions: 'wpstg--modal--actions'
2621
- },
2622
- buttonsStyling: false // progressSteps: ['1', '2']
2623
-
2624
- }).queue([{
2625
- html: that.backups.modal["import"].html,
2626
- confirmButtonText: that.backups.modal["import"].btnTxtNext,
2627
- showCancelButton: false,
2628
- showConfirmButton: true,
2629
- showLoaderOnConfirm: true,
2630
- width: 650,
2631
- onRender: function onRender() {
2632
- // $('.wpstg--modal--actions .swal2-confirm').hide();
2633
- // todo: hide this again
2634
- $('.wpstg--modal--actions .swal2-confirm').show();
2635
- $('.wpstg--modal--actions .swal2-confirm').prop('disabled', false);
2636
- that.backups.modal["import"].containerUpload = $('.wpstg--modal--backup--import--upload');
2637
- that.backups.modal["import"].containerFilesystem = $('.wpstg--modal--backup--import--filesystem');
2638
- that.backups.modal["import"].containerConfigure = $('.wpstg--modal--backup--import--configure');
2639
- },
2640
- preConfirm: function preConfirm() {
2641
- var body = new FormData();
2642
- body.append('accessToken', wpstg.accessToken);
2643
- body.append('nonce', wpstg.nonce);
2644
- body.append('filePath', that.backups.modal["import"].data.file);
2645
- that.backups.modal["import"].data.search.forEach(function (item, index) {
2646
- body.append("search[" + index + "]", item);
2647
- });
2648
- that.backups.modal["import"].data.replace.forEach(function (item, index) {
2649
- body.append("replace[" + index + "]", item);
2650
- });
2651
- return fetch(ajaxurl + "?action=wpstg--backups--import--file-info", {
2652
- method: 'POST',
2653
- body: body
2654
- }).then(handleFetchErrors).then(function (res) {
2655
- return res.json();
2656
- }).then(function (html) {
2657
- return Swal.insertQueueStep({
2658
- html: html,
2659
- confirmButtonText: that.backups.modal["import"].btnTxtConfirm,
2660
- cancelButtonText: that.backups.modal["import"].btnTxtCancel,
2661
- showCancelButton: true
2662
- });
2663
- })["catch"](function (e) {
2664
- return showAjaxFatalError(e, '', 'Submit an error report.');
2665
- });
2666
- }
2667
- }]).then(function (res) {
2668
- if (!res || !res.value || !res.value[1] || res.value[1] !== true) {
2669
- return;
2670
  }
2671
 
2672
- that.backups.isCancelled = false;
2673
- var data = that.backups.modal["import"].data;
2674
- data['file'] = that.backups.modal["import"].baseDirectory + data['file'];
2675
- WPStaging.ajax({
2676
- action: 'wpstg--backups--prepare-import',
2677
- accessToken: wpstg.accessToken,
2678
- nonce: wpstg.nonce,
2679
- wpstgImportData: data
2680
- }, function (response) {
2681
- if (response.success) {
2682
- that.backups.process({
2683
- execute: function execute() {
2684
- that.backups.messages.reset();
2685
- importSiteBackup(data);
2686
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2687
  });
2688
- } else {
2689
- showAjaxFatalError(response.data, '', 'Submit an error report.');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2690
  }
2691
- }, 'json', false, 0, 1.25);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2692
  });
2693
- }
2694
- };
2695
- window.addEventListener('backupListingFinished', function () {
2696
- fetch(ajaxurl + "?action=wpstg--backups--import--file-list&_=" + Math.random() + "&accessToken=" + wpstg.accessToken + "&nonce=" + wpstg.nonce + "&withTemplate=true").then(handleFetchErrors).then(function (res) {
2697
- return res.json();
2698
- }).then(function (res) {
2699
- var $ul = $('.wpstg-backup-list ul');
2700
- $ul.empty();
2701
- $ul.html(res);
2702
- })["catch"](function (e) {
2703
- return showAjaxFatalError(e, '', 'Submit an error report.');
2704
  });
2705
- });
2706
- return that;
2707
- }(jQuery);
2708
-
2709
- jQuery(document).ready(function () {
2710
- WPStaging.init(); // This is necessary to make WPStaging var accessibile in WP Staging PRO js script
2711
-
2712
- window.WPStaging = WPStaging;
2713
- });
2714
- /**
2715
- * Report Issue modal
2716
- */
2717
-
2718
- jQuery(document).ready(function ($) {
2719
- $('#wpstg-report-issue-button').on('click', function (e) {
2720
- $('.wpstg-report-issue-form').toggleClass('wpstg-report-show');
2721
- e.preventDefault();
2722
- });
2723
- $('body').on('click', '#wpstg-backups-report-issue-button', function (e) {
2724
- $('.wpstg-report-issue-form').toggleClass('wpstg-report-show');
2725
- console.log('test');
2726
- e.preventDefault();
2727
- });
2728
- $('#wpstg-report-cancel').on('click', function (e) {
2729
- $('.wpstg-report-issue-form').removeClass('wpstg-report-show');
2730
- e.preventDefault();
2731
- });
2732
- /*
2733
- * Close Success Modal
2734
- */
2735
 
2736
- $('body').on('click', '#wpstg-success-button', function (e) {
2737
- e.preventDefault();
2738
- $('.wpstg-report-issue-form').removeClass('wpstg-report-show');
 
2739
  });
 
 
 
2740
 
2741
- function sendIssueReport(button, forceSend) {
2742
- if (forceSend === void 0) {
2743
- forceSend = 'false';
2744
- }
 
 
 
 
 
 
 
 
 
 
 
 
2745
 
2746
- var spinner = button.next();
2747
- var email = $('.wpstg-report-email').val();
2748
- var hosting_provider = $('.wpstg-report-hosting-provider').val();
2749
- var message = $('.wpstg-report-description').val();
2750
- var syslog = $('.wpstg-report-syslog').is(':checked');
2751
- var terms = $('.wpstg-report-terms').is(':checked');
2752
- button.attr('disabled', true);
2753
- spinner.css('visibility', 'visible');
2754
- $.ajax({
2755
- url: ajaxurl,
2756
- type: 'POST',
2757
- dataType: 'json',
2758
- async: true,
2759
- data: {
2760
- 'action': 'wpstg_send_report',
2761
- 'accessToken': wpstg.accessToken,
2762
- 'nonce': wpstg.nonce,
2763
- 'wpstg_email': email,
2764
- 'wpstg_provider': hosting_provider,
2765
- 'wpstg_message': message,
2766
- 'wpstg_syslog': +syslog,
2767
- 'wpstg_terms': +terms,
2768
- 'wpstg_force_send': forceSend
2769
- }
2770
- }).done(function (data) {
2771
- button.attr('disabled', false);
2772
- spinner.css('visibility', 'hidden');
2773
-
2774
- if (data.errors.length > 0) {
2775
- $('.wpstg-report-issue-form .wpstg-message').remove();
2776
- var errorMessage = $('<div />').addClass('wpstg-message wpstg-error-message');
2777
- $.each(data.errors, function (key, value) {
2778
- if (value.status === 'already_submitted') {
2779
- errorMessage = '';
2780
- Swal.fire({
2781
- title: '',
2782
- customClass: {
2783
- container: 'wpstg-issue-resubmit-confirmation'
2784
- },
2785
- icon: 'warning',
2786
- html: value.message,
2787
- showCloseButton: true,
2788
- showCancelButton: true,
2789
- focusConfirm: false,
2790
- confirmButtonText: 'Yes',
2791
- cancelButtonText: 'No'
2792
- }).then(function (result) {
2793
- if (result.isConfirmed) {
2794
- sendIssueReport(button, 'true');
2795
- }
2796
- });
2797
- } else {
2798
- errorMessage.append('<p>' + value + '</p>');
2799
- }
2800
- });
2801
- $('.wpstg-report-issue-form').prepend(errorMessage);
2802
- } else {
2803
- var successMessage = $('<div />').addClass('wpstg-message wpstg-success-message');
2804
- successMessage.append('<p>Thanks for submitting your request! You should receive an auto reply mail with your ticket ID immediately for confirmation!<br><br>If you do not get that mail please contact us directly at <strong>support@wp-staging.com</strong></p>');
2805
- $('.wpstg-report-issue-form').html(successMessage);
2806
- $('.wpstg-success-message').append('<div style="float:right;margin-top:10px;"><a id="wpstg-success-button" href="#">Close</a></div>'); // Hide message
2807
 
2808
- setTimeout(function () {
2809
- $('.wpstg-report-issue-form').removeClass('wpstg-report-active');
2810
- }, 2000);
2811
  }
2812
- });
2813
- }
2814
 
2815
- $('#wpstg-report-submit').on('click', function (e) {
2816
- var self = $(this);
2817
- sendIssueReport(self, 'false');
2818
- e.preventDefault();
2819
- }); // Open/close actions drop down menu
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2820
 
2821
- $(document).on('click', '.wpstg-dropdown>.wpstg-dropdown-toggler', function (e) {
2822
- e.preventDefault();
2823
- $(e.target).next('.wpstg-dropdown-menu').toggleClass('shown');
2824
- }); // Close action drop down menu if clicked anywhere outside
2825
 
2826
- document.addEventListener('click', function (event) {
2827
- var isClickInside = event.target.closest('.wpstg-dropdown-toggler');
2828
 
2829
- if (!isClickInside) {
2830
- var dropDown = document.getElementsByClassName('wpstg-dropdown-menu');
2831
 
2832
- for (var i = 0; i < dropDown.length; i++) {
2833
- dropDown[i].classList.remove('shown');
 
2834
  }
2835
- }
2836
  });
2837
- });
 
 
1
+ (function () {
2
+ 'use strict';
3
+
4
+ function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
5
+ try {
6
+ var info = gen[key](arg);
7
+ var value = info.value;
8
+ } catch (error) {
9
+ reject(error);
10
+ return;
11
+ }
12
 
13
+ if (info.done) {
14
+ resolve(value);
15
+ } else {
16
+ Promise.resolve(value).then(_next, _throw);
17
+ }
18
+ }
19
 
20
+ function _asyncToGenerator(fn) {
21
+ return function () {
22
+ var self = this,
23
+ args = arguments;
24
+ return new Promise(function (resolve, reject) {
25
+ var gen = fn.apply(self, args);
26
 
27
+ function _next(value) {
28
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
29
+ }
30
 
31
+ function _throw(err) {
32
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
33
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
 
35
+ _next(undefined);
36
+ });
37
+ };
38
+ }
 
39
 
40
+ function _extends() {
41
+ _extends = Object.assign || function (target) {
42
+ for (var i = 1; i < arguments.length; i++) {
43
+ var source = arguments[i];
44
 
45
+ for (var key in source) {
46
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
47
+ target[key] = source[key];
48
+ }
49
+ }
50
+ }
 
51
 
52
+ return target;
53
+ };
54
 
55
+ return _extends.apply(this, arguments);
56
+ }
 
 
 
 
 
57
 
58
+ function _unsupportedIterableToArray(o, minLen) {
59
+ if (!o) return;
60
+ if (typeof o === "string") return _arrayLikeToArray(o, minLen);
61
+ var n = Object.prototype.toString.call(o).slice(8, -1);
62
+ if (n === "Object" && o.constructor) n = o.constructor.name;
63
+ if (n === "Map" || n === "Set") return Array.from(o);
64
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
65
+ }
66
 
67
+ function _arrayLikeToArray(arr, len) {
68
+ if (len == null || len > arr.length) len = arr.length;
 
 
 
 
 
 
 
 
 
 
 
 
 
69
 
70
+ for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
71
 
72
+ return arr2;
73
+ }
 
 
 
 
 
 
 
 
74
 
75
+ function _createForOfIteratorHelperLoose(o, allowArrayLike) {
76
+ var it;
77
 
78
+ if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) {
79
+ if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
80
+ if (it) o = it;
81
+ var i = 0;
82
+ return function () {
83
+ if (i >= o.length) return {
84
+ done: true
85
+ };
86
+ return {
87
+ done: false,
88
+ value: o[i++]
89
+ };
90
+ };
91
  }
92
+
93
+ throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
94
  }
95
 
96
+ it = o[Symbol.iterator]();
97
+ return it.next.bind(it);
98
  }
99
+
100
  /**
101
+ * WP Staging basic jQuery replacement
102
+ */
 
 
 
 
103
 
104
+ /**
105
+ * Shortcut for document.querySelector() or jQuery's $()
106
+ * Return single element only
107
+ */
108
+ function qs(selector) {
109
+ return document.querySelector(selector);
110
+ }
111
+ /**
112
+ * Shortcut for document.querySelector() or jQuery's $()
113
+ * Return collection of elements
114
+ */
115
 
116
+ function all(selector) {
117
+ return document.querySelectorAll(selector);
118
+ }
119
+ /**
120
+ * alternative of jQuery - $(parent).on(event, selector, handler)
121
+ */
122
 
123
+ function addEvent(parent, evt, selector, handler) {
124
+ parent.addEventListener(evt, function (event) {
125
+ if (event.target.matches(selector + ', ' + selector + ' *')) {
126
+ handler(event.target.closest(selector), event);
127
+ }
128
+ }, false);
129
+ }
130
+ function slideDown(element, duration) {
131
+ if (duration === void 0) {
132
+ duration = 400;
133
  }
134
 
135
+ element.style.display = 'block';
136
+ element.style.overflow = 'hidden';
137
+ var height = element.offsetHeight;
138
+ element.style.height = '0px';
139
+ element.style.transitionProperty = 'height';
140
+ element.style.transitionDuration = duration + 'ms';
141
+ setTimeout(function () {
142
+ element.style.height = height + 'px';
143
+ window.setTimeout(function () {
144
+ element.style.removeProperty('height');
145
+ element.style.removeProperty('overflow');
146
+ element.style.removeProperty('transition-duration');
147
+ element.style.removeProperty('transition-property');
148
+ }, duration);
149
+ }, 0);
150
+ }
151
+ function slideUp(element, duration) {
152
+ if (duration === void 0) {
153
+ duration = 400;
154
  }
 
 
 
 
 
 
155
 
156
+ element.style.display = 'block';
157
+ element.style.overflow = 'hidden';
158
+ var height = element.offsetHeight;
159
+ element.style.height = height + 'px';
160
+ element.style.transitionProperty = 'height';
161
+ element.style.transitionDuration = duration + 'ms';
162
+ setTimeout(function () {
163
+ element.style.height = '0px';
164
+ window.setTimeout(function () {
165
+ element.style.display = 'none';
166
+ element.style.removeProperty('height');
167
+ element.style.removeProperty('overflow');
168
+ element.style.removeProperty('transition-duration');
169
+ element.style.removeProperty('transition-property');
170
+ }, duration);
171
+ }, 0);
172
+ }
173
+ function getNextSibling(element, selector) {
174
+ var sibling = element.nextElementSibling;
175
 
176
+ while (sibling) {
177
+ if (sibling.matches(selector)) {
178
+ return sibling;
179
+ }
180
 
181
+ sibling = sibling.nextElementSibling;
182
+ }
183
+ }
184
+ function getParents(element, selector) {
185
+ var result = [];
186
 
187
+ for (var parent = element && element.parentElement; parent; parent = parent.parentElement) {
188
+ if (parent.matches(selector)) {
189
+ result.push(parent);
190
+ }
191
+ }
192
 
193
+ return result;
194
+ }
 
195
 
 
 
 
196
  /**
197
+ * Enable/Disable cloning for staging site
198
+ */
199
 
200
+ var WpstgCloneStaging = /*#__PURE__*/function () {
201
+ function WpstgCloneStaging(pageWrapperId, wpstgObject) {
202
+ if (pageWrapperId === void 0) {
203
+ pageWrapperId = '#wpstg-clonepage-wrapper';
204
+ }
205
 
206
+ if (wpstgObject === void 0) {
207
+ wpstgObject = wpstg;
208
+ }
 
 
209
 
210
+ this.pageWrapper = qs(pageWrapperId);
211
+ this.wpstgObject = wpstgObject;
212
+ this.enableButtonId = '#wpstg-enable-staging-cloning';
213
+ this.enableAction = 'wpstg_enable_staging_cloning';
214
+ this.notyf = new Notyf({
215
+ duration: 10000,
216
+ position: {
217
+ x: 'center',
218
+ y: 'bottom'
219
+ },
220
+ dismissible: true,
221
+ types: [{
222
+ type: 'warning',
223
+ background: 'orange',
224
+ icon: false
225
+ }]
226
+ });
227
+ this.init();
228
  }
229
 
230
+ var _proto = WpstgCloneStaging.prototype;
 
231
 
232
+ _proto.addEvents = function addEvents() {
233
+ var _this = this;
234
+
235
+ if (this.pageWrapper === null) {
236
+ return;
237
+ }
238
+
239
+ addEvent(this.pageWrapper, 'click', this.enableButtonId, function () {
240
+ _this.sendRequest(_this.enableAction);
241
+ });
242
  };
243
 
244
+ _proto.init = function init() {
245
+ this.addEvents();
246
+ };
247
 
248
+ _proto.sendRequest = function sendRequest(action) {
249
+ var _this2 = this;
250
+
251
+ fetch(this.wpstgObject.ajaxUrl, {
252
+ method: 'POST',
253
+ credentials: 'same-origin',
254
+ body: new URLSearchParams({
255
+ action: action,
256
+ accessToken: this.wpstgObject.accessToken,
257
+ nonce: this.wpstgObject.nonce
258
+ }),
259
+ headers: {
260
+ 'Content-Type': 'application/x-www-form-urlencoded'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
261
  }
262
+ }).then(function (response) {
263
+ if (response.ok) {
264
+ return response.json();
 
 
 
 
265
  }
 
 
 
 
 
266
 
267
+ return Promise.reject(response);
268
+ }).then(function (data) {
269
+ // Reload current page if successful.
270
+ if ('undefined' !== typeof data.success && data.success) {
271
+ location.reload();
272
+ return;
273
+ } // There will be message probably in case of error
274
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
275
 
276
+ if ('undefined' !== typeof data.message) {
277
+ _this2.notyf.error(data.message);
 
278
 
279
+ return;
280
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
281
 
282
+ _this2.notyf.error(_this2.wpstgObject.i18n['somethingWentWrong']);
283
+ })["catch"](function (error) {
284
+ console.warn(_this2.wpstgObject.i18n['somethingWentWrong'], error);
285
+ });
286
+ };
287
 
288
+ return WpstgCloneStaging;
289
+ }();
 
290
 
291
+ /**
292
+ * Fetch directory direct child directories
293
+ */
294
 
295
+ var WpstgDirectoryNavigation = /*#__PURE__*/function () {
296
+ function WpstgDirectoryNavigation(directoryListingSelector, wpstgObject, notyf) {
297
+ if (directoryListingSelector === void 0) {
298
+ directoryListingSelector = '#wpstg-directories-listing';
 
 
 
 
 
 
299
  }
300
 
301
+ if (wpstgObject === void 0) {
302
+ wpstgObject = wpstg;
303
  }
 
 
 
 
 
 
 
 
304
 
305
+ if (notyf === void 0) {
306
+ notyf = null;
307
+ }
 
 
308
 
309
+ this.directoryListingContainer = qs(directoryListingSelector);
310
+ this.wpstgObject = wpstgObject;
311
+ this.dirCheckboxSelector = '.wpstg-check-dir';
312
+ this.dirExpandSelector = '.wpstg-expand-dirs';
313
+ this.unselectAllDirsSelector = '.wpstg-unselect-dirs';
314
+ this.selectDefaultDirsSelector = '.wpstg-select-dirs-default';
315
+ this.fetchChildrenAction = 'wpstg_fetch_dir_childrens';
316
+ this.currentCheckboxElement = null;
317
+ this.currentParentDiv = null;
318
+ this.currentLoader = null;
319
+ this.existingExcludes = [];
320
+ this.excludedDirectories = [];
321
+ this.isDefaultSelected = false;
322
+ this.notyf = notyf;
323
+ this.init();
324
  }
325
 
326
+ var _proto = WpstgDirectoryNavigation.prototype;
 
 
 
 
327
 
328
+ _proto.addEvents = function addEvents() {
329
+ var _this = this;
330
 
331
+ if (this.directoryListingContainer === null) {
332
+ console.log('Error: directory navigation add events');
333
+ return;
 
 
 
334
  }
335
 
336
+ addEvent(this.directoryListingContainer, 'click', this.dirExpandSelector, function (element, event) {
337
+ event.preventDefault();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
338
 
339
+ if (_this.toggleDirExpand(element)) {
340
+ _this.sendRequest(_this.fetchChildrenAction, element);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
341
  }
342
  });
343
+ addEvent(this.directoryListingContainer, 'click', this.unselectAllDirsSelector, function () {
344
+ _this.unselectAll();
345
+ });
346
+ addEvent(this.directoryListingContainer, 'click', this.selectDefaultDirsSelector, function () {
347
+ _this.selectDefault();
348
+ });
349
+ };
 
 
 
 
 
 
350
 
351
+ _proto.init = function init() {
352
+ this.addEvents();
353
+ this.parseExcludes();
354
  }
355
+ /**
356
+ * Toggle Dir Expand,
357
+ * Return true if children aren't fetched
358
+ * @param {HTMLElement} element
359
+ * @return {boolean}
360
+ */
361
+ ;
362
 
363
+ _proto.toggleDirExpand = function toggleDirExpand(element) {
364
+ this.currentParentDiv = element.parentElement;
365
+ this.currentCheckboxElement = element.previousSibling;
366
+ this.currentLoader = this.currentParentDiv.querySelector('.wpstg-is-dir-loading');
367
 
368
+ if (this.currentCheckboxElement.getAttribute('data-navigateable', 'false') === 'false') {
369
+ return false;
370
+ }
371
 
372
+ if (this.currentCheckboxElement.getAttribute('data-scanned', 'false') === 'false') {
373
+ return true;
374
+ }
 
375
 
376
+ return false;
377
+ };
 
378
 
379
+ _proto.sendRequest = function sendRequest(action) {
380
+ var _this2 = this;
 
 
 
 
 
 
381
 
382
+ if (this.currentLoader !== null) {
383
+ this.currentLoader.style.display = 'inline-block';
384
+ }
385
 
386
+ fetch(this.wpstgObject.ajaxUrl, {
387
+ method: 'POST',
388
+ credentials: 'same-origin',
389
+ body: new URLSearchParams({
390
+ action: action,
391
+ accessToken: this.wpstgObject.accessToken,
392
+ nonce: this.wpstgObject.nonce,
393
+ dirPath: this.currentCheckboxElement.value,
394
+ isChecked: this.currentCheckboxElement.checked,
395
+ forceDefault: this.isDefaultSelected
396
+ }),
397
+ headers: {
398
+ 'Content-Type': 'application/x-www-form-urlencoded'
399
  }
400
+ }).then(function (response) {
401
+ if (response.ok) {
402
+ return response.json();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
403
  }
 
 
 
 
 
 
404
 
405
+ return Promise.reject(response);
406
+ }).then(function (data) {
407
+ if ('undefined' !== typeof data.success && data.success) {
408
+ _this2.currentCheckboxElement.setAttribute('data-scanned', true);
409
 
410
+ var dirContainer = document.createElement('div');
411
+ dirContainer.classList.add('wpstg-dir');
412
+ dirContainer.classList.add('wpstg-subdir');
413
+ dirContainer.innerHTML = JSON.parse(data.directoryListing);
 
 
 
414
 
415
+ _this2.currentParentDiv.appendChild(dirContainer);
 
 
 
416
 
417
+ if (_this2.currentLoader !== null) {
418
+ _this2.currentLoader.style.display = 'none';
419
+ }
420
 
421
+ slideDown(dirContainer);
422
+ return;
423
  }
424
 
425
+ if (_this2.notyf !== null) {
426
+ _this2.notyf.error(_this2.wpstgObject.i18n['somethingWentWrong']);
427
+ } else {
428
+ alert('Error: ' + _this2.wpstgObject.i18n['somethingWentWrong']);
429
  }
430
+ })["catch"](function (error) {
431
+ console.warn(_this2.wpstgObject.i18n['somethingWentWrong'], error);
432
+ });
433
+ };
434
 
435
+ _proto.getExcludedDirectories = function getExcludedDirectories() {
436
+ var _this3 = this;
437
 
438
+ this.excludedDirectories = [];
439
+ this.directoryListingContainer.querySelectorAll('.wpstg-dir input:not(:checked)').forEach(function (element) {
440
+ if (!_this3.isParentExcluded(element.value)) {
441
+ _this3.excludedDirectories.push(element.value);
442
+ }
443
+ });
444
+ this.existingExcludes.forEach(function (exclude) {
445
+ if (!_this3.isParentExcluded(exclude) && !_this3.isExcludeScanned(exclude)) {
446
+ _this3.excludedDirectories.push(exclude);
447
+ }
448
+ });
449
+ return this.excludedDirectories.join(this.wpstgObject.settings.directorySeparator);
450
+ }
451
+ /**
452
+ * @param {string} path
453
+ * @return {bool}
454
+ */
455
+ ;
456
 
457
+ _proto.isParentExcluded = function isParentExcluded(path) {
458
+ var isParentAlreadyExcluded = false;
459
+ this.excludedDirectories.forEach(function (dir) {
460
+ if (path.startsWith(dir + '/')) {
461
+ isParentAlreadyExcluded = true;
462
  }
463
+ });
464
+ return isParentAlreadyExcluded;
465
+ };
466
+
467
+ _proto.getExtraDirectoriesRootOnly = function getExtraDirectoriesRootOnly() {
468
+ this.getExcludedDirectories();
469
+ var extraDirectories = [];
470
+ this.directoryListingContainer.querySelectorAll(':not(.wpstg-subdir)>.wpstg-dir>input.wpstg-wp-non-core-dir:checked').forEach(function (element) {
471
+ extraDirectories.push(element.value);
472
+ }); // Check if extra directories text area exists
473
+ // TODO: remove extraCustomDirectories code if no one require extraCustomDirectories...
474
+
475
+ var extraDirectoriesTextArea = qs('#wpstg_extraDirectories');
476
+
477
+ if (extraDirectoriesTextArea === null || extraDirectoriesTextArea.value === '') {
478
+ return extraDirectories.join(this.wpstgObject.settings.directorySeparator);
479
  }
480
 
481
+ var extraCustomDirectories = extraDirectoriesTextArea.value.split(/\r?\n/);
482
+ return extraDirectories.concat(extraCustomDirectories).join(this.wpstgObject.settings.directorySeparator);
483
+ };
 
 
 
 
 
 
 
 
 
 
484
 
485
+ _proto.unselectAll = function unselectAll() {
486
+ this.directoryListingContainer.querySelectorAll('.wpstg-dir input').forEach(function (element) {
487
+ element.checked = false;
488
+ });
489
+ };
490
 
491
+ _proto.selectDefault = function selectDefault() {
492
+ // unselect all checkboxes
493
+ this.unselectAll(); // only select those checkboxes whose class is wpstg-wp-core-dir
 
 
 
 
 
 
 
 
 
494
 
495
+ this.directoryListingContainer.querySelectorAll('.wpstg-dir input.wpstg-wp-core-dir').forEach(function (element) {
496
+ element.checked = true;
497
+ }); // then unselect those checkboxes whose parent has wpstg extra checkbox
498
 
499
+ this.directoryListingContainer.querySelectorAll('.wpstg-dir > .wpstg-wp-non-core-dir').forEach(function (element) {
500
+ element.parentElement.querySelectorAll('input.wpstg-wp-core-dir').forEach(function (element) {
501
+ element.checked = false;
502
+ });
503
+ });
504
+ this.isDefaultSelected = true;
505
+ };
 
 
 
 
506
 
507
+ _proto.parseExcludes = function parseExcludes() {
508
+ this.existingExcludes = this.directoryListingContainer.getAttribute('data-existing-excludes', []);
509
 
510
+ if (this.existingExcludes === '') {
511
+ this.existingExcludes = [];
512
+ }
 
 
 
 
 
 
 
 
 
513
 
514
+ if (this.existingExcludes.length !== 0) {
515
+ this.existingExcludes = this.existingExcludes.split(',');
516
+ }
517
+ };
518
+
519
+ _proto.isExcludeScanned = function isExcludeScanned(exclude) {
520
+ this.directoryListingContainer.querySelectorAll('.wpstg-dir input').forEach(function (element) {
521
+ if (element.value === exclude) {
522
+ return true;
523
+ }
524
+ });
525
+ return false;
526
+ };
527
+
528
+ return WpstgDirectoryNavigation;
529
+ }();
530
 
 
 
 
 
 
 
 
 
531
  /**
532
+ * Rich Exclude Filter Module
 
 
533
  */
534
 
535
+ var WpstgExcludeFilters = /*#__PURE__*/function () {
536
+ function WpstgExcludeFilters(excludeFilterContainerSelector, wpstgObject) {
537
+ if (excludeFilterContainerSelector === void 0) {
538
+ excludeFilterContainerSelector = '#wpstg-exclude-filters-container';
539
+ }
540
 
541
+ if (wpstgObject === void 0) {
542
+ wpstgObject = wpstg;
543
+ }
 
 
 
 
544
 
545
+ this.excludeContainer = qs(excludeFilterContainerSelector);
546
+ this.excludeTableBody = qs(excludeFilterContainerSelector + " tbody");
547
+ this.wpstgObject = wpstgObject;
548
+ this.init();
549
  }
550
 
551
+ var _proto = WpstgExcludeFilters.prototype;
 
 
 
 
 
552
 
553
+ _proto.addEvents = function addEvents() {
554
+ var _this = this;
555
 
556
+ addEvent(this.excludeContainer, 'click', '.wpstg-file-size-rule', function () {
557
+ _this.addFileSizeExclude();
558
+ });
559
+ addEvent(this.excludeContainer, 'click', '.wpstg-file-ext-rule', function () {
560
+ _this.addFileExtExclude();
561
+ });
562
+ addEvent(this.excludeContainer, 'click', '.wpstg-file-name-rule', function () {
563
+ _this.addFileNameExclude();
564
+ });
565
+ addEvent(this.excludeContainer, 'click', '.wpstg-dir-name-rule', function () {
566
+ _this.addDirNameExclude();
567
+ });
568
+ addEvent(this.excludeContainer, 'click', '.wpstg-clear-all-rules', function () {
569
+ _this.clearExcludes();
570
+ });
571
+ addEvent(this.excludeContainer, 'click', '.wpstg-remove-exclude-rule', function (target) {
572
+ _this.removeExclude(target);
573
+ });
574
+ };
575
 
576
+ _proto.init = function init() {
577
+ if (this.excludeContainer === null) {
578
+ console.log('Error: Given table selector not found!');
579
  return;
580
  }
581
 
582
+ this.addEvents();
583
+ };
 
 
 
584
 
585
+ _proto.addFileSizeExclude = function addFileSizeExclude() {
586
+ this.addExcludeRuleRow('#wpstg-file-size-exclude-filter-template');
587
+ };
 
 
588
 
589
+ _proto.addFileExtExclude = function addFileExtExclude() {
590
+ this.addExcludeRuleRow('#wpstg-file-ext-exclude-filter-template');
591
+ };
592
 
593
+ _proto.addFileNameExclude = function addFileNameExclude() {
594
+ this.addExcludeRuleRow('#wpstg-file-name-exclude-filter-template');
595
+ };
596
+
597
+ _proto.addDirNameExclude = function addDirNameExclude() {
598
+ this.addExcludeRuleRow('#wpstg-dir-name-exclude-filter-template');
599
+ };
600
+
601
+ _proto.addExcludeRuleRow = function addExcludeRuleRow(templateName) {
602
+ var excludeRowTemplate = qs(templateName);
603
+
604
+ if (excludeRowTemplate !== null) {
605
+ var clone = excludeRowTemplate.content.cloneNode(true);
606
+ var excludeRow = clone.querySelector('tr');
607
+ this.excludeTableBody.appendChild(excludeRow);
608
+ all('.wpstg-has-exclude-rules').forEach(function (e) {
609
+ e.style.display = 'inherit';
610
  });
 
611
  }
612
+ };
613
 
614
+ _proto.clearExcludes = function clearExcludes() {
615
+ this.excludeTableBody.innerHTML = '';
616
+ all('.wpstg-has-exclude-rules').forEach(function (e) {
617
+ e.style.display = 'none';
 
 
 
618
  });
619
+ };
 
 
 
 
 
620
 
621
+ _proto.removeExclude = function removeExclude(target) {
622
+ if (target.parentElement !== null && target.parentElement.parentElement !== null) {
623
+ this.excludeTableBody.removeChild(target.parentElement.parentElement);
624
+ }
625
 
626
+ if (this.excludeTableBody.innerHTML.trim() === '') {
627
+ all('.wpstg-has-exclude-rules').forEach(function (e) {
628
+ e.style.display = 'none';
629
+ });
630
+ }
631
  }
632
+ /**
633
+ * Converts all the exclude filters arrays into one single string to keep size of post request small
634
+ * @return {string}
635
+ */
636
+ ;
637
 
638
+ _proto.getExcludeFilters = function getExcludeFilters() {
639
+ var _this2 = this;
 
 
 
 
 
 
 
 
 
 
 
 
640
 
641
+ var globExcludes = [];
642
+ var sizeExcludes = [];
643
+ var sizeCompares = this.excludeTableBody.querySelectorAll('select[name="wpstgFileSizeExcludeRuleCompare[]"]');
644
+ var sizeSizes = this.excludeTableBody.querySelectorAll('input[name="wpstgFileSizeExcludeRuleSize[]"]');
645
+ var sizeByte = this.excludeTableBody.querySelectorAll('select[name="wpstgFileSizeExcludeRuleByte[]"]');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
646
 
647
+ for (var _i = 0, _Object$entries = Object.entries(sizeSizes); _i < _Object$entries.length; _i++) {
648
+ var _Object$entries$_i = _Object$entries[_i],
649
+ key = _Object$entries$_i[0],
650
+ sizeInput = _Object$entries$_i[1];
651
 
652
+ if (sizeInput.value !== '') {
653
+ sizeExcludes.push(sizeCompares[key].value + ' ' + sizeInput.value + sizeByte[key].value);
654
+ }
 
 
 
 
 
 
 
655
  }
656
 
657
+ var extensionInputs = this.excludeTableBody.querySelectorAll('input[name="wpstgFileExtExcludeRule[]"]');
658
+ extensionInputs.forEach(function (x) {
659
+ var ext = _this2.cleanStringForGlob(x.value);
 
 
 
 
 
 
 
 
660
 
661
+ if (ext !== '') {
662
+ globExcludes.push('ext:' + ext.trim());
663
+ }
664
+ });
665
+ var fileNamesPos = this.excludeTableBody.querySelectorAll('select[name="wpstgFileNameExcludeRulePos[]"]');
666
+ var fileNames = this.excludeTableBody.querySelectorAll('input[name="wpstgFileNameExcludeRulePath[]"]');
667
 
668
+ for (var _i2 = 0, _Object$entries2 = Object.entries(fileNames); _i2 < _Object$entries2.length; _i2++) {
669
+ var _Object$entries2$_i = _Object$entries2[_i2],
670
+ _key = _Object$entries2$_i[0],
671
+ fileInput = _Object$entries2$_i[1];
672
+ var fileName = this.cleanStringForGlob(fileInput.value);
 
 
673
 
674
+ if (fileName !== '') {
675
+ globExcludes.push('file:' + fileNamesPos[_key].value + ' ' + fileName.trim());
676
+ }
 
677
  }
 
 
 
 
 
 
678
 
679
+ var dirNamesPos = this.excludeTableBody.querySelectorAll('select[name="wpstgDirNameExcludeRulePos[]"]');
680
+ var dirNames = this.excludeTableBody.querySelectorAll('input[name="wpstgDirNameExcludeRulePath[]"]');
681
 
682
+ for (var _i3 = 0, _Object$entries3 = Object.entries(dirNames); _i3 < _Object$entries3.length; _i3++) {
683
+ var _Object$entries3$_i = _Object$entries3[_i3],
684
+ _key2 = _Object$entries3$_i[0],
685
+ dirInput = _Object$entries3$_i[1];
686
+ var dirName = this.cleanStringForGlob(dirInput.value);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
687
 
688
+ if (dirName !== '') {
689
+ globExcludes.push('dir:' + dirNamesPos[_key2].value + ' ' + dirName.trim());
690
  }
 
 
 
 
 
 
691
  }
 
 
 
 
 
 
692
 
693
+ return {
694
+ 'sizes': sizeExcludes.filter(this.onlyUnique).join(','),
695
+ // return set of unique rules
696
+ 'globs': globExcludes.filter(this.onlyUnique).join(',')
697
+ };
698
+ };
699
 
700
+ _proto.onlyUnique = function onlyUnique(value, index, self) {
701
+ return self.indexOf(value) === index;
702
  }
703
+ /**
704
+ * Remove most of the comment glob characters from the string
705
+ * @param {String} value
706
+ * @return {String}
707
+ */
708
+ ;
709
 
710
+ _proto.cleanStringForGlob = function cleanStringForGlob(value) {
711
+ // will replace character like * ^ / \ ! ? [ from the string
712
+ return value.replace(/[*^//!\.[?]/g, '');
713
+ };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
714
 
715
+ return WpstgExcludeFilters;
716
+ }();
717
 
 
 
 
718
  /**
719
+ * Basic WP Staging Modal implemented with help of Sweetalerts
720
  */
721
+ var WpstgModal = /*#__PURE__*/function () {
722
+ function WpstgModal(confirmAction, wpstgObject) {
723
+ if (wpstgObject === void 0) {
724
+ wpstgObject = wpstg;
725
+ }
726
 
727
+ this.confirmAction = confirmAction;
728
+ this.wpstgObject = wpstgObject;
 
 
729
  }
730
 
731
+ var _proto = WpstgModal.prototype;
 
 
 
 
 
 
 
 
 
 
732
 
733
+ _proto.show = function show(swalOptions, additionalParams, callback) {
734
+ var _this = this;
 
 
 
735
 
736
+ if (additionalParams === void 0) {
737
+ additionalParams = {};
738
+ }
739
 
740
+ if (callback === void 0) {
741
+ callback = null;
742
+ }
 
 
 
743
 
744
+ Swal.fire(swalOptions).then(function (result) {
745
+ if (result.value && _this.error !== null) {
746
+ _this.triggerConfirmAction(additionalParams, callback);
747
+ }
748
+ });
749
+ };
750
 
751
+ _proto.triggerConfirmAction = function triggerConfirmAction(additionalParams, callback) {
752
+ var _this2 = this;
 
 
753
 
754
+ if (additionalParams === void 0) {
755
+ additionalParams = {};
 
 
 
 
 
 
 
 
756
  }
757
 
758
+ if (callback === void 0) {
759
+ callback = null;
760
+ }
 
 
 
761
 
762
+ fetch(this.wpstgObject.ajaxUrl, {
763
+ method: 'POST',
764
+ credentials: 'same-origin',
765
+ body: new URLSearchParams(Object.assign({
766
+ action: this.confirmAction,
767
+ accessToken: this.wpstgObject.accessToken,
768
+ nonce: this.wpstgObject.nonce
769
+ }, additionalParams)),
770
+ headers: {
771
+ 'Content-Type': 'application/x-www-form-urlencoded'
772
+ }
773
+ }).then(function (response) {
774
+ if (response.ok) {
775
+ return response.json();
776
+ }
777
 
778
+ return Promise.reject(response);
779
+ }).then(function (response) {
780
+ if (callback !== null) {
781
+ callback(response);
782
+ }
783
+ })["catch"](function (error) {
784
+ console.log(_this2.wpstgObject.i18n['somethingWentWrong'], error);
785
+ });
786
+ };
787
 
788
+ return WpstgModal;
789
+ }();
790
 
 
 
 
 
791
  /**
792
+ * Manage RESET MODAL
 
 
793
  */
794
 
795
+ var WpstgResetModal = /*#__PURE__*/function () {
796
+ function WpstgResetModal(cloneID, workflowSelector, fetchExcludeSettingsAction, modalErrorAction, wpstgObject) {
797
+ if (workflowSelector === void 0) {
798
+ workflowSelector = '#wpstg-workflow';
 
 
 
 
 
 
 
 
 
 
 
 
 
799
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
800
 
801
+ if (fetchExcludeSettingsAction === void 0) {
802
+ fetchExcludeSettingsAction = 'wpstg_clone_excludes_settings';
 
 
 
 
 
 
 
 
 
 
 
 
803
  }
804
 
805
+ if (modalErrorAction === void 0) {
806
+ modalErrorAction = 'wpstg_modal_error';
807
  }
 
 
 
 
 
 
808
 
809
+ if (wpstgObject === void 0) {
810
+ wpstgObject = wpstg;
811
+ }
812
 
813
+ this.cloneID = cloneID;
814
+ this.workflow = qs(workflowSelector);
815
+ this.wpstgObject = wpstgObject;
816
+ this.fetchExcludeSettingsAction = fetchExcludeSettingsAction;
817
+ this.modalErrorAction = modalErrorAction;
818
+ this.resetButtonClass = 'wpstg-confirm-reset-clone';
819
+ this.resetModalContainerClass = 'wpstg-reset-confirmation';
820
+ this.resetTabSelector = '.wpstg-reset-exclude-tab';
821
+ this.directoryNavigator = null;
822
+ this.excludeFilters = null;
823
+ this.isAllTablesChecked = true;
824
  }
 
 
 
 
 
 
825
 
826
+ var _proto = WpstgResetModal.prototype;
827
 
828
+ _proto.addEvents = function addEvents() {
829
+ var _this = this;
 
 
 
 
 
 
 
 
 
 
830
 
831
+ var resetModalContainer = qs('.' + this.resetModalContainerClass);
832
 
833
+ if (resetModalContainer === null) {
834
+ console.log('Exit');
835
+ return;
836
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
837
 
838
+ addEvent(resetModalContainer, 'click', this.resetTabSelector, function (target) {
839
+ _this.toggleContent(target);
840
+ });
841
+ addEvent(resetModalContainer, 'click', '.wpstg-button-select', function () {
842
+ _this.selectDefaultTables();
843
+ });
844
+ addEvent(resetModalContainer, 'click', '.wpstg-button-unselect', function () {
845
+ _this.toggleTableSelection();
846
+ });
847
+ addEvent(resetModalContainer, 'click', '.wpstg-expand-dirs', function (target, event) {
848
+ event.preventDefault();
849
 
850
+ _this.toggleDirectoryNavigation(target);
851
+ });
852
+ addEvent(resetModalContainer, 'change', 'input.wpstg-check-dir', function (target) {
853
+ _this.updateDirectorySelection(target);
854
+ });
855
+ };
856
 
857
+ _proto.init = function init() {
858
+ this.addEvents();
859
+ };
860
 
861
+ _proto.toggleContent = function toggleContent(target) {
862
+ var resetModalContainer = qs('.' + this.resetModalContainerClass);
863
+ var contentId = target.getAttribute('data-id');
864
+ var tabTriangle = target.querySelector('.wpstg-tab-triangle');
865
+ var isCollapsed = target.getAttribute('data-collapsed', 'true');
866
+ var content = qs(contentId);
867
 
868
+ if (isCollapsed === 'true') {
869
+ if (resetModalContainer.classList.contains('has-collapsible-open')) {
870
+ resetModalContainer.classList.add('has-collapsible-open-2');
871
+ } else {
872
+ resetModalContainer.classList.add('has-collapsible-open');
873
+ }
874
 
875
+ slideDown(content);
876
+ tabTriangle.style.transform = 'rotate(90deg)';
877
+ target.setAttribute('data-collapsed', 'false');
878
+ } else {
879
+ if (resetModalContainer.classList.contains('has-collapsible-open-2')) {
880
+ resetModalContainer.classList.remove('has-collapsible-open-2');
881
+ } else {
882
+ resetModalContainer.classList.remove('has-collapsible-open');
883
+ }
884
 
885
+ slideUp(content);
886
+ tabTriangle.style.removeProperty('transform');
887
+ target.setAttribute('data-collapsed', 'true');
888
+ }
 
 
 
 
 
 
 
 
 
889
  }
890
  /**
891
+ * Show Swal alert with loader and send ajax request to fetch content of alert.
892
+ * @return Promise
893
  */
894
+ ;
895
 
896
+ _proto.showModal = function showModal() {
897
+ var swalPromise = this.loadModal();
898
+ this.init();
899
+ this.fetchCloneExcludes();
900
+ return swalPromise;
901
+ };
902
 
903
+ _proto.loadModal = function loadModal() {
904
+ return Swal.fire({
905
+ title: '',
906
+ icon: 'warning',
907
+ html: this.getAjaxLoader(),
908
+ width: '300px',
909
+ focusConfirm: false,
910
+ customClass: {
911
+ confirmButton: this.resetButtonClass,
912
+ container: 'wpstg-swal2-container wpstg-swal2-loading ' + this.resetModalContainerClass
913
+ },
914
+ confirmButtonText: this.wpstgObject.i18n.resetClone,
915
+ showCancelButton: true
916
+ });
917
+ };
 
 
 
 
 
 
 
 
 
918
 
919
+ _proto.fetchCloneExcludes = function fetchCloneExcludes() {
920
+ var _this2 = this;
921
+
922
+ this.error = null; // send ajax request and fetch preserved exclude settings
923
+
924
+ fetch(this.wpstgObject.ajaxUrl, {
925
+ method: 'POST',
926
+ credentials: 'same-origin',
927
+ body: new URLSearchParams({
928
+ action: this.fetchExcludeSettingsAction,
929
+ accessToken: this.wpstgObject.accessToken,
930
+ nonce: this.wpstgObject.nonce,
931
+ clone: this.cloneID,
932
+ job: 'resetting'
933
+ }),
934
+ headers: {
935
+ 'Content-Type': 'application/x-www-form-urlencoded'
936
+ }
937
+ }).then(function (response) {
938
+ if (response.ok) {
939
+ return response.json();
940
  }
941
 
942
+ return Promise.reject(response);
943
+ }).then(function (data) {
944
+ if (!data.success) {
945
+ var errorModal = new WpstgModal(_this2.modalErrorAction, _this2.wpstgObject);
946
+ errorModal.show(Object.assign({
947
+ title: 'Error',
948
+ icon: 'error',
949
+ html: _this2.wpstgObject.i18n['somethingWentWrong'],
950
+ width: '500px',
951
+ confirmButtonText: 'Ok',
952
+ showCancelButton: false
953
+ }, data.swalOptions), {
954
+ type: data.type
955
+ });
956
+ return;
957
+ }
958
 
959
+ var modal = qs('.wpstg-reset-confirmation');
960
+ modal.classList.remove('wpstg-swal2-loading');
961
+ modal.querySelector('.swal2-popup').style.width = 'auto';
962
+ modal.querySelector('.swal2-content').innerHTML = data.html;
963
+ _this2.directoryNavigator = new WpstgDirectoryNavigation();
964
+ _this2.excludeFilters = new WpstgExcludeFilters();
965
+ })["catch"](function (error) {
966
+ _this2.renderError({
967
+ 'html': _this2.wpstgObject.i18n['somethingWentWrong'] + ' ' + error
968
+ });
969
+ });
970
+ };
971
 
972
+ _proto.getDirectoryNavigator = function getDirectoryNavigator() {
973
+ return this.directoryNavigator;
974
+ };
975
 
976
+ _proto.getExcludeFilters = function getExcludeFilters() {
977
+ return this.excludeFilters;
978
+ };
979
 
980
+ _proto.getAjaxLoader = function getAjaxLoader() {
981
+ return '<div class="wpstg-swal2-ajax-loader"><img src="' + this.wpstgObject.wpstgIcon + '" /></div>';
982
+ };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
983
 
984
+ _proto.toggleDirectoryNavigation = function toggleDirectoryNavigation(element) {
985
+ var cbElement = element.previousSibling;
986
 
987
+ if (cbElement.getAttribute('data-navigateable', 'false') === 'false') {
988
+ return;
 
989
  }
990
 
991
+ if (cbElement.getAttribute('data-scanned', 'false') === 'false') {
992
+ return;
 
993
  }
994
 
995
+ var subDirectories = getNextSibling(element, '.wpstg-subdir');
 
 
 
996
 
997
+ if (subDirectories.style.display === 'none') {
998
+ slideDown(subDirectories);
999
+ } else {
1000
+ slideUp(subDirectories);
 
 
 
 
 
 
 
1001
  }
1002
+ };
1003
 
1004
+ _proto.updateDirectorySelection = function updateDirectorySelection(element) {
1005
+ var parent = element.parentElement;
 
 
 
 
 
1006
 
1007
+ if (element.checked) {
1008
+ getParents(parent, '.wpstg-dir').forEach(function (parElem) {
1009
+ for (var i = 0; i < parElem.children.length; i++) {
1010
+ if (parElem.children[i].matches('.wpstg-check-dir')) {
1011
+ parElem.children[i].checked = true;
1012
+ }
1013
+ }
1014
+ });
1015
+ parent.querySelectorAll('.wpstg-expand-dirs').forEach(function (x) {
1016
+ x.classList.remove('disabled');
1017
+ });
1018
+ parent.querySelectorAll('.wpstg-subdir .wpstg-check-dir').forEach(function (x) {
1019
+ x.checked = true;
1020
+ });
1021
+ } else {
1022
+ parent.querySelectorAll('.wpstg-expand-dirs, .wpstg-check-subdirs').forEach(function (x) {
1023
+ x.classList.add('disabled');
1024
+ });
1025
+ parent.querySelectorAll('.wpstg-dir .wpstg-check-dir').forEach(function (x) {
1026
+ x.checked = false;
1027
+ });
1028
  }
1029
  };
 
1030
 
1031
+ _proto.selectDefaultTables = function selectDefaultTables() {
1032
+ var _this3 = this;
 
 
 
 
 
 
1033
 
1034
+ var resetModalContainer = qs('.' + this.resetModalContainerClass);
1035
+ var options = resetModalContainer.querySelectorAll('#wpstg_select_tables_cloning .wpstg-db-table');
1036
+ var multisitePattern = '^' + this.wpstgObject.tblprefix + '([^0-9])_*';
1037
+ var singleSitePattern = '^' + this.wpstgObject.tblprefix;
1038
+ options.forEach(function (option) {
1039
+ var name = option.getAttribute('name', '');
1040
 
1041
+ if (_this3.wpstgObject.isMultisite === '1' && name.match(multisitePattern)) {
1042
+ option.setAttribute('selected', 'selected');
1043
+ } else if (_this3.wpstgObject.isMultisite === '' && name.match(singleSitePattern)) {
1044
+ option.setAttribute('selected', 'selected');
1045
+ } else {
1046
+ option.removeAttribute('selected');
1047
+ }
1048
+ });
1049
+ };
1050
+
1051
+ _proto.toggleTableSelection = function toggleTableSelection() {
1052
+ var resetModalContainer = qs('.' + this.resetModalContainerClass);
1053
+
1054
+ if (false === this.isAllTablesChecked) {
1055
+ resetModalContainer.querySelectorAll('#wpstg_select_tables_cloning .wpstg-db-table').forEach(function (option) {
1056
+ option.setAttribute('selected', 'selected');
1057
+ });
1058
+ resetModalContainer.querySelector('.wpstg-button-unselect').innerHTML = 'Unselect All'; // cache.get('.wpstg-db-table-checkboxes').prop('checked', true);
1059
+
1060
+ this.isAllTablesChecked = true;
1061
+ } else {
1062
+ resetModalContainer.querySelectorAll('#wpstg_select_tables_cloning .wpstg-db-table').forEach(function (option) {
1063
+ option.removeAttribute('selected');
1064
+ });
1065
+ resetModalContainer.querySelector('.wpstg-button-unselect').innerHTML = 'Select All'; // cache.get('.wpstg-db-table-checkboxes').prop('checked', false);
1066
+
1067
+ this.isAllTablesChecked = false;
1068
+ }
1069
+ };
1070
+
1071
+ return WpstgResetModal;
1072
+ }();
1073
+
1074
+ var WPStaging = function ($) {
1075
+ var that = {
1076
+ isCancelled: false,
1077
+ isFinished: false,
1078
+ getLogs: false,
1079
+ time: 1,
1080
+ executionTime: false,
1081
+ progressBar: 0,
1082
+ cloneExcludeFilters: null,
1083
+ directoryNavigator: null,
1084
+ notyf: new Notyf({
1085
+ duration: 10000,
1086
+ position: {
1087
+ x: 'center',
1088
+ y: 'bottom'
1089
+ },
1090
+ dismissible: true,
1091
+ types: [{
1092
+ type: 'warning',
1093
+ background: 'orange',
1094
+ icon: false
1095
+ }]
1096
+ })
1097
+ };
1098
+ var cache = {
1099
+ elements: []
1100
+ };
1101
+ var ajaxSpinner;
1102
+ /**
1103
+ * Get / Set Cache for Selector
1104
+ * @param {String} selector
1105
+ * @return {*}
1106
+ */
1107
+
1108
+ cache.get = function (selector) {
1109
+ // It is already cached!
1110
+ if ($.inArray(selector, cache.elements) !== -1) {
1111
+ return cache.elements[selector];
1112
+ } // Create cache and return
1113
+
1114
+
1115
+ cache.elements[selector] = jQuery(selector);
1116
+ return cache.elements[selector];
1117
+ };
1118
+ /**
1119
+ * Refreshes given cache
1120
+ * @param {String} selector
1121
+ */
1122
+
1123
+
1124
+ cache.refresh = function (selector) {
1125
+ selector.elements[selector] = jQuery(selector);
1126
+ };
1127
+ /**
1128
+ * Show and Log Error Message
1129
+ * @param {String} message
1130
+ */
1131
+
1132
+
1133
+ var showError = function showError(message) {
1134
+ cache.get('#wpstg-try-again').css('display', 'inline-block');
1135
+ cache.get('#wpstg-cancel-cloning').text('Reset');
1136
+ cache.get('#wpstg-resume-cloning').show();
1137
+ cache.get('#wpstg-error-wrapper').show();
1138
+ cache.get('#wpstg-error-details').show().html(message);
1139
+ cache.get('#wpstg-removing-clone').removeClass('loading');
1140
+ cache.get('.wpstg-loader').hide();
1141
+ $('.wpstg--modal--process--generic-problem').show().html(message);
1142
+ };
1143
+ /**
1144
+ * Show warning during cloning or push process when closing tab or browser, or changing page
1145
+ * @param {beforeunload} event
1146
+ * @return {null}
1147
+ */
1148
+
1149
+
1150
+ that.warnIfClosingDuringProcess = function (event) {
1151
+ // Only some browsers show the message below, most say something like "Changes you made may not be saved" (Chrome) or "You have unsaved changes. Exit?"
1152
+ event.returnValue = 'You MUST leave this window open while cloning/pushing. Please wait...';
1153
+ return null;
1154
+ };
1155
+ /**
1156
+ *
1157
+ * @param obj
1158
+ * @return {boolean}
1159
+ */
1160
+
1161
+
1162
+ function isEmpty(obj) {
1163
+ for (var prop in obj) {
1164
+ if (obj.hasOwnProperty(prop)) {
1165
+ return false;
1166
+ }
1167
+ }
1168
+
1169
+ return true;
1170
+ }
1171
+ /**
1172
+ *
1173
+ * @param response the error object
1174
+ * @param prependMessage Overwrite default error message at beginning
1175
+ * @param appendMessage Overwrite default error message at end
1176
+ * @returns void
1177
+ */
1178
+
1179
+
1180
+ var showAjaxFatalError = function showAjaxFatalError(response, prependMessage, appendMessage) {
1181
+ prependMessage = prependMessage ? prependMessage + '<br/><br/>' : 'Something went wrong! <br/><br/>';
1182
+ appendMessage = appendMessage ? appendMessage + '<br/><br/>' : '<br/><br/>Please try the <a href=\'https://wp-staging.com/docs/wp-staging-settings-for-small-servers/\' target=\'_blank\'>WP Staging Small Server Settings</a> or submit an error report and contact us.';
1183
+
1184
+ if (response === false) {
1185
+ showError(prependMessage + ' Error: No response.' + appendMessage);
1186
+ window.removeEventListener('beforeunload', WPStaging.warnIfClosingDuringProcess);
1187
+ return;
1188
+ }
1189
+
1190
+ if (typeof response.error !== 'undefined' && response.error) {
1191
+ console.error(response.message);
1192
+ showError(prependMessage + ' Error: ' + response.message + appendMessage);
1193
+ window.removeEventListener('beforeunload', WPStaging.warnIfClosingDuringProcess);
1194
+ return;
1195
+ }
1196
+ };
1197
+ /**
1198
+ *
1199
+ * @param response
1200
+ * @return {{ok}|*}
1201
+ */
1202
+
1203
+
1204
+ var handleFetchErrors = function handleFetchErrors(response) {
1205
+ if (!response.ok) {
1206
+ showError('Error: ' + response.status + ' - ' + response.statusText + '. Please try again or contact support.');
1207
+ }
1208
+
1209
+ return response;
1210
+ };
1211
+ /** Hide and reset previous thrown visible errors */
1212
+
1213
+
1214
+ var resetErrors = function resetErrors() {
1215
+ cache.get('#wpstg-error-details').hide().html('');
1216
+ };
1217
+
1218
+ var slugify = function slugify(url) {
1219
+ return url.toString().toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g, '').replace(/\s+/g, '-').replace(/&/g, '-and-').replace(/[^a-z0-9\-]/g, '').replace(/-+/g, '-').replace(/^-*/, '').replace(/-*$/, '');
1220
+ };
1221
+ /**
1222
+ * Common Elements
1223
+ */
1224
+
1225
+
1226
+ var elements = function elements() {
1227
+ var $workFlow = cache.get('#wpstg-workflow');
1228
+ var isAllChecked = true;
1229
+ var urlSpinner = ajaxurl.replace('/admin-ajax.php', '') + '/images/spinner';
1230
+ var timer;
1231
+
1232
+ if (2 < window.devicePixelRatio) {
1233
+ urlSpinner += '-2x';
1234
+ }
1235
+
1236
+ urlSpinner += '.gif';
1237
+ ajaxSpinner = '<img src=\'\'' + urlSpinner + '\' alt=\'\' class=\'ajax-spinner general-spinner\' />';
1238
+
1239
+ $workFlow // Check / Un-check All Database Tables New
1240
+ .on('click', '.wpstg-button-unselect', function (e) {
1241
+ e.preventDefault();
1242
+
1243
+ if (false === isAllChecked) {
1244
+ cache.get('#wpstg_select_tables_cloning .wpstg-db-table').prop('selected', 'selected');
1245
+ cache.get('.wpstg-button-unselect').text('Unselect All');
1246
+ cache.get('.wpstg-db-table-checkboxes').prop('checked', true);
1247
+ isAllChecked = true;
1248
+ } else {
1249
+ cache.get('#wpstg_select_tables_cloning .wpstg-db-table').prop('selected', false);
1250
+ cache.get('.wpstg-button-unselect').text('Select All');
1251
+ cache.get('.wpstg-db-table-checkboxes').prop('checked', false);
1252
+ isAllChecked = false;
1253
+ }
1254
+ })
1255
+ /**
1256
+ * Select tables with certain tbl prefix | NEW
1257
+ * @param obj e
1258
+ * @returns {undefined}
1259
+ */
1260
+ .on('click', '.wpstg-button-select', function (e) {
1261
+ e.preventDefault();
1262
+ $('#wpstg_select_tables_cloning .wpstg-db-table').each(function () {
1263
+ if (wpstg.isMultisite == 1) {
1264
+ if ($(this).attr('name').match('^' + wpstg.tblprefix + '([^0-9])_*')) {
1265
+ $(this).prop('selected', 'selected');
1266
+ } else {
1267
+ $(this).prop('selected', false);
1268
+ }
1269
+ }
1270
+
1271
+ if (wpstg.isMultisite == 0) {
1272
+ if ($(this).attr('name').match('^' + wpstg.tblprefix)) {
1273
+ $(this).prop('selected', 'selected');
1274
+ } else {
1275
+ $(this).prop('selected', false);
1276
+ }
1277
+ }
1278
+ });
1279
+ }) // Expand Directories
1280
+ .on('click', '.wpstg-expand-dirs', function (e) {
1281
+ e.preventDefault();
1282
+ var $this = $(this);
1283
+ $this.siblings('.wpstg-subdir').slideToggle();
1284
+ }) // When a directory checkbox is Selected
1285
+ .on('change', 'input.wpstg-check-dir', function () {
1286
+ var $directory = $(this).parent('.wpstg-dir');
1287
+
1288
+ if (this.checked) {
1289
+ $directory.parents('.wpstg-dir').children('.wpstg-check-dir').prop('checked', true);
1290
+ $directory.find('.wpstg-expand-dirs').removeClass('disabled');
1291
+ $directory.find('.wpstg-subdir .wpstg-check-dir').prop('checked', true);
1292
+ } else {
1293
+ $directory.find('.wpstg-dir .wpstg-check-dir').prop('checked', false);
1294
+ $directory.find('.wpstg-expand-dirs, .wpstg-check-subdirs').addClass('disabled');
1295
+ $directory.find('.wpstg-check-subdirs').data('action', 'check').text('check');
1296
+ }
1297
+ }) // When a directory name is Selected
1298
+ .on('change', 'href.wpstg-check-dir', function () {
1299
+ var $directory = $(this).parent('.wpstg-dir');
1300
+
1301
+ if (this.checked) {
1302
+ $directory.parents('.wpstg-dir').children('.wpstg-check-dir').prop('checked', true);
1303
+ $directory.find('.wpstg-expand-dirs').removeClass('disabled');
1304
+ $directory.find('.wpstg-subdir .wpstg-check-dir').prop('checked', true);
1305
+ } else {
1306
+ $directory.find('.wpstg-dir .wpstg-check-dir').prop('checked', false);
1307
+ $directory.find('.wpstg-expand-dirs, .wpstg-check-subdirs').addClass('disabled');
1308
+ $directory.find('.wpstg-check-subdirs').data('action', 'check').text('check');
1309
+ }
1310
+ }) // Check the max length of the clone name and if the clone name already exists
1311
+ .on('keyup', '#wpstg-new-clone-id', function () {
1312
+ // Hide previous errors
1313
+ document.getElementById('wpstg-error-details').style.display = 'none'; // This request was already sent, clear it up!
1314
+
1315
+ if ('number' === typeof timer) {
1316
+ clearInterval(timer);
1317
+ }
1318
+
1319
+ var cloneID = this.value;
1320
+ timer = setTimeout(function () {
1321
+ ajax({
1322
+ action: 'wpstg_check_clone',
1323
+ accessToken: wpstg.accessToken,
1324
+ nonce: wpstg.nonce,
1325
+ cloneID: cloneID
1326
+ }, function (response) {
1327
+ if (response.status === 'success') {
1328
+ cache.get('#wpstg-new-clone-id').removeClass('wpstg-error-input');
1329
+ cache.get('#wpstg-start-cloning').removeAttr('disabled');
1330
+ cache.get('#wpstg-clone-id-error').text('').hide();
1331
+ } else {
1332
+ cache.get('#wpstg-new-clone-id').addClass('wpstg-error-input');
1333
+ cache.get('#wpstg-start-cloning').prop('disabled', true);
1334
+ cache.get('#wpstg-clone-id-error').text(response.message).show();
1335
+ }
1336
+ });
1337
+ }, 500);
1338
+ }) // Restart cloning process
1339
+ .on('click', '#wpstg-start-cloning', function () {
1340
+ resetErrors();
1341
+ that.isCancelled = false;
1342
+ that.getLogs = false;
1343
+ that.progressBar = 0;
1344
+ }).on('input', '#wpstg-new-clone-id', function () {
1345
+ if ($('#wpstg-clone-directory').length < 1) {
1346
+ return;
1347
+ }
1348
+
1349
+ var slug = slugify(this.value);
1350
+ var $targetDir = $('#wpstg-use-target-dir');
1351
+ var $targetUri = $('#wpstg-use-target-hostname');
1352
+ var path = $targetDir.data('base-path');
1353
+ var uri = $targetUri.data('base-uri');
1354
+
1355
+ if (path) {
1356
+ path = path.replace(/\/+$/g, '') + '/' + slug + '/';
1357
+ }
1358
+
1359
+ if (uri) {
1360
+ uri = uri.replace(/\/+$/g, '') + '/' + slug;
1361
+ }
1362
+
1363
+ $('.wpstg-use-target-dir--value').text(path);
1364
+ $('.wpstg-use-target-hostname--value').text(uri);
1365
+ $targetDir.attr('data-path', path);
1366
+ $targetUri.attr('data-uri', uri);
1367
+ $('#wpstg_clone_dir').attr('placeholder', path);
1368
+ $('#wpstg_clone_hostname').attr('placeholder', uri);
1369
+ }).on('input', '#wpstg_clone_hostname', function () {
1370
+ if ($(this).val() === '' || validateTargetHost()) {
1371
+ $('#wpstg_clone_hostname_error').remove();
1372
+ return;
1373
+ }
1374
+
1375
+ if (!validateTargetHost() && !$('#wpstg_clone_hostname_error').length) {
1376
+ $('#wpstg-clone-directory tr:last-of-type').after('<tr><td>&nbsp;</td><td><p id="wpstg_clone_hostname_error" style="color: red;">&nbsp;Invalid host name. Please provide it in a format like http://example.com</p></td></tr>');
1377
+ }
1378
+ });
1379
+ cloneActions();
1380
+ };
1381
+ /* @returns {boolean} */
1382
+
1383
+
1384
+ var validateTargetHost = function validateTargetHost() {
1385
+ var the_domain = $('#wpstg_clone_hostname').val();
1386
+
1387
+ if (the_domain === '') {
1388
+ return true;
1389
+ }
1390
+
1391
+ var reg = /^http(s)?:\/\/.*$/;
1392
+
1393
+ if (reg.test(the_domain) === false) {
1394
+ return false;
1395
+ }
1396
+
1397
+ return true;
1398
+ };
1399
+ /**
1400
+ * Clone actions
1401
+ */
1402
+
1403
+
1404
+ var cloneActions = function cloneActions() {
1405
+ var $workFlow = cache.get('#wpstg-workflow');
1406
+ $workFlow // Cancel cloning
1407
+ .on('click', '#wpstg-cancel-cloning', function () {
1408
+ if (!confirm('Are you sure you want to cancel cloning process?')) {
1409
+ return false;
1410
+ }
1411
+
1412
+ var $this = $(this);
1413
+ $('#wpstg-try-again, #wpstg-home-link').hide();
1414
+ $this.prop('disabled', true);
1415
+ that.isCancelled = true;
1416
+ that.progressBar = 0;
1417
+ $('#wpstg-processing-status').text('Please wait...this can take up a while.');
1418
+ $('.wpstg-loader, #wpstg-show-log-button').hide();
1419
+ $this.parent().append(ajaxSpinner);
1420
+ cancelCloning();
1421
+ }) // Resume cloning
1422
+ .on('click', '#wpstg-resume-cloning', function () {
1423
+ resetErrors();
1424
+ var $this = $(this);
1425
+ $('#wpstg-try-again, #wpstg-home-link').hide();
1426
+ that.isCancelled = false;
1427
+ $('#wpstg-processing-status').text('Try to resume cloning process...');
1428
+ $('#wpstg-error-details').hide();
1429
+ $('.wpstg-loader').show();
1430
+ $this.parent().append(ajaxSpinner);
1431
+ that.startCloning();
1432
+ }) // Cancel update cloning
1433
+ .on('click', '#wpstg-cancel-cloning-update', function () {
1434
+ resetErrors();
1435
+ var $this = $(this);
1436
+ $('#wpstg-try-again, #wpstg-home-link').hide();
1437
+ $this.prop('disabled', true);
1438
+ that.isCancelled = true;
1439
+ $('#wpstg-cloning-result').text('Please wait...this can take up a while.');
1440
+ $('.wpstg-loader, #wpstg-show-log-button').hide();
1441
+ $this.parent().append(ajaxSpinner);
1442
+ cancelCloningUpdate();
1443
+ }) // Restart cloning
1444
+ .on('click', '#wpstg-restart-cloning', function () {
1445
+ resetErrors();
1446
+ var $this = $(this);
1447
+ $('#wpstg-try-again, #wpstg-home-link').hide();
1448
+ $this.prop('disabled', true);
1449
+ that.isCancelled = true;
1450
+ $('#wpstg-cloning-result').text('Please wait...this can take up a while.');
1451
+ $('.wpstg-loader, #wpstg-show-log-button').hide();
1452
+ $this.parent().append(ajaxSpinner);
1453
+ restart();
1454
+ }) // Delete clone - confirmation
1455
+ .on('click', '.wpstg-remove-clone[data-clone]', function (e) {
1456
+ resetErrors();
1457
+ e.preventDefault();
1458
+ var $existingClones = cache.get('#wpstg-existing-clones');
1459
+ $workFlow.removeClass('active');
1460
+ cache.get('.wpstg-loader').show();
1461
+ ajax({
1462
+ action: 'wpstg_confirm_delete_clone',
1463
+ accessToken: wpstg.accessToken,
1464
+ nonce: wpstg.nonce,
1465
+ clone: $(this).data('clone')
1466
+ }, function (response) {
1467
+ cache.get('#wpstg-removing-clone').html(response);
1468
+ $existingClones.children('img').remove();
1469
+ cache.get('.wpstg-loader').hide();
1470
+ $('html, body').animate({
1471
+ // This logic is meant to be a "scrollBottom"
1472
+ scrollTop: $('#wpstg-remove-clone').offset().top - $(window).height() + $('#wpstg-remove-clone').height() + 50
1473
+ }, 100);
1474
+ }, 'HTML');
1475
+ }) // Delete clone - confirmed
1476
+ .on('click', '#wpstg-remove-clone', function (e) {
1477
+ resetErrors();
1478
+ e.preventDefault();
1479
+ cache.get('#wpstg-removing-clone').addClass('loading');
1480
+ cache.get('.wpstg-loader').show();
1481
+ deleteClone($(this).data('clone'));
1482
+ }) // Cancel deleting clone
1483
+ .on('click', '#wpstg-cancel-removing', function (e) {
1484
+ e.preventDefault();
1485
+ $('.wpstg-clone').removeClass('active');
1486
+ cache.get('#wpstg-removing-clone').html('');
1487
+ }) // Update
1488
+ .on('click', '.wpstg-execute-clone', function (e) {
1489
+ e.preventDefault();
1490
+ var clone = $(this).data('clone');
1491
+ $workFlow.addClass('loading');
1492
+ that.cloneExcludeFilters = null;
1493
+ ajax({
1494
+ action: 'wpstg_scanning',
1495
+ clone: clone,
1496
+ accessToken: wpstg.accessToken,
1497
+ nonce: wpstg.nonce
1498
+ }, function (response) {
1499
+ if (response.length < 1) {
1500
+ showError('Something went wrong! Error: No response. Please try the <a href=\'https://wp-staging.com/docs/wp-staging-settings-for-small-servers/\' target=\'_blank\'>WP Staging Small Server Settings</a> or submit an error report and contact us.');
1501
+ }
1502
+
1503
+ var jsonResponse = tryParseJson(response);
1504
+
1505
+ if (jsonResponse !== false && jsonResponse.success === false) {
1506
+ $workFlow.removeClass('loading');
1507
+ showErrorModal(jsonResponse);
1508
+ return;
1509
+ }
1510
+
1511
+ $workFlow.removeClass('loading').html(response); // register check disk space function for clone update process.
1512
+
1513
+ checkDiskSpace();
1514
+ that.directoryNavigator = new WpstgDirectoryNavigation('#wpstg-directories-listing', wpstg, that.notyf);
1515
+ that.cloneExcludeFilters = new WpstgExcludeFilters();
1516
+ that.switchStep(2);
1517
+ }, 'HTML');
1518
+ }) // Reset Clone
1519
+ .on('click', '.wpstg-reset-clone', function (e) {
1520
+ e.preventDefault();
1521
+ var clone = $(this).data('clone');
1522
+ var resetModal = new WpstgResetModal(clone);
1523
+ var promise = resetModal.showModal();
1524
+ promise.then(function (result) {
1525
+ if (result.value) {
1526
+ var dirNavigator = resetModal.getDirectoryNavigator();
1527
+ var exclFilters = resetModal.getExcludeFilters().getExcludeFilters();
1528
+ resetClone(clone, {
1529
+ includedTables: getIncludedTables(),
1530
+ excludeSizeRules: encodeURIComponent(exclFilters.sizes),
1531
+ excludeGlobRules: encodeURIComponent(exclFilters.globs),
1532
+ excludedDirectories: dirNavigator.getExcludedDirectories(),
1533
+ extraDirectories: dirNavigator.getExtraDirectoriesRootOnly()
1534
+ });
1535
+ }
1536
+ });
1537
+ return;
1538
+ });
1539
+ };
1540
+ /**
1541
+ * Ajax Requests
1542
+ * @param Object data
1543
+ * @param Function callback
1544
+ * @param string dataType
1545
+ * @param bool showErrors
1546
+ * @param int tryCount
1547
+ * @param float incrementRatio
1548
+ */
1549
+
1550
+
1551
+ var ajax = function ajax(data, callback, dataType, showErrors, tryCount, incrementRatio) {
1552
+ if (incrementRatio === void 0) {
1553
+ incrementRatio = null;
1554
+ }
1555
+
1556
+ if ('undefined' === typeof dataType) {
1557
+ dataType = 'json';
1558
+ }
1559
+
1560
+ if (false !== showErrors) {
1561
+ showErrors = true;
1562
+ }
1563
+
1564
+ tryCount = 'undefined' === typeof tryCount ? 0 : tryCount;
1565
+ var retryLimit = 10;
1566
+ var retryTimeout = 10000 * tryCount;
1567
+ incrementRatio = parseInt(incrementRatio);
1568
+
1569
+ if (!isNaN(incrementRatio)) {
1570
+ retryTimeout *= incrementRatio;
1571
+ }
1572
+
1573
+ $.ajax({
1574
+ url: ajaxurl + '?action=wpstg_processing&_=' + Date.now() / 1000,
1575
+ type: 'POST',
1576
+ dataType: dataType,
1577
+ cache: false,
1578
+ data: data,
1579
+ error: function error(xhr, textStatus, errorThrown) {
1580
+ // try again after 10 seconds
1581
+ tryCount++;
1582
+
1583
+ if (tryCount <= retryLimit) {
1584
+ setTimeout(function () {
1585
+ ajax(data, callback, dataType, showErrors, tryCount, incrementRatio);
1586
+ return;
1587
+ }, retryTimeout);
1588
+ } else {
1589
+ var errorCode = 'undefined' === typeof xhr.status ? 'Unknown' : xhr.status;
1590
+ showError('Fatal Error: ' + errorCode + ' Please try the <a href=\'https://wp-staging.com/docs/wp-staging-settings-for-small-servers/\' target=\'_blank\'>WP Staging Small Server Settings</a> or submit an error report and contact us.');
1591
+ }
1592
+ },
1593
+ success: function success(data) {
1594
+ if ('function' === typeof callback) {
1595
+ callback(data);
1596
+ }
1597
+ },
1598
+ statusCode: {
1599
+ 404: function _() {
1600
+ if (tryCount >= retryLimit) {
1601
+ showError('Error 404 - Can\'t find ajax request URL! Please try the <a href=\'https://wp-staging.com/docs/wp-staging-settings-for-small-servers/\' target=\'_blank\'>WP Staging Small Server Settings</a> or submit an error report and contact us.');
1602
+ }
1603
+ },
1604
+ 500: function _() {
1605
+ if (tryCount >= retryLimit) {
1606
+ showError('Fatal Error 500 - Internal server error while processing the request! Please try the <a href=\'https://wp-staging.com/docs/wp-staging-settings-for-small-servers/\' target=\'_blank\'>WP Staging Small Server Settings</a> or submit an error report and contact us.');
1607
+ }
1608
+ },
1609
+ 504: function _() {
1610
+ if (tryCount > retryLimit) {
1611
+ showError('Error 504 - It looks like your server is rate limiting ajax requests. Please try to resume after a minute. If this still not works try the <a href=\'https://wp-staging.com/docs/wp-staging-settings-for-small-servers/\' target=\'_blank\'>WP Staging Small Server Settings</a> or submit an error report and contact us.\n\ ');
1612
+ }
1613
+ },
1614
+ 502: function _() {
1615
+ if (tryCount >= retryLimit) {
1616
+ showError('Error 502 - It looks like your server is rate limiting ajax requests. Please try to resume after a minute. If this still not works try the <a href=\'https://wp-staging.com/docs/wp-staging-settings-for-small-servers/\' target=\'_blank\'>WP Staging Small Server Settings</a> or submit an error report and contact us.\n\ ');
1617
+ }
1618
+ },
1619
+ 503: function _() {
1620
+ if (tryCount >= retryLimit) {
1621
+ showError('Error 503 - It looks like your server is rate limiting ajax requests. Please try to resume after a minute. If this still not works try the <a href=\'https://wp-staging.com/docs/wp-staging-settings-for-small-servers/\' target=\'_blank\'>WP Staging Small Server Settings</a> or submit an error report and contact us.\n\ ');
1622
+ }
1623
+ },
1624
+ 429: function _() {
1625
+ if (tryCount >= retryLimit) {
1626
+ showError('Error 429 - It looks like your server is rate limiting ajax requests. Please try to resume after a minute. If this still not works try the <a href=\'https://wp-staging.com/docs/wp-staging-settings-for-small-servers/\' target=\'_blank\'>WP Staging Small Server Settings</a> or submit an error report and contact us.\n\ ');
1627
+ }
1628
+ },
1629
+ 403: function _() {
1630
+ if (tryCount >= retryLimit) {
1631
+ showError('Refresh page or login again! The process should be finished successfully. \n\ ');
1632
+ }
1633
+ }
1634
+ }
1635
+ });
1636
+ };
1637
+ /**
1638
+ * Next / Previous Step Clicks to Navigate Through Staging Job
1639
+ */
1640
+
1641
+
1642
+ var stepButtons = function stepButtons() {
1643
+ var $workFlow = cache.get('#wpstg-workflow');
1644
+ $workFlow // Next Button
1645
+ .on('click', '.wpstg-next-step-link', function (e) {
1646
+ e.preventDefault();
1647
+ var $this = $(this);
1648
+
1649
+ if ($('#wpstg_clone_hostname').length && !validateTargetHost()) {
1650
+ $('#wpstg_clone_hostname').focus();
1651
+ return false;
1652
+ }
1653
+
1654
+ if ($this.data('action') === 'wpstg_update' || $this.data('action') === 'wpstg_reset') {
1655
+ // Update / Reset Clone - confirmed
1656
+ var onlyUpdateMessage = '';
1657
+
1658
+ if ($this.data('action') === 'wpstg_update') {
1659
+ onlyUpdateMessage = ' \n\nExclude all tables and folders you do not want to overwrite, first! \n\nDo not cancel the updating process! This can break your staging site. \n\n\Create a backup of your staging website before you proceed.';
1660
+ }
1661
+
1662
+ if (!confirm('STOP! This will overwrite your staging site with all selected data from the production site! This should be used only if you want to clone again your production site. Are you sure you want to do this?' + onlyUpdateMessage)) {
1663
+ return false;
1664
+ }
1665
+ } // Button is disabled
1666
+
1667
+
1668
+ if ($this.attr('disabled')) {
1669
+ return false;
1670
+ }
1671
+
1672
+ if ($this.data('action') === 'wpstg_cloning') {
1673
+ // Verify External Database If Checked and Not Skipped
1674
+ if ($('#wpstg-ext-db').is(':checked')) {
1675
+ verifyExternalDatabase($this, $workFlow);
1676
+ return;
1677
+ }
1678
+ }
1679
+
1680
+ proceedCloning($this, $workFlow);
1681
+ }) // Previous Button
1682
+ .on('click', '.wpstg-prev-step-link', function (e) {
1683
+ e.preventDefault();
1684
+ cache.get('.wpstg-loader').removeClass('wpstg-finished');
1685
+ cache.get('.wpstg-loader').hide();
1686
+ loadOverview();
1687
+ });
1688
+ };
1689
+ /**
1690
+ * Get Included (Checked) Database Tables
1691
+ * @return {Array}
1692
+ */
1693
+
1694
+
1695
+ var getIncludedTables = function getIncludedTables() {
1696
+ var includedTables = [];
1697
+ $('#wpstg_select_tables_cloning option:selected').each(function () {
1698
+ includedTables.push(this.value);
1699
+ });
1700
+ return includedTables;
1701
+ };
1702
+ /**
1703
+ * Get Excluded (Unchecked) Database Tables
1704
+ * Not used anymore!
1705
+ * @return {Array}
1706
+ */
1707
+
1708
+
1709
+ var getExcludedTables = function getExcludedTables() {
1710
+ var excludedTables = [];
1711
+ $('.wpstg-db-table input:not(:checked)').each(function () {
1712
+ excludedTables.push(this.name);
1713
+ });
1714
+ return excludedTables;
1715
+ };
1716
+ /**
1717
+ * Verify External Database for Cloning
1718
+ */
1719
+
1720
+
1721
+ var verifyExternalDatabase = function verifyExternalDatabase($this, workflow) {
1722
+ cache.get('.wpstg-loader').show();
1723
+ ajax({
1724
+ action: 'wpstg_database_verification',
1725
+ accessToken: wpstg.accessToken,
1726
+ nonce: wpstg.nonce,
1727
+ databaseUser: cache.get('#wpstg_db_username').val(),
1728
+ databasePassword: cache.get('#wpstg_db_password').val(),
1729
+ databaseServer: cache.get('#wpstg_db_server').val(),
1730
+ databaseDatabase: cache.get('#wpstg_db_database').val()
1731
+ }, function (response) {
1732
+ // Undefined Error
1733
+ if (false === response) {
1734
+ showError('Something went wrong! Error: No response.' + 'Please try again. If that does not help, ' + '<a href=\'https://wp-staging.com/support/\' target=\'_blank\'>open a support ticket</a> ');
1735
+ cache.get('.wpstg-loader').hide();
1736
+ return;
1737
+ } // Throw Error
1738
+
1739
+
1740
+ if ('undefined' === typeof response.success) {
1741
+ showError('Something went wrong! Error: Invalid response.' + 'Please try again. If that does not help, ' + '<a href=\'https://wp-staging.com/support/\' target=\'_blank\'>open a support ticket</a> ');
1742
+ cache.get('.wpstg-loader').hide();
1743
+ return;
1744
+ }
1745
+
1746
+ if (response.success) {
1747
+ cache.get('.wpstg-loader').hide();
1748
+ proceedCloning($this, workflow);
1749
+ return;
1750
+ }
1751
+
1752
+ if (response.error_type === 'comparison') {
1753
+ cache.get('.wpstg-loader').hide();
1754
+ var render = '<table style="width: 100%;"><thead><tr><th>Property</th><th>Production DB</th><th>Staging DB</th><th>Status</th></tr></thead><tbody>';
1755
+ response.checks.forEach(function (x) {
1756
+ var icon = '<i style="color: #00ff00">✔</i>';
1757
+
1758
+ if (x.production !== x.staging) {
1759
+ icon = '<i style="color: #ff0000">❌</i>';
1760
+ }
1761
+
1762
+ render += '<tr><td>' + x.name + '</td><td>' + x.production + '</td><td>' + x.staging + '</td><td>' + icon + '</td></tr>';
1763
+ });
1764
+ render += '</tbody></table><p>Note: Some mySQL properties do not match. You may proceed but the staging site may not work as expected.</p>';
1765
+ Swal.fire({
1766
+ title: 'Different Database Properties',
1767
+ icon: 'warning',
1768
+ html: render,
1769
+ width: '650px',
1770
+ focusConfirm: false,
1771
+ confirmButtonText: 'Proceed Anyway',
1772
+ showCancelButton: true
1773
+ }).then(function (result) {
1774
+ if (result.value) {
1775
+ proceedCloning($this, workflow);
1776
+ }
1777
+ });
1778
+ return;
1779
+ }
1780
+
1781
+ Swal.fire({
1782
+ title: 'Different Database Properties',
1783
+ icon: 'error',
1784
+ html: response.message,
1785
+ focusConfirm: true,
1786
+ confirmButtonText: 'Ok',
1787
+ showCancelButton: false
1788
+ });
1789
+ cache.get('.wpstg-loader').hide();
1790
+ }, 'json', false);
1791
+ };
1792
+ /**
1793
+ * Get Cloning Step Data
1794
+ */
1795
+
1796
+
1797
+ var getCloningData = function getCloningData() {
1798
+ if ('wpstg_cloning' !== that.data.action && 'wpstg_update' !== that.data.action && 'wpstg_reset' !== that.data.action) {
1799
+ return;
1800
+ }
1801
+
1802
+ that.data.cloneID = $('#wpstg-new-clone-id').val() || new Date().getTime().toString(); // Remove this to keep &_POST[] small otherwise mod_security will throw error 404
1803
+ // that.data.excludedTables = getExcludedTables();
1804
+
1805
+ if (that.directoryNavigator !== null) {
1806
+ that.data.excludedDirectories = encodeURIComponent(that.directoryNavigator.getExcludedDirectories());
1807
+ that.data.extraDirectories = encodeURIComponent(that.directoryNavigator.getExtraDirectoriesRootOnly());
1808
+ }
1809
+
1810
+ that.data.excludeGlobRules = '';
1811
+ that.data.excludeSizeRules = '';
1812
+
1813
+ if (that.cloneExcludeFilters instanceof WpstgExcludeFilters) {
1814
+ var rules = that.cloneExcludeFilters.getExcludeFilters();
1815
+ that.data.excludeGlobRules = encodeURIComponent(rules.globs);
1816
+ that.data.excludeSizeRules = encodeURIComponent(rules.sizes);
1817
+ }
1818
+
1819
+ that.data.includedTables = getIncludedTables();
1820
+ that.data.databaseServer = $('#wpstg_db_server').val();
1821
+ that.data.databaseUser = $('#wpstg_db_username').val();
1822
+ that.data.databasePassword = $('#wpstg_db_password').val();
1823
+ that.data.databaseDatabase = $('#wpstg_db_database').val();
1824
+ that.data.databasePrefix = $('#wpstg_db_prefix').val();
1825
+ var cloneDir = $('#wpstg_clone_dir').val();
1826
+ that.data.cloneDir = encodeURIComponent($.trim(cloneDir));
1827
+ that.data.cloneHostname = $('#wpstg_clone_hostname').val();
1828
+ that.data.emailsAllowed = $('#wpstg_allow_emails').is(':checked');
1829
+ that.data.uploadsSymlinked = $('#wpstg_symlink_upload').is(':checked');
1830
+ that.data.cleanPluginsThemes = $('#wpstg-clean-plugins-themes').is(':checked');
1831
+ that.data.cleanUploadsDir = $('#wpstg-clean-uploads').is(':checked');
1832
+ };
1833
+
1834
+ var proceedCloning = function proceedCloning($this, workflow) {
1835
+ // Add loading overlay
1836
+ workflow.addClass('loading'); // Prepare data
1837
+
1838
+ that.data = {
1839
+ action: $this.data('action'),
1840
+ accessToken: wpstg.accessToken,
1841
+ nonce: wpstg.nonce
1842
+ }; // Cloning data
1843
+
1844
+ getCloningData();
1845
+ sendCloningAjax(workflow);
1846
+ };
1847
+
1848
+ var sendCloningAjax = function sendCloningAjax(workflow) {
1849
+ // Send ajax request
1850
+ ajax(that.data, function (response) {
1851
+ // Undefined Error
1852
+ if (false === response) {
1853
+ showError('Something went wrong!<br/><br/> Go to WP Staging > Settings and lower \'File Copy Limit\' and \'DB Query Limit\'. Also set \'CPU Load Priority to low \'' + 'and try again. If that does not help, ' + '<a href=\'https://wp-staging.com/support/\' target=\'_blank\'>open a support ticket</a> ');
1854
+ }
1855
+
1856
+ if (response.length < 1) {
1857
+ showError('Something went wrong! No response. Go to WP Staging > Settings and lower \'File Copy Limit\' and \'DB Query Limit\'. Also set \'CPU Load Priority to low \'' + 'and try again. If that does not help, ' + '<a href=\'https://wp-staging.com/support/\' target=\'_blank\'>open a support ticket</a> ');
1858
+ }
1859
+
1860
+ var jsonResponse = tryParseJson(response);
1861
+
1862
+ if (jsonResponse !== false && jsonResponse.success === false) {
1863
+ workflow.removeClass('loading');
1864
+ showErrorModal(jsonResponse);
1865
+ return;
1866
+ } // Styling of elements
1867
+
1868
+
1869
+ workflow.removeClass('loading').html(response);
1870
+ that.cloneExcludeFilters = null;
1871
+
1872
+ if (that.data.action === 'wpstg_scanning') {
1873
+ that.directoryNavigator = new WpstgDirectoryNavigation('#wpstg-directories-listing', wpstg, that.notyf);
1874
+ that.switchStep(2);
1875
+ that.cloneExcludeFilters = new WpstgExcludeFilters();
1876
+ } else if (that.data.action === 'wpstg_cloning' || that.data.action === 'wpstg_update' || that.data.action === 'wpstg_reset') {
1877
+ that.switchStep(3);
1878
+ } // Start cloning
1879
+
1880
+
1881
+ that.startCloning();
1882
+ }, 'HTML');
1883
+ };
1884
+
1885
+ var showErrorModal = function showErrorModal(response) {
1886
+ var errorModal = new WpstgModal('wpstg_modal_error', wpstg);
1887
+ errorModal.show(Object.assign({
1888
+ title: 'Error',
1889
+ icon: 'error',
1890
+ html: wpstg.i18n['somethingWentWrong'],
1891
+ width: '500px',
1892
+ confirmButtonText: 'Ok',
1893
+ showCancelButton: false
1894
+ }, response.swalOptions), {
1895
+ type: response.type
1896
+ });
1897
+ };
1898
+
1899
+ var tryParseJson = function tryParseJson(json) {
1900
+ // early bail if not string
1901
+ if (!json) {
1902
+ return false;
1903
+ }
1904
+
1905
+ try {
1906
+ var object = JSON.parse(json);
1907
+
1908
+ if (object && typeof object === 'object') {
1909
+ return object;
1910
+ }
1911
+ } catch (e) {// do nothing on catch
1912
+ }
1913
+
1914
+ return false;
1915
+ };
1916
+
1917
+ var resetClone = function resetClone(clone, excludeOptions) {
1918
+ that.data = {
1919
+ action: 'wpstg_reset',
1920
+ accessToken: wpstg.accessToken,
1921
+ nonce: wpstg.nonce,
1922
+ cloneID: clone
1923
+ };
1924
+ that.data = _extends({}, that.data, excludeOptions);
1925
+ var $workFlow = cache.get('#wpstg-workflow');
1926
+ sendCloningAjax($workFlow);
1927
+ };
1928
+ /**
1929
+ * Loads Overview (first step) of Staging Job
1930
+ */
1931
+
1932
+
1933
+ var loadOverview = function loadOverview() {
1934
+ var $workFlow = cache.get('#wpstg-workflow');
1935
+ $workFlow.addClass('loading');
1936
+ ajax({
1937
+ action: 'wpstg_overview',
1938
+ accessToken: wpstg.accessToken,
1939
+ nonce: wpstg.nonce
1940
+ }, function (response) {
1941
+ if (response.length < 1) {
1942
+ showError('Something went wrong! No response. Please try the <a href=\'https://wp-staging.com/docs/wp-staging-settings-for-small-servers/\' target=\'_blank\'>WP Staging Small Server Settings</a> or submit an error report.');
1943
+ }
1944
 
1945
+ cache.get('.wpstg-current-step'); // Styling of elements
1946
 
1947
+ $workFlow.removeClass('loading').html(response);
1948
+ }, 'HTML');
1949
+ that.switchStep(1);
1950
+ cache.get('.wpstg-step3-cloning').show();
1951
+ cache.get('.wpstg-step3-pushing').hide();
1952
+ };
1953
+ /**
1954
+ * Load Tabs
1955
+ */
1956
+
1957
+
1958
+ var tabs = function tabs() {
1959
+ cache.get('#wpstg-workflow').on('click', '.wpstg-tab-header', function (e) {
1960
+ e.preventDefault();
1961
+ var $this = $(this);
1962
+ var $section = cache.get($this.data('id'));
1963
+ $this.toggleClass('expand');
1964
+ $section.slideToggle();
1965
+
1966
+ if ($this.hasClass('expand')) {
1967
+ $this.find('.wpstg-tab-triangle').html('&#9660;');
1968
+ } else {
1969
+ $this.find('.wpstg-tab-triangle').html('&#9658;');
1970
+ }
1971
+ });
1972
+ };
1973
+ /**
1974
+ * Delete Clone
1975
+ * @param {String} clone
1976
+ */
1977
+
1978
+
1979
+ var deleteClone = function deleteClone(clone) {
1980
+ var deleteDir = $('#deleteDirectory:checked').data('deletepath');
1981
+ ajax({
1982
+ action: 'wpstg_delete_clone',
1983
+ clone: clone,
1984
+ accessToken: wpstg.accessToken,
1985
+ nonce: wpstg.nonce,
1986
+ excludedTables: getExcludedTables(),
1987
+ deleteDir: deleteDir
1988
+ }, function (response) {
1989
+ if (response) {
1990
+ showAjaxFatalError(response); // Finished
1991
+
1992
+ if ('undefined' !== typeof response["delete"] && (response["delete"] === 'finished' || response["delete"] === 'unfinished')) {
1993
+ cache.get('#wpstg-removing-clone').removeClass('loading').html('');
1994
+
1995
+ if (response["delete"] === 'finished') {
1996
+ $('.wpstg-clone#' + clone).remove();
1997
+ }
1998
+
1999
+ if ($('.wpstg-clone').length < 1) {
2000
+ cache.get('#wpstg-existing-clones').find('h3').text('');
2001
+ }
2002
+
2003
+ cache.get('.wpstg-loader').hide();
2004
+ return;
2005
  }
2006
+ } // continue
2007
 
 
 
 
 
2008
 
2009
+ if (true !== response) {
2010
+ deleteClone(clone);
2011
+ return;
2012
+ }
2013
+ });
2014
+ };
2015
+ /**
2016
+ * Cancel Cloning Process
2017
+ */
2018
+
2019
+
2020
+ var cancelCloning = function cancelCloning() {
2021
+ that.timer('stop');
2022
+
2023
+ if (true === that.isFinished) {
2024
+ return true;
2025
+ }
2026
+
2027
+ ajax({
2028
+ action: 'wpstg_cancel_clone',
2029
+ clone: that.data.cloneID,
2030
+ accessToken: wpstg.accessToken,
2031
+ nonce: wpstg.nonce
2032
+ }, function (response) {
2033
+ if (response && 'undefined' !== typeof response["delete"] && response["delete"] === 'finished') {
2034
+ cache.get('.wpstg-loader').hide(); // Load overview
2035
+
2036
+ loadOverview();
2037
+ return;
2038
+ }
2039
+
2040
+ if (true !== response) {
2041
+ // continue
2042
+ cancelCloning();
2043
+ return;
2044
+ } // Load overview
2045
+
2046
+
2047
+ loadOverview();
2048
+ });
2049
+ };
2050
+ /**
2051
+ * Cancel Cloning Process
2052
+ */
2053
+
2054
+
2055
+ var cancelCloningUpdate = function cancelCloningUpdate() {
2056
+ if (true === that.isFinished) {
2057
+ return true;
2058
+ }
2059
+
2060
+ ajax({
2061
+ action: 'wpstg_cancel_update',
2062
+ clone: that.data.cloneID,
2063
+ accessToken: wpstg.accessToken,
2064
+ nonce: wpstg.nonce
2065
+ }, function (response) {
2066
+ if (response && 'undefined' !== typeof response["delete"] && response["delete"] === 'finished') {
2067
+ // Load overview
2068
+ loadOverview();
2069
+ return;
2070
+ }
2071
+
2072
+ if (true !== response) {
2073
+ // continue
2074
+ cancelCloningUpdate();
2075
+ return;
2076
+ } // Load overview
2077
+
2078
+
2079
+ loadOverview();
2080
+ });
2081
+ };
2082
+ /**
2083
+ * Cancel Cloning Process
2084
+ */
2085
+
2086
+
2087
+ var restart = function restart() {
2088
+ if (true === that.isFinished) {
2089
+ return true;
2090
+ }
2091
+
2092
+ ajax({
2093
+ action: 'wpstg_restart',
2094
+ // clone: that.data.cloneID,
2095
+ accessToken: wpstg.accessToken,
2096
+ nonce: wpstg.nonce
2097
+ }, function (response) {
2098
+ if (response && 'undefined' !== typeof response["delete"] && response["delete"] === 'finished') {
2099
+ // Load overview
2100
+ loadOverview();
2101
+ return;
2102
+ }
2103
+
2104
+ if (true !== response) {
2105
+ // continue
2106
+ cancelCloningUpdate();
2107
+ return;
2108
+ } // Load overview
2109
+
2110
+
2111
+ loadOverview();
2112
+ });
2113
+ };
2114
+ /**
2115
+ * Scroll the window log to bottom
2116
+ * @return void
2117
+ */
2118
+
2119
+
2120
+ var logscroll = function logscroll() {
2121
+ var $div = cache.get('.wpstg-log-details');
2122
+
2123
+ if ('undefined' !== typeof $div[0]) {
2124
+ $div.scrollTop($div[0].scrollHeight);
2125
+ }
2126
+ };
2127
+ /**
2128
+ * Append the log to the logging window
2129
+ * @param string log
2130
+ * @return void
2131
+ */
2132
+
2133
+
2134
+ var getLogs = function getLogs(log) {
2135
+ if (log != null && 'undefined' !== typeof log) {
2136
+ if (log.constructor === Array) {
2137
+ $.each(log, function (index, value) {
2138
+ if (value === null) {
2139
+ return;
2140
+ }
2141
+
2142
+ if (value.type === 'ERROR') {
2143
+ cache.get('.wpstg-log-details').append('<span style="color:red;">[' + value.type + ']</span>-' + '[' + value.date + '] ' + value.message + '</br>');
2144
+ } else {
2145
+ cache.get('.wpstg-log-details').append('[' + value.type + ']-' + '[' + value.date + '] ' + value.message + '</br>');
2146
+ }
2147
+ });
2148
+ } else {
2149
+ cache.get('.wpstg-log-details').append('[' + log.type + ']-' + '[' + log.date + '] ' + log.message + '</br>');
2150
+ }
2151
+ }
2152
+
2153
+ logscroll();
2154
+ };
2155
+ /**
2156
+ * Check diskspace
2157
+ * @return string json
2158
+ */
2159
+
2160
+
2161
+ var checkDiskSpace = function checkDiskSpace() {
2162
+ cache.get('#wpstg-check-space').on('click', function (e) {
2163
+ cache.get('.wpstg-loader').show();
2164
+ var excludedDirectories = encodeURIComponent(that.directoryNavigator.getExcludedDirectories());
2165
+ var extraDirectories = encodeURIComponent(that.directoryNavigator.getExtraDirectoriesRootOnly());
2166
+ ajax({
2167
+ action: 'wpstg_check_disk_space',
2168
+ accessToken: wpstg.accessToken,
2169
+ nonce: wpstg.nonce,
2170
+ excludedDirectories: excludedDirectories,
2171
+ extraDirectories: extraDirectories
2172
+ }, function (response) {
2173
+ if (false === response) {
2174
+ cache.get('#wpstg-clone-id-error').text('Can not detect required disk space').show();
2175
+ cache.get('.wpstg-loader').hide();
2176
+ return;
2177
+ } // Show required disk space
2178
+
2179
+
2180
+ cache.get('#wpstg-clone-id-error').html('Estimated necessary disk space: ' + response.usedspace + '<br> <span style="color:#444;">Before you proceed ensure your account has enough free disk space to hold the entire instance of the production site. You can check the available space from your hosting account (cPanel or similar).</span>').show();
2181
+ cache.get('.wpstg-loader').hide();
2182
+ }, 'json', false);
2183
+ });
2184
+ };
2185
+
2186
+ var mainTabs = function mainTabs() {
2187
+ $('.wpstg--tab--header a[data-target]').on('click', function () {
2188
+ var $this = $(this);
2189
+ var target = $this.attr('data-target');
2190
+ var $wrapper = $this.parents('.wpstg--tab--wrapper');
2191
+ var $menuItems = $wrapper.find('.wpstg--tab--header a[data-target]');
2192
+ var $contents = $wrapper.find('.wpstg--tab--contents > .wpstg--tab--content');
2193
+ $contents.filter('.wpstg--tab--active:not(.wpstg--tab--active' + target + ')').removeClass('wpstg--tab--active');
2194
+ $menuItems.not($this).removeClass('wpstg--tab--active');
2195
+ $this.addClass('wpstg--tab--active');
2196
+ $(target).addClass('wpstg--tab--active');
2197
+
2198
+ if ('#wpstg--tab--backup' === target) {
2199
+ that.backups.init();
2200
+ }
2201
+
2202
+ if ('#wpstg--tab--database-backups' === target) {
2203
+ window.dispatchEvent(new Event('database-backups-tab'));
2204
+ }
2205
+ });
2206
+ };
2207
+ /**
2208
+ * Show or hide animated loading icon
2209
+ * @param isLoading bool
2210
+ */
2211
+
2212
+
2213
+ var isLoading = function isLoading(_isLoading) {
2214
+ if (!_isLoading || _isLoading === false) {
2215
+ cache.get('.wpstg-loader').hide();
2216
+ } else {
2217
+ cache.get('.wpstg-loader').show();
2218
+ }
2219
+ };
2220
+ /**
2221
+ * Count up processing execution time
2222
+ * @param string status
2223
+ * @return html
2224
+ */
2225
+
2226
+
2227
+ that.timer = function (status) {
2228
+ if (status === 'stop') {
2229
+ var time = that.time;
2230
+ that.time = 1;
2231
+ clearInterval(that.executionTime);
2232
+ return that.convertSeconds(time);
2233
+ }
2234
+
2235
+ that.executionTime = setInterval(function () {
2236
+ if (null !== document.getElementById('wpstg-processing-timer')) {
2237
+ document.getElementById('wpstg-processing-timer').innerHTML = 'Elapsed Time: ' + that.convertSeconds(that.time);
2238
+ }
2239
+
2240
+ that.time++;
2241
+
2242
+ if (status === 'stop') {
2243
+ that.time = 1;
2244
+ clearInterval(that.executionTime);
2245
+ }
2246
+ }, 1000);
2247
+ };
2248
+ /**
2249
+ * Convert seconds to hourly format
2250
+ * @param int seconds
2251
+ * @return string
2252
+ */
2253
+
2254
+
2255
+ that.convertSeconds = function (seconds) {
2256
+ var date = new Date(null);
2257
+ date.setSeconds(seconds); // specify value for SECONDS here
2258
+
2259
+ return date.toISOString().substr(11, 8);
2260
+ };
2261
+ /**
2262
+ * Start Cloning Process
2263
+ * @type {Function}
2264
+ */
2265
+
2266
+
2267
+ that.startCloning = function () {
2268
+ resetErrors(); // Register function for checking disk space
2269
+
2270
+ checkDiskSpace();
2271
+
2272
+ if ('wpstg_cloning' !== that.data.action && 'wpstg_update' !== that.data.action && 'wpstg_reset' !== that.data.action) {
2273
+ return;
2274
+ }
2275
+
2276
+ that.isCancelled = false; // Start the process
2277
+
2278
+ start(); // Functions
2279
+ // Start
2280
+
2281
+ function start() {
2282
+ cache.get('.wpstg-loader').show();
2283
+ cache.get('#wpstg-cancel-cloning').text('Cancel');
2284
+ cache.get('#wpstg-resume-cloning').hide();
2285
+ cache.get('#wpstg-error-details').hide(); // Clone Database
2286
+
2287
+ setTimeout(function () {
2288
+ // cloneDatabase();
2289
+ window.addEventListener('beforeunload', WPStaging.warnIfClosingDuringProcess);
2290
+ processing();
2291
+ }, wpstg.delayReq);
2292
+ that.timer('start');
2293
+ }
2294
+ /**
2295
+ * Start ajax processing
2296
+ * @return string
2297
+ */
2298
+
2299
+
2300
+ var processing = function processing() {
2301
+ if (true === that.isCancelled) {
2302
+ window.removeEventListener('beforeunload', WPStaging.warnIfClosingDuringProcess);
2303
+ return false;
2304
+ }
2305
+
2306
+ isLoading(true);
2307
+ var excludedDirectories = '';
2308
+ var extraDirectories = '';
2309
+
2310
+ if (that.directoryNavigator !== null) {
2311
+ excludedDirectories = that.directoryNavigator.getExcludedDirectories();
2312
+ extraDirectories = that.directoryNavigator.getExtraDirectoriesRootOnly();
2313
+ } // Show logging window
2314
+
2315
+
2316
+ cache.get('.wpstg-log-details').show();
2317
+ WPStaging.ajax({
2318
+ action: 'wpstg_processing',
2319
+ accessToken: wpstg.accessToken,
2320
+ nonce: wpstg.nonce,
2321
+ excludedTables: getExcludedTables(),
2322
+ excludedDirectories: encodeURIComponent(excludedDirectories),
2323
+ extraDirectories: encodeURIComponent(extraDirectories)
2324
+ }, function (response) {
2325
+ showAjaxFatalError(response); // Add Log messages
2326
+
2327
+ if ('undefined' !== typeof response.last_msg && response.last_msg) {
2328
+ getLogs(response.last_msg);
2329
+ } // Continue processing
2330
+
2331
+
2332
+ if (false === response.status) {
2333
+ progressBar(response);
2334
+ setTimeout(function () {
2335
+ cache.get('.wpstg-loader').show();
2336
+ processing();
2337
+ }, wpstg.delayReq);
2338
+ } else if (true === response.status && 'finished' !== response.status) {
2339
+ cache.get('#wpstg-error-details').hide();
2340
+ cache.get('#wpstg-error-wrapper').hide();
2341
+ progressBar(response);
2342
+ processing();
2343
+ } else if ('finished' === response.status || 'undefined' !== typeof response.job_done && response.job_done) {
2344
+ window.removeEventListener('beforeunload', WPStaging.warnIfClosingDuringProcess);
2345
+ finish(response);
2346
+ }
2347
+ }, 'json', false);
2348
+ }; // Finish
2349
+
2350
+
2351
+ function finish(response) {
2352
+ if (true === that.getLogs) {
2353
+ getLogs();
2354
+ }
2355
+
2356
+ progressBar(response); // Add Log
2357
+
2358
+ if ('undefined' !== typeof response.last_msg) {
2359
+ getLogs(response.last_msg);
2360
+ }
2361
+
2362
+ cache.get('.wpstg-loader').hide();
2363
+ cache.get('#wpstg-processing-header').html('Processing Complete');
2364
+ $('#wpstg-processing-status').text('Succesfully finished');
2365
+ cache.get('#wpstg_staging_name').html(that.data.cloneID);
2366
+ cache.get('#wpstg-finished-result').show();
2367
+ cache.get('#wpstg-cancel-cloning').hide();
2368
+ cache.get('#wpstg-resume-cloning').hide();
2369
+ cache.get('#wpstg-cancel-cloning-update').prop('disabled', true);
2370
+ var $link1 = cache.get('#wpstg-clone-url-1');
2371
+ var $link = cache.get('#wpstg-clone-url');
2372
+ $link1.attr('href', response.url);
2373
+ $link1.html(response.url);
2374
+ $link.attr('href', response.url);
2375
+ cache.get('#wpstg-remove-clone').data('clone', that.data.cloneID); // Finished
2376
+
2377
+ that.isFinished = true;
2378
+ that.timer('stop');
2379
+ cache.get('.wpstg-loader').hide();
2380
+ cache.get('#wpstg-processing-header').html('Processing Complete'); // show alert
2381
+
2382
+ var msg = wpstg.i18n.cloneResetComplete;
2383
+
2384
+ if (that.data.action === 'wpstg_update') {
2385
+ msg = wpstg.i18n.cloneUpdateComplete;
2386
+ }
2387
+
2388
+ if (that.data.action === 'wpstg_update' || that.data.action === 'wpstg_reset') {
2389
+ Swal.fire({
2390
+ title: '',
2391
+ icon: 'success',
2392
+ html: msg,
2393
+ width: '500px',
2394
+ focusConfirm: true
2395
+ });
2396
+ }
2397
+
2398
+ return false;
2399
+ }
2400
+ /**
2401
+ * Add percentage progress bar
2402
+ * @param object response
2403
+ * @return {Boolean}
2404
+ */
2405
+
2406
+
2407
+ var progressBar = function progressBar(response, restart) {
2408
+ if ('undefined' === typeof response.percentage) {
2409
+ return false;
2410
+ }
2411
+
2412
+ if (response.job === 'database') {
2413
+ cache.get('#wpstg-progress-db').width(response.percentage * 0.2 + '%').html(response.percentage + '%');
2414
+ cache.get('#wpstg-processing-status').html(response.percentage.toFixed(0) + '%' + ' - Step 1 of 4 Cloning Database Tables...');
2415
+ }
2416
+
2417
+ if (response.job === 'SearchReplace') {
2418
+ cache.get('#wpstg-progress-db').css('background-color', '#3bc36b');
2419
+ cache.get('#wpstg-progress-db').html('1. Database'); // Assumption: All previous steps are done.
2420
+ // This avoids bugs where some steps are skipped and the progress bar is incomplete as a result
2421
+
2422
+ cache.get('#wpstg-progress-db').width('20%');
2423
+ cache.get('#wpstg-progress-sr').width(response.percentage * 0.1 + '%').html(response.percentage + '%');
2424
+ cache.get('#wpstg-processing-status').html(response.percentage.toFixed(0) + '%' + ' - Step 2 of 4 Preparing Database Data...');
2425
+ }
2426
+
2427
+ if (response.job === 'directories') {
2428
+ cache.get('#wpstg-progress-sr').css('background-color', '#3bc36b');
2429
+ cache.get('#wpstg-progress-sr').html('2. Data');
2430
+ cache.get('#wpstg-progress-sr').width('10%');
2431
+ cache.get('#wpstg-progress-dirs').width(response.percentage * 0.1 + '%').html(response.percentage + '%');
2432
+ cache.get('#wpstg-processing-status').html(response.percentage.toFixed(0) + '%' + ' - Step 3 of 4 Getting files...');
2433
+ }
2434
+
2435
+ if (response.job === 'files') {
2436
+ cache.get('#wpstg-progress-dirs').css('background-color', '#3bc36b');
2437
+ cache.get('#wpstg-progress-dirs').html('3. Files');
2438
+ cache.get('#wpstg-progress-dirs').width('10%');
2439
+ cache.get('#wpstg-progress-files').width(response.percentage * 0.6 + '%').html(response.percentage + '%');
2440
+ cache.get('#wpstg-processing-status').html(response.percentage.toFixed(0) + '%' + ' - Step 4 of 4 Copy files...');
2441
+ }
2442
+
2443
+ if (response.job === 'finish') {
2444
+ cache.get('#wpstg-progress-files').css('background-color', '#3bc36b');
2445
+ cache.get('#wpstg-progress-files').html('4. Copy Files');
2446
+ cache.get('#wpstg-progress-files').width('60%');
2447
+ cache.get('#wpstg-processing-status').html(response.percentage.toFixed(0) + '%' + ' - Cloning Process Finished');
2448
+ }
2449
+ };
2450
+ };
2451
+
2452
+ that.switchStep = function (step) {
2453
+ cache.get('.wpstg-current-step').removeClass('wpstg-current-step');
2454
+ cache.get('.wpstg-step' + step).addClass('wpstg-current-step');
2455
+ };
2456
+ /**
2457
+ * Initiation
2458
+ * @type {Function}
2459
+ */
2460
+
2461
+
2462
+ that.init = function () {
2463
+ loadOverview();
2464
+ elements();
2465
+ stepButtons();
2466
+ tabs();
2467
+ mainTabs();
2468
+ new WpstgCloneStaging();
2469
+ };
2470
+ /**
2471
+ * Ajax call
2472
+ * @type {ajax}
2473
+ */
2474
+
2475
 
2476
+ that.ajax = ajax;
2477
+ that.showError = showError;
2478
+ that.getLogs = getLogs;
2479
+ that.loadOverview = loadOverview; // TODO RPoC (too big, scattered and unorganized)
 
 
2480
 
2481
+ that.backups = {
2482
+ type: null,
2483
+ isCancelled: false,
2484
+ processInfo: {
2485
+ title: null,
2486
+ interval: null
2487
+ },
2488
+ modal: {
2489
+ create: {
2490
+ html: null,
2491
+ confirmBtnTxt: null
2492
  },
2493
+ process: {
2494
+ html: null,
2495
+ cancelBtnTxt: null,
2496
+ modal: null
2497
+ },
2498
+ download: {
2499
+ html: null
2500
+ },
2501
+ "import": {
2502
+ html: null,
2503
+ btnTxtNext: null,
2504
+ btnTxtConfirm: null,
2505
+ btnTxtCancel: null,
2506
+ searchReplaceForm: null,
2507
  file: null,
2508
+ containerUpload: null,
2509
+ containerFilesystem: null,
2510
+ setFile: function setFile(file, upload) {
2511
+ if (upload === void 0) {
2512
+ upload = true;
2513
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2514
 
2515
+ var toUnit = function toUnit(bytes) {
2516
+ var i = Math.floor(Math.log(bytes) / Math.log(1024));
2517
+ return (bytes / Math.pow(1024, i)).toFixed(2) * 1 + ' ' + ['B', 'kB', 'MB', 'GB', 'TB'][i];
2518
+ };
2519
 
2520
+ if (!file) {
2521
+ return;
2522
+ }
2523
 
2524
+ that.backups.modal["import"].file = file;
2525
+ that.backups.modal["import"].data.file = file.name;
2526
+ $('.wpstg--backup--import--selected-file').html(file.name + " <br /> (" + toUnit(file.size) + ")").show();
2527
+ $('.wpstg--drag').hide();
2528
+ $('.wpstg--drag-or-upload').show();
2529
 
2530
+ if (upload) {
2531
+ $('.wpstg--modal--actions .swal2-confirm').prop('disabled', true);
2532
+ that.backups.upload.start();
2533
+ }
2534
+ },
2535
+ baseDirectory: null,
2536
+ data: {
2537
+ file: null,
2538
+ search: [],
2539
+ replace: []
2540
+ }
2541
+ }
2542
  },
2543
+ messages: {
2544
+ WARNING: 'warning',
2545
+ ERROR: 'error',
2546
+ INFO: 'info',
2547
+ DEBUG: 'debug',
2548
+ CRITICAL: 'critical',
2549
+ data: {
2550
  all: [],
2551
+ // TODO RPoC
2552
  info: [],
2553
  error: [],
2554
  critical: [],
2555
  warning: [],
2556
  debug: []
2557
+ },
2558
+ shouldWarn: function shouldWarn() {
2559
+ return that.backups.messages.data.error.length > 0 || that.backups.messages.data.critical.length > 0;
2560
+ },
2561
+ countByType: function countByType(type) {
2562
+ if (type === void 0) {
2563
+ type = that.backups.messages.ERROR;
2564
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2565
 
2566
+ return that.backups.messages.data[type].length;
2567
+ },
2568
+ addMessage: function addMessage(message) {
2569
+ if (Array.isArray(message)) {
2570
+ message.forEach(function (item) {
2571
+ that.backups.messages.addMessage(item);
2572
+ });
2573
+ return;
2574
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2575
 
2576
+ var type = message.type.toLowerCase() || 'info';
 
 
 
 
 
 
 
 
 
 
 
 
 
2577
 
2578
+ if (!that.backups.messages.data[type]) {
2579
+ that.backups.messages.data[type] = [];
2580
+ }
2581
 
2582
+ that.backups.messages.data.all.push(message); // TODO RPoC
 
 
2583
 
2584
+ that.backups.messages.data[type].push(message);
2585
+ },
2586
+ reset: function reset() {
2587
+ that.backups.messages.data = {
2588
+ all: [],
2589
+ info: [],
2590
+ error: [],
2591
+ critical: [],
2592
+ warning: [],
2593
+ debug: []
2594
+ };
2595
+ }
2596
+ },
2597
+ timer: {
2598
+ totalSeconds: 0,
2599
+ interval: null,
2600
+ start: function start() {
2601
+ if (null !== that.backups.timer.interval) {
2602
  return;
2603
  }
2604
 
2605
+ var prettify = function prettify(seconds) {
2606
+ // If potentially anything can exceed 24h execution time than that;
2607
+ // const _seconds = parseInt(seconds, 10)
2608
+ // const hours = Math.floor(_seconds / 3600)
2609
+ // const minutes = Math.floor(_seconds / 60) % 60
2610
+ // seconds = _seconds % 60
2611
+ //
2612
+ // return [hours, minutes, seconds]
2613
+ // .map(v => v < 10 ? '0' + v : v)
2614
+ // .filter((v,i) => v !== '00' || i > 0)
2615
+ // .join(':')
2616
+ // ;
2617
+ // Are we sure we won't create anything that exceeds 24h execution time? If not then this;
2618
+ return "" + new Date(seconds * 1000).toISOString().substr(11, 8);
2619
+ };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2620
 
2621
+ that.backups.timer.interval = setInterval(function () {
2622
+ $('.wpstg--modal--process--elapsed-time').text(prettify(that.backups.timer.totalSeconds));
2623
+ that.backups.timer.totalSeconds++;
2624
+ }, 1000);
2625
+ },
2626
+ stop: function stop() {
2627
+ that.backups.timer.totalSeconds = 0;
2628
 
2629
+ if (that.backups.timer.interval) {
2630
+ clearInterval(that.backups.timer.interval);
2631
+ that.backups.timer.interval = null;
2632
+ }
2633
  }
2634
+ },
2635
+ upload: {
2636
+ reader: null,
2637
+ file: null,
2638
+ iop: 1000 * 1024,
2639
+ uploadInfo: function uploadInfo(isShow) {
2640
+ var $containerUpload = $('.wpstg--modal--import--upload--process');
2641
+ var $containerUploader = $('.wpstg--uploader');
2642
+
2643
+ if (isShow) {
2644
+ $containerUpload.css('display', 'flex');
2645
+ $containerUploader.hide();
2646
+ return;
2647
+ }
2648
 
2649
+ $containerUploader.css('display', 'flex');
2650
+ $containerUpload.hide();
2651
+ },
2652
+ start: function start() {
2653
+ that.backups.upload.reader = new FileReader();
2654
+ that.backups.upload.file = that.backups.modal["import"].file;
2655
+ that.backups.upload.uploadInfo(true);
2656
+ that.backups.upload.sendChunk();
2657
+ },
2658
+ sendChunk: function sendChunk(startsAt) {
2659
+ if (startsAt === void 0) {
2660
+ startsAt = 0;
2661
+ }
 
 
 
 
 
 
2662
 
2663
+ if (!that.backups.upload.file) {
2664
+ return;
2665
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2666
 
2667
+ var isReset = startsAt < 1;
2668
+ var endsAt = startsAt + that.backups.upload.iop + 1;
2669
+ var blob = that.backups.upload.file.slice(startsAt, endsAt);
 
 
2670
 
2671
+ that.backups.upload.reader.onloadend = function (event) {
2672
+ if (event.target.readyState !== FileReader.DONE) {
2673
+ return;
2674
+ }
 
 
2675
 
2676
+ var body = new FormData();
2677
+ body.append('accessToken', wpstg.accessToken);
2678
+ body.append('nonce', wpstg.nonce);
2679
+ body.append('data', event.target.result);
2680
+ body.append('filename', that.backups.upload.file.name);
2681
+ body.append('reset', isReset ? '1' : '0');
2682
+ fetch(ajaxurl + "?action=wpstg--backups--import--file-upload", {
2683
+ method: 'POST',
2684
+ body: body
2685
+ }).then(handleFetchErrors).then(function (res) {
2686
+ return res.json();
2687
+ }).then(function (res) {
2688
+ showAjaxFatalError(res, '', 'Submit an error report.');
2689
+ var writtenBytes = startsAt + that.backups.upload.iop;
2690
+ var percent = Math.floor(writtenBytes / that.backups.upload.file.size * 100);
2691
+
2692
+ if (endsAt >= that.backups.upload.file.size) {
2693
+ that.backups.upload.uploadInfo(false);
2694
+ isLoading(false);
2695
+ that.backups.switchModalToConfigure();
2696
+ return;
2697
+ }
2698
 
2699
+ $('.wpstg--modal--import--upload--progress--title > span').text(percent);
2700
+ $('.wpstg--modal--import--upload--progress').css('width', percent + "%");
2701
+ that.backups.upload.sendChunk(endsAt);
2702
+ })["catch"](function (e) {
2703
+ return showAjaxFatalError(e, '', 'Submit an error report.');
2704
+ });
2705
+ };
2706
 
2707
+ that.backups.upload.reader.readAsDataURL(blob);
 
2708
  }
2709
+ },
2710
+ status: {
2711
+ hasResponse: null,
2712
+ reTryAfter: 5000
2713
+ },
2714
+ init: function init() {
2715
+ this.create();
2716
+ this["delete"]();
2717
+ this.edit(); // noinspection JSIgnoredPromiseFromCall
2718
 
2719
+ that.backups.fetchListing();
2720
+ $('body').on('click', '.wpstg--backup--download', function () {
2721
+ var url = this.getAttribute('data-url');
 
 
 
 
 
2722
 
2723
+ if (url.length > 0) {
2724
+ window.location.href = url;
 
2725
  return;
2726
  }
2727
 
2728
+ that.backups.downloadModal({
2729
+ titleExport: this.getAttribute('data-title-export'),
2730
+ title: this.getAttribute('data-title'),
2731
+ id: this.getAttribute('data-id'),
2732
+ btnTxtCancel: this.getAttribute('data-btn-cancel-txt'),
2733
+ btnTxtConfirm: this.getAttribute('data-btn-download-txt')
2734
  });
2735
+ }).on('click', '.wpstg--backup--import', function () {
2736
+ // Clicked "Import" on the backup list
2737
+ that.backups.importModal();
2738
+ that.backups.modal["import"].data.file = this.getAttribute('data-filePath');
2739
+ that.backups.switchModalToConfigure(); // $('.wpstg--modal--actions .swal2-confirm').show();
2740
+ // $('.wpstg--modal--actions .swal2-confirm').prop('disabled', false);
2741
+ }).off('click', '#wpstg-import-backup').on('click', '#wpstg-import-backup', function () {
2742
+ that.backups.importModal();
2743
+ }) // Import
2744
+ .off('click', '.wpstg--backup--import--choose-option').on('click', '.wpstg--backup--import--choose-option', function () {
2745
+ var $this = $(this);
2746
+ var $parent = $this.parent();
2747
+
2748
+ if (!$parent.hasClass('wpstg--show-options')) {
2749
+ $parent.addClass('wpstg--show-options');
2750
+ $this.text($this.attr('data-txtChoose'));
2751
+ } else {
2752
+ $parent.removeClass('wpstg--show-options');
2753
+ $this.text($this.attr('data-txtOther'));
2754
+ }
2755
+ }).off('click', '.wpstg--modal--backup--import--search-replace--new').on('click', '.wpstg--modal--backup--import--search-replace--new', function (e) {
2756
+ e.preventDefault();
2757
+ var $container = $(Swal.getContainer()).find('.wpstg--modal--backup--import--search-replace--input--container');
2758
+ var total = $container.find('.wpstg--modal--backup--import--search-replace--input-group').length;
2759
+ $container.append(that.backups.modal["import"].searchReplaceForm.replace(/{i}/g, total));
2760
+ }).off('click', '.wpstg--modal--backup--import--search-replace--remove').on('click', '.wpstg--modal--backup--import--search-replace--remove', function (e) {
2761
+ e.preventDefault();
2762
+ $(e.target).closest('.wpstg--modal--backup--import--search-replace--input-group').remove();
2763
+ }).off('input', '.wpstg--backup--import--search').on('input', '.wpstg--backup--import--search', function () {
2764
+ var index = parseInt(this.getAttribute('data-index'));
2765
+
2766
+ if (!isNaN(index)) {
2767
+ that.backups.modal["import"].data.search[index] = this.value;
2768
+ }
2769
+ }).off('input', '.wpstg--backup--import--replace').on('input', '.wpstg--backup--import--replace', function () {
2770
+ var index = parseInt(this.getAttribute('data-index'));
2771
 
2772
+ if (!isNaN(index)) {
2773
+ that.backups.modal["import"].data.replace[index] = this.value;
2774
+ }
2775
+ }) // Other Options
2776
+ .off('click', '.wpstg--backup--import--option[data-option]').on('click', '.wpstg--backup--import--option[data-option]', function () {
2777
+ var option = this.getAttribute('data-option');
 
 
 
 
 
 
 
2778
 
2779
+ if (option === 'file') {
2780
+ $('input[type="file"][name="wpstg--backup--import--upload--file"]').trigger('click');
2781
+ return;
2782
+ }
2783
 
2784
+ if (option === 'upload') {
2785
+ that.backups.modal["import"].containerFilesystem.hide();
2786
+ that.backups.modal["import"].containerUpload.show();
2787
  }
 
 
 
 
 
 
 
2788
 
2789
+ if (option !== 'filesystem') {
2790
+ return;
2791
+ }
2792
 
2793
+ that.backups.modal["import"].containerUpload.hide();
2794
+ var $containerFilesystem = that.backups.modal["import"].containerFilesystem;
2795
+ $containerFilesystem.show();
2796
+ fetch(ajaxurl + "?action=wpstg--backups--import--file-list&_=" + Math.random() + "&accessToken=" + wpstg.accessToken + "&nonce=" + wpstg.nonce).then(handleFetchErrors).then(function (res) {
2797
+ return res.json();
2798
+ }).then(function (res) {
2799
+ var $ul = $('.wpstg--modal--backup--import--filesystem ul');
2800
+ $ul.empty();
2801
 
2802
+ if (!res || isEmpty(res)) {
2803
+ $ul.append("<span id=\"wpstg--backups--import--file-list-empty\">" + wpstg.i18n.noImportFileFound + "</span><br />");
2804
+ $('.wpstg--modal--backup--import--search-replace--wrapper').hide();
2805
+ return;
2806
+ }
 
 
 
 
 
 
 
 
 
 
 
2807
 
2808
+ $ul.append("<span id=\"wpstg--backups--import--file-list\">" + wpstg.i18n.selectFileToImport + "</span><br />");
2809
+ res.forEach(function (file, index) {
2810
+ $ul.append("\n<li data-filepath=\"" + file.fullPath + "\" class=\"wpstg--backups--import--file-list--sigle-item\">\n <ul class=\"wpstg-import-backup-more-info wpstg-import-backup-more-info-" + index + ("\">\n <li style=\"font-weight: bold\">" + file.backupName + "</li>\n <li>Created on: " + file.dateCreatedFormatted + "</li>\n <li>Size: " + file.size + "</li>\n <li>\n <div class=\"wpstg-import-backup-contains-title\">This backup contains:</div>\n <ul class=\"wpstg-import-backup-contains\">\n ") + (file.isExportingDatabase ? '<li><span class="dashicons dashicons-database wpstg--tooltip"><div class=\'wpstg--tooltiptext\'>Database</div></span></li>' : '') + "\n " + (file.isExportingPlugins ? '<li><span class="dashicons dashicons-admin-plugins wpstg--tooltip"><div class=\'wpstg--tooltiptext\'>Plugins</div></span></li>' : '') + "\n " + (file.isExportingMuPlugins ? '<li><span class="dashicons dashicons-plugins-checked wpstg--tooltip"><div class=\'wpstg--tooltiptext\'>Mu-plugins</div></span></li>' : '') + "\n " + (file.isExportingThemes ? '<li><span class="dashicons dashicons-layout wpstg--tooltip"><div class=\'wpstg--tooltiptext\'>Themes</div></span></li>' : '') + "\n " + (file.isExportingUploads ? '<li><span class="dashicons dashicons-images-alt wpstg--tooltip"><div class=\'wpstg--tooltiptext\'>Uploads</div></span></li>' : '') + "\n " + (file.isExportingOtherWpContentFiles ? '<li><span class="dashicons dashicons-admin-generic wpstg--tooltip"><div class=\'wpstg--tooltiptext\'>Other files in wp-content</div></span></li>' : '') + ("\n </ul>\n </li>\n <li>Filename: " + file.name + "</li>\n </ul>\n</li>\n"));
2811
+ });
2812
+ return res;
2813
+ })["catch"](function (e) {
2814
+ return showAjaxFatalError(e, '', 'Submit an error report.');
2815
+ });
2816
+ }).off('change', 'input[type="file"][name="wpstg--backup--import--upload--file"]').on('change', 'input[type="file"][name="wpstg--backup--import--upload--file"]', function () {
2817
+ that.backups.modal["import"].setFile(this.files[0] || null);
2818
+ }).off('change', 'input[type="radio"][name="backup_import_file"]').on('change', 'input[type="radio"][name="backup_import_file"]', function () {
2819
+ $('.wpstg--modal--actions .swal2-confirm').show();
2820
+ $('.wpstg--modal--actions .swal2-confirm').prop('disabled', false);
2821
+ that.backups.modal["import"].data.file = this.value;
2822
+ }) // Drag & Drop
2823
+ .on('drag dragstart dragend dragover dragenter dragleave drop', '.wpstg--modal--backup--import--upload--container', function (e) {
2824
+ e.preventDefault();
2825
+ e.stopPropagation();
2826
+ }).on('dragover dragenter', '.wpstg--modal--backup--import--upload--container', function () {
2827
+ $(this).addClass('wpstg--has-dragover');
2828
+ }).on('dragleave dragend drop', '.wpstg--modal--backup--import--upload--container', function () {
2829
+ $(this).removeClass('wpstg--has-dragover');
2830
+ }).on('drop', '.wpstg--modal--backup--import--upload--container', function (e) {
2831
+ // Uploaded a file through the "Import Backup modal"
2832
+ that.backups.modal["import"].setFile(e.originalEvent.dataTransfer.files[0] || null);
2833
+ }).on('click', '.wpstg--modal--backup--import--filesystem li', function (e) {
2834
+ // Selected an existing backup in the Import Backup modal
2835
+ var fullPath = $(e.target).closest('.wpstg--backups--import--file-list--sigle-item').data().filepath;
2836
+
2837
+ if (!fullPath.length) {
2838
+ alert('Error: Could not get file path.');
2839
+ return;
2840
+ }
2841
 
2842
+ that.backups.modal["import"].data.file = fullPath;
2843
+ that.backups.switchModalToConfigure(); // $('.wpstg--modal--actions .swal2-confirm').prop('disabled', false);
2844
+ // that.backups.modal.gotoStart();
2845
+ }).on('change', '.wpstg-advanced-options-site input[type="checkbox"]', function (e) {
2846
+ /*
2847
+ * We use a timeout here to simulate an "afterChange" event.
2848
+ * This allows us to read from the DOM whether the checkbox is checked or not,
2849
+ * instead of having to read from the event, which would require a lengthier code
2850
+ * to account for all elements we might want to read.
2851
+ */
2852
+ setTimeout(function (e) {
2853
+ // Reset
2854
+ document.getElementById('exportUploadsWithoutDatabaseWarning').style.display = 'none'; // Exporting Media Library without Database
2855
+
2856
+ var databaseChecked = document.getElementById('includeDatabaseInBackup').checked;
2857
+ var mediaLibraryChecked = document.getElementById('includeMediaLibraryInBackup').checked;
2858
+
2859
+ if (mediaLibraryChecked && !databaseChecked) {
2860
+ document.getElementById('exportUploadsWithoutDatabaseWarning').style.display = 'block';
2861
+ }
2862
+ }, 100);
2863
  });
2864
+ },
2865
+ fetchListing: function fetchListing(isResetErrors) {
2866
+ if (isResetErrors === void 0) {
2867
+ isResetErrors = true;
2868
+ }
2869
 
 
 
 
2870
  isLoading(true);
 
2871
 
2872
+ if (isResetErrors) {
2873
+ resetErrors();
 
2874
  }
2875
 
2876
+ return fetch(ajaxurl + "?action=wpstg--backups--listing&_=" + Math.random() + "&accessToken=" + wpstg.accessToken + "&nonce=" + wpstg.nonce).then(handleFetchErrors).then(function (res) {
2877
+ return res.json();
2878
+ }).then(function (res) {
2879
+ showAjaxFatalError(res, '', 'Submit an error report.');
2880
+ cache.get('#wpstg--tab--backup').html(res);
 
 
 
 
2881
  isLoading(false);
2882
+ window.dispatchEvent(new Event('backupListingFinished'));
2883
+ return res;
2884
+ })["catch"](function (e) {
2885
+ return showAjaxFatalError(e, '', 'Submit an error report.');
2886
  });
2887
+ },
2888
+ "delete": function _delete() {
2889
+ $('#wpstg--tab--backup').off('click', '.wpstg-delete-backup[data-md5]').on('click', '.wpstg-delete-backup[data-md5]', function (e) {
2890
+ e.preventDefault();
2891
+ resetErrors();
2892
+
2893
+ if (!confirm('Are you sure you want to delete this backup?')) {
2894
+ return;
 
 
 
 
 
 
 
2895
  }
 
 
2896
 
2897
+ isLoading(true);
2898
+ cache.get('#wpstg-existing-backups').hide();
2899
+ var md5 = this.getAttribute('data-md5');
2900
+ that.ajax({
2901
+ action: 'wpstg--backups--delete',
2902
+ md5: md5,
2903
+ accessToken: wpstg.accessToken,
2904
+ nonce: wpstg.nonce
2905
+ }, function (response) {
2906
+ showAjaxFatalError(response, '', ' Please submit an error report by using the REPORT ISSUE button.');
2907
+ isLoading(false);
2908
+ that.backups.fetchListing();
2909
+ });
2910
+ }); // Force delete if backup tables do not exist
2911
+ // TODO This is bloated, no need extra ID, use existing one?
2912
+
2913
+ $('#wpstg-error-wrapper').off('click', '#wpstg-backup-force-delete').on('click', '#wpstg-backup-force-delete', function (e) {
2914
+ e.preventDefault();
2915
+ resetErrors();
2916
+ isLoading(true);
2917
+ var id = this.getAttribute('data-id');
2918
+
2919
+ if (!confirm('Do you want to delete this backup ' + id + ' from the listed backups?')) {
2920
+ isLoading(false);
2921
+ return false;
2922
+ }
2923
 
2924
+ that.ajax({
2925
+ action: 'wpstg--backups--delete',
2926
+ id: id,
2927
+ accessToken: wpstg.accessToken,
2928
+ nonce: wpstg.nonce
2929
+ }, function (response) {
2930
+ showAjaxFatalError(response, '', ' Please submit an error report by using the REPORT ISSUE button.'); // noinspection JSIgnoredPromiseFromCall
2931
 
2932
+ that.backups.fetchListing();
2933
+ isLoading(false);
2934
+ });
2935
+ });
2936
+ },
2937
+ create: function create() {
2938
+ var prepareBackup = function prepareBackup(data) {
2939
+ WPStaging.ajax({
2940
+ action: 'wpstg--backups--prepare-export',
2941
+ accessToken: wpstg.accessToken,
2942
+ nonce: wpstg.nonce,
2943
+ wpstgExportData: data
2944
+ }, function (response) {
2945
+ if (response.success) {
2946
+ that.backups.timer.start();
2947
+ createBackup();
2948
+ } else {
2949
+ showAjaxFatalError(response.data, '', 'Submit an error report.');
2950
+ }
2951
+ }, 'json', false, 0, 1.25);
2952
  };
2953
 
2954
+ var createBackup = function createBackup() {
2955
+ resetErrors();
2956
+
2957
+ if (that.backups.isCancelled) {
2958
+ // Swal.close();
2959
  return;
2960
  }
2961
 
2962
+ var statusStop = function statusStop() {
2963
+ clearInterval(that.backups.processInfo.interval);
2964
+ that.backups.processInfo.interval = null;
2965
+ };
 
 
2966
 
2967
+ var status = function status() {
2968
+ if (that.backups.processInfo.interval !== null) {
2969
  return;
2970
  }
2971
 
2972
+ that.backups.processInfo.interval = setInterval(function () {
2973
+ if (true === that.backups.isCancelled) {
 
 
 
 
 
2974
  statusStop();
2975
+ return;
2976
  }
2977
 
2978
+ if (that.backups.status.hasResponse === false) {
2979
  return;
2980
  }
2981
 
2982
+ that.backups.status.hasResponse = false;
2983
+ fetch(ajaxurl + "?action=wpstg--backups--status&accessToken=" + wpstg.accessToken + "&nonce=" + wpstg.nonce).then(function (res) {
2984
+ return res.json();
2985
+ }).then(function (res) {
2986
+ that.backups.status.hasResponse = true;
 
 
 
 
 
 
 
 
 
 
 
 
2987
 
2988
+ if (typeof res === 'undefined') {
2989
+ statusStop();
2990
+ }
 
 
 
2991
 
2992
+ if (that.backups.processInfo.title === res.currentStatusTitle) {
2993
+ return;
2994
+ }
2995
+
2996
+ that.backups.processInfo.title = res.currentStatusTitle;
2997
+ var $container = $(Swal.getContainer());
2998
+ $container.find('.wpstg--modal--process--title').text(res.currentStatusTitle);
2999
+ $container.find('.wpstg--modal--process--percent').text('0');
3000
+ })["catch"](function (e) {
3001
+ that.backups.status.hasResponse = true;
3002
+ showAjaxFatalError(e, '', 'Submit an error report.');
3003
+ });
3004
+ }, 5000);
3005
+ };
3006
 
3007
+ WPStaging.ajax({
3008
+ action: 'wpstg--backups--export',
3009
+ accessToken: wpstg.accessToken,
3010
+ nonce: wpstg.nonce
3011
+ }, function (response) {
3012
+ if (typeof response === 'undefined') {
3013
+ setTimeout(function () {
3014
+ createBackup();
3015
+ }, wpstg.delayReq);
3016
+ return;
3017
+ }
3018
 
3019
+ that.backups.processResponse(response);
 
 
 
 
3020
 
3021
+ if (!that.backups.processInfo.interval) {
3022
+ status();
 
 
 
3023
  }
3024
 
3025
+ if (response.status === false) {
3026
+ createBackup();
3027
+ } else if (response.status === true) {
3028
+ $('#wpstg--progress--status').text('Backup successfully created!');
3029
+ that.backups.type = null;
3030
+
3031
+ if (that.backups.messages.shouldWarn()) {
3032
+ // noinspection JSIgnoredPromiseFromCall
3033
+ that.backups.fetchListing();
3034
+ that.backups.logsModal();
3035
  return;
3036
+ }
3037
 
3038
+ statusStop();
3039
+ Swal.close();
3040
+ that.backups.fetchListing().then(function () {
3041
+ if (!response.backupMd5) {
3042
+ showError('Failed to get backup md5 from response');
3043
+ return;
3044
+ } // Wait for fetchListing to populate the DOM with the backup data that we want to read
3045
 
 
 
 
 
 
3046
 
3047
+ var $el = '';
3048
+ var timesWaited = 0;
3049
+ var intervalWaitForBackupInDom = setInterval(function () {
3050
+ timesWaited++;
3051
+ $el = $(".wpstg--backup--download[data-md5=\"" + response.backupMd5 + "\"]"); // Could not find element, let's try again...
3052
 
3053
+ if (!$el.length) {
3054
+ if (timesWaited >= 10) {
3055
+ // Bail: We tried too many times and couldn't find.
3056
+ clearInterval(intervalWaitForBackupInDom);
3057
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3058
 
3059
+ return;
3060
+ } // Found it. No more need for the interval.
 
 
 
3061
 
 
 
 
 
 
 
 
 
 
3062
 
3063
+ clearInterval(intervalWaitForBackupInDom);
3064
+ var backupSize = response.hasOwnProperty('backupSize') ? ' (' + response.backupSize + ')' : '';
3065
+ that.backups.downloadModal({
3066
+ id: $el.data('id'),
3067
+ url: $el.data('url'),
3068
+ title: $el.data('title'),
3069
+ titleExport: $el.data('title-export'),
3070
+ btnTxtCancel: $el.data('btn-cancel-txt'),
3071
+ btnTxtConfirm: $el.data('btn-download-txt') + backupSize
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3072
  });
3073
+ $('.wpstg--modal--download--logs--wrapper').show();
3074
+ var $logsContainer = $('.wpstg--modal--process--logs');
3075
+ that.backups.messages.data.all.forEach(function (message) {
3076
+ var msgClass = "wpstg--modal--process--msg--" + message.type.toLowerCase();
3077
+ $logsContainer.append("<p class=\"" + msgClass + "\">[" + message.type + "] - [" + message.date + "] - " + message.message + "</p>");
3078
+ });
3079
+ }, 200);
3080
+ });
3081
+ } else {
3082
+ setTimeout(function () {
3083
+ createBackup();
3084
+ }, wpstg.delayReq);
3085
+ }
3086
+ }, 'json', false, 0, // Don't retry upon failure
3087
+ 1.25);
3088
+ };
3089
 
3090
+ var $body = $('body');
3091
+ $body.off('click', '.wpstg--tab--toggle').on('click', '.wpstg--tab--toggle', function () {
3092
+ var $this = $(this);
3093
+ var $target = $($this.attr('data-target'));
3094
+ $target.toggle();
3095
 
3096
+ if ($target.is(':visible')) {
3097
+ $this.find('span').text('▼');
3098
+ } else {
3099
+ $this.find('span').text('►');
3100
+ }
3101
+ }).off('change', '[name="includedDirectories\[\]"], input#includeDatabaseInBackup, input#includeOtherFilesInWpContent').on('change', '[type="checkbox"][name="includedDirectories\[\]"], input#includeDatabaseInBackup, input#includeOtherFilesInWpContent', function () {
3102
+ var isExportingAnyDir = $('[type="checkbox"][name="includedDirectories\[\]"]:checked').length > 0;
3103
+ var isExportingDatabase = $('input#includeDatabaseInBackup:checked').length === 1;
3104
+ var isExportingOtherFilesInWpContent = $('input#includeOtherFilesInWpContent:checked').length === 1;
3105
 
3106
+ if (!isExportingAnyDir && !isExportingDatabase && !isExportingOtherFilesInWpContent) {
3107
+ $('.swal2-confirm').prop('disabled', true);
3108
+ } else {
3109
+ $('.swal2-confirm').prop('disabled', false);
3110
+ }
3111
+ }); // Add backup name and notes
3112
+
3113
+ $('#wpstg--tab--backup').off('click', '#wpstg-new-backup').on('click', '#wpstg-new-backup', /*#__PURE__*/function () {
3114
+ var _ref = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(e) {
3115
+ var $newBackupModal, html, btnTxt, _yield$Swal$fire, formValues;
3116
+
3117
+ return regeneratorRuntime.wrap(function _callee$(_context) {
3118
+ while (1) {
3119
+ switch (_context.prev = _context.next) {
3120
+ case 0:
3121
+ resetErrors();
3122
+ e.preventDefault();
3123
+ that.backups.isCancelled = false;
3124
+
3125
+ if (!that.backups.modal.create.html || !that.backups.modal.create.confirmBtnTxt) {
3126
+ $newBackupModal = $('#wpstg--modal--backup--new');
3127
+ html = $newBackupModal.html();
3128
+ btnTxt = $newBackupModal.attr('data-confirmButtonText');
3129
+ that.backups.modal.create.html = html || null;
3130
+ that.backups.modal.create.confirmBtnTxt = btnTxt || null;
3131
+ $newBackupModal.remove();
3132
+ }
3133
 
3134
+ _context.next = 6;
3135
+ return Swal.fire({
3136
+ title: '',
3137
+ html: that.backups.modal.create.html,
3138
+ focusConfirm: false,
3139
+ confirmButtonText: that.backups.modal.create.confirmBtnTxt,
3140
+ showCancelButton: true,
3141
+ preConfirm: function preConfirm() {
3142
+ var container = Swal.getContainer();
3143
+ return {
3144
+ name: container.querySelector('input[name="backup_name"]').value || null,
3145
+ isExportingPlugins: container.querySelector('#includePluginsInBackup:checked') !== null,
3146
+ isExportingMuPlugins: container.querySelector('#includeMuPluginsInBackup:checked') !== null,
3147
+ isExportingThemes: container.querySelector('#includeThemesInBackup:checked') !== null,
3148
+ isExportingUploads: container.querySelector('#includeMediaLibraryInBackup:checked') !== null,
3149
+ isExportingOtherWpContentFiles: container.querySelector('#includeOtherFilesInWpContent:checked') !== null,
3150
+ isExportingDatabase: container.querySelector('#includeDatabaseInBackup:checked') !== null
3151
+ };
3152
+ }
3153
+ });
3154
+
3155
+ case 6:
3156
+ _yield$Swal$fire = _context.sent;
3157
+ formValues = _yield$Swal$fire.value;
3158
+
3159
+ if (formValues) {
3160
+ _context.next = 10;
3161
+ break;
3162
  }
 
3163
 
3164
+ return _context.abrupt("return");
 
 
 
 
 
 
3165
 
3166
+ case 10:
3167
+ that.backups.process({
3168
+ execute: function execute() {
3169
+ that.backups.messages.reset();
3170
+ prepareBackup(formValues);
3171
+ }
3172
+ });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3173
 
3174
+ case 11:
3175
+ case "end":
3176
+ return _context.stop();
3177
+ }
3178
+ }
3179
+ }, _callee);
3180
+ }));
3181
+
3182
+ return function (_x) {
3183
+ return _ref.apply(this, arguments);
3184
+ };
3185
+ }());
3186
+ },
3187
+ switchModalToConfigure: function switchModalToConfigure() {
3188
+ that.backups.modal["import"].containerUpload.hide();
3189
+ that.backups.modal["import"].containerFilesystem.hide();
3190
+ that.backups.modal["import"].containerConfigure.show();
3191
+ },
3192
+ // Edit backups name and notes
3193
+ edit: function edit() {
3194
+ $('#wpstg--tab--backup').off('click', '.wpstg--backup--edit[data-md5]').on('click', '.wpstg--backup--edit[data-md5]', /*#__PURE__*/function () {
3195
+ var _ref2 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee2(e) {
3196
+ var $this, name, notes, _yield$Swal$fire2, formValues;
3197
+
3198
+ return regeneratorRuntime.wrap(function _callee2$(_context2) {
3199
+ while (1) {
3200
+ switch (_context2.prev = _context2.next) {
3201
+ case 0:
3202
+ e.preventDefault();
3203
+ $this = $(this);
3204
+ name = $this.data('name');
3205
+ notes = $this.data('notes');
3206
+ _context2.next = 6;
3207
+ return Swal.fire({
3208
+ title: '',
3209
+ html: "\n <label id=\"wpstg-backup-edit-name\">Backup Name</label>\n <input id=\"wpstg-backup-edit-name-input\" class=\"swal2-input\" value=\"" + name + "\">\n <label>Additional Notes</label>\n <textarea id=\"wpstg-backup-edit-notes-textarea\" class=\"swal2-textarea\">" + notes + "</textarea>\n ",
3210
+ focusConfirm: false,
3211
+ confirmButtonText: 'Update Backup',
3212
+ showCancelButton: true,
3213
+ preConfirm: function preConfirm() {
3214
+ return {
3215
+ name: document.getElementById('wpstg-backup-edit-name-input').value || null,
3216
+ notes: document.getElementById('wpstg-backup-edit-notes-textarea').value || null
3217
+ };
3218
+ }
3219
+ });
3220
+
3221
+ case 6:
3222
+ _yield$Swal$fire2 = _context2.sent;
3223
+ formValues = _yield$Swal$fire2.value;
3224
+
3225
+ if (formValues) {
3226
+ _context2.next = 10;
3227
+ break;
3228
+ }
3229
 
3230
+ return _context2.abrupt("return");
3231
+
3232
+ case 10:
3233
+ that.ajax({
3234
+ action: 'wpstg--backups--edit',
3235
+ accessToken: wpstg.accessToken,
3236
+ nonce: wpstg.nonce,
3237
+ md5: $this.data('md5'),
3238
+ name: formValues.name,
3239
+ notes: formValues.notes
3240
+ }, function (response) {
3241
+ showAjaxFatalError(response, '', 'Submit an error report.'); // noinspection JSIgnoredPromiseFromCall
3242
+
3243
+ that.backups.fetchListing();
3244
+ });
3245
+
3246
+ case 11:
3247
+ case "end":
3248
+ return _context2.stop();
3249
+ }
3250
  }
3251
+ }, _callee2, this);
3252
+ }));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3253
 
3254
+ return function (_x2) {
3255
+ return _ref2.apply(this, arguments);
3256
+ };
3257
+ }());
3258
+ },
3259
+ cancel: function cancel() {
3260
+ that.backups.timer.stop();
3261
+ that.backups.isCancelled = true;
3262
  Swal.close();
3263
+ setTimeout(function () {
3264
+ return that.ajax({
3265
+ action: 'wpstg--backups--cancel',
3266
+ accessToken: wpstg.accessToken,
3267
+ nonce: wpstg.nonce,
3268
+ type: that.backups.type
3269
+ }, function (response) {
3270
+ showAjaxFatalError(response, '', 'Submit an error report.');
3271
+ });
3272
+ }, 500);
3273
+ },
3274
 
3275
+ /**
3276
+ * If process.execute exists, process.data and process.onResponse is not used
3277
+ * process = { data: {}, onResponse: (resp) => {}, onAfterClose: () => {}, execute: () => {}, isShowCancelButton: bool }
3278
+ * @param {object} process
3279
+ */
3280
+ process: function process(_process) {
3281
+ if (typeof _process.execute !== 'function' && (!_process.data || !_process.onResponse)) {
3282
+ Swal.close();
3283
+ showError('process.data and / or process.onResponse is not set');
3284
+ return;
3285
+ } // TODO move to backend and get the contents as xhr response?
3286
 
 
 
 
 
 
3287
 
3288
+ if (!that.backups.modal.process.html || !that.backups.modal.process.cancelBtnTxt) {
3289
+ var $modal = $('#wpstg--modal--backup--process');
3290
+ var html = $modal.html();
3291
+ var btnTxt = $modal.attr('data-cancelButtonText');
3292
+ that.backups.modal.process.html = html || null;
3293
+ that.backups.modal.process.cancelBtnTxt = btnTxt || null;
3294
+ $modal.remove();
3295
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3296
 
3297
+ $('body').off('click', '.wpstg--modal--process--logs--tail').on('click', '.wpstg--modal--process--logs--tail', function (e) {
3298
+ e.preventDefault();
3299
+ var container = Swal.getContainer();
3300
+ var $logs = $(container).find('.wpstg--modal--process--logs');
3301
+ $logs.toggle();
3302
 
3303
+ if ($logs.is(':visible')) {
3304
+ container.childNodes[0].style.width = '100%';
3305
+ container.style['z-index'] = 9999;
3306
+ } else {
3307
+ container.childNodes[0].style.width = '600px';
3308
  }
3309
+ });
3310
+ _process.isShowCancelButton = false !== _process.isShowCancelButton;
3311
+ that.backups.modal.process.modal = Swal.mixin({
3312
+ customClass: {
3313
+ cancelButton: 'wpstg--btn--cancel wpstg-blue-primary wpstg-link-btn',
3314
+ content: 'wpstg--process--content'
3315
+ },
3316
+ buttonsStyling: false
3317
+ }).fire({
3318
+ html: that.backups.modal.process.html,
3319
+ cancelButtonText: that.backups.modal.process.cancelBtnTxt,
3320
+ showCancelButton: _process.isShowCancelButton,
3321
+ showConfirmButton: false,
3322
+ allowOutsideClick: false,
3323
+ allowEscapeKey: false,
3324
+ width: 600,
3325
+ onRender: function onRender() {
3326
+ var _btnCancel = Swal.getContainer().getElementsByClassName('swal2-cancel wpstg--btn--cancel')[0];
3327
 
3328
+ var btnCancel = _btnCancel.cloneNode(true);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3329
 
3330
+ _btnCancel.parentNode.replaceChild(btnCancel, _btnCancel);
 
 
 
 
3331
 
3332
+ btnCancel.addEventListener('click', function (e) {
3333
+ if (confirm('Are You Sure? This will cancel the process!')) {
3334
+ Swal.close();
3335
+ }
3336
+ });
3337
 
3338
+ if (typeof _process.execute === 'function') {
3339
+ _process.execute();
 
 
3340
 
3341
+ return;
3342
+ }
3343
 
3344
+ if (!_process.data || !_process.onResponse) {
3345
+ Swal.close();
3346
+ showError('process.data and / or process.onResponse is not set');
3347
+ return;
 
3348
  }
3349
 
3350
+ that.ajax(_process.data, _process.onResponse);
3351
+ },
3352
+ onAfterClose: function onAfterClose() {
3353
+ return typeof _process.onAfterClose === 'function' && _process.onAfterClose();
3354
+ },
3355
+ onClose: function onClose() {
3356
+ that.backups.cancel();
3357
  }
3358
+ });
3359
+ },
3360
+ processResponse: function processResponse(response, useTitle) {
3361
+ if (response === null) {
3362
+ Swal.close();
3363
+ showError('Invalid Response; null');
3364
+ throw new Error("Invalid Response; " + response);
3365
+ }
3366
 
3367
+ var $container = $(Swal.getContainer());
 
3368
 
3369
+ var title = function title() {
3370
+ if ((response.title || response.statusTitle) && useTitle === true) {
3371
+ $container.find('.wpstg--modal--process--title').text(response.title || response.statusTitle);
3372
  }
3373
  };
3374
 
3375
+ var percentage = function percentage() {
3376
+ if (response.percentage) {
3377
+ $container.find('.wpstg--modal--process--percent').text(response.percentage);
3378
+ }
3379
+ };
3380
 
3381
+ var logs = function logs() {
3382
+ if (!response.messages) {
3383
+ return;
3384
  }
3385
 
3386
+ var $logsContainer = $container.find('.wpstg--modal--process--logs');
3387
+ var stoppingTypes = [that.backups.messages.ERROR, that.backups.messages.CRITICAL];
 
3388
 
3389
+ var appendMessage = function appendMessage(message) {
3390
+ if (Array.isArray(message)) {
3391
+ for (var _iterator = _createForOfIteratorHelperLoose(message), _step; !(_step = _iterator()).done;) {
3392
+ var item = _step.value;
3393
+ appendMessage(item);
3394
+ }
3395
 
3396
+ return;
3397
+ }
 
3398
 
3399
+ var msgClass = "wpstg--modal--process--msg--" + message.type.toLowerCase();
3400
+ $logsContainer.append("<p class=\"" + msgClass + "\">[" + message.type + "] - [" + message.date + "] - " + message.message + "</p>");
 
 
 
 
3401
 
3402
+ if (stoppingTypes.includes(message.type.toLowerCase())) {
3403
+ that.backups.cancel();
3404
+ setTimeout(that.backups.logsModal, 500);
3405
+ }
3406
+ };
3407
 
3408
+ for (var _iterator2 = _createForOfIteratorHelperLoose(response.messages), _step2; !(_step2 = _iterator2()).done;) {
3409
+ var message = _step2.value;
3410
+
3411
+ if (!message) {
3412
+ continue;
3413
+ }
3414
+
3415
+ that.backups.messages.addMessage(message);
3416
+ appendMessage(message);
3417
+ }
3418
+
3419
+ if ($logsContainer.is(':visible')) {
3420
+ $logsContainer.scrollTop($logsContainer[0].scrollHeight);
3421
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3422
 
3423
  if (!that.backups.messages.shouldWarn()) {
3424
+ return;
3425
  }
3426
 
3427
+ var $btnShowLogs = $container.find('.wpstg--modal--process--logs--tail');
3428
+ $btnShowLogs.html($btnShowLogs.attr('data-txt-bad'));
3429
+ $btnShowLogs.find('.wpstg--modal--logs--critical-count').text(that.backups.messages.countByType(that.backups.messages.CRITICAL));
3430
+ $btnShowLogs.find('.wpstg--modal--logs--error-count').text(that.backups.messages.countByType(that.backups.messages.ERROR));
3431
+ $btnShowLogs.find('.wpstg--modal--logs--warning-count').text(that.backups.messages.countByType(that.backups.messages.WARNING));
3432
+ };
3433
 
3434
+ title();
3435
+ percentage();
3436
+ logs();
3437
 
3438
+ if (response.status === true && response.job_done === true) {
3439
+ that.backups.timer.stop();
3440
+ that.backups.isCancelled = true;
 
 
 
3441
  }
3442
+ },
3443
+ requestData: function requestData(notation, data) {
3444
+ var obj = {};
3445
+ var keys = notation.split('.');
3446
+ var lastIndex = keys.length - 1;
3447
+ keys.reduce(function (accumulated, current, index) {
3448
+ return accumulated[current] = index >= lastIndex ? data : {};
3449
+ }, obj);
3450
+ return obj;
3451
+ },
3452
+ logsModal: function logsModal() {
3453
+ Swal.fire({
3454
+ html: "<div class=\"wpstg--modal--error--logs\" style=\"display:block\"></div><div class=\"wpstg--modal--process--logs\" style=\"display:block\"></div>",
3455
+ width: '95%',
 
 
 
 
 
 
 
 
 
 
 
 
 
3456
  onRender: function onRender() {
3457
+ var $container = $(Swal.getContainer());
3458
+ $container[0].style['z-index'] = 9999;
3459
+ var $logsContainer = $container.find('.wpstg--modal--process--logs');
3460
+ var $errorContainer = $container.find('.wpstg--modal--error--logs');
3461
+ var $translations = $('#wpstg--js--translations');
3462
+ var messages = that.backups.messages;
3463
+ var title = $translations.attr('data-modal-logs-title').replace('{critical}', messages.countByType(messages.CRITICAL)).replace('{errors}', messages.countByType(messages.ERROR)).replace('{warnings}', messages.countByType(messages.WARNING));
3464
+ $errorContainer.before("<h3>" + title + "</h3>");
3465
+ var warnings = [that.backups.messages.CRITICAL, that.backups.messages.ERROR, that.backups.messages.WARNING];
3466
+
3467
+ if (!that.backups.messages.shouldWarn()) {
3468
+ $errorContainer.hide();
3469
+ }
3470
+
3471
+ for (var _iterator3 = _createForOfIteratorHelperLoose(messages.data.all), _step3; !(_step3 = _iterator3()).done;) {
3472
+ var message = _step3.value;
3473
+ var msgClass = "wpstg--modal--process--msg--" + message.type.toLowerCase(); // TODO RPoC
3474
+
3475
+ if (warnings.includes(message.type)) {
3476
+ $errorContainer.append("<p class=\"" + msgClass + "\">[" + message.type + "] - [" + message.date + "] - " + message.message + "</p>");
3477
  }
3478
 
3479
+ $logsContainer.append("<p class=\"" + msgClass + "\">[" + message.type + "] - [" + message.date + "] - " + message.message + "</p>");
3480
+ }
3481
+ },
3482
+ onOpen: function onOpen(container) {
3483
+ var $logsContainer = $(container).find('.wpstg--modal--process--logs');
3484
+ $logsContainer.scrollTop($logsContainer[0].scrollHeight);
 
 
3485
  }
3486
  });
3487
+ },
3488
+ downloadModal: function downloadModal(_ref3) {
3489
+ var _ref3$title = _ref3.title,
3490
+ title = _ref3$title === void 0 ? null : _ref3$title,
3491
+ _ref3$titleExport = _ref3.titleExport,
3492
+ titleExport = _ref3$titleExport === void 0 ? null : _ref3$titleExport,
3493
+ _ref3$id = _ref3.id,
3494
+ id = _ref3$id === void 0 ? null : _ref3$id,
3495
+ _ref3$url = _ref3.url,
3496
+ url = _ref3$url === void 0 ? null : _ref3$url,
3497
+ _ref3$btnTxtCancel = _ref3.btnTxtCancel,
3498
+ btnTxtCancel = _ref3$btnTxtCancel === void 0 ? 'Cancel' : _ref3$btnTxtCancel,
3499
+ _ref3$btnTxtConfirm = _ref3.btnTxtConfirm,
3500
+ btnTxtConfirm = _ref3$btnTxtConfirm === void 0 ? 'Download' : _ref3$btnTxtConfirm;
3501
+
3502
+ if (null === that.backups.modal.download.html) {
3503
+ var $el = $('#wpstg--modal--backup--download');
3504
+ that.backups.modal.download.html = $el.html();
3505
+ $el.remove();
 
 
 
 
 
3506
  }
3507
 
3508
+ var exportModal = function exportModal() {
3509
+ return Swal.fire({
3510
+ html: "<h2>" + titleExport + "</h2><span class=\"wpstg-loader\"></span>",
3511
+ showCancelButton: false,
3512
+ showConfirmButton: false,
3513
+ onRender: function onRender() {
3514
+ that.ajax({
3515
+ action: 'wpstg--backups--export',
3516
+ accessToken: wpstg.accessToken,
3517
+ nonce: wpstg.nonce,
3518
+ id: id
3519
+ }, function (response) {
3520
+ if (!response || !response.success || !response.data || response.data.length < 1) {
3521
+ return;
3522
+ }
3523
+
3524
+ var a = document.createElement('a');
3525
+ a.style.display = 'none';
3526
+ a.href = response.data;
3527
+ document.body.appendChild(a);
3528
+ a.click();
3529
+ document.body.removeChild(a);
3530
+ Swal.close();
3531
+ });
3532
+ }
3533
+ });
3534
+ };
3535
 
3536
+ Swal.mixin({
3537
+ customClass: {
3538
+ cancelButton: 'wpstg--btn--cancel wpstg-blue-primary wpstg-link-btn',
3539
+ confirmButton: 'wpstg--btn--confirm wpstg-blue-primary wpstg-button wpstg-link-btn',
3540
+ actions: 'wpstg--modal--actions'
3541
+ },
3542
+ buttonsStyling: false
3543
+ }).fire({
3544
+ icon: 'success',
3545
+ html: that.backups.modal.download.html.replace('{title}', title).replace('{btnTxtLog}', 'Show Logs'),
3546
+ cancelButtonText: btnTxtCancel,
3547
+ confirmButtonText: btnTxtConfirm,
3548
+ showCancelButton: true,
3549
+ showConfirmButton: true
3550
+ }).then(function (isConfirm) {
3551
+ if (!isConfirm || !isConfirm.value) {
3552
+ return;
3553
+ }
3554
 
3555
+ if (url && url.length > 0) {
3556
+ window.location.href = url;
3557
+ return;
3558
+ }
3559
 
3560
+ exportModal();
3561
+ });
3562
+ },
3563
+ importModal: function importModal() {
3564
+ var importSiteBackup = function importSiteBackup(data) {
3565
+ resetErrors();
3566
 
3567
+ if (that.backups.isCancelled) {
3568
+ // Swal.close();
3569
  return;
3570
  }
3571
 
3572
+ that.backups.timer.start();
3573
+
3574
+ var statusStop = function statusStop() {
3575
+ clearInterval(that.backups.processInfo.interval);
3576
+ that.backups.processInfo.interval = null;
3577
+ };
3578
 
3579
+ var status = function status() {
3580
+ if (that.backups.processInfo.interval !== null) {
3581
  return;
3582
  }
3583
 
3584
+ that.backups.processInfo.interval = setInterval(function () {
3585
+ if (true === that.backups.isCancelled) {
 
 
 
 
 
3586
  statusStop();
3587
+ return;
3588
  }
3589
 
3590
+ if (that.backups.status.hasResponse === false) {
3591
  return;
3592
  }
3593
 
3594
+ that.backups.status.hasResponse = false;
3595
+ fetch(ajaxurl + "?action=wpstg--backups--status&process=restore&accessToken=" + wpstg.accessToken + "&nonce=" + wpstg.nonce).then(function (res) {
3596
+ return res.json();
3597
+ }).then(function (res) {
3598
+ that.backups.status.hasResponse = true;
 
 
 
 
 
3599
 
3600
+ if (typeof res === 'undefined') {
3601
+ statusStop();
3602
+ }
 
 
 
 
 
 
 
 
3603
 
3604
+ if (that.backups.processInfo.title === res.currentStatusTitle) {
3605
+ return;
3606
+ }
3607
+
3608
+ that.backups.processInfo.title = res.currentStatusTitle;
3609
+ var $container = $(Swal.getContainer());
3610
+ $container.find('.wpstg--modal--process--title').text(res.currentStatusTitle);
3611
+ $container.find('.wpstg--modal--process--percent').text('0');
3612
+ })["catch"](function (e) {
3613
+ that.backups.status.hasResponse = true;
3614
+ showAjaxFatalError(e, '', 'Submit an error report.');
3615
+ });
3616
+ }, 5000);
3617
+ };
3618
 
3619
+ WPStaging.ajax({
3620
+ action: 'wpstg--backups--import',
3621
+ accessToken: wpstg.accessToken,
3622
+ nonce: wpstg.nonce
3623
+ }, function (response) {
3624
+ if (typeof response === 'undefined') {
3625
+ setTimeout(function () {
3626
+ importSiteBackup();
3627
+ }, wpstg.delayReq);
3628
+ return;
3629
+ }
3630
 
3631
+ that.backups.processResponse(response, true);
 
 
 
 
3632
 
3633
+ if (!that.backups.processInfo.interval) {
3634
+ status();
 
 
 
3635
  }
3636
 
3637
+ if (response.status === false) {
3638
+ importSiteBackup();
3639
+ } else if (response.status === true) {
3640
+ $('#wpstg--progress--status').text('Backup successfully imported!');
3641
+ that.backups.type = null;
 
 
3642
 
3643
+ if (that.backups.messages.shouldWarn()) {
3644
+ // noinspection JSIgnoredPromiseFromCall
3645
+ that.backups.fetchListing();
3646
+ that.backups.logsModal();
3647
+ return;
3648
+ }
3649
 
3650
+ statusStop();
3651
+ var logEntries = $('.wpstg--modal--process--logs').get(1).innerHTML;
3652
+ var html = '<div class="wpstg--modal--process--logs">' + logEntries + '</div>';
3653
+ var issueFound = html.includes('wpstg--modal--process--msg--warning') || html.includes('wpstg--modal--process--msg--error') ? 'Issues(s) found! ' : ''; // var errorMessage = html.includes('wpstg--modal--process--msg--error') ? 'Errors(s) found! ' : '';
3654
+ // var Message = warningMessage + errorMessage;
3655
+ // Swal.close();
3656
+
3657
+ Swal.fire({
3658
+ icon: 'success',
3659
+ title: 'Finished',
3660
+ html: 'System imported from backup. <br/><span class="wpstg--modal--process--msg-found">' + issueFound + '</span><button class="wpstg--modal--process--logs--tail" data-txt-bad="">Show Logs</button><br/>' + html
3661
+ }); // noinspection JSIgnoredPromiseFromCall
3662
 
3663
+ that.backups.fetchListing();
3664
+ } else {
3665
+ setTimeout(function () {
3666
+ importSiteBackup();
3667
+ }, wpstg.delayReq);
3668
+ }
3669
+ }, 'json', false, 0, // Don't retry upon failure
3670
+ 1.25);
3671
+ };
3672
+
3673
+ if (!that.backups.modal["import"].html) {
3674
+ var $modal = $('#wpstg--modal--backup--import'); // Search & Replace Form
3675
+
3676
+ var $form = $modal.find('.wpstg--modal--backup--import--search-replace--input--container');
3677
+ that.backups.modal["import"].searchReplaceForm = $form.html();
3678
+ $form.find('.wpstg--modal--backup--import--search-replace--input-group').remove();
3679
+ $form.html(that.backups.modal["import"].searchReplaceForm.replace(/{i}/g, 0));
3680
+ that.backups.modal["import"].html = $modal.html();
3681
+ that.backups.modal["import"].baseDirectory = $modal.attr('data-baseDirectory');
3682
+ that.backups.modal["import"].btnTxtNext = $modal.attr('data-nextButtonText');
3683
+ that.backups.modal["import"].btnTxtConfirm = $modal.attr('data-confirmButtonText');
3684
+ that.backups.modal["import"].btnTxtCancel = $modal.attr('data-cancelButtonText');
3685
+ $modal.remove();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3686
  }
3687
 
3688
+ that.backups.modal["import"].data.search = [];
3689
+ that.backups.modal["import"].data.replace = [];
3690
+ Swal.mixin({
3691
+ customClass: {
3692
+ confirmButton: 'wpstg--btn--confirm wpstg-blue-primary wpstg-button wpstg-link-btn',
3693
+ cancelButton: 'wpstg--btn--cancel wpstg-blue-primary wpstg-link-btn',
3694
+ actions: 'wpstg--modal--actions'
3695
+ },
3696
+ buttonsStyling: false // progressSteps: ['1', '2']
3697
+
3698
+ }).queue([{
3699
+ html: that.backups.modal["import"].html,
3700
+ confirmButtonText: that.backups.modal["import"].btnTxtNext,
3701
+ showCancelButton: false,
3702
+ showConfirmButton: true,
3703
+ showLoaderOnConfirm: true,
3704
+ width: 650,
3705
+ onRender: function onRender() {
3706
+ // $('.wpstg--modal--actions .swal2-confirm').hide();
3707
+ // todo: hide this again
3708
+ $('.wpstg--modal--actions .swal2-confirm').show();
3709
+ $('.wpstg--modal--actions .swal2-confirm').prop('disabled', false);
3710
+ that.backups.modal["import"].containerUpload = $('.wpstg--modal--backup--import--upload');
3711
+ that.backups.modal["import"].containerFilesystem = $('.wpstg--modal--backup--import--filesystem');
3712
+ that.backups.modal["import"].containerConfigure = $('.wpstg--modal--backup--import--configure');
3713
+ },
3714
+ preConfirm: function preConfirm() {
3715
+ var body = new FormData();
3716
+ body.append('accessToken', wpstg.accessToken);
3717
+ body.append('nonce', wpstg.nonce);
3718
+ body.append('filePath', that.backups.modal["import"].data.file);
3719
+ that.backups.modal["import"].data.search.forEach(function (item, index) {
3720
+ body.append("search[" + index + "]", item);
3721
  });
3722
+ that.backups.modal["import"].data.replace.forEach(function (item, index) {
3723
+ body.append("replace[" + index + "]", item);
3724
+ });
3725
+ return fetch(ajaxurl + "?action=wpstg--backups--import--file-info", {
3726
+ method: 'POST',
3727
+ body: body
3728
+ }).then(handleFetchErrors).then(function (res) {
3729
+ return res.json();
3730
+ }).then(function (html) {
3731
+ return Swal.insertQueueStep({
3732
+ html: html,
3733
+ confirmButtonText: that.backups.modal["import"].btnTxtConfirm,
3734
+ cancelButtonText: that.backups.modal["import"].btnTxtCancel,
3735
+ showCancelButton: true
3736
+ });
3737
+ })["catch"](function (e) {
3738
+ return showAjaxFatalError(e, '', 'Submit an error report.');
3739
+ });
3740
+ }
3741
+ }]).then(function (res) {
3742
+ if (!res || !res.value || !res.value[1] || res.value[1] !== true) {
3743
+ return;
3744
  }
3745
+
3746
+ that.backups.isCancelled = false;
3747
+ var data = that.backups.modal["import"].data;
3748
+ data['file'] = that.backups.modal["import"].baseDirectory + data['file'];
3749
+ WPStaging.ajax({
3750
+ action: 'wpstg--backups--prepare-import',
3751
+ accessToken: wpstg.accessToken,
3752
+ nonce: wpstg.nonce,
3753
+ wpstgImportData: data
3754
+ }, function (response) {
3755
+ if (response.success) {
3756
+ that.backups.process({
3757
+ execute: function execute() {
3758
+ that.backups.messages.reset();
3759
+ importSiteBackup();
3760
+ }
3761
+ });
3762
+ } else {
3763
+ showAjaxFatalError(response.data, '', 'Submit an error report.');
3764
+ }
3765
+ }, 'json', false, 0, 1.25);
3766
+ });
3767
+ }
3768
+ };
3769
+ window.addEventListener('backupListingFinished', function () {
3770
+ fetch(ajaxurl + "?action=wpstg--backups--import--file-list&_=" + Math.random() + "&accessToken=" + wpstg.accessToken + "&nonce=" + wpstg.nonce + "&withTemplate=true").then(handleFetchErrors).then(function (res) {
3771
+ return res.json();
3772
+ }).then(function (res) {
3773
+ var $ul = $('.wpstg-backup-list ul');
3774
+ $ul.empty();
3775
+ $ul.html(res);
3776
+ })["catch"](function (e) {
3777
+ return showAjaxFatalError(e, '', 'Submit an error report.');
3778
  });
 
 
 
 
 
 
 
 
 
 
 
3779
  });
3780
+ return that;
3781
+ }(jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3782
 
3783
+ jQuery(document).ready(function () {
3784
+ WPStaging.init(); // This is necessary to make WPStaging var accessibile in WP Staging PRO js script
3785
+
3786
+ window.WPStaging = WPStaging;
3787
  });
3788
+ /**
3789
+ * Report Issue modal
3790
+ */
3791
 
3792
+ jQuery(document).ready(function ($) {
3793
+ $('#wpstg-report-issue-button').on('click', function (e) {
3794
+ $('.wpstg-report-issue-form').toggleClass('wpstg-report-show');
3795
+ e.preventDefault();
3796
+ });
3797
+ $('body').on('click', '#wpstg-backups-report-issue-button', function (e) {
3798
+ $('.wpstg-report-issue-form').toggleClass('wpstg-report-show');
3799
+ e.preventDefault();
3800
+ });
3801
+ $('#wpstg-report-cancel').on('click', function (e) {
3802
+ $('.wpstg-report-issue-form').removeClass('wpstg-report-show');
3803
+ e.preventDefault();
3804
+ });
3805
+ /*
3806
+ * Close Success Modal
3807
+ */
3808
 
3809
+ $('body').on('click', '#wpstg-success-button', function (e) {
3810
+ e.preventDefault();
3811
+ $('.wpstg-report-issue-form').removeClass('wpstg-report-show');
3812
+ });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3813
 
3814
+ function sendIssueReport(button, forceSend) {
3815
+ if (forceSend === void 0) {
3816
+ forceSend = 'false';
3817
  }
 
 
3818
 
3819
+ var spinner = button.next();
3820
+ var email = $('.wpstg-report-email').val();
3821
+ var hosting_provider = $('.wpstg-report-hosting-provider').val();
3822
+ var message = $('.wpstg-report-description').val();
3823
+ var syslog = $('.wpstg-report-syslog').is(':checked');
3824
+ var terms = $('.wpstg-report-terms').is(':checked');
3825
+ button.attr('disabled', true);
3826
+ spinner.css('visibility', 'visible');
3827
+ $.ajax({
3828
+ url: ajaxurl,
3829
+ type: 'POST',
3830
+ dataType: 'json',
3831
+ async: true,
3832
+ data: {
3833
+ 'action': 'wpstg_send_report',
3834
+ 'accessToken': wpstg.accessToken,
3835
+ 'nonce': wpstg.nonce,
3836
+ 'wpstg_email': email,
3837
+ 'wpstg_provider': hosting_provider,
3838
+ 'wpstg_message': message,
3839
+ 'wpstg_syslog': +syslog,
3840
+ 'wpstg_terms': +terms,
3841
+ 'wpstg_force_send': forceSend
3842
+ }
3843
+ }).done(function (data) {
3844
+ button.attr('disabled', false);
3845
+ spinner.css('visibility', 'hidden');
3846
+
3847
+ if (data.errors.length > 0) {
3848
+ $('.wpstg-report-issue-form .wpstg-message').remove();
3849
+ var errorMessage = $('<div />').addClass('wpstg-message wpstg-error-message');
3850
+ $.each(data.errors, function (key, value) {
3851
+ if (value.status === 'already_submitted') {
3852
+ errorMessage = '';
3853
+ Swal.fire({
3854
+ title: '',
3855
+ customClass: {
3856
+ container: 'wpstg-issue-resubmit-confirmation'
3857
+ },
3858
+ icon: 'warning',
3859
+ html: value.message,
3860
+ showCloseButton: true,
3861
+ showCancelButton: true,
3862
+ focusConfirm: false,
3863
+ confirmButtonText: 'Yes',
3864
+ cancelButtonText: 'No'
3865
+ }).then(function (result) {
3866
+ if (result.isConfirmed) {
3867
+ sendIssueReport(button, 'true');
3868
+ }
3869
+ });
3870
+ } else {
3871
+ errorMessage.append('<p>' + value + '</p>');
3872
+ }
3873
+ });
3874
+ $('.wpstg-report-issue-form').prepend(errorMessage);
3875
+ } else {
3876
+ var successMessage = $('<div />').addClass('wpstg-message wpstg-success-message');
3877
+ successMessage.append('<p>Thanks for submitting your request! You should receive an auto reply mail with your ticket ID immediately for confirmation!<br><br>If you do not get that mail please contact us directly at <strong>support@wp-staging.com</strong></p>');
3878
+ $('.wpstg-report-issue-form').html(successMessage);
3879
+ $('.wpstg-success-message').append('<div style="float:right;margin-top:10px;"><a id="wpstg-success-button" href="#">Close</a></div>'); // Hide message
3880
+
3881
+ setTimeout(function () {
3882
+ $('.wpstg-report-issue-form').removeClass('wpstg-report-active');
3883
+ }, 2000);
3884
+ }
3885
+ });
3886
+ }
3887
+
3888
+ $('#wpstg-report-submit').on('click', function (e) {
3889
+ var self = $(this);
3890
+ sendIssueReport(self, 'false');
3891
+ e.preventDefault();
3892
+ }); // Open/close actions drop down menu
3893
 
3894
+ $(document).on('click', '.wpstg-dropdown>.wpstg-dropdown-toggler', function (e) {
3895
+ e.preventDefault();
3896
+ $(e.target).next('.wpstg-dropdown-menu').toggleClass('shown');
3897
+ }); // Close action drop down menu if clicked anywhere outside
3898
 
3899
+ document.addEventListener('click', function (event) {
3900
+ var isClickInside = event.target.closest('.wpstg-dropdown-toggler');
3901
 
3902
+ if (!isClickInside) {
3903
+ var dropDown = document.getElementsByClassName('wpstg-dropdown-menu');
3904
 
3905
+ for (var i = 0; i < dropDown.length; i++) {
3906
+ dropDown[i].classList.remove('shown');
3907
+ }
3908
  }
3909
+ });
3910
  });
3911
+
3912
+ }());
3913
+ //# sourceMappingURL=wpstg-admin.js.map
assets/js/dist/wpstg-admin.js.map ADDED
@@ -0,0 +1 @@
 
1
+ {"version":3,"file":"wpstg-admin.js","sources":["../src/modules/wpstg-dom-utils.js","../src/modules/wpstg-clone-staging.js","../src/modules/wpstg-directory-navigation.js","../src/modules/wpstg-exclude-filters.js","../src/modules/wpstg-modal.js","../src/modules/wpstg-reset-modal.js","../src/wpstg-admin.js"],"sourcesContent":["/**\n * WP Staging basic jQuery replacement\n */\n\n/**\n * Shortcut for document.querySelector() or jQuery's $()\n * Return single element only\n */\nexport function qs(selector) {\n return document.querySelector(selector);\n}\n\n/**\n * Shortcut for document.querySelector() or jQuery's $()\n * Return collection of elements\n */\nexport function all(selector) {\n return document.querySelectorAll(selector);\n}\n\n/**\n * alternative of jQuery - $(parent).on(event, selector, handler)\n */\nexport function addEvent(parent, evt, selector, handler) {\n parent.addEventListener(evt, function(event) {\n if (event.target.matches(selector + ', ' + selector + ' *')) {\n handler(event.target.closest(selector), event);\n }\n }, false);\n}\n\nexport function slideDown(element, duration = 400) {\n element.style.display = 'block';\n element.style.overflow = 'hidden';\n const height = element.offsetHeight;\n element.style.height = '0px';\n element.style.transitionProperty = 'height';\n element.style.transitionDuration = duration + 'ms';\n setTimeout(() => {\n element.style.height = height + 'px';\n window.setTimeout(() => {\n element.style.removeProperty('height');\n element.style.removeProperty('overflow');\n element.style.removeProperty('transition-duration');\n element.style.removeProperty('transition-property');\n }, duration);\n }, 0);\n}\n\nexport function slideUp(element, duration = 400) {\n element.style.display = 'block';\n element.style.overflow = 'hidden';\n const height = element.offsetHeight;\n element.style.height = height + 'px';\n element.style.transitionProperty = 'height';\n element.style.transitionDuration = duration + 'ms';\n setTimeout(() => {\n element.style.height = '0px';\n window.setTimeout(() => {\n element.style.display = 'none';\n element.style.removeProperty('height');\n element.style.removeProperty('overflow');\n element.style.removeProperty('transition-duration');\n element.style.removeProperty('transition-property');\n }, duration);\n }, 0);\n}\n\nexport function getNextSibling(element, selector) {\n let sibling = element.nextElementSibling;\n\n while (sibling) {\n if (sibling.matches(selector)) {\n return sibling;\n }\n\n sibling = sibling.nextElementSibling;\n }\n};\n\nexport function getParents(element, selector) {\n const result = [];\n for (let parent = element && element.parentElement; parent; parent = parent.parentElement) {\n if (parent.matches(selector)) {\n result.push(parent);\n }\n }\n\n return result;\n}\n","import * as dom from './wpstg-dom-utils.js';\n\n/**\n * Enable/Disable cloning for staging site\n */\nexport default class WpstgCloneStaging {\n constructor(\n pageWrapperId = '#wpstg-clonepage-wrapper',\n wpstgObject = wpstg,\n ) {\n this.pageWrapper = dom.qs(pageWrapperId);\n this.wpstgObject = wpstgObject;\n this.enableButtonId = '#wpstg-enable-staging-cloning';\n this.enableAction = 'wpstg_enable_staging_cloning';\n\n this.notyf = new Notyf({\n duration: 10000,\n position: {\n x: 'center',\n y: 'bottom',\n },\n dismissible: true,\n types: [\n {\n type: 'warning',\n background: 'orange',\n icon: false,\n },\n ],\n });\n this.init();\n }\n\n addEvents() {\n if (this.pageWrapper === null) {\n return;\n }\n\n dom.addEvent(this.pageWrapper, 'click', this.enableButtonId, () => {\n this.sendRequest(this.enableAction);\n });\n }\n\n init() {\n this.addEvents();\n }\n\n sendRequest(action) {\n fetch(this.wpstgObject.ajaxUrl, {\n method: 'POST',\n credentials: 'same-origin',\n body: new URLSearchParams({\n action: action,\n accessToken: this.wpstgObject.accessToken,\n nonce: this.wpstgObject.nonce,\n }),\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n }).then((response) => {\n if (response.ok) {\n return response.json();\n }\n\n return Promise.reject(response);\n }).then((data) => {\n // Reload current page if successful.\n if ('undefined' !== typeof (data.success) && data.success) {\n location.reload();\n return;\n }\n\n // There will be message probably in case of error\n if ('undefined' !== typeof (data.message)) {\n this.notyf.error(data.message);\n return;\n }\n\n this.notyf.error(this.wpstgObject.i18n['somethingWentWrong']);\n }).catch((error) => {\n console.warn(this.wpstgObject.i18n['somethingWentWrong'], error);\n });\n }\n}\n","import * as dom from './wpstg-dom-utils.js';\n\n/**\n * Fetch directory direct child directories\n */\nexport default class WpstgDirectoryNavigation {\n constructor(\n directoryListingSelector = '#wpstg-directories-listing',\n wpstgObject = wpstg,\n notyf = null,\n ) {\n this.directoryListingContainer = dom.qs(directoryListingSelector);\n this.wpstgObject = wpstgObject;\n this.dirCheckboxSelector = '.wpstg-check-dir';\n this.dirExpandSelector = '.wpstg-expand-dirs';\n this.unselectAllDirsSelector = '.wpstg-unselect-dirs';\n this.selectDefaultDirsSelector = '.wpstg-select-dirs-default';\n this.fetchChildrenAction = 'wpstg_fetch_dir_childrens';\n this.currentCheckboxElement = null;\n this.currentParentDiv = null;\n this.currentLoader = null;\n this.existingExcludes = [];\n this.excludedDirectories = [];\n this.isDefaultSelected = false;\n this.notyf = notyf;\n\n this.init();\n }\n\n addEvents() {\n if (this.directoryListingContainer === null) {\n console.log('Error: directory navigation add events');\n return;\n }\n\n dom.addEvent(this.directoryListingContainer, 'click', this.dirExpandSelector, (element, event) => {\n event.preventDefault();\n if (this.toggleDirExpand(element)) {\n this.sendRequest(this.fetchChildrenAction, element);\n }\n });\n\n dom.addEvent(this.directoryListingContainer, 'click', this.unselectAllDirsSelector, () => {\n this.unselectAll();\n });\n\n dom.addEvent(this.directoryListingContainer, 'click', this.selectDefaultDirsSelector, () => {\n this.selectDefault();\n });\n }\n\n init() {\n this.addEvents();\n this.parseExcludes();\n }\n\n /**\n * Toggle Dir Expand,\n * Return true if children aren't fetched\n * @param {HTMLElement} element\n * @return {boolean}\n */\n toggleDirExpand(element) {\n this.currentParentDiv = element.parentElement;\n this.currentCheckboxElement = element.previousSibling;\n this.currentLoader = this.currentParentDiv.querySelector('.wpstg-is-dir-loading');\n if (this.currentCheckboxElement.getAttribute('data-navigateable', 'false') === 'false') {\n return false;\n }\n\n if (this.currentCheckboxElement.getAttribute('data-scanned', 'false') === 'false') {\n return true;\n }\n\n return false;\n }\n\n sendRequest(action) {\n if (this.currentLoader !== null) {\n this.currentLoader.style.display = 'inline-block';\n }\n\n fetch(this.wpstgObject.ajaxUrl, {\n method: 'POST',\n credentials: 'same-origin',\n body: new URLSearchParams({\n action: action,\n accessToken: this.wpstgObject.accessToken,\n nonce: this.wpstgObject.nonce,\n dirPath: this.currentCheckboxElement.value,\n isChecked: this.currentCheckboxElement.checked,\n forceDefault: this.isDefaultSelected,\n }),\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n }).then((response) => {\n if (response.ok) {\n return response.json();\n }\n\n return Promise.reject(response);\n }).then((data) => {\n if ('undefined' !== typeof (data.success) && data.success) {\n this.currentCheckboxElement.setAttribute('data-scanned', true);\n const dirContainer = document.createElement('div');\n dirContainer.classList.add('wpstg-dir');\n dirContainer.classList.add('wpstg-subdir');\n dirContainer.innerHTML = JSON.parse(data.directoryListing);\n this.currentParentDiv.appendChild(dirContainer);\n if (this.currentLoader !== null) {\n this.currentLoader.style.display = 'none';\n }\n\n dom.slideDown(dirContainer);\n\n return;\n }\n\n if (this.notyf !== null) {\n this.notyf.error(this.wpstgObject.i18n['somethingWentWrong']);\n } else {\n alert('Error: ' + this.wpstgObject.i18n['somethingWentWrong']);\n }\n }).catch((error) => {\n console.warn(this.wpstgObject.i18n['somethingWentWrong'], error);\n });\n }\n\n getExcludedDirectories() {\n this.excludedDirectories = [];\n this.directoryListingContainer.querySelectorAll('.wpstg-dir input:not(:checked)').forEach((element) => {\n if (!this.isParentExcluded(element.value)) {\n this.excludedDirectories.push(element.value);\n }\n });\n\n this.existingExcludes.forEach((exclude) => {\n if (!this.isParentExcluded(exclude) && !this.isExcludeScanned(exclude)) {\n this.excludedDirectories.push(exclude);\n }\n });\n\n return this.excludedDirectories.join(this.wpstgObject.settings.directorySeparator);\n }\n\n /**\n * @param {string} path\n * @return {bool}\n */\n isParentExcluded(path) {\n let isParentAlreadyExcluded = false;\n this.excludedDirectories.forEach((dir) => {\n if (path.startsWith(dir + '/')) {\n isParentAlreadyExcluded = true;\n }\n });\n\n return isParentAlreadyExcluded;\n }\n\n getExtraDirectoriesRootOnly() {\n this.getExcludedDirectories();\n const extraDirectories = [];\n this.directoryListingContainer.querySelectorAll(':not(.wpstg-subdir)>.wpstg-dir>input.wpstg-wp-non-core-dir:checked').forEach((element) => {\n extraDirectories.push(element.value);\n });\n\n // Check if extra directories text area exists\n // TODO: remove extraCustomDirectories code if no one require extraCustomDirectories...\n const extraDirectoriesTextArea = dom.qs('#wpstg_extraDirectories');\n if (extraDirectoriesTextArea === null || extraDirectoriesTextArea.value === '') {\n return extraDirectories.join(this.wpstgObject.settings.directorySeparator);\n }\n\n const extraCustomDirectories = extraDirectoriesTextArea.value.split(/\\r?\\n/);\n\n return extraDirectories.concat(extraCustomDirectories).join(this.wpstgObject.settings.directorySeparator);\n }\n\n unselectAll() {\n this.directoryListingContainer.querySelectorAll('.wpstg-dir input').forEach((element) => {\n element.checked = false;\n });\n }\n\n selectDefault() {\n // unselect all checkboxes\n this.unselectAll();\n\n // only select those checkboxes whose class is wpstg-wp-core-dir\n this.directoryListingContainer.querySelectorAll('.wpstg-dir input.wpstg-wp-core-dir').forEach((element) => {\n element.checked = true;\n });\n\n // then unselect those checkboxes whose parent has wpstg extra checkbox\n this.directoryListingContainer.querySelectorAll('.wpstg-dir > .wpstg-wp-non-core-dir').forEach((element) => {\n element.parentElement.querySelectorAll('input.wpstg-wp-core-dir').forEach((element) => {\n element.checked = false;\n });\n });\n\n this.isDefaultSelected = true;\n }\n\n parseExcludes() {\n this.existingExcludes = this.directoryListingContainer.getAttribute('data-existing-excludes', []);\n if (this.existingExcludes === '') {\n this.existingExcludes = [];\n }\n\n if (this.existingExcludes.length !== 0) {\n this.existingExcludes = this.existingExcludes.split(',');\n }\n }\n\n isExcludeScanned(exclude) {\n this.directoryListingContainer.querySelectorAll('.wpstg-dir input').forEach((element) => {\n if (element.value === exclude) {\n return true;\n }\n });\n\n return false;\n }\n}\n","import * as dom from './wpstg-dom-utils.js';\n\n/**\n * Rich Exclude Filter Module\n */\nexport default class WpstgExcludeFilters {\n constructor(\n excludeFilterContainerSelector = '#wpstg-exclude-filters-container',\n wpstgObject = wpstg,\n ) {\n this.excludeContainer = dom.qs(excludeFilterContainerSelector);\n this.excludeTableBody = dom.qs(`${excludeFilterContainerSelector} tbody`);\n this.wpstgObject = wpstgObject;\n this.init();\n }\n\n addEvents() {\n dom.addEvent(this.excludeContainer, 'click', '.wpstg-file-size-rule', () => {\n this.addFileSizeExclude();\n });\n\n dom.addEvent(this.excludeContainer, 'click', '.wpstg-file-ext-rule', () => {\n this.addFileExtExclude();\n });\n\n dom.addEvent(this.excludeContainer, 'click', '.wpstg-file-name-rule', () => {\n this.addFileNameExclude();\n });\n\n dom.addEvent(this.excludeContainer, 'click', '.wpstg-dir-name-rule', () => {\n this.addDirNameExclude();\n });\n\n dom.addEvent(this.excludeContainer, 'click', '.wpstg-clear-all-rules', () => {\n this.clearExcludes();\n });\n\n dom.addEvent(this.excludeContainer, 'click', '.wpstg-remove-exclude-rule', (target) => {\n this.removeExclude(target);\n });\n }\n\n init() {\n if (this.excludeContainer === null) {\n console.log('Error: Given table selector not found!');\n return;\n }\n\n this.addEvents();\n }\n\n addFileSizeExclude() {\n this.addExcludeRuleRow('#wpstg-file-size-exclude-filter-template');\n }\n\n addFileExtExclude() {\n this.addExcludeRuleRow('#wpstg-file-ext-exclude-filter-template');\n }\n\n addFileNameExclude() {\n this.addExcludeRuleRow('#wpstg-file-name-exclude-filter-template');\n }\n\n addDirNameExclude() {\n this.addExcludeRuleRow('#wpstg-dir-name-exclude-filter-template');\n }\n\n addExcludeRuleRow(templateName) {\n const excludeRowTemplate = dom.qs(templateName);\n if (excludeRowTemplate !== null) {\n const clone = excludeRowTemplate.content.cloneNode(true);\n const excludeRow = clone.querySelector('tr');\n\n this.excludeTableBody.appendChild(excludeRow);\n dom.all('.wpstg-has-exclude-rules').forEach((e) => {\n e.style.display = 'inherit';\n });\n }\n }\n\n clearExcludes() {\n this.excludeTableBody.innerHTML = '';\n dom.all('.wpstg-has-exclude-rules').forEach((e) => {\n e.style.display = 'none';\n });\n }\n\n removeExclude(target) {\n if (target.parentElement !== null && target.parentElement.parentElement !== null) {\n this.excludeTableBody.removeChild(target.parentElement.parentElement);\n }\n\n if (this.excludeTableBody.innerHTML.trim() === '') {\n dom.all('.wpstg-has-exclude-rules').forEach((e) => {\n e.style.display = 'none';\n });\n }\n }\n\n /**\n * Converts all the exclude filters arrays into one single string to keep size of post request small\n * @return {string}\n */\n getExcludeFilters() {\n const globExcludes = [];\n const sizeExcludes = [];\n\n const sizeCompares = this.excludeTableBody.querySelectorAll('select[name=\"wpstgFileSizeExcludeRuleCompare[]\"]');\n const sizeSizes = this.excludeTableBody.querySelectorAll('input[name=\"wpstgFileSizeExcludeRuleSize[]\"]');\n const sizeByte = this.excludeTableBody.querySelectorAll('select[name=\"wpstgFileSizeExcludeRuleByte[]\"]');\n for (const [key, sizeInput] of Object.entries(sizeSizes)) {\n if (sizeInput.value !== '') {\n sizeExcludes.push(sizeCompares[key].value + ' ' + sizeInput.value + sizeByte[key].value);\n }\n }\n\n const extensionInputs = this.excludeTableBody.querySelectorAll('input[name=\"wpstgFileExtExcludeRule[]\"]');\n extensionInputs.forEach((x) => {\n const ext = this.cleanStringForGlob(x.value);\n if (ext !== '') {\n globExcludes.push('ext:' + ext.trim());\n }\n });\n\n const fileNamesPos = this.excludeTableBody.querySelectorAll('select[name=\"wpstgFileNameExcludeRulePos[]\"]');\n const fileNames = this.excludeTableBody.querySelectorAll('input[name=\"wpstgFileNameExcludeRulePath[]\"]');\n for (const [key, fileInput] of Object.entries(fileNames)) {\n const fileName = this.cleanStringForGlob(fileInput.value);\n if (fileName !== '') {\n globExcludes.push('file:' + fileNamesPos[key].value + ' ' + fileName.trim());\n }\n }\n\n const dirNamesPos = this.excludeTableBody.querySelectorAll('select[name=\"wpstgDirNameExcludeRulePos[]\"]');\n const dirNames = this.excludeTableBody.querySelectorAll('input[name=\"wpstgDirNameExcludeRulePath[]\"]');\n for (const [key, dirInput] of Object.entries(dirNames)) {\n const dirName = this.cleanStringForGlob(dirInput.value);\n if (dirName !== '') {\n globExcludes.push('dir:' + dirNamesPos[key].value + ' ' + dirName.trim());\n }\n }\n\n return {\n 'sizes': sizeExcludes.filter(this.onlyUnique).join(','),\n // return set of unique rules\n 'globs': globExcludes.filter(this.onlyUnique).join(','),\n };\n }\n\n onlyUnique(value, index, self) {\n return self.indexOf(value) === index;\n }\n\n /**\n * Remove most of the comment glob characters from the string\n * @param {String} value\n * @return {String}\n */\n cleanStringForGlob(value) {\n // will replace character like * ^ / \\ ! ? [ from the string\n return value.replace(/[*^//!\\.[?]/g, '');\n }\n}\n","/**\n * Basic WP Staging Modal implemented with help of Sweetalerts\n */\nexport default class WpstgModal {\n constructor(\n confirmAction,\n wpstgObject = wpstg,\n ) {\n this.confirmAction = confirmAction;\n this.wpstgObject = wpstgObject;\n }\n\n show(swalOptions, additionalParams = {}, callback = null) {\n Swal.fire(swalOptions).then((result) => {\n if (result.value && this.error !== null) {\n this.triggerConfirmAction(additionalParams, callback);\n }\n });\n }\n\n triggerConfirmAction(additionalParams = {}, callback = null) {\n fetch(this.wpstgObject.ajaxUrl, {\n method: 'POST',\n credentials: 'same-origin',\n body: new URLSearchParams(Object.assign({\n action: this.confirmAction,\n accessToken: this.wpstgObject.accessToken,\n nonce: this.wpstgObject.nonce,\n }, additionalParams)),\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n }).then((response) => {\n if (response.ok) {\n return response.json();\n }\n\n return Promise.reject(response);\n }).then((response) => {\n if (callback !== null) {\n callback(response);\n }\n }).catch((error) => {\n console.log(this.wpstgObject.i18n['somethingWentWrong'], error);\n });\n }\n}\n","\nimport * as dom from './wpstg-dom-utils.js';\nimport WpstgDirectoryNavigation from './wpstg-directory-navigation.js';\nimport WpstgExcludeFilters from './wpstg-exclude-filters.js';\nimport WpstgModal from './wpstg-modal.js';\n\n/**\n * Manage RESET MODAL\n */\nexport default class WpstgResetModal {\n constructor(\n cloneID,\n workflowSelector = '#wpstg-workflow',\n fetchExcludeSettingsAction = 'wpstg_clone_excludes_settings',\n modalErrorAction = 'wpstg_modal_error',\n wpstgObject = wpstg,\n ) {\n this.cloneID = cloneID;\n this.workflow = dom.qs(workflowSelector);\n this.wpstgObject = wpstgObject;\n this.fetchExcludeSettingsAction = fetchExcludeSettingsAction;\n this.modalErrorAction = modalErrorAction;\n this.resetButtonClass = 'wpstg-confirm-reset-clone';\n this.resetModalContainerClass = 'wpstg-reset-confirmation';\n this.resetTabSelector = '.wpstg-reset-exclude-tab';\n this.directoryNavigator = null;\n this.excludeFilters = null;\n this.isAllTablesChecked = true;\n }\n\n addEvents() {\n const resetModalContainer = dom.qs('.' + this.resetModalContainerClass);\n if (resetModalContainer === null) {\n console.log('Exit');\n return;\n }\n\n dom.addEvent(resetModalContainer, 'click', this.resetTabSelector, (target) => {\n this.toggleContent(target);\n });\n\n dom.addEvent(resetModalContainer, 'click', '.wpstg-button-select', () => {\n this.selectDefaultTables();\n });\n\n dom.addEvent(resetModalContainer, 'click', '.wpstg-button-unselect', () => {\n this.toggleTableSelection();\n });\n\n dom.addEvent(resetModalContainer, 'click', '.wpstg-expand-dirs', (target, event) => {\n event.preventDefault();\n this.toggleDirectoryNavigation(target);\n });\n\n dom.addEvent(resetModalContainer, 'change', 'input.wpstg-check-dir', (target) => {\n this.updateDirectorySelection(target);\n });\n }\n\n init() {\n this.addEvents();\n }\n\n toggleContent(target) {\n const resetModalContainer = dom.qs('.' + this.resetModalContainerClass);\n const contentId = target.getAttribute('data-id');\n const tabTriangle = target.querySelector('.wpstg-tab-triangle');\n const isCollapsed = target.getAttribute('data-collapsed', 'true');\n const content = dom.qs(contentId);\n if (isCollapsed === 'true') {\n if (resetModalContainer.classList.contains('has-collapsible-open')) {\n resetModalContainer.classList.add('has-collapsible-open-2');\n } else {\n resetModalContainer.classList.add('has-collapsible-open');\n }\n\n dom.slideDown(content);\n tabTriangle.style.transform = 'rotate(90deg)';\n target.setAttribute('data-collapsed', 'false');\n } else {\n if (resetModalContainer.classList.contains('has-collapsible-open-2')) {\n resetModalContainer.classList.remove('has-collapsible-open-2');\n } else {\n resetModalContainer.classList.remove('has-collapsible-open');\n }\n\n dom.slideUp(content);\n tabTriangle.style.removeProperty('transform');\n target.setAttribute('data-collapsed', 'true');\n }\n }\n\n /**\n * Show Swal alert with loader and send ajax request to fetch content of alert.\n * @return Promise\n */\n showModal() {\n const swalPromise = this.loadModal();\n this.init();\n this.fetchCloneExcludes();\n return swalPromise;\n }\n\n loadModal() {\n return Swal.fire({\n title: '',\n icon: 'warning',\n html: this.getAjaxLoader(),\n width: '300px',\n focusConfirm: false,\n customClass: {\n confirmButton: this.resetButtonClass,\n container: 'wpstg-swal2-container wpstg-swal2-loading ' + this.resetModalContainerClass,\n },\n confirmButtonText: this.wpstgObject.i18n.resetClone,\n showCancelButton: true,\n });\n }\n\n fetchCloneExcludes() {\n this.error = null;\n // send ajax request and fetch preserved exclude settings\n fetch(this.wpstgObject.ajaxUrl, {\n method: 'POST',\n credentials: 'same-origin',\n body: new URLSearchParams({\n action: this.fetchExcludeSettingsAction,\n accessToken: this.wpstgObject.accessToken,\n nonce: this.wpstgObject.nonce,\n clone: this.cloneID,\n job: 'resetting',\n }),\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n }).then((response) => {\n if (response.ok) {\n return response.json();\n }\n\n return Promise.reject(response);\n }).then((data) => {\n if (!data.success) {\n const errorModal = new WpstgModal(this.modalErrorAction, this.wpstgObject);\n errorModal.show(Object.assign({\n title: 'Error',\n icon: 'error',\n html: this.wpstgObject.i18n['somethingWentWrong'],\n width: '500px',\n confirmButtonText: 'Ok',\n showCancelButton: false,\n }, data.swalOptions), {\n type: data.type,\n });\n\n return;\n }\n\n const modal = dom.qs('.wpstg-reset-confirmation');\n modal.classList.remove('wpstg-swal2-loading');\n modal.querySelector('.swal2-popup').style.width = 'auto';\n modal.querySelector('.swal2-content').innerHTML = data.html;\n this.directoryNavigator = new WpstgDirectoryNavigation();\n this.excludeFilters = new WpstgExcludeFilters();\n }).catch((error) => {\n this.renderError({\n 'html': this.wpstgObject.i18n['somethingWentWrong'] + ' ' + error,\n });\n });\n }\n\n getDirectoryNavigator() {\n return this.directoryNavigator;\n }\n\n getExcludeFilters() {\n return this.excludeFilters;\n }\n\n getAjaxLoader() {\n return '<div class=\"wpstg-swal2-ajax-loader\"><img src=\"' + this.wpstgObject.wpstgIcon + '\" /></div>';\n }\n\n toggleDirectoryNavigation(element) {\n const cbElement = element.previousSibling;\n if (cbElement.getAttribute('data-navigateable', 'false') === 'false') {\n return;\n }\n\n if (cbElement.getAttribute('data-scanned', 'false') === 'false') {\n return;\n }\n\n const subDirectories = dom.getNextSibling(element, '.wpstg-subdir');\n\n if (subDirectories.style.display === 'none') {\n dom.slideDown(subDirectories);\n } else {\n dom.slideUp(subDirectories);\n }\n }\n\n updateDirectorySelection(element) {\n const parent = element.parentElement;\n if (element.checked) {\n dom.getParents(parent, '.wpstg-dir').forEach((parElem) => {\n for (let i = 0; i < parElem.children.length; i++) {\n if (parElem.children[i].matches('.wpstg-check-dir')) {\n parElem.children[i].checked = true;\n }\n }\n });\n parent.querySelectorAll('.wpstg-expand-dirs').forEach((x) => {\n x.classList.remove('disabled');\n });\n parent.querySelectorAll('.wpstg-subdir .wpstg-check-dir').forEach((x) => {\n x.checked = true;\n });\n } else {\n parent.querySelectorAll('.wpstg-expand-dirs, .wpstg-check-subdirs').forEach((x) => {\n x.classList.add('disabled');\n });\n parent.querySelectorAll('.wpstg-dir .wpstg-check-dir').forEach((x) => {\n x.checked = false;\n });\n }\n }\n\n selectDefaultTables() {\n const resetModalContainer = dom.qs('.' + this.resetModalContainerClass);\n const options = resetModalContainer.querySelectorAll('#wpstg_select_tables_cloning .wpstg-db-table');\n const multisitePattern = '^' + this.wpstgObject.tblprefix + '([^0-9])_*';\n const singleSitePattern = '^' + this.wpstgObject.tblprefix;\n options.forEach((option) => {\n const name = option.getAttribute('name', '');\n if (this.wpstgObject.isMultisite === '1' && name.match(multisitePattern)) {\n option.setAttribute('selected', 'selected');\n } else if (this.wpstgObject.isMultisite === '' && name.match(singleSitePattern)) {\n option.setAttribute('selected', 'selected');\n } else {\n option.removeAttribute('selected');\n }\n });\n }\n\n toggleTableSelection() {\n const resetModalContainer = dom.qs('.' + this.resetModalContainerClass);\n if (false === this.isAllTablesChecked) {\n resetModalContainer.querySelectorAll('#wpstg_select_tables_cloning .wpstg-db-table').forEach((option) => {\n option.setAttribute('selected', 'selected');\n });\n resetModalContainer.querySelector('.wpstg-button-unselect').innerHTML = 'Unselect All';\n // cache.get('.wpstg-db-table-checkboxes').prop('checked', true);\n this.isAllTablesChecked = true;\n } else {\n resetModalContainer.querySelectorAll('#wpstg_select_tables_cloning .wpstg-db-table').forEach((option) => {\n option.removeAttribute('selected');\n });\n resetModalContainer.querySelector('.wpstg-button-unselect').innerHTML = 'Select All';\n // cache.get('.wpstg-db-table-checkboxes').prop('checked', false);\n this.isAllTablesChecked = false;\n }\n }\n}\n","import WpstgCloneStaging from './modules/wpstg-clone-staging.js';\nimport WpstgDirectoryNavigation from './modules/wpstg-directory-navigation.js';\nimport WpstgExcludeFilters from './modules/wpstg-exclude-filters.js';\nimport WpstgResetModal from './modules/wpstg-reset-modal.js';\nimport WpstgModal from './modules/wpstg-modal.js';\n\nvar WPStaging = (function($) {\n const that = {\n isCancelled: false,\n isFinished: false,\n getLogs: false,\n time: 1,\n executionTime: false,\n progressBar: 0,\n cloneExcludeFilters: null,\n directoryNavigator: null,\n notyf: new Notyf({\n duration: 10000,\n position: {\n x: 'center',\n y: 'bottom',\n },\n dismissible: true,\n types: [\n {\n type: 'warning',\n background: 'orange',\n icon: false,\n },\n ],\n }),\n };\n const cache = {elements: []};\n let timeout; let ajaxSpinner;\n\n /**\n * Get / Set Cache for Selector\n * @param {String} selector\n * @return {*}\n */\n cache.get = function(selector) {\n // It is already cached!\n if ($.inArray(selector, cache.elements) !== -1) {\n return cache.elements[selector];\n }\n\n // Create cache and return\n cache.elements[selector] = jQuery(selector);\n\n return cache.elements[selector];\n };\n\n /**\n * Refreshes given cache\n * @param {String} selector\n */\n cache.refresh = function(selector) {\n selector.elements[selector] = jQuery(selector);\n };\n\n /**\n * Show and Log Error Message\n * @param {String} message\n */\n const showError = function(message) {\n cache.get('#wpstg-try-again').css('display', 'inline-block');\n cache.get('#wpstg-cancel-cloning').text('Reset');\n cache.get('#wpstg-resume-cloning').show();\n cache.get('#wpstg-error-wrapper').show();\n cache.get('#wpstg-error-details').show().html(message);\n cache.get('#wpstg-removing-clone').removeClass('loading');\n cache.get('.wpstg-loader').hide();\n $('.wpstg--modal--process--generic-problem').show().html(message);\n };\n\n /**\n * Show warning during cloning or push process when closing tab or browser, or changing page\n * @param {beforeunload} event\n * @return {null}\n */\n that.warnIfClosingDuringProcess = function(event) {\n // Only some browsers show the message below, most say something like \"Changes you made may not be saved\" (Chrome) or \"You have unsaved changes. Exit?\"\n event.returnValue = 'You MUST leave this window open while cloning/pushing. Please wait...';\n return null;\n };\n\n /**\n *\n * @param obj\n * @return {boolean}\n */\n function isEmpty(obj) {\n for (const prop in obj) {\n if (obj.hasOwnProperty(prop)) {\n return false;\n }\n }\n\n return true;\n }\n\n /**\n *\n * @param response the error object\n * @param prependMessage Overwrite default error message at beginning\n * @param appendMessage Overwrite default error message at end\n * @returns void\n */\n\n const showAjaxFatalError = function(response, prependMessage, appendMessage) {\n prependMessage = prependMessage ? prependMessage + '<br/><br/>' : 'Something went wrong! <br/><br/>';\n appendMessage = appendMessage ? appendMessage + '<br/><br/>' : '<br/><br/>Please try the <a href=\\'https://wp-staging.com/docs/wp-staging-settings-for-small-servers/\\' target=\\'_blank\\'>WP Staging Small Server Settings</a> or submit an error report and contact us.';\n\n if (response === false) {\n showError(prependMessage + ' Error: No response.' + appendMessage);\n window.removeEventListener('beforeunload', WPStaging.warnIfClosingDuringProcess);\n return;\n }\n\n if (typeof response.error !== 'undefined' && response.error) {\n console.error(response.message);\n showError(prependMessage + ' Error: ' + response.message + appendMessage);\n window.removeEventListener('beforeunload', WPStaging.warnIfClosingDuringProcess);\n return;\n }\n };\n\n /**\n *\n * @param response\n * @return {{ok}|*}\n */\n const handleFetchErrors = function(response) {\n if (!response.ok) {\n showError('Error: ' + response.status + ' - ' + response.statusText + '. Please try again or contact support.');\n }\n return response;\n };\n\n /** Hide and reset previous thrown visible errors */\n const resetErrors = function() {\n cache.get('#wpstg-error-details').hide().html('');\n };\n\n const slugify = function(url) {\n return url.toString()\n .toLowerCase()\n .normalize('NFD')\n .replace(/[\\u0300-\\u036f]/g, '')\n .replace(/\\s+/g, '-')\n .replace(/&/g, '-and-')\n .replace(/[^a-z0-9\\-]/g, '')\n .replace(/-+/g, '-')\n .replace(/^-*/, '')\n .replace(/-*$/, '')\n ;\n };\n\n\n /**\n * Common Elements\n */\n const elements = function() {\n const $workFlow = cache.get('#wpstg-workflow');\n let isAllChecked = true;\n let urlSpinner = ajaxurl.replace('/admin-ajax.php', '') + '/images/spinner';\n let timer;\n\n if (2 < window.devicePixelRatio) {\n urlSpinner += '-2x';\n }\n\n urlSpinner += '.gif';\n\n ajaxSpinner = '<img src=\\'\\'' + urlSpinner + '\\' alt=\\'\\' class=\\'ajax-spinner general-spinner\\' />';\n\n const getBaseValues = function() {\n const path = $('#wpstg-use-target-dir').data('base-path');\n const uri = $('#wpstg-use-target-hostname').data('base-uri');\n return {\n path,\n };\n };\n\n $workFlow\n // Check / Un-check All Database Tables New\n .on('click', '.wpstg-button-unselect', function(e) {\n e.preventDefault();\n\n if (false === isAllChecked) {\n cache.get('#wpstg_select_tables_cloning .wpstg-db-table').prop('selected', 'selected');\n cache.get('.wpstg-button-unselect').text('Unselect All');\n cache.get('.wpstg-db-table-checkboxes').prop('checked', true);\n isAllChecked = true;\n } else {\n cache.get('#wpstg_select_tables_cloning .wpstg-db-table').prop('selected', false);\n cache.get('.wpstg-button-unselect').text('Select All');\n cache.get('.wpstg-db-table-checkboxes').prop('checked', false);\n isAllChecked = false;\n }\n })\n\n /**\n * Select tables with certain tbl prefix | NEW\n * @param obj e\n * @returns {undefined}\n */\n .on('click', '.wpstg-button-select', function(e) {\n e.preventDefault();\n $('#wpstg_select_tables_cloning .wpstg-db-table').each(function() {\n if (wpstg.isMultisite == 1) {\n if ($(this).attr('name').match('^' + wpstg.tblprefix + '([^0-9])_*')) {\n $(this).prop('selected', 'selected');\n } else {\n $(this).prop('selected', false);\n }\n }\n\n if (wpstg.isMultisite == 0) {\n if ($(this).attr('name').match('^' + wpstg.tblprefix)) {\n $(this).prop('selected', 'selected');\n } else {\n $(this).prop('selected', false);\n }\n }\n });\n })\n // Expand Directories\n .on('click', '.wpstg-expand-dirs', function(e) {\n e.preventDefault();\n\n const $this = $(this);\n\n $this.siblings('.wpstg-subdir').slideToggle();\n })\n // When a directory checkbox is Selected\n .on('change', 'input.wpstg-check-dir', function() {\n const $directory = $(this).parent('.wpstg-dir');\n\n if (this.checked) {\n $directory.parents('.wpstg-dir').children('.wpstg-check-dir').prop('checked', true);\n $directory.find('.wpstg-expand-dirs').removeClass('disabled');\n $directory.find('.wpstg-subdir .wpstg-check-dir').prop('checked', true);\n } else {\n $directory.find('.wpstg-dir .wpstg-check-dir').prop('checked', false);\n $directory.find('.wpstg-expand-dirs, .wpstg-check-subdirs').addClass('disabled');\n $directory.find('.wpstg-check-subdirs').data('action', 'check').text('check');\n }\n })\n // When a directory name is Selected\n .on('change', 'href.wpstg-check-dir', function() {\n const $directory = $(this).parent('.wpstg-dir');\n\n if (this.checked) {\n $directory.parents('.wpstg-dir').children('.wpstg-check-dir').prop('checked', true);\n $directory.find('.wpstg-expand-dirs').removeClass('disabled');\n $directory.find('.wpstg-subdir .wpstg-check-dir').prop('checked', true);\n } else {\n $directory.find('.wpstg-dir .wpstg-check-dir').prop('checked', false);\n $directory.find('.wpstg-expand-dirs, .wpstg-check-subdirs').addClass('disabled');\n $directory.find('.wpstg-check-subdirs').data('action', 'check').text('check');\n }\n })\n // Check the max length of the clone name and if the clone name already exists\n .on('keyup', '#wpstg-new-clone-id', function() {\n // Hide previous errors\n document.getElementById('wpstg-error-details').style.display = 'none';\n\n // This request was already sent, clear it up!\n if ('number' === typeof (timer)) {\n clearInterval(timer);\n }\n\n const cloneID = this.value;\n\n timer = setTimeout(\n function() {\n ajax(\n {\n action: 'wpstg_check_clone',\n accessToken: wpstg.accessToken,\n nonce: wpstg.nonce,\n cloneID: cloneID,\n },\n function(response) {\n if (response.status === 'success') {\n cache.get('#wpstg-new-clone-id').removeClass('wpstg-error-input');\n cache.get('#wpstg-start-cloning').removeAttr('disabled');\n cache.get('#wpstg-clone-id-error').text('').hide();\n } else {\n cache.get('#wpstg-new-clone-id').addClass('wpstg-error-input');\n cache.get('#wpstg-start-cloning').prop('disabled', true);\n cache.get('#wpstg-clone-id-error').text(response.message).show();\n }\n },\n );\n },\n 500,\n );\n })\n // Restart cloning process\n .on('click', '#wpstg-start-cloning', function() {\n resetErrors();\n that.isCancelled = false;\n that.getLogs = false;\n that.progressBar = 0;\n })\n .on('input', '#wpstg-new-clone-id', function() {\n if ($('#wpstg-clone-directory').length < 1) {\n return;\n }\n\n const slug = slugify(this.value);\n const $targetDir = $('#wpstg-use-target-dir');\n const $targetUri = $('#wpstg-use-target-hostname');\n let path = $targetDir.data('base-path');\n let uri = $targetUri.data('base-uri');\n\n if (path) {\n path = path.replace(/\\/+$/g, '') + '/' + slug + '/';\n }\n\n if (uri) {\n uri = uri.replace(/\\/+$/g, '') + '/' + slug;\n }\n\n\n $('.wpstg-use-target-dir--value').text(path);\n $('.wpstg-use-target-hostname--value').text(uri);\n\n $targetDir.attr('data-path', path);\n $targetUri.attr('data-uri', uri);\n $('#wpstg_clone_dir').attr('placeholder', path);\n $('#wpstg_clone_hostname').attr('placeholder', uri);\n })\n .on('input', '#wpstg_clone_hostname', function() {\n if ($(this).val() === '' || validateTargetHost()) {\n $('#wpstg_clone_hostname_error').remove();\n return;\n }\n if (!validateTargetHost() && !$('#wpstg_clone_hostname_error').length) {\n $('#wpstg-clone-directory tr:last-of-type').after('<tr><td>&nbsp;</td><td><p id=\"wpstg_clone_hostname_error\" style=\"color: red;\">&nbsp;Invalid host name. Please provide it in a format like http://example.com</p></td></tr>');\n }\n })\n ;\n\n cloneActions();\n };\n\n /* @returns {boolean} */\n var validateTargetHost = function() {\n const the_domain = $('#wpstg_clone_hostname').val();\n\n if (the_domain === '') {\n return true;\n }\n\n const reg = /^http(s)?:\\/\\/.*$/;\n if (reg.test(the_domain) === false) {\n return false;\n }\n return true;\n };\n\n /**\n * Clone actions\n */\n var cloneActions = function() {\n const $workFlow = cache.get('#wpstg-workflow');\n\n $workFlow\n // Cancel cloning\n .on('click', '#wpstg-cancel-cloning', function() {\n if (!confirm('Are you sure you want to cancel cloning process?')) {\n return false;\n }\n\n const $this = $(this);\n\n $('#wpstg-try-again, #wpstg-home-link').hide();\n $this.prop('disabled', true);\n\n that.isCancelled = true;\n that.progressBar = 0;\n\n $('#wpstg-processing-status').text('Please wait...this can take up a while.');\n $('.wpstg-loader, #wpstg-show-log-button').hide();\n\n $this.parent().append(ajaxSpinner);\n\n cancelCloning();\n })\n // Resume cloning\n .on('click', '#wpstg-resume-cloning', function() {\n resetErrors();\n const $this = $(this);\n\n $('#wpstg-try-again, #wpstg-home-link').hide();\n\n that.isCancelled = false;\n\n $('#wpstg-processing-status').text('Try to resume cloning process...');\n $('#wpstg-error-details').hide();\n $('.wpstg-loader').show();\n\n $this.parent().append(ajaxSpinner);\n\n that.startCloning();\n })\n // Cancel update cloning\n .on('click', '#wpstg-cancel-cloning-update', function() {\n resetErrors();\n\n const $this = $(this);\n\n $('#wpstg-try-again, #wpstg-home-link').hide();\n $this.prop('disabled', true);\n\n that.isCancelled = true;\n\n $('#wpstg-cloning-result').text('Please wait...this can take up a while.');\n $('.wpstg-loader, #wpstg-show-log-button').hide();\n\n $this.parent().append(ajaxSpinner);\n\n cancelCloningUpdate();\n })\n // Restart cloning\n .on('click', '#wpstg-restart-cloning', function() {\n resetErrors();\n\n const $this = $(this);\n\n $('#wpstg-try-again, #wpstg-home-link').hide();\n $this.prop('disabled', true);\n\n that.isCancelled = true;\n\n $('#wpstg-cloning-result').text('Please wait...this can take up a while.');\n $('.wpstg-loader, #wpstg-show-log-button').hide();\n\n $this.parent().append(ajaxSpinner);\n\n restart();\n })\n // Delete clone - confirmation\n .on('click', '.wpstg-remove-clone[data-clone]', function(e) {\n resetErrors();\n e.preventDefault();\n\n const $existingClones = cache.get('#wpstg-existing-clones');\n\n $workFlow.removeClass('active');\n\n cache.get('.wpstg-loader').show();\n\n ajax(\n {\n action: 'wpstg_confirm_delete_clone',\n accessToken: wpstg.accessToken,\n nonce: wpstg.nonce,\n clone: $(this).data('clone'),\n },\n function(response) {\n cache.get('#wpstg-removing-clone').html(response);\n\n $existingClones.children('img').remove();\n\n cache.get('.wpstg-loader').hide();\n\n $('html, body').animate({\n // This logic is meant to be a \"scrollBottom\"\n scrollTop: $('#wpstg-remove-clone').offset().top - $(window).height() +\n $('#wpstg-remove-clone').height() + 50,\n }, 100);\n },\n 'HTML',\n );\n })\n // Delete clone - confirmed\n .on('click', '#wpstg-remove-clone', function(e) {\n resetErrors();\n e.preventDefault();\n\n cache.get('#wpstg-removing-clone').addClass('loading');\n\n cache.get('.wpstg-loader').show();\n\n deleteClone($(this).data('clone'));\n })\n // Cancel deleting clone\n .on('click', '#wpstg-cancel-removing', function(e) {\n e.preventDefault();\n $('.wpstg-clone').removeClass('active');\n cache.get('#wpstg-removing-clone').html('');\n })\n // Update\n .on('click', '.wpstg-execute-clone', function(e) {\n e.preventDefault();\n\n const clone = $(this).data('clone');\n\n $workFlow.addClass('loading');\n that.cloneExcludeFilters = null;\n ajax(\n {\n action: 'wpstg_scanning',\n clone: clone,\n accessToken: wpstg.accessToken,\n nonce: wpstg.nonce,\n },\n function(response) {\n if (response.length < 1) {\n showError(\n 'Something went wrong! Error: No response. Please try the <a href=\\'https://wp-staging.com/docs/wp-staging-settings-for-small-servers/\\' target=\\'_blank\\'>WP Staging Small Server Settings</a> or submit an error report and contact us.',\n );\n }\n\n const jsonResponse = tryParseJson(response);\n if (jsonResponse !== false && jsonResponse.success === false) {\n $workFlow.removeClass('loading');\n showErrorModal(jsonResponse);\n\n return;\n }\n\n $workFlow.removeClass('loading').html(response);\n // register check disk space function for clone update process.\n checkDiskSpace();\n that.directoryNavigator = new WpstgDirectoryNavigation('#wpstg-directories-listing', wpstg, that.notyf);\n that.cloneExcludeFilters = new WpstgExcludeFilters();\n that.switchStep(2);\n },\n 'HTML',\n );\n })\n // Reset Clone\n .on('click', '.wpstg-reset-clone', function(e) {\n e.preventDefault();\n const clone = $(this).data('clone');\n const resetModal = new WpstgResetModal(clone);\n const promise = resetModal.showModal();\n\n promise.then((result) => {\n if (result.value) {\n const dirNavigator = resetModal.getDirectoryNavigator();\n const exclFilters = resetModal.getExcludeFilters().getExcludeFilters();\n resetClone(clone, {\n includedTables: getIncludedTables(),\n excludeSizeRules: encodeURIComponent(exclFilters.sizes),\n excludeGlobRules: encodeURIComponent(exclFilters.globs),\n excludedDirectories: dirNavigator.getExcludedDirectories(),\n extraDirectories: dirNavigator.getExtraDirectoriesRootOnly(),\n });\n }\n });\n\n return;\n });\n };\n\n /**\n * Ajax Requests\n * @param Object data\n * @param Function callback\n * @param string dataType\n * @param bool showErrors\n * @param int tryCount\n * @param float incrementRatio\n */\n var ajax = function(data, callback, dataType, showErrors, tryCount, incrementRatio = null) {\n if ('undefined' === typeof (dataType)) {\n dataType = 'json';\n }\n\n if (false !== showErrors) {\n showErrors = true;\n }\n\n tryCount = 'undefined' === typeof (tryCount) ? 0 : tryCount;\n\n const retryLimit = 10;\n\n let retryTimeout = 10000 * tryCount;\n\n incrementRatio = parseInt(incrementRatio);\n if (!isNaN(incrementRatio)) {\n retryTimeout *= incrementRatio;\n }\n\n $.ajax({\n url: ajaxurl + '?action=wpstg_processing&_=' + (Date.now() / 1000),\n type: 'POST',\n dataType: dataType,\n cache: false,\n data: data,\n error: function(xhr, textStatus, errorThrown) {\n // try again after 10 seconds\n tryCount++;\n if (tryCount <= retryLimit) {\n setTimeout(function() {\n ajax(data, callback, dataType, showErrors, tryCount, incrementRatio);\n return;\n }, retryTimeout);\n } else {\n const errorCode = 'undefined' === typeof (xhr.status) ? 'Unknown' : xhr.status;\n showError(\n 'Fatal Error: ' + errorCode + ' Please try the <a href=\\'https://wp-staging.com/docs/wp-staging-settings-for-small-servers/\\' target=\\'_blank\\'>WP Staging Small Server Settings</a> or submit an error report and contact us.',\n );\n }\n },\n success: function(data) {\n if ('function' === typeof (callback)) {\n callback(data);\n }\n },\n statusCode: {\n 404: function() {\n if (tryCount >= retryLimit) {\n showError('Error 404 - Can\\'t find ajax request URL! Please try the <a href=\\'https://wp-staging.com/docs/wp-staging-settings-for-small-servers/\\' target=\\'_blank\\'>WP Staging Small Server Settings</a> or submit an error report and contact us.');\n }\n },\n 500: function() {\n if (tryCount >= retryLimit) {\n showError('Fatal Error 500 - Internal server error while processing the request! Please try the <a href=\\'https://wp-staging.com/docs/wp-staging-settings-for-small-servers/\\' target=\\'_blank\\'>WP Staging Small Server Settings</a> or submit an error report and contact us.');\n }\n },\n 504: function() {\n if (tryCount > retryLimit) {\n showError('Error 504 - It looks like your server is rate limiting ajax requests. Please try to resume after a minute. If this still not works try the <a href=\\'https://wp-staging.com/docs/wp-staging-settings-for-small-servers/\\' target=\\'_blank\\'>WP Staging Small Server Settings</a> or submit an error report and contact us.\\n\\ ');\n }\n },\n 502: function() {\n if (tryCount >= retryLimit) {\n showError('Error 502 - It looks like your server is rate limiting ajax requests. Please try to resume after a minute. If this still not works try the <a href=\\'https://wp-staging.com/docs/wp-staging-settings-for-small-servers/\\' target=\\'_blank\\'>WP Staging Small Server Settings</a> or submit an error report and contact us.\\n\\ ');\n }\n },\n 503: function() {\n if (tryCount >= retryLimit) {\n showError('Error 503 - It looks like your server is rate limiting ajax requests. Please try to resume after a minute. If this still not works try the <a href=\\'https://wp-staging.com/docs/wp-staging-settings-for-small-servers/\\' target=\\'_blank\\'>WP Staging Small Server Settings</a> or submit an error report and contact us.\\n\\ ');\n }\n },\n 429: function() {\n if (tryCount >= retryLimit) {\n showError('Error 429 - It looks like your server is rate limiting ajax requests. Please try to resume after a minute. If this still not works try the <a href=\\'https://wp-staging.com/docs/wp-staging-settings-for-small-servers/\\' target=\\'_blank\\'>WP Staging Small Server Settings</a> or submit an error report and contact us.\\n\\ ');\n }\n },\n 403: function() {\n if (tryCount >= retryLimit) {\n showError('Refresh page or login again! The process should be finished successfully. \\n\\ ');\n }\n },\n },\n });\n };\n\n /**\n * Next / Previous Step Clicks to Navigate Through Staging Job\n */\n const stepButtons = function() {\n const $workFlow = cache.get('#wpstg-workflow');\n\n $workFlow\n // Next Button\n .on('click', '.wpstg-next-step-link', function(e) {\n e.preventDefault();\n\n const $this = $(this);\n const isScan = false;\n\n if ($('#wpstg_clone_hostname').length && !validateTargetHost()) {\n $('#wpstg_clone_hostname').focus();\n return false;\n }\n\n if ($this.data('action') === 'wpstg_update' || $this.data('action') === 'wpstg_reset') {\n // Update / Reset Clone - confirmed\n let onlyUpdateMessage = '';\n if ($this.data('action') === 'wpstg_update') {\n onlyUpdateMessage = ' \\n\\nExclude all tables and folders you do not want to overwrite, first! \\n\\nDo not cancel the updating process! This can break your staging site. \\n\\n\\Create a backup of your staging website before you proceed.';\n }\n\n if (!confirm('STOP! This will overwrite your staging site with all selected data from the production site! This should be used only if you want to clone again your production site. Are you sure you want to do this?' + onlyUpdateMessage)) {\n return false;\n }\n }\n\n // Button is disabled\n if ($this.attr('disabled')) {\n return false;\n }\n\n if ($this.data('action') === 'wpstg_cloning') {\n // Verify External Database If Checked and Not Skipped\n if ($('#wpstg-ext-db').is(':checked')) {\n verifyExternalDatabase($this, $workFlow);\n return;\n }\n }\n\n proceedCloning($this, $workFlow);\n })\n // Previous Button\n .on('click', '.wpstg-prev-step-link', function(e) {\n e.preventDefault();\n cache.get('.wpstg-loader').removeClass('wpstg-finished');\n cache.get('.wpstg-loader').hide();\n loadOverview();\n });\n };\n\n /**\n * Get Included (Checked) Database Tables\n * @return {Array}\n */\n const getIncludedTables = function() {\n const includedTables = [];\n\n $('#wpstg_select_tables_cloning option:selected').each(function() {\n includedTables.push(this.value);\n });\n\n return includedTables;\n };\n\n /**\n * Get Excluded (Unchecked) Database Tables\n * Not used anymore!\n * @return {Array}\n */\n const getExcludedTables = function() {\n const excludedTables = [];\n\n $('.wpstg-db-table input:not(:checked)').each(function() {\n excludedTables.push(this.name);\n });\n\n return excludedTables;\n };\n\n /**\n * Verify External Database for Cloning\n */\n var verifyExternalDatabase = function($this, workflow) {\n cache.get('.wpstg-loader').show();\n ajax(\n {\n action: 'wpstg_database_verification',\n accessToken: wpstg.accessToken,\n nonce: wpstg.nonce,\n databaseUser: cache.get('#wpstg_db_username').val(),\n databasePassword: cache.get('#wpstg_db_password').val(),\n databaseServer: cache.get('#wpstg_db_server').val(),\n databaseDatabase: cache.get('#wpstg_db_database').val(),\n },\n function(response) {\n // Undefined Error\n if (false === response) {\n showError(\n 'Something went wrong! Error: No response.' +\n 'Please try again. If that does not help, ' +\n '<a href=\\'https://wp-staging.com/support/\\' target=\\'_blank\\'>open a support ticket</a> ',\n );\n cache.get('.wpstg-loader').hide();\n return;\n }\n\n // Throw Error\n if ('undefined' === typeof (response.success)) {\n showError(\n 'Something went wrong! Error: Invalid response.' +\n 'Please try again. If that does not help, ' +\n '<a href=\\'https://wp-staging.com/support/\\' target=\\'_blank\\'>open a support ticket</a> ',\n );\n cache.get('.wpstg-loader').hide();\n return;\n }\n\n if (response.success) {\n cache.get('.wpstg-loader').hide();\n proceedCloning($this, workflow);\n return;\n }\n\n if (response.error_type === 'comparison') {\n cache.get('.wpstg-loader').hide();\n let render = '<table style=\"width: 100%;\"><thead><tr><th>Property</th><th>Production DB</th><th>Staging DB</th><th>Status</th></tr></thead><tbody>';\n response.checks.forEach((x) => {\n let icon = '<i style=\"color: #00ff00\">✔</i>';\n if (x.production !== x.staging) {\n icon = '<i style=\"color: #ff0000\">❌</i>';\n }\n render += '<tr><td>' + x.name + '</td><td>' + x.production + '</td><td>' + x.staging + '</td><td>' + icon + '</td></tr>';\n });\n render += '</tbody></table><p>Note: Some mySQL properties do not match. You may proceed but the staging site may not work as expected.</p>';\n Swal.fire({\n title: 'Different Database Properties',\n icon: 'warning',\n html: render,\n width: '650px',\n focusConfirm: false,\n confirmButtonText: 'Proceed Anyway',\n showCancelButton: true,\n }).then(function(result) {\n if (result.value) {\n proceedCloning($this, workflow);\n }\n });\n return;\n }\n\n Swal.fire({\n title: 'Different Database Properties',\n icon: 'error',\n html: response.message,\n focusConfirm: true,\n confirmButtonText: 'Ok',\n showCancelButton: false,\n });\n cache.get('.wpstg-loader').hide();\n },\n 'json',\n false,\n );\n };\n\n /**\n * Get Cloning Step Data\n */\n const getCloningData = function() {\n if ('wpstg_cloning' !== that.data.action && 'wpstg_update' !== that.data.action && 'wpstg_reset' !== that.data.action) {\n return;\n }\n\n that.data.cloneID = $('#wpstg-new-clone-id').val() || new Date().getTime().toString();\n // Remove this to keep &_POST[] small otherwise mod_security will throw error 404\n // that.data.excludedTables = getExcludedTables();\n\n if (that.directoryNavigator !== null) {\n that.data.excludedDirectories = encodeURIComponent(that.directoryNavigator.getExcludedDirectories());\n that.data.extraDirectories = encodeURIComponent(that.directoryNavigator.getExtraDirectoriesRootOnly());\n }\n\n that.data.excludeGlobRules = '';\n that.data.excludeSizeRules = '';\n if (that.cloneExcludeFilters instanceof WpstgExcludeFilters) {\n const rules = that.cloneExcludeFilters.getExcludeFilters();\n that.data.excludeGlobRules = encodeURIComponent(rules.globs);\n that.data.excludeSizeRules = encodeURIComponent(rules.sizes);\n }\n\n that.data.includedTables = getIncludedTables();\n that.data.databaseServer = $('#wpstg_db_server').val();\n that.data.databaseUser = $('#wpstg_db_username').val();\n that.data.databasePassword = $('#wpstg_db_password').val();\n that.data.databaseDatabase = $('#wpstg_db_database').val();\n that.data.databasePrefix = $('#wpstg_db_prefix').val();\n const cloneDir = $('#wpstg_clone_dir').val();\n that.data.cloneDir = encodeURIComponent($.trim(cloneDir));\n that.data.cloneHostname = $('#wpstg_clone_hostname').val();\n that.data.emailsAllowed = $('#wpstg_allow_emails').is(':checked');\n that.data.uploadsSymlinked = $('#wpstg_symlink_upload').is(':checked');\n that.data.cleanPluginsThemes = $('#wpstg-clean-plugins-themes').is(':checked');\n that.data.cleanUploadsDir = $('#wpstg-clean-uploads').is(':checked');\n };\n\n var proceedCloning = function($this, workflow) {\n // Add loading overlay\n workflow.addClass('loading');\n\n // Prepare data\n that.data = {\n action: $this.data('action'),\n accessToken: wpstg.accessToken,\n nonce: wpstg.nonce,\n };\n\n // Cloning data\n getCloningData();\n\n sendCloningAjax(workflow);\n };\n\n var sendCloningAjax = function(workflow) {\n // Send ajax request\n ajax(\n that.data,\n function(response) {\n // Undefined Error\n if (false === response) {\n showError(\n 'Something went wrong!<br/><br/> Go to WP Staging > Settings and lower \\'File Copy Limit\\' and \\'DB Query Limit\\'. Also set \\'CPU Load Priority to low \\'' +\n 'and try again. If that does not help, ' +\n '<a href=\\'https://wp-staging.com/support/\\' target=\\'_blank\\'>open a support ticket</a> ',\n );\n }\n\n\n if (response.length < 1) {\n showError(\n 'Something went wrong! No response. Go to WP Staging > Settings and lower \\'File Copy Limit\\' and \\'DB Query Limit\\'. Also set \\'CPU Load Priority to low \\'' +\n 'and try again. If that does not help, ' +\n '<a href=\\'https://wp-staging.com/support/\\' target=\\'_blank\\'>open a support ticket</a> ',\n );\n }\n\n const jsonResponse = tryParseJson(response);\n if (jsonResponse !== false && jsonResponse.success === false) {\n workflow.removeClass('loading');\n showErrorModal(jsonResponse);\n\n return;\n }\n\n // Styling of elements\n workflow.removeClass('loading').html(response);\n that.cloneExcludeFilters = null;\n if (that.data.action === 'wpstg_scanning') {\n that.directoryNavigator = new WpstgDirectoryNavigation('#wpstg-directories-listing', wpstg, that.notyf);\n that.switchStep(2);\n that.cloneExcludeFilters = new WpstgExcludeFilters();\n } else if (that.data.action === 'wpstg_cloning' || that.data.action === 'wpstg_update' || that.data.action === 'wpstg_reset') {\n that.switchStep(3);\n }\n\n // Start cloning\n that.startCloning();\n },\n 'HTML',\n );\n };\n\n var showErrorModal = function(response) {\n const errorModal = new WpstgModal('wpstg_modal_error', wpstg);\n errorModal.show(Object.assign({\n title: 'Error',\n icon: 'error',\n html: wpstg.i18n['somethingWentWrong'],\n width: '500px',\n confirmButtonText: 'Ok',\n showCancelButton: false,\n }, response.swalOptions), {\n type: response.type,\n });\n };\n\n const tryParseJson = function(json) {\n // early bail if not string\n if (!json) {\n return false;\n }\n\n try {\n const object = JSON.parse(json);\n if (object && typeof object === 'object') {\n return object;\n }\n } catch (e) {\n // do nothing on catch\n }\n\n return false;\n };\n\n var resetClone = function(clone, excludeOptions) {\n that.data = {\n action: 'wpstg_reset',\n accessToken: wpstg.accessToken,\n nonce: wpstg.nonce,\n cloneID: clone,\n };\n\n that.data = {...that.data, ...excludeOptions};\n\n const $workFlow = cache.get('#wpstg-workflow');\n sendCloningAjax($workFlow);\n };\n\n /**\n * Loads Overview (first step) of Staging Job\n */\n var loadOverview = function() {\n const $workFlow = cache.get('#wpstg-workflow');\n\n $workFlow.addClass('loading');\n\n ajax(\n {\n action: 'wpstg_overview',\n accessToken: wpstg.accessToken,\n nonce: wpstg.nonce,\n },\n function(response) {\n if (response.length < 1) {\n showError(\n 'Something went wrong! No response. Please try the <a href=\\'https://wp-staging.com/docs/wp-staging-settings-for-small-servers/\\' target=\\'_blank\\'>WP Staging Small Server Settings</a> or submit an error report.',\n );\n }\n\n const $currentStep = cache.get('.wpstg-current-step');\n\n // Styling of elements\n $workFlow.removeClass('loading').html(response);\n },\n 'HTML',\n );\n\n that.switchStep(1);\n cache.get('.wpstg-step3-cloning').show();\n cache.get('.wpstg-step3-pushing').hide();\n };\n\n /**\n * Load Tabs\n */\n const tabs = function() {\n cache.get('#wpstg-workflow').on('click', '.wpstg-tab-header', function(e) {\n e.preventDefault();\n\n const $this = $(this);\n const $section = cache.get($this.data('id'));\n\n $this.toggleClass('expand');\n\n $section.slideToggle();\n\n if ($this.hasClass('expand')) {\n $this.find('.wpstg-tab-triangle').html('&#9660;');\n } else {\n $this.find('.wpstg-tab-triangle').html('&#9658;');\n }\n });\n };\n\n /**\n * Delete Clone\n * @param {String} clone\n */\n var deleteClone = function(clone) {\n const deleteDir = $('#deleteDirectory:checked').data('deletepath');\n\n ajax(\n {\n action: 'wpstg_delete_clone',\n clone: clone,\n accessToken: wpstg.accessToken,\n nonce: wpstg.nonce,\n excludedTables: getExcludedTables(),\n deleteDir: deleteDir,\n },\n function(response) {\n if (response) {\n showAjaxFatalError(response);\n\n // Finished\n if ('undefined' !== typeof response.delete && (response.delete === 'finished' || response.delete === 'unfinished')) {\n cache.get('#wpstg-removing-clone').removeClass('loading').html('');\n\n if (response.delete === 'finished') {\n $('.wpstg-clone#' + clone).remove();\n }\n\n if ($('.wpstg-clone').length < 1) {\n cache.get('#wpstg-existing-clones').find('h3').text('');\n }\n\n cache.get('.wpstg-loader').hide();\n return;\n }\n }\n // continue\n if (true !== response) {\n deleteClone(clone);\n return;\n }\n },\n );\n };\n\n /**\n * Cancel Cloning Process\n */\n var cancelCloning = function() {\n that.timer('stop');\n\n\n if (true === that.isFinished) {\n return true;\n }\n\n ajax(\n {\n action: 'wpstg_cancel_clone',\n clone: that.data.cloneID,\n accessToken: wpstg.accessToken,\n nonce: wpstg.nonce,\n },\n function(response) {\n if (response && 'undefined' !== typeof (response.delete) && response.delete === 'finished') {\n cache.get('.wpstg-loader').hide();\n // Load overview\n loadOverview();\n return;\n }\n\n if (true !== response) {\n // continue\n cancelCloning();\n return;\n }\n\n // Load overview\n loadOverview();\n },\n );\n };\n\n /**\n * Cancel Cloning Process\n */\n var cancelCloningUpdate = function() {\n if (true === that.isFinished) {\n return true;\n }\n\n ajax(\n {\n action: 'wpstg_cancel_update',\n clone: that.data.cloneID,\n accessToken: wpstg.accessToken,\n nonce: wpstg.nonce,\n },\n function(response) {\n if (response && 'undefined' !== typeof (response.delete) && response.delete === 'finished') {\n // Load overview\n loadOverview();\n return;\n }\n\n if (true !== response) {\n // continue\n cancelCloningUpdate();\n return;\n }\n\n // Load overview\n loadOverview();\n },\n );\n };\n\n /**\n * Cancel Cloning Process\n */\n var restart = function() {\n if (true === that.isFinished) {\n return true;\n }\n\n ajax(\n {\n action: 'wpstg_restart',\n // clone: that.data.cloneID,\n accessToken: wpstg.accessToken,\n nonce: wpstg.nonce,\n },\n function(response) {\n if (response && 'undefined' !== typeof (response.delete) && response.delete === 'finished') {\n // Load overview\n loadOverview();\n return;\n }\n\n if (true !== response) {\n // continue\n cancelCloningUpdate();\n return;\n }\n\n // Load overview\n loadOverview();\n },\n );\n };\n\n /**\n * Scroll the window log to bottom\n * @return void\n */\n const logscroll = function() {\n const $div = cache.get('.wpstg-log-details');\n if ('undefined' !== typeof ($div[0])) {\n $div.scrollTop($div[0].scrollHeight);\n }\n };\n\n /**\n * Append the log to the logging window\n * @param string log\n * @return void\n */\n const getLogs = function(log) {\n if (log != null && 'undefined' !== typeof (log)) {\n if (log.constructor === Array) {\n $.each(log, function(index, value) {\n if (value === null) {\n return;\n }\n if (value.type === 'ERROR') {\n cache.get('.wpstg-log-details').append('<span style=\"color:red;\">[' + value.type + ']</span>-' + '[' + value.date + '] ' + value.message + '</br>');\n } else {\n cache.get('.wpstg-log-details').append('[' + value.type + ']-' + '[' + value.date + '] ' + value.message + '</br>');\n }\n });\n } else {\n cache.get('.wpstg-log-details').append('[' + log.type + ']-' + '[' + log.date + '] ' + log.message + '</br>');\n }\n }\n logscroll();\n };\n\n /**\n * Check diskspace\n * @return string json\n */\n var checkDiskSpace = function() {\n cache.get('#wpstg-check-space').on('click', function(e) {\n cache.get('.wpstg-loader').show();\n const excludedDirectories = encodeURIComponent(that.directoryNavigator.getExcludedDirectories());\n const extraDirectories = encodeURIComponent(that.directoryNavigator.getExtraDirectoriesRootOnly());\n\n ajax(\n {\n action: 'wpstg_check_disk_space',\n accessToken: wpstg.accessToken,\n nonce: wpstg.nonce,\n excludedDirectories: excludedDirectories,\n extraDirectories: extraDirectories,\n },\n function(response) {\n if (false === response) {\n cache.get('#wpstg-clone-id-error').text('Can not detect required disk space').show();\n cache.get('.wpstg-loader').hide();\n return;\n }\n\n // Show required disk space\n cache.get('#wpstg-clone-id-error').html('Estimated necessary disk space: ' + response.usedspace + '<br> <span style=\"color:#444;\">Before you proceed ensure your account has enough free disk space to hold the entire instance of the production site. You can check the available space from your hosting account (cPanel or similar).</span>').show();\n cache.get('.wpstg-loader').hide();\n },\n 'json',\n false,\n );\n });\n };\n\n const mainTabs = function() {\n $('.wpstg--tab--header a[data-target]').on('click', function() {\n const $this = $(this);\n const target = $this.attr('data-target');\n const $wrapper = $this.parents('.wpstg--tab--wrapper');\n const $menuItems = $wrapper.find('.wpstg--tab--header a[data-target]');\n const $contents = $wrapper.find('.wpstg--tab--contents > .wpstg--tab--content');\n\n $contents.filter('.wpstg--tab--active:not(.wpstg--tab--active' + target + ')').removeClass('wpstg--tab--active');\n $menuItems.not($this).removeClass('wpstg--tab--active');\n $this.addClass('wpstg--tab--active');\n $(target).addClass('wpstg--tab--active');\n\n if ('#wpstg--tab--backup' === target) {\n that.backups.init();\n }\n\n if ('#wpstg--tab--database-backups' === target) {\n window.dispatchEvent(new Event('database-backups-tab'));\n }\n });\n };\n\n /**\n * Show or hide animated loading icon\n * @param isLoading bool\n */\n const isLoading = function(isLoading) {\n if (!isLoading || isLoading === false) {\n cache.get('.wpstg-loader').hide();\n } else {\n cache.get('.wpstg-loader').show();\n }\n };\n\n /**\n * Count up processing execution time\n * @param string status\n * @return html\n */\n that.timer = function(status) {\n if (status === 'stop') {\n const time = that.time;\n that.time = 1;\n clearInterval(that.executionTime);\n return that.convertSeconds(time);\n }\n\n\n that.executionTime = setInterval(function() {\n if (null !== document.getElementById('wpstg-processing-timer')) {\n document.getElementById('wpstg-processing-timer').innerHTML = 'Elapsed Time: ' + that.convertSeconds(that.time);\n }\n that.time++;\n if (status === 'stop') {\n that.time = 1;\n clearInterval(that.executionTime);\n }\n }, 1000);\n };\n\n /**\n * Convert seconds to hourly format\n * @param int seconds\n * @return string\n */\n that.convertSeconds = function(seconds) {\n const date = new Date(null);\n date.setSeconds(seconds); // specify value for SECONDS here\n return date.toISOString().substr(11, 8);\n };\n\n /**\n * Start Cloning Process\n * @type {Function}\n */\n that.startCloning = (function() {\n resetErrors();\n\n // Register function for checking disk space\n checkDiskSpace();\n\n if ('wpstg_cloning' !== that.data.action && 'wpstg_update' !== that.data.action && 'wpstg_reset' !== that.data.action) {\n return;\n }\n\n that.isCancelled = false;\n\n // Start the process\n start();\n\n // Functions\n // Start\n function start() {\n cache.get('.wpstg-loader').show();\n cache.get('#wpstg-cancel-cloning').text('Cancel');\n cache.get('#wpstg-resume-cloning').hide();\n cache.get('#wpstg-error-details').hide();\n\n\n // Clone Database\n setTimeout(function() {\n // cloneDatabase();\n window.addEventListener('beforeunload', WPStaging.warnIfClosingDuringProcess);\n processing();\n }, wpstg.delayReq);\n\n that.timer('start');\n }\n\n\n /**\n * Start ajax processing\n * @return string\n */\n var processing = function() {\n if (true === that.isCancelled) {\n window.removeEventListener('beforeunload', WPStaging.warnIfClosingDuringProcess);\n return false;\n }\n\n isLoading(true);\n\n let excludedDirectories = '';\n let extraDirectories = '';\n if (that.directoryNavigator !== null) {\n excludedDirectories = that.directoryNavigator.getExcludedDirectories();\n extraDirectories = that.directoryNavigator.getExtraDirectoriesRootOnly();\n }\n\n // Show logging window\n cache.get('.wpstg-log-details').show();\n\n WPStaging.ajax(\n {\n action: 'wpstg_processing',\n accessToken: wpstg.accessToken,\n nonce: wpstg.nonce,\n excludedTables: getExcludedTables(),\n excludedDirectories: encodeURIComponent(excludedDirectories),\n extraDirectories: encodeURIComponent(extraDirectories),\n },\n function(response) {\n showAjaxFatalError(response);\n\n // Add Log messages\n if ('undefined' !== typeof (response.last_msg) && response.last_msg) {\n getLogs(response.last_msg);\n }\n // Continue processing\n if (false === response.status) {\n progressBar(response);\n\n setTimeout(function() {\n cache.get('.wpstg-loader').show();\n processing();\n }, wpstg.delayReq);\n } else if (true === response.status && 'finished' !== response.status) {\n cache.get('#wpstg-error-details').hide();\n cache.get('#wpstg-error-wrapper').hide();\n progressBar(response, true);\n processing();\n } else if ('finished' === response.status || ('undefined' !== typeof (response.job_done) && response.job_done)) {\n window.removeEventListener('beforeunload', WPStaging.warnIfClosingDuringProcess);\n finish(response);\n }\n ;\n },\n 'json',\n false,\n );\n };\n\n // Finish\n function finish(response) {\n if (true === that.getLogs) {\n getLogs();\n }\n\n progressBar(response);\n\n // Add Log\n if ('undefined' !== typeof (response.last_msg)) {\n getLogs(response.last_msg);\n }\n\n cache.get('.wpstg-loader').hide();\n cache.get('#wpstg-processing-header').html('Processing Complete');\n $('#wpstg-processing-status').text('Succesfully finished');\n\n cache.get('#wpstg_staging_name').html(that.data.cloneID);\n cache.get('#wpstg-finished-result').show();\n cache.get('#wpstg-cancel-cloning').hide();\n cache.get('#wpstg-resume-cloning').hide();\n cache.get('#wpstg-cancel-cloning-update').prop('disabled', true);\n\n const $link1 = cache.get('#wpstg-clone-url-1');\n const $link = cache.get('#wpstg-clone-url');\n $link1.attr('href', response.url);\n $link1.html(response.url);\n $link.attr('href', response.url);\n\n cache.get('#wpstg-remove-clone').data('clone', that.data.cloneID);\n\n // Finished\n that.isFinished = true;\n that.timer('stop');\n\n\n cache.get('.wpstg-loader').hide();\n cache.get('#wpstg-processing-header').html('Processing Complete');\n\n // show alert\n let msg = wpstg.i18n.cloneResetComplete;\n if (that.data.action === 'wpstg_update') {\n msg = wpstg.i18n.cloneUpdateComplete;\n }\n\n if (that.data.action === 'wpstg_update' || that.data.action === 'wpstg_reset') {\n Swal.fire({\n title: '',\n icon: 'success',\n html: msg,\n width: '500px',\n focusConfirm: true,\n });\n }\n\n return false;\n }\n\n /**\n * Add percentage progress bar\n * @param object response\n * @return {Boolean}\n */\n var progressBar = function(response, restart) {\n if ('undefined' === typeof (response.percentage)) {\n return false;\n }\n\n if (response.job === 'database') {\n cache.get('#wpstg-progress-db').width(response.percentage * 0.2 + '%').html(response.percentage + '%');\n cache.get('#wpstg-processing-status').html(response.percentage.toFixed(0) + '%' + ' - Step 1 of 4 Cloning Database Tables...');\n }\n\n if (response.job === 'SearchReplace') {\n cache.get('#wpstg-progress-db').css('background-color', '#3bc36b');\n cache.get('#wpstg-progress-db').html('1. Database');\n // Assumption: All previous steps are done.\n // This avoids bugs where some steps are skipped and the progress bar is incomplete as a result\n cache.get('#wpstg-progress-db').width('20%');\n\n cache.get('#wpstg-progress-sr').width(response.percentage * 0.1 + '%').html(response.percentage + '%');\n cache.get('#wpstg-processing-status').html(response.percentage.toFixed(0) + '%' + ' - Step 2 of 4 Preparing Database Data...');\n }\n\n if (response.job === 'directories') {\n cache.get('#wpstg-progress-sr').css('background-color', '#3bc36b');\n cache.get('#wpstg-progress-sr').html('2. Data');\n cache.get('#wpstg-progress-sr').width('10%');\n\n cache.get('#wpstg-progress-dirs').width(response.percentage * 0.1 + '%').html(response.percentage + '%');\n cache.get('#wpstg-processing-status').html(response.percentage.toFixed(0) + '%' + ' - Step 3 of 4 Getting files...');\n }\n if (response.job === 'files') {\n cache.get('#wpstg-progress-dirs').css('background-color', '#3bc36b');\n cache.get('#wpstg-progress-dirs').html('3. Files');\n cache.get('#wpstg-progress-dirs').width('10%');\n\n cache.get('#wpstg-progress-files').width(response.percentage * 0.6 + '%').html(response.percentage + '%');\n cache.get('#wpstg-processing-status').html(response.percentage.toFixed(0) + '%' + ' - Step 4 of 4 Copy files...');\n }\n if (response.job === 'finish') {\n cache.get('#wpstg-progress-files').css('background-color', '#3bc36b');\n cache.get('#wpstg-progress-files').html('4. Copy Files');\n cache.get('#wpstg-progress-files').width('60%');\n\n cache.get('#wpstg-processing-status').html(response.percentage.toFixed(0) + '%' + ' - Cloning Process Finished');\n }\n };\n });\n\n that.switchStep = function(step) {\n cache.get('.wpstg-current-step')\n .removeClass('wpstg-current-step');\n cache.get('.wpstg-step' + step)\n .addClass('wpstg-current-step');\n };\n\n /**\n * Initiation\n * @type {Function}\n */\n that.init = (function() {\n loadOverview();\n elements();\n stepButtons();\n tabs();\n mainTabs();\n new WpstgCloneStaging();\n });\n\n /**\n * Ajax call\n * @type {ajax}\n */\n that.ajax = ajax;\n that.showError = showError;\n that.getLogs = getLogs;\n that.loadOverview = loadOverview;\n\n // TODO RPoC (too big, scattered and unorganized)\n that.backups = {\n type: null,\n isCancelled: false,\n processInfo: {\n title: null,\n interval: null,\n },\n modal: {\n create: {\n html: null,\n confirmBtnTxt: null,\n },\n process: {\n html: null,\n cancelBtnTxt: null,\n modal: null,\n },\n download: {\n html: null,\n },\n import: {\n html: null,\n btnTxtNext: null,\n btnTxtConfirm: null,\n btnTxtCancel: null,\n searchReplaceForm: null,\n file: null,\n containerUpload: null,\n containerFilesystem: null,\n setFile: (file, upload = true) => {\n const toUnit = (bytes) => {\n const i = Math.floor(Math.log(bytes) / Math.log(1024));\n return (bytes / Math.pow(1024, i)).toFixed(2) * 1 + ' ' + ['B', 'kB', 'MB', 'GB', 'TB'][i];\n };\n\n if (!file) {\n return;\n }\n\n that.backups.modal.import.file = file;\n that.backups.modal.import.data.file = file.name;\n\n $('.wpstg--backup--import--selected-file').html(`${file.name} <br /> (${toUnit(file.size)})`).show();\n $('.wpstg--drag').hide();\n $('.wpstg--drag-or-upload').show();\n\n if (upload) {\n $('.wpstg--modal--actions .swal2-confirm').prop('disabled', true);\n that.backups.upload.start();\n }\n },\n baseDirectory: null,\n data: {\n file: null,\n search: [],\n replace: [],\n },\n },\n },\n messages: {\n WARNING: 'warning',\n ERROR: 'error',\n INFO: 'info',\n DEBUG: 'debug',\n CRITICAL: 'critical',\n data: {\n all: [], // TODO RPoC\n info: [],\n error: [],\n critical: [],\n warning: [],\n debug: [],\n },\n shouldWarn() {\n return that.backups.messages.data.error.length > 0 ||\n that.backups.messages.data.critical.length > 0\n ;\n },\n countByType(type = that.backups.messages.ERROR) {\n return that.backups.messages.data[type].length;\n },\n addMessage(message) {\n if (Array.isArray(message)) {\n message.forEach((item) => {\n that.backups.messages.addMessage(item);\n });\n return;\n }\n const type = message.type.toLowerCase() || 'info';\n if (!that.backups.messages.data[type]) {\n that.backups.messages.data[type] = [];\n }\n that.backups.messages.data.all.push(message); // TODO RPoC\n that.backups.messages.data[type].push(message);\n },\n reset() {\n that.backups.messages.data = {\n all: [],\n info: [],\n error: [],\n critical: [],\n warning: [],\n debug: [],\n };\n },\n },\n timer: {\n totalSeconds: 0,\n interval: null,\n start() {\n if (null !== that.backups.timer.interval) {\n return;\n }\n\n const prettify = (seconds) => {\n // If potentially anything can exceed 24h execution time than that;\n // const _seconds = parseInt(seconds, 10)\n // const hours = Math.floor(_seconds / 3600)\n // const minutes = Math.floor(_seconds / 60) % 60\n // seconds = _seconds % 60\n //\n // return [hours, minutes, seconds]\n // .map(v => v < 10 ? '0' + v : v)\n // .filter((v,i) => v !== '00' || i > 0)\n // .join(':')\n // ;\n // Are we sure we won't create anything that exceeds 24h execution time? If not then this;\n return `${(new Date(seconds * 1000)).toISOString().substr(11, 8)}`;\n };\n\n that.backups.timer.interval = setInterval(() => {\n $('.wpstg--modal--process--elapsed-time').text(prettify(that.backups.timer.totalSeconds));\n that.backups.timer.totalSeconds++;\n }, 1000);\n },\n stop() {\n that.backups.timer.totalSeconds = 0;\n if (that.backups.timer.interval) {\n clearInterval(that.backups.timer.interval);\n that.backups.timer.interval = null;\n }\n },\n },\n upload: {\n reader: null,\n file: null,\n iop: 1000 * 1024,\n uploadInfo(isShow) {\n const $containerUpload = $('.wpstg--modal--import--upload--process');\n const $containerUploader = $('.wpstg--uploader');\n if (isShow) {\n $containerUpload.css('display', 'flex');\n $containerUploader.hide();\n return;\n }\n\n $containerUploader.css('display', 'flex');\n $containerUpload.hide();\n },\n start() {\n that.backups.upload.reader = new FileReader();\n that.backups.upload.file = that.backups.modal.import.file;\n that.backups.upload.uploadInfo(true);\n that.backups.upload.sendChunk();\n },\n sendChunk(startsAt = 0) {\n if (!that.backups.upload.file) {\n return;\n }\n const isReset = startsAt < 1;\n const endsAt = startsAt + that.backups.upload.iop + 1;\n const blob = that.backups.upload.file.slice(startsAt, endsAt);\n that.backups.upload.reader.onloadend = function(event) {\n if (event.target.readyState !== FileReader.DONE) {\n return;\n }\n\n const body = new FormData();\n body.append('accessToken', wpstg.accessToken);\n body.append('nonce', wpstg.nonce);\n body.append('data', event.target.result);\n body.append('filename', that.backups.upload.file.name);\n body.append('reset', isReset ? '1' : '0');\n\n\n fetch(`${ajaxurl}?action=wpstg--backups--import--file-upload`, {\n method: 'POST',\n body,\n }).then(handleFetchErrors)\n .then((res) => res.json())\n .then((res) => {\n showAjaxFatalError(res, '', 'Submit an error report.');\n const writtenBytes = startsAt + that.backups.upload.iop;\n const percent = Math.floor((writtenBytes / that.backups.upload.file.size) * 100);\n if (endsAt >= that.backups.upload.file.size) {\n that.backups.upload.uploadInfo(false);\n isLoading(false);\n that.backups.switchModalToConfigure();\n return;\n }\n $('.wpstg--modal--import--upload--progress--title > span').text(percent);\n $('.wpstg--modal--import--upload--progress').css('width', `${percent}%`);\n that.backups.upload.sendChunk(endsAt);\n })\n .catch((e) => showAjaxFatalError(e, '', 'Submit an error report.'))\n ;\n };\n that.backups.upload.reader.readAsDataURL(blob);\n },\n },\n status: {\n hasResponse: null,\n reTryAfter: 5000,\n },\n init() {\n this.create();\n this.delete();\n this.edit();\n\n // noinspection JSIgnoredPromiseFromCall\n that.backups.fetchListing();\n\n $('body')\n .on('click', '.wpstg--backup--download', function() {\n const url = this.getAttribute('data-url');\n if (url.length > 0) {\n window.location.href = url;\n return;\n }\n that.backups.downloadModal({\n titleExport: this.getAttribute('data-title-export'),\n title: this.getAttribute('data-title'),\n id: this.getAttribute('data-id'),\n btnTxtCancel: this.getAttribute('data-btn-cancel-txt'),\n btnTxtConfirm: this.getAttribute('data-btn-download-txt'),\n });\n })\n .on('click', '.wpstg--backup--import', function() {\n // Clicked \"Import\" on the backup list\n that.backups.importModal();\n that.backups.modal.import.data.file = this.getAttribute('data-filePath');\n that.backups.switchModalToConfigure();\n // $('.wpstg--modal--actions .swal2-confirm').show();\n // $('.wpstg--modal--actions .swal2-confirm').prop('disabled', false);\n })\n .off('click', '#wpstg-import-backup')\n .on('click', '#wpstg-import-backup', function() {\n that.backups.importModal();\n })\n // Import\n .off('click', '.wpstg--backup--import--choose-option')\n .on('click', '.wpstg--backup--import--choose-option', function() {\n const $this = $(this);\n const $parent = $this.parent();\n if (!$parent.hasClass('wpstg--show-options')) {\n $parent.addClass('wpstg--show-options');\n $this.text($this.attr('data-txtChoose'));\n } else {\n $parent.removeClass('wpstg--show-options');\n $this.text($this.attr('data-txtOther'));\n }\n })\n .off('click', '.wpstg--modal--backup--import--search-replace--new')\n .on('click', '.wpstg--modal--backup--import--search-replace--new', function(e) {\n e.preventDefault();\n const $container = $(Swal.getContainer()).find('.wpstg--modal--backup--import--search-replace--input--container');\n const total = $container.find('.wpstg--modal--backup--import--search-replace--input-group').length;\n $container.append(that.backups.modal.import.searchReplaceForm.replace(/{i}/g, total));\n })\n .off('click', '.wpstg--modal--backup--import--search-replace--remove')\n .on('click', '.wpstg--modal--backup--import--search-replace--remove', function(e) {\n e.preventDefault();\n $(e.target).closest('.wpstg--modal--backup--import--search-replace--input-group').remove();\n })\n .off('input', '.wpstg--backup--import--search')\n .on('input', '.wpstg--backup--import--search', function() {\n const index = parseInt(this.getAttribute('data-index'));\n if (!isNaN(index)) {\n that.backups.modal.import.data.search[index] = this.value;\n }\n })\n .off('input', '.wpstg--backup--import--replace')\n .on('input', '.wpstg--backup--import--replace', function() {\n const index = parseInt(this.getAttribute('data-index'));\n if (!isNaN(index)) {\n that.backups.modal.import.data.replace[index] = this.value;\n }\n })\n // Other Options\n .off('click', '.wpstg--backup--import--option[data-option]')\n .on('click', '.wpstg--backup--import--option[data-option]', function() {\n const option = this.getAttribute('data-option');\n\n if (option === 'file') {\n $('input[type=\"file\"][name=\"wpstg--backup--import--upload--file\"]').trigger('click');\n return;\n }\n\n if (option === 'upload') {\n that.backups.modal.import.containerFilesystem.hide();\n that.backups.modal.import.containerUpload.show();\n }\n\n if (option !== 'filesystem') {\n return;\n }\n\n that.backups.modal.import.containerUpload.hide();\n const $containerFilesystem = that.backups.modal.import.containerFilesystem;\n $containerFilesystem.show();\n\n fetch(`${ajaxurl}?action=wpstg--backups--import--file-list&_=${Math.random()}&accessToken=${wpstg.accessToken}&nonce=${wpstg.nonce}`)\n .then(handleFetchErrors)\n .then((res) => res.json())\n .then((res) => {\n const $ul = $('.wpstg--modal--backup--import--filesystem ul');\n $ul.empty();\n\n if (!res || isEmpty(res)) {\n $ul.append(`<span id=\"wpstg--backups--import--file-list-empty\">`+ wpstg.i18n.noImportFileFound +`</span><br />`);\n $('.wpstg--modal--backup--import--search-replace--wrapper').hide();\n return;\n }\n\n $ul.append(`<span id=\"wpstg--backups--import--file-list\">`+ wpstg.i18n.selectFileToImport +`</span><br />`);\n res.forEach(function(file, index) {\n $ul.append(`\n<li data-filepath=\"${file.fullPath}\" class=\"wpstg--backups--import--file-list--sigle-item\">\n <ul class=\"wpstg-import-backup-more-info wpstg-import-backup-more-info-` + index + `\">\n <li style=\"font-weight: bold\">${file.backupName}</li>\n <li>Created on: ${file.dateCreatedFormatted}</li>\n <li>Size: ${file.size}</li>\n <li>\n <div class=\"wpstg-import-backup-contains-title\">This backup contains:</div>\n <ul class=\"wpstg-import-backup-contains\">\n ` + (file.isExportingDatabase ? '<li><span class=\"dashicons dashicons-database wpstg--tooltip\"><div class=\\'wpstg--tooltiptext\\'>Database</div></span></li>' : '') + `\n ` + (file.isExportingPlugins ? '<li><span class=\"dashicons dashicons-admin-plugins wpstg--tooltip\"><div class=\\'wpstg--tooltiptext\\'>Plugins</div></span></li>' : '') + `\n ` + (file.isExportingMuPlugins ? '<li><span class=\"dashicons dashicons-plugins-checked wpstg--tooltip\"><div class=\\'wpstg--tooltiptext\\'>Mu-plugins</div></span></li>' : '') + `\n ` + (file.isExportingThemes ? '<li><span class=\"dashicons dashicons-layout wpstg--tooltip\"><div class=\\'wpstg--tooltiptext\\'>Themes</div></span></li>' : '') + `\n ` + (file.isExportingUploads ? '<li><span class=\"dashicons dashicons-images-alt wpstg--tooltip\"><div class=\\'wpstg--tooltiptext\\'>Uploads</div></span></li>' : '') + `\n ` + (file.isExportingOtherWpContentFiles ? '<li><span class=\"dashicons dashicons-admin-generic wpstg--tooltip\"><div class=\\'wpstg--tooltiptext\\'>Other files in wp-content</div></span></li>' : '') + `\n </ul>\n </li>\n <li>Filename: ${file.name}</li>\n </ul>\n</li>\n`);\n });\n return res;\n })\n .catch((e) => showAjaxFatalError(e, '', 'Submit an error report.'))\n ;\n })\n .off('change', 'input[type=\"file\"][name=\"wpstg--backup--import--upload--file\"]')\n .on('change', 'input[type=\"file\"][name=\"wpstg--backup--import--upload--file\"]', function() {\n that.backups.modal.import.setFile(this.files[0] || null);\n })\n .off('change', 'input[type=\"radio\"][name=\"backup_import_file\"]')\n .on('change', 'input[type=\"radio\"][name=\"backup_import_file\"]', function() {\n $('.wpstg--modal--actions .swal2-confirm').show();\n $('.wpstg--modal--actions .swal2-confirm').prop('disabled', false);\n that.backups.modal.import.data.file = this.value;\n })\n // Drag & Drop\n .on('drag dragstart dragend dragover dragenter dragleave drop', '.wpstg--modal--backup--import--upload--container', function(e) {\n e.preventDefault();\n e.stopPropagation();\n })\n .on('dragover dragenter', '.wpstg--modal--backup--import--upload--container', function() {\n $(this).addClass('wpstg--has-dragover');\n })\n .on('dragleave dragend drop', '.wpstg--modal--backup--import--upload--container', function() {\n $(this).removeClass('wpstg--has-dragover');\n })\n .on('drop', '.wpstg--modal--backup--import--upload--container', function(e) {\n // Uploaded a file through the \"Import Backup modal\"\n that.backups.modal.import.setFile(e.originalEvent.dataTransfer.files[0] || null);\n })\n .on('click', '.wpstg--modal--backup--import--filesystem li', function(e) {\n // Selected an existing backup in the Import Backup modal\n const fullPath = $(e.target).closest('.wpstg--backups--import--file-list--sigle-item').data().filepath;\n if (!fullPath.length) {\n alert('Error: Could not get file path.');\n return;\n }\n that.backups.modal.import.data.file = fullPath;\n that.backups.switchModalToConfigure();\n // $('.wpstg--modal--actions .swal2-confirm').prop('disabled', false);\n // that.backups.modal.gotoStart();\n })\n .on('change', '.wpstg-advanced-options-site input[type=\"checkbox\"]', function(e) {\n /*\n * We use a timeout here to simulate an \"afterChange\" event.\n * This allows us to read from the DOM whether the checkbox is checked or not,\n * instead of having to read from the event, which would require a lengthier code\n * to account for all elements we might want to read.\n */\n setTimeout(function(e) {\n // Reset\n document.getElementById('exportUploadsWithoutDatabaseWarning').style.display = 'none';\n\n // Exporting Media Library without Database\n const databaseChecked = document.getElementById('includeDatabaseInBackup').checked;\n const mediaLibraryChecked = document.getElementById('includeMediaLibraryInBackup').checked;\n if (mediaLibraryChecked && !databaseChecked) {\n document.getElementById('exportUploadsWithoutDatabaseWarning').style.display = 'block';\n }\n }, 100);\n })\n ;\n },\n fetchListing(isResetErrors = true) {\n isLoading(true);\n\n if (isResetErrors) {\n resetErrors();\n }\n\n return fetch(`${ajaxurl}?action=wpstg--backups--listing&_=${Math.random()}&accessToken=${wpstg.accessToken}&nonce=${wpstg.nonce}`)\n .then(handleFetchErrors)\n .then((res) => res.json())\n .then((res) => {\n showAjaxFatalError(res, '', 'Submit an error report.');\n cache.get('#wpstg--tab--backup').html(res);\n isLoading(false);\n window.dispatchEvent(new Event('backupListingFinished'));\n return res;\n })\n .catch((e) => showAjaxFatalError(e, '', 'Submit an error report.'))\n ;\n },\n delete() {\n $('#wpstg--tab--backup')\n .off('click', '.wpstg-delete-backup[data-md5]')\n .on('click', '.wpstg-delete-backup[data-md5]', function(e) {\n e.preventDefault();\n resetErrors();\n\n if (!confirm('Are you sure you want to delete this backup?')) {\n return;\n }\n\n isLoading(true);\n cache.get('#wpstg-existing-backups').hide();\n const md5 = this.getAttribute('data-md5');\n that.ajax(\n {\n action: 'wpstg--backups--delete',\n md5: md5,\n accessToken: wpstg.accessToken,\n nonce: wpstg.nonce,\n },\n function(response) {\n showAjaxFatalError(response, '', ' Please submit an error report by using the REPORT ISSUE button.');\n isLoading(false);\n that.backups.fetchListing();\n },\n );\n })\n ;\n\n // Force delete if backup tables do not exist\n // TODO This is bloated, no need extra ID, use existing one?\n $('#wpstg-error-wrapper')\n .off('click', '#wpstg-backup-force-delete')\n .on('click', '#wpstg-backup-force-delete', function(e) {\n e.preventDefault();\n resetErrors();\n isLoading(true);\n const id = this.getAttribute('data-id');\n\n if (!confirm('Do you want to delete this backup ' + id + ' from the listed backups?')) {\n isLoading(false);\n return false;\n }\n\n that.ajax(\n {\n action: 'wpstg--backups--delete',\n id: id,\n accessToken: wpstg.accessToken,\n nonce: wpstg.nonce,\n },\n function(response) {\n showAjaxFatalError(response, '', ' Please submit an error report by using the REPORT ISSUE button.');\n // noinspection JSIgnoredPromiseFromCall\n that.backups.fetchListing();\n isLoading(false);\n },\n );\n })\n ;\n },\n create() {\n const prepareBackup = function(data) {\n WPStaging.ajax(\n {\n action: 'wpstg--backups--prepare-export',\n accessToken: wpstg.accessToken,\n nonce: wpstg.nonce,\n wpstgExportData: data,\n },\n function(response) {\n if (response.success) {\n that.backups.timer.start();\n\n createBackup();\n } else {\n showAjaxFatalError(response.data, '', 'Submit an error report.');\n }\n },\n 'json',\n false,\n 0,\n 1.25,\n );\n };\n const createBackup = function() {\n resetErrors();\n\n if (that.backups.isCancelled) {\n // Swal.close();\n return;\n }\n\n const statusStop = () => {\n clearInterval(that.backups.processInfo.interval);\n that.backups.processInfo.interval = null;\n };\n const status = () => {\n if (that.backups.processInfo.interval !== null) {\n return;\n }\n that.backups.processInfo.interval = setInterval(() => {\n if (true === that.backups.isCancelled) {\n statusStop();\n return;\n }\n\n if (that.backups.status.hasResponse === false) {\n return;\n }\n\n that.backups.status.hasResponse = false;\n fetch(`${ajaxurl}?action=wpstg--backups--status&accessToken=${wpstg.accessToken}&nonce=${wpstg.nonce}`)\n .then((res) => res.json())\n .then((res) => {\n that.backups.status.hasResponse = true;\n if (typeof res === 'undefined') {\n statusStop();\n }\n\n if (that.backups.processInfo.title === res.currentStatusTitle) {\n return;\n }\n\n that.backups.processInfo.title = res.currentStatusTitle;\n const $container = $(Swal.getContainer());\n $container.find('.wpstg--modal--process--title').text(res.currentStatusTitle);\n $container.find('.wpstg--modal--process--percent').text('0');\n })\n .catch((e) => {\n that.backups.status.hasResponse = true;\n showAjaxFatalError(e, '', 'Submit an error report.');\n })\n ;\n }, 5000);\n };\n WPStaging.ajax(\n {\n action: 'wpstg--backups--export',\n accessToken: wpstg.accessToken,\n nonce: wpstg.nonce,\n },\n function(response) {\n if (typeof response === 'undefined') {\n setTimeout(function() {\n createBackup();\n }, wpstg.delayReq);\n return;\n }\n\n that.backups.processResponse(response);\n if (!that.backups.processInfo.interval) {\n status();\n }\n\n if (response.status === false) {\n createBackup();\n } else if (response.status === true) {\n $('#wpstg--progress--status').text('Backup successfully created!');\n that.backups.type = null;\n if (that.backups.messages.shouldWarn()) {\n // noinspection JSIgnoredPromiseFromCall\n that.backups.fetchListing();\n that.backups.logsModal();\n return;\n }\n statusStop();\n Swal.close();\n that.backups.fetchListing()\n .then(() => {\n if (!response.backupMd5) {\n showError('Failed to get backup md5 from response');\n return;\n }\n\n // Wait for fetchListing to populate the DOM with the backup data that we want to read\n let $el = '';\n let timesWaited = 0;\n const intervalWaitForBackupInDom = setInterval(function() {\n timesWaited++;\n $el = $(`.wpstg--backup--download[data-md5=\"${response.backupMd5}\"]`);\n\n // Could not find element, let's try again...\n if (!$el.length) {\n if (timesWaited >= 10) {\n // Bail: We tried too many times and couldn't find.\n clearInterval(intervalWaitForBackupInDom);\n }\n return;\n }\n\n // Found it. No more need for the interval.\n clearInterval(intervalWaitForBackupInDom);\n\n const backupSize = response.hasOwnProperty('backupSize') ? ' (' + response.backupSize + ')' : '';\n\n that.backups.downloadModal({\n id: $el.data('id'),\n url: $el.data('url'),\n title: $el.data('title'),\n titleExport: $el.data('title-export'),\n btnTxtCancel: $el.data('btn-cancel-txt'),\n btnTxtConfirm: $el.data('btn-download-txt') + backupSize,\n });\n $('.wpstg--modal--download--logs--wrapper').show();\n const $logsContainer = $('.wpstg--modal--process--logs');\n that.backups.messages.data.all.forEach((message) => {\n const msgClass = `wpstg--modal--process--msg--${message.type.toLowerCase()}`;\n $logsContainer\n .append(`<p class=\"${msgClass}\">[${message.type}] - [${message.date}] - ${message.message}</p>`)\n ;\n });\n }, 200);\n })\n ;\n } else {\n setTimeout(function() {\n createBackup();\n }, wpstg.delayReq);\n }\n },\n 'json',\n false,\n 0, // Don't retry upon failure\n 1.25,\n );\n };\n\n const $body = $('body');\n\n $body\n .off('click', '.wpstg--tab--toggle')\n .on('click', '.wpstg--tab--toggle', function() {\n const $this = $(this);\n const $target = $($this.attr('data-target'));\n $target.toggle();\n if ($target.is(':visible')) {\n $this.find('span').text('▼');\n } else {\n $this.find('span').text('►');\n }\n })\n .off('change', '[name=\"includedDirectories\\[\\]\"], input#includeDatabaseInBackup, input#includeOtherFilesInWpContent')\n .on('change', '[type=\"checkbox\"][name=\"includedDirectories\\[\\]\"], input#includeDatabaseInBackup, input#includeOtherFilesInWpContent', function() {\n const isExportingAnyDir = $('[type=\"checkbox\"][name=\"includedDirectories\\[\\]\"]:checked').length > 0;\n const isExportingDatabase = $('input#includeDatabaseInBackup:checked').length === 1;\n const isExportingOtherFilesInWpContent = $('input#includeOtherFilesInWpContent:checked').length === 1;\n if (!isExportingAnyDir && !isExportingDatabase && !isExportingOtherFilesInWpContent) {\n $('.swal2-confirm').prop('disabled', true);\n } else {\n $('.swal2-confirm').prop('disabled', false);\n }\n })\n ;\n\n // Add backup name and notes\n $('#wpstg--tab--backup')\n .off('click', '#wpstg-new-backup')\n .on('click', '#wpstg-new-backup', async function(e) {\n resetErrors();\n e.preventDefault();\n that.backups.isCancelled = false;\n\n if (!that.backups.modal.create.html || !that.backups.modal.create.confirmBtnTxt) {\n const $newBackupModal = $('#wpstg--modal--backup--new');\n const html = $newBackupModal.html();\n const btnTxt = $newBackupModal.attr('data-confirmButtonText');\n that.backups.modal.create.html = html || null;\n that.backups.modal.create.confirmBtnTxt = btnTxt || null;\n $newBackupModal.remove();\n }\n\n const {value: formValues} = await Swal.fire({\n title: '',\n html: that.backups.modal.create.html,\n focusConfirm: false,\n confirmButtonText: that.backups.modal.create.confirmBtnTxt,\n showCancelButton: true,\n preConfirm: () => {\n const container = Swal.getContainer();\n\n return {\n name: container.querySelector('input[name=\"backup_name\"]').value || null,\n isExportingPlugins: container.querySelector('#includePluginsInBackup:checked') !== null,\n isExportingMuPlugins: container.querySelector('#includeMuPluginsInBackup:checked') !== null,\n isExportingThemes: container.querySelector('#includeThemesInBackup:checked') !== null,\n isExportingUploads: container.querySelector('#includeMediaLibraryInBackup:checked') !== null,\n isExportingOtherWpContentFiles: container.querySelector('#includeOtherFilesInWpContent:checked') !== null,\n isExportingDatabase: container.querySelector('#includeDatabaseInBackup:checked') !== null,\n };\n },\n });\n\n if (!formValues) {\n return;\n }\n\n that.backups.process({\n execute: () => {\n that.backups.messages.reset();\n prepareBackup(formValues);\n },\n });\n })\n ;\n },\n switchModalToConfigure() {\n that.backups.modal.import.containerUpload.hide();\n that.backups.modal.import.containerFilesystem.hide();\n that.backups.modal.import.containerConfigure.show();\n },\n // Edit backups name and notes\n edit() {\n $('#wpstg--tab--backup')\n .off('click', '.wpstg--backup--edit[data-md5]')\n .on('click', '.wpstg--backup--edit[data-md5]', async function(e) {\n e.preventDefault();\n\n const $this = $(this);\n const name = $this.data('name');\n const notes = $this.data('notes');\n\n const {value: formValues} = await Swal.fire({\n title: '',\n html: `\n <label id=\"wpstg-backup-edit-name\">Backup Name</label>\n <input id=\"wpstg-backup-edit-name-input\" class=\"swal2-input\" value=\"${name}\">\n <label>Additional Notes</label>\n <textarea id=\"wpstg-backup-edit-notes-textarea\" class=\"swal2-textarea\">${notes}</textarea>\n `,\n focusConfirm: false,\n confirmButtonText: 'Update Backup',\n showCancelButton: true,\n preConfirm: () => ({\n name: document.getElementById('wpstg-backup-edit-name-input').value || null,\n notes: document.getElementById('wpstg-backup-edit-notes-textarea').value || null,\n }),\n });\n\n if (!formValues) {\n return;\n }\n\n that.ajax(\n {\n action: 'wpstg--backups--edit',\n accessToken: wpstg.accessToken,\n nonce: wpstg.nonce,\n md5: $this.data('md5'),\n name: formValues.name,\n notes: formValues.notes,\n },\n function(response) {\n showAjaxFatalError(response, '', 'Submit an error report.');\n // noinspection JSIgnoredPromiseFromCall\n that.backups.fetchListing();\n },\n );\n })\n ;\n },\n cancel() {\n that.backups.timer.stop();\n that.backups.isCancelled = true;\n Swal.close();\n setTimeout(() => that.ajax(\n {\n action: 'wpstg--backups--cancel',\n accessToken: wpstg.accessToken,\n nonce: wpstg.nonce,\n type: that.backups.type,\n },\n function(response) {\n showAjaxFatalError(response, '', 'Submit an error report.');\n },\n ), 500);\n },\n /**\n * If process.execute exists, process.data and process.onResponse is not used\n * process = { data: {}, onResponse: (resp) => {}, onAfterClose: () => {}, execute: () => {}, isShowCancelButton: bool }\n * @param {object} process\n */\n process(process) {\n if (typeof process.execute !== 'function' && (!process.data || !process.onResponse)) {\n Swal.close();\n showError('process.data and / or process.onResponse is not set');\n return;\n }\n\n // TODO move to backend and get the contents as xhr response?\n if (!that.backups.modal.process.html || !that.backups.modal.process.cancelBtnTxt) {\n const $modal = $('#wpstg--modal--backup--process');\n const html = $modal.html();\n const btnTxt = $modal.attr('data-cancelButtonText');\n that.backups.modal.process.html = html || null;\n that.backups.modal.process.cancelBtnTxt = btnTxt || null;\n $modal.remove();\n }\n\n $('body')\n .off('click', '.wpstg--modal--process--logs--tail')\n .on('click', '.wpstg--modal--process--logs--tail', function(e) {\n e.preventDefault();\n const container = Swal.getContainer();\n const $logs = $(container).find('.wpstg--modal--process--logs');\n $logs.toggle();\n if ($logs.is(':visible')) {\n container.childNodes[0].style.width = '100%';\n container.style['z-index'] = 9999;\n } else {\n container.childNodes[0].style.width = '600px';\n }\n })\n ;\n\n process.isShowCancelButton = false !== process.isShowCancelButton;\n\n that.backups.modal.process.modal = Swal.mixin({\n customClass: {\n cancelButton: 'wpstg--btn--cancel wpstg-blue-primary wpstg-link-btn',\n content: 'wpstg--process--content',\n },\n buttonsStyling: false,\n }).fire({\n html: that.backups.modal.process.html,\n cancelButtonText: that.backups.modal.process.cancelBtnTxt,\n showCancelButton: process.isShowCancelButton,\n showConfirmButton: false,\n allowOutsideClick: false,\n allowEscapeKey: false,\n width: 600,\n onRender: () => {\n const _btnCancel = Swal.getContainer().getElementsByClassName('swal2-cancel wpstg--btn--cancel')[0];\n const btnCancel = _btnCancel.cloneNode(true);\n _btnCancel.parentNode.replaceChild(btnCancel, _btnCancel);\n\n btnCancel.addEventListener('click', function(e) {\n if (confirm('Are You Sure? This will cancel the process!')) {\n Swal.close();\n }\n });\n\n if (typeof process.execute === 'function') {\n process.execute();\n return;\n }\n\n if (!process.data || !process.onResponse) {\n Swal.close();\n showError('process.data and / or process.onResponse is not set');\n return;\n }\n\n that.ajax(process.data, process.onResponse);\n },\n onAfterClose: () => typeof process.onAfterClose === 'function' && process.onAfterClose(),\n onClose: () => {\n that.backups.cancel();\n },\n });\n },\n processResponse(response, useTitle) {\n if (response === null) {\n Swal.close();\n showError('Invalid Response; null');\n throw new Error(`Invalid Response; ${response}`);\n }\n\n const $container = $(Swal.getContainer());\n const title = () => {\n if ((response.title || response.statusTitle) && useTitle === true) {\n $container.find('.wpstg--modal--process--title').text(response.title || response.statusTitle);\n }\n };\n const percentage = () => {\n if (response.percentage) {\n $container.find('.wpstg--modal--process--percent').text(response.percentage);\n }\n };\n const logs = () => {\n if (!response.messages) {\n return;\n }\n const $logsContainer = $container.find('.wpstg--modal--process--logs');\n const stoppingTypes = [\n that.backups.messages.ERROR,\n that.backups.messages.CRITICAL,\n ];\n const appendMessage = (message) => {\n if (Array.isArray(message)) {\n for (const item of message) {\n appendMessage(item);\n }\n return;\n }\n const msgClass = `wpstg--modal--process--msg--${message.type.toLowerCase()}`;\n $logsContainer.append(`<p class=\"${msgClass}\">[${message.type}] - [${message.date}] - ${message.message}</p>`);\n\n if (stoppingTypes.includes(message.type.toLowerCase())) {\n that.backups.cancel();\n setTimeout(that.backups.logsModal, 500);\n }\n };\n for (const message of response.messages) {\n if (!message) {\n continue;\n }\n that.backups.messages.addMessage(message);\n appendMessage(message);\n }\n\n if ($logsContainer.is(':visible')) {\n $logsContainer.scrollTop($logsContainer[0].scrollHeight);\n }\n\n if (!that.backups.messages.shouldWarn()) {\n return;\n }\n\n const $btnShowLogs = $container.find('.wpstg--modal--process--logs--tail');\n $btnShowLogs.html($btnShowLogs.attr('data-txt-bad'));\n\n $btnShowLogs\n .find('.wpstg--modal--logs--critical-count')\n .text(that.backups.messages.countByType(that.backups.messages.CRITICAL))\n ;\n\n $btnShowLogs\n .find('.wpstg--modal--logs--error-count')\n .text(that.backups.messages.countByType(that.backups.messages.ERROR))\n ;\n\n $btnShowLogs\n .find('.wpstg--modal--logs--warning-count')\n .text(that.backups.messages.countByType(that.backups.messages.WARNING))\n ;\n };\n\n title();\n percentage();\n logs();\n\n if (response.status === true && response.job_done === true) {\n that.backups.timer.stop();\n that.backups.isCancelled = true;\n }\n },\n requestData(notation, data) {\n const obj = {};\n const keys = notation.split('.');\n const lastIndex = keys.length - 1;\n keys.reduce((accumulated, current, index) => {\n return accumulated[current] = index >= lastIndex ? data : {};\n }, obj);\n return obj;\n },\n logsModal() {\n Swal.fire({\n html: `<div class=\"wpstg--modal--error--logs\" style=\"display:block\"></div><div class=\"wpstg--modal--process--logs\" style=\"display:block\"></div>`,\n width: '95%',\n onRender: () => {\n const $container = $(Swal.getContainer());\n $container[0].style['z-index'] = 9999;\n\n const $logsContainer = $container.find('.wpstg--modal--process--logs');\n const $errorContainer = $container.find('.wpstg--modal--error--logs');\n const $translations = $('#wpstg--js--translations');\n const messages = that.backups.messages;\n const title = $translations.attr('data-modal-logs-title')\n .replace('{critical}', messages.countByType(messages.CRITICAL))\n .replace('{errors}', messages.countByType(messages.ERROR))\n .replace('{warnings}', messages.countByType(messages.WARNING))\n ;\n\n $errorContainer.before(`<h3>${title}</h3>`);\n const warnings = [\n that.backups.messages.CRITICAL,\n that.backups.messages.ERROR,\n that.backups.messages.WARNING,\n ];\n\n if (!that.backups.messages.shouldWarn()) {\n $errorContainer.hide();\n }\n\n for (const message of messages.data.all) {\n const msgClass = `wpstg--modal--process--msg--${message.type.toLowerCase()}`;\n // TODO RPoC\n if (warnings.includes(message.type)) {\n $errorContainer.append(\n `<p class=\"${msgClass}\">[${message.type}] - [${message.date}] - ${message.message}</p>`,\n );\n }\n $logsContainer.append(\n `<p class=\"${msgClass}\">[${message.type}] - [${message.date}] - ${message.message}</p>`,\n );\n }\n },\n onOpen: (container) => {\n const $logsContainer = $(container).find('.wpstg--modal--process--logs');\n $logsContainer.scrollTop($logsContainer[0].scrollHeight);\n },\n });\n },\n downloadModal({title = null, titleExport = null, id = null, url = null, btnTxtCancel = 'Cancel', btnTxtConfirm = 'Download'}) {\n if (null === that.backups.modal.download.html) {\n const $el = $('#wpstg--modal--backup--download');\n that.backups.modal.download.html = $el.html();\n $el.remove();\n }\n\n const exportModal = () => Swal.fire({\n html: `<h2>${titleExport}</h2><span class=\"wpstg-loader\"></span>`,\n showCancelButton: false,\n showConfirmButton: false,\n onRender: () => {\n that.ajax(\n {\n action: 'wpstg--backups--export',\n accessToken: wpstg.accessToken,\n nonce: wpstg.nonce,\n id,\n },\n function(response) {\n if (!response || !response.success || !response.data || response.data.length < 1) {\n return;\n }\n\n const a = document.createElement('a');\n a.style.display = 'none';\n a.href = response.data;\n document.body.appendChild(a);\n a.click();\n document.body.removeChild(a);\n\n Swal.close();\n },\n );\n },\n });\n\n Swal.mixin({\n customClass: {\n cancelButton: 'wpstg--btn--cancel wpstg-blue-primary wpstg-link-btn',\n confirmButton: 'wpstg--btn--confirm wpstg-blue-primary wpstg-button wpstg-link-btn',\n actions: 'wpstg--modal--actions',\n },\n buttonsStyling: false,\n })\n .fire({\n icon: 'success',\n html: that.backups.modal.download.html.replace('{title}', title).replace('{btnTxtLog}', 'Show Logs'),\n cancelButtonText: btnTxtCancel,\n confirmButtonText: btnTxtConfirm,\n showCancelButton: true,\n showConfirmButton: true,\n })\n .then((isConfirm) => {\n if (!isConfirm || !isConfirm.value) {\n return;\n }\n\n if (url && url.length > 0) {\n window.location.href = url;\n return;\n }\n\n exportModal();\n })\n ;\n },\n importModal() {\n const importSiteBackup = (data) => {\n resetErrors();\n\n if (that.backups.isCancelled) {\n // Swal.close();\n return;\n }\n\n that.backups.timer.start();\n\n const statusStop = () => {\n clearInterval(that.backups.processInfo.interval);\n that.backups.processInfo.interval = null;\n };\n const status = () => {\n if (that.backups.processInfo.interval !== null) {\n return;\n }\n that.backups.processInfo.interval = setInterval(() => {\n if (true === that.backups.isCancelled) {\n statusStop();\n return;\n }\n\n if (that.backups.status.hasResponse === false) {\n return;\n }\n\n that.backups.status.hasResponse = false;\n fetch(`${ajaxurl}?action=wpstg--backups--status&process=restore&accessToken=${wpstg.accessToken}&nonce=${wpstg.nonce}`)\n .then((res) => res.json())\n .then((res) => {\n that.backups.status.hasResponse = true;\n if (typeof res === 'undefined') {\n statusStop();\n }\n\n if (that.backups.processInfo.title === res.currentStatusTitle) {\n return;\n }\n\n that.backups.processInfo.title = res.currentStatusTitle;\n const $container = $(Swal.getContainer());\n $container.find('.wpstg--modal--process--title').text(res.currentStatusTitle);\n $container.find('.wpstg--modal--process--percent').text('0');\n })\n .catch((e) => {\n that.backups.status.hasResponse = true;\n showAjaxFatalError(e, '', 'Submit an error report.');\n })\n ;\n }, 5000);\n };\n\n WPStaging.ajax(\n {\n action: 'wpstg--backups--import',\n accessToken: wpstg.accessToken,\n nonce: wpstg.nonce,\n },\n function(response) {\n if (typeof response === 'undefined') {\n setTimeout(function() {\n importSiteBackup(data);\n }, wpstg.delayReq);\n return;\n }\n\n that.backups.processResponse(response, true);\n if (!that.backups.processInfo.interval) {\n status();\n }\n\n if (response.status === false) {\n importSiteBackup(data);\n } else if (response.status === true) {\n $('#wpstg--progress--status').text('Backup successfully imported!');\n that.backups.type = null;\n if (that.backups.messages.shouldWarn()) {\n // noinspection JSIgnoredPromiseFromCall\n that.backups.fetchListing();\n that.backups.logsModal();\n return;\n }\n statusStop();\n const logEntries = $('.wpstg--modal--process--logs').get(1).innerHTML;\n const html = '<div class=\"wpstg--modal--process--logs\">' + logEntries + '</div>';\n const issueFound = html.includes('wpstg--modal--process--msg--warning') || html.includes('wpstg--modal--process--msg--error') ? 'Issues(s) found! ' : '';\n // var errorMessage = html.includes('wpstg--modal--process--msg--error') ? 'Errors(s) found! ' : '';\n // var Message = warningMessage + errorMessage;\n\n // Swal.close();\n Swal.fire({\n icon: 'success',\n title: 'Finished',\n html: 'System imported from backup. <br/><span class=\"wpstg--modal--process--msg-found\">' + issueFound + '</span><button class=\"wpstg--modal--process--logs--tail\" data-txt-bad=\"\">Show Logs</button><br/>' + html,\n },\n );\n\n // noinspection JSIgnoredPromiseFromCall\n that.backups.fetchListing();\n } else {\n setTimeout(function() {\n importSiteBackup(data);\n }, wpstg.delayReq);\n }\n },\n 'json',\n false,\n 0, // Don't retry upon failure\n 1.25,\n );\n };\n\n if (!that.backups.modal.import.html) {\n const $modal = $('#wpstg--modal--backup--import');\n\n // Search & Replace Form\n const $form = $modal.find('.wpstg--modal--backup--import--search-replace--input--container');\n that.backups.modal.import.searchReplaceForm = $form.html();\n $form.find('.wpstg--modal--backup--import--search-replace--input-group').remove();\n $form.html(that.backups.modal.import.searchReplaceForm.replace(/{i}/g, 0));\n\n that.backups.modal.import.html = $modal.html();\n that.backups.modal.import.baseDirectory = $modal.attr('data-baseDirectory');\n that.backups.modal.import.btnTxtNext = $modal.attr('data-nextButtonText');\n that.backups.modal.import.btnTxtConfirm = $modal.attr('data-confirmButtonText');\n that.backups.modal.import.btnTxtCancel = $modal.attr('data-cancelButtonText');\n $modal.remove();\n }\n\n that.backups.modal.import.data.search = [];\n that.backups.modal.import.data.replace = [];\n\n const $btnConfirm = null;\n Swal\n .mixin({\n customClass: {\n confirmButton: 'wpstg--btn--confirm wpstg-blue-primary wpstg-button wpstg-link-btn',\n cancelButton: 'wpstg--btn--cancel wpstg-blue-primary wpstg-link-btn',\n actions: 'wpstg--modal--actions',\n },\n buttonsStyling: false,\n // progressSteps: ['1', '2']\n })\n .queue([{\n html: that.backups.modal.import.html,\n confirmButtonText: that.backups.modal.import.btnTxtNext,\n showCancelButton: false,\n showConfirmButton: true,\n showLoaderOnConfirm: true,\n width: 650,\n onRender() {\n // $('.wpstg--modal--actions .swal2-confirm').hide();\n\n // todo: hide this again\n $('.wpstg--modal--actions .swal2-confirm').show();\n $('.wpstg--modal--actions .swal2-confirm').prop('disabled', false);\n\n that.backups.modal.import.containerUpload = $('.wpstg--modal--backup--import--upload');\n that.backups.modal.import.containerFilesystem = $('.wpstg--modal--backup--import--filesystem');\n that.backups.modal.import.containerConfigure = $('.wpstg--modal--backup--import--configure');\n },\n preConfirm() {\n const body = new FormData;\n body.append('accessToken', wpstg.accessToken);\n body.append('nonce', wpstg.nonce);\n body.append('filePath', that.backups.modal.import.data.file);\n\n that.backups.modal.import.data.search.forEach((item, index) => {\n body.append(`search[${index}]`, item);\n });\n that.backups.modal.import.data.replace.forEach((item, index) => {\n body.append(`replace[${index}]`, item);\n });\n\n return fetch(`${ajaxurl}?action=wpstg--backups--import--file-info`, {\n method: 'POST',\n body,\n }).then(handleFetchErrors)\n .then((res) => res.json())\n .then((html) => {\n return Swal.insertQueueStep({\n html: html,\n confirmButtonText: that.backups.modal.import.btnTxtConfirm,\n cancelButtonText: that.backups.modal.import.btnTxtCancel,\n showCancelButton: true,\n });\n })\n .catch((e) => showAjaxFatalError(e, '', 'Submit an error report.'))\n ;\n },\n }])\n .then((res) => {\n if (!res || !res.value || !res.value[1] || res.value[1] !== true) {\n return;\n }\n\n that.backups.isCancelled = false;\n const data = that.backups.modal.import.data;\n data['file'] = that.backups.modal.import.baseDirectory + data['file'];\n\n WPStaging.ajax(\n {\n action: 'wpstg--backups--prepare-import',\n accessToken: wpstg.accessToken,\n nonce: wpstg.nonce,\n wpstgImportData: data,\n },\n function(response) {\n if (response.success) {\n that.backups.process({\n execute: () => {\n that.backups.messages.reset();\n importSiteBackup(data);\n },\n });\n } else {\n showAjaxFatalError(response.data, '', 'Submit an error report.');\n }\n },\n 'json',\n false,\n 0,\n 1.25,\n );\n });\n },\n };\n\n window.addEventListener('backupListingFinished', function() {\n fetch(`${ajaxurl}?action=wpstg--backups--import--file-list&_=${Math.random()}&accessToken=${wpstg.accessToken}&nonce=${wpstg.nonce}&withTemplate=true`)\n .then(handleFetchErrors)\n .then((res) => res.json())\n .then((res) => {\n const $ul = $('.wpstg-backup-list ul');\n $ul.empty();\n $ul.html(res);\n })\n .catch((e) => showAjaxFatalError(e, '', 'Submit an error report.'))\n ;\n });\n\n return that;\n})(jQuery);\n\njQuery(document).ready(function() {\n WPStaging.init();\n // This is necessary to make WPStaging var accessibile in WP Staging PRO js script\n window.WPStaging = WPStaging;\n});\n\n/**\n * Report Issue modal\n */\njQuery(document).ready(function($) {\n $('#wpstg-report-issue-button').on('click', function(e) {\n $('.wpstg-report-issue-form').toggleClass('wpstg-report-show');\n e.preventDefault();\n });\n\n $('body').on('click', '#wpstg-backups-report-issue-button', function(e) {\n $('.wpstg-report-issue-form').toggleClass('wpstg-report-show');\n e.preventDefault();\n });\n\n $('#wpstg-report-cancel').on('click', function(e) {\n $('.wpstg-report-issue-form').removeClass('wpstg-report-show');\n e.preventDefault();\n });\n\n /*\n * Close Success Modal\n */\n\n $('body').on('click', '#wpstg-success-button', function(e) {\n e.preventDefault();\n $('.wpstg-report-issue-form').removeClass('wpstg-report-show');\n });\n\n function sendIssueReport(button, forceSend = 'false') {\n const spinner = button.next();\n const email = $('.wpstg-report-email').val();\n const hosting_provider = $('.wpstg-report-hosting-provider').val();\n const message = $('.wpstg-report-description').val();\n const syslog = $('.wpstg-report-syslog').is(':checked');\n const terms = $('.wpstg-report-terms').is(':checked');\n\n button.attr('disabled', true);\n spinner.css('visibility', 'visible');\n\n $.ajax({\n url: ajaxurl,\n type: 'POST',\n dataType: 'json',\n async: true,\n data: {\n 'action': 'wpstg_send_report',\n 'accessToken': wpstg.accessToken,\n 'nonce': wpstg.nonce,\n 'wpstg_email': email,\n 'wpstg_provider': hosting_provider,\n 'wpstg_message': message,\n 'wpstg_syslog': +syslog,\n 'wpstg_terms': +terms,\n 'wpstg_force_send': forceSend,\n },\n }).done(function(data) {\n button.attr('disabled', false);\n spinner.css('visibility', 'hidden');\n\n if (data.errors.length > 0) {\n $('.wpstg-report-issue-form .wpstg-message').remove();\n\n let errorMessage = $('<div />').addClass('wpstg-message wpstg-error-message');\n $.each(data.errors, function(key, value) {\n if (value.status === 'already_submitted') {\n errorMessage = '';\n Swal.fire({\n title: '',\n customClass: {\n container: 'wpstg-issue-resubmit-confirmation',\n },\n icon: 'warning',\n html: value.message,\n showCloseButton: true,\n showCancelButton: true,\n focusConfirm: false,\n confirmButtonText: 'Yes',\n cancelButtonText: 'No',\n }).then((result) => {\n if (result.isConfirmed) {\n sendIssueReport(button, 'true');\n }\n });\n } else {\n errorMessage.append('<p>' + value + '</p>');\n }\n });\n\n $('.wpstg-report-issue-form').prepend(errorMessage);\n } else {\n const successMessage = $('<div />').addClass('wpstg-message wpstg-success-message');\n successMessage.append('<p>Thanks for submitting your request! You should receive an auto reply mail with your ticket ID immediately for confirmation!<br><br>If you do not get that mail please contact us directly at <strong>support@wp-staging.com</strong></p>');\n\n $('.wpstg-report-issue-form').html(successMessage);\n $('.wpstg-success-message').append('<div style=\"float:right;margin-top:10px;\"><a id=\"wpstg-success-button\" href=\"#\">Close</a></div>');\n\n // Hide message\n setTimeout(function() {\n $('.wpstg-report-issue-form').removeClass('wpstg-report-active');\n }, 2000);\n }\n });\n }\n\n $('#wpstg-report-submit').on('click', function(e) {\n const self = $(this);\n sendIssueReport(self, 'false');\n e.preventDefault();\n });\n\n // Open/close actions drop down menu\n $(document).on('click', '.wpstg-dropdown>.wpstg-dropdown-toggler', function(e) {\n e.preventDefault();\n $(e.target).next('.wpstg-dropdown-menu').toggleClass('shown');\n });\n\n // Close action drop down menu if clicked anywhere outside\n document.addEventListener('click', function(event) {\n const isClickInside = event.target.closest('.wpstg-dropdown-toggler');\n if (!isClickInside) {\n const dropDown = document.getElementsByClassName('wpstg-dropdown-menu');\n for (let i = 0; i < dropDown.length; i++) {\n dropDown[i].classList.remove('shown');\n }\n }\n });\n});\n"],"names":["qs","selector","document","querySelector","all","querySelectorAll","addEvent","parent","evt","handler","addEventListener","event","target","matches","closest","slideDown","element","duration","style","display","overflow","height","offsetHeight","transitionProperty","transitionDuration","setTimeout","window","removeProperty","slideUp","getNextSibling","sibling","nextElementSibling","getParents","result","parentElement","push","WpstgCloneStaging","pageWrapperId","wpstgObject","wpstg","pageWrapper","dom","enableButtonId","enableAction","notyf","Notyf","position","x","y","dismissible","types","type","background","icon","init","addEvents","sendRequest","action","fetch","ajaxUrl","method","credentials","body","URLSearchParams","accessToken","nonce","headers","then","response","ok","json","Promise","reject","data","success","location","reload","message","error","i18n","console","warn","WpstgDirectoryNavigation","directoryListingSelector","directoryListingContainer","dirCheckboxSelector","dirExpandSelector","unselectAllDirsSelector","selectDefaultDirsSelector","fetchChildrenAction","currentCheckboxElement","currentParentDiv","currentLoader","existingExcludes","excludedDirectories","isDefaultSelected","log","preventDefault","toggleDirExpand","unselectAll","selectDefault","parseExcludes","previousSibling","getAttribute","dirPath","value","isChecked","checked","forceDefault","setAttribute","dirContainer","createElement","classList","add","innerHTML","JSON","parse","directoryListing","appendChild","alert","getExcludedDirectories","forEach","isParentExcluded","exclude","isExcludeScanned","join","settings","directorySeparator","path","isParentAlreadyExcluded","dir","startsWith","getExtraDirectoriesRootOnly","extraDirectories","extraDirectoriesTextArea","extraCustomDirectories","split","concat","length","WpstgExcludeFilters","excludeFilterContainerSelector","excludeContainer","excludeTableBody","addFileSizeExclude","addFileExtExclude","addFileNameExclude","addDirNameExclude","clearExcludes","removeExclude","addExcludeRuleRow","templateName","excludeRowTemplate","clone","content","cloneNode","excludeRow","e","removeChild","trim","getExcludeFilters","globExcludes","sizeExcludes","sizeCompares","sizeSizes","sizeByte","Object","entries","key","sizeInput","extensionInputs","ext","cleanStringForGlob","fileNamesPos","fileNames","fileInput","fileName","dirNamesPos","dirNames","dirInput","dirName","filter","onlyUnique","index","self","indexOf","replace","WpstgModal","confirmAction","show","swalOptions","additionalParams","callback","Swal","fire","triggerConfirmAction","assign","WpstgResetModal","cloneID","workflowSelector","fetchExcludeSettingsAction","modalErrorAction","workflow","resetButtonClass","resetModalContainerClass","resetTabSelector","directoryNavigator","excludeFilters","isAllTablesChecked","resetModalContainer","toggleContent","selectDefaultTables","toggleTableSelection","toggleDirectoryNavigation","updateDirectorySelection","contentId","tabTriangle","isCollapsed","contains","transform","remove","showModal","swalPromise","loadModal","fetchCloneExcludes","title","html","getAjaxLoader","width","focusConfirm","customClass","confirmButton","container","confirmButtonText","resetClone","showCancelButton","job","errorModal","modal","renderError","getDirectoryNavigator","wpstgIcon","cbElement","subDirectories","parElem","i","children","options","multisitePattern","tblprefix","singleSitePattern","option","name","isMultisite","match","removeAttribute","WPStaging","$","that","isCancelled","isFinished","getLogs","time","executionTime","progressBar","cloneExcludeFilters","cache","elements","ajaxSpinner","get","inArray","jQuery","refresh","showError","css","text","removeClass","hide","warnIfClosingDuringProcess","returnValue","isEmpty","obj","prop","hasOwnProperty","showAjaxFatalError","prependMessage","appendMessage","removeEventListener","handleFetchErrors","status","statusText","resetErrors","slugify","url","toString","toLowerCase","normalize","$workFlow","isAllChecked","urlSpinner","ajaxurl","timer","devicePixelRatio","on","each","attr","$this","siblings","slideToggle","$directory","parents","find","addClass","getElementById","clearInterval","ajax","removeAttr","slug","$targetDir","$targetUri","uri","val","validateTargetHost","after","cloneActions","the_domain","reg","test","confirm","append","cancelCloning","startCloning","cancelCloningUpdate","restart","$existingClones","animate","scrollTop","offset","top","deleteClone","jsonResponse","tryParseJson","showErrorModal","checkDiskSpace","switchStep","resetModal","promise","dirNavigator","exclFilters","includedTables","getIncludedTables","excludeSizeRules","encodeURIComponent","sizes","excludeGlobRules","globs","dataType","showErrors","tryCount","incrementRatio","retryLimit","retryTimeout","parseInt","isNaN","Date","now","xhr","textStatus","errorThrown","errorCode","statusCode","stepButtons","focus","onlyUpdateMessage","is","verifyExternalDatabase","proceedCloning","loadOverview","getExcludedTables","excludedTables","databaseUser","databasePassword","databaseServer","databaseDatabase","error_type","render","checks","production","staging","getCloningData","getTime","rules","databasePrefix","cloneDir","cloneHostname","emailsAllowed","uploadsSymlinked","cleanPluginsThemes","cleanUploadsDir","sendCloningAjax","object","excludeOptions","tabs","$section","toggleClass","hasClass","deleteDir","logscroll","$div","scrollHeight","constructor","Array","date","usedspace","mainTabs","$wrapper","$menuItems","$contents","not","backups","dispatchEvent","Event","isLoading","convertSeconds","setInterval","seconds","setSeconds","toISOString","substr","start","processing","delayReq","last_msg","job_done","finish","$link1","$link","msg","cloneResetComplete","cloneUpdateComplete","percentage","toFixed","step","processInfo","interval","create","confirmBtnTxt","process","cancelBtnTxt","download","btnTxtNext","btnTxtConfirm","btnTxtCancel","searchReplaceForm","file","containerUpload","containerFilesystem","setFile","upload","toUnit","bytes","Math","floor","pow","size","baseDirectory","search","messages","WARNING","ERROR","INFO","DEBUG","CRITICAL","info","critical","warning","debug","shouldWarn","countByType","addMessage","isArray","item","reset","totalSeconds","prettify","stop","reader","iop","uploadInfo","isShow","$containerUpload","$containerUploader","FileReader","sendChunk","startsAt","isReset","endsAt","blob","slice","onloadend","readyState","DONE","FormData","res","writtenBytes","percent","switchModalToConfigure","readAsDataURL","hasResponse","reTryAfter","edit","fetchListing","href","downloadModal","titleExport","id","importModal","off","$parent","$container","getContainer","total","trigger","$containerFilesystem","random","$ul","empty","noImportFileFound","selectFileToImport","fullPath","backupName","dateCreatedFormatted","isExportingDatabase","isExportingPlugins","isExportingMuPlugins","isExportingThemes","isExportingUploads","isExportingOtherWpContentFiles","files","stopPropagation","originalEvent","dataTransfer","filepath","databaseChecked","mediaLibraryChecked","isResetErrors","md5","prepareBackup","wpstgExportData","createBackup","statusStop","currentStatusTitle","processResponse","logsModal","close","backupMd5","$el","timesWaited","intervalWaitForBackupInDom","backupSize","$logsContainer","msgClass","$body","$target","toggle","isExportingAnyDir","isExportingOtherFilesInWpContent","$newBackupModal","btnTxt","preConfirm","formValues","execute","containerConfigure","notes","cancel","onResponse","$modal","$logs","childNodes","isShowCancelButton","mixin","cancelButton","buttonsStyling","cancelButtonText","showConfirmButton","allowOutsideClick","allowEscapeKey","onRender","_btnCancel","getElementsByClassName","btnCancel","parentNode","replaceChild","onAfterClose","onClose","useTitle","Error","statusTitle","logs","stoppingTypes","includes","$btnShowLogs","requestData","notation","keys","lastIndex","reduce","accumulated","current","$errorContainer","$translations","before","warnings","onOpen","exportModal","a","click","actions","isConfirm","importSiteBackup","logEntries","issueFound","$form","queue","showLoaderOnConfirm","insertQueueStep","wpstgImportData","ready","sendIssueReport","button","forceSend","spinner","next","email","hosting_provider","syslog","terms","async","done","errors","errorMessage","showCloseButton","isConfirmed","prepend","successMessage","isClickInside","dropDown"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAAA;EACA;EACA;;EAEA;EACA;EACA;EACA;EACO,SAASA,EAAT,CAAYC,QAAZ,EAAsB;EAC3B,SAAOC,QAAQ,CAACC,aAAT,CAAuBF,QAAvB,CAAP;EACD;EAED;EACA;EACA;EACA;;EACO,SAASG,GAAT,CAAaH,QAAb,EAAuB;EAC5B,SAAOC,QAAQ,CAACG,gBAAT,CAA0BJ,QAA1B,CAAP;EACD;EAED;EACA;EACA;;EACO,SAASK,QAAT,CAAkBC,MAAlB,EAA0BC,GAA1B,EAA+BP,QAA/B,EAAyCQ,OAAzC,EAAkD;EACvDF,EAAAA,MAAM,CAACG,gBAAP,CAAwBF,GAAxB,EAA6B,UAASG,KAAT,EAAgB;EAC3C,QAAIA,KAAK,CAACC,MAAN,CAAaC,OAAb,CAAqBZ,QAAQ,GAAG,IAAX,GAAkBA,QAAlB,GAA6B,IAAlD,CAAJ,EAA6D;EAC3DQ,MAAAA,OAAO,CAACE,KAAK,CAACC,MAAN,CAAaE,OAAb,CAAqBb,QAArB,CAAD,EAAiCU,KAAjC,CAAP;EACD;EACF,GAJD,EAIG,KAJH;EAKD;EAEM,SAASI,SAAT,CAAmBC,OAAnB,EAA4BC,QAA5B,EAA4C;EAAA,MAAhBA,QAAgB;EAAhBA,IAAAA,QAAgB,GAAL,GAAK;EAAA;;EACjDD,EAAAA,OAAO,CAACE,KAAR,CAAcC,OAAd,GAAwB,OAAxB;EACAH,EAAAA,OAAO,CAACE,KAAR,CAAcE,QAAd,GAAyB,QAAzB;EACA,MAAMC,MAAM,GAAGL,OAAO,CAACM,YAAvB;EACAN,EAAAA,OAAO,CAACE,KAAR,CAAcG,MAAd,GAAuB,KAAvB;EACAL,EAAAA,OAAO,CAACE,KAAR,CAAcK,kBAAd,GAAmC,QAAnC;EACAP,EAAAA,OAAO,CAACE,KAAR,CAAcM,kBAAd,GAAmCP,QAAQ,GAAG,IAA9C;EACAQ,EAAAA,UAAU,CAAC,YAAM;EACfT,IAAAA,OAAO,CAACE,KAAR,CAAcG,MAAd,GAAuBA,MAAM,GAAG,IAAhC;EACAK,IAAAA,MAAM,CAACD,UAAP,CAAkB,YAAM;EACtBT,MAAAA,OAAO,CAACE,KAAR,CAAcS,cAAd,CAA6B,QAA7B;EACAX,MAAAA,OAAO,CAACE,KAAR,CAAcS,cAAd,CAA6B,UAA7B;EACAX,MAAAA,OAAO,CAACE,KAAR,CAAcS,cAAd,CAA6B,qBAA7B;EACAX,MAAAA,OAAO,CAACE,KAAR,CAAcS,cAAd,CAA6B,qBAA7B;EACD,KALD,EAKGV,QALH;EAMD,GARS,EAQP,CARO,CAAV;EASD;EAEM,SAASW,OAAT,CAAiBZ,OAAjB,EAA0BC,QAA1B,EAA0C;EAAA,MAAhBA,QAAgB;EAAhBA,IAAAA,QAAgB,GAAL,GAAK;EAAA;;EAC/CD,EAAAA,OAAO,CAACE,KAAR,CAAcC,OAAd,GAAwB,OAAxB;EACAH,EAAAA,OAAO,CAACE,KAAR,CAAcE,QAAd,GAAyB,QAAzB;EACA,MAAMC,MAAM,GAAGL,OAAO,CAACM,YAAvB;EACAN,EAAAA,OAAO,CAACE,KAAR,CAAcG,MAAd,GAAuBA,MAAM,GAAG,IAAhC;EACAL,EAAAA,OAAO,CAACE,KAAR,CAAcK,kBAAd,GAAmC,QAAnC;EACAP,EAAAA,OAAO,CAACE,KAAR,CAAcM,kBAAd,GAAmCP,QAAQ,GAAG,IAA9C;EACAQ,EAAAA,UAAU,CAAC,YAAM;EACfT,IAAAA,OAAO,CAACE,KAAR,CAAcG,MAAd,GAAuB,KAAvB;EACAK,IAAAA,MAAM,CAACD,UAAP,CAAkB,YAAM;EACtBT,MAAAA,OAAO,CAACE,KAAR,CAAcC,OAAd,GAAwB,MAAxB;EACAH,MAAAA,OAAO,CAACE,KAAR,CAAcS,cAAd,CAA6B,QAA7B;EACAX,MAAAA,OAAO,CAACE,KAAR,CAAcS,cAAd,CAA6B,UAA7B;EACAX,MAAAA,OAAO,CAACE,KAAR,CAAcS,cAAd,CAA6B,qBAA7B;EACAX,MAAAA,OAAO,CAACE,KAAR,CAAcS,cAAd,CAA6B,qBAA7B;EACD,KAND,EAMGV,QANH;EAOD,GATS,EASP,CATO,CAAV;EAUD;EAEM,SAASY,cAAT,CAAwBb,OAAxB,EAAiCf,QAAjC,EAA2C;EAChD,MAAI6B,OAAO,GAAGd,OAAO,CAACe,kBAAtB;;EAEA,SAAOD,OAAP,EAAgB;EACd,QAAIA,OAAO,CAACjB,OAAR,CAAgBZ,QAAhB,CAAJ,EAA+B;EAC7B,aAAO6B,OAAP;EACD;;EAEDA,IAAAA,OAAO,GAAGA,OAAO,CAACC,kBAAlB;EACD;EACF;EAEM,SAASC,UAAT,CAAoBhB,OAApB,EAA6Bf,QAA7B,EAAuC;EAC5C,MAAMgC,MAAM,GAAG,EAAf;;EACA,OAAK,IAAI1B,MAAM,GAAGS,OAAO,IAAIA,OAAO,CAACkB,aAArC,EAAoD3B,MAApD,EAA4DA,MAAM,GAAGA,MAAM,CAAC2B,aAA5E,EAA2F;EACzF,QAAI3B,MAAM,CAACM,OAAP,CAAeZ,QAAf,CAAJ,EAA8B;EAC5BgC,MAAAA,MAAM,CAACE,IAAP,CAAY5B,MAAZ;EACD;EACF;;EAED,SAAO0B,MAAP;EACD;;ECvFD;EACA;EACA;;MACqBG;EACnB,6BACIC,aADJ,EAEIC,WAFJ,EAGE;EAAA,QAFED,aAEF;EAFEA,MAAAA,aAEF,GAFkB,0BAElB;EAAA;;EAAA,QADEC,WACF;EADEA,MAAAA,WACF,GADgBC,KAChB;EAAA;;EACA,SAAKC,WAAL,GAAmBC,EAAA,CAAOJ,aAAP,CAAnB;EACA,SAAKC,WAAL,GAAmBA,WAAnB;EACA,SAAKI,cAAL,GAAsB,+BAAtB;EACA,SAAKC,YAAL,GAAoB,8BAApB;EAEA,SAAKC,KAAL,GAAa,IAAIC,KAAJ,CAAU;EACrB5B,MAAAA,QAAQ,EAAE,KADW;EAErB6B,MAAAA,QAAQ,EAAE;EACRC,QAAAA,CAAC,EAAE,QADK;EAERC,QAAAA,CAAC,EAAE;EAFK,OAFW;EAMrBC,MAAAA,WAAW,EAAE,IANQ;EAOrBC,MAAAA,KAAK,EAAE,CACL;EACEC,QAAAA,IAAI,EAAE,SADR;EAEEC,QAAAA,UAAU,EAAE,QAFd;EAGEC,QAAAA,IAAI,EAAE;EAHR,OADK;EAPc,KAAV,CAAb;EAeA,SAAKC,IAAL;EACD;;;;WAEDC,YAAA,qBAAY;EAAA;;EACV,QAAI,KAAKf,WAAL,KAAqB,IAAzB,EAA+B;EAC7B;EACD;;EAEDC,IAAAA,QAAA,CAAa,KAAKD,WAAlB,EAA+B,OAA/B,EAAwC,KAAKE,cAA7C,EAA6D,YAAM;EACjE,MAAA,KAAI,CAACc,WAAL,CAAiB,KAAI,CAACb,YAAtB;EACD,KAFD;EAGD;;WAEDW,OAAA,gBAAO;EACL,SAAKC,SAAL;EACD;;WAEDC,cAAA,qBAAYC,MAAZ,EAAoB;EAAA;;EAClBC,IAAAA,KAAK,CAAC,KAAKpB,WAAL,CAAiBqB,OAAlB,EAA2B;EAC9BC,MAAAA,MAAM,EAAE,MADsB;EAE9BC,MAAAA,WAAW,EAAE,aAFiB;EAG9BC,MAAAA,IAAI,EAAE,IAAIC,eAAJ,CAAoB;EACxBN,QAAAA,MAAM,EAAEA,MADgB;EAExBO,QAAAA,WAAW,EAAE,KAAK1B,WAAL,CAAiB0B,WAFN;EAGxBC,QAAAA,KAAK,EAAE,KAAK3B,WAAL,CAAiB2B;EAHA,OAApB,CAHwB;EAQ9BC,MAAAA,OAAO,EAAE;EACP,wBAAgB;EADT;EARqB,KAA3B,CAAL,CAWGC,IAXH,CAWQ,UAACC,QAAD,EAAc;EACpB,UAAIA,QAAQ,CAACC,EAAb,EAAiB;EACf,eAAOD,QAAQ,CAACE,IAAT,EAAP;EACD;;EAED,aAAOC,OAAO,CAACC,MAAR,CAAeJ,QAAf,CAAP;EACD,KAjBD,EAiBGD,IAjBH,CAiBQ,UAACM,IAAD,EAAU;EAChB;EACA,UAAI,gBAAgB,OAAQA,IAAI,CAACC,OAA7B,IAAyCD,IAAI,CAACC,OAAlD,EAA2D;EACzDC,QAAAA,QAAQ,CAACC,MAAT;EACA;EACD,OALe;;;EAQhB,UAAI,gBAAgB,OAAQH,IAAI,CAACI,OAAjC,EAA2C;EACzC,QAAA,MAAI,CAACjC,KAAL,CAAWkC,KAAX,CAAiBL,IAAI,CAACI,OAAtB;;EACA;EACD;;EAED,MAAA,MAAI,CAACjC,KAAL,CAAWkC,KAAX,CAAiB,MAAI,CAACxC,WAAL,CAAiByC,IAAjB,CAAsB,oBAAtB,CAAjB;EACD,KA/BD,WA+BS,UAACD,KAAD,EAAW;EAClBE,MAAAA,OAAO,CAACC,IAAR,CAAa,MAAI,CAAC3C,WAAL,CAAiByC,IAAjB,CAAsB,oBAAtB,CAAb,EAA0DD,KAA1D;EACD,KAjCD;EAkCD;;;;;EChFH;EACA;EACA;;MACqBI;EACnB,oCACIC,wBADJ,EAEI7C,WAFJ,EAGIM,KAHJ,EAIE;EAAA,QAHEuC,wBAGF;EAHEA,MAAAA,wBAGF,GAH6B,4BAG7B;EAAA;;EAAA,QAFE7C,WAEF;EAFEA,MAAAA,WAEF,GAFgBC,KAEhB;EAAA;;EAAA,QADEK,KACF;EADEA,MAAAA,KACF,GADU,IACV;EAAA;;EACA,SAAKwC,yBAAL,GAAiC3C,EAAA,CAAO0C,wBAAP,CAAjC;EACA,SAAK7C,WAAL,GAAmBA,WAAnB;EACA,SAAK+C,mBAAL,GAA2B,kBAA3B;EACA,SAAKC,iBAAL,GAAyB,oBAAzB;EACA,SAAKC,uBAAL,GAA+B,sBAA/B;EACA,SAAKC,yBAAL,GAAiC,4BAAjC;EACA,SAAKC,mBAAL,GAA2B,2BAA3B;EACA,SAAKC,sBAAL,GAA8B,IAA9B;EACA,SAAKC,gBAAL,GAAwB,IAAxB;EACA,SAAKC,aAAL,GAAqB,IAArB;EACA,SAAKC,gBAAL,GAAwB,EAAxB;EACA,SAAKC,mBAAL,GAA2B,EAA3B;EACA,SAAKC,iBAAL,GAAyB,KAAzB;EACA,SAAKnD,KAAL,GAAaA,KAAb;EAEA,SAAKU,IAAL;EACD;;;;WAEDC,YAAA,qBAAY;EAAA;;EACV,QAAI,KAAK6B,yBAAL,KAAmC,IAAvC,EAA6C;EAC3CJ,MAAAA,OAAO,CAACgB,GAAR,CAAY,wCAAZ;EACA;EACD;;EAEDvD,IAAAA,QAAA,CAAa,KAAK2C,yBAAlB,EAA6C,OAA7C,EAAsD,KAAKE,iBAA3D,EAA8E,UAACtE,OAAD,EAAUL,KAAV,EAAoB;EAChGA,MAAAA,KAAK,CAACsF,cAAN;;EACA,UAAI,KAAI,CAACC,eAAL,CAAqBlF,OAArB,CAAJ,EAAmC;EACjC,QAAA,KAAI,CAACwC,WAAL,CAAiB,KAAI,CAACiC,mBAAtB,EAA2CzE,OAA3C;EACD;EACF,KALD;EAOAyB,IAAAA,QAAA,CAAa,KAAK2C,yBAAlB,EAA6C,OAA7C,EAAsD,KAAKG,uBAA3D,EAAoF,YAAM;EACxF,MAAA,KAAI,CAACY,WAAL;EACD,KAFD;EAIA1D,IAAAA,QAAA,CAAa,KAAK2C,yBAAlB,EAA6C,OAA7C,EAAsD,KAAKI,yBAA3D,EAAsF,YAAM;EAC1F,MAAA,KAAI,CAACY,aAAL;EACD,KAFD;EAGD;;WAED9C,OAAA,gBAAO;EACL,SAAKC,SAAL;EACA,SAAK8C,aAAL;EACD;EAED;EACF;EACA;EACA;EACA;EACA;;;WACEH,kBAAA,yBAAgBlF,OAAhB,EAAyB;EACvB,SAAK2E,gBAAL,GAAwB3E,OAAO,CAACkB,aAAhC;EACA,SAAKwD,sBAAL,GAA8B1E,OAAO,CAACsF,eAAtC;EACA,SAAKV,aAAL,GAAqB,KAAKD,gBAAL,CAAsBxF,aAAtB,CAAoC,uBAApC,CAArB;;EACA,QAAI,KAAKuF,sBAAL,CAA4Ba,YAA5B,CAAyC,mBAAzC,EAA8D,OAA9D,MAA2E,OAA/E,EAAwF;EACtF,aAAO,KAAP;EACD;;EAED,QAAI,KAAKb,sBAAL,CAA4Ba,YAA5B,CAAyC,cAAzC,EAAyD,OAAzD,MAAsE,OAA1E,EAAmF;EACjF,aAAO,IAAP;EACD;;EAED,WAAO,KAAP;EACD;;WAED/C,cAAA,qBAAYC,MAAZ,EAAoB;EAAA;;EAClB,QAAI,KAAKmC,aAAL,KAAuB,IAA3B,EAAiC;EAC/B,WAAKA,aAAL,CAAmB1E,KAAnB,CAAyBC,OAAzB,GAAmC,cAAnC;EACD;;EAEDuC,IAAAA,KAAK,CAAC,KAAKpB,WAAL,CAAiBqB,OAAlB,EAA2B;EAC9BC,MAAAA,MAAM,EAAE,MADsB;EAE9BC,MAAAA,WAAW,EAAE,aAFiB;EAG9BC,MAAAA,IAAI,EAAE,IAAIC,eAAJ,CAAoB;EACxBN,QAAAA,MAAM,EAAEA,MADgB;EAExBO,QAAAA,WAAW,EAAE,KAAK1B,WAAL,CAAiB0B,WAFN;EAGxBC,QAAAA,KAAK,EAAE,KAAK3B,WAAL,CAAiB2B,KAHA;EAIxBuC,QAAAA,OAAO,EAAE,KAAKd,sBAAL,CAA4Be,KAJb;EAKxBC,QAAAA,SAAS,EAAE,KAAKhB,sBAAL,CAA4BiB,OALf;EAMxBC,QAAAA,YAAY,EAAE,KAAKb;EANK,OAApB,CAHwB;EAW9B7B,MAAAA,OAAO,EAAE;EACP,wBAAgB;EADT;EAXqB,KAA3B,CAAL,CAcGC,IAdH,CAcQ,UAACC,QAAD,EAAc;EACpB,UAAIA,QAAQ,CAACC,EAAb,EAAiB;EACf,eAAOD,QAAQ,CAACE,IAAT,EAAP;EACD;;EAED,aAAOC,OAAO,CAACC,MAAR,CAAeJ,QAAf,CAAP;EACD,KApBD,EAoBGD,IApBH,CAoBQ,UAACM,IAAD,EAAU;EAChB,UAAI,gBAAgB,OAAQA,IAAI,CAACC,OAA7B,IAAyCD,IAAI,CAACC,OAAlD,EAA2D;EACzD,QAAA,MAAI,CAACgB,sBAAL,CAA4BmB,YAA5B,CAAyC,cAAzC,EAAyD,IAAzD;;EACA,YAAMC,YAAY,GAAG5G,QAAQ,CAAC6G,aAAT,CAAuB,KAAvB,CAArB;EACAD,QAAAA,YAAY,CAACE,SAAb,CAAuBC,GAAvB,CAA2B,WAA3B;EACAH,QAAAA,YAAY,CAACE,SAAb,CAAuBC,GAAvB,CAA2B,cAA3B;EACAH,QAAAA,YAAY,CAACI,SAAb,GAAyBC,IAAI,CAACC,KAAL,CAAW3C,IAAI,CAAC4C,gBAAhB,CAAzB;;EACA,QAAA,MAAI,CAAC1B,gBAAL,CAAsB2B,WAAtB,CAAkCR,YAAlC;;EACA,YAAI,MAAI,CAAClB,aAAL,KAAuB,IAA3B,EAAiC;EAC/B,UAAA,MAAI,CAACA,aAAL,CAAmB1E,KAAnB,CAAyBC,OAAzB,GAAmC,MAAnC;EACD;;EAEDsB,QAAAA,SAAA,CAAcqE,YAAd;EAEA;EACD;;EAED,UAAI,MAAI,CAAClE,KAAL,KAAe,IAAnB,EAAyB;EACvB,QAAA,MAAI,CAACA,KAAL,CAAWkC,KAAX,CAAiB,MAAI,CAACxC,WAAL,CAAiByC,IAAjB,CAAsB,oBAAtB,CAAjB;EACD,OAFD,MAEO;EACLwC,QAAAA,KAAK,CAAC,YAAY,MAAI,CAACjF,WAAL,CAAiByC,IAAjB,CAAsB,oBAAtB,CAAb,CAAL;EACD;EACF,KA1CD,WA0CS,UAACD,KAAD,EAAW;EAClBE,MAAAA,OAAO,CAACC,IAAR,CAAa,MAAI,CAAC3C,WAAL,CAAiByC,IAAjB,CAAsB,oBAAtB,CAAb,EAA0DD,KAA1D;EACD,KA5CD;EA6CD;;WAED0C,yBAAA,kCAAyB;EAAA;;EACvB,SAAK1B,mBAAL,GAA2B,EAA3B;EACA,SAAKV,yBAAL,CAA+B/E,gBAA/B,CAAgD,gCAAhD,EAAkFoH,OAAlF,CAA0F,UAACzG,OAAD,EAAa;EACrG,UAAI,CAAC,MAAI,CAAC0G,gBAAL,CAAsB1G,OAAO,CAACyF,KAA9B,CAAL,EAA2C;EACzC,QAAA,MAAI,CAACX,mBAAL,CAAyB3D,IAAzB,CAA8BnB,OAAO,CAACyF,KAAtC;EACD;EACF,KAJD;EAMA,SAAKZ,gBAAL,CAAsB4B,OAAtB,CAA8B,UAACE,OAAD,EAAa;EACzC,UAAI,CAAC,MAAI,CAACD,gBAAL,CAAsBC,OAAtB,CAAD,IAAmC,CAAC,MAAI,CAACC,gBAAL,CAAsBD,OAAtB,CAAxC,EAAwE;EACtE,QAAA,MAAI,CAAC7B,mBAAL,CAAyB3D,IAAzB,CAA8BwF,OAA9B;EACD;EACF,KAJD;EAMA,WAAO,KAAK7B,mBAAL,CAAyB+B,IAAzB,CAA8B,KAAKvF,WAAL,CAAiBwF,QAAjB,CAA0BC,kBAAxD,CAAP;EACD;EAED;EACF;EACA;EACA;;;WACEL,mBAAA,0BAAiBM,IAAjB,EAAuB;EACrB,QAAIC,uBAAuB,GAAG,KAA9B;EACA,SAAKnC,mBAAL,CAAyB2B,OAAzB,CAAiC,UAACS,GAAD,EAAS;EACxC,UAAIF,IAAI,CAACG,UAAL,CAAgBD,GAAG,GAAG,GAAtB,CAAJ,EAAgC;EAC9BD,QAAAA,uBAAuB,GAAG,IAA1B;EACD;EACF,KAJD;EAMA,WAAOA,uBAAP;EACD;;WAEDG,8BAAA,uCAA8B;EAC5B,SAAKZ,sBAAL;EACA,QAAMa,gBAAgB,GAAG,EAAzB;EACA,SAAKjD,yBAAL,CAA+B/E,gBAA/B,CAAgD,oEAAhD,EAAsHoH,OAAtH,CAA8H,UAACzG,OAAD,EAAa;EACzIqH,MAAAA,gBAAgB,CAAClG,IAAjB,CAAsBnB,OAAO,CAACyF,KAA9B;EACD,KAFD,EAH4B;EAQ5B;;EACA,QAAM6B,wBAAwB,GAAG7F,EAAA,CAAO,yBAAP,CAAjC;;EACA,QAAI6F,wBAAwB,KAAK,IAA7B,IAAqCA,wBAAwB,CAAC7B,KAAzB,KAAmC,EAA5E,EAAgF;EAC9E,aAAO4B,gBAAgB,CAACR,IAAjB,CAAsB,KAAKvF,WAAL,CAAiBwF,QAAjB,CAA0BC,kBAAhD,CAAP;EACD;;EAED,QAAMQ,sBAAsB,GAAGD,wBAAwB,CAAC7B,KAAzB,CAA+B+B,KAA/B,CAAqC,OAArC,CAA/B;EAEA,WAAOH,gBAAgB,CAACI,MAAjB,CAAwBF,sBAAxB,EAAgDV,IAAhD,CAAqD,KAAKvF,WAAL,CAAiBwF,QAAjB,CAA0BC,kBAA/E,CAAP;EACD;;WAED5B,cAAA,uBAAc;EACZ,SAAKf,yBAAL,CAA+B/E,gBAA/B,CAAgD,kBAAhD,EAAoEoH,OAApE,CAA4E,UAACzG,OAAD,EAAa;EACvFA,MAAAA,OAAO,CAAC2F,OAAR,GAAkB,KAAlB;EACD,KAFD;EAGD;;WAEDP,gBAAA,yBAAgB;EACd;EACA,SAAKD,WAAL,GAFc;;EAKd,SAAKf,yBAAL,CAA+B/E,gBAA/B,CAAgD,oCAAhD,EAAsFoH,OAAtF,CAA8F,UAACzG,OAAD,EAAa;EACzGA,MAAAA,OAAO,CAAC2F,OAAR,GAAkB,IAAlB;EACD,KAFD,EALc;;EAUd,SAAKvB,yBAAL,CAA+B/E,gBAA/B,CAAgD,qCAAhD,EAAuFoH,OAAvF,CAA+F,UAACzG,OAAD,EAAa;EAC1GA,MAAAA,OAAO,CAACkB,aAAR,CAAsB7B,gBAAtB,CAAuC,yBAAvC,EAAkEoH,OAAlE,CAA0E,UAACzG,OAAD,EAAa;EACrFA,QAAAA,OAAO,CAAC2F,OAAR,GAAkB,KAAlB;EACD,OAFD;EAGD,KAJD;EAMA,SAAKZ,iBAAL,GAAyB,IAAzB;EACD;;WAEDM,gBAAA,yBAAgB;EACd,SAAKR,gBAAL,GAAwB,KAAKT,yBAAL,CAA+BmB,YAA/B,CAA4C,wBAA5C,EAAsE,EAAtE,CAAxB;;EACA,QAAI,KAAKV,gBAAL,KAA0B,EAA9B,EAAkC;EAChC,WAAKA,gBAAL,GAAwB,EAAxB;EACD;;EAED,QAAI,KAAKA,gBAAL,CAAsB6C,MAAtB,KAAiC,CAArC,EAAwC;EACtC,WAAK7C,gBAAL,GAAwB,KAAKA,gBAAL,CAAsB2C,KAAtB,CAA4B,GAA5B,CAAxB;EACD;EACF;;WAEDZ,mBAAA,0BAAiBD,OAAjB,EAA0B;EACxB,SAAKvC,yBAAL,CAA+B/E,gBAA/B,CAAgD,kBAAhD,EAAoEoH,OAApE,CAA4E,UAACzG,OAAD,EAAa;EACvF,UAAIA,OAAO,CAACyF,KAAR,KAAkBkB,OAAtB,EAA+B;EAC7B,eAAO,IAAP;EACD;EACF,KAJD;EAMA,WAAO,KAAP;EACD;;;;;EC9NH;EACA;EACA;;MACqBgB;EACnB,+BACIC,8BADJ,EAEItG,WAFJ,EAGE;EAAA,QAFEsG,8BAEF;EAFEA,MAAAA,8BAEF,GAFmC,kCAEnC;EAAA;;EAAA,QADEtG,WACF;EADEA,MAAAA,WACF,GADgBC,KAChB;EAAA;;EACA,SAAKsG,gBAAL,GAAwBpG,EAAA,CAAOmG,8BAAP,CAAxB;EACA,SAAKE,gBAAL,GAAwBrG,EAAA,CAAUmG,8BAAV,YAAxB;EACA,SAAKtG,WAAL,GAAmBA,WAAnB;EACA,SAAKgB,IAAL;EACD;;;;WAEDC,YAAA,qBAAY;EAAA;;EACVd,IAAAA,QAAA,CAAa,KAAKoG,gBAAlB,EAAoC,OAApC,EAA6C,uBAA7C,EAAsE,YAAM;EAC1E,MAAA,KAAI,CAACE,kBAAL;EACD,KAFD;EAIAtG,IAAAA,QAAA,CAAa,KAAKoG,gBAAlB,EAAoC,OAApC,EAA6C,sBAA7C,EAAqE,YAAM;EACzE,MAAA,KAAI,CAACG,iBAAL;EACD,KAFD;EAIAvG,IAAAA,QAAA,CAAa,KAAKoG,gBAAlB,EAAoC,OAApC,EAA6C,uBAA7C,EAAsE,YAAM;EAC1E,MAAA,KAAI,CAACI,kBAAL;EACD,KAFD;EAIAxG,IAAAA,QAAA,CAAa,KAAKoG,gBAAlB,EAAoC,OAApC,EAA6C,sBAA7C,EAAqE,YAAM;EACzE,MAAA,KAAI,CAACK,iBAAL;EACD,KAFD;EAIAzG,IAAAA,QAAA,CAAa,KAAKoG,gBAAlB,EAAoC,OAApC,EAA6C,wBAA7C,EAAuE,YAAM;EAC3E,MAAA,KAAI,CAACM,aAAL;EACD,KAFD;EAIA1G,IAAAA,QAAA,CAAa,KAAKoG,gBAAlB,EAAoC,OAApC,EAA6C,4BAA7C,EAA2E,UAACjI,MAAD,EAAY;EACrF,MAAA,KAAI,CAACwI,aAAL,CAAmBxI,MAAnB;EACD,KAFD;EAGD;;WAED0C,OAAA,gBAAO;EACL,QAAI,KAAKuF,gBAAL,KAA0B,IAA9B,EAAoC;EAClC7D,MAAAA,OAAO,CAACgB,GAAR,CAAY,wCAAZ;EACA;EACD;;EAED,SAAKzC,SAAL;EACD;;WAEDwF,qBAAA,8BAAqB;EACnB,SAAKM,iBAAL,CAAuB,0CAAvB;EACD;;WAEDL,oBAAA,6BAAoB;EAClB,SAAKK,iBAAL,CAAuB,yCAAvB;EACD;;WAEDJ,qBAAA,8BAAqB;EACnB,SAAKI,iBAAL,CAAuB,0CAAvB;EACD;;WAEDH,oBAAA,6BAAoB;EAClB,SAAKG,iBAAL,CAAuB,yCAAvB;EACD;;WAEDA,oBAAA,2BAAkBC,YAAlB,EAAgC;EAC9B,QAAMC,kBAAkB,GAAG9G,EAAA,CAAO6G,YAAP,CAA3B;;EACA,QAAIC,kBAAkB,KAAK,IAA3B,EAAiC;EAC/B,UAAMC,KAAK,GAAGD,kBAAkB,CAACE,OAAnB,CAA2BC,SAA3B,CAAqC,IAArC,CAAd;EACA,UAAMC,UAAU,GAAGH,KAAK,CAACrJ,aAAN,CAAoB,IAApB,CAAnB;EAEA,WAAK2I,gBAAL,CAAsBxB,WAAtB,CAAkCqC,UAAlC;EACAlH,MAAAA,GAAA,CAAQ,0BAAR,EAAoCgF,OAApC,CAA4C,UAACmC,CAAD,EAAO;EACjDA,QAAAA,CAAC,CAAC1I,KAAF,CAAQC,OAAR,GAAkB,SAAlB;EACD,OAFD;EAGD;EACF;;WAEDgI,gBAAA,yBAAgB;EACd,SAAKL,gBAAL,CAAsB5B,SAAtB,GAAkC,EAAlC;EACAzE,IAAAA,GAAA,CAAQ,0BAAR,EAAoCgF,OAApC,CAA4C,UAACmC,CAAD,EAAO;EACjDA,MAAAA,CAAC,CAAC1I,KAAF,CAAQC,OAAR,GAAkB,MAAlB;EACD,KAFD;EAGD;;WAEDiI,gBAAA,uBAAcxI,MAAd,EAAsB;EACpB,QAAIA,MAAM,CAACsB,aAAP,KAAyB,IAAzB,IAAiCtB,MAAM,CAACsB,aAAP,CAAqBA,aAArB,KAAuC,IAA5E,EAAkF;EAChF,WAAK4G,gBAAL,CAAsBe,WAAtB,CAAkCjJ,MAAM,CAACsB,aAAP,CAAqBA,aAAvD;EACD;;EAED,QAAI,KAAK4G,gBAAL,CAAsB5B,SAAtB,CAAgC4C,IAAhC,OAA2C,EAA/C,EAAmD;EACjDrH,MAAAA,GAAA,CAAQ,0BAAR,EAAoCgF,OAApC,CAA4C,UAACmC,CAAD,EAAO;EACjDA,QAAAA,CAAC,CAAC1I,KAAF,CAAQC,OAAR,GAAkB,MAAlB;EACD,OAFD;EAGD;EACF;EAED;EACF;EACA;EACA;;;WACE4I,oBAAA,6BAAoB;EAAA;;EAClB,QAAMC,YAAY,GAAG,EAArB;EACA,QAAMC,YAAY,GAAG,EAArB;EAEA,QAAMC,YAAY,GAAG,KAAKpB,gBAAL,CAAsBzI,gBAAtB,CAAuC,kDAAvC,CAArB;EACA,QAAM8J,SAAS,GAAG,KAAKrB,gBAAL,CAAsBzI,gBAAtB,CAAuC,8CAAvC,CAAlB;EACA,QAAM+J,QAAQ,GAAG,KAAKtB,gBAAL,CAAsBzI,gBAAtB,CAAuC,+CAAvC,CAAjB;;EACA,uCAA+BgK,MAAM,CAACC,OAAP,CAAeH,SAAf,CAA/B,qCAA0D;EAAA;EAAA,UAA9CI,GAA8C;EAAA,UAAzCC,SAAyC;;EACxD,UAAIA,SAAS,CAAC/D,KAAV,KAAoB,EAAxB,EAA4B;EAC1BwD,QAAAA,YAAY,CAAC9H,IAAb,CAAkB+H,YAAY,CAACK,GAAD,CAAZ,CAAkB9D,KAAlB,GAA0B,GAA1B,GAAgC+D,SAAS,CAAC/D,KAA1C,GAAkD2D,QAAQ,CAACG,GAAD,CAAR,CAAc9D,KAAlF;EACD;EACF;;EAED,QAAMgE,eAAe,GAAG,KAAK3B,gBAAL,CAAsBzI,gBAAtB,CAAuC,yCAAvC,CAAxB;EACAoK,IAAAA,eAAe,CAAChD,OAAhB,CAAwB,UAAC1E,CAAD,EAAO;EAC7B,UAAM2H,GAAG,GAAG,MAAI,CAACC,kBAAL,CAAwB5H,CAAC,CAAC0D,KAA1B,CAAZ;;EACA,UAAIiE,GAAG,KAAK,EAAZ,EAAgB;EACdV,QAAAA,YAAY,CAAC7H,IAAb,CAAkB,SAASuI,GAAG,CAACZ,IAAJ,EAA3B;EACD;EACF,KALD;EAOA,QAAMc,YAAY,GAAG,KAAK9B,gBAAL,CAAsBzI,gBAAtB,CAAuC,8CAAvC,CAArB;EACA,QAAMwK,SAAS,GAAG,KAAK/B,gBAAL,CAAsBzI,gBAAtB,CAAuC,8CAAvC,CAAlB;;EACA,yCAA+BgK,MAAM,CAACC,OAAP,CAAeO,SAAf,CAA/B,wCAA0D;EAAA;EAAA,UAA9CN,IAA8C;EAAA,UAAzCO,SAAyC;EACxD,UAAMC,QAAQ,GAAG,KAAKJ,kBAAL,CAAwBG,SAAS,CAACrE,KAAlC,CAAjB;;EACA,UAAIsE,QAAQ,KAAK,EAAjB,EAAqB;EACnBf,QAAAA,YAAY,CAAC7H,IAAb,CAAkB,UAAUyI,YAAY,CAACL,IAAD,CAAZ,CAAkB9D,KAA5B,GAAoC,GAApC,GAA0CsE,QAAQ,CAACjB,IAAT,EAA5D;EACD;EACF;;EAED,QAAMkB,WAAW,GAAG,KAAKlC,gBAAL,CAAsBzI,gBAAtB,CAAuC,6CAAvC,CAApB;EACA,QAAM4K,QAAQ,GAAG,KAAKnC,gBAAL,CAAsBzI,gBAAtB,CAAuC,6CAAvC,CAAjB;;EACA,yCAA8BgK,MAAM,CAACC,OAAP,CAAeW,QAAf,CAA9B,wCAAwD;EAAA;EAAA,UAA5CV,KAA4C;EAAA,UAAvCW,QAAuC;EACtD,UAAMC,OAAO,GAAG,KAAKR,kBAAL,CAAwBO,QAAQ,CAACzE,KAAjC,CAAhB;;EACA,UAAI0E,OAAO,KAAK,EAAhB,EAAoB;EAClBnB,QAAAA,YAAY,CAAC7H,IAAb,CAAkB,SAAS6I,WAAW,CAACT,KAAD,CAAX,CAAiB9D,KAA1B,GAAkC,GAAlC,GAAwC0E,OAAO,CAACrB,IAAR,EAA1D;EACD;EACF;;EAED,WAAO;EACL,eAASG,YAAY,CAACmB,MAAb,CAAoB,KAAKC,UAAzB,EAAqCxD,IAArC,CAA0C,GAA1C,CADJ;EAEL;EACA,eAASmC,YAAY,CAACoB,MAAb,CAAoB,KAAKC,UAAzB,EAAqCxD,IAArC,CAA0C,GAA1C;EAHJ,KAAP;EAKD;;WAEDwD,aAAA,oBAAW5E,KAAX,EAAkB6E,KAAlB,EAAyBC,IAAzB,EAA+B;EAC7B,WAAOA,IAAI,CAACC,OAAL,CAAa/E,KAAb,MAAwB6E,KAA/B;EACD;EAED;EACF;EACA;EACA;EACA;;;WACEX,qBAAA,4BAAmBlE,KAAnB,EAA0B;EACxB;EACA,WAAOA,KAAK,CAACgF,OAAN,CAAc,cAAd,EAA8B,EAA9B,CAAP;EACD;;;;;ECjKH;EACA;EACA;MACqBC;EACnB,sBACIC,aADJ,EAEIrJ,WAFJ,EAGE;EAAA,QADEA,WACF;EADEA,MAAAA,WACF,GADgBC,KAChB;EAAA;;EACA,SAAKoJ,aAAL,GAAqBA,aAArB;EACA,SAAKrJ,WAAL,GAAmBA,WAAnB;EACD;;;;WAEDsJ,OAAA,cAAKC,WAAL,EAAkBC,gBAAlB,EAAyCC,QAAzC,EAA0D;EAAA;;EAAA,QAAxCD,gBAAwC;EAAxCA,MAAAA,gBAAwC,GAArB,EAAqB;EAAA;;EAAA,QAAjBC,QAAiB;EAAjBA,MAAAA,QAAiB,GAAN,IAAM;EAAA;;EACxDC,IAAAA,IAAI,CAACC,IAAL,CAAUJ,WAAV,EAAuB1H,IAAvB,CAA4B,UAAClC,MAAD,EAAY;EACtC,UAAIA,MAAM,CAACwE,KAAP,IAAgB,KAAI,CAAC3B,KAAL,KAAe,IAAnC,EAAyC;EACvC,QAAA,KAAI,CAACoH,oBAAL,CAA0BJ,gBAA1B,EAA4CC,QAA5C;EACD;EACF,KAJD;EAKD;;WAEDG,uBAAA,8BAAqBJ,gBAArB,EAA4CC,QAA5C,EAA6D;EAAA;;EAAA,QAAxCD,gBAAwC;EAAxCA,MAAAA,gBAAwC,GAArB,EAAqB;EAAA;;EAAA,QAAjBC,QAAiB;EAAjBA,MAAAA,QAAiB,GAAN,IAAM;EAAA;;EAC3DrI,IAAAA,KAAK,CAAC,KAAKpB,WAAL,CAAiBqB,OAAlB,EAA2B;EAC9BC,MAAAA,MAAM,EAAE,MADsB;EAE9BC,MAAAA,WAAW,EAAE,aAFiB;EAG9BC,MAAAA,IAAI,EAAE,IAAIC,eAAJ,CAAoBsG,MAAM,CAAC8B,MAAP,CAAc;EACtC1I,QAAAA,MAAM,EAAE,KAAKkI,aADyB;EAEtC3H,QAAAA,WAAW,EAAE,KAAK1B,WAAL,CAAiB0B,WAFQ;EAGtCC,QAAAA,KAAK,EAAE,KAAK3B,WAAL,CAAiB2B;EAHc,OAAd,EAIvB6H,gBAJuB,CAApB,CAHwB;EAQ9B5H,MAAAA,OAAO,EAAE;EACP,wBAAgB;EADT;EARqB,KAA3B,CAAL,CAWGC,IAXH,CAWQ,UAACC,QAAD,EAAc;EACpB,UAAIA,QAAQ,CAACC,EAAb,EAAiB;EACf,eAAOD,QAAQ,CAACE,IAAT,EAAP;EACD;;EAED,aAAOC,OAAO,CAACC,MAAR,CAAeJ,QAAf,CAAP;EACD,KAjBD,EAiBGD,IAjBH,CAiBQ,UAACC,QAAD,EAAc;EACpB,UAAI2H,QAAQ,KAAK,IAAjB,EAAuB;EACrBA,QAAAA,QAAQ,CAAC3H,QAAD,CAAR;EACD;EACF,KArBD,WAqBS,UAACU,KAAD,EAAW;EAClBE,MAAAA,OAAO,CAACgB,GAAR,CAAY,MAAI,CAAC1D,WAAL,CAAiByC,IAAjB,CAAsB,oBAAtB,CAAZ,EAAyDD,KAAzD;EACD,KAvBD;EAwBD;;;;;ECvCH;EACA;EACA;;MACqBsH;EACnB,2BACIC,OADJ,EAEIC,gBAFJ,EAGIC,0BAHJ,EAIIC,gBAJJ,EAKIlK,WALJ,EAME;EAAA,QAJEgK,gBAIF;EAJEA,MAAAA,gBAIF,GAJqB,iBAIrB;EAAA;;EAAA,QAHEC,0BAGF;EAHEA,MAAAA,0BAGF,GAH+B,+BAG/B;EAAA;;EAAA,QAFEC,gBAEF;EAFEA,MAAAA,gBAEF,GAFqB,mBAErB;EAAA;;EAAA,QADElK,WACF;EADEA,MAAAA,WACF,GADgBC,KAChB;EAAA;;EACA,SAAK8J,OAAL,GAAeA,OAAf;EACA,SAAKI,QAAL,GAAgBhK,EAAA,CAAO6J,gBAAP,CAAhB;EACA,SAAKhK,WAAL,GAAmBA,WAAnB;EACA,SAAKiK,0BAAL,GAAkCA,0BAAlC;EACA,SAAKC,gBAAL,GAAwBA,gBAAxB;EACA,SAAKE,gBAAL,GAAwB,2BAAxB;EACA,SAAKC,wBAAL,GAAgC,0BAAhC;EACA,SAAKC,gBAAL,GAAwB,0BAAxB;EACA,SAAKC,kBAAL,GAA0B,IAA1B;EACA,SAAKC,cAAL,GAAsB,IAAtB;EACA,SAAKC,kBAAL,GAA0B,IAA1B;EACD;;;;WAEDxJ,YAAA,qBAAY;EAAA;;EACV,QAAMyJ,mBAAmB,GAAGvK,EAAA,CAAO,MAAM,KAAKkK,wBAAlB,CAA5B;;EACA,QAAIK,mBAAmB,KAAK,IAA5B,EAAkC;EAChChI,MAAAA,OAAO,CAACgB,GAAR,CAAY,MAAZ;EACA;EACD;;EAEDvD,IAAAA,QAAA,CAAauK,mBAAb,EAAkC,OAAlC,EAA2C,KAAKJ,gBAAhD,EAAkE,UAAChM,MAAD,EAAY;EAC5E,MAAA,KAAI,CAACqM,aAAL,CAAmBrM,MAAnB;EACD,KAFD;EAIA6B,IAAAA,QAAA,CAAauK,mBAAb,EAAkC,OAAlC,EAA2C,sBAA3C,EAAmE,YAAM;EACvE,MAAA,KAAI,CAACE,mBAAL;EACD,KAFD;EAIAzK,IAAAA,QAAA,CAAauK,mBAAb,EAAkC,OAAlC,EAA2C,wBAA3C,EAAqE,YAAM;EACzE,MAAA,KAAI,CAACG,oBAAL;EACD,KAFD;EAIA1K,IAAAA,QAAA,CAAauK,mBAAb,EAAkC,OAAlC,EAA2C,oBAA3C,EAAiE,UAACpM,MAAD,EAASD,KAAT,EAAmB;EAClFA,MAAAA,KAAK,CAACsF,cAAN;;EACA,MAAA,KAAI,CAACmH,yBAAL,CAA+BxM,MAA/B;EACD,KAHD;EAKA6B,IAAAA,QAAA,CAAauK,mBAAb,EAAkC,QAAlC,EAA4C,uBAA5C,EAAqE,UAACpM,MAAD,EAAY;EAC/E,MAAA,KAAI,CAACyM,wBAAL,CAA8BzM,MAA9B;EACD,KAFD;EAGD;;WAED0C,OAAA,gBAAO;EACL,SAAKC,SAAL;EACD;;WAED0J,gBAAA,uBAAcrM,MAAd,EAAsB;EACpB,QAAMoM,mBAAmB,GAAGvK,EAAA,CAAO,MAAM,KAAKkK,wBAAlB,CAA5B;EACA,QAAMW,SAAS,GAAG1M,MAAM,CAAC2F,YAAP,CAAoB,SAApB,CAAlB;EACA,QAAMgH,WAAW,GAAG3M,MAAM,CAACT,aAAP,CAAqB,qBAArB,CAApB;EACA,QAAMqN,WAAW,GAAG5M,MAAM,CAAC2F,YAAP,CAAoB,gBAApB,EAAsC,MAAtC,CAApB;EACA,QAAMkD,OAAO,GAAGhH,EAAA,CAAO6K,SAAP,CAAhB;;EACA,QAAIE,WAAW,KAAK,MAApB,EAA4B;EAC1B,UAAIR,mBAAmB,CAAChG,SAApB,CAA8ByG,QAA9B,CAAuC,sBAAvC,CAAJ,EAAoE;EAClET,QAAAA,mBAAmB,CAAChG,SAApB,CAA8BC,GAA9B,CAAkC,wBAAlC;EACD,OAFD,MAEO;EACL+F,QAAAA,mBAAmB,CAAChG,SAApB,CAA8BC,GAA9B,CAAkC,sBAAlC;EACD;;EAEDxE,MAAAA,SAAA,CAAcgH,OAAd;EACA8D,MAAAA,WAAW,CAACrM,KAAZ,CAAkBwM,SAAlB,GAA8B,eAA9B;EACA9M,MAAAA,MAAM,CAACiG,YAAP,CAAoB,gBAApB,EAAsC,OAAtC;EACD,KAVD,MAUO;EACL,UAAImG,mBAAmB,CAAChG,SAApB,CAA8ByG,QAA9B,CAAuC,wBAAvC,CAAJ,EAAsE;EACpET,QAAAA,mBAAmB,CAAChG,SAApB,CAA8B2G,MAA9B,CAAqC,wBAArC;EACD,OAFD,MAEO;EACLX,QAAAA,mBAAmB,CAAChG,SAApB,CAA8B2G,MAA9B,CAAqC,sBAArC;EACD;;EAEDlL,MAAAA,OAAA,CAAYgH,OAAZ;EACA8D,MAAAA,WAAW,CAACrM,KAAZ,CAAkBS,cAAlB,CAAiC,WAAjC;EACAf,MAAAA,MAAM,CAACiG,YAAP,CAAoB,gBAApB,EAAsC,MAAtC;EACD;EACF;EAED;EACF;EACA;EACA;;;WACE+G,YAAA,qBAAY;EACV,QAAMC,WAAW,GAAG,KAAKC,SAAL,EAApB;EACA,SAAKxK,IAAL;EACA,SAAKyK,kBAAL;EACA,WAAOF,WAAP;EACD;;WAEDC,YAAA,qBAAY;EACV,WAAO9B,IAAI,CAACC,IAAL,CAAU;EACf+B,MAAAA,KAAK,EAAE,EADQ;EAEf3K,MAAAA,IAAI,EAAE,SAFS;EAGf4K,MAAAA,IAAI,EAAE,KAAKC,aAAL,EAHS;EAIfC,MAAAA,KAAK,EAAE,OAJQ;EAKfC,MAAAA,YAAY,EAAE,KALC;EAMfC,MAAAA,WAAW,EAAE;EACXC,QAAAA,aAAa,EAAE,KAAK5B,gBADT;EAEX6B,QAAAA,SAAS,EAAE,+CAA+C,KAAK5B;EAFpD,OANE;EAUf6B,MAAAA,iBAAiB,EAAE,KAAKlM,WAAL,CAAiByC,IAAjB,CAAsB0J,UAV1B;EAWfC,MAAAA,gBAAgB,EAAE;EAXH,KAAV,CAAP;EAaD;;WAEDX,qBAAA,8BAAqB;EAAA;;EACnB,SAAKjJ,KAAL,GAAa,IAAb,CADmB;;EAGnBpB,IAAAA,KAAK,CAAC,KAAKpB,WAAL,CAAiBqB,OAAlB,EAA2B;EAC9BC,MAAAA,MAAM,EAAE,MADsB;EAE9BC,MAAAA,WAAW,EAAE,aAFiB;EAG9BC,MAAAA,IAAI,EAAE,IAAIC,eAAJ,CAAoB;EACxBN,QAAAA,MAAM,EAAE,KAAK8I,0BADW;EAExBvI,QAAAA,WAAW,EAAE,KAAK1B,WAAL,CAAiB0B,WAFN;EAGxBC,QAAAA,KAAK,EAAE,KAAK3B,WAAL,CAAiB2B,KAHA;EAIxBuF,QAAAA,KAAK,EAAE,KAAK6C,OAJY;EAKxBsC,QAAAA,GAAG,EAAE;EALmB,OAApB,CAHwB;EAU9BzK,MAAAA,OAAO,EAAE;EACP,wBAAgB;EADT;EAVqB,KAA3B,CAAL,CAaGC,IAbH,CAaQ,UAACC,QAAD,EAAc;EACpB,UAAIA,QAAQ,CAACC,EAAb,EAAiB;EACf,eAAOD,QAAQ,CAACE,IAAT,EAAP;EACD;;EAED,aAAOC,OAAO,CAACC,MAAR,CAAeJ,QAAf,CAAP;EACD,KAnBD,EAmBGD,IAnBH,CAmBQ,UAACM,IAAD,EAAU;EAChB,UAAI,CAACA,IAAI,CAACC,OAAV,EAAmB;EACjB,YAAMkK,UAAU,GAAG,IAAIlD,UAAJ,CAAe,MAAI,CAACc,gBAApB,EAAsC,MAAI,CAAClK,WAA3C,CAAnB;EACAsM,QAAAA,UAAU,CAAChD,IAAX,CAAgBvB,MAAM,CAAC8B,MAAP,CAAc;EAC5B6B,UAAAA,KAAK,EAAE,OADqB;EAE5B3K,UAAAA,IAAI,EAAE,OAFsB;EAG5B4K,UAAAA,IAAI,EAAE,MAAI,CAAC3L,WAAL,CAAiByC,IAAjB,CAAsB,oBAAtB,CAHsB;EAI5BoJ,UAAAA,KAAK,EAAE,OAJqB;EAK5BK,UAAAA,iBAAiB,EAAE,IALS;EAM5BE,UAAAA,gBAAgB,EAAE;EANU,SAAd,EAObjK,IAAI,CAACoH,WAPQ,CAAhB,EAOsB;EACpB1I,UAAAA,IAAI,EAAEsB,IAAI,CAACtB;EADS,SAPtB;EAWA;EACD;;EAED,UAAM0L,KAAK,GAAGpM,EAAA,CAAO,2BAAP,CAAd;EACAoM,MAAAA,KAAK,CAAC7H,SAAN,CAAgB2G,MAAhB,CAAuB,qBAAvB;EACAkB,MAAAA,KAAK,CAAC1O,aAAN,CAAoB,cAApB,EAAoCe,KAApC,CAA0CiN,KAA1C,GAAkD,MAAlD;EACAU,MAAAA,KAAK,CAAC1O,aAAN,CAAoB,gBAApB,EAAsC+G,SAAtC,GAAkDzC,IAAI,CAACwJ,IAAvD;EACA,MAAA,MAAI,CAACpB,kBAAL,GAA0B,IAAI3H,wBAAJ,EAA1B;EACA,MAAA,MAAI,CAAC4H,cAAL,GAAsB,IAAInE,mBAAJ,EAAtB;EACD,KA1CD,WA0CS,UAAC7D,KAAD,EAAW;EAClB,MAAA,MAAI,CAACgK,WAAL,CAAiB;EACf,gBAAQ,MAAI,CAACxM,WAAL,CAAiByC,IAAjB,CAAsB,oBAAtB,IAA8C,GAA9C,GAAoDD;EAD7C,OAAjB;EAGD,KA9CD;EA+CD;;WAEDiK,wBAAA,iCAAwB;EACtB,WAAO,KAAKlC,kBAAZ;EACD;;WAED9C,oBAAA,6BAAoB;EAClB,WAAO,KAAK+C,cAAZ;EACD;;WAEDoB,gBAAA,yBAAgB;EACd,WAAO,oDAAoD,KAAK5L,WAAL,CAAiB0M,SAArE,GAAiF,YAAxF;EACD;;WAED5B,4BAAA,mCAA0BpM,OAA1B,EAAmC;EACjC,QAAMiO,SAAS,GAAGjO,OAAO,CAACsF,eAA1B;;EACA,QAAI2I,SAAS,CAAC1I,YAAV,CAAuB,mBAAvB,EAA4C,OAA5C,MAAyD,OAA7D,EAAsE;EACpE;EACD;;EAED,QAAI0I,SAAS,CAAC1I,YAAV,CAAuB,cAAvB,EAAuC,OAAvC,MAAoD,OAAxD,EAAiE;EAC/D;EACD;;EAED,QAAM2I,cAAc,GAAGzM,cAAA,CAAmBzB,OAAnB,EAA4B,eAA5B,CAAvB;;EAEA,QAAIkO,cAAc,CAAChO,KAAf,CAAqBC,OAArB,KAAiC,MAArC,EAA6C;EAC3CsB,MAAAA,SAAA,CAAcyM,cAAd;EACD,KAFD,MAEO;EACLzM,MAAAA,OAAA,CAAYyM,cAAZ;EACD;EACF;;WAED7B,2BAAA,kCAAyBrM,OAAzB,EAAkC;EAChC,QAAMT,MAAM,GAAGS,OAAO,CAACkB,aAAvB;;EACA,QAAIlB,OAAO,CAAC2F,OAAZ,EAAqB;EACnBlE,MAAAA,UAAA,CAAelC,MAAf,EAAuB,YAAvB,EAAqCkH,OAArC,CAA6C,UAAC0H,OAAD,EAAa;EACxD,aAAK,IAAIC,CAAC,GAAG,CAAb,EAAgBA,CAAC,GAAGD,OAAO,CAACE,QAAR,CAAiB3G,MAArC,EAA6C0G,CAAC,EAA9C,EAAkD;EAChD,cAAID,OAAO,CAACE,QAAR,CAAiBD,CAAjB,EAAoBvO,OAApB,CAA4B,kBAA5B,CAAJ,EAAqD;EACnDsO,YAAAA,OAAO,CAACE,QAAR,CAAiBD,CAAjB,EAAoBzI,OAApB,GAA8B,IAA9B;EACD;EACF;EACF,OAND;EAOApG,MAAAA,MAAM,CAACF,gBAAP,CAAwB,oBAAxB,EAA8CoH,OAA9C,CAAsD,UAAC1E,CAAD,EAAO;EAC3DA,QAAAA,CAAC,CAACiE,SAAF,CAAY2G,MAAZ,CAAmB,UAAnB;EACD,OAFD;EAGApN,MAAAA,MAAM,CAACF,gBAAP,CAAwB,gCAAxB,EAA0DoH,OAA1D,CAAkE,UAAC1E,CAAD,EAAO;EACvEA,QAAAA,CAAC,CAAC4D,OAAF,GAAY,IAAZ;EACD,OAFD;EAGD,KAdD,MAcO;EACLpG,MAAAA,MAAM,CAACF,gBAAP,CAAwB,0CAAxB,EAAoEoH,OAApE,CAA4E,UAAC1E,CAAD,EAAO;EACjFA,QAAAA,CAAC,CAACiE,SAAF,CAAYC,GAAZ,CAAgB,UAAhB;EACD,OAFD;EAGA1G,MAAAA,MAAM,CAACF,gBAAP,CAAwB,6BAAxB,EAAuDoH,OAAvD,CAA+D,UAAC1E,CAAD,EAAO;EACpEA,QAAAA,CAAC,CAAC4D,OAAF,GAAY,KAAZ;EACD,OAFD;EAGD;EACF;;WAEDuG,sBAAA,+BAAsB;EAAA;;EACpB,QAAMF,mBAAmB,GAAGvK,EAAA,CAAO,MAAM,KAAKkK,wBAAlB,CAA5B;EACA,QAAM2C,OAAO,GAAGtC,mBAAmB,CAAC3M,gBAApB,CAAqC,8CAArC,CAAhB;EACA,QAAMkP,gBAAgB,GAAG,MAAM,KAAKjN,WAAL,CAAiBkN,SAAvB,GAAmC,YAA5D;EACA,QAAMC,iBAAiB,GAAG,MAAM,KAAKnN,WAAL,CAAiBkN,SAAjD;EACAF,IAAAA,OAAO,CAAC7H,OAAR,CAAgB,UAACiI,MAAD,EAAY;EAC1B,UAAMC,IAAI,GAAGD,MAAM,CAACnJ,YAAP,CAAoB,MAApB,EAA4B,EAA5B,CAAb;;EACA,UAAI,MAAI,CAACjE,WAAL,CAAiBsN,WAAjB,KAAiC,GAAjC,IAAwCD,IAAI,CAACE,KAAL,CAAWN,gBAAX,CAA5C,EAA0E;EACxEG,QAAAA,MAAM,CAAC7I,YAAP,CAAoB,UAApB,EAAgC,UAAhC;EACD,OAFD,MAEO,IAAI,MAAI,CAACvE,WAAL,CAAiBsN,WAAjB,KAAiC,EAAjC,IAAuCD,IAAI,CAACE,KAAL,CAAWJ,iBAAX,CAA3C,EAA0E;EAC/EC,QAAAA,MAAM,CAAC7I,YAAP,CAAoB,UAApB,EAAgC,UAAhC;EACD,OAFM,MAEA;EACL6I,QAAAA,MAAM,CAACI,eAAP,CAAuB,UAAvB;EACD;EACF,KATD;EAUD;;WAED3C,uBAAA,gCAAuB;EACrB,QAAMH,mBAAmB,GAAGvK,EAAA,CAAO,MAAM,KAAKkK,wBAAlB,CAA5B;;EACA,QAAI,UAAU,KAAKI,kBAAnB,EAAuC;EACrCC,MAAAA,mBAAmB,CAAC3M,gBAApB,CAAqC,8CAArC,EAAqFoH,OAArF,CAA6F,UAACiI,MAAD,EAAY;EACvGA,QAAAA,MAAM,CAAC7I,YAAP,CAAoB,UAApB,EAAgC,UAAhC;EACD,OAFD;EAGAmG,MAAAA,mBAAmB,CAAC7M,aAApB,CAAkC,wBAAlC,EAA4D+G,SAA5D,GAAwE,cAAxE,CAJqC;;EAMrC,WAAK6F,kBAAL,GAA0B,IAA1B;EACD,KAPD,MAOO;EACLC,MAAAA,mBAAmB,CAAC3M,gBAApB,CAAqC,8CAArC,EAAqFoH,OAArF,CAA6F,UAACiI,MAAD,EAAY;EACvGA,QAAAA,MAAM,CAACI,eAAP,CAAuB,UAAvB;EACD,OAFD;EAGA9C,MAAAA,mBAAmB,CAAC7M,aAApB,CAAkC,wBAAlC,EAA4D+G,SAA5D,GAAwE,YAAxE,CAJK;;EAML,WAAK6F,kBAAL,GAA0B,KAA1B;EACD;EACF;;;;;EChQH,IAAIgD,SAAS,GAAI,UAASC,CAAT,EAAY;EAC3B,MAAMC,IAAI,GAAG;EACXC,IAAAA,WAAW,EAAE,KADF;EAEXC,IAAAA,UAAU,EAAE,KAFD;EAGXC,IAAAA,OAAO,EAAE,KAHE;EAIXC,IAAAA,IAAI,EAAE,CAJK;EAKXC,IAAAA,aAAa,EAAE,KALJ;EAMXC,IAAAA,WAAW,EAAE,CANF;EAOXC,IAAAA,mBAAmB,EAAE,IAPV;EAQX3D,IAAAA,kBAAkB,EAAE,IART;EASXjK,IAAAA,KAAK,EAAE,IAAIC,KAAJ,CAAU;EACf5B,MAAAA,QAAQ,EAAE,KADK;EAEf6B,MAAAA,QAAQ,EAAE;EACRC,QAAAA,CAAC,EAAE,QADK;EAERC,QAAAA,CAAC,EAAE;EAFK,OAFK;EAMfC,MAAAA,WAAW,EAAE,IANE;EAOfC,MAAAA,KAAK,EAAE,CACL;EACEC,QAAAA,IAAI,EAAE,SADR;EAEEC,QAAAA,UAAU,EAAE,QAFd;EAGEC,QAAAA,IAAI,EAAE;EAHR,OADK;EAPQ,KAAV;EATI,GAAb;EAyBA,MAAMoN,KAAK,GAAG;EAACC,IAAAA,QAAQ,EAAE;EAAX,GAAd;EACa,MAAIC,WAAJ;EAEb;EACF;EACA;EACA;EACA;;EACEF,EAAAA,KAAK,CAACG,GAAN,GAAY,UAAS3Q,QAAT,EAAmB;EAC7B;EACA,QAAI+P,CAAC,CAACa,OAAF,CAAU5Q,QAAV,EAAoBwQ,KAAK,CAACC,QAA1B,MAAwC,CAAC,CAA7C,EAAgD;EAC9C,aAAOD,KAAK,CAACC,QAAN,CAAezQ,QAAf,CAAP;EACD,KAJ4B;;;EAO7BwQ,IAAAA,KAAK,CAACC,QAAN,CAAezQ,QAAf,IAA2B6Q,MAAM,CAAC7Q,QAAD,CAAjC;EAEA,WAAOwQ,KAAK,CAACC,QAAN,CAAezQ,QAAf,CAAP;EACD,GAVD;EAYA;EACF;EACA;EACA;;;EACEwQ,EAAAA,KAAK,CAACM,OAAN,GAAgB,UAAS9Q,QAAT,EAAmB;EACjCA,IAAAA,QAAQ,CAACyQ,QAAT,CAAkBzQ,QAAlB,IAA8B6Q,MAAM,CAAC7Q,QAAD,CAApC;EACD,GAFD;EAIA;EACF;EACA;EACA;;;EACE,MAAM+Q,SAAS,GAAG,SAAZA,SAAY,CAASnM,OAAT,EAAkB;EAClC4L,IAAAA,KAAK,CAACG,GAAN,CAAU,kBAAV,EAA8BK,GAA9B,CAAkC,SAAlC,EAA6C,cAA7C;EACAR,IAAAA,KAAK,CAACG,GAAN,CAAU,uBAAV,EAAmCM,IAAnC,CAAwC,OAAxC;EACAT,IAAAA,KAAK,CAACG,GAAN,CAAU,uBAAV,EAAmChF,IAAnC;EACA6E,IAAAA,KAAK,CAACG,GAAN,CAAU,sBAAV,EAAkChF,IAAlC;EACA6E,IAAAA,KAAK,CAACG,GAAN,CAAU,sBAAV,EAAkChF,IAAlC,GAAyCqC,IAAzC,CAA8CpJ,OAA9C;EACA4L,IAAAA,KAAK,CAACG,GAAN,CAAU,uBAAV,EAAmCO,WAAnC,CAA+C,SAA/C;EACAV,IAAAA,KAAK,CAACG,GAAN,CAAU,eAAV,EAA2BQ,IAA3B;EACApB,IAAAA,CAAC,CAAC,yCAAD,CAAD,CAA6CpE,IAA7C,GAAoDqC,IAApD,CAAyDpJ,OAAzD;EACD,GATD;EAWA;EACF;EACA;EACA;EACA;;;EACEoL,EAAAA,IAAI,CAACoB,0BAAL,GAAkC,UAAS1Q,KAAT,EAAgB;EAChD;EACAA,IAAAA,KAAK,CAAC2Q,WAAN,GAAoB,uEAApB;EACA,WAAO,IAAP;EACD,GAJD;EAMA;EACF;EACA;EACA;EACA;;;EACE,WAASC,OAAT,CAAiBC,GAAjB,EAAsB;EACpB,SAAK,IAAMC,IAAX,IAAmBD,GAAnB,EAAwB;EACtB,UAAIA,GAAG,CAACE,cAAJ,CAAmBD,IAAnB,CAAJ,EAA8B;EAC5B,eAAO,KAAP;EACD;EACF;;EAED,WAAO,IAAP;EACD;EAED;EACF;EACA;EACA;EACA;EACA;EACA;;;EAEE,MAAME,kBAAkB,GAAG,SAArBA,kBAAqB,CAASvN,QAAT,EAAmBwN,cAAnB,EAAmCC,aAAnC,EAAkD;EAC3ED,IAAAA,cAAc,GAAGA,cAAc,GAAGA,cAAc,GAAG,YAApB,GAAmC,kCAAlE;EACAC,IAAAA,aAAa,GAAGA,aAAa,GAAGA,aAAa,GAAG,YAAnB,GAAkC,0MAA/D;;EAEA,QAAIzN,QAAQ,KAAK,KAAjB,EAAwB;EACtB4M,MAAAA,SAAS,CAACY,cAAc,GAAG,sBAAjB,GAA0CC,aAA3C,CAAT;EACAnQ,MAAAA,MAAM,CAACoQ,mBAAP,CAA2B,cAA3B,EAA2C/B,SAAS,CAACsB,0BAArD;EACA;EACD;;EAED,QAAI,OAAOjN,QAAQ,CAACU,KAAhB,KAA0B,WAA1B,IAAyCV,QAAQ,CAACU,KAAtD,EAA6D;EAC3DE,MAAAA,OAAO,CAACF,KAAR,CAAcV,QAAQ,CAACS,OAAvB;EACAmM,MAAAA,SAAS,CAACY,cAAc,GAAG,UAAjB,GAA8BxN,QAAQ,CAACS,OAAvC,GAAiDgN,aAAlD,CAAT;EACAnQ,MAAAA,MAAM,CAACoQ,mBAAP,CAA2B,cAA3B,EAA2C/B,SAAS,CAACsB,0BAArD;EACA;EACD;EACF,GAhBD;EAkBA;EACF;EACA;EACA;EACA;;;EACE,MAAMU,iBAAiB,GAAG,SAApBA,iBAAoB,CAAS3N,QAAT,EAAmB;EAC3C,QAAI,CAACA,QAAQ,CAACC,EAAd,EAAkB;EAChB2M,MAAAA,SAAS,CAAC,YAAY5M,QAAQ,CAAC4N,MAArB,GAA8B,KAA9B,GAAsC5N,QAAQ,CAAC6N,UAA/C,GAA4D,wCAA7D,CAAT;EACD;;EACD,WAAO7N,QAAP;EACD,GALD;EAOA;;;EACA,MAAM8N,WAAW,GAAG,SAAdA,WAAc,GAAW;EAC7BzB,IAAAA,KAAK,CAACG,GAAN,CAAU,sBAAV,EAAkCQ,IAAlC,GAAyCnD,IAAzC,CAA8C,EAA9C;EACD,GAFD;;EAIA,MAAMkE,OAAO,GAAG,SAAVA,OAAU,CAASC,GAAT,EAAc;EAC5B,WAAOA,GAAG,CAACC,QAAJ,GACFC,WADE,GAEFC,SAFE,CAEQ,KAFR,EAGF9G,OAHE,CAGM,kBAHN,EAG0B,EAH1B,EAIFA,OAJE,CAIM,MAJN,EAIc,GAJd,EAKFA,OALE,CAKM,IALN,EAKY,OALZ,EAMFA,OANE,CAMM,cANN,EAMsB,EANtB,EAOFA,OAPE,CAOM,KAPN,EAOa,GAPb,EAQFA,OARE,CAQM,KARN,EAQa,EARb,EASFA,OATE,CASM,KATN,EASa,EATb,CAAP;EAWD,GAZD;EAeA;EACF;EACA;;;EACE,MAAMiF,QAAQ,GAAG,SAAXA,QAAW,GAAW;EAC1B,QAAM8B,SAAS,GAAG/B,KAAK,CAACG,GAAN,CAAU,iBAAV,CAAlB;EACA,QAAI6B,YAAY,GAAG,IAAnB;EACA,QAAIC,UAAU,GAAGC,OAAO,CAAClH,OAAR,CAAgB,iBAAhB,EAAmC,EAAnC,IAAyC,iBAA1D;EACA,QAAImH,KAAJ;;EAEA,QAAI,IAAIlR,MAAM,CAACmR,gBAAf,EAAiC;EAC/BH,MAAAA,UAAU,IAAI,KAAd;EACD;;EAEDA,IAAAA,UAAU,IAAI,MAAd;EAEA/B,IAAAA,WAAW,GAAG,kBAAkB+B,UAAlB,GAA+B,uDAA7C;;EAUAF,IAAAA,SAAS;EAAA,KAEJM,EAFL,CAEQ,OAFR,EAEiB,wBAFjB,EAE2C,UAASlJ,CAAT,EAAY;EACjDA,MAAAA,CAAC,CAAC3D,cAAF;;EAEA,UAAI,UAAUwM,YAAd,EAA4B;EAC1BhC,QAAAA,KAAK,CAACG,GAAN,CAAU,8CAAV,EAA0Da,IAA1D,CAA+D,UAA/D,EAA2E,UAA3E;EACAhB,QAAAA,KAAK,CAACG,GAAN,CAAU,wBAAV,EAAoCM,IAApC,CAAyC,cAAzC;EACAT,QAAAA,KAAK,CAACG,GAAN,CAAU,4BAAV,EAAwCa,IAAxC,CAA6C,SAA7C,EAAwD,IAAxD;EACAgB,QAAAA,YAAY,GAAG,IAAf;EACD,OALD,MAKO;EACLhC,QAAAA,KAAK,CAACG,GAAN,CAAU,8CAAV,EAA0Da,IAA1D,CAA+D,UAA/D,EAA2E,KAA3E;EACAhB,QAAAA,KAAK,CAACG,GAAN,CAAU,wBAAV,EAAoCM,IAApC,CAAyC,YAAzC;EACAT,QAAAA,KAAK,CAACG,GAAN,CAAU,4BAAV,EAAwCa,IAAxC,CAA6C,SAA7C,EAAwD,KAAxD;EACAgB,QAAAA,YAAY,GAAG,KAAf;EACD;EACF,KAhBL;EAkBA;EACJ;EACA;EACA;EACA;EAtBI,KAuBKK,EAvBL,CAuBQ,OAvBR,EAuBiB,sBAvBjB,EAuByC,UAASlJ,CAAT,EAAY;EAC/CA,MAAAA,CAAC,CAAC3D,cAAF;EACA+J,MAAAA,CAAC,CAAC,8CAAD,CAAD,CAAkD+C,IAAlD,CAAuD,YAAW;EAChE,YAAIxQ,KAAK,CAACqN,WAAN,IAAqB,CAAzB,EAA4B;EAC1B,cAAII,CAAC,CAAC,IAAD,CAAD,CAAQgD,IAAR,CAAa,MAAb,EAAqBnD,KAArB,CAA2B,MAAMtN,KAAK,CAACiN,SAAZ,GAAwB,YAAnD,CAAJ,EAAsE;EACpEQ,YAAAA,CAAC,CAAC,IAAD,CAAD,CAAQyB,IAAR,CAAa,UAAb,EAAyB,UAAzB;EACD,WAFD,MAEO;EACLzB,YAAAA,CAAC,CAAC,IAAD,CAAD,CAAQyB,IAAR,CAAa,UAAb,EAAyB,KAAzB;EACD;EACF;;EAED,YAAIlP,KAAK,CAACqN,WAAN,IAAqB,CAAzB,EAA4B;EAC1B,cAAII,CAAC,CAAC,IAAD,CAAD,CAAQgD,IAAR,CAAa,MAAb,EAAqBnD,KAArB,CAA2B,MAAMtN,KAAK,CAACiN,SAAvC,CAAJ,EAAuD;EACrDQ,YAAAA,CAAC,CAAC,IAAD,CAAD,CAAQyB,IAAR,CAAa,UAAb,EAAyB,UAAzB;EACD,WAFD,MAEO;EACLzB,YAAAA,CAAC,CAAC,IAAD,CAAD,CAAQyB,IAAR,CAAa,UAAb,EAAyB,KAAzB;EACD;EACF;EACF,OAhBD;EAiBD,KA1CL;EAAA,KA4CKqB,EA5CL,CA4CQ,OA5CR,EA4CiB,oBA5CjB,EA4CuC,UAASlJ,CAAT,EAAY;EAC7CA,MAAAA,CAAC,CAAC3D,cAAF;EAEA,UAAMgN,KAAK,GAAGjD,CAAC,CAAC,IAAD,CAAf;EAEAiD,MAAAA,KAAK,CAACC,QAAN,CAAe,eAAf,EAAgCC,WAAhC;EACD,KAlDL;EAAA,KAoDKL,EApDL,CAoDQ,QApDR,EAoDkB,uBApDlB,EAoD2C,YAAW;EAChD,UAAMM,UAAU,GAAGpD,CAAC,CAAC,IAAD,CAAD,CAAQzP,MAAR,CAAe,YAAf,CAAnB;;EAEA,UAAI,KAAKoG,OAAT,EAAkB;EAChByM,QAAAA,UAAU,CAACC,OAAX,CAAmB,YAAnB,EAAiChE,QAAjC,CAA0C,kBAA1C,EAA8DoC,IAA9D,CAAmE,SAAnE,EAA8E,IAA9E;EACA2B,QAAAA,UAAU,CAACE,IAAX,CAAgB,oBAAhB,EAAsCnC,WAAtC,CAAkD,UAAlD;EACAiC,QAAAA,UAAU,CAACE,IAAX,CAAgB,gCAAhB,EAAkD7B,IAAlD,CAAuD,SAAvD,EAAkE,IAAlE;EACD,OAJD,MAIO;EACL2B,QAAAA,UAAU,CAACE,IAAX,CAAgB,6BAAhB,EAA+C7B,IAA/C,CAAoD,SAApD,EAA+D,KAA/D;EACA2B,QAAAA,UAAU,CAACE,IAAX,CAAgB,0CAAhB,EAA4DC,QAA5D,CAAqE,UAArE;EACAH,QAAAA,UAAU,CAACE,IAAX,CAAgB,sBAAhB,EAAwC7O,IAAxC,CAA6C,QAA7C,EAAuD,OAAvD,EAAgEyM,IAAhE,CAAqE,OAArE;EACD;EACF,KAhEL;EAAA,KAkEK4B,EAlEL,CAkEQ,QAlER,EAkEkB,sBAlElB,EAkE0C,YAAW;EAC/C,UAAMM,UAAU,GAAGpD,CAAC,CAAC,IAAD,CAAD,CAAQzP,MAAR,CAAe,YAAf,CAAnB;;EAEA,UAAI,KAAKoG,OAAT,EAAkB;EAChByM,QAAAA,UAAU,CAACC,OAAX,CAAmB,YAAnB,EAAiChE,QAAjC,CAA0C,kBAA1C,EAA8DoC,IAA9D,CAAmE,SAAnE,EAA8E,IAA9E;EACA2B,QAAAA,UAAU,CAACE,IAAX,CAAgB,oBAAhB,EAAsCnC,WAAtC,CAAkD,UAAlD;EACAiC,QAAAA,UAAU,CAACE,IAAX,CAAgB,gCAAhB,EAAkD7B,IAAlD,CAAuD,SAAvD,EAAkE,IAAlE;EACD,OAJD,MAIO;EACL2B,QAAAA,UAAU,CAACE,IAAX,CAAgB,6BAAhB,EAA+C7B,IAA/C,CAAoD,SAApD,EAA+D,KAA/D;EACA2B,QAAAA,UAAU,CAACE,IAAX,CAAgB,0CAAhB,EAA4DC,QAA5D,CAAqE,UAArE;EACAH,QAAAA,UAAU,CAACE,IAAX,CAAgB,sBAAhB,EAAwC7O,IAAxC,CAA6C,QAA7C,EAAuD,OAAvD,EAAgEyM,IAAhE,CAAqE,OAArE;EACD;EACF,KA9EL;EAAA,KAgFK4B,EAhFL,CAgFQ,OAhFR,EAgFiB,qBAhFjB,EAgFwC,YAAW;EAC7C;EACA5S,MAAAA,QAAQ,CAACsT,cAAT,CAAwB,qBAAxB,EAA+CtS,KAA/C,CAAqDC,OAArD,GAA+D,MAA/D,CAF6C;;EAK7C,UAAI,aAAa,OAAQyR,KAAzB,EAAiC;EAC/Ba,QAAAA,aAAa,CAACb,KAAD,CAAb;EACD;;EAED,UAAMvG,OAAO,GAAG,KAAK5F,KAArB;EAEAmM,MAAAA,KAAK,GAAGnR,UAAU,CACd,YAAW;EACTiS,QAAAA,IAAI,CACA;EACEjQ,UAAAA,MAAM,EAAE,mBADV;EAEEO,UAAAA,WAAW,EAAEzB,KAAK,CAACyB,WAFrB;EAGEC,UAAAA,KAAK,EAAE1B,KAAK,CAAC0B,KAHf;EAIEoI,UAAAA,OAAO,EAAEA;EAJX,SADA,EAOA,UAASjI,QAAT,EAAmB;EACjB,cAAIA,QAAQ,CAAC4N,MAAT,KAAoB,SAAxB,EAAmC;EACjCvB,YAAAA,KAAK,CAACG,GAAN,CAAU,qBAAV,EAAiCO,WAAjC,CAA6C,mBAA7C;EACAV,YAAAA,KAAK,CAACG,GAAN,CAAU,sBAAV,EAAkC+C,UAAlC,CAA6C,UAA7C;EACAlD,YAAAA,KAAK,CAACG,GAAN,CAAU,uBAAV,EAAmCM,IAAnC,CAAwC,EAAxC,EAA4CE,IAA5C;EACD,WAJD,MAIO;EACLX,YAAAA,KAAK,CAACG,GAAN,CAAU,qBAAV,EAAiC2C,QAAjC,CAA0C,mBAA1C;EACA9C,YAAAA,KAAK,CAACG,GAAN,CAAU,sBAAV,EAAkCa,IAAlC,CAAuC,UAAvC,EAAmD,IAAnD;EACAhB,YAAAA,KAAK,CAACG,GAAN,CAAU,uBAAV,EAAmCM,IAAnC,CAAwC9M,QAAQ,CAACS,OAAjD,EAA0D+G,IAA1D;EACD;EACF,SAjBD,CAAJ;EAmBD,OArBa,EAsBd,GAtBc,CAAlB;EAwBD,KAnHL;EAAA,KAqHKkH,EArHL,CAqHQ,OArHR,EAqHiB,sBArHjB,EAqHyC,YAAW;EAC9CZ,MAAAA,WAAW;EACXjC,MAAAA,IAAI,CAACC,WAAL,GAAmB,KAAnB;EACAD,MAAAA,IAAI,CAACG,OAAL,GAAe,KAAf;EACAH,MAAAA,IAAI,CAACM,WAAL,GAAmB,CAAnB;EACD,KA1HL,EA2HKuC,EA3HL,CA2HQ,OA3HR,EA2HiB,qBA3HjB,EA2HwC,YAAW;EAC7C,UAAI9C,CAAC,CAAC,wBAAD,CAAD,CAA4BtH,MAA5B,GAAqC,CAAzC,EAA4C;EAC1C;EACD;;EAED,UAAMkL,IAAI,GAAGzB,OAAO,CAAC,KAAK1L,KAAN,CAApB;EACA,UAAMoN,UAAU,GAAG7D,CAAC,CAAC,uBAAD,CAApB;EACA,UAAM8D,UAAU,GAAG9D,CAAC,CAAC,4BAAD,CAApB;EACA,UAAIhI,IAAI,GAAG6L,UAAU,CAACpP,IAAX,CAAgB,WAAhB,CAAX;EACA,UAAIsP,GAAG,GAAGD,UAAU,CAACrP,IAAX,CAAgB,UAAhB,CAAV;;EAEA,UAAIuD,IAAJ,EAAU;EACRA,QAAAA,IAAI,GAAGA,IAAI,CAACyD,OAAL,CAAa,OAAb,EAAsB,EAAtB,IAA4B,GAA5B,GAAkCmI,IAAlC,GAAyC,GAAhD;EACD;;EAED,UAAIG,GAAJ,EAAS;EACPA,QAAAA,GAAG,GAAGA,GAAG,CAACtI,OAAJ,CAAY,OAAZ,EAAqB,EAArB,IAA2B,GAA3B,GAAiCmI,IAAvC;EACD;;EAGD5D,MAAAA,CAAC,CAAC,8BAAD,CAAD,CAAkCkB,IAAlC,CAAuClJ,IAAvC;EACAgI,MAAAA,CAAC,CAAC,mCAAD,CAAD,CAAuCkB,IAAvC,CAA4C6C,GAA5C;EAEAF,MAAAA,UAAU,CAACb,IAAX,CAAgB,WAAhB,EAA6BhL,IAA7B;EACA8L,MAAAA,UAAU,CAACd,IAAX,CAAgB,UAAhB,EAA4Be,GAA5B;EACA/D,MAAAA,CAAC,CAAC,kBAAD,CAAD,CAAsBgD,IAAtB,CAA2B,aAA3B,EAA0ChL,IAA1C;EACAgI,MAAAA,CAAC,CAAC,uBAAD,CAAD,CAA2BgD,IAA3B,CAAgC,aAAhC,EAA+Ce,GAA/C;EACD,KAtJL,EAuJKjB,EAvJL,CAuJQ,OAvJR,EAuJiB,uBAvJjB,EAuJ0C,YAAW;EAC/C,UAAI9C,CAAC,CAAC,IAAD,CAAD,CAAQgE,GAAR,OAAkB,EAAlB,IAAwBC,kBAAkB,EAA9C,EAAkD;EAChDjE,QAAAA,CAAC,CAAC,6BAAD,CAAD,CAAiCrC,MAAjC;EACA;EACD;;EACD,UAAI,CAACsG,kBAAkB,EAAnB,IAAyB,CAACjE,CAAC,CAAC,6BAAD,CAAD,CAAiCtH,MAA/D,EAAuE;EACrEsH,QAAAA,CAAC,CAAC,wCAAD,CAAD,CAA4CkE,KAA5C,CAAkD,4KAAlD;EACD;EACF,KA/JL;EAkKAC,IAAAA,YAAY;EACb,GAzLD;EA2LA;;;EACA,MAAIF,kBAAkB,GAAG,SAArBA,kBAAqB,GAAW;EAClC,QAAMG,UAAU,GAAGpE,CAAC,CAAC,uBAAD,CAAD,CAA2BgE,GAA3B,EAAnB;;EAEA,QAAII,UAAU,KAAK,EAAnB,EAAuB;EACrB,aAAO,IAAP;EACD;;EAED,QAAMC,GAAG,GAAG,mBAAZ;;EACA,QAAIA,GAAG,CAACC,IAAJ,CAASF,UAAT,MAAyB,KAA7B,EAAoC;EAClC,aAAO,KAAP;EACD;;EACD,WAAO,IAAP;EACD,GAZD;EAcA;EACF;EACA;;;EACE,MAAID,YAAY,GAAG,SAAfA,YAAe,GAAW;EAC5B,QAAM3B,SAAS,GAAG/B,KAAK,CAACG,GAAN,CAAU,iBAAV,CAAlB;EAEA4B,IAAAA,SAAS;EAAA,KAEJM,EAFL,CAEQ,OAFR,EAEiB,uBAFjB,EAE0C,YAAW;EAC/C,UAAI,CAACyB,OAAO,CAAC,kDAAD,CAAZ,EAAkE;EAChE,eAAO,KAAP;EACD;;EAED,UAAMtB,KAAK,GAAGjD,CAAC,CAAC,IAAD,CAAf;EAEAA,MAAAA,CAAC,CAAC,oCAAD,CAAD,CAAwCoB,IAAxC;EACA6B,MAAAA,KAAK,CAACxB,IAAN,CAAW,UAAX,EAAuB,IAAvB;EAEAxB,MAAAA,IAAI,CAACC,WAAL,GAAmB,IAAnB;EACAD,MAAAA,IAAI,CAACM,WAAL,GAAmB,CAAnB;EAEAP,MAAAA,CAAC,CAAC,0BAAD,CAAD,CAA8BkB,IAA9B,CAAmC,yCAAnC;EACAlB,MAAAA,CAAC,CAAC,uCAAD,CAAD,CAA2CoB,IAA3C;EAEA6B,MAAAA,KAAK,CAAC1S,MAAN,GAAeiU,MAAf,CAAsB7D,WAAtB;EAEA8D,MAAAA,aAAa;EACd,KArBL;EAAA,KAuBK3B,EAvBL,CAuBQ,OAvBR,EAuBiB,uBAvBjB,EAuB0C,YAAW;EAC/CZ,MAAAA,WAAW;EACX,UAAMe,KAAK,GAAGjD,CAAC,CAAC,IAAD,CAAf;EAEAA,MAAAA,CAAC,CAAC,oCAAD,CAAD,CAAwCoB,IAAxC;EAEAnB,MAAAA,IAAI,CAACC,WAAL,GAAmB,KAAnB;EAEAF,MAAAA,CAAC,CAAC,0BAAD,CAAD,CAA8BkB,IAA9B,CAAmC,kCAAnC;EACAlB,MAAAA,CAAC,CAAC,sBAAD,CAAD,CAA0BoB,IAA1B;EACApB,MAAAA,CAAC,CAAC,eAAD,CAAD,CAAmBpE,IAAnB;EAEAqH,MAAAA,KAAK,CAAC1S,MAAN,GAAeiU,MAAf,CAAsB7D,WAAtB;EAEAV,MAAAA,IAAI,CAACyE,YAAL;EACD,KAtCL;EAAA,KAwCK5B,EAxCL,CAwCQ,OAxCR,EAwCiB,8BAxCjB,EAwCiD,YAAW;EACtDZ,MAAAA,WAAW;EAEX,UAAMe,KAAK,GAAGjD,CAAC,CAAC,IAAD,CAAf;EAEAA,MAAAA,CAAC,CAAC,oCAAD,CAAD,CAAwCoB,IAAxC;EACA6B,MAAAA,KAAK,CAACxB,IAAN,CAAW,UAAX,EAAuB,IAAvB;EAEAxB,MAAAA,IAAI,CAACC,WAAL,GAAmB,IAAnB;EAEAF,MAAAA,CAAC,CAAC,uBAAD,CAAD,CAA2BkB,IAA3B,CAAgC,yCAAhC;EACAlB,MAAAA,CAAC,CAAC,uCAAD,CAAD,CAA2CoB,IAA3C;EAEA6B,MAAAA,KAAK,CAAC1S,MAAN,GAAeiU,MAAf,CAAsB7D,WAAtB;EAEAgE,MAAAA,mBAAmB;EACpB,KAxDL;EAAA,KA0DK7B,EA1DL,CA0DQ,OA1DR,EA0DiB,wBA1DjB,EA0D2C,YAAW;EAChDZ,MAAAA,WAAW;EAEX,UAAMe,KAAK,GAAGjD,CAAC,CAAC,IAAD,CAAf;EAEAA,MAAAA,CAAC,CAAC,oCAAD,CAAD,CAAwCoB,IAAxC;EACA6B,MAAAA,KAAK,CAACxB,IAAN,CAAW,UAAX,EAAuB,IAAvB;EAEAxB,MAAAA,IAAI,CAACC,WAAL,GAAmB,IAAnB;EAEAF,MAAAA,CAAC,CAAC,uBAAD,CAAD,CAA2BkB,IAA3B,CAAgC,yCAAhC;EACAlB,MAAAA,CAAC,CAAC,uCAAD,CAAD,CAA2CoB,IAA3C;EAEA6B,MAAAA,KAAK,CAAC1S,MAAN,GAAeiU,MAAf,CAAsB7D,WAAtB;EAEAiE,MAAAA,OAAO;EACR,KA1EL;EAAA,KA4EK9B,EA5EL,CA4EQ,OA5ER,EA4EiB,iCA5EjB,EA4EoD,UAASlJ,CAAT,EAAY;EAC1DsI,MAAAA,WAAW;EACXtI,MAAAA,CAAC,CAAC3D,cAAF;EAEA,UAAM4O,eAAe,GAAGpE,KAAK,CAACG,GAAN,CAAU,wBAAV,CAAxB;EAEA4B,MAAAA,SAAS,CAACrB,WAAV,CAAsB,QAAtB;EAEAV,MAAAA,KAAK,CAACG,GAAN,CAAU,eAAV,EAA2BhF,IAA3B;EAEA8H,MAAAA,IAAI,CACA;EACEjQ,QAAAA,MAAM,EAAE,4BADV;EAEEO,QAAAA,WAAW,EAAEzB,KAAK,CAACyB,WAFrB;EAGEC,QAAAA,KAAK,EAAE1B,KAAK,CAAC0B,KAHf;EAIEuF,QAAAA,KAAK,EAAEwG,CAAC,CAAC,IAAD,CAAD,CAAQvL,IAAR,CAAa,OAAb;EAJT,OADA,EAOA,UAASL,QAAT,EAAmB;EACjBqM,QAAAA,KAAK,CAACG,GAAN,CAAU,uBAAV,EAAmC3C,IAAnC,CAAwC7J,QAAxC;EAEAyQ,QAAAA,eAAe,CAACxF,QAAhB,CAAyB,KAAzB,EAAgC1B,MAAhC;EAEA8C,QAAAA,KAAK,CAACG,GAAN,CAAU,eAAV,EAA2BQ,IAA3B;EAEApB,QAAAA,CAAC,CAAC,YAAD,CAAD,CAAgB8E,OAAhB,CAAwB;EACtB;EACAC,UAAAA,SAAS,EAAE/E,CAAC,CAAC,qBAAD,CAAD,CAAyBgF,MAAzB,GAAkCC,GAAlC,GAAwCjF,CAAC,CAACtO,MAAD,CAAD,CAAUL,MAAV,EAAxC,GACG2O,CAAC,CAAC,qBAAD,CAAD,CAAyB3O,MAAzB,EADH,GACuC;EAH5B,SAAxB,EAIG,GAJH;EAKD,OAnBD,EAoBA,MApBA,CAAJ;EAsBD,KA5GL;EAAA,KA8GKyR,EA9GL,CA8GQ,OA9GR,EA8GiB,qBA9GjB,EA8GwC,UAASlJ,CAAT,EAAY;EAC9CsI,MAAAA,WAAW;EACXtI,MAAAA,CAAC,CAAC3D,cAAF;EAEAwK,MAAAA,KAAK,CAACG,GAAN,CAAU,uBAAV,EAAmC2C,QAAnC,CAA4C,SAA5C;EAEA9C,MAAAA,KAAK,CAACG,GAAN,CAAU,eAAV,EAA2BhF,IAA3B;EAEAsJ,MAAAA,WAAW,CAAClF,CAAC,CAAC,IAAD,CAAD,CAAQvL,IAAR,CAAa,OAAb,CAAD,CAAX;EACD,KAvHL;EAAA,KAyHKqO,EAzHL,CAyHQ,OAzHR,EAyHiB,wBAzHjB,EAyH2C,UAASlJ,CAAT,EAAY;EACjDA,MAAAA,CAAC,CAAC3D,cAAF;EACA+J,MAAAA,CAAC,CAAC,cAAD,CAAD,CAAkBmB,WAAlB,CAA8B,QAA9B;EACAV,MAAAA,KAAK,CAACG,GAAN,CAAU,uBAAV,EAAmC3C,IAAnC,CAAwC,EAAxC;EACD,KA7HL;EAAA,KA+HK6E,EA/HL,CA+HQ,OA/HR,EA+HiB,sBA/HjB,EA+HyC,UAASlJ,CAAT,EAAY;EAC/CA,MAAAA,CAAC,CAAC3D,cAAF;EAEA,UAAMuD,KAAK,GAAGwG,CAAC,CAAC,IAAD,CAAD,CAAQvL,IAAR,CAAa,OAAb,CAAd;EAEA+N,MAAAA,SAAS,CAACe,QAAV,CAAmB,SAAnB;EACAtD,MAAAA,IAAI,CAACO,mBAAL,GAA2B,IAA3B;EACAkD,MAAAA,IAAI,CACA;EACEjQ,QAAAA,MAAM,EAAE,gBADV;EAEE+F,QAAAA,KAAK,EAAEA,KAFT;EAGExF,QAAAA,WAAW,EAAEzB,KAAK,CAACyB,WAHrB;EAIEC,QAAAA,KAAK,EAAE1B,KAAK,CAAC0B;EAJf,OADA,EAOA,UAASG,QAAT,EAAmB;EACjB,YAAIA,QAAQ,CAACsE,MAAT,GAAkB,CAAtB,EAAyB;EACvBsI,UAAAA,SAAS,CACL,2OADK,CAAT;EAGD;;EAED,YAAMmE,YAAY,GAAGC,YAAY,CAAChR,QAAD,CAAjC;;EACA,YAAI+Q,YAAY,KAAK,KAAjB,IAA0BA,YAAY,CAACzQ,OAAb,KAAyB,KAAvD,EAA8D;EAC5D8N,UAAAA,SAAS,CAACrB,WAAV,CAAsB,SAAtB;EACAkE,UAAAA,cAAc,CAACF,YAAD,CAAd;EAEA;EACD;;EAED3C,QAAAA,SAAS,CAACrB,WAAV,CAAsB,SAAtB,EAAiClD,IAAjC,CAAsC7J,QAAtC,EAfiB;;EAiBjBkR,QAAAA,cAAc;EACdrF,QAAAA,IAAI,CAACpD,kBAAL,GAA0B,IAAI3H,wBAAJ,CAA6B,4BAA7B,EAA2D3C,KAA3D,EAAkE0N,IAAI,CAACrN,KAAvE,CAA1B;EACAqN,QAAAA,IAAI,CAACO,mBAAL,GAA2B,IAAI7H,mBAAJ,EAA3B;EACAsH,QAAAA,IAAI,CAACsF,UAAL,CAAgB,CAAhB;EACD,OA5BD,EA6BA,MA7BA,CAAJ;EA+BD,KArKL;EAAA,KAuKKzC,EAvKL,CAuKQ,OAvKR,EAuKiB,oBAvKjB,EAuKuC,UAASlJ,CAAT,EAAY;EAC7CA,MAAAA,CAAC,CAAC3D,cAAF;EACA,UAAMuD,KAAK,GAAGwG,CAAC,CAAC,IAAD,CAAD,CAAQvL,IAAR,CAAa,OAAb,CAAd;EACA,UAAM+Q,UAAU,GAAG,IAAIpJ,eAAJ,CAAoB5C,KAApB,CAAnB;EACA,UAAMiM,OAAO,GAAGD,UAAU,CAAC5H,SAAX,EAAhB;EAEA6H,MAAAA,OAAO,CAACtR,IAAR,CAAa,UAAClC,MAAD,EAAY;EACvB,YAAIA,MAAM,CAACwE,KAAX,EAAkB;EAChB,cAAMiP,YAAY,GAAGF,UAAU,CAACzG,qBAAX,EAArB;EACA,cAAM4G,WAAW,GAAGH,UAAU,CAACzL,iBAAX,GAA+BA,iBAA/B,EAApB;EACA0E,UAAAA,UAAU,CAACjF,KAAD,EAAQ;EAChBoM,YAAAA,cAAc,EAAEC,iBAAiB,EADjB;EAEhBC,YAAAA,gBAAgB,EAAEC,kBAAkB,CAACJ,WAAW,CAACK,KAAb,CAFpB;EAGhBC,YAAAA,gBAAgB,EAAEF,kBAAkB,CAACJ,WAAW,CAACO,KAAb,CAHpB;EAIhBpQ,YAAAA,mBAAmB,EAAE4P,YAAY,CAAClO,sBAAb,EAJL;EAKhBa,YAAAA,gBAAgB,EAAEqN,YAAY,CAACtN,2BAAb;EALF,WAAR,CAAV;EAOD;EACF,OAZD;EAcA;EACD,KA5LL;EA6LD,GAhMD;EAkMA;EACF;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;EACE,MAAIsL,IAAI,GAAG,SAAPA,IAAO,CAASjP,IAAT,EAAesH,QAAf,EAAyBoK,QAAzB,EAAmCC,UAAnC,EAA+CC,QAA/C,EAAyDC,cAAzD,EAAgF;EAAA,QAAvBA,cAAuB;EAAvBA,MAAAA,cAAuB,GAAN,IAAM;EAAA;;EACzF,QAAI,gBAAgB,OAAQH,QAA5B,EAAuC;EACrCA,MAAAA,QAAQ,GAAG,MAAX;EACD;;EAED,QAAI,UAAUC,UAAd,EAA0B;EACxBA,MAAAA,UAAU,GAAG,IAAb;EACD;;EAEDC,IAAAA,QAAQ,GAAG,gBAAgB,OAAQA,QAAxB,GAAoC,CAApC,GAAwCA,QAAnD;EAEA,QAAME,UAAU,GAAG,EAAnB;EAEA,QAAIC,YAAY,GAAG,QAAQH,QAA3B;EAEAC,IAAAA,cAAc,GAAGG,QAAQ,CAACH,cAAD,CAAzB;;EACA,QAAI,CAACI,KAAK,CAACJ,cAAD,CAAV,EAA4B;EAC1BE,MAAAA,YAAY,IAAIF,cAAhB;EACD;;EAEDtG,IAAAA,CAAC,CAAC0D,IAAF,CAAO;EACLtB,MAAAA,GAAG,EAAEO,OAAO,GAAG,6BAAV,GAA2CgE,IAAI,CAACC,GAAL,KAAa,IADxD;EAELzT,MAAAA,IAAI,EAAE,MAFD;EAGLgT,MAAAA,QAAQ,EAAEA,QAHL;EAIL1F,MAAAA,KAAK,EAAE,KAJF;EAKLhM,MAAAA,IAAI,EAAEA,IALD;EAMLK,MAAAA,KAAK,EAAE,eAAS+R,GAAT,EAAcC,UAAd,EAA0BC,WAA1B,EAAuC;EAC5C;EACAV,QAAAA,QAAQ;;EACR,YAAIA,QAAQ,IAAIE,UAAhB,EAA4B;EAC1B9U,UAAAA,UAAU,CAAC,YAAW;EACpBiS,YAAAA,IAAI,CAACjP,IAAD,EAAOsH,QAAP,EAAiBoK,QAAjB,EAA2BC,UAA3B,EAAuCC,QAAvC,EAAiDC,cAAjD,CAAJ;EACA;EACD,WAHS,EAGPE,YAHO,CAAV;EAID,SALD,MAKO;EACL,cAAMQ,SAAS,GAAG,gBAAgB,OAAQH,GAAG,CAAC7E,MAA5B,GAAsC,SAAtC,GAAkD6E,GAAG,CAAC7E,MAAxE;EACAhB,UAAAA,SAAS,CACL,mBAAmBgG,SAAnB,GAA+B,iMAD1B,CAAT;EAGD;EACF,OApBI;EAqBLtS,MAAAA,OAAO,EAAE,iBAASD,IAAT,EAAe;EACtB,YAAI,eAAe,OAAQsH,QAA3B,EAAsC;EACpCA,UAAAA,QAAQ,CAACtH,IAAD,CAAR;EACD;EACF,OAzBI;EA0BLwS,MAAAA,UAAU,EAAE;EACV,aAAK,aAAW;EACd,cAAIZ,QAAQ,IAAIE,UAAhB,EAA4B;EAC1BvF,YAAAA,SAAS,CAAC,0OAAD,CAAT;EACD;EACF,SALS;EAMV,aAAK,aAAW;EACd,cAAIqF,QAAQ,IAAIE,UAAhB,EAA4B;EAC1BvF,YAAAA,SAAS,CAAC,sQAAD,CAAT;EACD;EACF,SAVS;EAWV,aAAK,aAAW;EACd,cAAIqF,QAAQ,GAAGE,UAAf,EAA2B;EACzBvF,YAAAA,SAAS,CAAC,gUAAD,CAAT;EACD;EACF,SAfS;EAgBV,aAAK,aAAW;EACd,cAAIqF,QAAQ,IAAIE,UAAhB,EAA4B;EAC1BvF,YAAAA,SAAS,CAAC,gUAAD,CAAT;EACD;EACF,SApBS;EAqBV,aAAK,aAAW;EACd,cAAIqF,QAAQ,IAAIE,UAAhB,EAA4B;EAC1BvF,YAAAA,SAAS,CAAC,gUAAD,CAAT;EACD;EACF,SAzBS;EA0BV,aAAK,aAAW;EACd,cAAIqF,QAAQ,IAAIE,UAAhB,EAA4B;EAC1BvF,YAAAA,SAAS,CAAC,gUAAD,CAAT;EACD;EACF,SA9BS;EA+BV,aAAK,aAAW;EACd,cAAIqF,QAAQ,IAAIE,UAAhB,EAA4B;EAC1BvF,YAAAA,SAAS,CAAC,gFAAD,CAAT;EACD;EACF;EAnCS;EA1BP,KAAP;EAgED,GApFD;EAsFA;EACF;EACA;;;EACE,MAAMkG,WAAW,GAAG,SAAdA,WAAc,GAAW;EAC7B,QAAM1E,SAAS,GAAG/B,KAAK,CAACG,GAAN,CAAU,iBAAV,CAAlB;EAEA4B,IAAAA,SAAS;EAAA,KAEJM,EAFL,CAEQ,OAFR,EAEiB,uBAFjB,EAE0C,UAASlJ,CAAT,EAAY;EAChDA,MAAAA,CAAC,CAAC3D,cAAF;EAEA,UAAMgN,KAAK,GAAGjD,CAAC,CAAC,IAAD,CAAf;;EAGA,UAAIA,CAAC,CAAC,uBAAD,CAAD,CAA2BtH,MAA3B,IAAqC,CAACuL,kBAAkB,EAA5D,EAAgE;EAC9DjE,QAAAA,CAAC,CAAC,uBAAD,CAAD,CAA2BmH,KAA3B;EACA,eAAO,KAAP;EACD;;EAED,UAAIlE,KAAK,CAACxO,IAAN,CAAW,QAAX,MAAyB,cAAzB,IAA2CwO,KAAK,CAACxO,IAAN,CAAW,QAAX,MAAyB,aAAxE,EAAuF;EACvF;EACE,YAAI2S,iBAAiB,GAAG,EAAxB;;EACA,YAAInE,KAAK,CAACxO,IAAN,CAAW,QAAX,MAAyB,cAA7B,EAA6C;EAC3C2S,UAAAA,iBAAiB,GAAG,qNAApB;EACD;;EAED,YAAI,CAAC7C,OAAO,CAAC,6MAA6M6C,iBAA9M,CAAZ,EAA8O;EAC5O,iBAAO,KAAP;EACD;EACF,OArB+C;;;EAwBhD,UAAInE,KAAK,CAACD,IAAN,CAAW,UAAX,CAAJ,EAA4B;EAC1B,eAAO,KAAP;EACD;;EAED,UAAIC,KAAK,CAACxO,IAAN,CAAW,QAAX,MAAyB,eAA7B,EAA8C;EAC9C;EACE,YAAIuL,CAAC,CAAC,eAAD,CAAD,CAAmBqH,EAAnB,CAAsB,UAAtB,CAAJ,EAAuC;EACrCC,UAAAA,sBAAsB,CAACrE,KAAD,EAAQT,SAAR,CAAtB;EACA;EACD;EACF;;EAED+E,MAAAA,cAAc,CAACtE,KAAD,EAAQT,SAAR,CAAd;EACD,KAvCL;EAAA,KAyCKM,EAzCL,CAyCQ,OAzCR,EAyCiB,uBAzCjB,EAyC0C,UAASlJ,CAAT,EAAY;EAChDA,MAAAA,CAAC,CAAC3D,cAAF;EACAwK,MAAAA,KAAK,CAACG,GAAN,CAAU,eAAV,EAA2BO,WAA3B,CAAuC,gBAAvC;EACAV,MAAAA,KAAK,CAACG,GAAN,CAAU,eAAV,EAA2BQ,IAA3B;EACAoG,MAAAA,YAAY;EACb,KA9CL;EA+CD,GAlDD;EAoDA;EACF;EACA;EACA;;;EACE,MAAM3B,iBAAiB,GAAG,SAApBA,iBAAoB,GAAW;EACnC,QAAMD,cAAc,GAAG,EAAvB;EAEA5F,IAAAA,CAAC,CAAC,8CAAD,CAAD,CAAkD+C,IAAlD,CAAuD,YAAW;EAChE6C,MAAAA,cAAc,CAACzT,IAAf,CAAoB,KAAKsE,KAAzB;EACD,KAFD;EAIA,WAAOmP,cAAP;EACD,GARD;EAUA;EACF;EACA;EACA;EACA;;;EACE,MAAM6B,iBAAiB,GAAG,SAApBA,iBAAoB,GAAW;EACnC,QAAMC,cAAc,GAAG,EAAvB;EAEA1H,IAAAA,CAAC,CAAC,qCAAD,CAAD,CAAyC+C,IAAzC,CAA8C,YAAW;EACvD2E,MAAAA,cAAc,CAACvV,IAAf,CAAoB,KAAKwN,IAAzB;EACD,KAFD;EAIA,WAAO+H,cAAP;EACD,GARD;EAUA;EACF;EACA;;;EACE,MAAIJ,sBAAsB,GAAG,SAAzBA,sBAAyB,CAASrE,KAAT,EAAgBxG,QAAhB,EAA0B;EACrDgE,IAAAA,KAAK,CAACG,GAAN,CAAU,eAAV,EAA2BhF,IAA3B;EACA8H,IAAAA,IAAI,CACA;EACEjQ,MAAAA,MAAM,EAAE,6BADV;EAEEO,MAAAA,WAAW,EAAEzB,KAAK,CAACyB,WAFrB;EAGEC,MAAAA,KAAK,EAAE1B,KAAK,CAAC0B,KAHf;EAIE0T,MAAAA,YAAY,EAAElH,KAAK,CAACG,GAAN,CAAU,oBAAV,EAAgCoD,GAAhC,EAJhB;EAKE4D,MAAAA,gBAAgB,EAAEnH,KAAK,CAACG,GAAN,CAAU,oBAAV,EAAgCoD,GAAhC,EALpB;EAME6D,MAAAA,cAAc,EAAEpH,KAAK,CAACG,GAAN,CAAU,kBAAV,EAA8BoD,GAA9B,EANlB;EAOE8D,MAAAA,gBAAgB,EAAErH,KAAK,CAACG,GAAN,CAAU,oBAAV,EAAgCoD,GAAhC;EAPpB,KADA,EAUA,UAAS5P,QAAT,EAAmB;EACnB;EACE,UAAI,UAAUA,QAAd,EAAwB;EACtB4M,QAAAA,SAAS,CACL,8CACJ,2CADI,GAEJ,0FAHS,CAAT;EAKAP,QAAAA,KAAK,CAACG,GAAN,CAAU,eAAV,EAA2BQ,IAA3B;EACA;EACD,OAVgB;;;EAajB,UAAI,gBAAgB,OAAQhN,QAAQ,CAACM,OAArC,EAA+C;EAC7CsM,QAAAA,SAAS,CACL,mDACJ,2CADI,GAEJ,0FAHS,CAAT;EAKAP,QAAAA,KAAK,CAACG,GAAN,CAAU,eAAV,EAA2BQ,IAA3B;EACA;EACD;;EAED,UAAIhN,QAAQ,CAACM,OAAb,EAAsB;EACpB+L,QAAAA,KAAK,CAACG,GAAN,CAAU,eAAV,EAA2BQ,IAA3B;EACAmG,QAAAA,cAAc,CAACtE,KAAD,EAAQxG,QAAR,CAAd;EACA;EACD;;EAED,UAAIrI,QAAQ,CAAC2T,UAAT,KAAwB,YAA5B,EAA0C;EACxCtH,QAAAA,KAAK,CAACG,GAAN,CAAU,eAAV,EAA2BQ,IAA3B;EACA,YAAI4G,MAAM,GAAG,sIAAb;EACA5T,QAAAA,QAAQ,CAAC6T,MAAT,CAAgBxQ,OAAhB,CAAwB,UAAC1E,CAAD,EAAO;EAC7B,cAAIM,IAAI,GAAG,iCAAX;;EACA,cAAIN,CAAC,CAACmV,UAAF,KAAiBnV,CAAC,CAACoV,OAAvB,EAAgC;EAC9B9U,YAAAA,IAAI,GAAG,iCAAP;EACD;;EACD2U,UAAAA,MAAM,IAAI,aAAajV,CAAC,CAAC4M,IAAf,GAAsB,WAAtB,GAAoC5M,CAAC,CAACmV,UAAtC,GAAmD,WAAnD,GAAiEnV,CAAC,CAACoV,OAAnE,GAA6E,WAA7E,GAA2F9U,IAA3F,GAAkG,YAA5G;EACD,SAND;EAOA2U,QAAAA,MAAM,IAAI,iIAAV;EACAhM,QAAAA,IAAI,CAACC,IAAL,CAAU;EACR+B,UAAAA,KAAK,EAAE,+BADC;EAER3K,UAAAA,IAAI,EAAE,SAFE;EAGR4K,UAAAA,IAAI,EAAE+J,MAHE;EAIR7J,UAAAA,KAAK,EAAE,OAJC;EAKRC,UAAAA,YAAY,EAAE,KALN;EAMRI,UAAAA,iBAAiB,EAAE,gBANX;EAORE,UAAAA,gBAAgB,EAAE;EAPV,SAAV,EAQGvK,IARH,CAQQ,UAASlC,MAAT,EAAiB;EACvB,cAAIA,MAAM,CAACwE,KAAX,EAAkB;EAChB8Q,YAAAA,cAAc,CAACtE,KAAD,EAAQxG,QAAR,CAAd;EACD;EACF,SAZD;EAaA;EACD;;EAEDT,MAAAA,IAAI,CAACC,IAAL,CAAU;EACR+B,QAAAA,KAAK,EAAE,+BADC;EAER3K,QAAAA,IAAI,EAAE,OAFE;EAGR4K,QAAAA,IAAI,EAAE7J,QAAQ,CAACS,OAHP;EAIRuJ,QAAAA,YAAY,EAAE,IAJN;EAKRI,QAAAA,iBAAiB,EAAE,IALX;EAMRE,QAAAA,gBAAgB,EAAE;EANV,OAAV;EAQA+B,MAAAA,KAAK,CAACG,GAAN,CAAU,eAAV,EAA2BQ,IAA3B;EACD,KA3ED,EA4EA,MA5EA,EA6EA,KA7EA,CAAJ;EA+ED,GAjFD;EAmFA;EACF;EACA;;;EACE,MAAMgH,cAAc,GAAG,SAAjBA,cAAiB,GAAW;EAChC,QAAI,oBAAoBnI,IAAI,CAACxL,IAAL,CAAUhB,MAA9B,IAAwC,mBAAmBwM,IAAI,CAACxL,IAAL,CAAUhB,MAArE,IAA+E,kBAAkBwM,IAAI,CAACxL,IAAL,CAAUhB,MAA/G,EAAuH;EACrH;EACD;;EAEDwM,IAAAA,IAAI,CAACxL,IAAL,CAAU4H,OAAV,GAAoB2D,CAAC,CAAC,qBAAD,CAAD,CAAyBgE,GAAzB,MAAkC,IAAI2C,IAAJ,GAAW0B,OAAX,GAAqBhG,QAArB,EAAtD,CALgC;EAOhC;;EAEA,QAAIpC,IAAI,CAACpD,kBAAL,KAA4B,IAAhC,EAAsC;EACpCoD,MAAAA,IAAI,CAACxL,IAAL,CAAUqB,mBAAV,GAAgCiQ,kBAAkB,CAAC9F,IAAI,CAACpD,kBAAL,CAAwBrF,sBAAxB,EAAD,CAAlD;EACAyI,MAAAA,IAAI,CAACxL,IAAL,CAAU4D,gBAAV,GAA6B0N,kBAAkB,CAAC9F,IAAI,CAACpD,kBAAL,CAAwBzE,2BAAxB,EAAD,CAA/C;EACD;;EAED6H,IAAAA,IAAI,CAACxL,IAAL,CAAUwR,gBAAV,GAA6B,EAA7B;EACAhG,IAAAA,IAAI,CAACxL,IAAL,CAAUqR,gBAAV,GAA6B,EAA7B;;EACA,QAAI7F,IAAI,CAACO,mBAAL,YAAoC7H,mBAAxC,EAA6D;EAC3D,UAAM2P,KAAK,GAAGrI,IAAI,CAACO,mBAAL,CAAyBzG,iBAAzB,EAAd;EACAkG,MAAAA,IAAI,CAACxL,IAAL,CAAUwR,gBAAV,GAA6BF,kBAAkB,CAACuC,KAAK,CAACpC,KAAP,CAA/C;EACAjG,MAAAA,IAAI,CAACxL,IAAL,CAAUqR,gBAAV,GAA6BC,kBAAkB,CAACuC,KAAK,CAACtC,KAAP,CAA/C;EACD;;EAED/F,IAAAA,IAAI,CAACxL,IAAL,CAAUmR,cAAV,GAA2BC,iBAAiB,EAA5C;EACA5F,IAAAA,IAAI,CAACxL,IAAL,CAAUoT,cAAV,GAA2B7H,CAAC,CAAC,kBAAD,CAAD,CAAsBgE,GAAtB,EAA3B;EACA/D,IAAAA,IAAI,CAACxL,IAAL,CAAUkT,YAAV,GAAyB3H,CAAC,CAAC,oBAAD,CAAD,CAAwBgE,GAAxB,EAAzB;EACA/D,IAAAA,IAAI,CAACxL,IAAL,CAAUmT,gBAAV,GAA6B5H,CAAC,CAAC,oBAAD,CAAD,CAAwBgE,GAAxB,EAA7B;EACA/D,IAAAA,IAAI,CAACxL,IAAL,CAAUqT,gBAAV,GAA6B9H,CAAC,CAAC,oBAAD,CAAD,CAAwBgE,GAAxB,EAA7B;EACA/D,IAAAA,IAAI,CAACxL,IAAL,CAAU8T,cAAV,GAA2BvI,CAAC,CAAC,kBAAD,CAAD,CAAsBgE,GAAtB,EAA3B;EACA,QAAMwE,QAAQ,GAAGxI,CAAC,CAAC,kBAAD,CAAD,CAAsBgE,GAAtB,EAAjB;EACA/D,IAAAA,IAAI,CAACxL,IAAL,CAAU+T,QAAV,GAAqBzC,kBAAkB,CAAC/F,CAAC,CAAClG,IAAF,CAAO0O,QAAP,CAAD,CAAvC;EACAvI,IAAAA,IAAI,CAACxL,IAAL,CAAUgU,aAAV,GAA0BzI,CAAC,CAAC,uBAAD,CAAD,CAA2BgE,GAA3B,EAA1B;EACA/D,IAAAA,IAAI,CAACxL,IAAL,CAAUiU,aAAV,GAA0B1I,CAAC,CAAC,qBAAD,CAAD,CAAyBqH,EAAzB,CAA4B,UAA5B,CAA1B;EACApH,IAAAA,IAAI,CAACxL,IAAL,CAAUkU,gBAAV,GAA6B3I,CAAC,CAAC,uBAAD,CAAD,CAA2BqH,EAA3B,CAA8B,UAA9B,CAA7B;EACApH,IAAAA,IAAI,CAACxL,IAAL,CAAUmU,kBAAV,GAA+B5I,CAAC,CAAC,6BAAD,CAAD,CAAiCqH,EAAjC,CAAoC,UAApC,CAA/B;EACApH,IAAAA,IAAI,CAACxL,IAAL,CAAUoU,eAAV,GAA4B7I,CAAC,CAAC,sBAAD,CAAD,CAA0BqH,EAA1B,CAA6B,UAA7B,CAA5B;EACD,GAnCD;;EAqCA,MAAIE,cAAc,GAAG,SAAjBA,cAAiB,CAAStE,KAAT,EAAgBxG,QAAhB,EAA0B;EAC7C;EACAA,IAAAA,QAAQ,CAAC8G,QAAT,CAAkB,SAAlB,EAF6C;;EAK7CtD,IAAAA,IAAI,CAACxL,IAAL,GAAY;EACVhB,MAAAA,MAAM,EAAEwP,KAAK,CAACxO,IAAN,CAAW,QAAX,CADE;EAEVT,MAAAA,WAAW,EAAEzB,KAAK,CAACyB,WAFT;EAGVC,MAAAA,KAAK,EAAE1B,KAAK,CAAC0B;EAHH,KAAZ,CAL6C;;EAY7CmU,IAAAA,cAAc;EAEdU,IAAAA,eAAe,CAACrM,QAAD,CAAf;EACD,GAfD;;EAiBA,MAAIqM,eAAe,GAAG,SAAlBA,eAAkB,CAASrM,QAAT,EAAmB;EACvC;EACAiH,IAAAA,IAAI,CACAzD,IAAI,CAACxL,IADL,EAEA,UAASL,QAAT,EAAmB;EACnB;EACE,UAAI,UAAUA,QAAd,EAAwB;EACtB4M,QAAAA,SAAS,CACL,6JACJ,wCADI,GAEJ,0FAHS,CAAT;EAKD;;EAGD,UAAI5M,QAAQ,CAACsE,MAAT,GAAkB,CAAtB,EAAyB;EACvBsI,QAAAA,SAAS,CACL,iKACJ,wCADI,GAEJ,0FAHS,CAAT;EAKD;;EAED,UAAMmE,YAAY,GAAGC,YAAY,CAAChR,QAAD,CAAjC;;EACA,UAAI+Q,YAAY,KAAK,KAAjB,IAA0BA,YAAY,CAACzQ,OAAb,KAAyB,KAAvD,EAA8D;EAC5D+H,QAAAA,QAAQ,CAAC0E,WAAT,CAAqB,SAArB;EACAkE,QAAAA,cAAc,CAACF,YAAD,CAAd;EAEA;EACD,OAzBgB;;;EA4BjB1I,MAAAA,QAAQ,CAAC0E,WAAT,CAAqB,SAArB,EAAgClD,IAAhC,CAAqC7J,QAArC;EACA6L,MAAAA,IAAI,CAACO,mBAAL,GAA2B,IAA3B;;EACA,UAAIP,IAAI,CAACxL,IAAL,CAAUhB,MAAV,KAAqB,gBAAzB,EAA2C;EACzCwM,QAAAA,IAAI,CAACpD,kBAAL,GAA0B,IAAI3H,wBAAJ,CAA6B,4BAA7B,EAA2D3C,KAA3D,EAAkE0N,IAAI,CAACrN,KAAvE,CAA1B;EACAqN,QAAAA,IAAI,CAACsF,UAAL,CAAgB,CAAhB;EACAtF,QAAAA,IAAI,CAACO,mBAAL,GAA2B,IAAI7H,mBAAJ,EAA3B;EACD,OAJD,MAIO,IAAIsH,IAAI,CAACxL,IAAL,CAAUhB,MAAV,KAAqB,eAArB,IAAwCwM,IAAI,CAACxL,IAAL,CAAUhB,MAAV,KAAqB,cAA7D,IAA+EwM,IAAI,CAACxL,IAAL,CAAUhB,MAAV,KAAqB,aAAxG,EAAuH;EAC5HwM,QAAAA,IAAI,CAACsF,UAAL,CAAgB,CAAhB;EACD,OApCgB;;;EAuCjBtF,MAAAA,IAAI,CAACyE,YAAL;EACD,KA1CD,EA2CA,MA3CA,CAAJ;EA6CD,GA/CD;;EAiDA,MAAIW,cAAc,GAAG,SAAjBA,cAAiB,CAASjR,QAAT,EAAmB;EACtC,QAAMwK,UAAU,GAAG,IAAIlD,UAAJ,CAAe,mBAAf,EAAoCnJ,KAApC,CAAnB;EACAqM,IAAAA,UAAU,CAAChD,IAAX,CAAgBvB,MAAM,CAAC8B,MAAP,CAAc;EAC5B6B,MAAAA,KAAK,EAAE,OADqB;EAE5B3K,MAAAA,IAAI,EAAE,OAFsB;EAG5B4K,MAAAA,IAAI,EAAE1L,KAAK,CAACwC,IAAN,CAAW,oBAAX,CAHsB;EAI5BoJ,MAAAA,KAAK,EAAE,OAJqB;EAK5BK,MAAAA,iBAAiB,EAAE,IALS;EAM5BE,MAAAA,gBAAgB,EAAE;EANU,KAAd,EAObtK,QAAQ,CAACyH,WAPI,CAAhB,EAO0B;EACxB1I,MAAAA,IAAI,EAAEiB,QAAQ,CAACjB;EADS,KAP1B;EAUD,GAZD;;EAcA,MAAMiS,YAAY,GAAG,SAAfA,YAAe,CAAS9Q,IAAT,EAAe;EAClC;EACA,QAAI,CAACA,IAAL,EAAW;EACT,aAAO,KAAP;EACD;;EAED,QAAI;EACF,UAAMyU,MAAM,GAAG5R,IAAI,CAACC,KAAL,CAAW9C,IAAX,CAAf;;EACA,UAAIyU,MAAM,IAAI,OAAOA,MAAP,KAAkB,QAAhC,EAA0C;EACxC,eAAOA,MAAP;EACD;EACF,KALD,CAKE,OAAOnP,CAAP,EAAU;EAEX;;EAED,WAAO,KAAP;EACD,GAhBD;;EAkBA,MAAI6E,UAAU,GAAG,SAAbA,UAAa,CAASjF,KAAT,EAAgBwP,cAAhB,EAAgC;EAC/C/I,IAAAA,IAAI,CAACxL,IAAL,GAAY;EACVhB,MAAAA,MAAM,EAAE,aADE;EAEVO,MAAAA,WAAW,EAAEzB,KAAK,CAACyB,WAFT;EAGVC,MAAAA,KAAK,EAAE1B,KAAK,CAAC0B,KAHH;EAIVoI,MAAAA,OAAO,EAAE7C;EAJC,KAAZ;EAOAyG,IAAAA,IAAI,CAACxL,IAAL,gBAAgBwL,IAAI,CAACxL,IAArB,EAA8BuU,cAA9B;EAEA,QAAMxG,SAAS,GAAG/B,KAAK,CAACG,GAAN,CAAU,iBAAV,CAAlB;EACAkI,IAAAA,eAAe,CAACtG,SAAD,CAAf;EACD,GAZD;EAcA;EACF;EACA;;;EACE,MAAIgF,YAAY,GAAG,SAAfA,YAAe,GAAW;EAC5B,QAAMhF,SAAS,GAAG/B,KAAK,CAACG,GAAN,CAAU,iBAAV,CAAlB;EAEA4B,IAAAA,SAAS,CAACe,QAAV,CAAmB,SAAnB;EAEAG,IAAAA,IAAI,CACA;EACEjQ,MAAAA,MAAM,EAAE,gBADV;EAEEO,MAAAA,WAAW,EAAEzB,KAAK,CAACyB,WAFrB;EAGEC,MAAAA,KAAK,EAAE1B,KAAK,CAAC0B;EAHf,KADA,EAMA,UAASG,QAAT,EAAmB;EACjB,UAAIA,QAAQ,CAACsE,MAAT,GAAkB,CAAtB,EAAyB;EACvBsI,QAAAA,SAAS,CACL,oNADK,CAAT;EAGD;;EAED,MAAqBP,KAAK,CAACG,GAAN,CAAU,qBAAV,EAPJ;;EAUjB4B,MAAAA,SAAS,CAACrB,WAAV,CAAsB,SAAtB,EAAiClD,IAAjC,CAAsC7J,QAAtC;EACD,KAjBD,EAkBA,MAlBA,CAAJ;EAqBA6L,IAAAA,IAAI,CAACsF,UAAL,CAAgB,CAAhB;EACA9E,IAAAA,KAAK,CAACG,GAAN,CAAU,sBAAV,EAAkChF,IAAlC;EACA6E,IAAAA,KAAK,CAACG,GAAN,CAAU,sBAAV,EAAkCQ,IAAlC;EACD,GA7BD;EA+BA;EACF;EACA;;;EACE,MAAM6H,IAAI,GAAG,SAAPA,IAAO,GAAW;EACtBxI,IAAAA,KAAK,CAACG,GAAN,CAAU,iBAAV,EAA6BkC,EAA7B,CAAgC,OAAhC,EAAyC,mBAAzC,EAA8D,UAASlJ,CAAT,EAAY;EACxEA,MAAAA,CAAC,CAAC3D,cAAF;EAEA,UAAMgN,KAAK,GAAGjD,CAAC,CAAC,IAAD,CAAf;EACA,UAAMkJ,QAAQ,GAAGzI,KAAK,CAACG,GAAN,CAAUqC,KAAK,CAACxO,IAAN,CAAW,IAAX,CAAV,CAAjB;EAEAwO,MAAAA,KAAK,CAACkG,WAAN,CAAkB,QAAlB;EAEAD,MAAAA,QAAQ,CAAC/F,WAAT;;EAEA,UAAIF,KAAK,CAACmG,QAAN,CAAe,QAAf,CAAJ,EAA8B;EAC5BnG,QAAAA,KAAK,CAACK,IAAN,CAAW,qBAAX,EAAkCrF,IAAlC,CAAuC,SAAvC;EACD,OAFD,MAEO;EACLgF,QAAAA,KAAK,CAACK,IAAN,CAAW,qBAAX,EAAkCrF,IAAlC,CAAuC,SAAvC;EACD;EACF,KAfD;EAgBD,GAjBD;EAmBA;EACF;EACA;EACA;;;EACE,MAAIiH,WAAW,GAAG,SAAdA,WAAc,CAAS1L,KAAT,EAAgB;EAChC,QAAM6P,SAAS,GAAGrJ,CAAC,CAAC,0BAAD,CAAD,CAA8BvL,IAA9B,CAAmC,YAAnC,CAAlB;EAEAiP,IAAAA,IAAI,CACA;EACEjQ,MAAAA,MAAM,EAAE,oBADV;EAEE+F,MAAAA,KAAK,EAAEA,KAFT;EAGExF,MAAAA,WAAW,EAAEzB,KAAK,CAACyB,WAHrB;EAIEC,MAAAA,KAAK,EAAE1B,KAAK,CAAC0B,KAJf;EAKEyT,MAAAA,cAAc,EAAED,iBAAiB,EALnC;EAME4B,MAAAA,SAAS,EAAEA;EANb,KADA,EASA,UAASjV,QAAT,EAAmB;EACjB,UAAIA,QAAJ,EAAc;EACZuN,QAAAA,kBAAkB,CAACvN,QAAD,CAAlB,CADY;;EAIZ,YAAI,gBAAgB,OAAOA,QAAQ,UAA/B,KAA2CA,QAAQ,UAAR,KAAoB,UAApB,IAAkCA,QAAQ,UAAR,KAAoB,YAAjG,CAAJ,EAAoH;EAClHqM,UAAAA,KAAK,CAACG,GAAN,CAAU,uBAAV,EAAmCO,WAAnC,CAA+C,SAA/C,EAA0DlD,IAA1D,CAA+D,EAA/D;;EAEA,cAAI7J,QAAQ,UAAR,KAAoB,UAAxB,EAAoC;EAClC4L,YAAAA,CAAC,CAAC,kBAAkBxG,KAAnB,CAAD,CAA2BmE,MAA3B;EACD;;EAED,cAAIqC,CAAC,CAAC,cAAD,CAAD,CAAkBtH,MAAlB,GAA2B,CAA/B,EAAkC;EAChC+H,YAAAA,KAAK,CAACG,GAAN,CAAU,wBAAV,EAAoC0C,IAApC,CAAyC,IAAzC,EAA+CpC,IAA/C,CAAoD,EAApD;EACD;;EAEDT,UAAAA,KAAK,CAACG,GAAN,CAAU,eAAV,EAA2BQ,IAA3B;EACA;EACD;EACF,OAnBgB;;;EAqBjB,UAAI,SAAShN,QAAb,EAAuB;EACrB8Q,QAAAA,WAAW,CAAC1L,KAAD,CAAX;EACA;EACD;EACF,KAlCD,CAAJ;EAoCD,GAvCD;EAyCA;EACF;EACA;;;EACE,MAAIiL,aAAa,GAAG,SAAhBA,aAAgB,GAAW;EAC7BxE,IAAAA,IAAI,CAAC2C,KAAL,CAAW,MAAX;;EAGA,QAAI,SAAS3C,IAAI,CAACE,UAAlB,EAA8B;EAC5B,aAAO,IAAP;EACD;;EAEDuD,IAAAA,IAAI,CACA;EACEjQ,MAAAA,MAAM,EAAE,oBADV;EAEE+F,MAAAA,KAAK,EAAEyG,IAAI,CAACxL,IAAL,CAAU4H,OAFnB;EAGErI,MAAAA,WAAW,EAAEzB,KAAK,CAACyB,WAHrB;EAIEC,MAAAA,KAAK,EAAE1B,KAAK,CAAC0B;EAJf,KADA,EAOA,UAASG,QAAT,EAAmB;EACjB,UAAIA,QAAQ,IAAI,gBAAgB,OAAQA,QAAQ,UAA5C,IAAwDA,QAAQ,UAAR,KAAoB,UAAhF,EAA4F;EAC1FqM,QAAAA,KAAK,CAACG,GAAN,CAAU,eAAV,EAA2BQ,IAA3B,GAD0F;;EAG1FoG,QAAAA,YAAY;EACZ;EACD;;EAED,UAAI,SAASpT,QAAb,EAAuB;EACvB;EACEqQ,QAAAA,aAAa;EACb;EACD,OAZgB;;;EAejB+C,MAAAA,YAAY;EACb,KAvBD,CAAJ;EAyBD,GAjCD;EAmCA;EACF;EACA;;;EACE,MAAI7C,mBAAmB,GAAG,SAAtBA,mBAAsB,GAAW;EACnC,QAAI,SAAS1E,IAAI,CAACE,UAAlB,EAA8B;EAC5B,aAAO,IAAP;EACD;;EAEDuD,IAAAA,IAAI,CACA;EACEjQ,MAAAA,MAAM,EAAE,qBADV;EAEE+F,MAAAA,KAAK,EAAEyG,IAAI,CAACxL,IAAL,CAAU4H,OAFnB;EAGErI,MAAAA,WAAW,EAAEzB,KAAK,CAACyB,WAHrB;EAIEC,MAAAA,KAAK,EAAE1B,KAAK,CAAC0B;EAJf,KADA,EAOA,UAASG,QAAT,EAAmB;EACjB,UAAIA,QAAQ,IAAI,gBAAgB,OAAQA,QAAQ,UAA5C,IAAwDA,QAAQ,UAAR,KAAoB,UAAhF,EAA4F;EAC5F;EACEoT,QAAAA,YAAY;EACZ;EACD;;EAED,UAAI,SAASpT,QAAb,EAAuB;EACvB;EACEuQ,QAAAA,mBAAmB;EACnB;EACD,OAXgB;;;EAcjB6C,MAAAA,YAAY;EACb,KAtBD,CAAJ;EAwBD,GA7BD;EA+BA;EACF;EACA;;;EACE,MAAI5C,OAAO,GAAG,SAAVA,OAAU,GAAW;EACvB,QAAI,SAAS3E,IAAI,CAACE,UAAlB,EAA8B;EAC5B,aAAO,IAAP;EACD;;EAEDuD,IAAAA,IAAI,CACA;EACEjQ,MAAAA,MAAM,EAAE,eADV;EAEE;EACAO,MAAAA,WAAW,EAAEzB,KAAK,CAACyB,WAHrB;EAIEC,MAAAA,KAAK,EAAE1B,KAAK,CAAC0B;EAJf,KADA,EAOA,UAASG,QAAT,EAAmB;EACjB,UAAIA,QAAQ,IAAI,gBAAgB,OAAQA,QAAQ,UAA5C,IAAwDA,QAAQ,UAAR,KAAoB,UAAhF,EAA4F;EAC5F;EACEoT,QAAAA,YAAY;EACZ;EACD;;EAED,UAAI,SAASpT,QAAb,EAAuB;EACvB;EACEuQ,QAAAA,mBAAmB;EACnB;EACD,OAXgB;;;EAcjB6C,MAAAA,YAAY;EACb,KAtBD,CAAJ;EAwBD,GA7BD;EA+BA;EACF;EACA;EACA;;;EACE,MAAM8B,SAAS,GAAG,SAAZA,SAAY,GAAW;EAC3B,QAAMC,IAAI,GAAG9I,KAAK,CAACG,GAAN,CAAU,oBAAV,CAAb;;EACA,QAAI,gBAAgB,OAAQ2I,IAAI,CAAC,CAAD,CAAhC,EAAsC;EACpCA,MAAAA,IAAI,CAACxE,SAAL,CAAewE,IAAI,CAAC,CAAD,CAAJ,CAAQC,YAAvB;EACD;EACF,GALD;EAOA;EACF;EACA;EACA;EACA;;;EACE,MAAMpJ,OAAO,GAAG,SAAVA,OAAU,CAASpK,GAAT,EAAc;EAC5B,QAAIA,GAAG,IAAI,IAAP,IAAe,gBAAgB,OAAQA,GAA3C,EAAiD;EAC/C,UAAIA,GAAG,CAACyT,WAAJ,KAAoBC,KAAxB,EAA+B;EAC7B1J,QAAAA,CAAC,CAAC+C,IAAF,CAAO/M,GAAP,EAAY,UAASsF,KAAT,EAAgB7E,KAAhB,EAAuB;EACjC,cAAIA,KAAK,KAAK,IAAd,EAAoB;EAClB;EACD;;EACD,cAAIA,KAAK,CAACtD,IAAN,KAAe,OAAnB,EAA4B;EAC1BsN,YAAAA,KAAK,CAACG,GAAN,CAAU,oBAAV,EAAgC4D,MAAhC,CAAuC,+BAA+B/N,KAAK,CAACtD,IAArC,GAA4C,WAA5C,GAA0D,GAA1D,GAAgEsD,KAAK,CAACkT,IAAtE,GAA6E,IAA7E,GAAoFlT,KAAK,CAAC5B,OAA1F,GAAoG,OAA3I;EACD,WAFD,MAEO;EACL4L,YAAAA,KAAK,CAACG,GAAN,CAAU,oBAAV,EAAgC4D,MAAhC,CAAuC,MAAM/N,KAAK,CAACtD,IAAZ,GAAmB,IAAnB,GAA0B,GAA1B,GAAgCsD,KAAK,CAACkT,IAAtC,GAA6C,IAA7C,GAAoDlT,KAAK,CAAC5B,OAA1D,GAAoE,OAA3G;EACD;EACF,SATD;EAUD,OAXD,MAWO;EACL4L,QAAAA,KAAK,CAACG,GAAN,CAAU,oBAAV,EAAgC4D,MAAhC,CAAuC,MAAMxO,GAAG,CAAC7C,IAAV,GAAiB,IAAjB,GAAwB,GAAxB,GAA8B6C,GAAG,CAAC2T,IAAlC,GAAyC,IAAzC,GAAgD3T,GAAG,CAACnB,OAApD,GAA8D,OAArG;EACD;EACF;;EACDyU,IAAAA,SAAS;EACV,GAlBD;EAoBA;EACF;EACA;EACA;;;EACE,MAAIhE,cAAc,GAAG,SAAjBA,cAAiB,GAAW;EAC9B7E,IAAAA,KAAK,CAACG,GAAN,CAAU,oBAAV,EAAgCkC,EAAhC,CAAmC,OAAnC,EAA4C,UAASlJ,CAAT,EAAY;EACtD6G,MAAAA,KAAK,CAACG,GAAN,CAAU,eAAV,EAA2BhF,IAA3B;EACA,UAAM9F,mBAAmB,GAAGiQ,kBAAkB,CAAC9F,IAAI,CAACpD,kBAAL,CAAwBrF,sBAAxB,EAAD,CAA9C;EACA,UAAMa,gBAAgB,GAAG0N,kBAAkB,CAAC9F,IAAI,CAACpD,kBAAL,CAAwBzE,2BAAxB,EAAD,CAA3C;EAEAsL,MAAAA,IAAI,CACA;EACEjQ,QAAAA,MAAM,EAAE,wBADV;EAEEO,QAAAA,WAAW,EAAEzB,KAAK,CAACyB,WAFrB;EAGEC,QAAAA,KAAK,EAAE1B,KAAK,CAAC0B,KAHf;EAIE6B,QAAAA,mBAAmB,EAAEA,mBAJvB;EAKEuC,QAAAA,gBAAgB,EAAEA;EALpB,OADA,EAQA,UAASjE,QAAT,EAAmB;EACjB,YAAI,UAAUA,QAAd,EAAwB;EACtBqM,UAAAA,KAAK,CAACG,GAAN,CAAU,uBAAV,EAAmCM,IAAnC,CAAwC,oCAAxC,EAA8EtF,IAA9E;EACA6E,UAAAA,KAAK,CAACG,GAAN,CAAU,eAAV,EAA2BQ,IAA3B;EACA;EACD,SALgB;;;EAQjBX,QAAAA,KAAK,CAACG,GAAN,CAAU,uBAAV,EAAmC3C,IAAnC,CAAwC,qCAAqC7J,QAAQ,CAACwV,SAA9C,GAA0D,8OAAlG,EAAkVhO,IAAlV;EACA6E,QAAAA,KAAK,CAACG,GAAN,CAAU,eAAV,EAA2BQ,IAA3B;EACD,OAlBD,EAmBA,MAnBA,EAoBA,KApBA,CAAJ;EAsBD,KA3BD;EA4BD,GA7BD;;EA+BA,MAAMyI,QAAQ,GAAG,SAAXA,QAAW,GAAW;EAC1B7J,IAAAA,CAAC,CAAC,oCAAD,CAAD,CAAwC8C,EAAxC,CAA2C,OAA3C,EAAoD,YAAW;EAC7D,UAAMG,KAAK,GAAGjD,CAAC,CAAC,IAAD,CAAf;EACA,UAAMpP,MAAM,GAAGqS,KAAK,CAACD,IAAN,CAAW,aAAX,CAAf;EACA,UAAM8G,QAAQ,GAAG7G,KAAK,CAACI,OAAN,CAAc,sBAAd,CAAjB;EACA,UAAM0G,UAAU,GAAGD,QAAQ,CAACxG,IAAT,CAAc,oCAAd,CAAnB;EACA,UAAM0G,SAAS,GAAGF,QAAQ,CAACxG,IAAT,CAAc,8CAAd,CAAlB;EAEA0G,MAAAA,SAAS,CAAC5O,MAAV,CAAiB,gDAAgDxK,MAAhD,GAAyD,GAA1E,EAA+EuQ,WAA/E,CAA2F,oBAA3F;EACA4I,MAAAA,UAAU,CAACE,GAAX,CAAehH,KAAf,EAAsB9B,WAAtB,CAAkC,oBAAlC;EACA8B,MAAAA,KAAK,CAACM,QAAN,CAAe,oBAAf;EACAvD,MAAAA,CAAC,CAACpP,MAAD,CAAD,CAAU2S,QAAV,CAAmB,oBAAnB;;EAEA,UAAI,0BAA0B3S,MAA9B,EAAsC;EACpCqP,QAAAA,IAAI,CAACiK,OAAL,CAAa5W,IAAb;EACD;;EAED,UAAI,oCAAoC1C,MAAxC,EAAgD;EAC9Cc,QAAAA,MAAM,CAACyY,aAAP,CAAqB,IAAIC,KAAJ,CAAU,sBAAV,CAArB;EACD;EACF,KAnBD;EAoBD,GArBD;EAuBA;EACF;EACA;EACA;;;EACE,MAAMC,SAAS,GAAG,mBAASA,UAAT,EAAoB;EACpC,QAAI,CAACA,UAAD,IAAcA,UAAS,KAAK,KAAhC,EAAuC;EACrC5J,MAAAA,KAAK,CAACG,GAAN,CAAU,eAAV,EAA2BQ,IAA3B;EACD,KAFD,MAEO;EACLX,MAAAA,KAAK,CAACG,GAAN,CAAU,eAAV,EAA2BhF,IAA3B;EACD;EACF,GAND;EAQA;EACF;EACA;EACA;EACA;;;EACEqE,EAAAA,IAAI,CAAC2C,KAAL,GAAa,UAASZ,MAAT,EAAiB;EAC5B,QAAIA,MAAM,KAAK,MAAf,EAAuB;EACrB,UAAM3B,IAAI,GAAGJ,IAAI,CAACI,IAAlB;EACAJ,MAAAA,IAAI,CAACI,IAAL,GAAY,CAAZ;EACAoD,MAAAA,aAAa,CAACxD,IAAI,CAACK,aAAN,CAAb;EACA,aAAOL,IAAI,CAACqK,cAAL,CAAoBjK,IAApB,CAAP;EACD;;EAGDJ,IAAAA,IAAI,CAACK,aAAL,GAAqBiK,WAAW,CAAC,YAAW;EAC1C,UAAI,SAASra,QAAQ,CAACsT,cAAT,CAAwB,wBAAxB,CAAb,EAAgE;EAC9DtT,QAAAA,QAAQ,CAACsT,cAAT,CAAwB,wBAAxB,EAAkDtM,SAAlD,GAA8D,mBAAmB+I,IAAI,CAACqK,cAAL,CAAoBrK,IAAI,CAACI,IAAzB,CAAjF;EACD;;EACDJ,MAAAA,IAAI,CAACI,IAAL;;EACA,UAAI2B,MAAM,KAAK,MAAf,EAAuB;EACrB/B,QAAAA,IAAI,CAACI,IAAL,GAAY,CAAZ;EACAoD,QAAAA,aAAa,CAACxD,IAAI,CAACK,aAAN,CAAb;EACD;EACF,KAT+B,EAS7B,IAT6B,CAAhC;EAUD,GAnBD;EAqBA;EACF;EACA;EACA;EACA;;;EACEL,EAAAA,IAAI,CAACqK,cAAL,GAAsB,UAASE,OAAT,EAAkB;EACtC,QAAMb,IAAI,GAAG,IAAIhD,IAAJ,CAAS,IAAT,CAAb;EACAgD,IAAAA,IAAI,CAACc,UAAL,CAAgBD,OAAhB,EAFsC;;EAGtC,WAAOb,IAAI,CAACe,WAAL,GAAmBC,MAAnB,CAA0B,EAA1B,EAA8B,CAA9B,CAAP;EACD,GAJD;EAMA;EACF;EACA;EACA;;;EACE1K,EAAAA,IAAI,CAACyE,YAAL,GAAqB,YAAW;EAC9BxC,IAAAA,WAAW,GADmB;;EAI9BoD,IAAAA,cAAc;;EAEd,QAAI,oBAAoBrF,IAAI,CAACxL,IAAL,CAAUhB,MAA9B,IAAwC,mBAAmBwM,IAAI,CAACxL,IAAL,CAAUhB,MAArE,IAA+E,kBAAkBwM,IAAI,CAACxL,IAAL,CAAUhB,MAA/G,EAAuH;EACrH;EACD;;EAEDwM,IAAAA,IAAI,CAACC,WAAL,GAAmB,KAAnB,CAV8B;;EAa9B0K,IAAAA,KAAK,GAbyB;EAgB9B;;EACA,aAASA,KAAT,GAAiB;EACfnK,MAAAA,KAAK,CAACG,GAAN,CAAU,eAAV,EAA2BhF,IAA3B;EACA6E,MAAAA,KAAK,CAACG,GAAN,CAAU,uBAAV,EAAmCM,IAAnC,CAAwC,QAAxC;EACAT,MAAAA,KAAK,CAACG,GAAN,CAAU,uBAAV,EAAmCQ,IAAnC;EACAX,MAAAA,KAAK,CAACG,GAAN,CAAU,sBAAV,EAAkCQ,IAAlC,GAJe;;EAQf3P,MAAAA,UAAU,CAAC,YAAW;EACpB;EACAC,QAAAA,MAAM,CAAChB,gBAAP,CAAwB,cAAxB,EAAwCqP,SAAS,CAACsB,0BAAlD;EACAwJ,QAAAA,UAAU;EACX,OAJS,EAIPtY,KAAK,CAACuY,QAJC,CAAV;EAMA7K,MAAAA,IAAI,CAAC2C,KAAL,CAAW,OAAX;EACD;EAGD;EACJ;EACA;EACA;;;EACI,QAAIiI,UAAU,GAAG,SAAbA,UAAa,GAAW;EAC1B,UAAI,SAAS5K,IAAI,CAACC,WAAlB,EAA+B;EAC7BxO,QAAAA,MAAM,CAACoQ,mBAAP,CAA2B,cAA3B,EAA2C/B,SAAS,CAACsB,0BAArD;EACA,eAAO,KAAP;EACD;;EAEDgJ,MAAAA,SAAS,CAAC,IAAD,CAAT;EAEA,UAAIvU,mBAAmB,GAAG,EAA1B;EACA,UAAIuC,gBAAgB,GAAG,EAAvB;;EACA,UAAI4H,IAAI,CAACpD,kBAAL,KAA4B,IAAhC,EAAsC;EACpC/G,QAAAA,mBAAmB,GAAGmK,IAAI,CAACpD,kBAAL,CAAwBrF,sBAAxB,EAAtB;EACAa,QAAAA,gBAAgB,GAAG4H,IAAI,CAACpD,kBAAL,CAAwBzE,2BAAxB,EAAnB;EACD,OAbyB;;;EAgB1BqI,MAAAA,KAAK,CAACG,GAAN,CAAU,oBAAV,EAAgChF,IAAhC;EAEAmE,MAAAA,SAAS,CAAC2D,IAAV,CACI;EACEjQ,QAAAA,MAAM,EAAE,kBADV;EAEEO,QAAAA,WAAW,EAAEzB,KAAK,CAACyB,WAFrB;EAGEC,QAAAA,KAAK,EAAE1B,KAAK,CAAC0B,KAHf;EAIEyT,QAAAA,cAAc,EAAED,iBAAiB,EAJnC;EAKE3R,QAAAA,mBAAmB,EAAEiQ,kBAAkB,CAACjQ,mBAAD,CALzC;EAMEuC,QAAAA,gBAAgB,EAAE0N,kBAAkB,CAAC1N,gBAAD;EANtC,OADJ,EASI,UAASjE,QAAT,EAAmB;EACjBuN,QAAAA,kBAAkB,CAACvN,QAAD,CAAlB,CADiB;;EAIjB,YAAI,gBAAgB,OAAQA,QAAQ,CAAC2W,QAAjC,IAA8C3W,QAAQ,CAAC2W,QAA3D,EAAqE;EACnE3K,UAAAA,OAAO,CAAChM,QAAQ,CAAC2W,QAAV,CAAP;EACD,SANgB;;;EAQjB,YAAI,UAAU3W,QAAQ,CAAC4N,MAAvB,EAA+B;EAC7BzB,UAAAA,WAAW,CAACnM,QAAD,CAAX;EAEA3C,UAAAA,UAAU,CAAC,YAAW;EACpBgP,YAAAA,KAAK,CAACG,GAAN,CAAU,eAAV,EAA2BhF,IAA3B;EACAiP,YAAAA,UAAU;EACX,WAHS,EAGPtY,KAAK,CAACuY,QAHC,CAAV;EAID,SAPD,MAOO,IAAI,SAAS1W,QAAQ,CAAC4N,MAAlB,IAA4B,eAAe5N,QAAQ,CAAC4N,MAAxD,EAAgE;EACrEvB,UAAAA,KAAK,CAACG,GAAN,CAAU,sBAAV,EAAkCQ,IAAlC;EACAX,UAAAA,KAAK,CAACG,GAAN,CAAU,sBAAV,EAAkCQ,IAAlC;EACAb,UAAAA,WAAW,CAACnM,QAAD,CAAX;EACAyW,UAAAA,UAAU;EACX,SALM,MAKA,IAAI,eAAezW,QAAQ,CAAC4N,MAAxB,IAAmC,gBAAgB,OAAQ5N,QAAQ,CAAC4W,QAAjC,IAA8C5W,QAAQ,CAAC4W,QAA9F,EAAyG;EAC9GtZ,UAAAA,MAAM,CAACoQ,mBAAP,CAA2B,cAA3B,EAA2C/B,SAAS,CAACsB,0BAArD;EACA4J,UAAAA,MAAM,CAAC7W,QAAD,CAAN;EACD;EAEF,OAlCL,EAmCI,MAnCJ,EAoCI,KApCJ;EAsCD,KAxDD,CAvC8B;;;EAkG9B,aAAS6W,MAAT,CAAgB7W,QAAhB,EAA0B;EACxB,UAAI,SAAS6L,IAAI,CAACG,OAAlB,EAA2B;EACzBA,QAAAA,OAAO;EACR;;EAEDG,MAAAA,WAAW,CAACnM,QAAD,CAAX,CALwB;;EAQxB,UAAI,gBAAgB,OAAQA,QAAQ,CAAC2W,QAArC,EAAgD;EAC9C3K,QAAAA,OAAO,CAAChM,QAAQ,CAAC2W,QAAV,CAAP;EACD;;EAEDtK,MAAAA,KAAK,CAACG,GAAN,CAAU,eAAV,EAA2BQ,IAA3B;EACAX,MAAAA,KAAK,CAACG,GAAN,CAAU,0BAAV,EAAsC3C,IAAtC,CAA2C,qBAA3C;EACA+B,MAAAA,CAAC,CAAC,0BAAD,CAAD,CAA8BkB,IAA9B,CAAmC,sBAAnC;EAEAT,MAAAA,KAAK,CAACG,GAAN,CAAU,qBAAV,EAAiC3C,IAAjC,CAAsCgC,IAAI,CAACxL,IAAL,CAAU4H,OAAhD;EACAoE,MAAAA,KAAK,CAACG,GAAN,CAAU,wBAAV,EAAoChF,IAApC;EACA6E,MAAAA,KAAK,CAACG,GAAN,CAAU,uBAAV,EAAmCQ,IAAnC;EACAX,MAAAA,KAAK,CAACG,GAAN,CAAU,uBAAV,EAAmCQ,IAAnC;EACAX,MAAAA,KAAK,CAACG,GAAN,CAAU,8BAAV,EAA0Ca,IAA1C,CAA+C,UAA/C,EAA2D,IAA3D;EAEA,UAAMyJ,MAAM,GAAGzK,KAAK,CAACG,GAAN,CAAU,oBAAV,CAAf;EACA,UAAMuK,KAAK,GAAG1K,KAAK,CAACG,GAAN,CAAU,kBAAV,CAAd;EACAsK,MAAAA,MAAM,CAAClI,IAAP,CAAY,MAAZ,EAAoB5O,QAAQ,CAACgO,GAA7B;EACA8I,MAAAA,MAAM,CAACjN,IAAP,CAAY7J,QAAQ,CAACgO,GAArB;EACA+I,MAAAA,KAAK,CAACnI,IAAN,CAAW,MAAX,EAAmB5O,QAAQ,CAACgO,GAA5B;EAEA3B,MAAAA,KAAK,CAACG,GAAN,CAAU,qBAAV,EAAiCnM,IAAjC,CAAsC,OAAtC,EAA+CwL,IAAI,CAACxL,IAAL,CAAU4H,OAAzD,EA5BwB;;EA+BxB4D,MAAAA,IAAI,CAACE,UAAL,GAAkB,IAAlB;EACAF,MAAAA,IAAI,CAAC2C,KAAL,CAAW,MAAX;EAGAnC,MAAAA,KAAK,CAACG,GAAN,CAAU,eAAV,EAA2BQ,IAA3B;EACAX,MAAAA,KAAK,CAACG,GAAN,CAAU,0BAAV,EAAsC3C,IAAtC,CAA2C,qBAA3C,EApCwB;;EAuCxB,UAAImN,GAAG,GAAG7Y,KAAK,CAACwC,IAAN,CAAWsW,kBAArB;;EACA,UAAIpL,IAAI,CAACxL,IAAL,CAAUhB,MAAV,KAAqB,cAAzB,EAAyC;EACvC2X,QAAAA,GAAG,GAAG7Y,KAAK,CAACwC,IAAN,CAAWuW,mBAAjB;EACD;;EAED,UAAIrL,IAAI,CAACxL,IAAL,CAAUhB,MAAV,KAAqB,cAArB,IAAuCwM,IAAI,CAACxL,IAAL,CAAUhB,MAAV,KAAqB,aAAhE,EAA+E;EAC7EuI,QAAAA,IAAI,CAACC,IAAL,CAAU;EACR+B,UAAAA,KAAK,EAAE,EADC;EAER3K,UAAAA,IAAI,EAAE,SAFE;EAGR4K,UAAAA,IAAI,EAAEmN,GAHE;EAIRjN,UAAAA,KAAK,EAAE,OAJC;EAKRC,UAAAA,YAAY,EAAE;EALN,SAAV;EAOD;;EAED,aAAO,KAAP;EACD;EAED;EACJ;EACA;EACA;EACA;;;EACI,QAAImC,WAAW,GAAG,SAAdA,WAAc,CAASnM,QAAT,EAAmBwQ,OAAnB,EAA4B;EAC5C,UAAI,gBAAgB,OAAQxQ,QAAQ,CAACmX,UAArC,EAAkD;EAChD,eAAO,KAAP;EACD;;EAED,UAAInX,QAAQ,CAACuK,GAAT,KAAiB,UAArB,EAAiC;EAC/B8B,QAAAA,KAAK,CAACG,GAAN,CAAU,oBAAV,EAAgCzC,KAAhC,CAAsC/J,QAAQ,CAACmX,UAAT,GAAsB,GAAtB,GAA4B,GAAlE,EAAuEtN,IAAvE,CAA4E7J,QAAQ,CAACmX,UAAT,GAAsB,GAAlG;EACA9K,QAAAA,KAAK,CAACG,GAAN,CAAU,0BAAV,EAAsC3C,IAAtC,CAA2C7J,QAAQ,CAACmX,UAAT,CAAoBC,OAApB,CAA4B,CAA5B,IAAiC,GAAjC,GAAuC,2CAAlF;EACD;;EAED,UAAIpX,QAAQ,CAACuK,GAAT,KAAiB,eAArB,EAAsC;EACpC8B,QAAAA,KAAK,CAACG,GAAN,CAAU,oBAAV,EAAgCK,GAAhC,CAAoC,kBAApC,EAAwD,SAAxD;EACAR,QAAAA,KAAK,CAACG,GAAN,CAAU,oBAAV,EAAgC3C,IAAhC,CAAqC,aAArC,EAFoC;EAIpC;;EACAwC,QAAAA,KAAK,CAACG,GAAN,CAAU,oBAAV,EAAgCzC,KAAhC,CAAsC,KAAtC;EAEAsC,QAAAA,KAAK,CAACG,GAAN,CAAU,oBAAV,EAAgCzC,KAAhC,CAAsC/J,QAAQ,CAACmX,UAAT,GAAsB,GAAtB,GAA4B,GAAlE,EAAuEtN,IAAvE,CAA4E7J,QAAQ,CAACmX,UAAT,GAAsB,GAAlG;EACA9K,QAAAA,KAAK,CAACG,GAAN,CAAU,0BAAV,EAAsC3C,IAAtC,CAA2C7J,QAAQ,CAACmX,UAAT,CAAoBC,OAApB,CAA4B,CAA5B,IAAiC,GAAjC,GAAuC,2CAAlF;EACD;;EAED,UAAIpX,QAAQ,CAACuK,GAAT,KAAiB,aAArB,EAAoC;EAClC8B,QAAAA,KAAK,CAACG,GAAN,CAAU,oBAAV,EAAgCK,GAAhC,CAAoC,kBAApC,EAAwD,SAAxD;EACAR,QAAAA,KAAK,CAACG,GAAN,CAAU,oBAAV,EAAgC3C,IAAhC,CAAqC,SAArC;EACAwC,QAAAA,KAAK,CAACG,GAAN,CAAU,oBAAV,EAAgCzC,KAAhC,CAAsC,KAAtC;EAEAsC,QAAAA,KAAK,CAACG,GAAN,CAAU,sBAAV,EAAkCzC,KAAlC,CAAwC/J,QAAQ,CAACmX,UAAT,GAAsB,GAAtB,GAA4B,GAApE,EAAyEtN,IAAzE,CAA8E7J,QAAQ,CAACmX,UAAT,GAAsB,GAApG;EACA9K,QAAAA,KAAK,CAACG,GAAN,CAAU,0BAAV,EAAsC3C,IAAtC,CAA2C7J,QAAQ,CAACmX,UAAT,CAAoBC,OAApB,CAA4B,CAA5B,IAAiC,GAAjC,GAAuC,iCAAlF;EACD;;EACD,UAAIpX,QAAQ,CAACuK,GAAT,KAAiB,OAArB,EAA8B;EAC5B8B,QAAAA,KAAK,CAACG,GAAN,CAAU,sBAAV,EAAkCK,GAAlC,CAAsC,kBAAtC,EAA0D,SAA1D;EACAR,QAAAA,KAAK,CAACG,GAAN,CAAU,sBAAV,EAAkC3C,IAAlC,CAAuC,UAAvC;EACAwC,QAAAA,KAAK,CAACG,GAAN,CAAU,sBAAV,EAAkCzC,KAAlC,CAAwC,KAAxC;EAEAsC,QAAAA,KAAK,CAACG,GAAN,CAAU,uBAAV,EAAmCzC,KAAnC,CAAyC/J,QAAQ,CAACmX,UAAT,GAAsB,GAAtB,GAA4B,GAArE,EAA0EtN,IAA1E,CAA+E7J,QAAQ,CAACmX,UAAT,GAAsB,GAArG;EACA9K,QAAAA,KAAK,CAACG,GAAN,CAAU,0BAAV,EAAsC3C,IAAtC,CAA2C7J,QAAQ,CAACmX,UAAT,CAAoBC,OAApB,CAA4B,CAA5B,IAAiC,GAAjC,GAAuC,8BAAlF;EACD;;EACD,UAAIpX,QAAQ,CAACuK,GAAT,KAAiB,QAArB,EAA+B;EAC7B8B,QAAAA,KAAK,CAACG,GAAN,CAAU,uBAAV,EAAmCK,GAAnC,CAAuC,kBAAvC,EAA2D,SAA3D;EACAR,QAAAA,KAAK,CAACG,GAAN,CAAU,uBAAV,EAAmC3C,IAAnC,CAAwC,eAAxC;EACAwC,QAAAA,KAAK,CAACG,GAAN,CAAU,uBAAV,EAAmCzC,KAAnC,CAAyC,KAAzC;EAEAsC,QAAAA,KAAK,CAACG,GAAN,CAAU,0BAAV,EAAsC3C,IAAtC,CAA2C7J,QAAQ,CAACmX,UAAT,CAAoBC,OAApB,CAA4B,CAA5B,IAAiC,GAAjC,GAAuC,6BAAlF;EACD;EACF,KA5CD;EA6CD,GA7MD;;EA+MAvL,EAAAA,IAAI,CAACsF,UAAL,GAAkB,UAASkG,IAAT,EAAe;EAC/BhL,IAAAA,KAAK,CAACG,GAAN,CAAU,qBAAV,EACKO,WADL,CACiB,oBADjB;EAEAV,IAAAA,KAAK,CAACG,GAAN,CAAU,gBAAgB6K,IAA1B,EACKlI,QADL,CACc,oBADd;EAED,GALD;EAOA;EACF;EACA;EACA;;;EACEtD,EAAAA,IAAI,CAAC3M,IAAL,GAAa,YAAW;EACtBkU,IAAAA,YAAY;EACZ9G,IAAAA,QAAQ;EACRwG,IAAAA,WAAW;EACX+B,IAAAA,IAAI;EACJY,IAAAA,QAAQ;EACR,QAAIzX,iBAAJ;EACD,GAPD;EASA;EACF;EACA;EACA;;;EACE6N,EAAAA,IAAI,CAACyD,IAAL,GAAYA,IAAZ;EACAzD,EAAAA,IAAI,CAACe,SAAL,GAAiBA,SAAjB;EACAf,EAAAA,IAAI,CAACG,OAAL,GAAeA,OAAf;EACAH,EAAAA,IAAI,CAACuH,YAAL,GAAoBA,YAApB,CAxhD2B;;EA2hD3BvH,EAAAA,IAAI,CAACiK,OAAL,GAAe;EACb/W,IAAAA,IAAI,EAAE,IADO;EAEb+M,IAAAA,WAAW,EAAE,KAFA;EAGbwL,IAAAA,WAAW,EAAE;EACX1N,MAAAA,KAAK,EAAE,IADI;EAEX2N,MAAAA,QAAQ,EAAE;EAFC,KAHA;EAOb9M,IAAAA,KAAK,EAAE;EACL+M,MAAAA,MAAM,EAAE;EACN3N,QAAAA,IAAI,EAAE,IADA;EAEN4N,QAAAA,aAAa,EAAE;EAFT,OADH;EAKLC,MAAAA,OAAO,EAAE;EACP7N,QAAAA,IAAI,EAAE,IADC;EAEP8N,QAAAA,YAAY,EAAE,IAFP;EAGPlN,QAAAA,KAAK,EAAE;EAHA,OALJ;EAULmN,MAAAA,QAAQ,EAAE;EACR/N,QAAAA,IAAI,EAAE;EADE,OAVL;EAaL,gBAAQ;EACNA,QAAAA,IAAI,EAAE,IADA;EAENgO,QAAAA,UAAU,EAAE,IAFN;EAGNC,QAAAA,aAAa,EAAE,IAHT;EAINC,QAAAA,YAAY,EAAE,IAJR;EAKNC,QAAAA,iBAAiB,EAAE,IALb;EAMNC,QAAAA,IAAI,EAAE,IANA;EAONC,QAAAA,eAAe,EAAE,IAPX;EAQNC,QAAAA,mBAAmB,EAAE,IARf;EASNC,QAAAA,OAAO,EAAE,iBAACH,IAAD,EAAOI,MAAP,EAAyB;EAAA,cAAlBA,MAAkB;EAAlBA,YAAAA,MAAkB,GAAT,IAAS;EAAA;;EAChC,cAAMC,MAAM,GAAG,SAATA,MAAS,CAACC,KAAD,EAAW;EACxB,gBAAMvN,CAAC,GAAGwN,IAAI,CAACC,KAAL,CAAWD,IAAI,CAAC5W,GAAL,CAAS2W,KAAT,IAAkBC,IAAI,CAAC5W,GAAL,CAAS,IAAT,CAA7B,CAAV;EACA,mBAAO,CAAC2W,KAAK,GAAGC,IAAI,CAACE,GAAL,CAAS,IAAT,EAAe1N,CAAf,CAAT,EAA4BoM,OAA5B,CAAoC,CAApC,IAAyC,CAAzC,GAA6C,GAA7C,GAAmD,CAAC,GAAD,EAAM,IAAN,EAAY,IAAZ,EAAkB,IAAlB,EAAwB,IAAxB,EAA8BpM,CAA9B,CAA1D;EACD,WAHD;;EAKA,cAAI,CAACiN,IAAL,EAAW;EACT;EACD;;EAEDpM,UAAAA,IAAI,CAACiK,OAAL,CAAarL,KAAb,WAA0BwN,IAA1B,GAAiCA,IAAjC;EACApM,UAAAA,IAAI,CAACiK,OAAL,CAAarL,KAAb,WAA0BpK,IAA1B,CAA+B4X,IAA/B,GAAsCA,IAAI,CAAC1M,IAA3C;EAEAK,UAAAA,CAAC,CAAC,uCAAD,CAAD,CAA2C/B,IAA3C,CAAmDoO,IAAI,CAAC1M,IAAxD,iBAAwE+M,MAAM,CAACL,IAAI,CAACU,IAAN,CAA9E,QAA8FnR,IAA9F;EACAoE,UAAAA,CAAC,CAAC,cAAD,CAAD,CAAkBoB,IAAlB;EACApB,UAAAA,CAAC,CAAC,wBAAD,CAAD,CAA4BpE,IAA5B;;EAEA,cAAI6Q,MAAJ,EAAY;EACVzM,YAAAA,CAAC,CAAC,uCAAD,CAAD,CAA2CyB,IAA3C,CAAgD,UAAhD,EAA4D,IAA5D;EACAxB,YAAAA,IAAI,CAACiK,OAAL,CAAauC,MAAb,CAAoB7B,KAApB;EACD;EACF,SA9BK;EA+BNoC,QAAAA,aAAa,EAAE,IA/BT;EAgCNvY,QAAAA,IAAI,EAAE;EACJ4X,UAAAA,IAAI,EAAE,IADF;EAEJY,UAAAA,MAAM,EAAE,EAFJ;EAGJxR,UAAAA,OAAO,EAAE;EAHL;EAhCA;EAbH,KAPM;EA2DbyR,IAAAA,QAAQ,EAAE;EACRC,MAAAA,OAAO,EAAE,SADD;EAERC,MAAAA,KAAK,EAAE,OAFC;EAGRC,MAAAA,IAAI,EAAE,MAHE;EAIRC,MAAAA,KAAK,EAAE,OAJC;EAKRC,MAAAA,QAAQ,EAAE,UALF;EAMR9Y,MAAAA,IAAI,EAAE;EACJrE,QAAAA,GAAG,EAAE,EADD;EACK;EACTod,QAAAA,IAAI,EAAE,EAFF;EAGJ1Y,QAAAA,KAAK,EAAE,EAHH;EAIJ2Y,QAAAA,QAAQ,EAAE,EAJN;EAKJC,QAAAA,OAAO,EAAE,EALL;EAMJC,QAAAA,KAAK,EAAE;EANH,OANE;EAcRC,MAAAA,UAdQ,wBAcK;EACX,eAAO3N,IAAI,CAACiK,OAAL,CAAagD,QAAb,CAAsBzY,IAAtB,CAA2BK,KAA3B,CAAiC4D,MAAjC,GAA0C,CAA1C,IACLuH,IAAI,CAACiK,OAAL,CAAagD,QAAb,CAAsBzY,IAAtB,CAA2BgZ,QAA3B,CAAoC/U,MAApC,GAA6C,CAD/C;EAGD,OAlBO;EAmBRmV,MAAAA,WAnBQ,uBAmBI1a,IAnBJ,EAmBwC;EAAA,YAApCA,IAAoC;EAApCA,UAAAA,IAAoC,GAA7B8M,IAAI,CAACiK,OAAL,CAAagD,QAAb,CAAsBE,KAAO;EAAA;;EAC9C,eAAOnN,IAAI,CAACiK,OAAL,CAAagD,QAAb,CAAsBzY,IAAtB,CAA2BtB,IAA3B,EAAiCuF,MAAxC;EACD,OArBO;EAsBRoV,MAAAA,UAtBQ,sBAsBGjZ,OAtBH,EAsBY;EAClB,YAAI6U,KAAK,CAACqE,OAAN,CAAclZ,OAAd,CAAJ,EAA4B;EAC1BA,UAAAA,OAAO,CAAC4C,OAAR,CAAgB,UAACuW,IAAD,EAAU;EACxB/N,YAAAA,IAAI,CAACiK,OAAL,CAAagD,QAAb,CAAsBY,UAAtB,CAAiCE,IAAjC;EACD,WAFD;EAGA;EACD;;EACD,YAAM7a,IAAI,GAAG0B,OAAO,CAAC1B,IAAR,CAAamP,WAAb,MAA8B,MAA3C;;EACA,YAAI,CAACrC,IAAI,CAACiK,OAAL,CAAagD,QAAb,CAAsBzY,IAAtB,CAA2BtB,IAA3B,CAAL,EAAuC;EACrC8M,UAAAA,IAAI,CAACiK,OAAL,CAAagD,QAAb,CAAsBzY,IAAtB,CAA2BtB,IAA3B,IAAmC,EAAnC;EACD;;EACD8M,QAAAA,IAAI,CAACiK,OAAL,CAAagD,QAAb,CAAsBzY,IAAtB,CAA2BrE,GAA3B,CAA+B+B,IAA/B,CAAoC0C,OAApC,EAXkB;;EAYlBoL,QAAAA,IAAI,CAACiK,OAAL,CAAagD,QAAb,CAAsBzY,IAAtB,CAA2BtB,IAA3B,EAAiChB,IAAjC,CAAsC0C,OAAtC;EACD,OAnCO;EAoCRoZ,MAAAA,KApCQ,mBAoCA;EACNhO,QAAAA,IAAI,CAACiK,OAAL,CAAagD,QAAb,CAAsBzY,IAAtB,GAA6B;EAC3BrE,UAAAA,GAAG,EAAE,EADsB;EAE3Bod,UAAAA,IAAI,EAAE,EAFqB;EAG3B1Y,UAAAA,KAAK,EAAE,EAHoB;EAI3B2Y,UAAAA,QAAQ,EAAE,EAJiB;EAK3BC,UAAAA,OAAO,EAAE,EALkB;EAM3BC,UAAAA,KAAK,EAAE;EANoB,SAA7B;EAQD;EA7CO,KA3DG;EA0Gb/K,IAAAA,KAAK,EAAE;EACLsL,MAAAA,YAAY,EAAE,CADT;EAELvC,MAAAA,QAAQ,EAAE,IAFL;EAGLf,MAAAA,KAHK,mBAGG;EACN,YAAI,SAAS3K,IAAI,CAACiK,OAAL,CAAatH,KAAb,CAAmB+I,QAAhC,EAA0C;EACxC;EACD;;EAED,YAAMwC,QAAQ,GAAG,SAAXA,QAAW,CAAC3D,OAAD,EAAa;EAC5B;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,sBAAW,IAAI7D,IAAJ,CAAS6D,OAAO,GAAG,IAAnB,CAAD,CAA2BE,WAA3B,GAAyCC,MAAzC,CAAgD,EAAhD,EAAoD,CAApD,CAAV;EACD,SAdD;;EAgBA1K,QAAAA,IAAI,CAACiK,OAAL,CAAatH,KAAb,CAAmB+I,QAAnB,GAA8BpB,WAAW,CAAC,YAAM;EAC9CvK,UAAAA,CAAC,CAAC,sCAAD,CAAD,CAA0CkB,IAA1C,CAA+CiN,QAAQ,CAAClO,IAAI,CAACiK,OAAL,CAAatH,KAAb,CAAmBsL,YAApB,CAAvD;EACAjO,UAAAA,IAAI,CAACiK,OAAL,CAAatH,KAAb,CAAmBsL,YAAnB;EACD,SAHwC,EAGtC,IAHsC,CAAzC;EAID,OA5BI;EA6BLE,MAAAA,IA7BK,kBA6BE;EACLnO,QAAAA,IAAI,CAACiK,OAAL,CAAatH,KAAb,CAAmBsL,YAAnB,GAAkC,CAAlC;;EACA,YAAIjO,IAAI,CAACiK,OAAL,CAAatH,KAAb,CAAmB+I,QAAvB,EAAiC;EAC/BlI,UAAAA,aAAa,CAACxD,IAAI,CAACiK,OAAL,CAAatH,KAAb,CAAmB+I,QAApB,CAAb;EACA1L,UAAAA,IAAI,CAACiK,OAAL,CAAatH,KAAb,CAAmB+I,QAAnB,GAA8B,IAA9B;EACD;EACF;EAnCI,KA1GM;EA+Ibc,IAAAA,MAAM,EAAE;EACN4B,MAAAA,MAAM,EAAE,IADF;EAENhC,MAAAA,IAAI,EAAE,IAFA;EAGNiC,MAAAA,GAAG,EAAE,OAAO,IAHN;EAINC,MAAAA,UAJM,sBAIKC,MAJL,EAIa;EACjB,YAAMC,gBAAgB,GAAGzO,CAAC,CAAC,wCAAD,CAA1B;EACA,YAAM0O,kBAAkB,GAAG1O,CAAC,CAAC,kBAAD,CAA5B;;EACA,YAAIwO,MAAJ,EAAY;EACVC,UAAAA,gBAAgB,CAACxN,GAAjB,CAAqB,SAArB,EAAgC,MAAhC;EACAyN,UAAAA,kBAAkB,CAACtN,IAAnB;EACA;EACD;;EAEDsN,QAAAA,kBAAkB,CAACzN,GAAnB,CAAuB,SAAvB,EAAkC,MAAlC;EACAwN,QAAAA,gBAAgB,CAACrN,IAAjB;EACD,OAfK;EAgBNwJ,MAAAA,KAhBM,mBAgBE;EACN3K,QAAAA,IAAI,CAACiK,OAAL,CAAauC,MAAb,CAAoB4B,MAApB,GAA6B,IAAIM,UAAJ,EAA7B;EACA1O,QAAAA,IAAI,CAACiK,OAAL,CAAauC,MAAb,CAAoBJ,IAApB,GAA2BpM,IAAI,CAACiK,OAAL,CAAarL,KAAb,WAA0BwN,IAArD;EACApM,QAAAA,IAAI,CAACiK,OAAL,CAAauC,MAAb,CAAoB8B,UAApB,CAA+B,IAA/B;EACAtO,QAAAA,IAAI,CAACiK,OAAL,CAAauC,MAAb,CAAoBmC,SAApB;EACD,OArBK;EAsBNA,MAAAA,SAtBM,qBAsBIC,QAtBJ,EAsBkB;EAAA,YAAdA,QAAc;EAAdA,UAAAA,QAAc,GAAH,CAAG;EAAA;;EACtB,YAAI,CAAC5O,IAAI,CAACiK,OAAL,CAAauC,MAAb,CAAoBJ,IAAzB,EAA+B;EAC7B;EACD;;EACD,YAAMyC,OAAO,GAAGD,QAAQ,GAAG,CAA3B;EACA,YAAME,MAAM,GAAGF,QAAQ,GAAG5O,IAAI,CAACiK,OAAL,CAAauC,MAAb,CAAoB6B,GAA/B,GAAqC,CAApD;EACA,YAAMU,IAAI,GAAG/O,IAAI,CAACiK,OAAL,CAAauC,MAAb,CAAoBJ,IAApB,CAAyB4C,KAAzB,CAA+BJ,QAA/B,EAAyCE,MAAzC,CAAb;;EACA9O,QAAAA,IAAI,CAACiK,OAAL,CAAauC,MAAb,CAAoB4B,MAApB,CAA2Ba,SAA3B,GAAuC,UAASve,KAAT,EAAgB;EACrD,cAAIA,KAAK,CAACC,MAAN,CAAaue,UAAb,KAA4BR,UAAU,CAACS,IAA3C,EAAiD;EAC/C;EACD;;EAED,cAAMtb,IAAI,GAAG,IAAIub,QAAJ,EAAb;EACAvb,UAAAA,IAAI,CAAC0Q,MAAL,CAAY,aAAZ,EAA2BjS,KAAK,CAACyB,WAAjC;EACAF,UAAAA,IAAI,CAAC0Q,MAAL,CAAY,OAAZ,EAAqBjS,KAAK,CAAC0B,KAA3B;EACAH,UAAAA,IAAI,CAAC0Q,MAAL,CAAY,MAAZ,EAAoB7T,KAAK,CAACC,MAAN,CAAaqB,MAAjC;EACA6B,UAAAA,IAAI,CAAC0Q,MAAL,CAAY,UAAZ,EAAwBvE,IAAI,CAACiK,OAAL,CAAauC,MAAb,CAAoBJ,IAApB,CAAyB1M,IAAjD;EACA7L,UAAAA,IAAI,CAAC0Q,MAAL,CAAY,OAAZ,EAAqBsK,OAAO,GAAG,GAAH,GAAS,GAArC;EAGApb,UAAAA,KAAK,CAAIiP,OAAJ,kDAA0D;EAC7D/O,YAAAA,MAAM,EAAE,MADqD;EAE7DE,YAAAA,IAAI,EAAJA;EAF6D,WAA1D,CAAL,CAGGK,IAHH,CAGQ4N,iBAHR,EAIK5N,IAJL,CAIU,UAACmb,GAAD;EAAA,mBAASA,GAAG,CAAChb,IAAJ,EAAT;EAAA,WAJV,EAKKH,IALL,CAKU,UAACmb,GAAD,EAAS;EACb3N,YAAAA,kBAAkB,CAAC2N,GAAD,EAAM,EAAN,EAAU,yBAAV,CAAlB;EACA,gBAAMC,YAAY,GAAGV,QAAQ,GAAG5O,IAAI,CAACiK,OAAL,CAAauC,MAAb,CAAoB6B,GAApD;EACA,gBAAMkB,OAAO,GAAG5C,IAAI,CAACC,KAAL,CAAY0C,YAAY,GAAGtP,IAAI,CAACiK,OAAL,CAAauC,MAAb,CAAoBJ,IAApB,CAAyBU,IAAzC,GAAiD,GAA5D,CAAhB;;EACA,gBAAIgC,MAAM,IAAI9O,IAAI,CAACiK,OAAL,CAAauC,MAAb,CAAoBJ,IAApB,CAAyBU,IAAvC,EAA6C;EAC3C9M,cAAAA,IAAI,CAACiK,OAAL,CAAauC,MAAb,CAAoB8B,UAApB,CAA+B,KAA/B;EACAlE,cAAAA,SAAS,CAAC,KAAD,CAAT;EACApK,cAAAA,IAAI,CAACiK,OAAL,CAAauF,sBAAb;EACA;EACD;;EACDzP,YAAAA,CAAC,CAAC,uDAAD,CAAD,CAA2DkB,IAA3D,CAAgEsO,OAAhE;EACAxP,YAAAA,CAAC,CAAC,yCAAD,CAAD,CAA6CiB,GAA7C,CAAiD,OAAjD,EAA6DuO,OAA7D;EACAvP,YAAAA,IAAI,CAACiK,OAAL,CAAauC,MAAb,CAAoBmC,SAApB,CAA8BG,MAA9B;EACD,WAlBL,WAmBW,UAACnV,CAAD;EAAA,mBAAO+H,kBAAkB,CAAC/H,CAAD,EAAI,EAAJ,EAAQ,yBAAR,CAAzB;EAAA,WAnBX;EAqBD,SAlCD;;EAmCAqG,QAAAA,IAAI,CAACiK,OAAL,CAAauC,MAAb,CAAoB4B,MAApB,CAA2BqB,aAA3B,CAAyCV,IAAzC;EACD;EAjEK,KA/IK;EAkNbhN,IAAAA,MAAM,EAAE;EACN2N,MAAAA,WAAW,EAAE,IADP;EAENC,MAAAA,UAAU,EAAE;EAFN,KAlNK;EAsNbtc,IAAAA,IAtNa,kBAsNN;EACL,WAAKsY,MAAL;EACA;EACA,WAAKiE,IAAL,GAHK;;EAML5P,MAAAA,IAAI,CAACiK,OAAL,CAAa4F,YAAb;EAEA9P,MAAAA,CAAC,CAAC,MAAD,CAAD,CACK8C,EADL,CACQ,OADR,EACiB,0BADjB,EAC6C,YAAW;EAClD,YAAMV,GAAG,GAAG,KAAK7L,YAAL,CAAkB,UAAlB,CAAZ;;EACA,YAAI6L,GAAG,CAAC1J,MAAJ,GAAa,CAAjB,EAAoB;EAClBhH,UAAAA,MAAM,CAACiD,QAAP,CAAgBob,IAAhB,GAAuB3N,GAAvB;EACA;EACD;;EACDnC,QAAAA,IAAI,CAACiK,OAAL,CAAa8F,aAAb,CAA2B;EACzBC,UAAAA,WAAW,EAAE,KAAK1Z,YAAL,CAAkB,mBAAlB,CADY;EAEzByH,UAAAA,KAAK,EAAE,KAAKzH,YAAL,CAAkB,YAAlB,CAFkB;EAGzB2Z,UAAAA,EAAE,EAAE,KAAK3Z,YAAL,CAAkB,SAAlB,CAHqB;EAIzB4V,UAAAA,YAAY,EAAE,KAAK5V,YAAL,CAAkB,qBAAlB,CAJW;EAKzB2V,UAAAA,aAAa,EAAE,KAAK3V,YAAL,CAAkB,uBAAlB;EALU,SAA3B;EAOD,OAdL,EAeKuM,EAfL,CAeQ,OAfR,EAeiB,wBAfjB,EAe2C,YAAW;EAClD;EACE7C,QAAAA,IAAI,CAACiK,OAAL,CAAaiG,WAAb;EACAlQ,QAAAA,IAAI,CAACiK,OAAL,CAAarL,KAAb,WAA0BpK,IAA1B,CAA+B4X,IAA/B,GAAsC,KAAK9V,YAAL,CAAkB,eAAlB,CAAtC;EACA0J,QAAAA,IAAI,CAACiK,OAAL,CAAauF,sBAAb,GAJgD;EAMlD;EACC,OAtBL,EAuBKW,GAvBL,CAuBS,OAvBT,EAuBkB,sBAvBlB,EAwBKtN,EAxBL,CAwBQ,OAxBR,EAwBiB,sBAxBjB,EAwByC,YAAW;EAC9C7C,QAAAA,IAAI,CAACiK,OAAL,CAAaiG,WAAb;EACD,OA1BL;EAAA,OA4BKC,GA5BL,CA4BS,OA5BT,EA4BkB,uCA5BlB,EA6BKtN,EA7BL,CA6BQ,OA7BR,EA6BiB,uCA7BjB,EA6B0D,YAAW;EAC/D,YAAMG,KAAK,GAAGjD,CAAC,CAAC,IAAD,CAAf;EACA,YAAMqQ,OAAO,GAAGpN,KAAK,CAAC1S,MAAN,EAAhB;;EACA,YAAI,CAAC8f,OAAO,CAACjH,QAAR,CAAiB,qBAAjB,CAAL,EAA8C;EAC5CiH,UAAAA,OAAO,CAAC9M,QAAR,CAAiB,qBAAjB;EACAN,UAAAA,KAAK,CAAC/B,IAAN,CAAW+B,KAAK,CAACD,IAAN,CAAW,gBAAX,CAAX;EACD,SAHD,MAGO;EACLqN,UAAAA,OAAO,CAAClP,WAAR,CAAoB,qBAApB;EACA8B,UAAAA,KAAK,CAAC/B,IAAN,CAAW+B,KAAK,CAACD,IAAN,CAAW,eAAX,CAAX;EACD;EACF,OAvCL,EAwCKoN,GAxCL,CAwCS,OAxCT,EAwCkB,oDAxClB,EAyCKtN,EAzCL,CAyCQ,OAzCR,EAyCiB,oDAzCjB,EAyCuE,UAASlJ,CAAT,EAAY;EAC7EA,QAAAA,CAAC,CAAC3D,cAAF;EACA,YAAMqa,UAAU,GAAGtQ,CAAC,CAAChE,IAAI,CAACuU,YAAL,EAAD,CAAD,CAAuBjN,IAAvB,CAA4B,iEAA5B,CAAnB;EACA,YAAMkN,KAAK,GAAGF,UAAU,CAAChN,IAAX,CAAgB,4DAAhB,EAA8E5K,MAA5F;EACA4X,QAAAA,UAAU,CAAC9L,MAAX,CAAkBvE,IAAI,CAACiK,OAAL,CAAarL,KAAb,WAA0BuN,iBAA1B,CAA4C3Q,OAA5C,CAAoD,MAApD,EAA4D+U,KAA5D,CAAlB;EACD,OA9CL,EA+CKJ,GA/CL,CA+CS,OA/CT,EA+CkB,uDA/ClB,EAgDKtN,EAhDL,CAgDQ,OAhDR,EAgDiB,uDAhDjB,EAgD0E,UAASlJ,CAAT,EAAY;EAChFA,QAAAA,CAAC,CAAC3D,cAAF;EACA+J,QAAAA,CAAC,CAACpG,CAAC,CAAChJ,MAAH,CAAD,CAAYE,OAAZ,CAAoB,4DAApB,EAAkF6M,MAAlF;EACD,OAnDL,EAoDKyS,GApDL,CAoDS,OApDT,EAoDkB,gCApDlB,EAqDKtN,EArDL,CAqDQ,OArDR,EAqDiB,gCArDjB,EAqDmD,YAAW;EACxD,YAAMxH,KAAK,GAAGmL,QAAQ,CAAC,KAAKlQ,YAAL,CAAkB,YAAlB,CAAD,CAAtB;;EACA,YAAI,CAACmQ,KAAK,CAACpL,KAAD,CAAV,EAAmB;EACjB2E,UAAAA,IAAI,CAACiK,OAAL,CAAarL,KAAb,WAA0BpK,IAA1B,CAA+BwY,MAA/B,CAAsC3R,KAAtC,IAA+C,KAAK7E,KAApD;EACD;EACF,OA1DL,EA2DK2Z,GA3DL,CA2DS,OA3DT,EA2DkB,iCA3DlB,EA4DKtN,EA5DL,CA4DQ,OA5DR,EA4DiB,iCA5DjB,EA4DoD,YAAW;EACzD,YAAMxH,KAAK,GAAGmL,QAAQ,CAAC,KAAKlQ,YAAL,CAAkB,YAAlB,CAAD,CAAtB;;EACA,YAAI,CAACmQ,KAAK,CAACpL,KAAD,CAAV,EAAmB;EACjB2E,UAAAA,IAAI,CAACiK,OAAL,CAAarL,KAAb,WAA0BpK,IAA1B,CAA+BgH,OAA/B,CAAuCH,KAAvC,IAAgD,KAAK7E,KAArD;EACD;EACF,OAjEL;EAAA,OAmEK2Z,GAnEL,CAmES,OAnET,EAmEkB,6CAnElB,EAoEKtN,EApEL,CAoEQ,OApER,EAoEiB,6CApEjB,EAoEgE,YAAW;EACrE,YAAMpD,MAAM,GAAG,KAAKnJ,YAAL,CAAkB,aAAlB,CAAf;;EAEA,YAAImJ,MAAM,KAAK,MAAf,EAAuB;EACrBM,UAAAA,CAAC,CAAC,gEAAD,CAAD,CAAoEyQ,OAApE,CAA4E,OAA5E;EACA;EACD;;EAED,YAAI/Q,MAAM,KAAK,QAAf,EAAyB;EACvBO,UAAAA,IAAI,CAACiK,OAAL,CAAarL,KAAb,WAA0B0N,mBAA1B,CAA8CnL,IAA9C;EACAnB,UAAAA,IAAI,CAACiK,OAAL,CAAarL,KAAb,WAA0ByN,eAA1B,CAA0C1Q,IAA1C;EACD;;EAED,YAAI8D,MAAM,KAAK,YAAf,EAA6B;EAC3B;EACD;;EAEDO,QAAAA,IAAI,CAACiK,OAAL,CAAarL,KAAb,WAA0ByN,eAA1B,CAA0ClL,IAA1C;EACA,YAAMsP,oBAAoB,GAAGzQ,IAAI,CAACiK,OAAL,CAAarL,KAAb,WAA0B0N,mBAAvD;EACAmE,QAAAA,oBAAoB,CAAC9U,IAArB;EAEAlI,QAAAA,KAAK,CAAIiP,OAAJ,oDAA0DiK,IAAI,CAAC+D,MAAL,EAA1D,qBAAuFpe,KAAK,CAACyB,WAA7F,eAAkHzB,KAAK,CAAC0B,KAAxH,CAAL,CACKE,IADL,CACU4N,iBADV,EAEK5N,IAFL,CAEU,UAACmb,GAAD;EAAA,iBAASA,GAAG,CAAChb,IAAJ,EAAT;EAAA,SAFV,EAGKH,IAHL,CAGU,UAACmb,GAAD,EAAS;EACb,cAAMsB,GAAG,GAAG5Q,CAAC,CAAC,8CAAD,CAAb;EACA4Q,UAAAA,GAAG,CAACC,KAAJ;;EAEA,cAAI,CAACvB,GAAD,IAAQ/N,OAAO,CAAC+N,GAAD,CAAnB,EAA0B;EACxBsB,YAAAA,GAAG,CAACpM,MAAJ,CAAW,0DAAuDjS,KAAK,CAACwC,IAAN,CAAW+b,iBAAlE,kBAAX;EACA9Q,YAAAA,CAAC,CAAC,wDAAD,CAAD,CAA4DoB,IAA5D;EACA;EACD;;EAEDwP,UAAAA,GAAG,CAACpM,MAAJ,CAAW,oDAAiDjS,KAAK,CAACwC,IAAN,CAAWgc,kBAA5D,kBAAX;EACAzB,UAAAA,GAAG,CAAC7X,OAAJ,CAAY,UAAS4U,IAAT,EAAe/Q,KAAf,EAAsB;EAChCsV,YAAAA,GAAG,CAACpM,MAAJ,CAAW,2BACV6H,IAAI,CAAC2E,QADK,iJAEgD1V,KAFhD,sDAGS+Q,IAAI,CAAC4E,UAHd,uCAIL5E,IAAI,CAAC6E,oBAJA,iCAKX7E,IAAI,CAACU,IALM,+LASdV,IAAI,CAAC8E,mBAAL,GAA2B,4HAA3B,GAA0J,EAT5I,wBAUd9E,IAAI,CAAC+E,kBAAL,GAA0B,gIAA1B,GAA6J,EAV/I,wBAWd/E,IAAI,CAACgF,oBAAL,GAA4B,qIAA5B,GAAoK,EAXtJ,wBAYdhF,IAAI,CAACiF,iBAAL,GAAyB,wHAAzB,GAAoJ,EAZtI,wBAadjF,IAAI,CAACkF,kBAAL,GAA0B,6HAA1B,GAA0J,EAb5I,wBAcdlF,IAAI,CAACmF,8BAAL,GAAsC,kJAAtC,GAA2L,EAd7K,oEAiBPnF,IAAI,CAAC1M,IAjBE,+BAAX;EAqBD,WAtBD;EAuBA,iBAAO2P,GAAP;EACD,SAtCL,WAuCW,UAAC1V,CAAD;EAAA,iBAAO+H,kBAAkB,CAAC/H,CAAD,EAAI,EAAJ,EAAQ,yBAAR,CAAzB;EAAA,SAvCX;EAyCD,OAlIL,EAmIKwW,GAnIL,CAmIS,QAnIT,EAmImB,gEAnInB,EAoIKtN,EApIL,CAoIQ,QApIR,EAoIkB,gEApIlB,EAoIoF,YAAW;EACzF7C,QAAAA,IAAI,CAACiK,OAAL,CAAarL,KAAb,WAA0B2N,OAA1B,CAAkC,KAAKiF,KAAL,CAAW,CAAX,KAAiB,IAAnD;EACD,OAtIL,EAuIKrB,GAvIL,CAuIS,QAvIT,EAuImB,gDAvInB,EAwIKtN,EAxIL,CAwIQ,QAxIR,EAwIkB,gDAxIlB,EAwIoE,YAAW;EACzE9C,QAAAA,CAAC,CAAC,uCAAD,CAAD,CAA2CpE,IAA3C;EACAoE,QAAAA,CAAC,CAAC,uCAAD,CAAD,CAA2CyB,IAA3C,CAAgD,UAAhD,EAA4D,KAA5D;EACAxB,QAAAA,IAAI,CAACiK,OAAL,CAAarL,KAAb,WAA0BpK,IAA1B,CAA+B4X,IAA/B,GAAsC,KAAK5V,KAA3C;EACD,OA5IL;EAAA,OA8IKqM,EA9IL,CA8IQ,0DA9IR,EA8IoE,kDA9IpE,EA8IwH,UAASlJ,CAAT,EAAY;EAC9HA,QAAAA,CAAC,CAAC3D,cAAF;EACA2D,QAAAA,CAAC,CAAC8X,eAAF;EACD,OAjJL,EAkJK5O,EAlJL,CAkJQ,oBAlJR,EAkJ8B,kDAlJ9B,EAkJkF,YAAW;EACvF9C,QAAAA,CAAC,CAAC,IAAD,CAAD,CAAQuD,QAAR,CAAiB,qBAAjB;EACD,OApJL,EAqJKT,EArJL,CAqJQ,wBArJR,EAqJkC,kDArJlC,EAqJsF,YAAW;EAC3F9C,QAAAA,CAAC,CAAC,IAAD,CAAD,CAAQmB,WAAR,CAAoB,qBAApB;EACD,OAvJL,EAwJK2B,EAxJL,CAwJQ,MAxJR,EAwJgB,kDAxJhB,EAwJoE,UAASlJ,CAAT,EAAY;EAC5E;EACEqG,QAAAA,IAAI,CAACiK,OAAL,CAAarL,KAAb,WAA0B2N,OAA1B,CAAkC5S,CAAC,CAAC+X,aAAF,CAAgBC,YAAhB,CAA6BH,KAA7B,CAAmC,CAAnC,KAAyC,IAA3E;EACD,OA3JL,EA4JK3O,EA5JL,CA4JQ,OA5JR,EA4JiB,8CA5JjB,EA4JiE,UAASlJ,CAAT,EAAY;EACzE;EACE,YAAMoX,QAAQ,GAAGhR,CAAC,CAACpG,CAAC,CAAChJ,MAAH,CAAD,CAAYE,OAAZ,CAAoB,gDAApB,EAAsE2D,IAAtE,GAA6Eod,QAA9F;;EACA,YAAI,CAACb,QAAQ,CAACtY,MAAd,EAAsB;EACpBnB,UAAAA,KAAK,CAAC,iCAAD,CAAL;EACA;EACD;;EACD0I,QAAAA,IAAI,CAACiK,OAAL,CAAarL,KAAb,WAA0BpK,IAA1B,CAA+B4X,IAA/B,GAAsC2E,QAAtC;EACA/Q,QAAAA,IAAI,CAACiK,OAAL,CAAauF,sBAAb,GARuE;EAUzE;EACC,OAvKL,EAwKK3M,EAxKL,CAwKQ,QAxKR,EAwKkB,qDAxKlB,EAwKyE,UAASlJ,CAAT,EAAY;EACjF;EACV;EACA;EACA;EACA;EACA;EACYnI,QAAAA,UAAU,CAAC,UAASmI,CAAT,EAAY;EACvB;EACE1J,UAAAA,QAAQ,CAACsT,cAAT,CAAwB,qCAAxB,EAA+DtS,KAA/D,CAAqEC,OAArE,GAA+E,MAA/E,CAFqB;;EAKrB,cAAM2gB,eAAe,GAAG5hB,QAAQ,CAACsT,cAAT,CAAwB,yBAAxB,EAAmD7M,OAA3E;EACA,cAAMob,mBAAmB,GAAG7hB,QAAQ,CAACsT,cAAT,CAAwB,6BAAxB,EAAuD7M,OAAnF;;EACA,cAAIob,mBAAmB,IAAI,CAACD,eAA5B,EAA6C;EAC3C5hB,YAAAA,QAAQ,CAACsT,cAAT,CAAwB,qCAAxB,EAA+DtS,KAA/D,CAAqEC,OAArE,GAA+E,OAA/E;EACD;EACF,SAVS,EAUP,GAVO,CAAV;EAWD,OA1LL;EA4LD,KA1ZY;EA2Zb2e,IAAAA,YA3Za,wBA2ZAkC,aA3ZA,EA2ZsB;EAAA,UAAtBA,aAAsB;EAAtBA,QAAAA,aAAsB,GAAN,IAAM;EAAA;;EACjC3H,MAAAA,SAAS,CAAC,IAAD,CAAT;;EAEA,UAAI2H,aAAJ,EAAmB;EACjB9P,QAAAA,WAAW;EACZ;;EAED,aAAOxO,KAAK,CAAIiP,OAAJ,0CAAgDiK,IAAI,CAAC+D,MAAL,EAAhD,qBAA6Epe,KAAK,CAACyB,WAAnF,eAAwGzB,KAAK,CAAC0B,KAA9G,CAAL,CACFE,IADE,CACG4N,iBADH,EAEF5N,IAFE,CAEG,UAACmb,GAAD;EAAA,eAASA,GAAG,CAAChb,IAAJ,EAAT;EAAA,OAFH,EAGFH,IAHE,CAGG,UAACmb,GAAD,EAAS;EACb3N,QAAAA,kBAAkB,CAAC2N,GAAD,EAAM,EAAN,EAAU,yBAAV,CAAlB;EACA7O,QAAAA,KAAK,CAACG,GAAN,CAAU,qBAAV,EAAiC3C,IAAjC,CAAsCqR,GAAtC;EACAjF,QAAAA,SAAS,CAAC,KAAD,CAAT;EACA3Y,QAAAA,MAAM,CAACyY,aAAP,CAAqB,IAAIC,KAAJ,CAAU,uBAAV,CAArB;EACA,eAAOkF,GAAP;EACD,OATE,WAUI,UAAC1V,CAAD;EAAA,eAAO+H,kBAAkB,CAAC/H,CAAD,EAAI,EAAJ,EAAQ,yBAAR,CAAzB;EAAA,OAVJ,CAAP;EAYD,KA9aY;EAAA,iCA+aJ;EACPoG,MAAAA,CAAC,CAAC,qBAAD,CAAD,CACKoQ,GADL,CACS,OADT,EACkB,gCADlB,EAEKtN,EAFL,CAEQ,OAFR,EAEiB,gCAFjB,EAEmD,UAASlJ,CAAT,EAAY;EACzDA,QAAAA,CAAC,CAAC3D,cAAF;EACAiM,QAAAA,WAAW;;EAEX,YAAI,CAACqC,OAAO,CAAC,8CAAD,CAAZ,EAA8D;EAC5D;EACD;;EAED8F,QAAAA,SAAS,CAAC,IAAD,CAAT;EACA5J,QAAAA,KAAK,CAACG,GAAN,CAAU,yBAAV,EAAqCQ,IAArC;EACA,YAAM6Q,GAAG,GAAG,KAAK1b,YAAL,CAAkB,UAAlB,CAAZ;EACA0J,QAAAA,IAAI,CAACyD,IAAL,CACI;EACEjQ,UAAAA,MAAM,EAAE,wBADV;EAEEwe,UAAAA,GAAG,EAAEA,GAFP;EAGEje,UAAAA,WAAW,EAAEzB,KAAK,CAACyB,WAHrB;EAIEC,UAAAA,KAAK,EAAE1B,KAAK,CAAC0B;EAJf,SADJ,EAOI,UAASG,QAAT,EAAmB;EACjBuN,UAAAA,kBAAkB,CAACvN,QAAD,EAAW,EAAX,EAAe,kEAAf,CAAlB;EACAiW,UAAAA,SAAS,CAAC,KAAD,CAAT;EACApK,UAAAA,IAAI,CAACiK,OAAL,CAAa4F,YAAb;EACD,SAXL;EAaD,OA1BL,EADO;EA+BP;;EACA9P,MAAAA,CAAC,CAAC,sBAAD,CAAD,CACKoQ,GADL,CACS,OADT,EACkB,4BADlB,EAEKtN,EAFL,CAEQ,OAFR,EAEiB,4BAFjB,EAE+C,UAASlJ,CAAT,EAAY;EACrDA,QAAAA,CAAC,CAAC3D,cAAF;EACAiM,QAAAA,WAAW;EACXmI,QAAAA,SAAS,CAAC,IAAD,CAAT;EACA,YAAM6F,EAAE,GAAG,KAAK3Z,YAAL,CAAkB,SAAlB,CAAX;;EAEA,YAAI,CAACgO,OAAO,CAAC,uCAAuC2L,EAAvC,GAA4C,2BAA7C,CAAZ,EAAuF;EACrF7F,UAAAA,SAAS,CAAC,KAAD,CAAT;EACA,iBAAO,KAAP;EACD;;EAEDpK,QAAAA,IAAI,CAACyD,IAAL,CACI;EACEjQ,UAAAA,MAAM,EAAE,wBADV;EAEEyc,UAAAA,EAAE,EAAEA,EAFN;EAGElc,UAAAA,WAAW,EAAEzB,KAAK,CAACyB,WAHrB;EAIEC,UAAAA,KAAK,EAAE1B,KAAK,CAAC0B;EAJf,SADJ,EAOI,UAASG,QAAT,EAAmB;EACjBuN,UAAAA,kBAAkB,CAACvN,QAAD,EAAW,EAAX,EAAe,kEAAf,CAAlB,CADiB;;EAGjB6L,UAAAA,IAAI,CAACiK,OAAL,CAAa4F,YAAb;EACAzF,UAAAA,SAAS,CAAC,KAAD,CAAT;EACD,SAZL;EAcD,OA3BL;EA6BD,KA5eY;EA6ebuB,IAAAA,MA7ea,oBA6eJ;EACP,UAAMsG,aAAa,GAAG,SAAhBA,aAAgB,CAASzd,IAAT,EAAe;EACnCsL,QAAAA,SAAS,CAAC2D,IAAV,CACI;EACEjQ,UAAAA,MAAM,EAAE,gCADV;EAEEO,UAAAA,WAAW,EAAEzB,KAAK,CAACyB,WAFrB;EAGEC,UAAAA,KAAK,EAAE1B,KAAK,CAAC0B,KAHf;EAIEke,UAAAA,eAAe,EAAE1d;EAJnB,SADJ,EAOI,UAASL,QAAT,EAAmB;EACjB,cAAIA,QAAQ,CAACM,OAAb,EAAsB;EACpBuL,YAAAA,IAAI,CAACiK,OAAL,CAAatH,KAAb,CAAmBgI,KAAnB;EAEAwH,YAAAA,YAAY;EACb,WAJD,MAIO;EACLzQ,YAAAA,kBAAkB,CAACvN,QAAQ,CAACK,IAAV,EAAgB,EAAhB,EAAoB,yBAApB,CAAlB;EACD;EACF,SAfL,EAgBI,MAhBJ,EAiBI,KAjBJ,EAkBI,CAlBJ,EAmBI,IAnBJ;EAqBD,OAtBD;;EAuBA,UAAM2d,YAAY,GAAG,SAAfA,YAAe,GAAW;EAC9BlQ,QAAAA,WAAW;;EAEX,YAAIjC,IAAI,CAACiK,OAAL,CAAahK,WAAjB,EAA8B;EAC5B;EACA;EACD;;EAED,YAAMmS,UAAU,GAAG,SAAbA,UAAa,GAAM;EACvB5O,UAAAA,aAAa,CAACxD,IAAI,CAACiK,OAAL,CAAawB,WAAb,CAAyBC,QAA1B,CAAb;EACA1L,UAAAA,IAAI,CAACiK,OAAL,CAAawB,WAAb,CAAyBC,QAAzB,GAAoC,IAApC;EACD,SAHD;;EAIA,YAAM3J,MAAM,GAAG,SAATA,MAAS,GAAM;EACnB,cAAI/B,IAAI,CAACiK,OAAL,CAAawB,WAAb,CAAyBC,QAAzB,KAAsC,IAA1C,EAAgD;EAC9C;EACD;;EACD1L,UAAAA,IAAI,CAACiK,OAAL,CAAawB,WAAb,CAAyBC,QAAzB,GAAoCpB,WAAW,CAAC,YAAM;EACpD,gBAAI,SAAStK,IAAI,CAACiK,OAAL,CAAahK,WAA1B,EAAuC;EACrCmS,cAAAA,UAAU;EACV;EACD;;EAED,gBAAIpS,IAAI,CAACiK,OAAL,CAAalI,MAAb,CAAoB2N,WAApB,KAAoC,KAAxC,EAA+C;EAC7C;EACD;;EAED1P,YAAAA,IAAI,CAACiK,OAAL,CAAalI,MAAb,CAAoB2N,WAApB,GAAkC,KAAlC;EACAjc,YAAAA,KAAK,CAAIiP,OAAJ,mDAAyDpQ,KAAK,CAACyB,WAA/D,eAAoFzB,KAAK,CAAC0B,KAA1F,CAAL,CACKE,IADL,CACU,UAACmb,GAAD;EAAA,qBAASA,GAAG,CAAChb,IAAJ,EAAT;EAAA,aADV,EAEKH,IAFL,CAEU,UAACmb,GAAD,EAAS;EACbrP,cAAAA,IAAI,CAACiK,OAAL,CAAalI,MAAb,CAAoB2N,WAApB,GAAkC,IAAlC;;EACA,kBAAI,OAAOL,GAAP,KAAe,WAAnB,EAAgC;EAC9B+C,gBAAAA,UAAU;EACX;;EAED,kBAAIpS,IAAI,CAACiK,OAAL,CAAawB,WAAb,CAAyB1N,KAAzB,KAAmCsR,GAAG,CAACgD,kBAA3C,EAA+D;EAC7D;EACD;;EAEDrS,cAAAA,IAAI,CAACiK,OAAL,CAAawB,WAAb,CAAyB1N,KAAzB,GAAiCsR,GAAG,CAACgD,kBAArC;EACA,kBAAMhC,UAAU,GAAGtQ,CAAC,CAAChE,IAAI,CAACuU,YAAL,EAAD,CAApB;EACAD,cAAAA,UAAU,CAAChN,IAAX,CAAgB,+BAAhB,EAAiDpC,IAAjD,CAAsDoO,GAAG,CAACgD,kBAA1D;EACAhC,cAAAA,UAAU,CAAChN,IAAX,CAAgB,iCAAhB,EAAmDpC,IAAnD,CAAwD,GAAxD;EACD,aAhBL,WAiBW,UAACtH,CAAD,EAAO;EACZqG,cAAAA,IAAI,CAACiK,OAAL,CAAalI,MAAb,CAAoB2N,WAApB,GAAkC,IAAlC;EACAhO,cAAAA,kBAAkB,CAAC/H,CAAD,EAAI,EAAJ,EAAQ,yBAAR,CAAlB;EACD,aApBL;EAsBD,WAjC8C,EAiC5C,IAjC4C,CAA/C;EAkCD,SAtCD;;EAuCAmG,QAAAA,SAAS,CAAC2D,IAAV,CACI;EACEjQ,UAAAA,MAAM,EAAE,wBADV;EAEEO,UAAAA,WAAW,EAAEzB,KAAK,CAACyB,WAFrB;EAGEC,UAAAA,KAAK,EAAE1B,KAAK,CAAC0B;EAHf,SADJ,EAMI,UAASG,QAAT,EAAmB;EACjB,cAAI,OAAOA,QAAP,KAAoB,WAAxB,EAAqC;EACnC3C,YAAAA,UAAU,CAAC,YAAW;EACpB2gB,cAAAA,YAAY;EACb,aAFS,EAEP7f,KAAK,CAACuY,QAFC,CAAV;EAGA;EACD;;EAED7K,UAAAA,IAAI,CAACiK,OAAL,CAAaqI,eAAb,CAA6Bne,QAA7B;;EACA,cAAI,CAAC6L,IAAI,CAACiK,OAAL,CAAawB,WAAb,CAAyBC,QAA9B,EAAwC;EACtC3J,YAAAA,MAAM;EACP;;EAED,cAAI5N,QAAQ,CAAC4N,MAAT,KAAoB,KAAxB,EAA+B;EAC7BoQ,YAAAA,YAAY;EACb,WAFD,MAEO,IAAIhe,QAAQ,CAAC4N,MAAT,KAAoB,IAAxB,EAA8B;EACnChC,YAAAA,CAAC,CAAC,0BAAD,CAAD,CAA8BkB,IAA9B,CAAmC,8BAAnC;EACAjB,YAAAA,IAAI,CAACiK,OAAL,CAAa/W,IAAb,GAAoB,IAApB;;EACA,gBAAI8M,IAAI,CAACiK,OAAL,CAAagD,QAAb,CAAsBU,UAAtB,EAAJ,EAAwC;EACxC;EACE3N,cAAAA,IAAI,CAACiK,OAAL,CAAa4F,YAAb;EACA7P,cAAAA,IAAI,CAACiK,OAAL,CAAasI,SAAb;EACA;EACD;;EACDH,YAAAA,UAAU;EACVrW,YAAAA,IAAI,CAACyW,KAAL;EACAxS,YAAAA,IAAI,CAACiK,OAAL,CAAa4F,YAAb,GACK3b,IADL,CACU,YAAM;EACV,kBAAI,CAACC,QAAQ,CAACse,SAAd,EAAyB;EACvB1R,gBAAAA,SAAS,CAAC,wCAAD,CAAT;EACA;EACD,eAJS;;;EAOV,kBAAI2R,GAAG,GAAG,EAAV;EACA,kBAAIC,WAAW,GAAG,CAAlB;EACA,kBAAMC,0BAA0B,GAAGtI,WAAW,CAAC,YAAW;EACxDqI,gBAAAA,WAAW;EACXD,gBAAAA,GAAG,GAAG3S,CAAC,0CAAuC5L,QAAQ,CAACse,SAAhD,SAAP,CAFwD;;EAKxD,oBAAI,CAACC,GAAG,CAACja,MAAT,EAAiB;EACf,sBAAIka,WAAW,IAAI,EAAnB,EAAuB;EACrB;EACAnP,oBAAAA,aAAa,CAACoP,0BAAD,CAAb;EACD;;EACD;EACD,iBAXuD;;;EAcxDpP,gBAAAA,aAAa,CAACoP,0BAAD,CAAb;EAEA,oBAAMC,UAAU,GAAG1e,QAAQ,CAACsN,cAAT,CAAwB,YAAxB,IAAwC,OAAOtN,QAAQ,CAAC0e,UAAhB,GAA6B,GAArE,GAA2E,EAA9F;EAEA7S,gBAAAA,IAAI,CAACiK,OAAL,CAAa8F,aAAb,CAA2B;EACzBE,kBAAAA,EAAE,EAAEyC,GAAG,CAACle,IAAJ,CAAS,IAAT,CADqB;EAEzB2N,kBAAAA,GAAG,EAAEuQ,GAAG,CAACle,IAAJ,CAAS,KAAT,CAFoB;EAGzBuJ,kBAAAA,KAAK,EAAE2U,GAAG,CAACle,IAAJ,CAAS,OAAT,CAHkB;EAIzBwb,kBAAAA,WAAW,EAAE0C,GAAG,CAACle,IAAJ,CAAS,cAAT,CAJY;EAKzB0X,kBAAAA,YAAY,EAAEwG,GAAG,CAACle,IAAJ,CAAS,gBAAT,CALW;EAMzByX,kBAAAA,aAAa,EAAEyG,GAAG,CAACle,IAAJ,CAAS,kBAAT,IAA+Bqe;EANrB,iBAA3B;EAQA9S,gBAAAA,CAAC,CAAC,wCAAD,CAAD,CAA4CpE,IAA5C;EACA,oBAAMmX,cAAc,GAAG/S,CAAC,CAAC,8BAAD,CAAxB;EACAC,gBAAAA,IAAI,CAACiK,OAAL,CAAagD,QAAb,CAAsBzY,IAAtB,CAA2BrE,GAA3B,CAA+BqH,OAA/B,CAAuC,UAAC5C,OAAD,EAAa;EAClD,sBAAMme,QAAQ,oCAAkCne,OAAO,CAAC1B,IAAR,CAAamP,WAAb,EAAhD;EACAyQ,kBAAAA,cAAc,CACTvO,MADL,iBACyBwO,QADzB,YACuCne,OAAO,CAAC1B,IAD/C,aAC2D0B,OAAO,CAAC8U,IADnE,YAC8E9U,OAAO,CAACA,OADtF;EAGD,iBALD;EAMD,eAlC6C,EAkC3C,GAlC2C,CAA9C;EAmCD,aA7CL;EA+CD,WA1DM,MA0DA;EACLpD,YAAAA,UAAU,CAAC,YAAW;EACpB2gB,cAAAA,YAAY;EACb,aAFS,EAEP7f,KAAK,CAACuY,QAFC,CAAV;EAGD;EACF,SApFL,EAqFI,MArFJ,EAsFI,KAtFJ,EAuFI,CAvFJ;EAwFI,YAxFJ;EA0FD,OA7ID;;EA+IA,UAAMmI,KAAK,GAAGjT,CAAC,CAAC,MAAD,CAAf;EAEAiT,MAAAA,KAAK,CACA7C,GADL,CACS,OADT,EACkB,qBADlB,EAEKtN,EAFL,CAEQ,OAFR,EAEiB,qBAFjB,EAEwC,YAAW;EAC7C,YAAMG,KAAK,GAAGjD,CAAC,CAAC,IAAD,CAAf;EACA,YAAMkT,OAAO,GAAGlT,CAAC,CAACiD,KAAK,CAACD,IAAN,CAAW,aAAX,CAAD,CAAjB;EACAkQ,QAAAA,OAAO,CAACC,MAAR;;EACA,YAAID,OAAO,CAAC7L,EAAR,CAAW,UAAX,CAAJ,EAA4B;EAC1BpE,UAAAA,KAAK,CAACK,IAAN,CAAW,MAAX,EAAmBpC,IAAnB,CAAwB,GAAxB;EACD,SAFD,MAEO;EACL+B,UAAAA,KAAK,CAACK,IAAN,CAAW,MAAX,EAAmBpC,IAAnB,CAAwB,GAAxB;EACD;EACF,OAXL,EAYKkP,GAZL,CAYS,QAZT,EAYmB,qGAZnB,EAaKtN,EAbL,CAaQ,QAbR,EAakB,sHAblB,EAa0I,YAAW;EAC/I,YAAMsQ,iBAAiB,GAAGpT,CAAC,CAAC,2DAAD,CAAD,CAA+DtH,MAA/D,GAAwE,CAAlG;EACA,YAAMyY,mBAAmB,GAAGnR,CAAC,CAAC,uCAAD,CAAD,CAA2CtH,MAA3C,KAAsD,CAAlF;EACA,YAAM2a,gCAAgC,GAAGrT,CAAC,CAAC,4CAAD,CAAD,CAAgDtH,MAAhD,KAA2D,CAApG;;EACA,YAAI,CAAC0a,iBAAD,IAAsB,CAACjC,mBAAvB,IAA8C,CAACkC,gCAAnD,EAAqF;EACnFrT,UAAAA,CAAC,CAAC,gBAAD,CAAD,CAAoByB,IAApB,CAAyB,UAAzB,EAAqC,IAArC;EACD,SAFD,MAEO;EACLzB,UAAAA,CAAC,CAAC,gBAAD,CAAD,CAAoByB,IAApB,CAAyB,UAAzB,EAAqC,KAArC;EACD;EACF,OAtBL,EAzKO;;EAmMPzB,MAAAA,CAAC,CAAC,qBAAD,CAAD,CACKoQ,GADL,CACS,OADT,EACkB,mBADlB,EAEKtN,EAFL,CAEQ,OAFR,EAEiB,mBAFjB;EAAA,2EAEsC,iBAAelJ,CAAf;EAAA;;EAAA;EAAA;EAAA;EAAA;EAChCsI,kBAAAA,WAAW;EACXtI,kBAAAA,CAAC,CAAC3D,cAAF;EACAgK,kBAAAA,IAAI,CAACiK,OAAL,CAAahK,WAAb,GAA2B,KAA3B;;EAEA,sBAAI,CAACD,IAAI,CAACiK,OAAL,CAAarL,KAAb,CAAmB+M,MAAnB,CAA0B3N,IAA3B,IAAmC,CAACgC,IAAI,CAACiK,OAAL,CAAarL,KAAb,CAAmB+M,MAAnB,CAA0BC,aAAlE,EAAiF;EACzEyH,oBAAAA,eADyE,GACvDtT,CAAC,CAAC,4BAAD,CADsD;EAEzE/B,oBAAAA,IAFyE,GAElEqV,eAAe,CAACrV,IAAhB,EAFkE;EAGzEsV,oBAAAA,MAHyE,GAGhED,eAAe,CAACtQ,IAAhB,CAAqB,wBAArB,CAHgE;EAI/E/C,oBAAAA,IAAI,CAACiK,OAAL,CAAarL,KAAb,CAAmB+M,MAAnB,CAA0B3N,IAA1B,GAAiCA,IAAI,IAAI,IAAzC;EACAgC,oBAAAA,IAAI,CAACiK,OAAL,CAAarL,KAAb,CAAmB+M,MAAnB,CAA0BC,aAA1B,GAA0C0H,MAAM,IAAI,IAApD;EACAD,oBAAAA,eAAe,CAAC3V,MAAhB;EACD;;EAZ+B;EAAA,yBAcE3B,IAAI,CAACC,IAAL,CAAU;EAC1C+B,oBAAAA,KAAK,EAAE,EADmC;EAE1CC,oBAAAA,IAAI,EAAEgC,IAAI,CAACiK,OAAL,CAAarL,KAAb,CAAmB+M,MAAnB,CAA0B3N,IAFU;EAG1CG,oBAAAA,YAAY,EAAE,KAH4B;EAI1CI,oBAAAA,iBAAiB,EAAEyB,IAAI,CAACiK,OAAL,CAAarL,KAAb,CAAmB+M,MAAnB,CAA0BC,aAJH;EAK1CnN,oBAAAA,gBAAgB,EAAE,IALwB;EAM1C8U,oBAAAA,UAAU,EAAE,sBAAM;EAChB,0BAAMjV,SAAS,GAAGvC,IAAI,CAACuU,YAAL,EAAlB;EAEA,6BAAO;EACL5Q,wBAAAA,IAAI,EAAEpB,SAAS,CAACpO,aAAV,CAAwB,2BAAxB,EAAqDsG,KAArD,IAA8D,IAD/D;EAEL2a,wBAAAA,kBAAkB,EAAE7S,SAAS,CAACpO,aAAV,CAAwB,iCAAxB,MAA+D,IAF9E;EAGLkhB,wBAAAA,oBAAoB,EAAE9S,SAAS,CAACpO,aAAV,CAAwB,mCAAxB,MAAiE,IAHlF;EAILmhB,wBAAAA,iBAAiB,EAAE/S,SAAS,CAACpO,aAAV,CAAwB,gCAAxB,MAA8D,IAJ5E;EAKLohB,wBAAAA,kBAAkB,EAAEhT,SAAS,CAACpO,aAAV,CAAwB,sCAAxB,MAAoE,IALnF;EAMLqhB,wBAAAA,8BAA8B,EAAEjT,SAAS,CAACpO,aAAV,CAAwB,uCAAxB,MAAqE,IANhG;EAOLghB,wBAAAA,mBAAmB,EAAE5S,SAAS,CAACpO,aAAV,CAAwB,kCAAxB,MAAgE;EAPhF,uBAAP;EASD;EAlByC,mBAAV,CAdF;;EAAA;EAAA;EAclBsjB,kBAAAA,UAdkB,oBAczBhd,KAdyB;;EAAA,sBAmC3Bgd,UAnC2B;EAAA;EAAA;EAAA;;EAAA;;EAAA;EAuChCxT,kBAAAA,IAAI,CAACiK,OAAL,CAAa4B,OAAb,CAAqB;EACnB4H,oBAAAA,OAAO,EAAE,mBAAM;EACbzT,sBAAAA,IAAI,CAACiK,OAAL,CAAagD,QAAb,CAAsBe,KAAtB;EACAiE,sBAAAA,aAAa,CAACuB,UAAD,CAAb;EACD;EAJkB,mBAArB;;EAvCgC;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA,SAFtC;;EAAA;EAAA;EAAA;EAAA;EAiDD,KAjuBY;EAkuBbhE,IAAAA,sBAluBa,oCAkuBY;EACvBxP,MAAAA,IAAI,CAACiK,OAAL,CAAarL,KAAb,WAA0ByN,eAA1B,CAA0ClL,IAA1C;EACAnB,MAAAA,IAAI,CAACiK,OAAL,CAAarL,KAAb,WAA0B0N,mBAA1B,CAA8CnL,IAA9C;EACAnB,MAAAA,IAAI,CAACiK,OAAL,CAAarL,KAAb,WAA0B8U,kBAA1B,CAA6C/X,IAA7C;EACD,KAtuBY;EAuuBb;EACAiU,IAAAA,IAxuBa,kBAwuBN;EACL7P,MAAAA,CAAC,CAAC,qBAAD,CAAD,CACKoQ,GADL,CACS,OADT,EACkB,gCADlB,EAEKtN,EAFL,CAEQ,OAFR,EAEiB,gCAFjB;EAAA,4EAEmD,kBAAelJ,CAAf;EAAA;;EAAA;EAAA;EAAA;EAAA;EAC7CA,kBAAAA,CAAC,CAAC3D,cAAF;EAEMgN,kBAAAA,KAHuC,GAG/BjD,CAAC,CAAC,IAAD,CAH8B;EAIvCL,kBAAAA,IAJuC,GAIhCsD,KAAK,CAACxO,IAAN,CAAW,MAAX,CAJgC;EAKvCmf,kBAAAA,KALuC,GAK/B3Q,KAAK,CAACxO,IAAN,CAAW,OAAX,CAL+B;EAAA;EAAA,yBAOXuH,IAAI,CAACC,IAAL,CAAU;EAC1C+B,oBAAAA,KAAK,EAAE,EADmC;EAE1CC,oBAAAA,IAAI,oLAEwE0B,IAFxE,iKAI2EiU,KAJ3E,oCAFsC;EAQ1CxV,oBAAAA,YAAY,EAAE,KAR4B;EAS1CI,oBAAAA,iBAAiB,EAAE,eATuB;EAU1CE,oBAAAA,gBAAgB,EAAE,IAVwB;EAW1C8U,oBAAAA,UAAU,EAAE;EAAA,6BAAO;EACjB7T,wBAAAA,IAAI,EAAEzP,QAAQ,CAACsT,cAAT,CAAwB,8BAAxB,EAAwD/M,KAAxD,IAAiE,IADtD;EAEjBmd,wBAAAA,KAAK,EAAE1jB,QAAQ,CAACsT,cAAT,CAAwB,kCAAxB,EAA4D/M,KAA5D,IAAqE;EAF3D,uBAAP;EAAA;EAX8B,mBAAV,CAPW;;EAAA;EAAA;EAO/Bgd,kBAAAA,UAP+B,qBAOtChd,KAPsC;;EAAA,sBAwBxCgd,UAxBwC;EAAA;EAAA;EAAA;;EAAA;;EAAA;EA4B7CxT,kBAAAA,IAAI,CAACyD,IAAL,CACI;EACEjQ,oBAAAA,MAAM,EAAE,sBADV;EAEEO,oBAAAA,WAAW,EAAEzB,KAAK,CAACyB,WAFrB;EAGEC,oBAAAA,KAAK,EAAE1B,KAAK,CAAC0B,KAHf;EAIEge,oBAAAA,GAAG,EAAEhP,KAAK,CAACxO,IAAN,CAAW,KAAX,CAJP;EAKEkL,oBAAAA,IAAI,EAAE8T,UAAU,CAAC9T,IALnB;EAMEiU,oBAAAA,KAAK,EAAEH,UAAU,CAACG;EANpB,mBADJ,EASI,UAASxf,QAAT,EAAmB;EACjBuN,oBAAAA,kBAAkB,CAACvN,QAAD,EAAW,EAAX,EAAe,yBAAf,CAAlB,CADiB;;EAGjB6L,oBAAAA,IAAI,CAACiK,OAAL,CAAa4F,YAAb;EACD,mBAbL;;EA5B6C;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA,SAFnD;;EAAA;EAAA;EAAA;EAAA;EA+CD,KAxxBY;EAyxBb+D,IAAAA,MAzxBa,oBAyxBJ;EACP5T,MAAAA,IAAI,CAACiK,OAAL,CAAatH,KAAb,CAAmBwL,IAAnB;EACAnO,MAAAA,IAAI,CAACiK,OAAL,CAAahK,WAAb,GAA2B,IAA3B;EACAlE,MAAAA,IAAI,CAACyW,KAAL;EACAhhB,MAAAA,UAAU,CAAC;EAAA,eAAMwO,IAAI,CAACyD,IAAL,CACb;EACEjQ,UAAAA,MAAM,EAAE,wBADV;EAEEO,UAAAA,WAAW,EAAEzB,KAAK,CAACyB,WAFrB;EAGEC,UAAAA,KAAK,EAAE1B,KAAK,CAAC0B,KAHf;EAIEd,UAAAA,IAAI,EAAE8M,IAAI,CAACiK,OAAL,CAAa/W;EAJrB,SADa,EAOb,UAASiB,QAAT,EAAmB;EACjBuN,UAAAA,kBAAkB,CAACvN,QAAD,EAAW,EAAX,EAAe,yBAAf,CAAlB;EACD,SATY,CAAN;EAAA,OAAD,EAUP,GAVO,CAAV;EAWD,KAxyBY;;EAyyBb;EACJ;EACA;EACA;EACA;EACI0X,IAAAA,OA9yBa,mBA8yBLA,QA9yBK,EA8yBI;EACf,UAAI,OAAOA,QAAO,CAAC4H,OAAf,KAA2B,UAA3B,KAA0C,CAAC5H,QAAO,CAACrX,IAAT,IAAiB,CAACqX,QAAO,CAACgI,UAApE,CAAJ,EAAqF;EACnF9X,QAAAA,IAAI,CAACyW,KAAL;EACAzR,QAAAA,SAAS,CAAC,qDAAD,CAAT;EACA;EACD,OALc;;;EAQf,UAAI,CAACf,IAAI,CAACiK,OAAL,CAAarL,KAAb,CAAmBiN,OAAnB,CAA2B7N,IAA5B,IAAoC,CAACgC,IAAI,CAACiK,OAAL,CAAarL,KAAb,CAAmBiN,OAAnB,CAA2BC,YAApE,EAAkF;EAChF,YAAMgI,MAAM,GAAG/T,CAAC,CAAC,gCAAD,CAAhB;EACA,YAAM/B,IAAI,GAAG8V,MAAM,CAAC9V,IAAP,EAAb;EACA,YAAMsV,MAAM,GAAGQ,MAAM,CAAC/Q,IAAP,CAAY,uBAAZ,CAAf;EACA/C,QAAAA,IAAI,CAACiK,OAAL,CAAarL,KAAb,CAAmBiN,OAAnB,CAA2B7N,IAA3B,GAAkCA,IAAI,IAAI,IAA1C;EACAgC,QAAAA,IAAI,CAACiK,OAAL,CAAarL,KAAb,CAAmBiN,OAAnB,CAA2BC,YAA3B,GAA0CwH,MAAM,IAAI,IAApD;EACAQ,QAAAA,MAAM,CAACpW,MAAP;EACD;;EAEDqC,MAAAA,CAAC,CAAC,MAAD,CAAD,CACKoQ,GADL,CACS,OADT,EACkB,oCADlB,EAEKtN,EAFL,CAEQ,OAFR,EAEiB,oCAFjB,EAEuD,UAASlJ,CAAT,EAAY;EAC7DA,QAAAA,CAAC,CAAC3D,cAAF;EACA,YAAMsI,SAAS,GAAGvC,IAAI,CAACuU,YAAL,EAAlB;EACA,YAAMyD,KAAK,GAAGhU,CAAC,CAACzB,SAAD,CAAD,CAAa+E,IAAb,CAAkB,8BAAlB,CAAd;EACA0Q,QAAAA,KAAK,CAACb,MAAN;;EACA,YAAIa,KAAK,CAAC3M,EAAN,CAAS,UAAT,CAAJ,EAA0B;EACxB9I,UAAAA,SAAS,CAAC0V,UAAV,CAAqB,CAArB,EAAwB/iB,KAAxB,CAA8BiN,KAA9B,GAAsC,MAAtC;EACAI,UAAAA,SAAS,CAACrN,KAAV,CAAgB,SAAhB,IAA6B,IAA7B;EACD,SAHD,MAGO;EACLqN,UAAAA,SAAS,CAAC0V,UAAV,CAAqB,CAArB,EAAwB/iB,KAAxB,CAA8BiN,KAA9B,GAAsC,OAAtC;EACD;EACF,OAbL;EAgBA2N,MAAAA,QAAO,CAACoI,kBAAR,GAA6B,UAAUpI,QAAO,CAACoI,kBAA/C;EAEAjU,MAAAA,IAAI,CAACiK,OAAL,CAAarL,KAAb,CAAmBiN,OAAnB,CAA2BjN,KAA3B,GAAmC7C,IAAI,CAACmY,KAAL,CAAW;EAC5C9V,QAAAA,WAAW,EAAE;EACX+V,UAAAA,YAAY,EAAE,sDADH;EAEX3a,UAAAA,OAAO,EAAE;EAFE,SAD+B;EAK5C4a,QAAAA,cAAc,EAAE;EAL4B,OAAX,EAMhCpY,IANgC,CAM3B;EACNgC,QAAAA,IAAI,EAAEgC,IAAI,CAACiK,OAAL,CAAarL,KAAb,CAAmBiN,OAAnB,CAA2B7N,IAD3B;EAENqW,QAAAA,gBAAgB,EAAErU,IAAI,CAACiK,OAAL,CAAarL,KAAb,CAAmBiN,OAAnB,CAA2BC,YAFvC;EAGNrN,QAAAA,gBAAgB,EAAEoN,QAAO,CAACoI,kBAHpB;EAINK,QAAAA,iBAAiB,EAAE,KAJb;EAKNC,QAAAA,iBAAiB,EAAE,KALb;EAMNC,QAAAA,cAAc,EAAE,KANV;EAONtW,QAAAA,KAAK,EAAE,GAPD;EAQNuW,QAAAA,QAAQ,EAAE,oBAAM;EACd,cAAMC,UAAU,GAAG3Y,IAAI,CAACuU,YAAL,GAAoBqE,sBAApB,CAA2C,iCAA3C,EAA8E,CAA9E,CAAnB;;EACA,cAAMC,SAAS,GAAGF,UAAU,CAACjb,SAAX,CAAqB,IAArB,CAAlB;;EACAib,UAAAA,UAAU,CAACG,UAAX,CAAsBC,YAAtB,CAAmCF,SAAnC,EAA8CF,UAA9C;;EAEAE,UAAAA,SAAS,CAACnkB,gBAAV,CAA2B,OAA3B,EAAoC,UAASkJ,CAAT,EAAY;EAC9C,gBAAI2K,OAAO,CAAC,6CAAD,CAAX,EAA4D;EAC1DvI,cAAAA,IAAI,CAACyW,KAAL;EACD;EACF,WAJD;;EAMA,cAAI,OAAO3G,QAAO,CAAC4H,OAAf,KAA2B,UAA/B,EAA2C;EACzC5H,YAAAA,QAAO,CAAC4H,OAAR;;EACA;EACD;;EAED,cAAI,CAAC5H,QAAO,CAACrX,IAAT,IAAiB,CAACqX,QAAO,CAACgI,UAA9B,EAA0C;EACxC9X,YAAAA,IAAI,CAACyW,KAAL;EACAzR,YAAAA,SAAS,CAAC,qDAAD,CAAT;EACA;EACD;;EAEDf,UAAAA,IAAI,CAACyD,IAAL,CAAUoI,QAAO,CAACrX,IAAlB,EAAwBqX,QAAO,CAACgI,UAAhC;EACD,SA/BK;EAgCNkB,QAAAA,YAAY,EAAE;EAAA,iBAAM,OAAOlJ,QAAO,CAACkJ,YAAf,KAAgC,UAAhC,IAA8ClJ,QAAO,CAACkJ,YAAR,EAApD;EAAA,SAhCR;EAiCNC,QAAAA,OAAO,EAAE,mBAAM;EACbhV,UAAAA,IAAI,CAACiK,OAAL,CAAa2J,MAAb;EACD;EAnCK,OAN2B,CAAnC;EA2CD,KA53BY;EA63BbtB,IAAAA,eA73Ba,2BA63BGne,QA73BH,EA63Ba8gB,QA73Bb,EA63BuB;EAClC,UAAI9gB,QAAQ,KAAK,IAAjB,EAAuB;EACrB4H,QAAAA,IAAI,CAACyW,KAAL;EACAzR,QAAAA,SAAS,CAAC,wBAAD,CAAT;EACA,cAAM,IAAImU,KAAJ,wBAA+B/gB,QAA/B,CAAN;EACD;;EAED,UAAMkc,UAAU,GAAGtQ,CAAC,CAAChE,IAAI,CAACuU,YAAL,EAAD,CAApB;;EACA,UAAMvS,KAAK,GAAG,SAARA,KAAQ,GAAM;EAClB,YAAI,CAAC5J,QAAQ,CAAC4J,KAAT,IAAkB5J,QAAQ,CAACghB,WAA5B,KAA4CF,QAAQ,KAAK,IAA7D,EAAmE;EACjE5E,UAAAA,UAAU,CAAChN,IAAX,CAAgB,+BAAhB,EAAiDpC,IAAjD,CAAsD9M,QAAQ,CAAC4J,KAAT,IAAkB5J,QAAQ,CAACghB,WAAjF;EACD;EACF,OAJD;;EAKA,UAAM7J,UAAU,GAAG,SAAbA,UAAa,GAAM;EACvB,YAAInX,QAAQ,CAACmX,UAAb,EAAyB;EACvB+E,UAAAA,UAAU,CAAChN,IAAX,CAAgB,iCAAhB,EAAmDpC,IAAnD,CAAwD9M,QAAQ,CAACmX,UAAjE;EACD;EACF,OAJD;;EAKA,UAAM8J,IAAI,GAAG,SAAPA,IAAO,GAAM;EACjB,YAAI,CAACjhB,QAAQ,CAAC8Y,QAAd,EAAwB;EACtB;EACD;;EACD,YAAM6F,cAAc,GAAGzC,UAAU,CAAChN,IAAX,CAAgB,8BAAhB,CAAvB;EACA,YAAMgS,aAAa,GAAG,CACpBrV,IAAI,CAACiK,OAAL,CAAagD,QAAb,CAAsBE,KADF,EAEpBnN,IAAI,CAACiK,OAAL,CAAagD,QAAb,CAAsBK,QAFF,CAAtB;;EAIA,YAAM1L,aAAa,GAAG,SAAhBA,aAAgB,CAAChN,OAAD,EAAa;EACjC,cAAI6U,KAAK,CAACqE,OAAN,CAAclZ,OAAd,CAAJ,EAA4B;EAC1B,iEAAmBA,OAAnB,wCAA4B;EAAA,kBAAjBmZ,IAAiB;EAC1BnM,cAAAA,aAAa,CAACmM,IAAD,CAAb;EACD;;EACD;EACD;;EACD,cAAMgF,QAAQ,oCAAkCne,OAAO,CAAC1B,IAAR,CAAamP,WAAb,EAAhD;EACAyQ,UAAAA,cAAc,CAACvO,MAAf,iBAAmCwO,QAAnC,YAAiDne,OAAO,CAAC1B,IAAzD,aAAqE0B,OAAO,CAAC8U,IAA7E,YAAwF9U,OAAO,CAACA,OAAhG;;EAEA,cAAIygB,aAAa,CAACC,QAAd,CAAuB1gB,OAAO,CAAC1B,IAAR,CAAamP,WAAb,EAAvB,CAAJ,EAAwD;EACtDrC,YAAAA,IAAI,CAACiK,OAAL,CAAa2J,MAAb;EACApiB,YAAAA,UAAU,CAACwO,IAAI,CAACiK,OAAL,CAAasI,SAAd,EAAyB,GAAzB,CAAV;EACD;EACF,SAdD;;EAeA,8DAAsBpe,QAAQ,CAAC8Y,QAA/B,2CAAyC;EAAA,cAA9BrY,OAA8B;;EACvC,cAAI,CAACA,OAAL,EAAc;EACZ;EACD;;EACDoL,UAAAA,IAAI,CAACiK,OAAL,CAAagD,QAAb,CAAsBY,UAAtB,CAAiCjZ,OAAjC;EACAgN,UAAAA,aAAa,CAAChN,OAAD,CAAb;EACD;;EAED,YAAIke,cAAc,CAAC1L,EAAf,CAAkB,UAAlB,CAAJ,EAAmC;EACjC0L,UAAAA,cAAc,CAAChO,SAAf,CAAyBgO,cAAc,CAAC,CAAD,CAAd,CAAkBvJ,YAA3C;EACD;;EAED,YAAI,CAACvJ,IAAI,CAACiK,OAAL,CAAagD,QAAb,CAAsBU,UAAtB,EAAL,EAAyC;EACvC;EACD;;EAED,YAAM4H,YAAY,GAAGlF,UAAU,CAAChN,IAAX,CAAgB,oCAAhB,CAArB;EACAkS,QAAAA,YAAY,CAACvX,IAAb,CAAkBuX,YAAY,CAACxS,IAAb,CAAkB,cAAlB,CAAlB;EAEAwS,QAAAA,YAAY,CACPlS,IADL,CACU,qCADV,EAEKpC,IAFL,CAEUjB,IAAI,CAACiK,OAAL,CAAagD,QAAb,CAAsBW,WAAtB,CAAkC5N,IAAI,CAACiK,OAAL,CAAagD,QAAb,CAAsBK,QAAxD,CAFV;EAKAiI,QAAAA,YAAY,CACPlS,IADL,CACU,kCADV,EAEKpC,IAFL,CAEUjB,IAAI,CAACiK,OAAL,CAAagD,QAAb,CAAsBW,WAAtB,CAAkC5N,IAAI,CAACiK,OAAL,CAAagD,QAAb,CAAsBE,KAAxD,CAFV;EAKAoI,QAAAA,YAAY,CACPlS,IADL,CACU,oCADV,EAEKpC,IAFL,CAEUjB,IAAI,CAACiK,OAAL,CAAagD,QAAb,CAAsBW,WAAtB,CAAkC5N,IAAI,CAACiK,OAAL,CAAagD,QAAb,CAAsBC,OAAxD,CAFV;EAID,OAzDD;;EA2DAnP,MAAAA,KAAK;EACLuN,MAAAA,UAAU;EACV8J,MAAAA,IAAI;;EAEJ,UAAIjhB,QAAQ,CAAC4N,MAAT,KAAoB,IAApB,IAA4B5N,QAAQ,CAAC4W,QAAT,KAAsB,IAAtD,EAA4D;EAC1D/K,QAAAA,IAAI,CAACiK,OAAL,CAAatH,KAAb,CAAmBwL,IAAnB;EACAnO,QAAAA,IAAI,CAACiK,OAAL,CAAahK,WAAb,GAA2B,IAA3B;EACD;EACF,KAl9BY;EAm9BbuV,IAAAA,WAn9Ba,uBAm9BDC,QAn9BC,EAm9BSjhB,IAn9BT,EAm9Be;EAC1B,UAAM+M,GAAG,GAAG,EAAZ;EACA,UAAMmU,IAAI,GAAGD,QAAQ,CAACld,KAAT,CAAe,GAAf,CAAb;EACA,UAAMod,SAAS,GAAGD,IAAI,CAACjd,MAAL,GAAc,CAAhC;EACAid,MAAAA,IAAI,CAACE,MAAL,CAAY,UAACC,WAAD,EAAcC,OAAd,EAAuBza,KAAvB,EAAiC;EAC3C,eAAOwa,WAAW,CAACC,OAAD,CAAX,GAAuBza,KAAK,IAAIsa,SAAT,GAAqBnhB,IAArB,GAA4B,EAA1D;EACD,OAFD,EAEG+M,GAFH;EAGA,aAAOA,GAAP;EACD,KA39BY;EA49BbgR,IAAAA,SA59Ba,uBA49BD;EACVxW,MAAAA,IAAI,CAACC,IAAL,CAAU;EACRgC,QAAAA,IAAI,oJADI;EAERE,QAAAA,KAAK,EAAE,KAFC;EAGRuW,QAAAA,QAAQ,EAAE,oBAAM;EACd,cAAMpE,UAAU,GAAGtQ,CAAC,CAAChE,IAAI,CAACuU,YAAL,EAAD,CAApB;EACAD,UAAAA,UAAU,CAAC,CAAD,CAAV,CAAcpf,KAAd,CAAoB,SAApB,IAAiC,IAAjC;EAEA,cAAM6hB,cAAc,GAAGzC,UAAU,CAAChN,IAAX,CAAgB,8BAAhB,CAAvB;EACA,cAAM0S,eAAe,GAAG1F,UAAU,CAAChN,IAAX,CAAgB,4BAAhB,CAAxB;EACA,cAAM2S,aAAa,GAAGjW,CAAC,CAAC,0BAAD,CAAvB;EACA,cAAMkN,QAAQ,GAAGjN,IAAI,CAACiK,OAAL,CAAagD,QAA9B;EACA,cAAMlP,KAAK,GAAGiY,aAAa,CAACjT,IAAd,CAAmB,uBAAnB,EACTvH,OADS,CACD,YADC,EACayR,QAAQ,CAACW,WAAT,CAAqBX,QAAQ,CAACK,QAA9B,CADb,EAET9R,OAFS,CAED,UAFC,EAEWyR,QAAQ,CAACW,WAAT,CAAqBX,QAAQ,CAACE,KAA9B,CAFX,EAGT3R,OAHS,CAGD,YAHC,EAGayR,QAAQ,CAACW,WAAT,CAAqBX,QAAQ,CAACC,OAA9B,CAHb,CAAd;EAMA6I,UAAAA,eAAe,CAACE,MAAhB,UAA8BlY,KAA9B;EACA,cAAMmY,QAAQ,GAAG,CACflW,IAAI,CAACiK,OAAL,CAAagD,QAAb,CAAsBK,QADP,EAEftN,IAAI,CAACiK,OAAL,CAAagD,QAAb,CAAsBE,KAFP,EAGfnN,IAAI,CAACiK,OAAL,CAAagD,QAAb,CAAsBC,OAHP,CAAjB;;EAMA,cAAI,CAAClN,IAAI,CAACiK,OAAL,CAAagD,QAAb,CAAsBU,UAAtB,EAAL,EAAyC;EACvCoI,YAAAA,eAAe,CAAC5U,IAAhB;EACD;;EAED,gEAAsB8L,QAAQ,CAACzY,IAAT,CAAcrE,GAApC,2CAAyC;EAAA,gBAA9ByE,OAA8B;EACvC,gBAAMme,QAAQ,oCAAkCne,OAAO,CAAC1B,IAAR,CAAamP,WAAb,EAAhD,CADuC;;EAGvC,gBAAI6T,QAAQ,CAACZ,QAAT,CAAkB1gB,OAAO,CAAC1B,IAA1B,CAAJ,EAAqC;EACnC6iB,cAAAA,eAAe,CAACxR,MAAhB,iBACiBwO,QADjB,YAC+Bne,OAAO,CAAC1B,IADvC,aACmD0B,OAAO,CAAC8U,IAD3D,YACsE9U,OAAO,CAACA,OAD9E;EAGD;;EACDke,YAAAA,cAAc,CAACvO,MAAf,iBACiBwO,QADjB,YAC+Bne,OAAO,CAAC1B,IADvC,aACmD0B,OAAO,CAAC8U,IAD3D,YACsE9U,OAAO,CAACA,OAD9E;EAGD;EACF,SAxCO;EAyCRuhB,QAAAA,MAAM,EAAE,gBAAC7X,SAAD,EAAe;EACrB,cAAMwU,cAAc,GAAG/S,CAAC,CAACzB,SAAD,CAAD,CAAa+E,IAAb,CAAkB,8BAAlB,CAAvB;EACAyP,UAAAA,cAAc,CAAChO,SAAf,CAAyBgO,cAAc,CAAC,CAAD,CAAd,CAAkBvJ,YAA3C;EACD;EA5CO,OAAV;EA8CD,KA3gCY;EA4gCbwG,IAAAA,aA5gCa,gCA4gCiH;EAAA,8BAA/GhS,KAA+G;EAAA,UAA/GA,KAA+G,4BAAvG,IAAuG;EAAA,oCAAjGiS,WAAiG;EAAA,UAAjGA,WAAiG,kCAAnF,IAAmF;EAAA,2BAA7EC,EAA6E;EAAA,UAA7EA,EAA6E,yBAAxE,IAAwE;EAAA,4BAAlE9N,GAAkE;EAAA,UAAlEA,GAAkE,0BAA5D,IAA4D;EAAA,qCAAtD+J,YAAsD;EAAA,UAAtDA,YAAsD,mCAAvC,QAAuC;EAAA,sCAA7BD,aAA6B;EAAA,UAA7BA,aAA6B,oCAAb,UAAa;;EAC5H,UAAI,SAASjM,IAAI,CAACiK,OAAL,CAAarL,KAAb,CAAmBmN,QAAnB,CAA4B/N,IAAzC,EAA+C;EAC7C,YAAM0U,GAAG,GAAG3S,CAAC,CAAC,iCAAD,CAAb;EACAC,QAAAA,IAAI,CAACiK,OAAL,CAAarL,KAAb,CAAmBmN,QAAnB,CAA4B/N,IAA5B,GAAmC0U,GAAG,CAAC1U,IAAJ,EAAnC;EACA0U,QAAAA,GAAG,CAAChV,MAAJ;EACD;;EAED,UAAM0Y,WAAW,GAAG,SAAdA,WAAc;EAAA,eAAMra,IAAI,CAACC,IAAL,CAAU;EAClCgC,UAAAA,IAAI,WAASgS,WAAT,8CAD8B;EAElCvR,UAAAA,gBAAgB,EAAE,KAFgB;EAGlC6V,UAAAA,iBAAiB,EAAE,KAHe;EAIlCG,UAAAA,QAAQ,EAAE,oBAAM;EACdzU,YAAAA,IAAI,CAACyD,IAAL,CACI;EACEjQ,cAAAA,MAAM,EAAE,wBADV;EAEEO,cAAAA,WAAW,EAAEzB,KAAK,CAACyB,WAFrB;EAGEC,cAAAA,KAAK,EAAE1B,KAAK,CAAC0B,KAHf;EAIEic,cAAAA,EAAE,EAAFA;EAJF,aADJ,EAOI,UAAS9b,QAAT,EAAmB;EACjB,kBAAI,CAACA,QAAD,IAAa,CAACA,QAAQ,CAACM,OAAvB,IAAkC,CAACN,QAAQ,CAACK,IAA5C,IAAoDL,QAAQ,CAACK,IAAT,CAAciE,MAAd,GAAuB,CAA/E,EAAkF;EAChF;EACD;;EAED,kBAAM4d,CAAC,GAAGpmB,QAAQ,CAAC6G,aAAT,CAAuB,GAAvB,CAAV;EACAuf,cAAAA,CAAC,CAACplB,KAAF,CAAQC,OAAR,GAAkB,MAAlB;EACAmlB,cAAAA,CAAC,CAACvG,IAAF,GAAS3b,QAAQ,CAACK,IAAlB;EACAvE,cAAAA,QAAQ,CAAC4D,IAAT,CAAcwD,WAAd,CAA0Bgf,CAA1B;EACAA,cAAAA,CAAC,CAACC,KAAF;EACArmB,cAAAA,QAAQ,CAAC4D,IAAT,CAAc+F,WAAd,CAA0Byc,CAA1B;EAEAta,cAAAA,IAAI,CAACyW,KAAL;EACD,aApBL;EAsBD;EA3BiC,SAAV,CAAN;EAAA,OAApB;;EA8BAzW,MAAAA,IAAI,CAACmY,KAAL,CAAW;EACT9V,QAAAA,WAAW,EAAE;EACX+V,UAAAA,YAAY,EAAE,sDADH;EAEX9V,UAAAA,aAAa,EAAE,oEAFJ;EAGXkY,UAAAA,OAAO,EAAE;EAHE,SADJ;EAMTnC,QAAAA,cAAc,EAAE;EANP,OAAX,EAQKpY,IARL,CAQU;EACJ5I,QAAAA,IAAI,EAAE,SADF;EAEJ4K,QAAAA,IAAI,EAAEgC,IAAI,CAACiK,OAAL,CAAarL,KAAb,CAAmBmN,QAAnB,CAA4B/N,IAA5B,CAAiCxC,OAAjC,CAAyC,SAAzC,EAAoDuC,KAApD,EAA2DvC,OAA3D,CAAmE,aAAnE,EAAkF,WAAlF,CAFF;EAGJ6Y,QAAAA,gBAAgB,EAAEnI,YAHd;EAIJ3N,QAAAA,iBAAiB,EAAE0N,aAJf;EAKJxN,QAAAA,gBAAgB,EAAE,IALd;EAMJ6V,QAAAA,iBAAiB,EAAE;EANf,OARV,EAgBKpgB,IAhBL,CAgBU,UAACsiB,SAAD,EAAe;EACnB,YAAI,CAACA,SAAD,IAAc,CAACA,SAAS,CAAChgB,KAA7B,EAAoC;EAClC;EACD;;EAED,YAAI2L,GAAG,IAAIA,GAAG,CAAC1J,MAAJ,GAAa,CAAxB,EAA2B;EACzBhH,UAAAA,MAAM,CAACiD,QAAP,CAAgBob,IAAhB,GAAuB3N,GAAvB;EACA;EACD;;EAEDiU,QAAAA,WAAW;EACZ,OA3BL;EA6BD,KA9kCY;EA+kCblG,IAAAA,WA/kCa,yBA+kCC;EACZ,UAAMuG,gBAAgB,GAAG,SAAnBA,gBAAmB,CAACjiB,IAAD,EAAU;EACjCyN,QAAAA,WAAW;;EAEX,YAAIjC,IAAI,CAACiK,OAAL,CAAahK,WAAjB,EAA8B;EAC5B;EACA;EACD;;EAEDD,QAAAA,IAAI,CAACiK,OAAL,CAAatH,KAAb,CAAmBgI,KAAnB;;EAEA,YAAMyH,UAAU,GAAG,SAAbA,UAAa,GAAM;EACvB5O,UAAAA,aAAa,CAACxD,IAAI,CAACiK,OAAL,CAAawB,WAAb,CAAyBC,QAA1B,CAAb;EACA1L,UAAAA,IAAI,CAACiK,OAAL,CAAawB,WAAb,CAAyBC,QAAzB,GAAoC,IAApC;EACD,SAHD;;EAIA,YAAM3J,MAAM,GAAG,SAATA,MAAS,GAAM;EACnB,cAAI/B,IAAI,CAACiK,OAAL,CAAawB,WAAb,CAAyBC,QAAzB,KAAsC,IAA1C,EAAgD;EAC9C;EACD;;EACD1L,UAAAA,IAAI,CAACiK,OAAL,CAAawB,WAAb,CAAyBC,QAAzB,GAAoCpB,WAAW,CAAC,YAAM;EACpD,gBAAI,SAAStK,IAAI,CAACiK,OAAL,CAAahK,WAA1B,EAAuC;EACrCmS,cAAAA,UAAU;EACV;EACD;;EAED,gBAAIpS,IAAI,CAACiK,OAAL,CAAalI,MAAb,CAAoB2N,WAApB,KAAoC,KAAxC,EAA+C;EAC7C;EACD;;EAED1P,YAAAA,IAAI,CAACiK,OAAL,CAAalI,MAAb,CAAoB2N,WAApB,GAAkC,KAAlC;EACAjc,YAAAA,KAAK,CAAIiP,OAAJ,mEAAyEpQ,KAAK,CAACyB,WAA/E,eAAoGzB,KAAK,CAAC0B,KAA1G,CAAL,CACKE,IADL,CACU,UAACmb,GAAD;EAAA,qBAASA,GAAG,CAAChb,IAAJ,EAAT;EAAA,aADV,EAEKH,IAFL,CAEU,UAACmb,GAAD,EAAS;EACbrP,cAAAA,IAAI,CAACiK,OAAL,CAAalI,MAAb,CAAoB2N,WAApB,GAAkC,IAAlC;;EACA,kBAAI,OAAOL,GAAP,KAAe,WAAnB,EAAgC;EAC9B+C,gBAAAA,UAAU;EACX;;EAED,kBAAIpS,IAAI,CAACiK,OAAL,CAAawB,WAAb,CAAyB1N,KAAzB,KAAmCsR,GAAG,CAACgD,kBAA3C,EAA+D;EAC7D;EACD;;EAEDrS,cAAAA,IAAI,CAACiK,OAAL,CAAawB,WAAb,CAAyB1N,KAAzB,GAAiCsR,GAAG,CAACgD,kBAArC;EACA,kBAAMhC,UAAU,GAAGtQ,CAAC,CAAChE,IAAI,CAACuU,YAAL,EAAD,CAApB;EACAD,cAAAA,UAAU,CAAChN,IAAX,CAAgB,+BAAhB,EAAiDpC,IAAjD,CAAsDoO,GAAG,CAACgD,kBAA1D;EACAhC,cAAAA,UAAU,CAAChN,IAAX,CAAgB,iCAAhB,EAAmDpC,IAAnD,CAAwD,GAAxD;EACD,aAhBL,WAiBW,UAACtH,CAAD,EAAO;EACZqG,cAAAA,IAAI,CAACiK,OAAL,CAAalI,MAAb,CAAoB2N,WAApB,GAAkC,IAAlC;EACAhO,cAAAA,kBAAkB,CAAC/H,CAAD,EAAI,EAAJ,EAAQ,yBAAR,CAAlB;EACD,aApBL;EAsBD,WAjC8C,EAiC5C,IAjC4C,CAA/C;EAkCD,SAtCD;;EAwCAmG,QAAAA,SAAS,CAAC2D,IAAV,CACI;EACEjQ,UAAAA,MAAM,EAAE,wBADV;EAEEO,UAAAA,WAAW,EAAEzB,KAAK,CAACyB,WAFrB;EAGEC,UAAAA,KAAK,EAAE1B,KAAK,CAAC0B;EAHf,SADJ,EAMI,UAASG,QAAT,EAAmB;EACjB,cAAI,OAAOA,QAAP,KAAoB,WAAxB,EAAqC;EACnC3C,YAAAA,UAAU,CAAC,YAAW;EACpBilB,cAAAA,gBAAgB,CAAA,CAAhB;EACD,aAFS,EAEPnkB,KAAK,CAACuY,QAFC,CAAV;EAGA;EACD;;EAED7K,UAAAA,IAAI,CAACiK,OAAL,CAAaqI,eAAb,CAA6Bne,QAA7B,EAAuC,IAAvC;;EACA,cAAI,CAAC6L,IAAI,CAACiK,OAAL,CAAawB,WAAb,CAAyBC,QAA9B,EAAwC;EACtC3J,YAAAA,MAAM;EACP;;EAED,cAAI5N,QAAQ,CAAC4N,MAAT,KAAoB,KAAxB,EAA+B;EAC7B0U,YAAAA,gBAAgB,CAAA,CAAhB;EACD,WAFD,MAEO,IAAItiB,QAAQ,CAAC4N,MAAT,KAAoB,IAAxB,EAA8B;EACnChC,YAAAA,CAAC,CAAC,0BAAD,CAAD,CAA8BkB,IAA9B,CAAmC,+BAAnC;EACAjB,YAAAA,IAAI,CAACiK,OAAL,CAAa/W,IAAb,GAAoB,IAApB;;EACA,gBAAI8M,IAAI,CAACiK,OAAL,CAAagD,QAAb,CAAsBU,UAAtB,EAAJ,EAAwC;EACxC;EACE3N,cAAAA,IAAI,CAACiK,OAAL,CAAa4F,YAAb;EACA7P,cAAAA,IAAI,CAACiK,OAAL,CAAasI,SAAb;EACA;EACD;;EACDH,YAAAA,UAAU;EACV,gBAAMsE,UAAU,GAAG3W,CAAC,CAAC,8BAAD,CAAD,CAAkCY,GAAlC,CAAsC,CAAtC,EAAyC1J,SAA5D;EACA,gBAAM+G,IAAI,GAAG,8CAA8C0Y,UAA9C,GAA2D,QAAxE;EACA,gBAAMC,UAAU,GAAG3Y,IAAI,CAACsX,QAAL,CAAc,qCAAd,KAAwDtX,IAAI,CAACsX,QAAL,CAAc,mCAAd,CAAxD,GAA6G,mBAA7G,GAAmI,EAAtJ,CAZmC;EAcnC;EAEA;;EACAvZ,YAAAA,IAAI,CAACC,IAAL,CAAU;EACR5I,cAAAA,IAAI,EAAE,SADE;EAER2K,cAAAA,KAAK,EAAE,UAFC;EAGRC,cAAAA,IAAI,EAAE,sFAAsF2Y,UAAtF,GAAmG,kGAAnG,GAAwM3Y;EAHtM,aAAV,EAjBmC;;EAyBnCgC,YAAAA,IAAI,CAACiK,OAAL,CAAa4F,YAAb;EACD,WA1BM,MA0BA;EACLre,YAAAA,UAAU,CAAC,YAAW;EACpBilB,cAAAA,gBAAgB,CAAA,CAAhB;EACD,aAFS,EAEPnkB,KAAK,CAACuY,QAFC,CAAV;EAGD;EACF,SApDL,EAqDI,MArDJ,EAsDI,KAtDJ,EAuDI,CAvDJ;EAwDI,YAxDJ;EA0DD,OAhHD;;EAkHA,UAAI,CAAC7K,IAAI,CAACiK,OAAL,CAAarL,KAAb,WAA0BZ,IAA/B,EAAqC;EACnC,YAAM8V,MAAM,GAAG/T,CAAC,CAAC,+BAAD,CAAhB,CADmC;;EAInC,YAAM6W,KAAK,GAAG9C,MAAM,CAACzQ,IAAP,CAAY,iEAAZ,CAAd;EACArD,QAAAA,IAAI,CAACiK,OAAL,CAAarL,KAAb,WAA0BuN,iBAA1B,GAA8CyK,KAAK,CAAC5Y,IAAN,EAA9C;EACA4Y,QAAAA,KAAK,CAACvT,IAAN,CAAW,4DAAX,EAAyE3F,MAAzE;EACAkZ,QAAAA,KAAK,CAAC5Y,IAAN,CAAWgC,IAAI,CAACiK,OAAL,CAAarL,KAAb,WAA0BuN,iBAA1B,CAA4C3Q,OAA5C,CAAoD,MAApD,EAA4D,CAA5D,CAAX;EAEAwE,QAAAA,IAAI,CAACiK,OAAL,CAAarL,KAAb,WAA0BZ,IAA1B,GAAiC8V,MAAM,CAAC9V,IAAP,EAAjC;EACAgC,QAAAA,IAAI,CAACiK,OAAL,CAAarL,KAAb,WAA0BmO,aAA1B,GAA0C+G,MAAM,CAAC/Q,IAAP,CAAY,oBAAZ,CAA1C;EACA/C,QAAAA,IAAI,CAACiK,OAAL,CAAarL,KAAb,WAA0BoN,UAA1B,GAAuC8H,MAAM,CAAC/Q,IAAP,CAAY,qBAAZ,CAAvC;EACA/C,QAAAA,IAAI,CAACiK,OAAL,CAAarL,KAAb,WAA0BqN,aAA1B,GAA0C6H,MAAM,CAAC/Q,IAAP,CAAY,wBAAZ,CAA1C;EACA/C,QAAAA,IAAI,CAACiK,OAAL,CAAarL,KAAb,WAA0BsN,YAA1B,GAAyC4H,MAAM,CAAC/Q,IAAP,CAAY,uBAAZ,CAAzC;EACA+Q,QAAAA,MAAM,CAACpW,MAAP;EACD;;EAEDsC,MAAAA,IAAI,CAACiK,OAAL,CAAarL,KAAb,WAA0BpK,IAA1B,CAA+BwY,MAA/B,GAAwC,EAAxC;EACAhN,MAAAA,IAAI,CAACiK,OAAL,CAAarL,KAAb,WAA0BpK,IAA1B,CAA+BgH,OAA/B,GAAyC,EAAzC;EAGAO,MAAAA,IAAI,CACCmY,KADL,CACW;EACL9V,QAAAA,WAAW,EAAE;EACXC,UAAAA,aAAa,EAAE,oEADJ;EAEX8V,UAAAA,YAAY,EAAE,sDAFH;EAGXoC,UAAAA,OAAO,EAAE;EAHE,SADR;EAMLnC,QAAAA,cAAc,EAAE,KANX;;EAAA,OADX,EAUKyC,KAVL,CAUW,CAAC;EACN7Y,QAAAA,IAAI,EAAEgC,IAAI,CAACiK,OAAL,CAAarL,KAAb,WAA0BZ,IAD1B;EAENO,QAAAA,iBAAiB,EAAEyB,IAAI,CAACiK,OAAL,CAAarL,KAAb,WAA0BoN,UAFvC;EAGNvN,QAAAA,gBAAgB,EAAE,KAHZ;EAIN6V,QAAAA,iBAAiB,EAAE,IAJb;EAKNwC,QAAAA,mBAAmB,EAAE,IALf;EAMN5Y,QAAAA,KAAK,EAAE,GAND;EAONuW,QAAAA,QAPM,sBAOK;EACT;EAEA;EACA1U,UAAAA,CAAC,CAAC,uCAAD,CAAD,CAA2CpE,IAA3C;EACAoE,UAAAA,CAAC,CAAC,uCAAD,CAAD,CAA2CyB,IAA3C,CAAgD,UAAhD,EAA4D,KAA5D;EAEAxB,UAAAA,IAAI,CAACiK,OAAL,CAAarL,KAAb,WAA0ByN,eAA1B,GAA4CtM,CAAC,CAAC,uCAAD,CAA7C;EACAC,UAAAA,IAAI,CAACiK,OAAL,CAAarL,KAAb,WAA0B0N,mBAA1B,GAAgDvM,CAAC,CAAC,2CAAD,CAAjD;EACAC,UAAAA,IAAI,CAACiK,OAAL,CAAarL,KAAb,WAA0B8U,kBAA1B,GAA+C3T,CAAC,CAAC,0CAAD,CAAhD;EACD,SAjBK;EAkBNwT,QAAAA,UAlBM,wBAkBO;EACX,cAAM1f,IAAI,GAAG,IAAIub,QAAJ,EAAb;EACAvb,UAAAA,IAAI,CAAC0Q,MAAL,CAAY,aAAZ,EAA2BjS,KAAK,CAACyB,WAAjC;EACAF,UAAAA,IAAI,CAAC0Q,MAAL,CAAY,OAAZ,EAAqBjS,KAAK,CAAC0B,KAA3B;EACAH,UAAAA,IAAI,CAAC0Q,MAAL,CAAY,UAAZ,EAAwBvE,IAAI,CAACiK,OAAL,CAAarL,KAAb,WAA0BpK,IAA1B,CAA+B4X,IAAvD;EAEApM,UAAAA,IAAI,CAACiK,OAAL,CAAarL,KAAb,WAA0BpK,IAA1B,CAA+BwY,MAA/B,CAAsCxV,OAAtC,CAA8C,UAACuW,IAAD,EAAO1S,KAAP,EAAiB;EAC7DxH,YAAAA,IAAI,CAAC0Q,MAAL,aAAsBlJ,KAAtB,QAAgC0S,IAAhC;EACD,WAFD;EAGA/N,UAAAA,IAAI,CAACiK,OAAL,CAAarL,KAAb,WAA0BpK,IAA1B,CAA+BgH,OAA/B,CAAuChE,OAAvC,CAA+C,UAACuW,IAAD,EAAO1S,KAAP,EAAiB;EAC9DxH,YAAAA,IAAI,CAAC0Q,MAAL,cAAuBlJ,KAAvB,QAAiC0S,IAAjC;EACD,WAFD;EAIA,iBAAOta,KAAK,CAAIiP,OAAJ,gDAAwD;EAClE/O,YAAAA,MAAM,EAAE,MAD0D;EAElEE,YAAAA,IAAI,EAAJA;EAFkE,WAAxD,CAAL,CAGJK,IAHI,CAGC4N,iBAHD,EAIF5N,IAJE,CAIG,UAACmb,GAAD;EAAA,mBAASA,GAAG,CAAChb,IAAJ,EAAT;EAAA,WAJH,EAKFH,IALE,CAKG,UAAC8J,IAAD,EAAU;EACd,mBAAOjC,IAAI,CAACgb,eAAL,CAAqB;EAC1B/Y,cAAAA,IAAI,EAAEA,IADoB;EAE1BO,cAAAA,iBAAiB,EAAEyB,IAAI,CAACiK,OAAL,CAAarL,KAAb,WAA0BqN,aAFnB;EAG1BoI,cAAAA,gBAAgB,EAAErU,IAAI,CAACiK,OAAL,CAAarL,KAAb,WAA0BsN,YAHlB;EAI1BzN,cAAAA,gBAAgB,EAAE;EAJQ,aAArB,CAAP;EAMD,WAZE,WAaI,UAAC9E,CAAD;EAAA,mBAAO+H,kBAAkB,CAAC/H,CAAD,EAAI,EAAJ,EAAQ,yBAAR,CAAzB;EAAA,WAbJ,CAAP;EAeD;EA9CK,OAAD,CAVX,EA0DKzF,IA1DL,CA0DU,UAACmb,GAAD,EAAS;EACb,YAAI,CAACA,GAAD,IAAQ,CAACA,GAAG,CAAC7Y,KAAb,IAAsB,CAAC6Y,GAAG,CAAC7Y,KAAJ,CAAU,CAAV,CAAvB,IAAuC6Y,GAAG,CAAC7Y,KAAJ,CAAU,CAAV,MAAiB,IAA5D,EAAkE;EAChE;EACD;;EAEDwJ,QAAAA,IAAI,CAACiK,OAAL,CAAahK,WAAb,GAA2B,KAA3B;EACA,YAAMzL,IAAI,GAAGwL,IAAI,CAACiK,OAAL,CAAarL,KAAb,WAA0BpK,IAAvC;EACAA,QAAAA,IAAI,CAAC,MAAD,CAAJ,GAAewL,IAAI,CAACiK,OAAL,CAAarL,KAAb,WAA0BmO,aAA1B,GAA0CvY,IAAI,CAAC,MAAD,CAA7D;EAEAsL,QAAAA,SAAS,CAAC2D,IAAV,CACI;EACEjQ,UAAAA,MAAM,EAAE,gCADV;EAEEO,UAAAA,WAAW,EAAEzB,KAAK,CAACyB,WAFrB;EAGEC,UAAAA,KAAK,EAAE1B,KAAK,CAAC0B,KAHf;EAIEgjB,UAAAA,eAAe,EAAExiB;EAJnB,SADJ,EAOI,UAASL,QAAT,EAAmB;EACjB,cAAIA,QAAQ,CAACM,OAAb,EAAsB;EACpBuL,YAAAA,IAAI,CAACiK,OAAL,CAAa4B,OAAb,CAAqB;EACnB4H,cAAAA,OAAO,EAAE,mBAAM;EACbzT,gBAAAA,IAAI,CAACiK,OAAL,CAAagD,QAAb,CAAsBe,KAAtB;EACAyI,gBAAAA,gBAAgB,CAAA,CAAhB;EACD;EAJkB,aAArB;EAMD,WAPD,MAOO;EACL/U,YAAAA,kBAAkB,CAACvN,QAAQ,CAACK,IAAV,EAAgB,EAAhB,EAAoB,yBAApB,CAAlB;EACD;EACF,SAlBL,EAmBI,MAnBJ,EAoBI,KApBJ,EAqBI,CArBJ,EAsBI,IAtBJ;EAwBD,OA3FL;EA4FD;EAnzCY,GAAf;EAszCA/C,EAAAA,MAAM,CAAChB,gBAAP,CAAwB,uBAAxB,EAAiD,YAAW;EAC1DgD,IAAAA,KAAK,CAAIiP,OAAJ,oDAA0DiK,IAAI,CAAC+D,MAAL,EAA1D,qBAAuFpe,KAAK,CAACyB,WAA7F,eAAkHzB,KAAK,CAAC0B,KAAxH,wBAAL,CACKE,IADL,CACU4N,iBADV,EAEK5N,IAFL,CAEU,UAACmb,GAAD;EAAA,aAASA,GAAG,CAAChb,IAAJ,EAAT;EAAA,KAFV,EAGKH,IAHL,CAGU,UAACmb,GAAD,EAAS;EACb,UAAMsB,GAAG,GAAG5Q,CAAC,CAAC,uBAAD,CAAb;EACA4Q,MAAAA,GAAG,CAACC,KAAJ;EACAD,MAAAA,GAAG,CAAC3S,IAAJ,CAASqR,GAAT;EACD,KAPL,WAQW,UAAC1V,CAAD;EAAA,aAAO+H,kBAAkB,CAAC/H,CAAD,EAAI,EAAJ,EAAQ,yBAAR,CAAzB;EAAA,KARX;EAUD,GAXD;EAaA,SAAOqG,IAAP;EACD,CA/1Fe,CA+1Fba,MA/1Fa,CAAhB;;EAi2FAA,MAAM,CAAC5Q,QAAD,CAAN,CAAiBgnB,KAAjB,CAAuB,YAAW;EAChCnX,EAAAA,SAAS,CAACzM,IAAV,GADgC;;EAGhC5B,EAAAA,MAAM,CAACqO,SAAP,GAAmBA,SAAnB;EACD,CAJD;EAMA;EACA;EACA;;EACAe,MAAM,CAAC5Q,QAAD,CAAN,CAAiBgnB,KAAjB,CAAuB,UAASlX,CAAT,EAAY;EACjCA,EAAAA,CAAC,CAAC,4BAAD,CAAD,CAAgC8C,EAAhC,CAAmC,OAAnC,EAA4C,UAASlJ,CAAT,EAAY;EACtDoG,IAAAA,CAAC,CAAC,0BAAD,CAAD,CAA8BmJ,WAA9B,CAA0C,mBAA1C;EACAvP,IAAAA,CAAC,CAAC3D,cAAF;EACD,GAHD;EAKA+J,EAAAA,CAAC,CAAC,MAAD,CAAD,CAAU8C,EAAV,CAAa,OAAb,EAAsB,oCAAtB,EAA4D,UAASlJ,CAAT,EAAY;EACtEoG,IAAAA,CAAC,CAAC,0BAAD,CAAD,CAA8BmJ,WAA9B,CAA0C,mBAA1C;EACAvP,IAAAA,CAAC,CAAC3D,cAAF;EACD,GAHD;EAKA+J,EAAAA,CAAC,CAAC,sBAAD,CAAD,CAA0B8C,EAA1B,CAA6B,OAA7B,EAAsC,UAASlJ,CAAT,EAAY;EAChDoG,IAAAA,CAAC,CAAC,0BAAD,CAAD,CAA8BmB,WAA9B,CAA0C,mBAA1C;EACAvH,IAAAA,CAAC,CAAC3D,cAAF;EACD,GAHD;EAKA;EACF;EACA;;EAEE+J,EAAAA,CAAC,CAAC,MAAD,CAAD,CAAU8C,EAAV,CAAa,OAAb,EAAsB,uBAAtB,EAA+C,UAASlJ,CAAT,EAAY;EACzDA,IAAAA,CAAC,CAAC3D,cAAF;EACA+J,IAAAA,CAAC,CAAC,0BAAD,CAAD,CAA8BmB,WAA9B,CAA0C,mBAA1C;EACD,GAHD;;EAKA,WAASgW,eAAT,CAAyBC,MAAzB,EAAiCC,SAAjC,EAAsD;EAAA,QAArBA,SAAqB;EAArBA,MAAAA,SAAqB,GAAT,OAAS;EAAA;;EACpD,QAAMC,OAAO,GAAGF,MAAM,CAACG,IAAP,EAAhB;EACA,QAAMC,KAAK,GAAGxX,CAAC,CAAC,qBAAD,CAAD,CAAyBgE,GAAzB,EAAd;EACA,QAAMyT,gBAAgB,GAAGzX,CAAC,CAAC,gCAAD,CAAD,CAAoCgE,GAApC,EAAzB;EACA,QAAMnP,OAAO,GAAGmL,CAAC,CAAC,2BAAD,CAAD,CAA+BgE,GAA/B,EAAhB;EACA,QAAM0T,MAAM,GAAG1X,CAAC,CAAC,sBAAD,CAAD,CAA0BqH,EAA1B,CAA6B,UAA7B,CAAf;EACA,QAAMsQ,KAAK,GAAG3X,CAAC,CAAC,qBAAD,CAAD,CAAyBqH,EAAzB,CAA4B,UAA5B,CAAd;EAEA+P,IAAAA,MAAM,CAACpU,IAAP,CAAY,UAAZ,EAAwB,IAAxB;EACAsU,IAAAA,OAAO,CAACrW,GAAR,CAAY,YAAZ,EAA0B,SAA1B;EAEAjB,IAAAA,CAAC,CAAC0D,IAAF,CAAO;EACLtB,MAAAA,GAAG,EAAEO,OADA;EAELxP,MAAAA,IAAI,EAAE,MAFD;EAGLgT,MAAAA,QAAQ,EAAE,MAHL;EAILyR,MAAAA,KAAK,EAAE,IAJF;EAK