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

Version Description

  • New Support for WordPress 5.2.4
  • New: Allow wildcards for excluding files
  • New: Add hook "wpstg_clone_action_staging" to execute code on staging site after cloning
  • Tweak: Improved support for custom uploads folder if user customized UPLOADS constant or upload_path in DB
  • Fix: Better compatibility with Windows IIS server
  • Fix: External links are broken after cloning if ABSPATH is equal to /www/
  • Fix: use an alternative method for file_put_contents as it is not supported on all systems due to file permission issues
  • Fix: Redundant and duplicated update comments in wp-config.php in staging site
Download this release

Release Info

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

Code changes from version 2.6.2 to 2.6.3

apps/Backend/Modules/Jobs/Data.php CHANGED
@@ -75,7 +75,7 @@ class Data extends JobExecutable {
75
* @return void
76
*/
77
protected function calculateTotalSteps() {
78
- $this->options->totalSteps = 18;
79
}
80
81
/**
@@ -219,7 +219,7 @@ class Data extends JobExecutable {
219
}
220
}
221
222
- $this->log( "Preparing Data Step0: Successfull", Logger::TYPE_INFO );
223
return true;
224
}
225
@@ -279,7 +279,7 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
279
280
$content = str_replace( $search, $replace, $content );
281
282
- if( false === @file_put_contents( $source, $content ) ) {
283
$this->log( "Preparing Data: Can't save wp-config.php", Logger::TYPE_ERROR );
284
return false;
285
}
@@ -389,11 +389,6 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
389
return true;
390
}
391
392
- // $result = $this->db->query(
393
- // $this->db->prepare(
394
- // "UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'wpstg_is_staging_site'", "true"
395
- // )
396
- // );
397
$delete = $this->db->query(
398
$this->db->prepare(
399
"DELETE FROM `{$this->prefix}options` WHERE `option_name` = %s;", 'wpstg_is_staging_site'
@@ -505,12 +500,19 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
505
}
506
507
// Replace table prefix
508
- $content = str_replace( '$table_prefix', '$table_prefix = \'' . $this->prefix . '\';//', $content );
509
510
// Replace URLs
511
$content = str_replace( $this->homeUrl, $this->getStagingSiteUrl(), $content );
512
513
- if( false === @file_put_contents( $path, $content ) ) {
514
$this->log( "Preparing Data Step5: Failed to update $table_prefix in {$path} to " . $this->prefix . ". Can't save contents", Logger::TYPE_ERROR );
515
return false;
516
}
@@ -548,11 +550,9 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
548
}
549
$this->log( "Preparing Data: WP installation is in a subdirectory. Progressing..." );
550
551
- $pattern = "/require(.*) dirname(.*) __FILE__ (.*) \. '(.*)wp-blog-header.php'(.*);/";
552
-
553
- $replace = "require( dirname( __FILE__ ) . '/wp-blog-header.php' ); // " . $matches[0];
554
- $replace.= " // Changed by WP-Staging";
555
556
557
558
if( null === ($content = preg_replace( array($pattern), $replace, $content )) ) {
@@ -560,7 +560,7 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
560
return false;
561
}
562
563
- if( false === @file_put_contents( $path, $content ) ) {
564
$this->log( "Preparing Data: Failed to reset index.php for sub directory; can't save contents", Logger::TYPE_ERROR );
565
return false;
566
}
@@ -695,10 +695,10 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
695
if( !empty( $matches[1] ) ) {
696
$matches[1];
697
698
- $pattern = "/define\s*\(\s*['\"]WP_HOME['\"]\s*,\s*(.*)\s*\);/";
699
700
- $replace = "define('WP_HOME','" . $this->getStagingSiteUrl() . "'); // " . $matches[1];
701
- $replace.= " // Changed by WP-Staging";
702
703
if( null === ($content = preg_replace( array($pattern), $replace, $content )) ) {
704
$this->log( "Preparing Data: Failed to update WP_HOME", Logger::TYPE_ERROR );
@@ -708,7 +708,7 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
708
$this->log( "Preparing Data Step10: WP_HOME not defined in wp-config.php. Skipping this step." );
709
}
710
711
- if( false === @file_put_contents( $path, $content ) ) {
712
$this->log( "Preparing Data Step10: Failed to update WP_HOME. Can't save contents", Logger::TYPE_ERROR );
713
return false;
714
}
@@ -737,10 +737,10 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
737
if( !empty( $matches[1] ) ) {
738
$matches[1];
739
740
- $pattern = "/define\s*\(\s*['\"]WP_SITEURL['\"]\s*,\s*(.*)\s*\);/";
741
742
- $replace = "define('WP_SITEURL','" . $this->getStagingSiteUrl() . "'); // " . $matches[1];
743
- $replace.= " // Changed by WP-Staging";
744
745
if( null === ($content = preg_replace( array($pattern), $replace, $content )) ) {
746
$this->log( "Preparing Data Step11: Failed to update WP_SITEURL to " . $this->getStagingSiteUrl(), Logger::TYPE_ERROR );
@@ -751,7 +751,7 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
751
}
752
753
754
- if( false === @file_put_contents( $path, $content ) ) {
755
$this->log( "Preparing Data Step11: Failed to update WP_SITEURL to " . $this->getStagingSiteUrl() . " Can't save contents", Logger::TYPE_ERROR );
756
return false;
757
}
@@ -759,72 +759,6 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
759
return true;
760
}
761
762
- /**
763
- * Set true WP_DEBUG & WP_DEBUG_DISPLAY in wp-config.php
764
- * @return bool
765
- */
766
- // protected function step12() {
767
- // $path = $this->getAbsDestination() . $this->options->cloneDirectoryName . "/wp-config.php";
768
- //
769
- // $this->log( "Preparing Data Step12: Set WP_DEBUG to true in wp-config.php." );
770
- //
771
- // if( false === ($content = file_get_contents( $path )) ) {
772
- // $this->log( "Preparing Data Step12: Failed to update WP_DEBUG in wp-config.php. Can't read wp-config.php", Logger::TYPE_ERROR );
773
- // return false;
774
- // }
775
- //
776
- //
777
- // // Get WP_DEBUG from wp-config.php
778
- // preg_match( "/define\s*\(\s*'WP_DEBUG'\s*,\s*(.*)\s*\);/", $content, $matches );
779
- //
780
- // // Found it!
781
- // if( !empty( $matches[1] ) ) {
782
- // $matches[1];
783
- //
784
- // $pattern = "/define\s*\(\s*'WP_DEBUG'\s*,\s*(.*)\s*\);/";
785
- //
786
- // $replace = "define('WP_DEBUG',true); // " . $matches[1];
787
- // $replace.= " // Changed by WP-Staging";
788
- //
789
- // if( null === ($content = preg_replace( array($pattern), $replace, $content )) ) {
790
- // $this->log( "Preparing Data Step12: Failed to update WP_DEBUG", Logger::TYPE_ERROR );
791
- // return false;
792
- // }
793
- // } else {
794
- // $this->log( "Preparing Data Step12: WP_DEBUG not defined in wp-config.php. Skip it." );
795
- // }
796
- //
797
- //
798
- //
799
- // // Get WP_DEBUG_DISPLAY
800
- // preg_match( "/define\s*\(\s*'WP_DEBUG_DISPLAY'\s*,\s*(.*)\s*\);/", $content, $matches );
801
- //
802
- // // Found it!
803
- // if( !empty( $matches[1] ) ) {
804
- // $matches[1];
805
- //
806
- // $pattern = "/define\s*\(\s*'WP_DEBUG_DISPLAY'\s*,\s*(.*)\s*\);/";
807
- //
808
- // $replace = "define('WP_DEBUG_DISPLAY',true); // " . $matches[1];
809
- // $replace.= " // Changed by WP-Staging";
810
- //
811
- // if( null === ($content = preg_replace( array($pattern), $replace, $content )) ) {
812
- // $this->log( "Preparing Data Step12: Failed to update WP_DEBUG", Logger::TYPE_ERROR );
813
- // return false;
814
- // }
815
- // } else {
816
- // $this->log( "Preparing Data Step12: WP_DEBUG not defined in wp-config.php. Skip it." );
817
- // }
818
- //
819
- //
820
- // if( false === @file_put_contents( $path, $content ) ) {
821
- // $this->log( "Preparing Data Step12: Failed to update WP_DEBUG. Can't save content in wp-config.php", Logger::TYPE_ERROR );
822
- // return false;
823
- // }
824
- // $this->Log( "Preparing Data: Finished Step 12 successfully" );
825
- // return true;
826
- // }
827
-
828
/**
829
* Update Table Prefix in wp_options
830
* @return bool
@@ -903,11 +837,14 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
903
904
$error = !empty( $this->db->last_error ) ? 'Last error: ' . $this->db->last_error : '';
905
906
// $updateOptions = $this->db->query(
907
// $this->db->prepare(
908
// "UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'upload_path'", $newUploadPath
909
// )
910
// );
911
$updateOptions = $this->db->query(
912
$this->db->prepare(
913
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'upload_path'", ""
@@ -942,10 +879,10 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
942
943
if( !empty( $matches[1] ) ) {
944
945
- $pattern = "/define\s*\(\s*['\"]WP_CACHE['\"]\s*,\s*(.*)\s*\);/";
946
947
- $replace = "define('WP_CACHE',false); // " . $matches[1];
948
- $replace.= " // Changed by WP-Staging";
949
950
if( null === ($content = preg_replace( array($pattern), $replace, $content )) ) {
951
$this->log( "Preparing Data: Failed to change WP_CACHE", Logger::TYPE_ERROR );
@@ -955,7 +892,7 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
955
$this->log( "Preparing Data Step14: WP_CACHE not defined in wp-config.php. Skipping this step." );
956
}
957
958
- if( false === @file_put_contents( $path, $content ) ) {
959
$this->log( "Preparing Data Step14: Failed to update WP_CACHE. Can't save contents", Logger::TYPE_ERROR );
960
return false;
961
}
@@ -995,7 +932,7 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
995
$this->log( "Preparing Data Step15: WP_CONTENT_DIR not defined in wp-config.php. Skipping this step." );
996
}
997
998
- if( false === @file_put_contents( $path, $content ) ) {
999
$this->log( "Preparing Data Step15: Failed to update WP_CONTENT_DIR. Can't save contents", Logger::TYPE_ERROR );
1000
return false;
1001
}
@@ -1035,7 +972,7 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
1035
$this->log( "Preparing Data Step16: WP_CONTENT_URL not defined in wp-config.php. Skipping this step." );
1036
}
1037
1038
- if( false === @file_put_contents( $path, $content ) ) {
1039
$this->log( "Preparing Data Step16: Failed to update WP_CONTENT_URL. Can't save contents", Logger::TYPE_ERROR );
1040
return false;
1041
}
@@ -1043,46 +980,6 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
1043
return true;
1044
}
1045
1046
- /**
1047
- * Remove UPLOADS constant in wp-config.php to reset default image folder
1048
- * @return bool
1049
- */
1050
- // protected function step17() {
1051
- // $path = $this->options->destinationDir . "wp-config.php";
1052
- //
1053
- // $this->log( "Preparing Data Step17: Remove UPLOADS in wp-config.php" );
1054
- //
1055
- // if( false === ($content = file_get_contents( $path )) ) {
1056
- // $this->log( "Preparing Data Step17: Failed to get UPLOADS in wp-config.php. Can't read wp-config.php", Logger::TYPE_ERROR );
1057
- // return false;
1058
- // }
1059
- //
1060
- //
1061
- // // Get UPLOADS from wp-config.php
1062
- // preg_match( "/define\s*\(\s*['\"]UPLOADS['\"]\s*,\s*(.*)\s*\);/", $content, $matches );
1063
- //
1064
- // if( !empty( $matches[0] ) ) {
1065
- //
1066
- // $pattern = "/define\s*\(\s*'UPLOADS'\s*,\s*(.*)\s*\);/";
1067
- //
1068
- // $replace = "";
1069
- //
1070
- // if( null === ($content = preg_replace( array($pattern), $replace, $content )) ) {
1071
- // $this->log( "Preparing Data: Failed to change UPLOADS", Logger::TYPE_ERROR );
1072
- // return false;
1073
- // }
1074
- // } else {
1075
- // $this->log( "Preparing Data Step17: UPLOADS not defined in wp-config.php. Skipping this step." );
1076
- // }
1077
- //
1078
- // if( false === @file_put_contents( $path, $content ) ) {
1079
- // $this->log( "Preparing Data Step17: Failed to update UPLOADS. Can't save contents", Logger::TYPE_ERROR );
1080
- // return false;
1081
- // }
1082
- // $this->Log( "Preparing Data Step17: Finished successfully" );
1083
- // return true;
1084
- // }
1085
-
1086
/**
1087
* Add UPLOADS constant in wp-config.php or change it to correct destination.
1088
* This is important when a custom uploads folder is used
@@ -1100,6 +997,7 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
1100
$uploadFolder = wpstg_get_rel_upload_dir();
1101
if( !empty( $matches[0] ) ) {
1102
$pattern = "/define\s*\(\s*'UPLOADS'\s*,\s*(.*)\s*\);/";
1103
$replace = "define('UPLOADS', '" . $uploadFolder . "');";
1104
if( null === ($content = preg_replace( array($pattern), $replace, $content )) ) {
1105
$this->log( "Preparing Data Step17: Failed to change UPLOADS", Logger::TYPE_ERROR );
@@ -1122,7 +1020,7 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
1122
$this->log( "Preparing Data Step 17: Can not add UPLOAD constant to wp-config.php. Can not find free position to add it.", Logger::TYPE_ERROR );
1123
}
1124
}
1125
- if( false === @file_put_contents( $path, $content ) ) {
1126
$this->log( "Preparing Data Step17: Failed to update UPLOADS. Can't save contents", Logger::TYPE_ERROR );
1127
return false;
1128
}
@@ -1131,49 +1029,131 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
1131
}
1132
1133
/**
1134
- * Empty wpstg_existing_clones_beta on the staging site
1135
* @return bool
1136
*/
1137
- // protected function step18() {
1138
- //
1139
- // $this->log( "Preparing Data Step18: Clean up list of staging sites" );
1140
//
1141
// if( false === $this->isTable( $this->prefix . 'options' ) ) {
1142
// return true;
1143
// }
1144
//
1145
// // Skip - Table is not selected or updated
1146
// if( !in_array( $this->prefix . 'options', $this->tables ) ) {
1147
- // $this->log( "Preparing Data Step18: Skipping" );
1148
// return true;
1149
// }
1150
//
1151
- // $result = $this->db->query(
1152
- // $this->db->prepare(
1153
- // "UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'wpstg_existing_clones_beta'", 'a:0:{}'
1154
- // )
1155
// );
1156
//
1157
- // // All good
1158
- // if( false === $result ) {
1159
- // $this->log( "Preparing Data Step18: Can not update listing of staging sites.", Logger::TYPE_WARNING );
1160
- // return true;
1161
// }
1162
//
1163
- // $this->Log( "Preparing Data Step18: Finished successfully" );
1164
// return true;
1165
// }
1166
1167
/**
1168
- * Create a robots.txt in path of the staging site
1169
*/
1170
- // protected function step18() {
1171
- // $file = new RobotsTxt();
1172
- // if( false === $file->create( $this->options->destinationDir . "robots.txt" ) ) {
1173
- // $this->log( "Preparing Data Step18: Failed to create robots.txt", Logger::TYPE_ERROR );
1174
- // }
1175
- // return true;
1176
- // }
1177
1178
/**
1179
* Change upload path of staging site if it has been customized on production site
@@ -1200,7 +1180,7 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
1200
return false;
1201
}
1202
1203
- $customSlug = str_replace( \WPStaging\WPStaging::getWPpath(), '', $uploadPath );
1204
1205
$newUploadPath = $this->options->destinationDir . $customSlug;
1206
75
* @return void
76
*/
77
protected function calculateTotalSteps() {
78
+ $this->options->totalSteps = 19;
79
}
80
81
/**
219
}
220
}
221
222
+ $this->log( "Preparing Data Step0: Successful", Logger::TYPE_INFO );
223
return true;
224
}
225
279
280
$content = str_replace( $search, $replace, $content );
281
282
+ if( false === @wpstg_put_contents( $source, $content ) ) {
283
$this->log( "Preparing Data: Can't save wp-config.php", Logger::TYPE_ERROR );
284
return false;
285
}
389
return true;
390
}
391
392
$delete = $this->db->query(
393
$this->db->prepare(
394
"DELETE FROM `{$this->prefix}options` WHERE `option_name` = %s;", 'wpstg_is_staging_site'
500
}
501
502
// Replace table prefix
503
+ $pattern = '/\$table_prefix\s*=\s*(.*)/';
504
+ $replacement = '$table_prefix = \'' . $this->prefix . '\'; // Changed by WP Staging';
505
+ $content = preg_replace( $pattern, $replacement, $content );
506
+
507
+ if( null === $content ) {
508
+ $this->log( "Preparing Data Step5: Failed to update table_prefix in {$path}. Can't read contents", Logger::TYPE_ERROR );
509
+ return false;
510
+ }
511
512
// Replace URLs
513
$content = str_replace( $this->homeUrl, $this->getStagingSiteUrl(), $content );
514
515
+ if( false === @wpstg_put_contents( $path, $content ) ) {
516
$this->log( "Preparing Data Step5: Failed to update $table_prefix in {$path} to " . $this->prefix . ". Can't save contents", Logger::TYPE_ERROR );
517
return false;
518
}
550
}
551
$this->log( "Preparing Data: WP installation is in a subdirectory. Progressing..." );
552
553
+ $pattern = "/require(.*) dirname(.*) __FILE__ (.*) \. '(.*)wp-blog-header.php'(.*);.*/";
554
555
+ $replace = "require( dirname( __FILE__ ) . '/wp-blog-header.php' ); // " . $matches[0] . " Changed by WP-Staging";
556
557
558
if( null === ($content = preg_replace( array($pattern), $replace, $content )) ) {
560
return false;
561
}
562
563
+ if( false === @wpstg_put_contents( $path, $content ) ) {
564
$this->log( "Preparing Data: Failed to reset index.php for sub directory; can't save contents", Logger::TYPE_ERROR );
565
return false;
566
}
695
if( !empty( $matches[1] ) ) {
696
$matches[1];
697
698
+ $pattern = "/define\s*\(\s*['\"]WP_HOME['\"]\s*,\s*(.*)\s*\);.*/";
699
700
+ $replace = "define('WP_HOME','" . $this->getStagingSiteUrl() . "'); // " . $matches[1] . " Changed by WP-Staging";
701
+ //$replace.= " // Changed by WP-Staging";
702
703
if( null === ($content = preg_replace( array($pattern), $replace, $content )) ) {
704
$this->log( "Preparing Data: Failed to update WP_HOME", Logger::TYPE_ERROR );
708
$this->log( "Preparing Data Step10: WP_HOME not defined in wp-config.php. Skipping this step." );
709
}
710
711
+ if( false === @wpstg_put_contents( $path, $content ) ) {
712
$this->log( "Preparing Data Step10: Failed to update WP_HOME. Can't save contents", Logger::TYPE_ERROR );
713
return false;
714
}
737
if( !empty( $matches[1] ) ) {
738
$matches[1];
739
740
+ $pattern = "/define\s*\(\s*['\"]WP_SITEURL['\"]\s*,\s*(.*)\s*\);.*/";
741
742
+ $replace = "define('WP_SITEURL','" . $this->getStagingSiteUrl() . "'); // " . $matches[1] . " Changed by WP-Staging";
743
+ //$replace.= " // Changed by WP-Staging";
744
745
if( null === ($content = preg_replace( array($pattern), $replace, $content )) ) {
746
$this->log( "Preparing Data Step11: Failed to update WP_SITEURL to " . $this->getStagingSiteUrl(), Logger::TYPE_ERROR );
751
}
752
753
754
+ if( false === @wpstg_put_contents( $path, $content ) ) {
755
$this->log( "Preparing Data Step11: Failed to update WP_SITEURL to " . $this->getStagingSiteUrl() . " Can't save contents", Logger::TYPE_ERROR );
756
return false;
757
}
759
return true;
760
}
761
762
/**
763
* Update Table Prefix in wp_options
764
* @return bool
837
838
$error = !empty( $this->db->last_error ) ? 'Last error: ' . $this->db->last_error : '';
839
840
+ $this->log( "Updating upload_path in {$this->prefix}options. {$error}" );
841
+
842
// $updateOptions = $this->db->query(
843
// $this->db->prepare(
844
// "UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'upload_path'", $newUploadPath
845
// )
846
// );
847
+ // remove upload_path value and use UPLOADS constant instead. (upload_path is deprecated and should not be used any longer)
848
$updateOptions = $this->db->query(
849
$this->db->prepare(
850
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'upload_path'", ""
879
880
if( !empty( $matches[1] ) ) {
881
882
+ $pattern = "/define\s*\(\s*['\"]WP_CACHE['\"]\s*,\s*(.*)\s*\);.*/";
883
884
+ $replace = "define('WP_CACHE',false); // " . $matches[1] . " Changed by WP-Staging";
885
+ //$replace.= " // Changed by WP-Staging";
886
887
if( null === ($content = preg_replace( array($pattern), $replace, $content )) ) {
888
$this->log( "Preparing Data: Failed to change WP_CACHE", Logger::TYPE_ERROR );
892
$this->log( "Preparing Data Step14: WP_CACHE not defined in wp-config.php. Skipping this step." );
893
}
894
895
+ if( false === @wpstg_put_contents( $path, $content ) ) {
896
$this->log( "Preparing Data Step14: Failed to update WP_CACHE. Can't save contents", Logger::TYPE_ERROR );
897
return false;
898
}
932
$this->log( "Preparing Data Step15: WP_CONTENT_DIR not defined in wp-config.php. Skipping this step." );
933
}
934
935
+ if( false === @wpstg_put_contents( $path, $content ) ) {
936
$this->log( "Preparing Data Step15: Failed to update WP_CONTENT_DIR. Can't save contents", Logger::TYPE_ERROR );
937
return false;
938
}
972
$this->log( "Preparing Data Step16: WP_CONTENT_URL not defined in wp-config.php. Skipping this step." );
973
}
974
975
+ if( false === @wpstg_put_contents( $path, $content ) ) {
976
$this->log( "Preparing Data Step16: Failed to update WP_CONTENT_URL. Can't save contents", Logger::TYPE_ERROR );
977
return false;
978
}
980
return true;
981
}
982
983
/**
984
* Add UPLOADS constant in wp-config.php or change it to correct destination.
985
* This is important when a custom uploads folder is used
997
$uploadFolder = wpstg_get_rel_upload_dir();
998
if( !empty( $matches[0] ) ) {
999
$pattern = "/define\s*\(\s*'UPLOADS'\s*,\s*(.*)\s*\);/";
1000
+
1001
$replace = "define('UPLOADS', '" . $uploadFolder . "');";
1002
if( null === ($content = preg_replace( array($pattern), $replace, $content )) ) {
1003
$this->log( "Preparing Data Step17: Failed to change UPLOADS", Logger::TYPE_ERROR );
1020
$this->log( "Preparing Data Step 17: Can not add UPLOAD constant to wp-config.php. Can not find free position to add it.", Logger::TYPE_ERROR );
1021
}
1022
}
1023
+ if( false === @wpstg_put_contents( $path, $content ) ) {
1024
$this->log( "Preparing Data Step17: Failed to update UPLOADS. Can't save contents", Logger::TYPE_ERROR );
1025
return false;
1026
}
1029
}
1030
1031
/**
1032
+ * Save hostname of parent production site in option_name wpstg_connection
1033
+ * @return boolean
1034
+ */
1035
+ protected function step18() {
1036
+
1037
+ $table = $this->prefix . 'options';
1038
+
1039
+ $siteurl = get_site_url();
1040
+
1041
+ $connection = json_encode( array('prodHostname' => $siteurl) );
1042
+
1043
+ $data = array(
1044
+ 'option_name' => 'wpstg_connection',
1045
+ 'option_value' => $connection
1046
+ );
1047
+
1048
+ $format = array('%s', '%s');
1049
+
1050
+ $result = $this->db->replace( $table, $data, $format );
1051
+
1052
+ if( false === $result ) {
1053
+ $this->Log( "Preparing Data Step18: Could not save {$siteurl} in {$table}", Logger::TYPE_ERROR );
1054
+ }
1055
+ return true;
1056
+ }
1057
+
1058
+ /**
1059
+ * Add option_name wpstg_execute and set it to true
1060
+ * This option is used to determine if the staging website has not been loaded initiall for executing certain custom actions from \WPStaging\initActions()
1061
+ * @return boolean
1062
+ */
1063
+ protected function step19() {
1064
+
1065
+ $table = $this->prefix . 'options';
1066
+
1067
+ // Skip - Table does not exist
1068
+ if( false === $this->isTable( $table ) ) {
1069
+ return true;
1070
+ }
1071
+
1072
+
1073
+ $result = $this->db->query(
1074
+ $this->db->prepare(
1075
+ "INSERT INTO {$this->prefix}options (option_name,option_value) VALUES ('wpstg_execute',%s) ON DUPLICATE KEY UPDATE option_value = %s", "true", "true"
1076
+ )
1077
+ );
1078
+
1079
+ if( false === $result ) {
1080
+ $this->Log( "Preparing Data Step19: Could not save wpstg_execute in {$table}", Logger::TYPE_ERROR );
1081
+ }
1082
+ return true;
1083
+ }
1084
+
1085
+ /**
1086
+ * Preserve data and prevents data in wp_options from beeing cloned to staging site
1087
* @return bool
1088
*/
1089
+ // protected function step20() {
1090
+ // $this->log( "Preparing Data Step20: Preserve Data in " . $this->prefix . "options" );
1091
//
1092
+ // // Skip - Table does not exist
1093
// if( false === $this->isTable( $this->prefix . 'options' ) ) {
1094
// return true;
1095
// }
1096
//
1097
// // Skip - Table is not selected or updated
1098
// if( !in_array( $this->prefix . 'options', $this->tables ) ) {
1099
+ // $this->log( "Preparing Data Step20: Skipped" );
1100
// return true;
1101
// }
1102
//
1103
+ // $sql = '';
1104
+ //
1105
+ // $preserved_option_names = array('wpstg_existing_clones_beta');
1106
+ //
1107
+ // $preserved_option_names = apply_filters( 'wpstg_preserved_options_cloning', $preserved_option_names );
1108
+ // $preserved_options_escaped = esc_sql( $preserved_option_names );
1109
+ //
1110
+ // $preserved_options_data = array();
1111
+ //
1112
+ // // Get preserved data in wp_options tables
1113
+ // $table = $this->db->prefix . 'options';
1114
+ // $preserved_options_data[$this->prefix . 'options'] = $this->db->get_results(
1115
+ // sprintf(
1116
+ // "SELECT * FROM `{$table}` WHERE `option_name` IN ('%s')", implode( "','", $preserved_options_escaped )
1117
+ // ), ARRAY_A
1118
// );
1119
//
1120
+ // // Create preserved data queries for options tables
1121
+ // foreach ( $preserved_options_data as $key => $value ) {
1122
+ // if( false === empty( $value ) ) {
1123
+ // foreach ( $value as $option ) {
1124
+ // $sql .= $this->db->prepare(
1125
+ // "DELETE FROM `{$key}` WHERE `option_name` = %s;\n", $option['option_name']
1126
+ // );
1127
+ //
1128
+ // $sql .= $this->db->prepare(
1129
+ // "INSERT INTO `{$key}` ( `option_id`, `option_name`, `option_value`, `autoload` ) VALUES ( NULL , %s, %s, %s );\n", $option['option_name'], $option['option_value'], $option['autoload']
1130
+ // );
1131
+ // }
1132
+ // }
1133
// }
1134
//
1135
+ // $this->debugLog( "Preparing Data Step20: Preserve values " . json_encode( $preserved_options_data ), Logger::TYPE_INFO );
1136
+ //
1137
+ // $this->executeSql( $sql );
1138
+ //
1139
+ // $this->log( "Preparing Data Step20: Successful!" );
1140
// return true;
1141
// }
1142
1143
/**
1144
+ * Execute a batch of sql queries
1145
+ * @param string $sqlbatch
1146
*/
1147
+ private function executeSql( $sqlbatch ) {
1148
+ $queries = array_filter( explode( ";\n", $sqlbatch ) );
1149
+
1150
+ foreach ( $queries as $query ) {
1151
+ if( false === $this->db->query( $query ) ) {
1152
+ $this->log( "Data Crunching Warning: Can not execute query {$query}", Logger::TYPE_WARNING );
1153
+ }
1154
+ }
1155
+ return true;
1156
+ }
1157
1158
/**
1159
* Change upload path of staging site if it has been customized on production site
1180
return false;
1181
}
1182
1183
+ $customSlug = str_replace( wpstg_replace_windows_directory_separator( \WPStaging\WPStaging::getWPpath() ), '', wpstg_replace_windows_directory_separator( $uploadPath ) );
1184
1185
$newUploadPath = $this->options->destinationDir . $customSlug;
1186
apps/Backend/Modules/Jobs/Directories.php CHANGED
@@ -164,7 +164,8 @@ class Directories extends JobExecutable {
164
foreach ( $iterator as $item ) {
165
if( $item->isFile() ) {
166
$wpContentDir = str_replace( ABSPATH, '', WP_CONTENT_DIR );
167
- if( $this->write( $files, $wpContentDir . '/' . $iterator->getSubPathName() . PHP_EOL ) ) {
168
$this->options->totalFiles++;
169
170
// Too much cpu time
@@ -315,7 +316,7 @@ class Directories extends JobExecutable {
315
foreach ( $iterator as $item ) {
316
if( $item->isFile() ) {
317
//if( $this->write( $files, $strings->getLastElemAfterString( '/', $folder ) . DIRECTORY_SEPARATOR . $iterator->getSubPathName() . PHP_EOL ) ) {
318
- if( $this->write( $files, str_replace( \WPStaging\WPStaging::getWPpath(), '', $folder ) . DIRECTORY_SEPARATOR . $iterator->getSubPathName() . PHP_EOL ) ) {
319
$this->options->totalFiles++;
320
// Too much cpu time
321
//$this->options->totalFileSize += $iterator->getSize();
164
foreach ( $iterator as $item ) {
165
if( $item->isFile() ) {
166
$wpContentDir = str_replace( ABSPATH, '', WP_CONTENT_DIR );
167
+ $file = $wpContentDir . '/' . $iterator->getSubPathName() . PHP_EOL;
168
+ if( $this->write( $files, $file ) ) {
169
$this->options->totalFiles++;
170
171
// Too much cpu time
316
foreach ( $iterator as $item ) {
317
if( $item->isFile() ) {
318
//if( $this->write( $files, $strings->getLastElemAfterString( '/', $folder ) . DIRECTORY_SEPARATOR . $iterator->getSubPathName() . PHP_EOL ) ) {
319
+ if( $this->write( $files, str_replace( wpstg_replace_windows_directory_separator(\WPStaging\WPStaging::getWPpath()), '', $folder ) . DIRECTORY_SEPARATOR . $iterator->getSubPathName() . PHP_EOL ) ) {
320
$this->options->totalFiles++;
321
// Too much cpu time
322
//$this->options->totalFileSize += $iterator->getSize();
apps/Backend/Modules/Jobs/Files.php CHANGED
@@ -135,9 +135,7 @@ class Files extends JobExecutable {
135
136
$file = $this->file->fgets();
137
138
- // if( false !== strpos( $file, 'index.php' ) ) {
139
- // $test = $file;
140
- // }
141
$this->copyFile( $file );
142
}
143
@@ -172,6 +170,8 @@ class Files extends JobExecutable {
172
173
$file = trim( \WPStaging\WPStaging::getWPpath() . $file );
174
175
$directory = dirname( $file );
176
177
// Directory is excluded
@@ -224,9 +224,6 @@ class Files extends JobExecutable {
224
return $this->copyBig( $file, $destination, $this->settings->batchSize );
225
}
226
227
- $this->debugLog( "Try to copy: {$file} to {$destination}", Logger::TYPE_INFO );
228
-
229
-
230
// Attempt to copy
231
if( !@copy( $file, $destination ) ) {
232
$errors = error_get_last();
@@ -242,34 +239,6 @@ class Files extends JobExecutable {
242
return true;
243
}
244
245
- /**
246
- * Get wp-content and wp-content/uploads destination dir
247
- * Necessary if these folders were customized and changed from the default ones.
248
- *
249
- * @return string
250
- */
251
- // protected function getWpContentPath( $file ) {
252
- // // Get absolute custom upload dir
253
- // $uploads = wp_upload_dir();
254
- //
255
- // // Get absolute upload dir from ABSPATH
256
- // $uploadsAbsPath = trailingslashit( $uploads['basedir'] );
257
- //
258
- // // Get absolute custom wp-content dir
259
- // $wpContentDir = trailingslashit( WP_CONTENT_DIR );
260
- //
261
- // // Check if there is a custom upload directory and do a search $ replace
262
- // $file = str_replace( $uploadsAbsPath, ABSPATH . 'wp-content/uploads/', $file, $count );
263
- //
264
- // // If there is no custom upload directory do a search & replace of the custom wp-content directory
265
- // if( empty( $count ) || $count === 0 ) {
266
- // $file = str_replace( $wpContentDir, ABSPATH . 'wp-content/', $file );
267
- // }
268
- //
269
- //
270
- // return $file;
271
- // }
272
-
273
/**
274
* Get wp-content and wp-content/uploads destination dir
275
* Necessary if these folders were customized and changed from the default ones.
@@ -278,7 +247,7 @@ class Files extends JobExecutable {
278
*/
279
protected function getWpContentPath( $file ) {
280
// Get upload directory information
281
- $uploads = wp_upload_dir();
282
283
// Get absolute path to wordpress uploads directory e.g srv/www/htdocs/sitename/wp-content/uploads
284
$uploadsAbsPath = trailingslashit( $uploads['basedir'] );
@@ -287,7 +256,7 @@ class Files extends JobExecutable {
287
$uploadsRelPath = wpstg_get_rel_upload_dir();
288
289
// Get absolute path to wp-content directory e.g srv/www/htdocs/sitename/wp-content
290
- $wpContentDir = trailingslashit( WP_CONTENT_DIR );
291
292
// Check if there is a custom uploads directory, then do a search $ replace. Do this only if custom upload path is not identical to WP_CONTENT_DIR
293
if( $uploadsAbsPath != $wpContentDir ) {
@@ -299,6 +268,8 @@ class Files extends JobExecutable {
299
//$file = str_replace( $wpContentDir, ABSPATH . 'wp-content/', $file );
300
$file = str_replace( $wpContentDir, ABSPATH . 'wp-content/', $file );
301
}
302
return $file;
303
}
304
@@ -322,15 +293,11 @@ class Files extends JobExecutable {
322
* @return bool|string
323
*/
324
private function getDestination( $file ) {
325
-
326
- // Get custom wp-content and uploads folder
327
- $file = $this->getWpContentPath( $file );
328
-
329
- // remove ABSPATH and get last part of the path
330
- $relativePath = str_replace( \WPStaging\WPStaging::getWPpath(), null, $file );
331
- // add destination path
332
$destinationPath = $this->destination . $relativePath;
333
- // get folder
334
$destinationDirectory = dirname( $destinationPath );
335
336
if( !is_dir( $destinationDirectory ) && !@mkdir( $destinationDirectory, wpstg_get_permissions_for_directory(), true ) ) {
@@ -382,11 +349,31 @@ class Files extends JobExecutable {
382
* @return boolean
383
*/
384
private function isFileExcluded( $file ) {
385
// If file name exists
386
- if( in_array( basename( $file ), $this->options->excludedFiles ) ) {
387
return true;
388
}
389
390
// Do not copy wp-config.php if the clone gets updated. This is for security purposes,
391
// because if the updating process fails, the staging site would not be accessable any longer
392
if( isset( $this->options->mainJob ) && $this->options->mainJob == "updating" && stripos( strrev( $file ), strrev( "wp-config.php" ) ) === 0 ) {
@@ -397,6 +384,41 @@ class Files extends JobExecutable {
397
return false;
398
}
399
400
/**
401
* Check if certain file is excluded from copying process
402
*
@@ -422,10 +444,6 @@ class Files extends JobExecutable {
422
* @return string
423
*/
424
private function sanitizeDirectorySeparator( $path ) {
425
- //$string = str_replace( '\\', '/', $path );
426
- //$string = str_replace( "/", "\\", $path );
427
- //return str_replace( '\\\\', '\\', $string );
428
- //return preg_replace( '/[\\\\]+/', '\\\\\\\\', $string );
429
return preg_replace( '/[\\\\]+/', '/', $path );
430
}
431
135
136
$file = $this->file->fgets();
137
138
+
139
$this->copyFile( $file );
140
}
141
170
171
$file = trim( \WPStaging\WPStaging::getWPpath() . $file );
172
173
+ $file = wpstg_replace_windows_directory_separator($file);
174
+
175
$directory = dirname( $file );
176
177
// Directory is excluded
224
return $this->copyBig( $file, $destination, $this->settings->batchSize );
225
}
226
227
// Attempt to copy
228
if( !@copy( $file, $destination ) ) {
229
$errors = error_get_last();
239
return true;
240
}
241
242
/**
243
* Get wp-content and wp-content/uploads destination dir
244
* Necessary if these folders were customized and changed from the default ones.
247
*/
248
protected function getWpContentPath( $file ) {
249
// Get upload directory information
250
+ $uploads = wp_upload_dir();
251
252
// Get absolute path to wordpress uploads directory e.g srv/www/htdocs/sitename/wp-content/uploads
253
$uploadsAbsPath = trailingslashit( $uploads['basedir'] );
256
$uploadsRelPath = wpstg_get_rel_upload_dir();
257
258
// Get absolute path to wp-content directory e.g srv/www/htdocs/sitename/wp-content
259
+ $wpContentDir = trailingslashit( WP_CONTENT_DIR );
260
261
// Check if there is a custom uploads directory, then do a search $ replace. Do this only if custom upload path is not identical to WP_CONTENT_DIR
262
if( $uploadsAbsPath != $wpContentDir ) {
268
//$file = str_replace( $wpContentDir, ABSPATH . 'wp-content/', $file );
269
$file = str_replace( $wpContentDir, ABSPATH . 'wp-content/', $file );
270
}
271
+
272
+
273
return $file;
274
}
275
293
* @return bool|string
294
*/
295
private function getDestination( $file ) {
296
+ //$file = $this->getMultisiteUploadFolder( $file );
297
+ $file = wpstg_replace_windows_directory_separator($file);
298
+ $rootPath = wpstg_replace_windows_directory_separator(\WPStaging\WPStaging::getWPpath());
299
+ $relativePath = str_replace( $rootPath, null, $file );
300
$destinationPath = $this->destination . $relativePath;
301
$destinationDirectory = dirname( $destinationPath );
302
303
if( !is_dir( $destinationDirectory ) && !@mkdir( $destinationDirectory, wpstg_get_permissions_for_directory(), true ) ) {
349
* @return boolean
350
*/
351
private function isFileExcluded( $file ) {
352
+
353
+ $excludedFiles = ( array ) $this->options->excludedFiles;
354
+
355
+ $basenameFile = basename( $file );
356
+
357
+
358
+ // Remove .htaccess and web.config from array excludedFiles if staging site is copied to a subdomain
359
+ //if( $this->isCustomDirectory() ) {
360
+ if( false === $this->isIdenticalHostname() ) {
361
+ $excludedFiles = \array_diff( $excludedFiles, array("web.config", ".htaccess") );
362
+ }
363
+
364
+
365
// If file name exists
366
+ if( in_array( $basenameFile, $excludedFiles ) ) {
367
return true;
368
}
369
370
+ // Check for wildcards
371
+ foreach ($excludedFiles as $pattern){
372
+ if(fnmatch($pattern, $basenameFile)){
373
+ return true;
374
+ }
375
+ }
376
+
377
// Do not copy wp-config.php if the clone gets updated. This is for security purposes,
378
// because if the updating process fails, the staging site would not be accessable any longer
379
if( isset( $this->options->mainJob ) && $this->options->mainJob == "updating" && stripos( strrev( $file ), strrev( "wp-config.php" ) ) === 0 ) {
384
return false;
385
}
386
387
+ /**
388
+ * Check if custom target directory is used
389
+ * @return boolean
390
+ */
391
+ // private function isCustomDirectory() {
392
+ //
393
+ // if( empty( $this->options->cloneDir ) ) {
394
+ // return false;
395
+ // }
396
+ // return true;
397
+ // }
398
+
399
+ /**
400
+ * Check if production and staging hostname are identical
401
+ * If they are not identical we assume website is cloned to a subdomain and not into a subfolder
402
+ * @return boolean
403
+ */
404
+ private function isIdenticalHostname() {
405
+ // hostname of production site without scheme
406
+ $siteurl = get_site_url();
407
+ $url = parse_url( $siteurl );
408
+ $productionHostname = $url['host'];
409
+
410
+ // hostname of staging site without scheme
411
+ $cloneUrl = empty($this->options->cloneHostname) ? $url : parse_url( $this->options->cloneHostname );
412
+ $targetHostname = $cloneUrl['host'];
413
+
414
+ // Check if target hostname beginns with the production hostname
415
+ // Only compare the hostname without path
416
+ if( wpstg_starts_with( $productionHostname, $targetHostname ) ) {
417
+ return true;
418
+ }
419
+ return false;
420
+ }
421
+
422
/**
423
* Check if certain file is excluded from copying process
424
*
444
* @return string
445
*/
446
private function sanitizeDirectorySeparator( $path ) {
447
return preg_replace( '/[\\\\]+/', '/', $path );
448
}
449
apps/Backend/Modules/Jobs/Multisite/Data.php CHANGED
@@ -40,9 +40,12 @@ class Data extends JobExecutable {
40
* Initialize
41
*/
42
public function initialize() {
43
- $this->db = WPStaging::getInstance()->get( "wpdb" );
44
$this->prefix = $this->options->prefix;
45
$this->getTables();
46
// Fix current step
47
if( 0 == $this->options->currentStep ) {
48
$this->options->currentStep = 0;
@@ -68,7 +71,7 @@ class Data extends JobExecutable {
68
* @return void
69
*/
70
protected function calculateTotalSteps() {
71
- $this->options->totalSteps = 18;
72
}
73
74
/**
@@ -78,8 +81,10 @@ class Data extends JobExecutable {
78
public function start() {
79
// Execute steps
80
$this->run();
81
// Save option, progress
82
$this->saveOptions();
83
return ( object ) $this->response;
84
}
85
@@ -93,6 +98,7 @@ class Data extends JobExecutable {
93
if( $this->isRoot() ) {
94
return false;
95
}
96
// Over limits threshold
97
if( $this->isOverThreshold() ) {
98
// Prepare response and save current progress
@@ -100,19 +106,23 @@ class Data extends JobExecutable {
100
$this->saveOptions();
101
return false;
102
}
103
// No more steps, finished
104
if( $this->isFinished() ) {
105
$this->prepareResponse( true, false );
106
return false;
107
}
108
// Execute step
109
$stepMethodName = "step" . $this->options->currentStep;
110
if( !$this->{$stepMethodName}() ) {
111
$this->prepareResponse( false, false );
112
return false;
113
}
114
// Prepare Response
115
$this->prepareResponse();
116
// Not finished
117
return true;
118
}
@@ -134,20 +144,24 @@ class Data extends JobExecutable {
134
* @return boolean
135
*/
136
protected function isRoot() {
137
// Prefix is the same as the one of live site
138
//$wpdb = WPStaging::getInstance()->get( "wpdb" );
139
if( $this->db->prefix === $this->prefix ) {
140
return true;
141
}
142
// CloneName is empty
143
$name = ( array ) $this->options->cloneDirectoryName;
144
if( empty( $name ) ) {
145
return true;
146
}
147
// Live domain === Staging domain
148
if( $this->multisiteHomeDomain . $this->options->cloneDirectoryName === $this->multisiteHomeDomain ) {
149
return true;
150
}
151
return false;
152
}
153
@@ -171,14 +185,19 @@ class Data extends JobExecutable {
171
*/
172
protected function step0() {
173
$this->log( "Preparing Data Step0: Copy wp-config.php file", Logger::TYPE_INFO );
174
- $dir = trailingslashit( dirname( ABSPATH ) );
175
- $source = $dir . 'wp-config.php';
176
$destination = $this->options->destinationDir . 'wp-config.php';
177
// Check if there is already a valid wp-config.php in root of staging site
178
if( $this->isValidWpConfig( $destination ) ) {
179
$this->log( "Preparing Data Step0: Found wp-config.php file in folder {$destination}", Logger::TYPE_INFO );
180
return true;
181
}
182
// Check if there is a valid wp-config.php outside root of wp production site
183
if( $this->isValidWpConfig( $source ) ) {
184
// Copy it to staging site
@@ -187,9 +206,12 @@ class Data extends JobExecutable {
187
return true;
188
}
189
}
190
// No valid wp-config.php found so let's copy wp stagings default wp-config.php to staging site
191
$source = WPSTG_PLUGIN_DIR . "apps/Backend/helpers/wp-config.php";
192
$this->log( "Preparing Data Step0: Copy default wp-config.php file from source {$source} to {$destination}", Logger::TYPE_INFO );
193
if( $this->copy( $source, $destination ) ) {
194
// add missing db credentials to wp-config.php
195
if( !$this->alterWpConfig( $destination ) ) {
@@ -197,6 +219,7 @@ class Data extends JobExecutable {
197
return false;
198
}
199
}
200
$this->log( "Preparing Data Step0: Successful", Logger::TYPE_INFO );
201
return true;
202
}
@@ -217,12 +240,14 @@ class Data extends JobExecutable {
217
return false;
218
}
219
}
220
// Copy file
221
if( !@copy( $source, $destination ) ) {
222
$errors = error_get_last();
223
$this->log( "Preparing Data Step0: Failed to copy {$source}! Error: {$errors['message']} {$source} -> {$destination}", Logger::TYPE_ERROR );
224
return false;
225
}
226
return true;
227
}
228
@@ -232,12 +257,16 @@ class Data extends JobExecutable {
232
* @return boolean
233
*/
234
protected function alterWpConfig( $source ) {
235
- $this->log( "Preparing Data: Alter wp-config.php", Logger::TYPE_ERROR );
236
$content = file_get_contents( $source );
237
if( false === ($content = file_get_contents( $source )) ) {
238
return false;
239
}
240
- $search = "// ** MySQL settings ** //";
241
$replace = "// ** MySQL settings ** //\r\n
242
define( 'DB_NAME', '" . DB_NAME . "' );\r\n
243
/** MySQL database username */\r\n
@@ -250,11 +279,14 @@ define( 'DB_HOST', '" . DB_HOST . "' );\r\n
250
define( 'DB_CHARSET', '" . DB_CHARSET . "' );\r\n
251
/** The Database Collate type. Don't change this if in doubt. */\r\n
252
define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
253
$content = str_replace( $search, $replace, $content );
254
- if( false === @file_put_contents( $source, $content ) ) {
255
$this->log( "Preparing Data: Can't save wp-config.php", Logger::TYPE_ERROR );
256
return false;
257
}
258
return true;
259
}
260
@@ -264,35 +296,46 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
264
* @return boolean
265
*/
266
protected function isValidWpConfig( $source ) {
267
if( !is_file( $source ) && !is_link( $source ) ) {
268
$this->log( "Preparing Data Step0: Can not find {$source}", Logger::TYPE_INFO );
269
return false;
270
}
271
$content = file_get_contents( $source );
272
if( false === ($content = file_get_contents( $source )) ) {
273
$this->log( "Preparing Data Step0: Can not read {$source}", Logger::TYPE_INFO );
274
return false;
275
}
276
// Get DB_NAME from wp-config.php
277
preg_match( "/define\s*\(\s*['\"]DB_NAME['\"]\s*,\s*(.*)\s*\);/", $content, $matches );
278
if( empty( $matches[1] ) ) {
279
$this->log( "Preparing Data Step0: Can not find DB_NAME in wp-config.php", Logger::TYPE_INFO );
280
return false;
281
}
282
// Get DB_USER from wp-config.php
283
preg_match( "/define\s*\(\s*['\"]DB_USER['\"]\s*,\s*(.*)\s*\);/", $content, $matches );
284
if( empty( $matches[1] ) ) {
285
$this->log( "Preparing Data Step0: Can not find DB_USER in wp-config.php", Logger::TYPE_INFO );
286
return false;
287
}
288
// Get DB_PASSWORD from wp-config.php
289
preg_match( "/define\s*\(\s*['\"]DB_PASSWORD['\"]\s*,\s*(.*)\s*\);/", $content, $matches );
290
if( empty( $matches[1] ) ) {
291
$this->log( "Preparing Data Step0: Can not find DB_PASSWORD in wp-config.php", Logger::TYPE_INFO );
292
return false;
293
}
294
// Get DB_HOST from wp-config.php
295
preg_match( "/define\s*\(\s*['\"]DB_HOST['\"]\s*,\s*(.*)\s*\);/", $content, $matches );
296
if( empty( $matches[1] ) ) {
297
$this->log( "Preparing Data Step0: Can not find DB_HOST in wp-config.php", Logger::TYPE_INFO );
298
return false;
@@ -306,6 +349,7 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
306
*/
307
protected function step1() {
308
$this->log( "Preparing Data Step1: Updating siteurl and homeurl in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_INFO );
309
// Skip - Table does not exist
310
if( false === $this->isTable( $this->prefix . 'options' ) ) {
311
return true;
@@ -315,6 +359,7 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
315
$this->log( "Preparing Data Step1: Skipping" );
316
return true;
317
}
318
$this->log( "Preparing Data Step1: Updating siteurl and homeurl to " . $this->getStagingSiteUrl() );
319
// Replace URLs
320
$result = $this->db->query(
@@ -322,10 +367,14 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
322
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'siteurl' or option_name='home'", $this->getStagingSiteUrl()
323
)
324
);
325
// All good
326
if( $result ) {
327
return true;
328
}
329
$this->log( "Preparing Data Step1: Skip updating siteurl and homeurl in {$this->prefix}options. Probably already did! {$this->db->last_error}", Logger::TYPE_WARNING );
330
return true;
331
}
@@ -335,7 +384,9 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
335
* @return bool
336
*/
337
protected function step2() {
338
$this->log( "Preparing Data Step2: Updating row wpstg_is_staging_site in {$this->prefix}options {$this->db->last_error}" );
339
// Skip - Table does not exist
340
if( false === $this->isTable( $this->prefix . 'options' ) ) {
341
$this->log( "Preparing Data Step2: Skipping" );
@@ -346,11 +397,13 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
346
$this->log( "Preparing Data Step2: Skipping" );
347
return true;
348
}
349
$result = $this->db->query(
350
$this->db->prepare(
351
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'wpstg_is_staging_site'", "true"
352
)
353
);
354
// No errors but no option name such as wpstg_is_staging_site
355
if( '' === $this->db->last_error && 0 == $result ) {
356
$result = $this->db->query(
@@ -359,10 +412,12 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
359
)
360
);
361
}
362
// All good
363
if( $result ) {
364
return true;
365
}
366
$this->log( "Preparing Data Step2: Failed to update wpstg_is_staging_site in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_ERROR );
367
return false;
368
}
@@ -372,30 +427,37 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
372
* @return bool
373
*/
374
protected function step3() {
375
$this->log( "Preparing Data Step3: Updating rewrite_rules in {$this->prefix}options {$this->db->last_error}" );
376
// Keep Permalinks
377
if( isset( $this->settings->keepPermalinks ) && $this->settings->keepPermalinks === "1" ) {
378
$this->log( "Preparing Data Step3: Skipping" );
379
return true;
380
}
381
// Skip - Table does not exist
382
if( false === $this->isTable( $this->prefix . 'options' ) ) {
383
return true;
384
}
385
// Skip - Table is not selected or updated
386
if( !in_array( $this->prefix . 'options', $this->tables ) ) {
387
$this->log( "Preparing Data Step3: Skipping" );
388
return true;
389
}
390
$result = $this->db->query(
391
$this->db->prepare(
392
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'rewrite_rules'", ' '
393
)
394
);
395
// All good
396
if( $result ) {
397
return true;
398
}
399
//$this->log( "Preparing Data Step3: Failed to update rewrite_rules in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_ERROR );
400
return true;
401
}
@@ -406,20 +468,38 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
406
*/
407
protected function step4() {
408
$this->log( "Preparing Data Step4: Updating db prefix in {$this->prefix}usermeta. " );
409
// Skip - Table does not exist
410
if( false === $this->isTable( $this->prefix . 'usermeta' ) ) {
411
return true;
412
}
413
// Skip - Table is not selected or updated
414
if( !in_array( $this->prefix . 'usermeta', $this->tables ) ) {
415
$this->log( "Preparing Data Step4: Skipping" );
416
return true;
417
}
418
$update = $this->db->query(
419
$this->db->prepare(
420
"UPDATE {$this->prefix}usermeta SET meta_key = replace(meta_key, %s, %s) WHERE meta_key LIKE %s", $this->db->prefix, $this->prefix, $this->db->prefix . "_%"
421
)
422
);
423
if( false === $update ) {
424
$this->log( "Preparing Data Step4: Failed to update {$this->prefix}usermeta meta_key database table prefixes; {$this->db->last_error}", Logger::TYPE_ERROR );
425
$this->returnException( "Data Crunching Step 4: Failed to update {$this->prefix}usermeta meta_key database table prefixes; {$this->db->last_error}" );
@@ -433,20 +513,32 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
433
* @return bool
434
*/
435
protected function step5() {
436
- $path = $this->options->destinationDir . "wp-config.php";
437
$this->log( "Preparing Data Step5: Updating table_prefix in {$path} to " . $this->prefix );
438
if( false === ($content = file_get_contents( $path )) ) {
439
$this->log( "Preparing Data Step5: Failed to update table_prefix in {$path}. Can't read contents", Logger::TYPE_ERROR );
440
return false;
441
}
442
// Replace table prefix
443
- $content = str_replace( '$table_prefix', '$table_prefix = \'' . $this->prefix . '\';//', $content );
444
// Replace URLs
445
$content = str_replace( $this->multisiteHomeDomain, $this->getStagingSiteUrl(), $content );
446
- if( false === @file_put_contents( $path, $content ) ) {
447
$this->log( "Preparing Data Step5: Failed to update $table_prefix in {$path} to " . $this->prefix . ". Can't save contents", Logger::TYPE_ERROR );
448
return false;
449
}
450
return true;
451
}
452
@@ -458,15 +550,20 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
458
* @return bool
459
*/
460
protected function step6() {
461
if( !$this->isSubDir() ) {
462
$this->debugLog( "Preparing Data Step6: WP installation is not in a subdirectory! All good, skipping this step" );
463
return true;
464
}
465
- $path = $this->options->destinationDir . "index.php";
466
if( false === ($content = file_get_contents( $path )) ) {
467
$this->log( "Preparing Data Step6: Failed to reset {$path} for sub directory; can't read contents", Logger::TYPE_ERROR );
468
return false;
469
}
470
if( !preg_match( "/(require(.*)wp-blog-header.php' \);)/", $content, $matches ) ) {
471
$this->log(
472
"Preparing Data Step6: Failed to reset index.php for sub directory; wp-blog-header.php is missing", Logger::TYPE_ERROR
@@ -474,14 +571,20 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
474
return false;
475
}
476
$this->log( "Preparing Data: WP installation is in a subdirectory. Progressing..." );
477
- $pattern = "/require(.*) dirname(.*) __FILE__ (.*) \. '(.*)wp-blog-header.php'(.*);/";
478
$replace = "require( dirname( __FILE__ ) . '/wp-blog-header.php' ); // " . $matches[0];
479
- $replace .= " // Changed by WP-Staging";
480
if( null === ($content = preg_replace( array($pattern), $replace, $content )) ) {
481
$this->log( "Preparing Data: Failed to reset index.php for sub directory; replacement failed", Logger::TYPE_ERROR );
482
return false;
483
}
484
- if( false === @file_put_contents( $path, $content ) ) {
485
$this->log( "Preparing Data: Failed to reset index.php for sub directory; can't save contents", Logger::TYPE_ERROR );
486
return false;
487
}
@@ -494,21 +597,26 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
494
* @return bool
495
*/
496
protected function step7() {
497
$this->log( "Preparing Data Step7: Updating wpstg_rmpermalinks_executed in {$this->prefix}options {$this->db->last_error}" );
498
// Skip - Table does not exist
499
if( false === $this->isTable( $this->prefix . 'options' ) ) {
500
return true;
501
}
502
// Skip - Table is not selected or updated
503
if( !in_array( $this->prefix . 'options', $this->tables ) ) {
504
$this->log( "Preparing Data Step7: Skipping" );
505
return true;
506
}
507
$result = $this->db->query(
508
$this->db->prepare(
509
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'wpstg_rmpermalinks_executed'", ' '
510
)
511
);
512
$this->Log( "Preparing Data Step7: Finished successfully" );
513
return true;
514
}
@@ -518,31 +626,38 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
518
* @return bool
519
*/
520
protected function step8() {
521
$this->log( "Preparing Data Step8: Updating permalink_structure in {$this->prefix}options {$this->db->last_error}" );
522
// Keep Permalinks
523
if( isset( $this->settings->keepPermalinks ) && $this->settings->keepPermalinks === "1" ) {
524
$this->log( "Preparing Data Step8: Skipping" );
525
return true;
526
}
527
// Skip - Table does not exist
528
if( false === $this->isTable( $this->prefix . 'options' ) ) {
529
return true;
530
}
531
// Skip - Table is not selected or updated
532
if( !in_array( $this->prefix . 'options', $this->tables ) ) {
533
$this->log( "Preparing Data Step8: Skipping" );
534
return true;
535
}
536
$result = $this->db->query(
537
$this->db->prepare(
538
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'permalink_structure'", ' '
539
)
540
);
541
// All good
542
if( $result ) {
543
$this->Log( "Preparing Data Step8: Finished successfully" );
544
return true;
545
}
546
$this->log( "Failed to update permalink_structure in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_ERROR );
547
return true;
548
}
@@ -552,25 +667,31 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
552
* @return bool
553
*/
554
protected function step9() {
555
$this->log( "Preparing Data Step9: Set staging site to noindex" );
556
if( false === $this->isTable( $this->prefix . 'options' ) ) {
557
return true;
558
}
559
// Skip - Table is not selected or updated
560
if( !in_array( $this->prefix . 'options', $this->tables ) ) {
561
$this->log( "Preparing Data Step9: Skipping" );
562
return true;
563
}
564
$result = $this->db->query(
565
$this->db->prepare(
566
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'blog_public'", '0'
567
)
568
);
569
// All good
570
if( $result ) {
571
$this->Log( "Preparing Data Step9: Finished successfully" );
572
return true;
573
}
574
$this->log( "Can not update staging site to noindex. Possible already done!", Logger::TYPE_WARNING );
575
return true;
576
}
@@ -580,19 +701,27 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
580
* @return bool
581
*/
582
protected function step10() {
583
- $path = $this->options->destinationDir . "wp-config.php";
584
$this->log( "Preparing Data Step10: Updating WP_HOME in wp-config.php to " . $this->getStagingSiteUrl() );
585
if( false === ($content = file_get_contents( $path )) ) {
586
$this->log( "Preparing Data Step10: Failed to update WP_HOME in wp-config.php. Can't read wp-config.php", Logger::TYPE_ERROR );
587
return false;
588
}
589
// Get WP_HOME from wp-config.php
590
preg_match( "/define\s*\(\s*['\"]WP_HOME['\"]\s*,\s*(.*)\s*\);/", $content, $matches );
591
if( !empty( $matches[1] ) ) {
592
$matches[1];
593
- $pattern = "/define\s*\(\s*['\"]WP_HOME['\"]\s*,\s*(.*)\s*\);/";
594
$replace = "define('WP_HOME','" . $this->getStagingSiteUrl() . "'); // " . $matches[1];
595
- $replace .= " // Changed by WP-Staging";
596
if( null === ($content = preg_replace( array($pattern), $replace, $content )) ) {
597
$this->log( "Preparing Data: Failed to update WP_HOME", Logger::TYPE_ERROR );
598
return false;
@@ -600,7 +729,8 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
600
} else {
601
$this->log( "Preparing Data Step10: WP_HOME not defined in wp-config.php. Skipping this step." );
602
}
603
- if( false === @file_put_contents( $path, $content ) ) {
604
$this->log( "Preparing Data Step10: Failed to update WP_HOME. Can't save contents", Logger::TYPE_ERROR );
605
return false;
606
}
@@ -613,19 +743,27 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
613
* @return bool
614
*/
615
protected function step11() {
616
- $path = $this->options->destinationDir . "wp-config.php";
617
$this->log( "Preparing Data Step11: Updating WP_SITEURL in wp-config.php to " . $this->getStagingSiteUrl() );
618
if( false === ($content = file_get_contents( $path )) ) {
619
$this->log( "Preparing Data Step11: Failed to update WP_SITEURL in wp-config.php. Can't read wp-config.php", Logger::TYPE_ERROR );
620
return false;
621
}
622
// Get WP_SITEURL from wp-config.php
623
preg_match( "/define\s*\(\s*['\"]WP_SITEURL['\"]\s*,\s*(.*)\s*\);/", $content, $matches );
624
if( !empty( $matches[1] ) ) {
625
$matches[1];
626
- $pattern = "/define\s*\(\s*['\"]WP_SITEURL['\"]\s*,\s*(.*)\s*\);/";
627
$replace = "define('WP_SITEURL','" . $this->getStagingSiteUrl() . "'); // " . $matches[1];
628
- $replace .= " // Changed by WP-Staging";
629
if( null === ($content = preg_replace( array($pattern), $replace, $content )) ) {
630
$this->log( "Preparing Data Step11: Failed to update WP_SITEURL", Logger::TYPE_ERROR );
631
return false;
@@ -633,7 +771,9 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
633
} else {
634
$this->log( "Preparing Data Step11: WP_SITEURL not defined in wp-config.php. Skipping this step." );
635
}
636
- if( false === @file_put_contents( $path, $content ) ) {
637
$this->log( "Preparing Data Step11: Failed to update WP_SITEURL. Can't save contents", Logger::TYPE_ERROR );
638
return false;
639
}
@@ -646,19 +786,27 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
646
* @return bool
647
*/
648
protected function step12() {
649
- $path = $this->options->destinationDir . "wp-config.php";
650
$this->log( "Preparing Data Step12: Updating WP_ALLOW_MULTISITE in wp-config.php to false" );
651
if( false === ($content = file_get_contents( $path )) ) {
652
$this->log( "Preparing Data Step12: Failed to update WP_ALLOW_MULTISITE in wp-config.php. Can't read wp-config.php", Logger::TYPE_ERROR );
653
return false;
654
}
655
// Get WP_SITEURL from wp-config.php
656
preg_match( "/define\s*\(\s*['\"]WP_ALLOW_MULTISITE['\"]\s*,\s*(.*)\s*\);/", $content, $matches );
657
if( !empty( $matches[1] ) ) {
658
$matches[1];
659
- $pattern = "/define\s*\(\s*['\"]WP_ALLOW_MULTISITE['\"]\s*,\s*(.*)\s*\);/";
660
$replace = "define('WP_ALLOW_MULTISITE',false); // " . $matches[1];
661
- $replace .= " // Changed by WP-Staging";
662
if( null === ($content = preg_replace( array($pattern), $replace, $content )) ) {
663
$this->log( "Preparing Data Step12: Failed to update WP_ALLOW_MULTISITE", Logger::TYPE_ERROR );
664
return false;
@@ -666,7 +814,9 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
666
} else {
667
$this->log( "Preparing Data Step12: WP_ALLOW_MULTISITE not defined in wp-config.php. Skipping this step." );
668
}
669
- if( false === @file_put_contents( $path, $content ) ) {
670
$this->log( "Preparing Data Step12: Failed to update WP_ALLOW_MULTISITE. Can't save contents", Logger::TYPE_ERROR );
671
return false;
672
}
@@ -679,19 +829,27 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
679
* @return bool
680
*/
681
protected function step13() {
682
- $path = $this->options->destinationDir . "wp-config.php";
683
$this->log( "Preparing Data Step13: Updating MULTISITE in wp-config.php to false" );
684
if( false === ($content = file_get_contents( $path )) ) {
685
$this->log( "Preparing Data Step13: Failed to update MULTISITE in wp-config.php. Can't read wp-config.php", Logger::TYPE_ERROR );
686
return false;
687
}
688
// Get WP_SITEURL from wp-config.php
689
preg_match( "/define\s*\(\s*['\"]MULTISITE['\"]\s*,\s*(.*)\s*\);/", $content, $matches );
690
if( !empty( $matches[1] ) ) {
691
$matches[1];
692
- $pattern = "/define\s*\(\s*['\"]MULTISITE['\"]\s*,\s*(.*)\s*\);/";
693
$replace = "define('MULTISITE',false); // " . $matches[1];
694
- $replace .= " // Changed by WP-Staging";
695
if( null === ($content = preg_replace( array($pattern), $replace, $content )) ) {
696
$this->log( "Preparing Data Step13: Failed to update MULTISITE", Logger::TYPE_ERROR );
697
return false;
@@ -699,7 +857,9 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
699
} else {
700
$this->log( "Preparing Data Step13: MULTISITE not defined in wp-config.php. Skipping this step." );
701
}
702
- if( false === @file_put_contents( $path, $content ) ) {
703
$this->log( "Preparing Data Step13: Failed to update MULTISITE. Can't save contents", Logger::TYPE_ERROR );
704
return false;
705
}
@@ -712,41 +872,55 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
712
* Merge both arrays and copy them to the staging site into active_plugins
713
*/
714
protected function step14() {
715
$this->log( "Data Crunching Step14: Updating active_plugins" );
716
if( false === $this->isTable( $this->prefix . 'options' ) ) {
717
$this->log( 'Data Crunching Step14: Fatal Error ' . $this->prefix . 'options does not exist' );
718
$this->returnException( 'Data Crunching Step14: Fatal Error ' . $this->prefix . 'options does not exist' );
719
return false;
720
}
721
// Skip - Table is not selected or updated
722
if( !in_array( $this->prefix . 'options', $this->tables ) ) {
723
$this->log( "Preparing Data Step14: Skipping" );
724
return true;
725
}
726
// Get active_plugins value from sub site options table
727
$active_plugins = $this->db->get_var( "SELECT option_value FROM {$this->db->prefix}options WHERE option_name = 'active_plugins' " );
728
if( !$active_plugins ) {
729
$this->log( "Data Crunching Step14: Option active_plugins are empty " );
730
$active_plugins = array();
731
}
732
// Get active_sitewide_plugins value from main multisite wp_sitemeta table
733
$active_sitewide_plugins = $this->db->get_var( "SELECT meta_value FROM {$this->db->base_prefix}sitemeta WHERE meta_key = 'active_sitewide_plugins' " );
734
if( !$active_sitewide_plugins ) {
735
$this->log( "Data Crunching Step14: Options {$this->db->base_prefix}active_sitewide_plugins is empty " );
736
$active_sitewide_plugins = array();
737
}
738
$active_sitewide_plugins = unserialize( $active_sitewide_plugins );
739
$active_plugins = unserialize( $active_plugins );
740
- $all_plugins = array_merge( $active_plugins, array_keys( $active_sitewide_plugins ) );
741
sort( $all_plugins );
742
// Update active_plugins
743
- $update = $this->db->query(
744
"UPDATE {$this->prefix}options SET option_value = '" . serialize( $all_plugins ) . "' WHERE option_name = 'active_plugins'"
745
);
746
if( false === $update ) {
747
$this->log( "Data Crunching Step14: Can not update option active_plugins in {$this->prefix}options", Logger::TYPE_WARNING );
748
return false;
749
}
750
$this->log( "Data Crunching Step14: Successful!" );
751
return true;
752
}
@@ -757,37 +931,48 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
757
*/
758
protected function step15() {
759
$this->log( "Preparing Data Step15: Updating db prefix in {$this->prefix}options." );
760
// Skip - Table does not exist
761
if( false === $this->isTable( $this->prefix . 'options' ) ) {
762
return true;
763
}
764
// Skip - Table is not selected or updated
765
if( !in_array( $this->prefix . 'options', $this->tables ) ) {
766
$this->log( "Preparing Data Step4: Skipping" );
767
return true;
768
}
769
$this->log( "Updating db option_names in {$this->prefix}options. " );
770
// Filter the rows below. Do not update them!
771
$filters = array(
772
'wp_mail_smtp',
773
'wp_mail_smtp_version',
774
'wp_mail_smtp_debug',
775
);
776
$filters = apply_filters( 'wpstg_data_excl_rows', $filters );
777
- $where = "";
778
foreach ( $filters as $filter ) {
779
$where .= " AND option_name <> '" . $filter . "'";
780
}
781
$updateOptions = $this->db->query(
782
$this->db->prepare(
783
"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 . "_%"
784
)
785
);
786
if( false === $updateOptions ) {
787
$this->log( "Preparing Data Step15: Failed to update db option_names in {$this->prefix}options. Error: {$this->db->last_error}", Logger::TYPE_WARNING );
788
//$this->returnException( "Data Crunching Step 15: Failed to update db option_names in {$this->prefix}options. Error: {$this->db->last_error}" );
789
return true;
790
}
791
return true;
792
}
793
@@ -797,27 +982,35 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
797
*/
798
protected function step16() {
799
$this->log( "Preparing Data Step16: Updating upload_path {$this->prefix}options." );
800
// Skip - Table does not exist
801
if( false === $this->isTable( $this->prefix . 'options' ) ) {
802
return true;
803
}
804
$newUploadPath = $this->getNewUploadPath();
805
if( false === $newUploadPath ) {
806
$this->log( "Preparing Data Step16: Skipping" );
807
return true;
808
}
809
// Skip - Table is not selected or updated
810
if( !in_array( $this->prefix . 'options', $this->tables ) ) {
811
$this->log( "Preparing Data Step16: Skipping" );
812
return true;
813
}
814
- $error = isset( $this->db->last_error ) ? 'Last error: ' . $this->db->last_error : '';
815
$this->log( "Updating upload_path in {$this->prefix}options. {$error}" );
816
$updateOptions = $this->db->query(
817
$this->db->prepare(
818
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'upload_path'", $newUploadPath
819
)
820
);
821
if( false === $updateOptions ) {
822
$this->log( "Preparing Data Step16: Failed to update upload_path in {$this->prefix}options. {$error}", Logger::TYPE_ERROR );
823
return true;
@@ -831,19 +1024,27 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
831
* @return bool
832
*/
833
protected function step17() {
834
- $path = $this->options->destinationDir . "wp-config.php";
835
$this->log( "Preparing Data Step17: Set WP_CACHE in wp-config.php to false" );
836
if( false === ($content = file_get_contents( $path )) ) {
837
$this->log( "Preparing Data Step17: Failed to update WP_CACHE in wp-config.php. Can't read wp-config.php", Logger::TYPE_ERROR );
838
return false;
839
}
840
// Get WP_CACHE from wp-config.php
841
preg_match( "/define\s*\(\s*['\"]WP_CACHE['\"]\s*,\s*(.*)\s*\);/", $content, $matches );
842
if( !empty( $matches[1] ) ) {
843
$matches[1];
844
- $pattern = "/define\s*\(\s*['\"]WP_CACHE['\"]\s*,\s*(.*)\s*\);/";
845
$replace = "define('WP_CACHE',false); // " . $matches[1];
846
- $replace .= " // Changed by WP-Staging";
847
if( null === ($content = preg_replace( array($pattern), $replace, $content )) ) {
848
$this->log( "Preparing Data: Failed to change WP_CACHE", Logger::TYPE_ERROR );
849
return false;
@@ -851,7 +1052,8 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
851
} else {
852
$this->log( "Preparing Data Step17: WP_CACHE not defined in wp-config.php. Skipping this step." );
853
}
854
- if( false === @file_put_contents( $path, $content ) ) {
855
$this->log( "Preparing Data Step17: Failed to update WP_CACHE. Can't save contents", Logger::TYPE_ERROR );
856
return false;
857
}
@@ -875,7 +1077,9 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
875
$uploadFolder = $this->getMultisiteUploadFolder();
876
if( !empty( $matches[0] ) ) {
877
$pattern = "/define\s*\(\s*'UPLOADS'\s*,\s*(.*)\s*\);/";
878
$replace = "define('UPLOADS', '" . $uploadFolder . "');";
879
if( null === ($content = preg_replace( array($pattern), $replace, $content )) ) {
880
$this->log( "Preparing Data Step 18: Failed to change UPLOADS", Logger::TYPE_ERROR );
881
return false;
@@ -889,6 +1093,7 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
889
$pattern = "/if\s*\(\s*\s*!\s*defined\s*\(\s*['\"]ABSPATH['\"]\s*(.*)\s*\)\s*\)/";
890
$replace = "define('UPLOADS', '" . $uploadFolder . "'); \n" .
891
"if ( ! defined( 'ABSPATH' ) )";
892
if( null === ($content = preg_replace( array($pattern), $replace, $content )) ) {
893
$this->log( "Preparing Data Step 18: Failed to change UPLOADS", Logger::TYPE_ERROR );
894
return false;
@@ -897,7 +1102,7 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
897
$this->log( "Preparing Data Step 18: Can not add UPLOAD constant to wp-config.php. Can not find free position to add it.", Logger::TYPE_ERROR );
898
}
899
}
900
- if( false === @file_put_contents( $path, $content ) ) {
901
$this->log( "Preparing Data Step18: Failed to update UPLOADS. Can't save contents", Logger::TYPE_ERROR );
902
return false;
903
}
@@ -906,140 +1111,132 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
906
}
907
908
/**
909
- * Update database credentials in wp-config.php
910
- * @return bool
911
*/
912
- // protected function step19() {
913
- // $path = $this->options->destinationDir . "wp-config.php";
914
- //
915
- // $this->log("Preparing Data Step19: Change database credentials in wp-config.php");
916
- //
917
- // if (false === ($content = file_get_contents($path))) {
918
- // $this->log("Preparing Data Step19: Failed to update database credentials in wp-config.php. Can't read wp-config.php", Logger::TYPE_ERROR);
919
- // return false;
920
- // }
921
- //
922
- //
923
- // // Get DB_NAME from wp-config.php
924
- // preg_match("/define\s*\(\s*['\"]DB_NAME['\"]\s*,\s*(.*)\s*\);/", $content, $matches);
925
- //
926
- // if (!empty($matches[1])) {
927
- // $matches[1];
928
- //
929
- // $pattern = "/define\s*\(\s*'DB_NAME'\s*,\s*(.*)\s*\);/";
930
- //
931
- // $replace = "define('DB_NAME','{$this->options->databaseDatabase}'); // " . $matches[1];
932
- // $replace .= " // Changed by WP-Staging";
933
- //
934
- // if (null === ($content = preg_replace(array($pattern), $replace, $content))) {
935
- // $this->log("Preparing Data: Failed to change DB_NAME", Logger::TYPE_ERROR);
936
- // return false;
937
- // }
938
- // } else {
939
- // $this->log("Preparing Data Step19: DB_NAME not defined in wp-config.php. Skipping this step.");
940
- // }
941
- // // Get DB_USER from wp-config.php
942
- // preg_match("/define\s*\(\s*['\"]DB_USER['\"]\s*,\s*(.*)\s*\);/", $content, $matches);
943
- //
944
- // if (!empty($matches[1])) {
945
- // $matches[1];
946
- //
947
- // $pattern = "/define\s*\(\s*['\"]DB_USER['\"]\s*,\s*(.*)\s*\);/";
948
- //
949
- // $replace = "define('DB_USER','{$this->options->databaseUser}'); // " . $matches[1];
950
- // $replace .= " // Changed by WP-Staging";
951
- //
952
- // if (null === ($content = preg_replace(array($pattern), $replace, $content))) {
953
- // $this->log("Preparing Data: Failed to change DB_USER", Logger::TYPE_ERROR);
954
- // return false;
955
- // }
956
- // } else {
957
- // $this->log("Preparing Data Step19: DB_USER not defined in wp-config.php. Skipping this step.");
958
- // }
959
- // // Get DB_PASSWORD from wp-config.php
960
- // preg_match("/define\s*\(\s*['\"]DB_PASSWORD['\"]\s*,\s*(.*)\s*\);/", $content, $matches);
961
- //
962
- // if (!empty($matches[1])) {
963
- // $matches[1];
964
- //
965
- // $pattern = "/define\s*\(\s*['\"]DB_PASSWORD['\"]\s*,\s*(.*)\s*\);/";
966
- //
967
- // $replace = "define('DB_PASSWORD','{$this->options->databasePassword}'); // " . $matches[1];
968
- // $replace .= " // Changed by WP-Staging";
969
- //
970
- // if (null === ($content = preg_replace(array($pattern), $replace, $content))) {
971
- // $this->log("Preparing Data: Failed to change DB_PASSWORD", Logger::TYPE_ERROR);
972
- // return false;
973
- // }
974
- // } else {
975
- // $this->log("Preparing Data Step19: DB_PASSWORD not defined in wp-config.php. Skipping this step.");
976
- // }
977
- // // Get DB_HOST from wp-config.php
978
- // preg_match("/define\s*\(\s*['\"]DB_HOST['\"]\s*,\s*(.*)\s*\);/", $content, $matches);
979
- //
980
- // if (!empty($matches[1])) {
981
- // $matches[1];
982
- //
983
- // $pattern = "/define\s*\(\s*['\"]DB_HOST['\"]\s*,\s*(.*)\s*\);/";
984
- //
985
- // $replace = "define('DB_HOST','{$this->options->databaseServer}'); // " . $matches[1];
986
- // $replace .= " // Changed by WP-Staging";
987
- //
988
- // if (null === ($content = preg_replace(array($pattern), $replace, $content))) {
989
- // $this->log("Preparing Data: Failed to change DB_HOST", Logger::TYPE_ERROR);
990
- // return false;
991
- // }
992
- // } else {
993
- // $this->log("Preparing Data Step19: DB_HOST not defined in wp-config.php. Skipping this step.");
994
- // }
995
- //
996
- //
997
- // if (false === @file_put_contents($path, $content)) {
998
- // $this->log("Preparing Data Step19: Failed to update database credentials in wp-config.php. Can't save contents", Logger::TYPE_ERROR);
999
- // return false;
1000
- // }
1001
- // $this->Log("Preparing Data Step 19: Finished successfully");
1002
- // return true;
1003
- // }
1004
/**
1005
- * Remove UPLOADS constant in wp-config.php to reset default image folder
1006
* @return bool
1007
*/
1008
- // protected function step20() {
1009
- // $path = $this->options->destinationDir . "wp-config.php";
1010
- //
1011
- // $this->log( "Preparing Data Step20: Remove UPLOADS in wp-config.php" );
1012
- //
1013
- // if( false === ($content = file_get_contents( $path )) ) {
1014
- // $this->log( "Preparing Data Step20: Failed to get UPLOADS in wp-config.php. Can't read wp-config.php", Logger::TYPE_ERROR );
1015
- // return false;
1016
- // }
1017
- //
1018
- //
1019
- // // Get UPLOADS from wp-config.php
1020
- // preg_match( "/define\s*\(\s*['\"]UPLOADS['\"]\s*,\s*(.*)\s*\);/", $content, $matches );
1021
- //
1022
- // if( !empty( $matches[0] ) ) {
1023
- //
1024
- // $pattern = "/define\s*\(\s*'UPLOADS'\s*,\s*(.*)\s*\);/";
1025
- //
1026
- // $replace = "";
1027
- //
1028
- // if( null === ($content = preg_replace( array($pattern), $replace, $content )) ) {
1029
- // $this->log( "Preparing Data: Failed to change UPLOADS", Logger::TYPE_ERROR );
1030
- // return false;
1031
- // }
1032
- // } else {
1033
- // $this->log( "Preparing Data Step19: UPLOADS not defined in wp-config.php. Skipping this step." );
1034
- // }
1035
- //
1036
- // if( false === @file_put_contents( $path, $content ) ) {
1037
- // $this->log( "Preparing Data Step20: Failed to update UPLOADS. Can't save contents", Logger::TYPE_ERROR );
1038
- // return false;
1039
- // }
1040
- // $this->Log( "Preparing Data Step 20: Finished successfully" );
1041
- // return true;
1042
- // }
1043
/**
1044
* Get relative path to the uploads media folder of multisite e.g.
1045
* wp-content/uploads/sites/SITEID or old wordpress structure wp-content/blogs.dir/SITEID/files
@@ -1049,9 +1246,9 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
1049
$strings = new Strings();
1050
// Get absolute path to uploads folder
1051
$uploads = wp_upload_dir();
1052
- $basedir = $strings->sanitizeDirectorySeparator( $uploads['basedir'] );
1053
// Get relative upload path
1054
- $relDir = str_replace( ABSPATH, null, $basedir );
1055
return $relDir;
1056
}
1057
@@ -1061,11 +1258,15 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
1061
*/
1062
protected function getNewUploadPath() {
1063
$uploadPath = get_option( 'upload_path' );
1064
if( !$uploadPath ) {
1065
return false;
1066
}
1067
- $customSlug = str_replace( \WPStaging\WPStaging::getWPpath(), '', $uploadPath );
1068
- $newUploadPath = \WPStaging\WPStaging::getWPpath() . $this->options->cloneDirectoryName . DIRECTORY_SEPARATOR . $customSlug;
1069
return $newUploadPath;
1070
}
1071
@@ -1074,17 +1275,19 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
1074
* @return string
1075
*/
1076
protected function getStagingSiteUrl() {
1077
if( !empty( $this->options->cloneHostname ) ) {
1078
return $this->options->cloneHostname;
1079
}
1080
if( $this->isSubDir() ) {
1081
return trailingslashit( $this->multisiteHomeDomain ) . trailingslashit( $this->getSubDir() ) . $this->options->cloneDirectoryName;
1082
}
1083
// Get the path to the main multisite without appending and trailingslash e.g. wordpress
1084
$multisitePath = defined( 'PATH_CURRENT_SITE' ) ? PATH_CURRENT_SITE : '/';
1085
$url = rtrim( $this->multisiteHomeDomain, '/\\' ) . $multisitePath . $this->options->cloneDirectoryName;
1086
- //$multisitePath = defined( 'PATH_CURRENT_SITE') ? str_replace('/', '', PATH_CURRENT_SITE) : '';
1087
- //$url = trailingslashit( $this->multisiteHomeDomain ) . $multisitePath . '/' . $this->options->cloneDirectoryName;
1088
return $url;
1089
}
1090
@@ -1097,6 +1300,7 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
1097
// This is happening much more often than you would expect
1098
$siteurl = preg_replace( '#^https?://#', '', rtrim( get_option( 'siteurl' ), '/' ) );
1099
$home = preg_replace( '#^https?://#', '', rtrim( get_option( 'home' ), '/' ) );
1100
if( $home !== $siteurl ) {
1101
return true;
1102
}
@@ -1110,9 +1314,11 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
1110
protected function getSubDir() {
1111
$home = get_option( 'home' );
1112
$siteurl = get_option( 'siteurl' );
1113
if( empty( $home ) || empty( $siteurl ) ) {
1114
return '';
1115
}
1116
$dir = str_replace( $home, '', $siteurl );
1117
return str_replace( '/', '', $dir );
1118
}
40
* Initialize
41
*/
42
public function initialize() {
43
+ $this->db = WPStaging::getInstance()->get( "wpdb" );
44
+
45
$this->prefix = $this->options->prefix;
46
+
47
$this->getTables();
48
+
49
// Fix current step
50
if( 0 == $this->options->currentStep ) {
51
$this->options->currentStep = 0;
71
* @return void
72
*/
73
protected function calculateTotalSteps() {
74
+ $this->options->totalSteps = 21;
75
}
76
77
/**
81
public function start() {
82
// Execute steps
83
$this->run();
84
+
85
// Save option, progress
86
$this->saveOptions();
87
+
88
return ( object ) $this->response;
89
}
90
98
if( $this->isRoot() ) {
99
return false;
100
}
101
+
102
// Over limits threshold
103
if( $this->isOverThreshold() ) {
104
// Prepare response and save current progress
106
$this->saveOptions();
107
return false;
108
}
109
+
110
// No more steps, finished
111
if( $this->isFinished() ) {
112
$this->prepareResponse( true, false );
113
return false;
114
}
115
+
116
// Execute step
117
$stepMethodName = "step" . $this->options->currentStep;
118
if( !$this->{$stepMethodName}() ) {
119
$this->prepareResponse( false, false );
120
return false;
121
}
122
+
123
// Prepare Response
124
$this->prepareResponse();
125
+
126
// Not finished
127
return true;
128
}
144
* @return boolean
145
*/
146
protected function isRoot() {
147
+
148
// Prefix is the same as the one of live site
149
//$wpdb = WPStaging::getInstance()->get( "wpdb" );
150
if( $this->db->prefix === $this->prefix ) {
151
return true;
152
}
153
+
154
// CloneName is empty
155
$name = ( array ) $this->options->cloneDirectoryName;
156
if( empty( $name ) ) {
157
return true;
158
}
159
+
160
// Live domain === Staging domain
161
if( $this->multisiteHomeDomain . $this->options->cloneDirectoryName === $this->multisiteHomeDomain ) {
162
return true;
163
}
164
+
165
return false;
166
}
167
185
*/
186
protected function step0() {
187
$this->log( "Preparing Data Step0: Copy wp-config.php file", Logger::TYPE_INFO );
188
+
189
+ $dir = trailingslashit( dirname( ABSPATH ) );
190
+
191
+ $source = $dir . 'wp-config.php';
192
+
193
$destination = $this->options->destinationDir . 'wp-config.php';
194
+
195
// Check if there is already a valid wp-config.php in root of staging site
196
if( $this->isValidWpConfig( $destination ) ) {
197
$this->log( "Preparing Data Step0: Found wp-config.php file in folder {$destination}", Logger::TYPE_INFO );
198
return true;
199
}
200
+
201
// Check if there is a valid wp-config.php outside root of wp production site
202
if( $this->isValidWpConfig( $source ) ) {
203
// Copy it to staging site
206
return true;
207
}
208
}
209
+
210
// No valid wp-config.php found so let's copy wp stagings default wp-config.php to staging site
211
$source = WPSTG_PLUGIN_DIR . "apps/Backend/helpers/wp-config.php";
212
+
213
$this->log( "Preparing Data Step0: Copy default wp-config.php file from source {$source} to {$destination}", Logger::TYPE_INFO );
214
+
215
if( $this->copy( $source, $destination ) ) {
216
// add missing db credentials to wp-config.php
217
if( !$this->alterWpConfig( $destination ) ) {
219
return false;
220
}
221
}
222
+
223
$this->log( "Preparing Data Step0: Successful", Logger::TYPE_INFO );
224
return true;
225
}
240
return false;
241
}
242
}
243
+
244
// Copy file
245
if( !@copy( $source, $destination ) ) {
246
$errors = error_get_last();
247
$this->log( "Preparing Data Step0: Failed to copy {$source}! Error: {$errors['message']} {$source} -> {$destination}", Logger::TYPE_ERROR );
248
return false;
249
}
250
+
251
return true;
252
}
253
257
* @return boolean
258
*/
259
protected function alterWpConfig( $source ) {
260
+ $this->log( "Preparing Data: Alter wp-config.php", Logger::TYPE_INFO );
261
+
262
$content = file_get_contents( $source );
263
+
264
if( false === ($content = file_get_contents( $source )) ) {
265
return false;
266
}
267
+
268
+ $search = "// ** MySQL settings ** //";
269
+
270
$replace = "// ** MySQL settings ** //\r\n
271
define( 'DB_NAME', '" . DB_NAME . "' );\r\n
272
/** MySQL database username */\r\n
279
define( 'DB_CHARSET', '" . DB_CHARSET . "' );\r\n
280
/** The Database Collate type. Don't change this if in doubt. */\r\n
281
define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
282
+
283
$content = str_replace( $search, $replace, $content );
284
+
285
+ if( false === @wpstg_put_contents( $source, $content ) ) {
286
$this->log( "Preparing Data: Can't save wp-config.php", Logger::TYPE_ERROR );
287
return false;
288
}
289
+
290
return true;
291
}
292
296
* @return boolean
297
*/
298
protected function isValidWpConfig( $source ) {
299
+
300
if( !is_file( $source ) && !is_link( $source ) ) {
301
$this->log( "Preparing Data Step0: Can not find {$source}", Logger::TYPE_INFO );
302
return false;
303
}
304
+
305
$content = file_get_contents( $source );
306
+
307
if( false === ($content = file_get_contents( $source )) ) {
308
$this->log( "Preparing Data Step0: Can not read {$source}", Logger::TYPE_INFO );
309
return false;
310
}
311
+
312
// Get DB_NAME from wp-config.php
313
preg_match( "/define\s*\(\s*['\"]DB_NAME['\"]\s*,\s*(.*)\s*\);/", $content, $matches );
314
+
315
if( empty( $matches[1] ) ) {
316
$this->log( "Preparing Data Step0: Can not find DB_NAME in wp-config.php", Logger::TYPE_INFO );
317
return false;
318
}
319
+
320
// Get DB_USER from wp-config.php
321
preg_match( "/define\s*\(\s*['\"]DB_USER['\"]\s*,\s*(.*)\s*\);/", $content, $matches );
322
+
323
if( empty( $matches[1] ) ) {
324
$this->log( "Preparing Data Step0: Can not find DB_USER in wp-config.php", Logger::TYPE_INFO );
325
return false;
326
}
327
+
328
// Get DB_PASSWORD from wp-config.php
329
preg_match( "/define\s*\(\s*['\"]DB_PASSWORD['\"]\s*,\s*(.*)\s*\);/", $content, $matches );
330
+
331
if( empty( $matches[1] ) ) {
332
$this->log( "Preparing Data Step0: Can not find DB_PASSWORD in wp-config.php", Logger::TYPE_INFO );
333
return false;
334
}
335
+
336
// Get DB_HOST from wp-config.php
337
preg_match( "/define\s*\(\s*['\"]DB_HOST['\"]\s*,\s*(.*)\s*\);/", $content, $matches );
338
+
339
if( empty( $matches[1] ) ) {
340
$this->log( "Preparing Data Step0: Can not find DB_HOST in wp-config.php", Logger::TYPE_INFO );
341
return false;
349
*/
350
protected function step1() {
351
$this->log( "Preparing Data Step1: Updating siteurl and homeurl in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_INFO );
352
+
353
// Skip - Table does not exist
354
if( false === $this->isTable( $this->prefix . 'options' ) ) {
355
return true;
359
$this->log( "Preparing Data Step1: Skipping" );
360
return true;
361
}
362
+
363
$this->log( "Preparing Data Step1: Updating siteurl and homeurl to " . $this->getStagingSiteUrl() );
364
// Replace URLs
365
$result = $this->db->query(
367
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'siteurl' or option_name='home'", $this->getStagingSiteUrl()
368
)
369
);
370
+
371
+
372
+
373
// All good
374
if( $result ) {
375
return true;
376
}
377
+
378
$this->log( "Preparing Data Step1: Skip updating siteurl and homeurl in {$this->prefix}options. Probably already did! {$this->db->last_error}", Logger::TYPE_WARNING );
379
return true;
380
}
384
* @return bool
385
*/
386
protected function step2() {
387
+
388
$this->log( "Preparing Data Step2: Updating row wpstg_is_staging_site in {$this->prefix}options {$this->db->last_error}" );
389
+
390
// Skip - Table does not exist
391
if( false === $this->isTable( $this->prefix . 'options' ) ) {
392
$this->log( "Preparing Data Step2: Skipping" );
397
$this->log( "Preparing Data Step2: Skipping" );
398
return true;
399
}
400
+
401
$result = $this->db->query(
402
$this->db->prepare(
403
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'wpstg_is_staging_site'", "true"
404
)
405
);
406
+
407
// No errors but no option name such as wpstg_is_staging_site
408
if( '' === $this->db->last_error && 0 == $result ) {
409
$result = $this->db->query(
412
)
413
);
414
}
415
+
416
// All good
417
if( $result ) {
418
return true;
419
}
420
+
421
$this->log( "Preparing Data Step2: Failed to update wpstg_is_staging_site in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_ERROR );
422
return false;
423
}
427
* @return bool
428
*/
429
protected function step3() {
430
+
431
$this->log( "Preparing Data Step3: Updating rewrite_rules in {$this->prefix}options {$this->db->last_error}" );
432
+
433
// Keep Permalinks
434
if( isset( $this->settings->keepPermalinks ) && $this->settings->keepPermalinks === "1" ) {
435
$this->log( "Preparing Data Step3: Skipping" );
436
return true;
437
}
438
+
439
// Skip - Table does not exist
440
if( false === $this->isTable( $this->prefix . 'options' ) ) {
441
return true;
442
}
443
+
444
// Skip - Table is not selected or updated
445
if( !in_array( $this->prefix . 'options', $this->tables ) ) {
446
$this->log( "Preparing Data Step3: Skipping" );
447
return true;
448
}
449
+
450
$result = $this->db->query(
451
$this->db->prepare(
452
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'rewrite_rules'", ' '
453
)
454
);
455
+
456
// All good
457
if( $result ) {
458
return true;
459
}
460
+
461
//$this->log( "Preparing Data Step3: Failed to update rewrite_rules in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_ERROR );
462
return true;
463
}
468
*/
469
protected function step4() {
470
$this->log( "Preparing Data Step4: Updating db prefix in {$this->prefix}usermeta. " );
471
+
472
// Skip - Table does not exist
473
if( false === $this->isTable( $this->prefix . 'usermeta' ) ) {
474
return true;
475
}
476
+
477
// Skip - Table is not selected or updated
478
if( !in_array( $this->prefix . 'usermeta', $this->tables ) ) {
479
$this->log( "Preparing Data Step4: Skipping" );
480
return true;
481
}
482
+
483
+ // Change the base table prefix of the main network site
484
+ $this->debugLog( "Preparing Data Step4: UPDATE {$this->prefix}usermeta SET meta_key = replace(meta_key, {$this->db->base_prefix}, {$this->prefix}) WHERE meta_key LIKE {$this->db->base_prefix}_%" );
485
+ $update = $this->db->query(
486
+ $this->db->prepare(
487
+ "UPDATE {$this->prefix}usermeta SET meta_key = replace(meta_key, %s, %s) WHERE meta_key LIKE %s", $this->db->base_prefix, $this->prefix, $this->db->base_prefix . "_%"
488
+ )
489
+ );
490
+
491
+ if( false === $update ) {
492
+ $this->log( "Preparing Data Step4a: Skip updating {$this->prefix}usermeta meta_key database base_prefix; {$this->db->last_error}", Logger::TYPE_INFO );
493
+ }
494
+
495
+ // Change the table prefix of the child network site
496
+ $this->debugLog( "Preparing Data Step4: UPDATE {$this->prefix}usermeta SET meta_key = replace(meta_key, {$this->db->prefix}, {$this->prefix}) WHERE meta_key LIKE {$this->db->prefix}_%" );
497
$update = $this->db->query(
498
$this->db->prepare(
499
"UPDATE {$this->prefix}usermeta SET meta_key = replace(meta_key, %s, %s) WHERE meta_key LIKE %s", $this->db->prefix, $this->prefix, $this->db->prefix . "_%"
500
)
501
);
502
+
503
if( false === $update ) {
504
$this->log( "Preparing Data Step4: Failed to update {$this->prefix}usermeta meta_key database table prefixes; {$this->db->last_error}", Logger::TYPE_ERROR );
505
$this->returnException( "Data Crunching Step 4: Failed to update {$this->prefix}usermeta meta_key database table prefixes; {$this->db->last_error}" );
513
* @return bool
514
*/
515
protected function step5() {
516
+ $path = $this->options->destinationDir . "wp-config.php";
517
+
518
$this->log( "Preparing Data Step5: Updating table_prefix in {$path} to " . $this->prefix );
519
if( false === ($content = file_get_contents( $path )) ) {
520
$this->log( "Preparing Data Step5: Failed to update table_prefix in {$path}. Can't read contents", Logger::TYPE_ERROR );
521
return false;
522
}
523
+
524
// Replace table prefix
525
+ $pattern = '/\$table_prefix\s*=\s*(.*).*/';
526
+ $replacement = '$table_prefix = \'' . $this->prefix . '\'; // Changed by WP Staging';
527
+ $content = preg_replace( $pattern, $replacement, $content );
528
+
529
+ if( null === $content ) {
530
+ $this->log( "Preparing Data Step5: Failed to update table_prefix in {$path}. Can't read contents", Logger::TYPE_ERROR );
531
+ return false;
532
+ }
533
+
534
// Replace URLs
535
$content = str_replace( $this->multisiteHomeDomain, $this->getStagingSiteUrl(), $content );
536
+
537
+ if( false === @wpstg_put_contents( $path, $content ) ) {
538
$this->log( "Preparing Data Step5: Failed to update $table_prefix in {$path} to " . $this->prefix . ". Can't save contents", Logger::TYPE_ERROR );
539
return false;
540
}
541
+
542
return true;
543
}
544
550
* @return bool
551
*/
552
protected function step6() {
553
+
554
if( !$this->isSubDir() ) {
555
$this->debugLog( "Preparing Data Step6: WP installation is not in a subdirectory! All good, skipping this step" );
556
return true;
557
}
558
+
559
+ $path = $this->options->destinationDir . "index.php";
560
+
561
if( false === ($content = file_get_contents( $path )) ) {
562
$this->log( "Preparing Data Step6: Failed to reset {$path} for sub directory; can't read contents", Logger::TYPE_ERROR );
563
return false;
564
}
565
+
566
+
567
if( !preg_match( "/(require(.*)wp-blog-header.php' \);)/", $content, $matches ) ) {
568
$this->log(
569
"Preparing Data Step6: Failed to reset index.php for sub directory; wp-blog-header.php is missing", Logger::TYPE_ERROR
571
return false;
572
}
573
$this->log( "Preparing Data: WP installation is in a subdirectory. Progressing..." );
574
+
575
+ $pattern = "/require(.*) dirname(.*) __FILE__ (.*) \. '(.*)wp-blog-header.php'(.*);.*/";
576
+
577
$replace = "require( dirname( __FILE__ ) . '/wp-blog-header.php' ); // " . $matches[0];
578
+ //$replace .= " // Changed by WP-Staging";
579
+
580
+
581
+
582
if( null === ($content = preg_replace( array($pattern), $replace, $content )) ) {
583
$this->log( "Preparing Data: Failed to reset index.php for sub directory; replacement failed", Logger::TYPE_ERROR );
584
return false;
585
}
586
+
587
+ if( false === @wpstg_put_contents( $path, $content ) ) {
588
$this->log( "Preparing Data: Failed to reset index.php for sub directory; can't save contents", Logger::TYPE_ERROR );
589
return false;
590
}
597
* @return bool
598
*/
599
protected function step7() {
600
+
601
$this->log( "Preparing Data Step7: Updating wpstg_rmpermalinks_executed in {$this->prefix}options {$this->db->last_error}" );
602
+
603
// Skip - Table does not exist
604
if( false === $this->isTable( $this->prefix . 'options' ) ) {
605
return true;
606
}
607
+
608
// Skip - Table is not selected or updated
609
if( !in_array( $this->prefix . 'options', $this->tables ) ) {
610
$this->log( "Preparing Data Step7: Skipping" );
611
return true;
612
}
613
+
614
$result = $this->db->query(
615
$this->db->prepare(
616
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'wpstg_rmpermalinks_executed'", ' '
617
)
618
);
619
+
620
$this->Log( "Preparing Data Step7: Finished successfully" );
621
return true;
622
}
626
* @return bool
627
*/
628
protected function step8() {
629
+
630
$this->log( "Preparing Data Step8: Updating permalink_structure in {$this->prefix}options {$this->db->last_error}" );
631
+
632
// Keep Permalinks
633
if( isset( $this->settings->keepPermalinks ) && $this->settings->keepPermalinks === "1" ) {
634
$this->log( "Preparing Data Step8: Skipping" );
635
return true;
636
}
637
+
638
// Skip - Table does not exist
639
if( false === $this->isTable( $this->prefix . 'options' ) ) {
640
return true;
641
}
642
+
643
// Skip - Table is not selected or updated
644
if( !in_array( $this->prefix . 'options', $this->tables ) ) {
645
$this->log( "Preparing Data Step8: Skipping" );
646
return true;
647
}
648
+
649
$result = $this->db->query(
650
$this->db->prepare(
651
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'permalink_structure'", ' '
652
)
653
);
654
+
655
// All good
656
if( $result ) {
657
$this->Log( "Preparing Data Step8: Finished successfully" );
658
return true;
659
}
660
+
661
$this->log( "Failed to update permalink_structure in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_ERROR );
662
return true;
663
}
667
* @return bool
668
*/
669
protected function step9() {
670
+
671
$this->log( "Preparing Data Step9: Set staging site to noindex" );
672
+
673
if( false === $this->isTable( $this->prefix . 'options' ) ) {
674
return true;
675
}
676
+
677
// Skip - Table is not selected or updated
678
if( !in_array( $this->prefix . 'options', $this->tables ) ) {
679
$this->log( "Preparing Data Step9: Skipping" );
680
return true;
681
}
682
+
683
$result = $this->db->query(
684
$this->db->prepare(
685
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'blog_public'", '0'
686
)
687
);
688
+
689
// All good
690
if( $result ) {
691
$this->Log( "Preparing Data Step9: Finished successfully" );
692
return true;
693
}
694
+
695
$this->log( "Can not update staging site to noindex. Possible already done!", Logger::TYPE_WARNING );
696
return true;
697
}
701
* @return bool
702
*/
703
protected function step10() {
704
+ $path = $this->options->destinationDir . "wp-config.php";
705
+
706
$this->log( "Preparing Data Step10: Updating WP_HOME in wp-config.php to " . $this->getStagingSiteUrl() );
707
+
708
if( false === ($content = file_get_contents( $path )) ) {
709
$this->log( "Preparing Data Step10: Failed to update WP_HOME in wp-config.php. Can't read wp-config.php", Logger::TYPE_ERROR );
710
return false;
711
}
712
+
713
+
714
// Get WP_HOME from wp-config.php
715
preg_match( "/define\s*\(\s*['\"]WP_HOME['\"]\s*,\s*(.*)\s*\);/", $content, $matches );
716
+
717
if( !empty( $matches[1] ) ) {
718
$matches[1];
719
+
720
+ $pattern = "/define\s*\(\s*['\"]WP_HOME['\"]\s*,\s*(.*)\s*\);.*/";
721
+
722
$replace = "define('WP_HOME','" . $this->getStagingSiteUrl() . "'); // " . $matches[1];
723
+ //$replace .= " // Changed by WP-Staging";
724
+
725
if( null === ($content = preg_replace( array($pattern), $replace, $content )) ) {
726
$this->log( "Preparing Data: Failed to update WP_HOME", Logger::TYPE_ERROR );
727
return false;
729
} else {
730
$this->log( "Preparing Data Step10: WP_HOME not defined in wp-config.php. Skipping this step." );
731
}
732
+
733
+ if( false === @wpstg_put_contents( $path, $content ) ) {
734
$this->log( "Preparing Data Step10: Failed to update WP_HOME. Can't save contents", Logger::TYPE_ERROR );
735
return false;
736
}
743
* @return bool
744
*/
745
protected function step11() {
746
+ $path = $this->options->destinationDir . "wp-config.php";
747
+
748
$this->log( "Preparing Data Step11: Updating WP_SITEURL in wp-config.php to " . $this->getStagingSiteUrl() );
749
+
750
if( false === ($content = file_get_contents( $path )) ) {
751
$this->log( "Preparing Data Step11: Failed to update WP_SITEURL in wp-config.php. Can't read wp-config.php", Logger::TYPE_ERROR );
752
return false;
753
}
754
+
755
+
756
// Get WP_SITEURL from wp-config.php
757
preg_match( "/define\s*\(\s*['\"]WP_SITEURL['\"]\s*,\s*(.*)\s*\);/", $content, $matches );
758
+
759
if( !empty( $matches[1] ) ) {
760
$matches[1];
761
+
762
+ $pattern = "/define\s*\(\s*['\"]WP_SITEURL['\"]\s*,\s*(.*)\s*\);.*/";
763
+
764
$replace = "define('WP_SITEURL','" . $this->getStagingSiteUrl() . "'); // " . $matches[1];
765
+ //$replace .= " // Changed by WP-Staging";
766
+
767
if( null === ($content = preg_replace( array($pattern), $replace, $content )) ) {
768
$this->log( "Preparing Data Step11: Failed to update WP_SITEURL", Logger::TYPE_ERROR );
769
return false;
771
} else {
772
$this->log( "Preparing Data Step11: WP_SITEURL not defined in wp-config.php. Skipping this step." );
773
}
774
+
775
+
776
+ if( false === @wpstg_put_contents( $path, $content ) ) {
777
$this->log( "Preparing Data Step11: Failed to update WP_SITEURL. Can't save contents", Logger::TYPE_ERROR );
778
return false;
779
}
786
* @return bool
787
*/
788
protected function step12() {
789
+ $path = $this->options->destinationDir . "wp-config.php";
790
+
791
$this->log( "Preparing Data Step12: Updating WP_ALLOW_MULTISITE in wp-config.php to false" );
792
+
793
if( false === ($content = file_get_contents( $path )) ) {
794
$this->log( "Preparing Data Step12: Failed to update WP_ALLOW_MULTISITE in wp-config.php. Can't read wp-config.php", Logger::TYPE_ERROR );
795
return false;
796
}
797
+
798
+
799
// Get WP_SITEURL from wp-config.php
800
preg_match( "/define\s*\(\s*['\"]WP_ALLOW_MULTISITE['\"]\s*,\s*(.*)\s*\);/", $content, $matches );
801
+
802
if( !empty( $matches[1] ) ) {
803
$matches[1];
804
+
805
+ $pattern = "/define\s*\(\s*['\"]WP_ALLOW_MULTISITE['\"]\s*,\s*(.*)\s*\);.*/";
806
+
807
$replace = "define('WP_ALLOW_MULTISITE',false); // " . $matches[1];
808
+ //$replace .= " // Changed by WP-Staging";
809
+
810
if( null === ($content = preg_replace( array($pattern), $replace, $content )) ) {
811
$this->log( "Preparing Data Step12: Failed to update WP_ALLOW_MULTISITE", Logger::TYPE_ERROR );
812
return false;
814
} else {
815
$this->log( "Preparing Data Step12: WP_ALLOW_MULTISITE not defined in wp-config.php. Skipping this step." );
816
}
817
+
818
+
819
+ if( false === @wpstg_put_contents( $path, $content ) ) {
820
$this->log( "Preparing Data Step12: Failed to update WP_ALLOW_MULTISITE. Can't save contents", Logger::TYPE_ERROR );
821
return false;
822
}
829
* @return bool
830
*/
831
protected function step13() {
832
+ $path = $this->options->destinationDir . "wp-config.php";
833
+
834
$this->log( "Preparing Data Step13: Updating MULTISITE in wp-config.php to false" );
835
+
836
if( false === ($content = file_get_contents( $path )) ) {
837
$this->log( "Preparing Data Step13: Failed to update MULTISITE in wp-config.php. Can't read wp-config.php", Logger::TYPE_ERROR );
838
return false;
839
}
840
+
841
+
842
// Get WP_SITEURL from wp-config.php
843
preg_match( "/define\s*\(\s*['\"]MULTISITE['\"]\s*,\s*(.*)\s*\);/", $content, $matches );
844
+
845
if( !empty( $matches[1] ) ) {
846
$matches[1];
847
+
848
+ $pattern = "/define\s*\(\s*['\"]MULTISITE['\"]\s*,\s*(.*)\s*\);.*/";
849
+
850
$replace = "define('MULTISITE',false); // " . $matches[1];
851
+ //$replace .= " // Changed by WP-Staging";
852
+
853
if( null === ($content = preg_replace( array($pattern), $replace, $content )) ) {
854
$this->log( "Preparing Data Step13: Failed to update MULTISITE", Logger::TYPE_ERROR );
855
return false;
857
} else {
858
$this->log( "Preparing Data Step13: MULTISITE not defined in wp-config.php. Skipping this step." );
859
}
860
+
861
+
862
+ if( false === @wpstg_put_contents( $path, $content ) ) {
863
$this->log( "Preparing Data Step13: Failed to update MULTISITE. Can't save contents", Logger::TYPE_ERROR );
864
return false;
865
}
872
* Merge both arrays and copy them to the staging site into active_plugins
873
*/
874
protected function step14() {
875
+
876
+
877
$this->log( "Data Crunching Step14: Updating active_plugins" );
878
+
879
if( false === $this->isTable( $this->prefix . 'options' ) ) {
880
$this->log( 'Data Crunching Step14: Fatal Error ' . $this->prefix . 'options does not exist' );
881
$this->returnException( 'Data Crunching Step14: Fatal Error ' . $this->prefix . 'options does not exist' );
882
return false;
883
}
884
+
885
// Skip - Table is not selected or updated
886
if( !in_array( $this->prefix . 'options', $this->tables ) ) {
887
$this->log( "Preparing Data Step14: Skipping" );
888
return true;
889
}
890
+
891
// Get active_plugins value from sub site options table
892
$active_plugins = $this->db->get_var( "SELECT option_value FROM {$this->db->prefix}options WHERE option_name = 'active_plugins' " );
893
+
894
if( !$active_plugins ) {
895
$this->log( "Data Crunching Step14: Option active_plugins are empty " );
896
$active_plugins = array();
897
}
898
// Get active_sitewide_plugins value from main multisite wp_sitemeta table
899
$active_sitewide_plugins = $this->db->get_var( "SELECT meta_value FROM {$this->db->base_prefix}sitemeta WHERE meta_key = 'active_sitewide_plugins' " );
900
+
901
if( !$active_sitewide_plugins ) {
902
$this->log( "Data Crunching Step14: Options {$this->db->base_prefix}active_sitewide_plugins is empty " );
903
$active_sitewide_plugins = array();
904
}
905
+
906
$active_sitewide_plugins = unserialize( $active_sitewide_plugins );
907
$active_plugins = unserialize( $active_plugins );
908
+
909
+ $all_plugins = array_merge( $active_plugins, array_keys( $active_sitewide_plugins ) );
910
+
911
sort( $all_plugins );
912
+
913
+
914
// Update active_plugins
915
+ $update = $this->db->query(
916
"UPDATE {$this->prefix}options SET option_value = '" . serialize( $all_plugins ) . "' WHERE option_name = 'active_plugins'"
917
);
918
+
919
if( false === $update ) {
920
$this->log( "Data Crunching Step14: Can not update option active_plugins in {$this->prefix}options", Logger::TYPE_WARNING );
921
return false;
922
}
923
+
924
$this->log( "Data Crunching Step14: Successful!" );
925
return true;
926
}
931
*/
932
protected function step15() {
933
$this->log( "Preparing Data Step15: Updating db prefix in {$this->prefix}options." );
934
+
935
// Skip - Table does not exist
936
if( false === $this->isTable( $this->prefix . 'options' ) ) {
937
return true;
938
}
939
+
940
// Skip - Table is not selected or updated
941
if( !in_array( $this->prefix . 'options', $this->tables ) ) {
942
$this->log( "Preparing Data Step4: Skipping" );
943
return true;
944
}
945
+
946
+
947
$this->log( "Updating db option_names in {$this->prefix}options. " );
948
+
949
// Filter the rows below. Do not update them!
950
$filters = array(
951
'wp_mail_smtp',
952
'wp_mail_smtp_version',
953
'wp_mail_smtp_debug',
954
);
955
+
956
$filters = apply_filters( 'wpstg_data_excl_rows', $filters );
957
+
958
+ $where = "";
959
foreach ( $filters as $filter ) {
960
$where .= " AND option_name <> '" . $filter . "'";
961
}
962
+
963
$updateOptions = $this->db->query(
964
$this->db->prepare(
965
"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 . "_%"
966
)
967
);
968
+
969
if( false === $updateOptions ) {
970
$this->log( "Preparing Data Step15: Failed to update db option_names in {$this->prefix}options. Error: {$this->db->last_error}", Logger::TYPE_WARNING );
971
//$this->returnException( "Data Crunching Step 15: Failed to update db option_names in {$this->prefix}options. Error: {$this->db->last_error}" );
972
return true;
973
}
974
+
975
+
976
return true;
977
}
978
982
*/
983
protected function step16() {
984
$this->log( "Preparing Data Step16: Updating upload_path {$this->prefix}options." );
985
+
986
// Skip - Table does not exist
987
if( false === $this->isTable( $this->prefix . 'options' ) ) {
988
return true;
989
}
990
+
991
$newUploadPath = $this->getNewUploadPath();
992
+
993
if( false === $newUploadPath ) {
994
$this->log( "Preparing Data Step16: Skipping" );
995
return true;
996
}
997
+
998
// Skip - Table is not selected or updated
999
if( !in_array( $this->prefix . 'options', $this->tables ) ) {
1000
$this->log( "Preparing Data Step16: Skipping" );
1001
return true;
1002
}
1003
+
1004
+ $error = isset( $this->db->last_error ) ? 'Last error: ' . $this->db->last_error : '';
1005
+
1006
$this->log( "Updating upload_path in {$this->prefix}options. {$error}" );
1007
+
1008
$updateOptions = $this->db->query(
1009
$this->db->prepare(
1010
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'upload_path'", $newUploadPath
1011
)
1012
);
1013
+
1014
if( false === $updateOptions ) {
1015
$this->log( "Preparing Data Step16: Failed to update upload_path in {$this->prefix}options. {$error}", Logger::TYPE_ERROR );
1016
return true;
1024
* @return bool
1025
*/
1026
protected function step17() {
1027
+ $path = $this->options->destinationDir . "wp-config.php";
1028
+
1029
$this->log( "Preparing Data Step17: Set WP_CACHE in wp-config.php to false" );
1030
+
1031
if( false === ($content = file_get_contents( $path )) ) {
1032
$this->log( "Preparing Data Step17: Failed to update WP_CACHE in wp-config.php. Can't read wp-config.php", Logger::TYPE_ERROR );
1033
return false;
1034
}
1035
+
1036
+
1037
// Get WP_CACHE from wp-config.php
1038
preg_match( "/define\s*\(\s*['\"]WP_CACHE['\"]\s*,\s*(.*)\s*\);/", $content, $matches );
1039
+
1040
if( !empty( $matches[1] ) ) {
1041
$matches[1];
1042
+
1043
+ $pattern = "/define\s*\(\s*['\"]WP_CACHE['\"]\s*,\s*(.*)\s*\);.*/";
1044
+
1045
$replace = "define('WP_CACHE',false); // " . $matches[1];
1046
+ //$replace .= " // Changed by WP-Staging";
1047
+
1048
if( null === ($content = preg_replace( array($pattern), $replace, $content )) ) {
1049
$this->log( "Preparing Data: Failed to change WP_CACHE", Logger::TYPE_ERROR );
1050
return false;
1052
} else {
1053
$this->log( "Preparing Data Step17: WP_CACHE not defined in wp-config.php. Skipping this step." );
1054
}
1055
+
1056
+ if( false === @wpstg_put_contents( $path, $content ) ) {
1057
$this->log( "Preparing Data Step17: Failed to update WP_CACHE. Can't save contents", Logger::TYPE_ERROR );
1058
return false;
1059
}
1077
$uploadFolder = $this->getMultisiteUploadFolder();
1078
if( !empty( $matches[0] ) ) {
1079
$pattern = "/define\s*\(\s*'UPLOADS'\s*,\s*(.*)\s*\);/";
1080
+
1081
$replace = "define('UPLOADS', '" . $uploadFolder . "');";
1082
+ $this->log( "Preparing Data Step18: Change UPLOADS constant in wp-config.php to {$uploadFolder}." );
1083
if( null === ($content = preg_replace( array