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

Version Description

  • Fix: Do not exclude db.php if it is not located in the wp-content folder
  • Fix: Select All button for db tables not working properly
  • New: Add Filter to exclude certain tables from search & replace operation
  • New: Show PHP user in system info
  • New: Check if there is already one process running before executing the cloning process
  • New: Support up to WordPress 5.1
Download this release

Release Info

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

Code changes from version 2.4.9 to 2.5.0

apps/Backend/Administrator.php CHANGED
@@ -15,6 +15,7 @@ use WPStaging\Backend\Modules\Jobs\Updating;
15
  use WPStaging\Backend\Modules\Jobs\Delete;
16
  use WPStaging\Backend\Modules\Jobs\Scan;
17
  use WPStaging\Backend\Modules\Jobs\Logs;
 
18
  use WPStaging\Backend\Modules\SystemInfo;
19
  use WPStaging\Backend\Modules\Views\Tabs\Tabs;
20
  use WPStaging\Backend\Notices\Notices;
@@ -87,6 +88,7 @@ class Administrator extends InjectionAware {
87
  $loader->addAction( "wp_ajax_wpstg_overview", $this, "ajaxOverview" );
88
  $loader->addAction( "wp_ajax_wpstg_scanning", $this, "ajaxScan" );
89
  $loader->addAction( "wp_ajax_wpstg_check_clone", $this, "ajaxcheckCloneName" );
 
90
  $loader->addAction( "wp_ajax_wpstg_update", $this, "ajaxUpdateProcess" );
91
  $loader->addAction( "wp_ajax_wpstg_cloning", $this, "ajaxStartClone" );
92
  $loader->addAction( "wp_ajax_wpstg_processing", $this, "ajaxCloneDatabase" );
@@ -362,6 +364,16 @@ class Administrator extends InjectionAware {
362
  return $contents;
363
  }
364
 
 
 
 
 
 
 
 
 
 
 
365
  /**
366
  * Ajax Overview
367
  */
@@ -392,6 +404,10 @@ class Administrator extends InjectionAware {
392
  public function ajaxScan() {
393
  check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
394
 
 
 
 
 
395
  $db = WPStaging::getInstance()->get( 'wpdb' );
396
 
397
  // Scan
@@ -460,6 +476,10 @@ class Administrator extends InjectionAware {
460
  public function ajaxStartClone() {
461
  check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
462
 
 
 
 
 
463
  $cloning = new Cloning();
464
 
465
  if( !$cloning->save() ) {
@@ -683,6 +703,7 @@ class Administrator extends InjectionAware {
683
  if( !class_exists( 'WPStaging\Backend\Pro\Modules\Jobs\Processing' ) ) {
684
  return false;
685
  }
 
686
  // Start the process
687
  $processing = new Processing();
688
  wp_send_json( $processing->start() );
@@ -751,7 +772,7 @@ class Administrator extends InjectionAware {
751
  $user = !empty( $args['databaseUser'] ) ? $args['databaseUser'] : '';
752
  $password = !empty( $args['databasePassword'] ) ? $args['databasePassword'] : '';
753
  $database = !empty( $args['databaseDatabase'] ) ? $args['databaseDatabase'] : '';
754
- $server = !empty( $args['databaseServer'] ) ? $args['databaseServer'] : '';
755
 
756
  $db = new \wpdb( $user, $password, $database, $server );
757
 
15
  use WPStaging\Backend\Modules\Jobs\Delete;
16
  use WPStaging\Backend\Modules\Jobs\Scan;
17
  use WPStaging\Backend\Modules\Jobs\Logs;
18
+ use WPStaging\Backend\Modules\Jobs\ProcessLock;
19
  use WPStaging\Backend\Modules\SystemInfo;
20
  use WPStaging\Backend\Modules\Views\Tabs\Tabs;
21
  use WPStaging\Backend\Notices\Notices;
88
  $loader->addAction( "wp_ajax_wpstg_overview", $this, "ajaxOverview" );
89
  $loader->addAction( "wp_ajax_wpstg_scanning", $this, "ajaxScan" );
90
  $loader->addAction( "wp_ajax_wpstg_check_clone", $this, "ajaxcheckCloneName" );
91
+ $loader->addAction( "wp_ajax_wpstg_restart", $this, "ajaxRestart" );
92
  $loader->addAction( "wp_ajax_wpstg_update", $this, "ajaxUpdateProcess" );
93
  $loader->addAction( "wp_ajax_wpstg_cloning", $this, "ajaxStartClone" );
94
  $loader->addAction( "wp_ajax_wpstg_processing", $this, "ajaxCloneDatabase" );
364
  return $contents;
365
  }
366
 
367
+ /**
368
+ * Restart cloning process
369
+ */
370
+ public function ajaxRestart() {
371
+ check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
372
+
373
+ $process = new ProcessLock();
374
+ $process->restart();
375
+ }
376
+
377
  /**
378
  * Ajax Overview
379
  */
404
  public function ajaxScan() {
405
  check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
406
 
407
+ // Check first if there is already a process running
408
+ $processLock = new ProcessLock();
409
+ $processLock->isRunning();
410
+
411
  $db = WPStaging::getInstance()->get( 'wpdb' );
412
 
413
  // Scan
476
  public function ajaxStartClone() {
477
  check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
478
 
479
+ // Check first if there is already a process running
480
+ $processLock = new ProcessLock();
481
+ $processLock->isRunning();
482
+
483
  $cloning = new Cloning();
484
 
485
  if( !$cloning->save() ) {
703
  if( !class_exists( 'WPStaging\Backend\Pro\Modules\Jobs\Processing' ) ) {
704
  return false;
705
  }
706
+
707
  // Start the process
708
  $processing = new Processing();
709
  wp_send_json( $processing->start() );
772
  $user = !empty( $args['databaseUser'] ) ? $args['databaseUser'] : '';
773
  $password = !empty( $args['databasePassword'] ) ? $args['databasePassword'] : '';
774
  $database = !empty( $args['databaseDatabase'] ) ? $args['databaseDatabase'] : '';
775
+ $server = !empty( $args['databaseServer'] ) ? $args['databaseServer'] : 'localhost';
776
 
777
  $db = new \wpdb( $user, $password, $database, $server );
778
 
apps/Backend/Modules/Jobs/Cloning.php CHANGED
@@ -49,7 +49,7 @@ class Cloning extends Job {
49
  'desktop.ini',
50
  '.gitignore',
51
  '.log',
52
- 'web.config'
53
  );
54
  $this->options->excludedFilesFullPath = array(
55
  'wp-content' . DIRECTORY_SEPARATOR . 'db.php',
@@ -153,6 +153,9 @@ class Cloning extends Job {
153
  $helper = new Helper();
154
  $this->options->homeHostname = $helper->get_home_url_without_scheme();
155
 
 
 
 
156
  return $this->saveOptions();
157
  }
158
 
@@ -297,8 +300,8 @@ class Cloning extends Job {
297
  * Start the cloning job
298
  */
299
  public function start() {
300
- if( null === $this->options->currentJob ) {
301
- $this->log( "Cloning job for {$this->options->clone} finished" );
302
  return true;
303
  }
304
 
49
  'desktop.ini',
50
  '.gitignore',
51
  '.log',
52
+ 'web.config' // Important: Windows IIS configuartion file. Must not be in the staging site!
53
  );
54
  $this->options->excludedFilesFullPath = array(
55
  'wp-content' . DIRECTORY_SEPARATOR . 'db.php',
153
  $helper = new Helper();
154
  $this->options->homeHostname = $helper->get_home_url_without_scheme();
155
 
156
+ // Process lock state
157
+ $this->options->isRunning = true;
158
+
159
  return $this->saveOptions();
160
  }
161
 
300
  * Start the cloning job
301
  */
302
  public function start() {
303
+ if( !property_exists($this->options, 'currentJob') || null === $this->options->currentJob ) {
304
+ $this->log( "Cloning job finished" );
305
  return true;
306
  }
307
 
apps/Backend/Modules/Jobs/Data.php CHANGED
@@ -137,6 +137,7 @@ class Data extends JobExecutable {
137
  */
138
  protected function isFinished() {
139
  return (
 
140
  $this->options->currentStep > $this->options->totalSteps ||
141
  !method_exists( $this, "step" . $this->options->currentStep )
142
  );
@@ -182,12 +183,12 @@ class Data extends JobExecutable {
182
  }
183
 
184
  /**
185
- * Copy wp-config.php if it is located outside of root one level up
186
- * @todo Needs some more testing before it will be released
187
  * @return boolean
188
  */
189
  protected function step0() {
190
- $this->log( "Preparing Data Step0: Check if wp-config.php is located in root path", Logger::TYPE_INFO );
191
 
192
  $dir = trailingslashit( dirname( ABSPATH ) );
193
 
@@ -239,25 +240,6 @@ class Data extends JobExecutable {
239
  return true;
240
  }
241
 
242
- // Installed in sub-directory
243
- // if( $this->isSubDir() ) {
244
- // $this->log( "Preparing Data Step1: Updating siteurl and homeurl to " . $this->getStagingSiteUrl() );
245
- // // Replace URLs
246
- // $result = $this->db->query(
247
- // $this->db->prepare(
248
- // "UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'siteurl' or option_name='home'", $this->getStagingSiteUrl()
249
- // )
250
- // );
251
- // } else {
252
- // $this->log( "Preparing Data Step1: Updating siteurl and homeurl to " . $this->getStagingSiteUrl() );
253
- // // Replace URLs
254
- // $result = $this->db->query(
255
- // $this->db->prepare(
256
- // "UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'siteurl' or option_name='home'", $this->getStagingSiteUrl()
257
- // )
258
- // );
259
- // }
260
-
261
  $this->log( "Preparing Data Step1: Updating siteurl and homeurl to " . $this->getStagingSiteUrl() );
262
  // Replace URLs
263
  $result = $this->db->query(
@@ -392,6 +374,8 @@ class Data extends JobExecutable {
392
  return false;
393
  }
394
 
 
 
395
  return true;
396
  }
397
 
@@ -446,7 +430,7 @@ class Data extends JobExecutable {
446
 
447
  if( !preg_match( "/(require(.*)wp-blog-header.php' \);)/", $content, $matches ) ) {
448
  $this->log(
449
- "Preparing Data Step6: Failed to reset index.php for sub directory; wp-blog-header.php is missing", Logger::TYPE_ERROR
450
  );
451
  return false;
452
  }
@@ -592,12 +576,12 @@ class Data extends JobExecutable {
592
 
593
 
594
  // Get WP_HOME from wp-config.php
595
- preg_match( "/define\s*\(\s*'WP_HOME'\s*,\s*(.*)\s*\);/", $content, $matches );
596
 
597
  if( !empty( $matches[1] ) ) {
598
  $matches[1];
599
 
600
- $pattern = "/define\s*\(\s*'WP_HOME'\s*,\s*(.*)\s*\);/";
601
 
602
  $replace = "define('WP_HOME','" . $this->getStagingSiteUrl() . "'); // " . $matches[1];
603
  $replace.= " // Changed by WP-Staging";
@@ -634,12 +618,12 @@ class Data extends JobExecutable {
634
 
635
 
636
  // Get WP_SITEURL from wp-config.php
637
- preg_match( "/define\s*\(\s*'WP_SITEURL'\s*,\s*(.*)\s*\);/", $content, $matches );
638
 
639
  if( !empty( $matches[1] ) ) {
640
  $matches[1];
641
 
642
- $pattern = "/define\s*\(\s*'WP_SITEURL'\s*,\s*(.*)\s*\);/";
643
 
644
  $replace = "define('WP_SITEURL','" . $this->getStagingSiteUrl() . "'); // " . $matches[1];
645
  $replace.= " // Changed by WP-Staging";
@@ -767,12 +751,13 @@ class Data extends JobExecutable {
767
  "UPDATE IGNORE {$this->prefix}options SET option_name= replace(option_name, %s, %s) WHERE option_name LIKE %s" . $where, $this->db->prefix, $this->prefix, $this->db->prefix . "_%"
768
  )
769
  );
770
-
771
- if( !$updateOptions ) {
772
  $this->log( "Preparing Data Step12: Failed to update option_name in {$this->prefix}options. Error: {$this->db->last_error}", Logger::TYPE_ERROR );
773
- $this->returnException( " Preparing Data Step12: Failed to update db option_names in {$this->prefix}options. Error: {$this->db->last_error}" );
774
- return false;
775
- }
 
776
  $this->Log( "Preparing Data Step 12: Finished successfully" );
777
  return true;
778
  }
@@ -836,11 +821,11 @@ class Data extends JobExecutable {
836
 
837
 
838
  // Get WP_CACHE from wp-config.php
839
- preg_match( "/define\s*\(\s*'WP_CACHE'\s*,\s*(.*)\s*\);/", $content, $matches );
840
 
841
  if( !empty( $matches[1] ) ) {
842
 
843
- $pattern = "/define\s*\(\s*'WP_CACHE'\s*,\s*(.*)\s*\);/";
844
 
845
  $replace = "define('WP_CACHE',false); // " . $matches[1];
846
  $replace.= " // Changed by WP-Staging";
@@ -876,12 +861,12 @@ class Data extends JobExecutable {
876
  }
877
 
878
 
879
- // Get WP_CONTENT_DIR from wp-config.php
880
- preg_match( "/define\s*\(\s*'WP_CONTENT_DIR'\s*,\s*(.*)\s*\);/", $content, $matches );
881
 
882
  if( !empty( $matches[0] ) ) {
883
 
884
- $pattern = "/define\s*\(\s*'WP_CONTENT_DIR'\s*,\s*(.*)\s*\);/";
885
 
886
  $replace = "";
887
 
@@ -900,8 +885,9 @@ class Data extends JobExecutable {
900
  $this->Log( "Preparing Data Step 15: Finished successfully" );
901
  return true;
902
  }
 
903
  /**
904
- * Remove WP_CONTENT_URL in wp-config.php
905
  * @return bool
906
  */
907
  protected function step16() {
@@ -915,8 +901,8 @@ class Data extends JobExecutable {
915
  }
916
 
917
 
918
- // Get WP_CONTENT_DIR from wp-config.php
919
- preg_match( "/define\s*\(\s*'WP_CONTENT_URL'\s*,\s*(.*)\s*\);/", $content, $matches );
920
 
921
  if( !empty( $matches[0] ) ) {
922
 
@@ -951,7 +937,7 @@ class Data extends JobExecutable {
951
 
952
  $customSlug = str_replace( \WPStaging\WPStaging::getWPpath(), '', $uploadPath );
953
 
954
- $newUploadPath = $this->options->destinationDir . $customSlug;
955
 
956
  return $newUploadPath;
957
  }
137
  */
138
  protected function isFinished() {
139
  return (
140
+ !isset($this->options->isRunning) ||
141
  $this->options->currentStep > $this->options->totalSteps ||
142
  !method_exists( $this, "step" . $this->options->currentStep )
143
  );
183
  }
184
 
185
  /**
186
+ * Copy wp-config.php from the staging site if it is located outside of root one level up or
187
+ * copy default wp-config.php if production site uses bedrock or any other boilerplate solution that stores wp default config data elsewhere.
188
  * @return boolean
189
  */
190
  protected function step0() {
191
+ $this->log( "Preparing Data Step0: Copy wp-config.php file", Logger::TYPE_INFO );
192
 
193
  $dir = trailingslashit( dirname( ABSPATH ) );
194
 
240
  return true;
241
  }
242
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
243
  $this->log( "Preparing Data Step1: Updating siteurl and homeurl to " . $this->getStagingSiteUrl() );
244
  // Replace URLs
245
  $result = $this->db->query(
374
  return false;
375
  }
376
 
377
+
378
+
379
  return true;
380
  }
381
 
430
 
431
  if( !preg_match( "/(require(.*)wp-blog-header.php' \);)/", $content, $matches ) ) {
432
  $this->log(
433
+ "Preparing Data Step6: Failed to reset index.php for sub directory. Can not find line 'require(.*)wp-blog-header.php' in index.php", Logger::TYPE_ERROR
434
  );
435
  return false;
436
  }
576
 
577
 
578
  // Get WP_HOME from wp-config.php
579
+ preg_match( "/define\s*\(\s*['\"]WP_HOME['\"]\s*,\s*(.*)\s*\);/", $content, $matches );
580
 
581
  if( !empty( $matches[1] ) ) {
582
  $matches[1];
583
 
584
+ $pattern = "/define\s*\(\s*['\"]WP_HOME['\"]\s*,\s*(.*)\s*\);/";
585
 
586
  $replace = "define('WP_HOME','" . $this->getStagingSiteUrl() . "'); // " . $matches[1];
587
  $replace.= " // Changed by WP-Staging";
618
 
619
 
620
  // Get WP_SITEURL from wp-config.php
621
+ preg_match( "/define\s*\(\s*['\"]WP_SITEURL['\"]\s*,\s*(.*)\s*\);/", $content, $matches );
622
 
623
  if( !empty( $matches[1] ) ) {
624
  $matches[1];
625
 
626
+ $pattern = "/define\s*\(\s*['\"]WP_SITEURL['\"]\s*,\s*(.*)\s*\);/";
627
 
628
  $replace = "define('WP_SITEURL','" . $this->getStagingSiteUrl() . "'); // " . $matches[1];
629
  $replace.= " // Changed by WP-Staging";
751
  "UPDATE IGNORE {$this->prefix}options SET option_name= replace(option_name, %s, %s) WHERE option_name LIKE %s" . $where, $this->db->prefix, $this->prefix, $this->db->prefix . "_%"
752
  )
753
  );
754
+
755
+ if( !$updateOptions ) {
756
  $this->log( "Preparing Data Step12: Failed to update option_name in {$this->prefix}options. Error: {$this->db->last_error}", Logger::TYPE_ERROR );
757
+ $this->log( "Preparing Data Step12: Query: UPDATE IGNORE {$this->prefix}options SET option_name= replace(option_name, {$this->db->prefix}, {$this->prefix}) WHERE option_name LIKE {$this->db->prefix} {$where}", Logger::TYPE_ERROR );
758
+ $this->returnException( " Preparing Data Step12: Failed to update db option_names in {$this->prefix}options. Error: {$this->db->last_error}" );
759
+ return false;
760
+ }
761
  $this->Log( "Preparing Data Step 12: Finished successfully" );
762
  return true;
763
  }
821
 
822
 
823
  // Get WP_CACHE from wp-config.php
824
+ preg_match( "/define\s*\(\s*['\"]WP_CACHE['\"]\s*,\s*(.*)\s*\);/", $content, $matches );
825
 
826
  if( !empty( $matches[1] ) ) {
827
 
828
+ $pattern = "/define\s*\(\s*['\"]WP_CACHE['\"]\s*,\s*(.*)\s*\);/";
829
 
830
  $replace = "define('WP_CACHE',false); // " . $matches[1];
831
  $replace.= " // Changed by WP-Staging";
861
  }
862
 
863
 
864
+ // Remove WP_CONTENT_DIR from wp-config.php
865
+ preg_match( "/define\s*\(\s*['\"]WP_CONTENT_DIR['\"]\s*,\s*(.*)\s*\);/", $content, $matches );
866
 
867
  if( !empty( $matches[0] ) ) {
868
 
869
+ $pattern = "/define\s*\(\s*['\"]WP_CONTENT_DIR['\"]\s*,\s*(.*)\s*\);/";
870
 
871
  $replace = "";
872
 
885
  $this->Log( "Preparing Data Step 15: Finished successfully" );
886
  return true;
887
  }
888
+
889
  /**
890
+ * Remove WP_CONTENT_URL in wp-config.php to reset default image folder
891
  * @return bool
892
  */
893
  protected function step16() {
901
  }
902
 
903
 
904
+ // Get WP_CONTENT_DIR from wp-config.php to reset default image folder
905
+ preg_match( "/define\s*\(\s*['\"]WP_CONTENT_URL['\"]\s*,\s*(.*)\s*\);/", $content, $matches );
906
 
907
  if( !empty( $matches[0] ) ) {
908
 
937
 
938
  $customSlug = str_replace( \WPStaging\WPStaging::getWPpath(), '', $uploadPath );
939
 
940
+ $newUploadPath = $this->options->destinationDir . $customSlug;
941
 
942
  return $newUploadPath;
943
  }
apps/Backend/Modules/Jobs/Database.php CHANGED
@@ -43,8 +43,7 @@ class Database extends JobExecutable {
43
  */
44
  private function isExternalDatabase() {
45
  if( !empty( $this->options->databaseUser ) ) {
46
- $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") );
47
-
48
  }
49
  return false;
50
  }
@@ -85,7 +84,7 @@ class Database extends JobExecutable {
85
  }
86
 
87
  // No more steps, finished
88
- if( $this->options->currentStep > $this->total || !isset( $this->options->tables[$this->options->currentStep] ) ) {
89
  $this->prepareResponse( true, false );
90
  return false;
91
  }
@@ -121,8 +120,7 @@ class Database extends JobExecutable {
121
  $stagingPrefix = $this->options->prefix;
122
  // Make sure prefix of staging site is NEVER identical to prefix of live site!
123
  if( $stagingPrefix == $this->db->prefix ) {
124
- //wp_die('Fatal error 7: The new database table prefix '. $stagingPrefix .' would be identical to the table prefix of the live site. Please open a support ticket to support@wp-staging.com');
125
- $this->returnException( 'Fatal error 7: The new database table prefix ' . $stagingPrefix . ' would be identical to the table prefix of the live site. Please open a support ticket to support@wp-staging.com' );
126
  }
127
  return $stagingPrefix;
128
  }
43
  */
44
  private function isExternalDatabase() {
45
  if( !empty( $this->options->databaseUser ) ) {
46
+ $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" ) );
 
47
  }
48
  return false;
49
  }
84
  }
85
 
86
  // No more steps, finished
87
+ if( !isset( $this->options->isRunning ) || $this->options->currentStep > $this->total || !isset( $this->options->tables[$this->options->currentStep] ) ) {
88
  $this->prepareResponse( true, false );
89
  return false;
90
  }
120
  $stagingPrefix = $this->options->prefix;
121
  // Make sure prefix of staging site is NEVER identical to prefix of live site!
122
  if( $stagingPrefix == $this->db->prefix ) {
123
+ wp_die( 'Fatal error 7: The new database table prefix ' . $stagingPrefix . ' would be identical to the table prefix of the live site. Please open a support ticket at support@wp-staging.com' );
 
124
  }
125
  return $stagingPrefix;
126
  }
apps/Backend/Modules/Jobs/Delete.php CHANGED
@@ -448,6 +448,7 @@ class Delete extends Job {
448
  // Delete cached file
449
  $this->cache->delete( "delete_job_{$this->clone->name}" );
450
  $this->cache->delete( "delete_directories_{$this->clone->name}" );
 
451
 
452
  //return true;
453
  $response = array('delete' => 'finished');
448
  // Delete cached file
449
  $this->cache->delete( "delete_job_{$this->clone->name}" );
450
  $this->cache->delete( "delete_directories_{$this->clone->name}" );
451
+ $this->cache->delete( "clone_options" );
452
 
453
  //return true;
454
  $response = array('delete' => 'finished');
apps/Backend/Modules/Jobs/Files.php CHANGED
@@ -158,6 +158,7 @@ class Files extends JobExecutable {
158
  */
159
  private function isFinished() {
160
  return (
 
161
  $this->options->currentStep > $this->options->totalSteps ||
162
  $this->options->copiedFiles >= $this->options->totalFiles
163
  );
158
  */
159
  private function isFinished() {
160
  return (
161
+ !isset($this->options->isRunning) ||
162
  $this->options->currentStep > $this->options->totalSteps ||
163
  $this->options->copiedFiles >= $this->options->totalFiles
164
  );
apps/Backend/Modules/Jobs/Finish.php CHANGED
@@ -30,6 +30,8 @@ class Finish extends Job {
30
  // Prepare clone records & save scanned directories for delete job later
31
  $this->prepareCloneDataRecords();
32
 
 
 
33
  $return = array(
34
  "directoryName" => $this->options->cloneDirectoryName,
35
  "path" => trailingslashit( $this->options->destinationDir ),
@@ -117,41 +119,6 @@ class Finish extends Job {
117
  return $this->options->cloneHostname;
118
  }
119
 
120
- // if( isSubDir ) {
121
- // return trailingslashit( get_site_url() ) . trailingslashit($this->getSubDir()) . $this->options->cloneDirectoryName;
122
- // }
123
  return trailingslashit( get_site_url() ) . $this->options->cloneDirectoryName;
124
  }
125
-
126
- /**
127
- * Check if WP is installed in subdir
128
- * @return boolean
129
- */
130
- // private function isSubDir() {
131
- // // Compare names without scheme to bypass cases where siteurl and home have different schemes http / https
132
- // // This is happening much more often than you would expect
133
- // $siteurl = preg_replace( '#^https?://#', '', rtrim( get_option( 'siteurl' ), '/' ) );
134
- // $home = preg_replace( '#^https?://#', '', rtrim( get_option( 'home' ), '/' ) );
135
- //
136
- // if( $home !== $siteurl ) {
137
- // return true;
138
- // }
139
- // return false;
140
- // }
141
-
142
- /**
143
- * Get the install sub directory if WP is installed in sub directory
144
- * @return string
145
- */
146
- // private function getSubDir() {
147
- // $home = get_option( 'home' );
148
- // $siteurl = get_option( 'siteurl' );
149
- //
150
- // if( empty( $home ) || empty( $siteurl ) ) {
151
- // return '';
152
- // }
153
- //
154
- // $dir = str_replace( $home, '', $siteurl );
155
- // return str_replace( '/', '', $dir );
156
- // }
157
  }
30
  // Prepare clone records & save scanned directories for delete job later
31
  $this->prepareCloneDataRecords();
32
 
33
+ $this->options->isRunning = false;
34
+
35
  $return = array(
36
  "directoryName" => $this->options->cloneDirectoryName,
37
  "path" => trailingslashit( $this->options->destinationDir ),
119
  return $this->options->cloneHostname;
120
  }
121
 
 
 
 
122
  return trailingslashit( get_site_url() ) . $this->options->cloneDirectoryName;
123
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
124
  }
apps/Backend/Modules/Jobs/Multisite/Data.php CHANGED
@@ -444,7 +444,7 @@ class Data extends JobExecutable {
444
 
445
  if( !preg_match( "/(require(.*)wp-blog-header.php' \);)/", $content, $matches ) ) {
446
  $this->log(
447
- "Preparing Data Step6: Failed to reset index.php for sub directory; wp-blog-header.php is missing", Logger::TYPE_ERROR
448
  );
449
  return false;
450
  }
444
 
445
  if( !preg_match( "/(require(.*)wp-blog-header.php' \);)/", $content, $matches ) ) {
446
  $this->log(
447
+ "Preparing Data Step6: Failed to reset index.php for sub directory. Can not find line 'require(.*)wp-blog-header.php' in index.php", Logger::TYPE_ERROR
448
  );
449
  return false;
450
  }
apps/Backend/Modules/Jobs/Multisite/DataExternal.php CHANGED
@@ -468,7 +468,7 @@ class DataExternal extends JobExecutable {
468
 
469
  if( !preg_match( "/(require(.*)wp-blog-header.php' \);)/", $content, $matches ) ) {
470
  $this->log(
471
- "Preparing Data Step6: Failed to reset index.php for sub directory; wp-blog-header.php is missing", Logger::TYPE_ERROR
472
  );
473
  return false;
474
  }
468
 
469
  if( !preg_match( "/(require(.*)wp-blog-header.php' \);)/", $content, $matches ) ) {
470
  $this->log(
471
+ "Preparing Data Step6: Failed to reset index.php for sub directory. Can not find line 'require(.*)wp-blog-header.php' in index.php", Logger::TYPE_ERROR
472
  );
473
  return false;
474
  }
apps/Backend/Modules/Jobs/ProcessLock.php ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPStaging\Backend\Modules\Jobs;
4
+
5
+ use WPStaging\WPStaging;
6
+
7
+ //use WPStaging\Utils\Cache;
8
+
9
+ /**
10
+ * Class Cloning
11
+ * @package WPStaging\Backend\Modules\Jobs
12
+ */
13
+ class ProcessLock extends JobExecutable {
14
+
15
+ /**
16
+ * Check if any process is already running
17
+ * @return boolean
18
+ */
19
+ public function isRunning() {
20
+ // Another process is running
21
+ if( isset( $this->options->isRunning ) ) {
22
+
23
+ $this->log( "Another process is running" );
24
+
25
+ $message = __( 'Hold on, another WP Staging process is already running...', 'wp-staging' );
26
+
27
+ require_once WPSTG_PLUGIN_DIR . "apps/Backend/views/clone/ajax/process-lock.php";
28
+
29
+ wp_die();
30
+ }
31
+ // No other process running
32
+
33
+ return false;
34
+ }
35
+
36
+ /**
37
+ * remove process lock value
38
+ */
39
+ public function restart() {
40
+ unset( $this->options->isRunning );
41
+ $this->cache->delete( "clone_options" );
42
+ $this->cache->delete( "files_to_copy" );
43
+ }
44
+
45
+ /**
46
+ * abstract
47
+ * @return void
48
+ */
49
+ protected function calculateTotalSteps() {
50
+
51
+ }
52
+
53
+ /**
54
+ * abstract
55
+ * @return bool
56
+ */
57
+ protected function execute() {
58
+
59
+ }
60
+
61
+ }
apps/Backend/Modules/Jobs/Updating.php CHANGED
@@ -60,7 +60,6 @@ class Updating extends Job {
60
  'desktop.ini',
61
  '.gitignore',
62
  '.log',
63
- 'db.php',
64
  'object-cache.php',
65
  'web.config' // Important: Windows IIS configuartion file. Must not be in the staging site!
66
 
@@ -150,6 +149,9 @@ class Updating extends Job {
150
  );
151
 
152
  array_unshift( $this->options->directoriesToCopy, ABSPATH );
 
 
 
153
 
154
  return $this->saveOptions();
155
  }
60
  'desktop.ini',
61
  '.gitignore',
62
  '.log',
 
63
  'object-cache.php',
64
  'web.config' // Important: Windows IIS configuartion file. Must not be in the staging site!
65
 
149
  );
150
 
151
  array_unshift( $this->options->directoriesToCopy, ABSPATH );
152
+
153
+ // Process lock state
154
+ $this->options->isRunning = true;
155
 
156
  return $this->saveOptions();
157
  }
apps/Backend/Modules/SystemInfo.php CHANGED
@@ -3,7 +3,7 @@
3
  namespace WPStaging\Backend\Modules;
4
 
5
  use WPStaging\DI\InjectionAware;
6
- use WPStaging\Library\Browser;
7
  use WPStaging\WPStaging;
8
  use WPStaging\Utils;
9
  use WPStaging\Utils\Multisite;
@@ -181,12 +181,12 @@ class SystemInfo extends InjectionAware {
181
 
182
  $output .= $this->info( "Number:", isset( $clone['number'] ) ? $clone['number'] : 'undefined' );
183
  $output .= $this->info( "directoryName:", isset( $clone['directoryName'] ) ? $clone['directoryName'] : 'undefined' );
184
- $output .= $this->info( "Path:", $path );
185
  $output .= $this->info( "URL:", isset( $clone['url'] ) ? $clone['url'] : 'undefined' );
186
  $output .= $this->info( "DB Prefix:", isset( $clone['prefix'] ) ? $clone['prefix'] : 'undefined' );
187
  $output .= $this->info( "DB Prefix wp-config.php:", $this->getStagingPrefix( $clone ) );
188
  $output .= $this->info( "WP Staging Version:", isset( $clone['version'] ) ? $clone['version'] : 'undefined' );
189
- $output .= $this->info( "WP Version:", $this->getStagingWpVersion($path)) . PHP_EOL . PHP_EOL;
190
  }
191
 
192
 
@@ -422,12 +422,13 @@ class SystemInfo extends InjectionAware {
422
  public function php() {
423
  $output = $this->header( "PHP Configuration" );
424
  $output .= $this->info( "Safe Mode:", ($this->isSafeModeEnabled() ? "Enabled" : "Disabled" ) );
425
- $output .= $this->info( "Memory Limit:", ini_get( "memory_limit" ) );
426
  $output .= $this->info( "Upload Max Size:", ini_get( "upload_max_filesize" ) );
427
  $output .= $this->info( "Post Max Size:", ini_get( "post_max_size" ) );
428
  $output .= $this->info( "Upload Max Filesize:", ini_get( "upload_max_filesize" ) );
429
  $output .= $this->info( "Time Limit:", ini_get( "max_execution_time" ) );
430
  $output .= $this->info( "Max Input Vars:", ini_get( "max_input_vars" ) );
 
431
 
432
  $displayErrors = ini_get( "display_errors" );
433
  $output .= $this->info( "Display Errors:", ($displayErrors) ? "On ({$displayErrors})" : "N/A" );
@@ -435,6 +436,28 @@ class SystemInfo extends InjectionAware {
435
  return apply_filters( "wpstg_sysinfo_after_php_config", $output );
436
  }
437
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
438
  /**
439
  * Check if PHP is on Safe Mode
440
  * @return bool
@@ -560,7 +583,7 @@ class SystemInfo extends InjectionAware {
560
  }
561
 
562
  // Get version number of wp staging
563
- $file = $path . 'wp-includes/version.php';
564
  $versionStaging = file_get_contents( $file );
565
 
566
  preg_match( "/\\\$wp_version.*=.*'(.*)';/", $versionStaging, $matches );
@@ -570,7 +593,6 @@ class SystemInfo extends InjectionAware {
570
  $error .= "Error: Cannot detect WP version";
571
  }
572
  return $matches[1];
573
-
574
  }
575
 
576
  }
3
  namespace WPStaging\Backend\Modules;
4
 
5
  use WPStaging\DI\InjectionAware;
6
+ use WPStaging\Utils\Browser;
7
  use WPStaging\WPStaging;
8
  use WPStaging\Utils;
9
  use WPStaging\Utils\Multisite;
181
 
182
  $output .= $this->info( "Number:", isset( $clone['number'] ) ? $clone['number'] : 'undefined' );
183
  $output .= $this->info( "directoryName:", isset( $clone['directoryName'] ) ? $clone['directoryName'] : 'undefined' );
184
+ $output .= $this->info( "Path:", $path );
185
  $output .= $this->info( "URL:", isset( $clone['url'] ) ? $clone['url'] : 'undefined' );
186
  $output .= $this->info( "DB Prefix:", isset( $clone['prefix'] ) ? $clone['prefix'] : 'undefined' );
187
  $output .= $this->info( "DB Prefix wp-config.php:", $this->getStagingPrefix( $clone ) );
188
  $output .= $this->info( "WP Staging Version:", isset( $clone['version'] ) ? $clone['version'] : 'undefined' );
189
+ $output .= $this->info( "WP Version:", $this->getStagingWpVersion( $path ) ) . PHP_EOL . PHP_EOL;
190
  }
191
 
192
 
422
  public function php() {
423
  $output = $this->header( "PHP Configuration" );
424
  $output .= $this->info( "Safe Mode:", ($this->isSafeModeEnabled() ? "Enabled" : "Disabled" ) );
425
+ $output .= $this->info( "PHP Max Memory Limit:", ini_get( "memory_limit" ) );
426
  $output .= $this->info( "Upload Max Size:", ini_get( "upload_max_filesize" ) );
427
  $output .= $this->info( "Post Max Size:", ini_get( "post_max_size" ) );
428
  $output .= $this->info( "Upload Max Filesize:", ini_get( "upload_max_filesize" ) );
429
  $output .= $this->info( "Time Limit:", ini_get( "max_execution_time" ) );
430
  $output .= $this->info( "Max Input Vars:", ini_get( "max_input_vars" ) );
431
+ $output .= $this->info( "PHP User:", $this->getPHPUser() );
432
 
433
  $displayErrors = ini_get( "display_errors" );
434
  $output .= $this->info( "Display Errors:", ($displayErrors) ? "On ({$displayErrors})" : "N/A" );
436
  return apply_filters( "wpstg_sysinfo_after_php_config", $output );
437
  }
438
 
439
+ /**
440
+ *
441
+ * @return string
442
+ */
443
+ private function getPHPUser() {
444
+
445
+ $user = '';
446
+
447
+ if( extension_loaded( 'posix' ) ) {
448
+ $file = WPSTG_PLUGIN_DIR . 'wp-staging-pro.php';
449
+ $user = posix_getpwuid( fileowner( $file ) );
450
+ return $user;
451
+ }
452
+
453
+ if( function_exists( 'exec' ) && @exec('echo EXEC') == 'EXEC') {
454
+ $user = exec( 'whoami' );
455
+ return $user;
456
+ }
457
+
458
+ return $user;
459
+ }
460
+
461
  /**
462
  * Check if PHP is on Safe Mode
463
  * @return bool
583
  }
584
 
585
  // Get version number of wp staging
586
+ $file = trailingslashit( $path ) . 'wp-includes/version.php';
587
  $versionStaging = file_get_contents( $file );
588
 
589
  preg_match( "/\\\$wp_version.*=.*'(.*)';/", $versionStaging, $matches );
593
  $error .= "Error: Cannot detect WP version";
594
  }
595
  return $matches[1];
 
596
  }
597
 
598
  }
apps/Backend/public/js/wpstg-admin.js CHANGED
@@ -64,7 +64,7 @@ var WPStaging = (function ($)
64
  var elements = function ()
65
  {
66
  var $workFlow = cache.get("#wpstg-workflow"),
67
- isAllChecked = false,
68
  urlSpinner = ajaxurl.replace("/admin-ajax.php", '') + "/images/spinner",
69
  timer;
70
 
@@ -99,13 +99,12 @@ var WPStaging = (function ($)
99
  .on("click", ".wpstg-button-unselect", function (e) {
100
  e.preventDefault();
101
 
102
-
103
- //if (typeof(isAllChecked) !== 'defined' || true === isAllChecked )
104
  if (false === isAllChecked )
105
  {
106
  console.log('true');
107
  cache.get("#wpstg_select_tables_cloning .wpstg-db-table").prop("selected", "selected");
108
  cache.get(".wpstg-button-unselect").text("Unselect All");
 
109
  isAllChecked = true;
110
  }
111
  else
@@ -113,6 +112,7 @@ var WPStaging = (function ($)
113
  console.log('false');
114
  cache.get("#wpstg_select_tables_cloning .wpstg-db-table").prop("selected", false);
115
  cache.get(".wpstg-button-unselect").text("Select All");
 
116
  isAllChecked = false;
117
  }
118
  })
@@ -333,6 +333,23 @@ var WPStaging = (function ($)
333
 
334
  cancelCloningUpdate();
335
  })
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
336
  // Delete clone - confirmation
337
  .on("click", ".wpstg-remove-clone[data-clone]", function (e) {
338
  e.preventDefault();
@@ -952,6 +969,44 @@ var WPStaging = (function ($)
952
  }
953
  );
954
  };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
955
 
956
 
957
  /**
64
  var elements = function ()
65
  {
66
  var $workFlow = cache.get("#wpstg-workflow"),
67
+ isAllChecked = true,
68
  urlSpinner = ajaxurl.replace("/admin-ajax.php", '') + "/images/spinner",
69
  timer;
70
 
99
  .on("click", ".wpstg-button-unselect", function (e) {
100
  e.preventDefault();
101
 
 
 
102
  if (false === isAllChecked )
103
  {
104
  console.log('true');
105
  cache.get("#wpstg_select_tables_cloning .wpstg-db-table").prop("selected", "selected");
106
  cache.get(".wpstg-button-unselect").text("Unselect All");
107
+ cache.get(".wpstg-db-table-checkboxes").prop("checked", true);
108
  isAllChecked = true;
109
  }
110
  else
112
  console.log('false');
113
  cache.get("#wpstg_select_tables_cloning .wpstg-db-table").prop("selected", false);
114
  cache.get(".wpstg-button-unselect").text("Select All");
115
+ cache.get(".wpstg-db-table-checkboxes").prop("checked", false);
116
  isAllChecked = false;
117
  }
118
  })
333
 
334
  cancelCloningUpdate();
335
  })
336
+ // Restart cloning
337
+ .on("click", "#wpstg-restart-cloning", function () {
338
+
339
+ var $this = $(this);
340
+
341
+ $("#wpstg-try-again, #wpstg-home-link").hide();
342
+ $this.prop("disabled", true);
343
+
344
+ that.isCancelled = true;
345
+
346
+ $("#wpstg-cloning-result").text("Please wait...this can take up a while.");
347
+ $("#wpstg-loader, #wpstg-show-log-button").hide();
348
+
349
+ $this.parent().append(ajaxSpinner);
350
+
351
+ restart();
352
+ })
353
  // Delete clone - confirmation
354
  .on("click", ".wpstg-remove-clone[data-clone]", function (e) {
355
  e.preventDefault();
969
  }
970
  );
971
  };
972
+ /**
973
+ * Cancel Cloning Process
974
+ */
975
+ var restart = function ()
976
+ {
977
+ if (true === that.isFinished)
978
+ {
979
+ return true;
980
+ }
981
+
982
+ ajax(
983
+ {
984
+ action: "wpstg_restart",
985
+ //clone: that.data.cloneID,
986
+ nonce: wpstg.nonce
987
+ },
988
+ function (response)
989
+ {
990
+
991
+
992
+ if (response && "undefined" !== typeof (response.delete) && response.delete === "finished") {
993
+ // Load overview
994
+ loadOverview();
995
+ return;
996
+ }
997
+
998
+ if (true !== response)
999
+ {
1000
+ // continue
1001
+ cancelCloningUpdate();
1002
+ return;
1003
+ }
1004
+
1005
+ // Load overview
1006
+ loadOverview();
1007
+ }
1008
+ );
1009
+ };
1010
 
1011
 
1012
  /**
apps/Backend/views/clone/ajax/process-lock.php ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ <h3><?php echo $message; ?></h3>
3
+
4
+
5
+ <button type="button" class="wpstg-prev-step-link wpstg-link-btn button-primary wpstg-button">
6
+ <?php _e( "Back", "wp-staging" ) ?>
7
+ </button>
8
+
9
+ <button type="button" id="wpstg-restart-cloning" class="wpstg-link-btn button-primary wpstg-button">
10
+ <?php echo __("Start over and stop other process", "wp-staging")?>
11
+ </button>
12
+
13
+
14
+
apps/Backend/views/clone/ajax/scan.php CHANGED
@@ -34,7 +34,7 @@
34
  ?>
35
  </h4>
36
  <div style="margin-top:10px;margin-bottom:10px;">
37
- <a href="#" class="wpstg-button-unselect button"><?php _e('Select All','wp-staging'); ?></a>
38
  <a href="#" class="wpstg-button-select button"> <?php _e( WPStaging\WPStaging::getTablePrefix(), 'wp-staging' ); ?> </a>
39
  </div>
40
  <select multiple="multiple" id="wpstg_select_tables_cloning">
@@ -68,7 +68,7 @@
68
  <?php // endforeach ?>
69
 
70
  <div style="margin-top:10px;">
71
- <a href="#" class="wpstg-button-unselect button"> None </a>
72
  <a href="#" class="wpstg-button-select button"> <?php _e( WPStaging\WPStaging::getTablePrefix(), 'wp-staging' ); ?> </a>
73
  </div>
74
  </div>
34
  ?>
35
  </h4>
36
  <div style="margin-top:10px;margin-bottom:10px;">
37
+ <a href="#" class="wpstg-button-unselect button"><?php _e('Unselect All','wp-staging'); ?></a>
38
  <a href="#" class="wpstg-button-select button"> <?php _e( WPStaging\WPStaging::getTablePrefix(), 'wp-staging' ); ?> </a>
39
  </div>
40
  <select multiple="multiple" id="wpstg_select_tables_cloning">
68
  <?php // endforeach ?>
69
 
70
  <div style="margin-top:10px;">
71
+ <a href="#" class="wpstg-button-unselect button"> <?php _e('Unselect All','wp-staging'); ?> </a>
72
  <a href="#" class="wpstg-button-select button"> <?php _e( WPStaging\WPStaging::getTablePrefix(), 'wp-staging' ); ?> </a>
73
  </div>
74
  </div>
apps/{Library → Core/Utils}/Browser.php RENAMED
File without changes
apps/Core/WPStaging.php CHANGED
@@ -29,7 +29,7 @@ final class WPStaging {
29
  /**
30
  * Plugin version
31
  */
32
- const VERSION = "2.4.9";
33
 
34
  /**
35
  * Plugin name
@@ -44,7 +44,7 @@ final class WPStaging {
44
  /**
45
  * Compatible WP Version
46
  */
47
- const WP_COMPATIBLE = "5.0.3";
48
 
49
  public $wpPath;
50
 
29
  /**
30
  * Plugin version
31
  */
32
+ const VERSION = "2.5.0";
33
 
34
  /**
35
  * Plugin name
44
  /**
45
  * Compatible WP Version
46
  */
47
+ const WP_COMPATIBLE = "5.1.0";
48
 
49
  public $wpPath;
50
 
apps/Core/thirdParty/thirdPartyCompatibility.php CHANGED
@@ -9,25 +9,27 @@ use WPStaging\DI\InjectionAware;
9
  *
10
  * @author IronMan
11
  */
12
- class thirdPartyCompatibility extends InjectionAware
13
- {
14
-
15
- /**
16
- * Define a list of tables which should not run through search & replace method
17
- * @param string table name e.g. wpsptg1_cerber_files or wpstgtmp_4_cerber_files
18
- * @return array
19
- */
20
- public function isSearchReplaceExcluded($table) {
21
- $excludedTables = array(
22
- '_cerber_files', // Cerber Security Plugin
23
- );
24
-
25
- foreach($excludedTables as $excludedTable){
26
- if( false !== strpos($table, $excludedTable) ){
27
- return true;
28
- }
29
- }
30
- return false;
31
- }
 
 
32
 
33
  }
9
  *
10
  * @author IronMan
11
  */
12
+ class thirdPartyCompatibility extends InjectionAware {
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 array
18
+ */
19
+ public function isSearchReplaceExcluded( $table ) {
20
+ $excludedTables = array(
21
+ '_cerber_files', // Cerber Security Plugin
22
+ );
23
+
24
+ $excludedTables = apply_filters( 'wpstg_searchreplace_excl_tables', $excludedTables );
25
+
26
+
27
+ foreach ( $excludedTables as $excludedTable ) {
28
+ if( false !== strpos( $table, $excludedTable ) ) {
29
+ return true;
30
+ }
31
+ }
32
+ return false;
33
+ }
34
 
35
  }
readme.txt CHANGED
@@ -8,8 +8,8 @@ License: GPLv2 or later
8
  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: 5.0
12
- Stable tag: 2.4.9
13
  Requires PHP: 5.3
14
 
15
  A duplicator plugin! Clone, duplicate and migrate live sites to independent staging and development sites that are available only to administrators.
@@ -146,6 +146,16 @@ https://wp-staging.com
146
 
147
  == Changelog ==
148
 
 
 
 
 
 
 
 
 
 
 
149
  = 2.4.9 =
150
  * New: Add new db table selection manager
151
  * Fix: Better warning notices before updating a staging site
@@ -217,23 +227,17 @@ https://wp-staging.com
217
  * Fix: Selected folders are not excluded under Windows IIS server
218
  * Fix: Windows IIS server compatibilility issues resolved
219
 
220
- = 2.3.9 =
221
- * New: Support for wp-config.php located in one level up of the root folder for multisites
222
- * New: Allow exclusion of custom options from wp_options from beeing pushed
223
- * New: Make sure Optimizer is installed and activated
224
- * New: Show date of site creation/update in list of staging sites
225
- * Tweak: Better looking UI elements
226
- * Fix: Requirements Check not working as intended
227
- * Fix: Filesize() failed if file to copy is not a regular file
228
- * Fix: remove ? parameter from staging site
229
-
230
 
231
  Complete changelog: [https://wp-staging.com/wp-staging-changelog](https://wp-staging.com/wp-staging-changelog)
232
 
233
  == Upgrade Notice ==
234
 
235
- = 2.4.9 =
236
- * Fix: Security, prevent downloading wp staging log files by third party users from uploads folder
237
- * New: Compatible up to WordPress 5.0.3 Gutenberg
 
 
 
 
238
 
239
 
8
  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: 5.1
12
+ Stable tag: 2.5.0
13
  Requires PHP: 5.3
14
 
15
  A duplicator plugin! Clone, duplicate and migrate live sites to independent staging and development sites that are available only to administrators.
146
 
147
  == Changelog ==
148
 
149
+ = 2.5.0 =
150
+ * Fix: Do not exclude db.php if it is not located in the wp-content folder
151
+ * Fix: Select All button for db tables not working properly
152
+ * New: Add Filter to exclude certain tables from search & replace operation
153
+ * New: Show PHP user in system info
154
+ * New: Check if there is already one process running before executing the cloning process
155
+ * New: Support up to WordPress 5.1
156
+
157
+
158
+
159
  = 2.4.9 =
160
  * New: Add new db table selection manager
161
  * Fix: Better warning notices before updating a staging site
227
  * Fix: Selected folders are not excluded under Windows IIS server
228
  * Fix: Windows IIS server compatibilility issues resolved
229
 
 
 
 
 
 
 
 
 
 
 
230
 
231
  Complete changelog: [https://wp-staging.com/wp-staging-changelog](https://wp-staging.com/wp-staging-changelog)
232
 
233
  == Upgrade Notice ==
234
 
235
+ = 2.5.0 =
236
+ * Fix: Do not exclude db.php if it is not located in the wp-content folder
237
+ * Fix: Select All button for db tables not working properly
238
+ * New: Add Filter to exclude certain tables from search & replace operation
239
+ * New: Show PHP user in system info
240
+ * New: Check if there is already one process running before executing the cloning process
241
+ * New: Support up to WordPress 5.1
242
 
243
 
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.4.9
11
  * Text Domain: wp-staging
12
  * Domain Path: /languages/
13
 
@@ -51,7 +51,7 @@ if( !defined( 'WPSTG_PLUGIN_URL' ) ) {
51
 
52
  // Version
53
  if( !defined( 'WPSTG_VERSION' ) ) {
54
- define( 'WPSTG_VERSION', '2.4.9' );
55
  }
56
 
57
  // Must use version of the optimizer
@@ -79,9 +79,11 @@ $plugin_requirements = new Wpstg_Requirements_Check( array(
79
  * @param int $seconds
80
  * @return int
81
  */
 
82
  function wpstg_overwrite_nonce( $seconds ) {
83
  return 86400;
84
  }
 
85
 
86
  add_filter( 'nonce_life', 'wpstg_overwrite_nonce', 99999 );
87
 
7
  * Author: WP-Staging
8
  * Author URI: https://wp-staging.com
9
  * Contributors: ReneHermi, ilgityildirim
10
+ * Version: 2.5.0
11
  * Text Domain: wp-staging
12
  * Domain Path: /languages/
13
 
51
 
52
  // Version
53
  if( !defined( 'WPSTG_VERSION' ) ) {
54
+ define( 'WPSTG_VERSION', '2.5.0' );
55
  }
56
 
57
  // Must use version of the optimizer
79
  * @param int $seconds
80
  * @return int
81
  */
82
+ if ( !function_exists( 'wpstgpro_overwrite_nonce')){
83
  function wpstg_overwrite_nonce( $seconds ) {
84
  return 86400;
85
  }
86
+ }
87
 
88
  add_filter( 'nonce_life', 'wpstg_overwrite_nonce', 99999 );
89