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

Version Description

  • New: Replace even hardcoded links and server path by using search & replace through all staging site database tables
  • New: New and improved progress bar with elapsed time
  • Fix: Cancel cloning does not clean up unused tables and leads to duplicate tables
  • Tweak: Wordings in rating admin notice
  • Tweak: Better error messages
  • Tweak: Open staging site in same window from login request
  • Fix: Set meta noindex for staging site to make it non indexable for search engines
Download this release

Release Info

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

Code changes from version 2.2.3 to 2.2.4

apps/Backend/Modules/Jobs/Cancel.php CHANGED
@@ -37,7 +37,7 @@ class Cancel extends Job {
37
  $clone["name"] = $this->options->clone;
38
  $clone["number"] = $this->options->cloneNumber;
39
  $clone["path"] = ABSPATH . $this->options->cloneDirectoryName;
40
- $clone["prefix"] = ABSPATH . $this->options->prefix;
41
 
42
  return $clone;
43
  }
37
  $clone["name"] = $this->options->clone;
38
  $clone["number"] = $this->options->cloneNumber;
39
  $clone["path"] = ABSPATH . $this->options->cloneDirectoryName;
40
+ $clone["prefix"] = $this->options->prefix;
41
 
42
  return $clone;
43
  }
apps/Backend/Modules/Jobs/Cloning.php CHANGED
@@ -38,6 +38,7 @@ class Cloning extends Job
38
  $this->options->excludedDirectories = array();
39
  $this->options->extraDirectories = array();
40
  $this->options->excludedFiles = array('.htaccess', '.DS_Store', '.git', '.svn', '.tmp', 'desktop.ini', '.gitignore', '.log');
 
41
 
42
  // Job
43
  $this->options->job = new \stdClass();
@@ -216,7 +217,17 @@ class Cloning extends Job
216
  public function jobDatabase()
217
  {
218
  $database = new Database();
219
- return $this->handleJobResponse($database->start(), "directories");
 
 
 
 
 
 
 
 
 
 
220
  }
221
 
222
  /**
38
  $this->options->excludedDirectories = array();
39
  $this->options->extraDirectories = array();
40
  $this->options->excludedFiles = array('.htaccess', '.DS_Store', '.git', '.svn', '.tmp', 'desktop.ini', '.gitignore', '.log');
41
+ $this->options->currentStep = 0;
42
 
43
  // Job
44
  $this->options->job = new \stdClass();
217
  public function jobDatabase()
218
  {
219
  $database = new Database();
220
+ return $this->handleJobResponse($database->start(), "SearchReplace");
221
+ }
222
+
223
+ /**
224
+ * Search & Replace
225
+ * @return object
226
+ */
227
+ public function jobSearchReplace()
228
+ {
229
+ $searchReplace = new SearchReplace();
230
+ return $this->handleJobResponse($searchReplace->start(), "directories");
231
  }
232
 
233
  /**
apps/Backend/Modules/Jobs/Data.php CHANGED
@@ -49,7 +49,7 @@ class Data extends JobExecutable
49
  */
50
  protected function calculateTotalSteps()
51
  {
52
- $this->options->totalSteps = 8;
53
  }
54
 
55
  /**
49
  */
50
  protected function calculateTotalSteps()
51
  {
52
+ $this->options->totalSteps = 9;
53
  }
54
 
55
  /**
apps/Backend/Modules/Jobs/Directories.php CHANGED
@@ -122,7 +122,6 @@ class Directories extends JobExecutable {
122
  $files = $this->open($this->filename, 'a');
123
 
124
  $excludeWpContent = array(
125
- 'HUGE-FOLDER',
126
  'cache',
127
  'wps-hide-login',
128
  'node_modules',
@@ -411,7 +410,7 @@ class Directories extends JobExecutable {
411
  }
412
 
413
  /**
414
- * Check if directory is excluded from colec
415
  * @param string $directory
416
  * @return bool
417
  */
122
  $files = $this->open($this->filename, 'a');
123
 
124
  $excludeWpContent = array(
 
125
  'cache',
126
  'wps-hide-login',
127
  'node_modules',
410
  }
411
 
412
  /**
413
+ * Check if directory is excluded
414
  * @param string $directory
415
  * @return bool
416
  */
apps/Backend/Modules/Jobs/Finish.php CHANGED
@@ -39,10 +39,12 @@ class Finish extends Job
39
  "url" => get_site_url() . '/' . $this->options->cloneDirectoryName,
40
  "number" => $this->options->cloneNumber,
41
  "version" => \WPStaging\WPStaging::VERSION,
42
- "status" => false,
43
  "prefix" => $this->options->prefix,
44
  "last_msg" => $this->logger->getLastLogMsg(),
45
- "job" => $this->options->currentJob
 
 
46
  );
47
 
48
  //$this->flush();
@@ -104,18 +106,4 @@ class Finish extends Job
104
 
105
  return true;
106
  }
107
-
108
-
109
- /**
110
- * Flush wpdb cache and permalinks
111
- * @global type $wp_rewrite
112
- */
113
- // protected function flush() {
114
- // // flush rewrite rules to prevent 404s
115
- // // and other oddities
116
- // wp_cache_flush();
117
- // global $wp_rewrite;
118
- // $wp_rewrite->init();
119
- // flush_rewrite_rules(true); // true = hard refresh, recreates the .htaccess file
120
- // }
121
  }
39
  "url" => get_site_url() . '/' . $this->options->cloneDirectoryName,
40
  "number" => $this->options->cloneNumber,
41
  "version" => \WPStaging\WPStaging::VERSION,
42
+ "status" => 'finished',
43
  "prefix" => $this->options->prefix,
44
  "last_msg" => $this->logger->getLastLogMsg(),
45
+ "job" => $this->options->currentJob,
46
+ "percentage" => 100
47
+
48
  );
49
 
50
  //$this->flush();
106
 
107
  return true;
108
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109
  }
apps/Backend/Modules/Jobs/JobExecutable.php CHANGED
@@ -40,7 +40,7 @@ abstract class JobExecutable extends Job
40
 
41
  /**
42
  * Prepare Response Array
43
- * @param bool $status
44
  * @param bool $incrementCurrentStep
45
  * @return array
46
  */
@@ -51,8 +51,11 @@ abstract class JobExecutable extends Job
51
  $this->options->currentStep++;
52
  }
53
 
 
 
54
  $percentage = round(($this->options->currentStep / $this->options->totalSteps) * 100);
55
  $percentage = (100 < $percentage) ? 100 : $percentage;
 
56
 
57
  return $this->response = array(
58
  "status" => $status,
@@ -94,6 +97,12 @@ abstract class JobExecutable extends Job
94
  {
95
  break;
96
  }
 
 
 
 
 
 
97
  }
98
  }
99
 
40
 
41
  /**
42
  * Prepare Response Array
43
+ * @param bool $status false if not finished
44
  * @param bool $incrementCurrentStep
45
  * @return array
46
  */
51
  $this->options->currentStep++;
52
  }
53
 
54
+ $percentage = 0;
55
+ if (isset($this->options->currentStep) && isset($this->options->totalSteps) && $this->options->totalSteps > 0){
56
  $percentage = round(($this->options->currentStep / $this->options->totalSteps) * 100);
57
  $percentage = (100 < $percentage) ? 100 : $percentage;
58
+ }
59
 
60
  return $this->response = array(
61
  "status" => $status,
97
  {
98
  break;
99
  }
100
+ // Return after every step to create lower batches
101
+ // This also gets a smoother progress bar and to a less consumptive php cpu load
102
+ // This decrease performance tremendous but also lowers memory consumption
103
+ if ($this->settings->cpuLoad === 'low'){
104
+ return (object) $this->response;
105
+ }
106
  }
107
  }
108
 
apps/Backend/Modules/Jobs/SearchReplace.php ADDED
@@ -0,0 +1,548 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPStaging\Backend\Modules\Jobs;
4
+
5
+ // No Direct Access
6
+ if( !defined( "WPINC" ) ) {
7
+ die;
8
+ }
9
+
10
+ use WPStaging\WPStaging;
11
+ use WPStaging\Utils\Strings;
12
+
13
+ /**
14
+ * Class Database
15
+ * @package WPStaging\Backend\Modules\Jobs
16
+ */
17
+ class SearchReplace extends JobExecutable {
18
+
19
+ /**
20
+ * @var int
21
+ */
22
+ private $total = 0;
23
+
24
+ /**
25
+ * @var \WPDB
26
+ */
27
+ public $db;
28
+
29
+ /**
30
+ * The prefix of the new database tables which are used for the live site after updating tables
31
+ * @var string
32
+ */
33
+ public $tmpPrefix;
34
+
35
+ /**
36
+ * Initialize
37
+ */
38
+ public function initialize() {
39
+ $this->total = count( $this->options->tables );
40
+ $this->db = WPStaging::getInstance()->get( "wpdb" );
41
+ //$this->tmpPrefix = 'wpstgtmp_';
42
+ $this->tmpPrefix = $this->options->prefix;
43
+ //$this->settings->queryLimit = 2;
44
+ }
45
+
46
+ public function start() {
47
+
48
+ $this->run();
49
+
50
+ // Save option, progress
51
+ $this->saveOptions();
52
+
53
+ return ( object ) $this->response;
54
+ }
55
+
56
+ /**
57
+ * Calculate Total Steps in This Job and Assign It to $this->options->totalSteps
58
+ * @return void
59
+ */
60
+ protected function calculateTotalSteps() {
61
+ $this->options->totalSteps = $this->total;
62
+ }
63
+
64
+ /**
65
+ * Execute the Current Step
66
+ * Returns false when over threshold limits are hit or when the job is done, true otherwise
67
+ * @return bool
68
+ */
69
+ protected function execute() {
70
+ // Over limits threshold
71
+ if( $this->isOverThreshold() ) {
72
+ // Prepare response and save current progress
73
+ $this->prepareResponse( false, false );
74
+ $this->saveOptions();
75
+ return false;
76
+ }
77
+
78
+ // No more steps, finished
79
+ if( $this->options->currentStep > $this->total || !isset( $this->options->tables[$this->options->currentStep] ) ) {
80
+ $this->prepareResponse( true, false );
81
+ return false;
82
+ }
83
+
84
+ // Table is excluded
85
+ if( in_array( $this->options->tables[$this->options->currentStep], $this->options->excludedTables ) ) {
86
+ $this->prepareResponse();
87
+ return true;
88
+ }
89
+
90
+ // Search & Replace
91
+ if( !$this->stopExecution() && !$this->updateTable( $this->options->tables[$this->options->currentStep] ) ) {
92
+ // Prepare Response
93
+ $this->prepareResponse( false, false );
94
+
95
+ // Not finished
96
+ return true;
97
+ }
98
+
99
+
100
+ // Prepare Response
101
+ $this->prepareResponse();
102
+
103
+ // Not finished
104
+ return true;
105
+ }
106
+
107
+ private function convertExcludedTables() {
108
+ $tmp = array();
109
+ foreach ( $this->options->excludedTables as $table ) {
110
+ $tmp[] = str_replace( $this->options->prefix, $this->tmpPrefix, $table );
111
+ }
112
+ $this->options->excludedTables = $tmp;
113
+ }
114
+
115
+ /**
116
+ * Stop Execution immediately
117
+ * return mixed bool | json
118
+ */
119
+ private function stopExecution() {
120
+ if( $this->db->prefix == $this->tmpPrefix ) {
121
+ $this->returnException( 'Fatal Error 9: Prefix ' . $this->db->prefix . ' is used for the live site hence it can not be used for the staging site as well. Please ask support@wp-staging.com how to resolve this.' );
122
+ }
123
+ return false;
124
+ }
125
+
126
+ /**
127
+ * Copy Tables
128
+ * @param string $tableName
129
+ * @return bool
130
+ */
131
+ private function updateTable( $tableName ) {
132
+ $strings = new Strings();
133
+ $table = $strings->str_replace_first( $this->db->prefix, '', $tableName );
134
+ $newTableName = $this->tmpPrefix . $table;
135
+
136
+ // Save current job
137
+ $this->setJob( $newTableName );
138
+
139
+ // Beginning of the job
140
+ if( !$this->startJob( $newTableName, $tableName ) ) {
141
+ return true;
142
+ }
143
+ // Copy data
144
+ $this->startReplace( $newTableName );
145
+
146
+ // Finis the step
147
+ return $this->finishStep();
148
+ }
149
+
150
+ /**
151
+ * Start search replace job
152
+ * @param string $new
153
+ * @param string $old
154
+ */
155
+ private function startReplace( $new ) {
156
+ $rows = $this->options->job->start + $this->settings->queryLimit;
157
+ $this->log(
158
+ "DB Processing: {$this->options->job->start} to {$rows} records"
159
+ );
160
+
161
+ // Search & Replace
162
+ $this->searchReplace( $new, $rows, array() );
163
+
164
+ // Set new offset
165
+ $this->options->job->start += $this->settings->queryLimit;
166
+ }
167
+
168
+ /**
169
+ * Returns the number of pages in a table.
170
+ * @access public
171
+ * @return int
172
+ */
173
+ public function get_pages_in_table( $table ) {
174
+ $table = esc_sql( $table );
175
+ $rows = $this->db->get_var( "SELECT COUNT(*) FROM $table" );
176
+ $pages = ceil( $rows / $this->settings->queryLimit );
177
+ return absint( $pages );
178
+ }
179
+
180
+ /**
181
+ * Gets the columns in a table.
182
+ * @access public
183
+ * @param string $table The table to check.
184
+ * @return array
185
+ */
186
+ public function get_columns( $table ) {
187
+ $primary_key = null;
188
+ $columns = array();
189
+ $fields = $this->db->get_results( 'DESCRIBE ' . $table );
190
+ if( is_array( $fields ) ) {
191
+ foreach ( $fields as $column ) {
192
+ $columns[] = $column->Field;
193
+ if( $column->Key == 'PRI' ) {
194
+ $primary_key = $column->Field;
195
+ }
196
+ }
197
+ }
198
+ return array($primary_key, $columns);
199
+ }
200
+
201
+ /**
202
+ * Adapated from interconnect/it's search/replace script, adapted from Better Search Replace
203
+ *
204
+ * Modified to use WordPress wpdb functions instead of PHP's native mysql/pdo functions,
205
+ * and to be compatible with batch processing.
206
+ *
207
+ * @link https://interconnectit.com/products/search-and-replace-for-wordpress-databases/
208
+ *
209
+ * @access public
210
+ * @param string $table The table to run the replacement on.
211
+ * @param int $page The page/block to begin the query on.
212
+ * @param array $args An associative array containing arguements for this run.
213
+ * @return array
214
+ */
215
+ private function searchReplace( $table, $page, $args ) {
216
+
217
+ // Load up the default settings for this chunk.
218
+ $table = esc_sql( $table );
219
+ $current_page = $this->options->job->start + $this->settings->queryLimit;
220
+ $pages = $this->get_pages_in_table( $table );
221
+ $done = false;
222
+
223
+ // Search URL example.com/staging and root path to staging site /var/www/htdocs/staging
224
+ $args['search_for'] = array(
225
+ get_home_url(),
226
+ ABSPATH
227
+ );
228
+ $args['replace_with'] = array(
229
+ rtrim( get_home_url(), '/' ) . '/' . $this->options->cloneDirectoryName,
230
+ rtrim( ABSPATH, '/' ) . '/' . $this->options->cloneDirectoryName
231
+ );
232
+ $args['replace_guids'] = 'off';
233
+ $args['dry_run'] = 'off';
234
+ $args['case_insensitive'] = false;
235
+ $args['replace_guids'] = 'off';
236
+
237
+ // Get a list of columns in this table.
238
+ list( $primary_key, $columns ) = $this->get_columns( $table );
239
+
240
+ $this->log( "DB Processing: Table {$table}" );
241
+
242
+
243
+ // Bail out early if there isn't a primary key.
244
+ if( null === $primary_key ) {
245
+ return false;
246
+ }
247
+
248
+ $current_row = 0;
249
+ $start = $this->options->job->start;
250
+ $end = $this->settings->queryLimit;
251
+
252
+ // Grab the content of the table.
253
+ $data = $this->db->get_results( "SELECT * FROM $table LIMIT $start, $end", ARRAY_A );
254
+
255
+ // Loop through the data.
256
+ foreach ( $data as $row ) {
257
+ $current_row++;
258
+ $update_sql = array();
259
+ $where_sql = array();
260
+ $upd = false;
261
+
262
+ foreach ( $columns as $column ) {
263
+
264
+ $dataRow = $row[$column];
265
+
266
+ if( $column == $primary_key ) {
267
+ $where_sql[] = $column . ' = "' . $this->mysql_escape_mimic( $dataRow ) . '"';
268
+ continue;
269
+ }
270
+
271
+ // Skip GUIDs by default.
272
+ if( 'on' !== $args['replace_guids'] && 'guid' == $column ) {
273
+ continue;
274
+ }
275
+
276
+
277
+ // Check options table
278
+ if( $this->options->prefix . 'options' === $table ) {
279
+
280
+ // Skip certain options
281
+ if( isset( $should_skip ) && true === $should_skip ) {
282
+ $should_skip = false;
283
+ continue;
284
+ }
285
+
286
+ // Skip this row
287
+ if( 'wpstg_existing_clones_beta' === $dataRow ||
288
+ 'wpstg_existing_clones' === $dataRow ||
289
+ 'wpstg_settings' === $dataRow ||
290
+ 'wpstg_license_status' === $dataRow ||
291
+ 'siteurl' === $dataRow ||
292
+ 'home' === $dataRow
293
+ ) {
294
+ $should_skip = true;
295
+ }
296
+ }
297
+
298
+ // Run a search replace on the data that'll respect the serialisation.
299
+ $i = 0;
300
+ foreach ( $args['search_for'] as $replace ) {
301
+ $dataRow = $this->recursive_unserialize_replace( $args['search_for'][$i], $args['replace_with'][$i], $dataRow, false, $args['case_insensitive'] );
302
+ // Do not uncomment line below! Will lead to memory issues and timeouts
303
+ //$this->debugLog('DB Processing: '.$table.' - Replace ' . $args['search_for'][$i] . ' with ' . $args['replace_with'][$i]);
304
+ $i++;
305
+ }
306
+ unset ($replace);
307
+ unset ($i);
308
+
309
+ // Something was changed
310
+ if( $row[$column] != $dataRow ) {
311
+ $update_sql[] = $column . ' = "' . $this->mysql_escape_mimic( $dataRow ) . '"';
312
+ $upd = true;
313
+ }
314
+ }
315
+
316
+ // Determine what to do with updates.
317
+ if( $args['dry_run'] === 'on' ) {
318
+ // Don't do anything if a dry run
319
+ } elseif( $upd && !empty( $where_sql ) ) {
320
+ // If there are changes to make, run the query.
321
+ $sql = 'UPDATE ' . $table . ' SET ' . implode( ', ', $update_sql ) . ' WHERE ' . implode( ' AND ', array_filter( $where_sql ) );
322
+
323
+ $result = $this->db->query( $sql );
324
+
325
+ if( !$result ) {
326
+ //$this->log("Error updating row {$current_row} {$sql}", \WPStaging\Utils\Logger::TYPE_ERROR);
327
+ } else {
328
+ // Do nothing
329
+ }
330
+ }
331
+ } // end row loop
332
+ unset ($row);
333
+
334
+ if( $current_page >= $pages - 1 ) {
335
+ $done = true;
336
+ }
337
+
338
+ // DB Flush
339
+ $this->db->flush();
340
+ return true;
341
+ }
342
+
343
+ /**
344
+ * Adapted from interconnect/it's search/replace script.
345
+ *
346
+ * @link https://interconnectit.com/products/search-and-replace-for-wordpress-databases/
347
+ *
348
+ * Take a serialised array and unserialise it replacing elements as needed and
349
+ * unserialising any subordinate arrays and performing the replace on those too.
350
+ *
351
+ * @access private
352
+ * @param string $from String we're looking to replace.
353
+ * @param string $to What we want it to be replaced with
354
+ * @param array $data Used to pass any subordinate arrays back to in.
355
+ * @param boolean $serialised Does the array passed via $data need serialising.
356
+ * @param sting|boolean $case_insensitive Set to 'on' if we should ignore case, false otherwise.
357
+ *
358
+ * @return string|array The original array with all elements replaced as needed.
359
+ */
360
+ private function recursive_unserialize_replace( $from = '', $to = '', $data = '', $serialised = false, $case_insensitive = false ) {
361
+ try {
362
+
363
+ if( is_string( $data ) && !is_serialized_string( $data ) && ( $unserialized = $this->unserialize( $data ) ) !== false ) {
364
+ $data = $this->recursive_unserialize_replace( $from, $to, $unserialized, true, $case_insensitive );
365
+ } elseif( is_array( $data ) ) {
366
+ $_tmp = array();
367
+ foreach ( $data as $key => $value ) {
368
+ $_tmp[$key] = $this->recursive_unserialize_replace( $from, $to, $value, false, $case_insensitive );
369
+ }
370
+
371
+ $data = $_tmp;
372
+ unset( $_tmp );
373
+ }
374
+
375
+ // Submitted by Tina Matter
376
+ elseif( is_object( $data ) ) {
377
+ // $data_class = get_class( $data );
378
+ $_tmp = $data; // new $data_class( );
379
+ $props = get_object_vars( $data );
380
+ foreach ( $props as $key => $value ) {
381
+ $_tmp->$key = $this->recursive_unserialize_replace( $from, $to, $value, false, $case_insensitive );
382
+ }
383
+
384
+ $data = $_tmp;
385
+ unset( $_tmp );
386
+ } elseif( is_serialized_string( $data ) ) {
387
+ if( $data = $this->unserialize( $data ) !== false ) {
388
+ $data = $this->str_replace( $from, $to, $data, $case_insensitive );
389
+ $data = serialize( $data );
390
+ }
391
+ } else {
392
+ if( is_string( $data ) ) {
393
+ $data = $this->str_replace( $from, $to, $data, $case_insensitive );
394
+ }
395
+ }
396
+
397
+ if( $serialised ) {
398
+ return serialize( $data );
399
+ }
400
+ } catch ( Exception $error ) {
401
+
402
+ }
403
+
404
+ return $data;
405
+ }
406
+
407
+ /**
408
+ * Mimics the mysql_real_escape_string function. Adapted from a post by 'feedr' on php.net.
409
+ * @link http://php.net/manual/en/function.mysql-real-escape-string.php#101248
410
+ * @access public
411
+ * @param string $input The string to escape.
412
+ * @return string
413
+ */
414
+ public function mysql_escape_mimic( $input ) {
415
+ if( is_array( $input ) ) {
416
+ return array_map( __METHOD__, $input );
417
+ }
418
+ if( !empty( $input ) && is_string( $input ) ) {
419
+ return str_replace( array('\\', "\0", "\n", "\r", "'", '"', "\x1a"), array('\\\\', '\\0', '\\n', '\\r', "\\'", '\\"', '\\Z'), $input );
420
+ }
421
+
422
+ return $input;
423
+ }
424
+
425
+ /**
426
+ * Return unserialized object or array
427
+ *
428
+ * @param string $serialized_string Serialized string.
429
+ * @param string $method The name of the caller method.
430
+ *
431
+ * @return mixed, false on failure
432
+ */
433
+ public static function unserialize( $serialized_string ) {
434
+ if( !is_serialized( $serialized_string ) ) {
435
+ return false;
436
+ }
437
+
438
+ $serialized_string = trim( $serialized_string );
439
+ $unserialized_string = @unserialize( $serialized_string );
440
+
441
+ return $unserialized_string;
442
+ }
443
+
444
+ /**
445
+ * Wrapper for str_replace
446
+ *
447
+ * @param string $from
448
+ * @param string $to
449
+ * @param string $data
450
+ * @param string|bool $case_insensitive
451
+ *
452
+ * @return string
453
+ */
454
+ public function str_replace( $from, $to, $data, $case_insensitive = false ) {
455
+ if( 'on' === $case_insensitive ) {
456
+ $data = str_ireplace( $from, $to, $data );
457
+ } else {
458
+ $data = str_replace( $from, $to, $data );
459
+ }
460
+
461
+ return $data;
462
+ }
463
+
464
+ /**
465
+ * Set the job
466
+ * @param string $table
467
+ */
468
+ private function setJob( $table ) {
469
+ if( !empty( $this->options->job->current ) ) {
470
+ return;
471
+ }
472
+
473
+ $this->options->job->current = $table;
474
+ $this->options->job->start = 0;
475
+ }
476
+
477
+ /**
478
+ * Start Job
479
+ * @param string $new
480
+ * @param string $old
481
+ * @return bool
482
+ */
483
+ private function startJob( $new, $old ) {
484
+ if( 0 != $this->options->job->start ) {
485
+ return true;
486
+ }
487
+
488
+ $this->options->job->total = ( int ) $this->db->get_var( "SELECT COUNT(1) FROM {$old}" );
489
+
490
+ if( 0 == $this->options->job->total ) {
491
+ $this->finishStep();
492
+ return false;
493
+ }
494
+
495
+ return true;
496
+ }
497
+
498
+ /**
499
+ * Finish the step
500
+ */
501
+ private function finishStep() {
502
+ // This job is not finished yet
503
+ if( $this->options->job->total > $this->options->job->start ) {
504
+ return false;
505
+ }
506
+
507
+ // Add it to cloned tables listing
508
+ $this->options->clonedTables[] = $this->options->tables[$this->options->currentStep];
509
+
510
+ // Reset job
511
+ $this->options->job = new \stdClass();
512
+
513
+ return true;
514
+ }
515
+
516
+ /**
517
+ * Drop table if necessary
518
+ * @param string $new
519
+ */
520
+ private function dropTable( $new ) {
521
+ $old = $this->db->get_var( $this->db->prepare( "SHOW TABLES LIKE %s", $new ) );
522
+
523
+ if( !$this->shouldDropTable( $new, $old ) ) {
524
+ return;
525
+ }
526
+
527
+ $this->log( "DB Processing: {$new} already exists, dropping it first" );
528
+ $this->db->query( "DROP TABLE {$new}" );
529
+ }
530
+
531
+ /**
532
+ * Check if table needs to be dropped
533
+ * @param string $new
534
+ * @param string $old
535
+ * @return bool
536
+ */
537
+ private function shouldDropTable( $new, $old ) {
538
+ return (
539
+ $old == $new &&
540
+ (
541
+ !isset( $this->options->job->current ) ||
542
+ !isset( $this->options->job->start ) ||
543
+ 0 == $this->options->job->start
544
+ )
545
+ );
546
+ }
547
+
548
+ }
apps/Backend/public/css/wpstg-admin.css CHANGED
@@ -249,7 +249,7 @@ color:#777777;
249
  border: 3px solid #ffffff;
250
  margin-bottom: 5px;
251
  padding: 5px 10px;
252
- width: 300px;
253
  position: relative;
254
  overflow: hidden;
255
  transition: border-color .2s ease-in-out;
@@ -324,13 +324,13 @@ color:#777777;
324
  pointer-events: none;
325
  }
326
 
327
- #wpstg-cancel-cloning {
328
  background: #ff3428;
329
  border-color: #e72f24;
330
  margin-top: 5px;
331
  }
332
 
333
- #wpstg-cancel-cloning.success {
334
  background: #64dd58;
335
  border-color: #54bd4a;
336
  }
@@ -373,14 +373,29 @@ color:#777777;
373
  }
374
 
375
  #wpstg-loader.wpstg-finished {
 
376
  content:"Finished";
377
  background-color:#00c89a;
378
  color:white;
379
  padding:2px;
380
- margin-top:6px;
 
 
 
 
 
 
 
 
 
 
 
 
 
381
  }
382
 
383
  #wpstg-workflow {
 
384
  position: relative;
385
  clear:both;
386
  padding-top:20px;
@@ -430,17 +445,27 @@ color:#777777;
430
  }
431
 
432
  .wpstg-progress-bar {
433
- max-width: 900px;
434
  height: 27px;
435
  padding: 0;
436
  background-color: #d6d8d7;
437
  }
438
 
439
  .wpstg-progress {
440
- background: #1d94cf;
 
 
 
 
 
 
 
 
 
 
441
  width: 0;
442
  height: 100%;
443
- transition: width 1s;
444
  color:white;
445
  line-height:25px;
446
  text-align:center;
@@ -570,6 +595,10 @@ color:#777777;
570
  display: none;
571
  margin-left: 20px;
572
  }
 
 
 
 
573
 
574
  .wpstg-dir a.disabled {
575
  color: #888;
@@ -606,9 +635,8 @@ color:#777777;
606
 
607
  #wpstg-log-details{
608
  height: 300px;
609
- max-width: 700px;
610
  overflow: scroll;
611
- /*max-width: 650px;*/
612
  font-family: monospace;
613
  font-size: 12px;
614
  line-height: 15px;
@@ -644,7 +672,7 @@ color:#777777;
644
 
645
  .wpstg-sysinfo {
646
  width:700px;
647
- height: 500px;
648
  }
649
 
650
  .form-table .col-title label {
@@ -686,7 +714,7 @@ color:#777777;
686
  border-radius:2px;
687
  color:#FFF;
688
  display:inline;
689
- font-size:16px;
690
  width:40px;
691
  padding:4px 8px;
692
  }
@@ -781,4 +809,17 @@ color:#777777;
781
 
782
  .wpstg-bold{
783
  font-weight: 600;
 
 
 
 
 
 
 
 
 
 
 
 
 
784
  }
249
  border: 3px solid #ffffff;
250
  margin-bottom: 5px;
251
  padding: 5px 10px;
252
+ width: 400px;
253
  position: relative;
254
  overflow: hidden;
255
  transition: border-color .2s ease-in-out;
324
  pointer-events: none;
325
  }
326
 
327
+ #wpstg-cancel-cloning, #wpstg-cancel-cloning-update {
328
  background: #ff3428;
329
  border-color: #e72f24;
330
  margin-top: 5px;
331
  }
332
 
333
+ #wpstg-cancel-cloning.success, #wpstg-cancel-cloning.success {
334
  background: #64dd58;
335
  border-color: #54bd4a;
336
  }
373
  }
374
 
375
  #wpstg-loader.wpstg-finished {
376
+ display:block;
377
  content:"Finished";
378
  background-color:#00c89a;
379
  color:white;
380
  padding:2px;
381
+ margin-top:0px;
382
+ }
383
+ .wpstg-loader {
384
+ content: url('../img/loading.gif');
385
+ margin-top:-5px;
386
+ }
387
+
388
+ .wpstg-loader.wpstg-finished {
389
+ content:"Finished";
390
+ background-color:#00c89a;
391
+ color:white;
392
+ padding:2px;
393
+ margin-top:0px;
394
+ max-width:60px;
395
  }
396
 
397
  #wpstg-workflow {
398
+ max-width:650px;
399
  position: relative;
400
  clear:both;
401
  padding-top:20px;
445
  }
446
 
447
  .wpstg-progress-bar {
448
+ /*max-width: 900px;*/
449
  height: 27px;
450
  padding: 0;
451
  background-color: #d6d8d7;
452
  }
453
 
454
  .wpstg-progress {
455
+ float:left;
456
+ background: #3fa5ee;
457
+ width: 0;
458
+ height: 100%;
459
+ transition: width .6s ease;
460
+ color:white;
461
+ line-height:25px;
462
+ text-align:center;
463
+ }
464
+ .wpstg-progress-files {
465
+ background: #16b4f0;
466
  width: 0;
467
  height: 100%;
468
+ transition: width .6s ease;
469
  color:white;
470
  line-height:25px;
471
  text-align:center;
595
  display: none;
596
  margin-left: 20px;
597
  }
598
+ .wpstg-subdir.wpstg-push {
599
+ display: block;
600
+ margin-left: 20px;
601
+ }
602
 
603
  .wpstg-dir a.disabled {
604
  color: #888;
635
 
636
  #wpstg-log-details{
637
  height: 300px;
 
638
  overflow: scroll;
639
+ max-width: 650px;
640
  font-family: monospace;
641
  font-size: 12px;
642
  line-height: 15px;
672
 
673
  .wpstg-sysinfo {
674
  width:700px;
675
+ height: 700px;
676
  }
677
 
678
  .form-table .col-title label {
714
  border-radius:2px;
715
  color:#FFF;
716
  display:inline;
717
+ font-size:12px;
718
  width:40px;
719
  padding:4px 8px;
720
  }
809
 
810
  .wpstg-bold{
811
  font-weight: 600;
812
+ }
813
+
814
+ #wpstg-processing-status {
815
+ margin-top:5px;
816
+ font-size: 13px;
817
+ font-weight: 400px;
818
+ float:left;
819
+ }
820
+ #wpstg-processing-timer {
821
+ margin-top:5px;
822
+ font-size: 13px;
823
+ font-weight: 400px;
824
+ float:right;
825
  }
apps/Backend/public/js/wpstg-admin.js CHANGED
@@ -5,7 +5,10 @@ var WPStaging = (function ($)
5
  var that = {
6
  isCancelled: false,
7
  isFinished: false,
8
- getLogs: false
 
 
 
9
  },
10
  cache = {elements: []},
11
  timeout, ajaxSpinner;
@@ -194,6 +197,7 @@ var WPStaging = (function ($)
194
  .on("click", "#wpstg-start-cloning", function () {
195
  that.isCancelled = false;
196
  that.getLogs = false;
 
197
  })
198
  // Display logs
199
  // .on("click", "#wpstg-show-log-button", function (e) {
@@ -232,8 +236,11 @@ var WPStaging = (function ($)
232
  $this.prop("disabled", true);
233
 
234
  that.isCancelled = true;
 
235
 
236
- $("#wpstg-cloning-result").text("Please wait...this can take up a while.");
 
 
237
  $("#wpstg-loader, #wpstg-show-log-button").hide();
238
 
239
  $this.parent().append(ajaxSpinner);
@@ -327,7 +334,11 @@ var WPStaging = (function ($)
327
  {
328
  if (response.length < 1)
329
  {
330
- showError("Something went wrong, please try again");
 
 
 
 
331
  }
332
 
333
  $workFlow.removeClass("loading").html(response);
@@ -379,9 +390,9 @@ var WPStaging = (function ($)
379
 
380
 
381
  showError(
382
- "Fatal Unknown Error. Go to WP Staging > Settings and lower 'File Copy Limit' and DB query limit" +
383
- "Than try again. If this does not help, " +
384
- "<a href='https://wpquads.com/support/' target='_blank'>open a support ticket</a> "
385
  );
386
  },
387
  success: function (data) {
@@ -392,10 +403,19 @@ var WPStaging = (function ($)
392
  },
393
  statusCode: {
394
  404: function (data) {
395
- showError("Something went wrong; can't find ajax request URL!");
 
 
 
 
 
396
  },
397
  500: function () {
398
- showError("Something went wrong; internal server error while processing the request!");
 
 
 
 
399
  }
400
  }
401
  });
@@ -445,7 +465,11 @@ var WPStaging = (function ($)
445
 
446
  if (response.length < 1)
447
  {
448
- showError("Something went wrong, please try again");
 
 
 
 
449
  }
450
 
451
  // Styling of elements
@@ -458,7 +482,7 @@ var WPStaging = (function ($)
458
 
459
  // Start cloning
460
  that.startCloning();
461
- //processing();
462
  },
463
  "HTML"
464
  );
@@ -530,10 +554,10 @@ var WPStaging = (function ($)
530
 
531
  $(".wpstg-dir input:not(:checked)").each(function () {
532
  var $this = $(this);
533
- if (!$this.parent(".wpstg-dir").parents(".wpstg-dir").children(".wpstg-expand-dirs").hasClass("disabled"))
534
- {
535
  excludedDirectories.push($this.val());
536
- }
537
  });
538
 
539
  return excludedDirectories;
@@ -572,7 +596,7 @@ var WPStaging = (function ($)
572
  }
573
 
574
  that.data.cloneID = $("#wpstg-new-clone-id").val() || new Date().getTime().toString();
575
- // Remove this to keep &_POST[] small otherwise mod_security will throw error 404
576
  //that.data.excludedTables = getExcludedTables();
577
  that.data.includedTables = getIncludedTables();
578
  that.data.includedDirectories = getIncludedDirectories();
@@ -600,7 +624,11 @@ var WPStaging = (function ($)
600
 
601
  if (response.length < 1)
602
  {
603
- showError("Something went wrong, please try again");
 
 
 
 
604
  }
605
 
606
  var $currentStep = cache.get(".wpstg-current-step");
@@ -618,22 +646,6 @@ var WPStaging = (function ($)
618
  */
619
  var tabs = function ()
620
  {
621
- // var $loaded = false;
622
- //
623
- // if ($loaded === false) {
624
- // console.log('select default tables');
625
- //
626
- // $(".wpstg-db-table input").each(function () {
627
- //
628
- // $loaded = true;
629
- //
630
- // if ($(this).attr('name').match("^" + wpstg.tblprefix)) {
631
- // $(this).prop("checked", true);
632
- // } else {
633
- // $(this).prop("checked", false);
634
- // }
635
- // });
636
- // }
637
 
638
  cache.get("#wpstg-workflow").on("click", ".wpstg-tab-header", function (e) {
639
  e.preventDefault();
@@ -679,7 +691,11 @@ var WPStaging = (function ($)
679
  if (response) {
680
  // Error
681
  if ("undefined" !== typeof response.error && "undefined" !== typeof response.message) {
682
- showError(response.message);
 
 
 
 
683
  console.log(response.message);
684
  }
685
 
@@ -687,6 +703,7 @@ var WPStaging = (function ($)
687
  if ("undefined" !== typeof response.delete && response.delete === 'finished') {
688
 
689
  cache.get("#wpstg-removing-clone").removeClass("loading").html('');
 
690
  $(".wpstg-clone#" + clone).remove();
691
 
692
  if ($(".wpstg-clone").length < 1)
@@ -714,6 +731,10 @@ var WPStaging = (function ($)
714
  */
715
  var cancelCloning = function ()
716
  {
 
 
 
 
717
  if (true === that.isFinished)
718
  {
719
  return true;
@@ -730,6 +751,7 @@ var WPStaging = (function ($)
730
 
731
 
732
  if (response && "undefined" !== typeof (response.delete) && response.delete === "finished") {
 
733
  // Load overview
734
  loadOverview();
735
  return;
@@ -757,7 +779,6 @@ var WPStaging = (function ($)
757
  return true;
758
  }
759
 
760
- //alert(that.data.cloneID);
761
  ajax(
762
  {
763
  action: "wpstg_cancel_update",
@@ -859,6 +880,43 @@ var WPStaging = (function ($)
859
  }
860
 
861
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
862
 
863
  /**
864
  * Start Cloning Process
@@ -877,261 +935,141 @@ var WPStaging = (function ($)
877
  // Start the process
878
  start();
879
 
 
880
  // Functions
881
  // Start
882
  function start()
883
  {
 
884
  console.log("Starting cloning process...");
885
 
886
  cache.get("#wpstg-loader").show();
887
 
888
  // Clone Database
889
  setTimeout(function () {
890
- cloneDatabase();
 
891
  }, wpstg.cpuLoad);
892
- }
893
 
894
- // Step 1: Clone Database
895
- function cloneDatabase()
896
- {
897
- if (true === that.isCancelled)
898
- {
899
- return false;
900
- }
901
 
902
- if (true === that.getLogs)
903
- {
904
- getLogs();
905
  }
906
 
907
- setTimeout(
908
- function () {
909
- ajax(
910
- {
911
- action: "wpstg_clone_database",
912
- nonce: wpstg.nonce
913
- },
914
- function (response) {
915
- // Add percentage
916
- if ("undefined" !== typeof (response.percentage))
917
- {
918
- cache.get("#wpstg-db-progress").width(response.percentage + '%');
919
- }
920
- // Add Log
921
- if ("undefined" !== typeof (response.last_msg))
922
- {
923
- getLogs(response.last_msg);
924
- }
925
 
926
- // Continue clone DB
927
- if (false === response.status)
928
- {
929
- setTimeout(function () {
930
- cloneDatabase();
931
- }, wpstg.cpuLoad);
932
- }
933
- // Next Step
934
- else if (true === response.status)
935
- {
936
- //console.log('prepareDirectories ' + response.status);
937
- setTimeout(function () {
938
- prepareDirectories();
939
- }, wpstg.cpuLoad);
940
- }
941
- }
942
- );
943
- },
944
- 500
945
- );
946
- }
947
 
948
- // Step 2: Prepare Directories
949
- function prepareDirectories()
950
- {
 
 
 
951
  if (true === that.isCancelled)
952
  {
953
  return false;
954
  }
955
 
956
- if (true === that.getLogs)
957
- {
958
- getLogs();
959
- }
960
 
961
- setTimeout(
962
- function () {
963
- ajax(
964
- {
965
- action: "wpstg_clone_prepare_directories",
966
- nonce: wpstg.nonce
967
- },
968
- function (response) {
969
 
970
- // Error
971
- if ("undefined" !== typeof response.error && "undefined" !== typeof response.message) {
972
- showError(response.message);
973
- console.log(response.message);
974
- }
975
 
976
- // Add percentage
977
- if ("undefined" !== typeof (response.percentage))
978
- {
979
- cache.get("#wpstg-directories-progress").width(response.percentage + '%');
980
- }
981
 
982
- // Add Log
983
- if ("undefined" !== typeof (response.last_msg))
984
- {
985
- getLogs(response.last_msg);
986
- }
987
 
988
- if (false === response.status)
989
- {
990
- setTimeout(function () {
991
- prepareDirectories();
992
- }, wpstg.cpuLoad);
993
- }
994
- else if (true === response.status)
995
  {
996
- console.log('prepareDirectories' + response.status);
997
- cloneFiles();
998
- }
999
- }
1000
- );
 
 
1001
  },
1002
- 500
1003
- );
1004
- }
1005
-
1006
- // Step 3: Clone Files
1007
- function cloneFiles()
1008
  {
1009
- if (true === that.isCancelled)
 
1010
  {
1011
- return false;
 
 
 
 
 
 
 
 
1012
  }
1013
 
1014
- if (true === that.getLogs)
1015
- {
1016
- getLogs();
 
 
 
 
 
 
 
1017
  }
1018
 
1019
- ajax(
 
1020
  {
1021
- action: "wpstg_clone_files",
1022
- nonce: wpstg.nonce
1023
- },
1024
- function (response) {
1025
- // Add percentage
1026
- if ("undefined" !== typeof (response.percentage))
1027
- {
1028
- cache.get("#wpstg-files-progress").width(response.percentage + '%');
1029
- }
1030
-
1031
- // Add Log
1032
- if ("undefined" !== typeof (response.last_msg))
1033
- {
1034
  getLogs(response.last_msg);
1035
  }
1036
-
1037
  if (false === response.status)
1038
  {
 
 
1039
  setTimeout(function () {
1040
- cloneFiles();
1041
- }, wpstg.cpuLoad);
1042
- }
1043
- else if (true === response.status)
1044
- {
1045
- setTimeout(function () {
1046
- replaceData();
1047
  }, wpstg.cpuLoad);
1048
- }
1049
- }
1050
- );
1051
- }
1052
-
1053
- // Step 4: Replace Data
1054
- function replaceData()
1055
- {
1056
- if (true === that.isCancelled)
1057
- {
1058
- return false;
1059
- }
1060
-
1061
- if (true === that.getLogs)
1062
- {
1063
- console.log('getLogs1')
1064
- getLogs();
1065
- }
1066
 
1067
- ajax(
1068
- {
1069
- action: "wpstg_clone_replace_data",
1070
- nonce: wpstg.nonce
 
 
 
1071
  },
1072
- function (response) {
1073
- // Add percentage
1074
- if ("undefined" !== typeof (response.percentage))
1075
- {
1076
- cache.get("#wpstg-links-progress").width(response.percentage + '%');
1077
- }
1078
-
1079
- // Add Log
1080
- if ("undefined" !== typeof (response.last_msg))
1081
- {
1082
- console.log('get Logs');
1083
- getLogs(response.last_msg);
1084
- }
1085
-
1086
- if (false === response.status)
1087
- {
1088
- setTimeout(function () {
1089
- console.log('replace data');
1090
- replaceData();
1091
- }, wpstg.cpuLoad);
1092
- }
1093
- else if (true === response.status)
1094
- {
1095
- console.log('finish');
1096
- finish();
1097
- }
1098
- }
1099
  );
1100
- }
1101
 
1102
  // Finish
1103
- function finish()
1104
  {
 
1105
  if (true === that.getLogs)
1106
  {
1107
  getLogs();
1108
  }
1109
 
1110
- if (true === that.isCancelled || true === that.isFinished)
1111
- {
1112
- cache.get("#wpstg-loader").hide();
1113
- return false;
1114
- }
1115
 
1116
- ajax(
1117
- {
1118
- action: "wpstg_clone_finish",
1119
- nonce: wpstg.nonce
1120
- },
1121
- function (response)
1122
- {
1123
- // Invalid response
1124
- if ("object" !== typeof (response))
1125
- {
1126
- showError(
1127
- "Couldn't finish the cloning process properly. " +
1128
- "Your clone has been copied but failed to do clean up and " +
1129
- "saving its records to the database." +
1130
- "Please contact support and provide your logs."
1131
- );
1132
 
1133
- return;
1134
- }
 
 
 
 
 
 
1135
 
1136
  // Add Log
1137
  if ("undefined" !== typeof (response.last_msg))
@@ -1141,27 +1079,350 @@ var WPStaging = (function ($)
1141
 
1142
  console.log("Cloning process finished");
1143
 
1144
- var $link1 = cache.get("#wpstg-clone-url-1");
1145
- var $link = cache.get("#wpstg-clone-url");
 
1146
 
1147
  cache.get("#wpstg_staging_name").html(that.data.cloneID);
1148
  cache.get("#wpstg-finished-result").show();
1149
- cache.get("#wpstg-cancel-cloning").prop("disabled", true);
 
1150
  cache.get("#wpstg-cancel-cloning-update").prop("disabled", true);
1151
- // $link1.attr("href", $link1.attr("href") + '/' + response.directoryName);
1152
- // $link1.append('/' + response.directoryName);
1153
- // $link.attr("href", $link.attr("href") + '/' + response.directoryName);
1154
  $link1.attr("href", response.url);
 
1155
  $link.attr("href", response.url);
 
1156
  cache.get("#wpstg-remove-clone").data("clone", that.data.cloneID);
1157
 
1158
  // Finished
1159
  that.isFinished = true;
 
 
 
 
 
 
 
1160
 
1161
- finish();
1162
  }
1163
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1164
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1165
  });
1166
 
1167
 
5
  var that = {
6
  isCancelled: false,
7
  isFinished: false,
8
+ getLogs: false,
9
+ time: 1,
10
+ executionTime: false,
11
+ progressBar: 0
12
  },
13
  cache = {elements: []},
14
  timeout, ajaxSpinner;
197
  .on("click", "#wpstg-start-cloning", function () {
198
  that.isCancelled = false;
199
  that.getLogs = false;
200
+ that.progressBar = 0;
201
  })
202
  // Display logs
203
  // .on("click", "#wpstg-show-log-button", function (e) {
236
  $this.prop("disabled", true);
237
 
238
  that.isCancelled = true;
239
+ that.progressBar = 0;
240
 
241
+
242
+ //$("#wpstg-cloning-result").text("Please wait...this can take up a while.");
243
+ $("#wpstg-processing-status").text("Please wait...this can take up a while.");
244
  $("#wpstg-loader, #wpstg-show-log-button").hide();
245
 
246
  $this.parent().append(ajaxSpinner);
334
  {
335
  if (response.length < 1)
336
  {
337
+ showError(
338
+ "Something went wrong! Error: No response. Go to WP Staging > Settings and lower 'File Copy Limit' and 'DB Query Limit'. Also set 'CPU Load Priority to low.'" +
339
+ "Than try again. If that does not help, " +
340
+ "<a href='https://wp-staging.com/support/' target='_blank'>open a support ticket</a> "
341
+ );
342
  }
343
 
344
  $workFlow.removeClass("loading").html(response);
390
 
391
 
392
  showError(
393
+ "Fatal Unknown Error. Go to WP Staging > Settings and lower 'File Copy Limit' and 'DB Query Limit'. Also set 'CPU Load Priority to low.'" +
394
+ "Than try again. If that does not help, " +
395
+ "<a href='https://wp-staging.com/support/' target='_blank'>open a support ticket</a> "
396
  );
397
  },
398
  success: function (data) {
403
  },
404
  statusCode: {
405
  404: function (data) {
406
+ showError(
407
+ "Something went wrong; can't find ajax request URL! Go to WP Staging > Settings and lower 'File Copy Limit' and 'DB Query Limit'. Also set 'CPU Load Priority to low.'" +
408
+ "Than try again. If that does not help, " +
409
+ "<a href='https://wp-staging.com/support/' target='_blank'>open a support ticket</a> "
410
+ );
411
+ // Try again after 10 seconds
412
  },
413
  500: function () {
414
+ showError(
415
+ "Something went wrong! Internal server error while processing the request! Go to WP Staging > Settings and lower 'File Copy Limit' and 'DB Query Limit'. Also set 'CPU Load Priority to low.'" +
416
+ "Than try again. If that does not help, " +
417
+ "<a href='https://wp-staging.com/support/' target='_blank'>open a support ticket</a> "
418
+ );
419
  }
420
  }
421
  });
465
 
466
  if (response.length < 1)
467
  {
468
+ showError(
469
+ "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.'" +
470
+ "Than try again. If that does not help, " +
471
+ "<a href='https://wp-staging.com/support/' target='_blank'>open a support ticket</a> "
472
+ );
473
  }
474
 
475
  // Styling of elements
482
 
483
  // Start cloning
484
  that.startCloning();
485
+
486
  },
487
  "HTML"
488
  );
554
 
555
  $(".wpstg-dir input:not(:checked)").each(function () {
556
  var $this = $(this);
557
+ //if (!$this.parent(".wpstg-dir").parents(".wpstg-dir").children(".wpstg-expand-dirs").hasClass("disabled"))
558
+ //{
559
  excludedDirectories.push($this.val());
560
+ //}
561
  });
562
 
563
  return excludedDirectories;
596
  }
597
 
598
  that.data.cloneID = $("#wpstg-new-clone-id").val() || new Date().getTime().toString();
599
+ // Remove this to keep &_POST[] small otherwise mod_security will throw erro 404
600
  //that.data.excludedTables = getExcludedTables();
601
  that.data.includedTables = getIncludedTables();
602
  that.data.includedDirectories = getIncludedDirectories();
624
 
625
  if (response.length < 1)
626
  {
627
+ showError(
628
+ "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.'" +
629
+ "Than try again. If that does not help, " +
630
+ "<a href='https://wp-staging.com/support/' target='_blank'>open a support ticket</a> "
631
+ );
632
  }
633
 
634
  var $currentStep = cache.get(".wpstg-current-step");
646
  */
647
  var tabs = function ()
648
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
649
 
650
  cache.get("#wpstg-workflow").on("click", ".wpstg-tab-header", function (e) {
651
  e.preventDefault();
691
  if (response) {
692
  // Error
693
  if ("undefined" !== typeof response.error && "undefined" !== typeof response.message) {
694
+ showError(
695
+ "Something went wrong! Error:" +response.message+ ". Go to WP Staging > Settings and lower 'File Copy Limit' and 'DB Query Limit'. Also set 'CPU Load Priority to low.'" +
696
+ "Than try again. If that does not help, " +
697
+ "<a href='https://wp-staging.com/support/' target='_blank'>open a support ticket</a> "
698
+ );
699
  console.log(response.message);
700
  }
701
 
703
  if ("undefined" !== typeof response.delete && response.delete === 'finished') {
704
 
705
  cache.get("#wpstg-removing-clone").removeClass("loading").html('');
706
+
707
  $(".wpstg-clone#" + clone).remove();
708
 
709
  if ($(".wpstg-clone").length < 1)
731
  */
732
  var cancelCloning = function ()
733
  {
734
+
735
+ that.timer('stop');
736
+
737
+
738
  if (true === that.isFinished)
739
  {
740
  return true;
751
 
752
 
753
  if (response && "undefined" !== typeof (response.delete) && response.delete === "finished") {
754
+ cache.get("#wpstg-loader").hide();
755
  // Load overview
756
  loadOverview();
757
  return;
779
  return true;
780
  }
781
 
 
782
  ajax(
783
  {
784
  action: "wpstg_cancel_update",
880
  }
881
 
882
 
883
+ /**
884
+ * Count up processing execution time
885
+ * @param string status
886
+ * @returns html
887
+ */
888
+ that.timer = function (status) {
889
+
890
+ if (status === 'stop') {
891
+ var time = that.time;
892
+ that.time = 1;
893
+ clearInterval(that.executionTime);
894
+ return that.convertSeconds(time);
895
+ }
896
+
897
+
898
+ that.executionTime = setInterval(function () {
899
+ if (null !== document.getElementById('wpstg-processing-timer')) {
900
+ document.getElementById('wpstg-processing-timer').innerHTML = 'Elapsed Time: ' + that.convertSeconds(that.time);
901
+ }
902
+ that.time++;
903
+ if (status === 'stop') {
904
+ that.time = 1;
905
+ clearInterval(that.executionTime);
906
+ }
907
+ }, 1000);
908
+ };
909
+ /**
910
+ * Convert seconds to hourly format
911
+ * @param int seconds
912
+ * @returns string
913
+ */
914
+ that.convertSeconds = function (seconds) {
915
+ var date = new Date(null);
916
+ date.setSeconds(seconds); // specify value for SECONDS here
917
+ return date.toISOString().substr(11, 8);
918
+ }
919
+
920
 
921
  /**
922
  * Start Cloning Process
935
  // Start the process
936
  start();
937
 
938
+
939
  // Functions
940
  // Start
941
  function start()
942
  {
943
+
944
  console.log("Starting cloning process...");
945
 
946
  cache.get("#wpstg-loader").show();
947
 
948
  // Clone Database
949
  setTimeout(function () {
950
+ //cloneDatabase();
951
+ processing();
952
  }, wpstg.cpuLoad);
 
953
 
954
+ that.timer('start');
 
 
 
 
 
 
955
 
 
 
 
956
  }
957
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
958
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
959
 
960
+ /**
961
+ * Start ajax processing
962
+ * @returns string
963
+ */
964
+ var processing = function () {
965
+
966
  if (true === that.isCancelled)
967
  {
968
  return false;
969
  }
970
 
 
 
 
 
971
 
 
 
 
 
 
 
 
 
972
 
973
+ //console.log("Start ajax processing");
 
 
 
 
974
 
975
+ // Show loader gif
976
+ cache.get("#wpstg-loader").show();
977
+ cache.get(".wpstg-loader").show();
 
 
978
 
979
+ // Show logging window
980
+ cache.get('#wpstg-log-details').show();
 
 
 
981
 
982
+ WPStaging.ajax(
 
 
 
 
 
 
983
  {
984
+ action: "wpstg_clone_database",
985
+ nonce: wpstg.nonce,
986
+ //clone: cloneID,
987
+ excludedTables: getExcludedTables(),
988
+ includedDirectories: getIncludedDirectories(),
989
+ excludedDirectories: getExcludedDirectories(),
990
+ extraDirectories: getIncludedExtraDirectories()
991
  },
992
+ function (response)
 
 
 
 
 
993
  {
994
+ // Undefined Error
995
+ if (false === response)
996
  {
997
+ showError("Unknown Error, please try again");
998
+ showError(
999
+ "Something went wrong! Error: No response. Go to WP Staging > Settings and lower 'File Copy Limit' and 'DB Query Limit'. Also set 'CPU Load Priority to low.'" +
1000
+ "Than try again. If that does not help, " +
1001
+ "<a href='https://wp-staging.com/support/' target='_blank'>open a support ticket</a> "
1002
+ );
1003
+ cache.get("#wpstg-loader").hide();
1004
+ cache.get(".wpstg-loader").hide();
1005
+ return;
1006
  }
1007
 
1008
+ // Throw Error
1009
+ if ("undefined" !== typeof (response.error) && response.error) {
1010
+ console.log(response.message);
1011
+ showError(
1012
+ "Something went wrong! Error:" +response.message+ ". Go to WP Staging > Settings and lower 'File Copy Limit' and 'DB Query Limit'. Also set 'CPU Load Priority to low.'" +
1013
+ "Than try again. If that does not help, " +
1014
+ "<a href='https://wp-staging.com/support/' target='_blank'>open a support ticket</a> "
1015
+ );
1016
+
1017
+ return;
1018
  }
1019
 
1020
+ // Add Log messages
1021
+ if ("undefined" !== typeof (response.last_msg) && response.last_msg)
1022
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
1023
  getLogs(response.last_msg);
1024
  }
1025
+ // Continue processing
1026
  if (false === response.status)
1027
  {
1028
+ progressBar(response);
1029
+
1030
  setTimeout(function () {
1031
+ //console.log('continue processing');
1032
+ cache.get("#wpstg-loader").show();
1033
+ processing();
 
 
 
 
1034
  }, wpstg.cpuLoad);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1035
 
1036
+ } else if (true === response.status && 'finished' !== response.status) {
1037
+ //console.log('Processing...');
1038
+ progressBar(response, true);
1039
+ processing();
1040
+ } else if ('finished' === response.status || ("undefined" !== typeof (response.job_done) && response.job_done)) {
1041
+ finish(response);
1042
+ };
1043
  },
1044
+ "json",
1045
+ false
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1046
  );
1047
+ };
1048
 
1049
  // Finish
1050
+ function finish(response)
1051
  {
1052
+
1053
  if (true === that.getLogs)
1054
  {
1055
  getLogs();
1056
  }
1057
 
1058
+ // var response = {
1059
+ // percentage: 100,
1060
+ // job: 'finish'
1061
+ // }
1062
+ progressBar(response);
1063
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1064
 
1065
+ // if (true === that.isCancelled || true === that.isFinished)
1066
+ // {
1067
+ // cache.get("#wpstg-loader").hide();
1068
+ // cache.get("#wpstg-processing-header").html('Processing Complete');
1069
+ // $("#wpstg-processing-status").text("Succesfully finished");
1070
+ // that.timer('stop');
1071
+ // return false;
1072
+ // }
1073
 
1074
  // Add Log
1075
  if ("undefined" !== typeof (response.last_msg))
1079
 
1080
  console.log("Cloning process finished");
1081
 
1082
+ cache.get("#wpstg-loader").hide();
1083
+ cache.get("#wpstg-processing-header").html('Processing Complete');
1084
+ $("#wpstg-processing-status").text("Succesfully finished");
1085
 
1086
  cache.get("#wpstg_staging_name").html(that.data.cloneID);
1087
  cache.get("#wpstg-finished-result").show();
1088
+ //cache.get("#wpstg-cancel-cloning").prop("disabled", true);
1089
+ cache.get("#wpstg-cancel-cloning").hide();
1090
  cache.get("#wpstg-cancel-cloning-update").prop("disabled", true);
1091
+
1092
+ var $link1 = cache.get("#wpstg-clone-url-1");
1093
+ var $link = cache.get("#wpstg-clone-url");
1094
  $link1.attr("href", response.url);
1095
+ $link1.html(response.url);
1096
  $link.attr("href", response.url);
1097
+
1098
  cache.get("#wpstg-remove-clone").data("clone", that.data.cloneID);
1099
 
1100
  // Finished
1101
  that.isFinished = true;
1102
+ that.timer('stop');
1103
+
1104
+
1105
+ cache.get("#wpstg-loader").hide();
1106
+ cache.get("#wpstg-processing-header").html('Processing Complete');
1107
+
1108
+ return false;
1109
 
 
1110
  }
1111
+ /**
1112
+ * Add percentage progress bar
1113
+ * @param object response
1114
+ * @returns {Boolean}
1115
+ */
1116
+ var progressBar = function (response, restart) {
1117
+ if ("undefined" === typeof (response.percentage))
1118
+ return false;
1119
+
1120
+ // //if (restart){
1121
+ // cache.get("#wpstg-db-progress").width('1%');
1122
+ // //}
1123
+
1124
+ if (response.job === 'database') {
1125
+ cache.get("#wpstg-progress-db").width(response.percentage * 0.2 + '%').html(response.percentage + '%');
1126
+ cache.get("#wpstg-processing-status").html(response.percentage.toFixed(0) + '%' + ' - Step 1 of 4 Cloning Database Tables...');
1127
+ }
1128
+
1129
+ if (response.job === 'SearchReplace') {
1130
+ cache.get("#wpstg-progress-db").css('background-color', '#3bc36b');
1131
+ cache.get("#wpstg-progress-db").html('1. Database');
1132
+ cache.get("#wpstg-progress-sr").width(response.percentage * 0.1 + '%').html(response.percentage + '%');
1133
+ cache.get("#wpstg-processing-status").html(response.percentage.toFixed(0) + '%' + ' - Step 2 of 4 Preparing Database Data...');
1134
+ }
1135
+
1136
+ if (response.job === 'directories') {
1137
+ cache.get("#wpstg-progress-sr").css('background-color', '#3bc36b');
1138
+ cache.get("#wpstg-progress-sr").html('2. Data');
1139
+ cache.get("#wpstg-progress-dirs").width(response.percentage * 0.1 + '%').html(response.percentage + '%');
1140
+ cache.get("#wpstg-processing-status").html(response.percentage.toFixed(0) + '%' + ' - Step 3 of 4 Getting files...');
1141
+ }
1142
+ if (response.job === 'files') {
1143
+ cache.get("#wpstg-progress-dirs").css('background-color', '#3bc36b');
1144
+ cache.get("#wpstg-progress-dirs").html('3. Files');
1145
+ cache.get("#wpstg-progress-files").width(response.percentage * 0.6 + '%').html(response.percentage + '%');
1146
+ cache.get("#wpstg-processing-status").html(response.percentage.toFixed(0) + '%' + ' - Step 4 of 4 Copy files...');
1147
+ }
1148
+ if (response.job === 'finish') {
1149
+ cache.get("#wpstg-progress-files").css('background-color', '#3bc36b');
1150
+ cache.get("#wpstg-progress-files").html('4. Copy Files');
1151
+ cache.get("#wpstg-processing-status").html(response.percentage.toFixed(0) + '%' + ' - Cloning Process Finished');
1152
+ }
1153
  }
1154
+
1155
+ // Step 1: Clone Database
1156
+ // function cloneDatabase()
1157
+ // {
1158
+ // if (true === that.isCancelled)
1159
+ // {
1160
+ // return false;
1161
+ // }
1162
+ //
1163
+ // if (true === that.getLogs)
1164
+ // {
1165
+ // getLogs();
1166
+ // }
1167
+ //
1168
+ // setTimeout(
1169
+ // function () {
1170
+ // ajax(
1171
+ // {
1172
+ // action: "wpstg_clone_database",
1173
+ // nonce: wpstg.nonce
1174
+ // },
1175
+ // function (response) {
1176
+ // // Add percentage
1177
+ // if ("undefined" !== typeof (response.percentage))
1178
+ // {
1179
+ // cache.get("#wpstg-db-progress").width(response.percentage + '%');
1180
+ // }
1181
+ // // Add Log
1182
+ // if ("undefined" !== typeof (response.last_msg))
1183
+ // {
1184
+ // getLogs(response.last_msg);
1185
+ // }
1186
+ //
1187
+ // // Continue clone DB
1188
+ // if (false === response.status)
1189
+ // {
1190
+ // setTimeout(function () {
1191
+ // cloneDatabase();
1192
+ // }, wpstg.cpuLoad);
1193
+ // }
1194
+ // // Next Step
1195
+ // else if (true === response.status)
1196
+ // {
1197
+ // //console.log('prepareDirectories ' + response.status);
1198
+ // setTimeout(function () {
1199
+ // prepareDirectories();
1200
+ // }, wpstg.cpuLoad);
1201
+ // }
1202
+ // }
1203
+ // );
1204
+ // },
1205
+ // 500
1206
+ // );
1207
+ // }
1208
+
1209
+ // Step 2: Prepare Directories
1210
+ // function prepareDirectories()
1211
+ // {
1212
+ // if (true === that.isCancelled)
1213
+ // {
1214
+ // return false;
1215
+ // }
1216
+ //
1217
+ // if (true === that.getLogs)
1218
+ // {
1219
+ // getLogs();
1220
+ // }
1221
+ //
1222
+ // setTimeout(
1223
+ // function () {
1224
+ // ajax(
1225
+ // {
1226
+ // action: "wpstg_clone_prepare_directories",
1227
+ // nonce: wpstg.nonce
1228
+ // },
1229
+ // function (response) {
1230
+ //
1231
+ // // Error
1232
+ // if ("undefined" !== typeof response.error && "undefined" !== typeof response.message) {
1233
+ // showError(response.message);
1234
+ // console.log(response.message);
1235
+ // }
1236
+ //
1237
+ // // Add percentage
1238
+ // if ("undefined" !== typeof (response.percentage))
1239
+ // {
1240
+ // cache.get("#wpstg-directories-progress").width(response.percentage + '%');
1241
+ // }
1242
+ //
1243
+ // // Add Log
1244
+ // if ("undefined" !== typeof (response.last_msg))
1245
+ // {
1246
+ // getLogs(response.last_msg);
1247
+ // }
1248
+ //
1249
+ // if (false === response.status)
1250
+ // {
1251
+ // setTimeout(function () {
1252
+ // prepareDirectories();
1253
+ // }, wpstg.cpuLoad);
1254
+ // }
1255
+ // else if (true === response.status)
1256
+ // {
1257
+ // console.log('prepareDirectories' + response.status);
1258
+ // cloneFiles();
1259
+ // }
1260
+ // }
1261
+ // );
1262
+ // },
1263
+ // 500
1264
+ // );
1265
+ // }
1266
+
1267
+ // Step 3: Clone Files
1268
+ // function cloneFiles()
1269
+ // {
1270
+ // if (true === that.isCancelled)
1271
+ // {
1272
+ // return false;
1273
+ // }
1274
+ //
1275
+ // if (true === that.getLogs)
1276
+ // {
1277
+ // getLogs();
1278
+ // }
1279
+ //
1280
+ // ajax(
1281
+ // {
1282
+ // action: "wpstg_clone_files",
1283
+ // nonce: wpstg.nonce
1284
+ // },
1285
+ // function (response) {
1286
+ // // Add percentage
1287
+ // if ("undefined" !== typeof (response.percentage))
1288
+ // {
1289
+ // cache.get("#wpstg-files-progress").width(response.percentage + '%');
1290
+ // }
1291
+ //
1292
+ // // Add Log
1293
+ // if ("undefined" !== typeof (response.last_msg))
1294
+ // {
1295
+ // getLogs(response.last_msg);
1296
+ // }
1297
+ //
1298
+ // if (false === response.status)
1299
+ // {
1300
+ // setTimeout(function () {
1301
+ // cloneFiles();
1302
+ // }, wpstg.cpuLoad);
1303
+ // }
1304
+ // else if (true === response.status)
1305
+ // {
1306
+ // setTimeout(function () {
1307
+ // replaceData();
1308
+ // }, wpstg.cpuLoad);
1309
+ // }
1310
+ // }
1311
+ // );
1312
+ // }
1313
+
1314
+ // Step 4: Replace Data
1315
+ // function replaceData()
1316
+ // {
1317
+ // if (true === that.isCancelled)
1318
+ // {
1319
+ // return false;
1320
+ // }
1321
+ //
1322
+ // if (true === that.getLogs)
1323
+ // {
1324
+ // console.log('getLogs1')
1325
+ // getLogs();
1326
+ // }
1327
+ //
1328
+ // ajax(
1329
+ // {
1330
+ // action: "wpstg_clone_replace_data",
1331
+ // nonce: wpstg.nonce
1332
+ // },
1333
+ // function (response) {
1334
+ // // Add percentage
1335
+ // if ("undefined" !== typeof (response.percentage))
1336
+ // {
1337
+ // cache.get("#wpstg-links-progress").width(response.percentage + '%');
1338
+ // }
1339
+ //
1340
+ // // Add Log
1341
+ // if ("undefined" !== typeof (response.last_msg))
1342
+ // {
1343
+ // console.log('get Logs');
1344
+ // getLogs(response.last_msg);
1345
+ // }
1346
+ //
1347
+ // if (false === response.status)
1348
+ // {
1349
+ // setTimeout(function () {
1350
+ // console.log('replace data');
1351
+ // replaceData();
1352
+ // }, wpstg.cpuLoad);
1353
+ // }
1354
+ // else if (true === response.status)
1355
+ // {
1356
+ // console.log('finish');
1357
+ // finish();
1358
+ // }
1359
+ // }
1360
+ // );
1361
+ // }
1362
+
1363
+ // Finish
1364
+ // function finish()
1365
+ // {
1366
+ // if (true === that.getLogs)
1367
+ // {
1368
+ // getLogs();
1369
+ // }
1370
+ //
1371
+ // if (true === that.isCancelled || true === that.isFinished)
1372
+ // {
1373
+ // cache.get("#wpstg-loader").hide();
1374
+ // return false;
1375
+ // }
1376
+ //
1377
+ // ajax(
1378
+ // {
1379
+ // action: "wpstg_clone_finish",
1380
+ // nonce: wpstg.nonce
1381
+ // },
1382
+ // function (response)
1383
+ // {
1384
+ // // Invalid response
1385
+ // if ("object" !== typeof (response))
1386
+ // {
1387
+ // showError(
1388
+ // "Couldn't finish the cloning process properly. " +
1389
+ // "Your clone has been copied but failed to do clean up and " +
1390
+ // "saving its records to the database." +
1391
+ // "Please contact support and provide your logs."
1392
+ // );
1393
+ //
1394
+ // return;
1395
+ // }
1396
+ //
1397
+ // // Add Log
1398
+ // if ("undefined" !== typeof (response.last_msg))
1399
+ // {
1400
+ // getLogs(response.last_msg);
1401
+ // }
1402
+ //
1403
+ // console.log("Cloning process finished");
1404
+ //
1405
+ // var $link1 = cache.get("#wpstg-clone-url-1");
1406
+ // var $link = cache.get("#wpstg-clone-url");
1407
+ //
1408
+ // cache.get("#wpstg_staging_name").html(that.data.cloneID);
1409
+ // cache.get("#wpstg-finished-result").show();
1410
+ // cache.get("#wpstg-cancel-cloning").prop("disabled", true);
1411
+ // cache.get("#wpstg-cancel-cloning-update").prop("disabled", true);
1412
+ //// $link1.attr("href", $link1.attr("href") + '/' + response.directoryName);
1413
+ //// $link1.append('/' + response.directoryName);
1414
+ //// $link.attr("href", $link.attr("href") + '/' + response.directoryName);
1415
+ // $link1.attr("href", response.url);
1416
+ // $link.attr("href", response.url);
1417
+ // cache.get("#wpstg-remove-clone").data("clone", that.data.cloneID);
1418
+ //
1419
+ // // Finished
1420
+ // that.isFinished = true;
1421
+ //
1422
+ // finish();
1423
+ // }
1424
+ // );
1425
+ // }
1426
  });
1427
 
1428
 
apps/Backend/views/_includes/header.php CHANGED
@@ -32,5 +32,6 @@
32
  </div>
33
  <div style="font-size:14px;">
34
  Tutorial: <a href="https://wp-staging.com/docs/copy-staging-site-to-live-site/" target="_blank">Learn how to push changes to live website</a>
 
35
  </div>
36
  </div>
32
  </div>
33
  <div style="font-size:14px;">
34
  Tutorial: <a href="https://wp-staging.com/docs/copy-staging-site-to-live-site/" target="_blank">Learn how to push changes to live website</a>
35
+ <span style="float:right;"><a href="https://wordpress.org/support/plugin/wp-staging/reviews/?filter=5" target="_blank" rel="external noopener">Rate the plugin</a></span>
36
  </div>
37
  </div>
apps/Backend/views/_includes/messages/rating.php CHANGED
@@ -18,13 +18,12 @@
18
  </a>
19
  </li>
20
  <li>
21
- <a href="javascript:void(0);" class="wpstg_hide_rating" title="I already did" style="font-weight:bold;">
22
- I already did
23
  <?php _e('I already did','wpstg')?>
24
  </a>
25
  </li>
26
  <li>
27
- <a href="javascript:void(0);" class="wpstg_hide_rating" title="No, not good enough" style="font-weight:bold;">
28
  <?php _e('No, not good enough','wpstg')?>
29
  </a>
30
  </li>
18
  </a>
19
  </li>
20
  <li>
21
+ <a href="javascript:void(0);" class="wpstg_hide_rating" title="I already did" style="font-weight:normal;color:white;">
 
22
  <?php _e('I already did','wpstg')?>
23
  </a>
24
  </li>
25
  <li>
26
+ <a href="javascript:void(0);" class="wpstg_hide_rating" title="No, not good enough" style="font-weight:normal;color:white;">
27
  <?php _e('No, not good enough','wpstg')?>
28
  </a>
29
  </li>
apps/Backend/views/clone/ajax/start.php CHANGED
@@ -1,30 +1,38 @@
1
  <div class=successfullying-section">
2
- <?php echo __("Copy Database Tables", "wpstg")?>
3
  <div class="wpstg-progress-bar">
4
- <div class="wpstg-progress" id="wpstg-db-progress" style="width:0"></div>
 
 
 
5
  </div>
 
 
 
 
 
6
  </div>
7
 
8
- <div class="wpstg-cloning-section">
9
- <?php echo __("Prepare Directories", "wpstg")?>
10
  <div class="wpstg-progress-bar">
11
  <div class="wpstg-progress" id="wpstg-directories-progress" style="width:0"></div>
12
  </div>
13
- </div>
14
 
15
- <div class="wpstg-cloning-section">
16
- <?php echo __("Copy Files", "wpstg")?>
17
  <div class="wpstg-progress-bar">
18
  <div class="wpstg-progress" id="wpstg-files-progress" style="width:0"></div>
19
  </div>
20
  </div>
21
 
22
  <div class="wpstg-cloning-section">
23
- <?php echo __("Replace Data", "wpstg")?>
24
  <div class="wpstg-progress-bar">
25
  <div class="wpstg-progress" id="wpstg-links-progress" style="width:0"></div>
26
  </div>
27
- </div>
28
 
29
  <button type="button" id="wpstg-cancel-cloning" class="wpstg-link-btn button-primary">
30
  <?php echo __("Cancel", "wpstg")?>
@@ -42,11 +50,9 @@
42
  <h3>Congratulations
43
  </h3>
44
  <?php
45
- //echo ABSPATH . '<br>';
46
- //echo get_home_path();
47
  $subDirectory = str_replace( get_home_path(), '', ABSPATH );
48
  $url = get_home_url() . str_replace('/', '', $subDirectory);
49
- echo sprintf( __( 'WP Staging successfully created a staging site in a sub-directory of your main site in:<br><strong><a href="%1$s" target="_blank" id="wpstg-clone-url-1">%1$s</a></strong>', 'wpstg' ), $url );
50
  ?>
51
  <br>
52
  <?php //echo __('Open and access the staging site: ', 'wpstg')?>
@@ -71,9 +77,10 @@
71
  Usually this is absolutely ok for a staging website and you do not need to use permalinks at all.
72
  <br>
73
  <p>
74
- If your site is executed by the Apache webserver there is a good chance that permalinks are working without less efforts.
75
- In that case, try to activate the permalinks at <a href="<?php echo admin_url() . 'options-permalink.php'; ?>">settings > permalinks</a>
76
- <br/>
 
77
  If that does not work or you are using Nginx webserver you need to do a few modifications to the .htaccess (Apache) or *.conf (Nginx).
78
  <br>
79
  WP Staging can not do these modifications automatically.
1
  <div class=successfullying-section">
2
+ <h2 id="wpstg-processing-header"><?php echo __("Processing, please wait...", "wpstg")?></h2>
3
  <div class="wpstg-progress-bar">
4
+ <div class="wpstg-progress" id="wpstg-progress-db" style="width:0;overflow: hidden;"></div>
5
+ <div class="wpstg-progress" id="wpstg-progress-sr" style="width:0;background-color:#3c9ee4;overflow: hidden;"></div>
6
+ <div class="wpstg-progress" id="wpstg-progress-dirs" style="width:0;background-color:#3a96d7;overflow: hidden;"></div>
7
+ <div class="wpstg-progress" id="wpstg-progress-files" style="width:0;background-color:#378cc9;overflow: hidden;"></div>
8
  </div>
9
+ <div style="clear:both;">
10
+ <div id="wpstg-processing-status"></div>
11
+ <div id="wpstg-processing-timer"></div>
12
+ </div>
13
+ <div style="clear: both;"></div>
14
  </div>
15
 
16
+ <!--<div class="wpstg-cloning-section">
17
+ <?php //echo __("Prepare Directories", "wpstg")?>
18
  <div class="wpstg-progress-bar">
19
  <div class="wpstg-progress" id="wpstg-directories-progress" style="width:0"></div>
20
  </div>
21
+ </div>-->
22
 
23
+ <!--<div class="wpstg-cloning-section">
24
+ <?php //echo __("Copy Files", "wpstg")?>
25
  <div class="wpstg-progress-bar">
26
  <div class="wpstg-progress" id="wpstg-files-progress" style="width:0"></div>
27
  </div>
28
  </div>
29
 
30
  <div class="wpstg-cloning-section">
31
+ <?php //echo __("Replace Data", "wpstg")?>
32
  <div class="wpstg-progress-bar">
33
  <div class="wpstg-progress" id="wpstg-links-progress" style="width:0"></div>
34
  </div>
35
+ </div>-->
36
 
37
  <button type="button" id="wpstg-cancel-cloning" class="wpstg-link-btn button-primary">
38
  <?php echo __("Cancel", "wpstg")?>
50
  <h3>Congratulations
51
  </h3>
52
  <?php
 
 
53
  $subDirectory = str_replace( get_home_path(), '', ABSPATH );
54
  $url = get_home_url() . str_replace('/', '', $subDirectory);
55
+ echo sprintf( __( 'WP Staging successfully created a staging site in a sub-directory of your main site accessable from:<br><strong><a href="%1$s" target="_blank" id="wpstg-clone-url-1">%1$s</a></strong>', 'wpstg' ), $url );
56
  ?>
57
  <br>
58
  <?php //echo __('Open and access the staging site: ', 'wpstg')?>
77
  Usually this is absolutely ok for a staging website and you do not need to use permalinks at all.
78
  <br>
79
  <p>
80
+ If your site is executed by the Apache webserver there is a good chance that permalinks are working without much efforts.
81
+ In that case, try to activate the permalinks from <br/>
82
+ Staging Site > wp-admin > Settings > Permalinks</a>
83
+ <br/><br/>
84
  If that does not work or you are using Nginx webserver you need to do a few modifications to the .htaccess (Apache) or *.conf (Nginx).
85
  <br>
86
  WP Staging can not do these modifications automatically.
apps/Backend/views/clone/index.php CHANGED
@@ -2,8 +2,6 @@
2
 
3
  <?php require_once($this->path . "views/_includes/header.php")?>
4
 
5
- <h2 class="wpstg-nav-tab-wrapper"></h2>
6
-
7
  <?php
8
  do_action("wpstg_notifications");
9
 
2
 
3
  <?php require_once($this->path . "views/_includes/header.php")?>
4
 
 
 
5
  <?php
6
  do_action("wpstg_notifications");
7
 
apps/Core/WPStaging.php CHANGED
@@ -29,7 +29,7 @@ final class WPStaging {
29
  /**
30
  * Plugin version
31
  */
32
- const VERSION = "2.2.3";
33
 
34
  /**
35
  * Plugin name
@@ -363,7 +363,7 @@ final class WPStaging {
363
  break;
364
 
365
  case "low":
366
- $cpuLoad = 3000;
367
  break;
368
 
369
  case "default":
29
  /**
30
  * Plugin version
31
  */
32
+ const VERSION = "2.2.4";
33
 
34
  /**
35
  * Plugin name
363
  break;
364
 
365
  case "low":
366
+ $cpuLoad = 1500;
367
  break;
368
 
369
  case "default":
apps/Frontend/Frontend.php CHANGED
@@ -69,7 +69,7 @@ class Frontend extends InjectionAware {
69
  $this->resetPermaLinks();
70
 
71
  if( $this->disableLogin() ) {
72
- wp_die( sprintf( __( 'Access denied. <a href="%1$s" target="_blank">Login</a> first to access this site', 'wpstg' ), $this->getLoginUrl() ) );
73
 
74
  /**
75
  * Lines below are not used at the moment but are fully functional
69
  $this->resetPermaLinks();
70
 
71
  if( $this->disableLogin() ) {
72
+ wp_die( sprintf( __( 'Access denied. <a href="%1$s">Login</a> first to access this site', 'wpstg' ), $this->getLoginUrl() ) );
73
 
74
  /**
75
  * Lines below are not used at the moment but are fully functional
readme.txt CHANGED
@@ -9,7 +9,7 @@ License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
  Tags: staging, duplication, cloning, clone, migration, sandbox, test site, testing, backup, post, admin, administration, duplicate posts
10
  Requires at least: 3.6+
11
  Tested up to: 4.9
12
- Stable tag: 2.2.3
13
 
14
  A duplicator plugin! Clone, duplicate and migrate live sites to independent staging and development sites that are available only to administrators.
15
 
@@ -145,6 +145,16 @@ https://wp-staging.com
145
 
146
  == Changelog ==
147
 
 
 
 
 
 
 
 
 
 
 
148
  = 2.2.3 =
149
  * Fix: Change default login link to wp-admin
150
  * Fix: Unneccessary duplicates of wpstg tables in db
@@ -235,5 +245,5 @@ Complete changelog: [https://wp-staging.com/changelog.txt](https://wp-staging.co
235
 
236
  == Upgrade Notice ==
237
 
238
- = 2.2.1 =
239
- 2.2.1 * Compatible to All In One WP Security & Firewall
9
  Tags: staging, duplication, cloning, clone, migration, sandbox, test site, testing, backup, post, admin, administration, duplicate posts
10
  Requires at least: 3.6+
11
  Tested up to: 4.9
12
+ Stable tag: 2.2.4
13
 
14
  A duplicator plugin! Clone, duplicate and migrate live sites to independent staging and development sites that are available only to administrators.
15
 
145
 
146
  == Changelog ==
147
 
148
+ = 2.2.4 =
149
+ * New: Replace even hardcoded links and server path by using search & replace through all staging site database tables
150
+ * New: New and improved progress bar with elapsed time
151
+ * Fix: Cancel cloning does not clean up unused tables and leads to duplicate tables
152
+ * Tweak: Wordings in rating admin notice
153
+ * Tweak: Better error messages
154
+ * Tweak: Open staging site in same window from login request
155
+ * Fix: Set meta noindex for staging site to make it non indexable for search engines
156
+
157
+
158
  = 2.2.3 =
159
  * Fix: Change default login link to wp-admin
160
  * Fix: Unneccessary duplicates of wpstg tables in db
245
 
246
  == Upgrade Notice ==
247
 
248
+ = 2.2.4 =
249
+ 2.2.1 * New search & replace feature for serialized data
wp-staging.php CHANGED
@@ -7,7 +7,7 @@
7
  * Author: WP-Staging
8
  * Author URI: https://wp-staging.com
9
  * Contributors: ReneHermi, ilgityildirim
10
- * Version: 2.2.3
11
  * Text Domain: wpstg
12
  * Domain Path: /languages/
13
 
7
  * Author: WP-Staging
8
  * Author URI: https://wp-staging.com
9
  * Contributors: ReneHermi, ilgityildirim
10
+ * Version: 2.2.4
11
  * Text Domain: wpstg
12
  * Domain Path: /languages/
13