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

Version Description

  • Fix: Do not show warning "Preparing Data Step3: Failed to update rewrite_rules in wpstg0_options"
  • Fix: Change error "Table wpstgtmp_options does not exist" to warning
  • New: Add arguments for hook wpstg_cloning_complete
  • New: Setup server environment variables per process and not globally (e.g. set_time_limit)
  • New: Add support for custom uploads folder if user customized UPLOADS constant or upload_path in DB
Download this release

Release Info

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

Code changes from version 2.6.1 to 2.6.2

apps/Backend/Modules/Jobs/Data.php CHANGED
@@ -176,7 +176,7 @@ class Data extends JobExecutable {
176
*/
177
protected function isTable( $table ) {
178
if( $this->db->get_var( "SHOW TABLES LIKE '{$table}'" ) != $table ) {
179
- $this->log( "Preparing Data: Table {$table} does not exist.", Logger::TYPE_ERROR );
180
return false;
181
}
182
return true;
@@ -411,7 +411,7 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
411
//}
412
// All good
413
if( $insert ) {
414
- $this->log( "Preparing Data Step2: Successfull", Logger::TYPE_INFO );
415
return true;
416
}
417
@@ -450,7 +450,7 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
450
return true;
451
}
452
453
- $this->log( "Preparing Data Step3: Failed to update rewrite_rules in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_ERROR );
454
return true;
455
}
456
@@ -614,6 +614,7 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
614
615
// Skip - Table does not exist
616
if( false === $this->isTable( $this->prefix . 'options' ) ) {
617
return true;
618
}
619
@@ -900,21 +901,24 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
900
return true;
901
}
902
903
- $error = isset( $this->db->last_error ) ? 'Last error: ' . $this->db->last_error : '';
904
-
905
- $this->log( "Preparing Data Step13: Updating upload_path in {$this->prefix}options. {$error}" );
906
907
$updateOptions = $this->db->query(
908
$this->db->prepare(
909
- "UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'upload_path'", $newUploadPath
910
)
911
);
912
913
if( false === $updateOptions ) {
914
- $this->log( "Preparing Data Step13: Failed to update upload_path in {$this->prefix}options. {$error}", Logger::TYPE_ERROR );
915
return true;
916
}
917
- $this->Log( "Preparing Data Step 13: Finished successfully" );
918
return true;
919
}
920
@@ -1043,34 +1047,81 @@ define( 'DB_COLLATE', '" . DB_COLLATE . "' );\r\n";
1043
* Remove UPLOADS constant in wp-config.php to reset default image folder
1044
* @return bool
1045
*/
1046
- protected function step17() {
1047
- $path = $this->options->destinationDir . "wp-config.php";
1048
-
1049
- $this->log( "Preparing Data Step17: Remove UPLOADS in wp-config.php" );
1050
1051
if( false === ($content = file_get_contents( $path )) ) {
1052
$this->log( "Preparing Data Step17: Failed to get UPLOADS in wp-config.php. Can't read wp-config.php", Logger::TYPE_ERROR );
1053
return false;
1054
}
1055
-
1056
-
1057
- // Get UPLOADS from wp-config.php
1058
preg_match( "/define\s*\(\s*['\"]UPLOADS['\"]\s*,\s*(.*)\s*\);/", $content, $matches );
1059
-
1060
if( !empty( $matches[0] ) ) {
1061
-
1062
$pattern = "/define\s*\(\s*'UPLOADS'\s*,\s*(.*)\s*\);/";
1063
-
1064
- $replace = "";
1065
-
1066
if( null === ($content = preg_replace( array($pattern), $replace, $content )) ) {
1067
- $this->log( "Preparing Data: Failed to change UPLOADS", Logger::TYPE_ERROR );
1068
return false;
1069
}
1070
} else {
1071
- $this->log( "Preparing Data Step17: UPLOADS not defined in wp-config.php. Skipping this step." );
1072
}
1073
-
1074
if( false === @file_put_contents( $path, $content ) ) {
1075
$this->log( "Preparing Data Step17: Failed to update UPLOADS. Can't save contents", Logger::TYPE_ERROR );
1076
return false;
176
*/
177
protected function isTable( $table ) {
178
if( $this->db->get_var( "SHOW TABLES LIKE '{$table}'" ) != $table ) {
179
+ $this->log( "Preparing Data: Table {$table} does not exist.", Logger::TYPE_INFO );
180
return false;
181
}
182
return true;
411
//}
412
// All good
413
if( $insert ) {
414
+ $this->log( "Preparing Data Step2: Successful", Logger::TYPE_INFO );
415
return true;
416
}
417
450
return true;
451
}
452
453
+ //$this->log( "Preparing Data Step3: Failed to update rewrite_rules in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_ERROR );
454
return true;
455
}
456
614
615
// Skip - Table does not exist
616
if( false === $this->isTable( $this->prefix . 'options' ) ) {
617
+ $this->log( "Preparing Data Step8: Skipping" );
618
return true;
619
}
620
901
return true;
902
}
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'", ""
914
)
915
);
916
917
if( false === $updateOptions ) {
918
+ $this->log( "Preparing Data Step13: Did not update upload_path in {$this->prefix}options. {$error}", Logger::TYPE_INFO );
919
return true;
920
}
921
+ $this->Log( "Preparing Data Step13: Finished successfully" );
922
return true;
923
}
924
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
1089
+ * @return bool
1090
+ */
1091
+ protected function step17() {
1092
+ $path = $this->options->destinationDir . "wp-config.php";
1093
+ $this->log( "Preparing Data Step17: Update UPLOADS constant in wp-config.php" );
1094
if( false === ($content = file_get_contents( $path )) ) {
1095
$this->log( "Preparing Data Step17: Failed to get UPLOADS in wp-config.php. Can't read wp-config.php", Logger::TYPE_ERROR );
1096
return false;
1097
}
1098
+ // Get UPLOADS from wp-config.php if there is already one
1099
preg_match( "/define\s*\(\s*['\"]UPLOADS['\"]\s*,\s*(.*)\s*\);/", $content, $matches );
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 );
1106
return false;
1107
}
1108
} else {
1109
+ $this->log( "Preparing Data Step17: UPLOADS not defined in wp-config.php. Creating new entry." );
1110
+ // Find line with ABSPATH and add UPLOADS constant above
1111
+ preg_match( "/if\s*\(\s*\s*!\s*defined\s*\(\s*['\"]ABSPATH['\"]\s*(.*)\s*\)\s*\)/", $content, $matches );
1112
+ if( !empty( $matches[0] ) ) {
1113
+ $matches[0];
1114
+ $pattern = "/if\s*\(\s*\s*!\s*defined\s*\(\s*['\"]ABSPATH['\"]\s*(.*)\s*\)\s*\)/";
1115
+ $replace = "define('UPLOADS', '" . $uploadFolder . "'); \n" .
1116
+ "if ( ! defined( 'ABSPATH' ) )";
1117
+ if( null === ($content = preg_replace( array($pattern), $replace, $content )) ) {
1118
+ $this->log( "Preparing Data Step 17: Failed to change UPLOADS", Logger::TYPE_ERROR );
1119
+ return false;
1120
+ }
1121
+ } else {
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;
apps/Backend/Modules/Jobs/Delete.php CHANGED
@@ -152,12 +152,15 @@ class Delete extends Job {
152
153
$this->tables = array();
154
155
foreach ( $tables as $table ) {
156
$this->tables[] = array(
157
"name" => $table->Name,
158
"size" => $this->formatSize( ($table->Data_length + $table->Index_length ) )
159
);
160
}
161
162
$this->tables = json_decode( json_encode( $this->tables ) );
163
}
@@ -310,10 +313,13 @@ class Delete extends Job {
310
*/
311
public function deleteTables() {
312
if( $this->isOverThreshold() ) {
313
return;
314
}
315
316
- foreach ( $this->getTablesToRemove() as $table ) {
317
// PROTECTION: Never delete any table that beginns with wp prefix of live site
318
if( !$this->isExternalDatabase() && $this->startsWith( $table, $this->wpdb->prefix ) ) {
319
$this->log( "Fatal Error: Trying to delete table {$table} of main WP installation!", Logger::TYPE_CRITICAL );
@@ -374,6 +380,7 @@ class Delete extends Job {
374
return;
375
}
376
377
$di = new \RecursiveDirectoryIterator( $this->deleteDir, \FilesystemIterator::SKIP_DOTS );
378
$ri = new \RecursiveIteratorIterator( $di, \RecursiveIteratorIterator::CHILD_FIRST );
379
foreach ( $ri as $file ) {
@@ -383,27 +390,43 @@ class Delete extends Job {
383
return;
384
}
385
}
386
387
// Delete left over staging site root folder
388
@rmdir( $this->deleteDir );
389
390
- // Throw fatal error if the folder is still not deleted
391
- if( is_dir($this->deleteDir) ) {
392
$clone = ( string ) $this->clone->path;
393
$response = array(
394
'job' => 'delete',
395
'status' => true,
396
'delete' => 'finished',
397
- 'message' => "Could not the staging site entirely. The folder {$clone}is still not empty. <br/><br/> If this happens again please contact us at support@wp-staging.com",
398
'error' => true,
399
);
400
wp_die( json_encode( $response ) );
401
}
402
403
- // Successfull finish deleting job
404
return $this->deleteFinish();
405
}
406
407
/**
408
* Delete file
409
* @param object iterator $file
152
153
$this->tables = array();
154
155
+ // no results
156
+ if( null !== $tables ) {
157
foreach ( $tables as $table ) {
158
$this->tables[] = array(
159
"name" => $table->Name,
160
"size" => $this->formatSize( ($table->Data_length + $table->Index_length ) )
161
);
162
}
163
+ }
164
165
$this->tables = json_decode( json_encode( $this->tables ) );
166
}
313
*/
314
public function deleteTables() {
315
if( $this->isOverThreshold() ) {
316
+ $this->log( "Deleting: Is over threshold", Logger::TYPE_INFO );
317
return;
318
}
319
320
+ $tables = $this->getTablesToRemove();
321
+
322
+ foreach ( $tables as $table ) {
323
// PROTECTION: Never delete any table that beginns with wp prefix of live site
324
if( !$this->isExternalDatabase() && $this->startsWith( $table, $this->wpdb->prefix ) ) {
325
$this->log( "Fatal Error: Trying to delete table {$table} of main WP installation!", Logger::TYPE_CRITICAL );
380
return;
381
}
382
383
+ if( $this->isNotEmpty( $this->deleteDir ) ) {
384
$di = new \RecursiveDirectoryIterator( $this->deleteDir, \FilesystemIterator::SKIP_DOTS );
385
$ri = new \RecursiveIteratorIterator( $di, \RecursiveIteratorIterator::CHILD_FIRST );
386
foreach ( $ri as $file ) {
390
return;
391
}
392
}
393
+ }
394
395
// Delete left over staging site root folder
396
@rmdir( $this->deleteDir );
397
398
+ // Throw fatal error if the folder has still not been deleted and there are files in it
399
+ if( $this->isNotEmpty( $this->deleteDir ) ) {
400
$clone = ( string ) $this->clone->path;
401
$response = array(
402
'job' => 'delete',
403
'status' => true,
404
'delete' => 'finished',
405
+ 'message' => "Could not delete the entire staging site. The folder {$clone} still exists and is not empty. <br/> Try to empty this folder manually by using FTP or file manager plugin and then try to delete again the staging site here.<br/> If this happens again please contact us at support@wp-staging.com",
406
'error' => true,
407
);
408
wp_die( json_encode( $response ) );
409
}
410
411
+ // Successful finish deleting job
412
return $this->deleteFinish();
413
}
414
415
+ /**
416
+ * Check if directory exists and is not empty
417
+ * @param string $dir
418
+ * @return bool
419
+ */
420
+ private function isNotEmpty( $dir ) {
421
+ // Throw fatal error if the folder has still not been deleted and there are files in it
422
+ $isDirNotEmpty = false;
423
+ if( is_dir( $dir ) ) {
424
+ $iterator = new \FilesystemIterator( $dir );
425
+ $isDirNotEmpty = $iterator->valid();
426
+ }
427
+ return $isDirNotEmpty;
428
+ }
429
+
430
/**
431
* Delete file
432
* @param object iterator $file
apps/Backend/Modules/Jobs/Files.php CHANGED
@@ -158,7 +158,7 @@ class Files extends JobExecutable {
158
*/
159
private function isFinished() {
160
return (
161
- !isset($this->options->isRunning) ||
162
$this->options->currentStep > $this->options->totalSteps ||
163
$this->options->copiedFiles >= $this->options->totalFiles
164
);
@@ -248,25 +248,57 @@ class Files extends JobExecutable {
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
@@ -294,8 +326,11 @@ class Files extends JobExecutable {
294
// Get custom wp-content and uploads folder
295
$file = $this->getWpContentPath( $file );
296
297
$relativePath = str_replace( \WPStaging\WPStaging::getWPpath(), null, $file );
298
$destinationPath = $this->destination . $relativePath;
299
$destinationDirectory = dirname( $destinationPath );
300
301
if( !is_dir( $destinationDirectory ) && !@mkdir( $destinationDirectory, wpstg_get_permissions_for_directory(), true ) ) {
@@ -434,4 +469,4 @@ class Files extends JobExecutable {
434
return false;
435
}
436
437
- }
158
*/
159
private function isFinished() {
160
return (
161
+ !isset( $this->options->isRunning ) ||
162
$this->options->currentStep > $this->options->totalSteps ||
163
$this->options->copiedFiles >= $this->options->totalFiles
164
);
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.
276
+ *
277
+ * @return string
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'] );
285
286
+ // Get relative path to the uploads folder, e.g assets
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 ) {
294
+ //$file = str_replace( $uploadsAbsPath, ABSPATH . 'wp-content/uploads/', $file, $count );
295
+ $file = str_replace( $uploadsAbsPath, ABSPATH . $uploadsRelPath, $file, $count );
296
+ }
297
// If there is no custom upload directory do a search & replace of the custom wp-content directory
298
if( empty( $count ) || $count === 0 ) {
299
+ //$file = str_replace( $wpContentDir, ABSPATH . 'wp-content/', $file );
300
$file = str_replace( $wpContentDir, ABSPATH . 'wp-content/', $file );
301
}
302
return $file;
303
}
304
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 ) ) {
469
return false;
470
}
471
472
+ }
apps/Backend/Modules/Jobs/Finish.php CHANGED
@@ -46,7 +46,7 @@ class Finish extends Job {
46
);
47
48
//$this->flush();
49
- do_action('wpstg_cloning_complete');
50
51
52
return ( object ) $return;
46
);
47
48
//$this->flush();
49
+ do_action('wpstg_cloning_complete', $this->options);
50
51
52
return ( object ) $return;
apps/Backend/Modules/Jobs/JobExecutable.php CHANGED
@@ -1,41 +1,41 @@
1
<?php
2
namespace WPStaging\Backend\Modules\Jobs;
3
4
// No Direct Access
5
- if (!defined("WPINC"))
6
- {
7
die;
8
}
9
10
-
11
/**
12
* Class JobExecutable
13
* I'm sorry for such mess, we need to support PHP 5.3
14
* @package WPStaging\Backend\Modules\Jobs
15
*/
16
- abstract class JobExecutable extends Job
17
- {
18
19
/**
20
* @var array
21
*/
22
protected $response = array(
23
- "status" => false,
24
- "percentage" => 0,
25
- "total" => 0,
26
- "step" => 0,
27
- "last_msg" => '',
28
);
29
30
/**
31
* JobExecutable constructor.
32
*/
33
- public function __construct()
34
- {
35
parent::__construct();
36
37
// Calculate total steps
38
$this->calculateTotalSteps();
39
}
40
41
/**
@@ -44,28 +44,26 @@ abstract class JobExecutable extends Job
44
* @param bool $incrementCurrentStep
45
* @return array
46
*/
47
- protected function prepareResponse($status = false, $incrementCurrentStep = true)
48
- {
49
- if ($incrementCurrentStep)
50
- {
51
$this->options->currentStep++;
52
}
53
54
$percentage = 0;
55
- if (isset($this->options->currentStep) && isset($this->options->totalSteps) && $this->options->totalSteps > 0){
56
- $percentage = round(($this->options->currentStep / $this->options->totalSteps) * 100);
57
- $percentage = (100 < $percentage) ? 100 : $percentage;
58
}
59
60
return $this->response = array(
61
- "status" => $status,
62
- "percentage" => $percentage,
63
- "total" => $this->options->totalSteps,
64
- "step" => $this->options->currentStep,
65
- "job" => $this->options->currentJob,
66
- "last_msg" => $this->logger->getLastLogMsg(),
67
- "running_time" => $this->time() - time(),
68
- "job_done" => $status
69
);
70
}
71
@@ -73,35 +71,31 @@ abstract class JobExecutable extends Job
73
* Start Module
74
* @return object
75
*/
76
- public function start()
77
- {
78
// Execute steps
79
$this->run();
80
81
// Save option, progress
82
$this->saveOptions();
83
84
- return (object) $this->response;
85
}
86
-
87
- /**
88
* Run Steps
89
*/
90
- protected function run()
91
- {
92
// Execute steps
93
- for ($i = 0; $i < $this->options->totalSteps; $i++)
94
- {
95
// Job is finished or over threshold limits was hit
96
- if (!$this->execute())
97
- {
98
break;
99
}
100
// Return after every step to create lower batches
101
// This also gets a smoother progress bar and to a less consumptive php cpu load
102
// This decrease performance tremendous but also lowers memory consumption
103
- if ($this->settings->cpuLoad === 'low'){
104
- return (object) $this->response;
105
}
106
}
107
}
@@ -118,4 +112,4 @@ abstract class JobExecutable extends Job
118
* @return bool
119
*/
120
abstract protected function execute();
121
- }
1
<?php
2
+
3
namespace WPStaging\Backend\Modules\Jobs;
4
5
// No Direct Access
6
+ if( !defined( "WPINC" ) ) {
7
die;
8
}
9
10
/**
11
* Class JobExecutable
12
* I'm sorry for such mess, we need to support PHP 5.3
13
* @package WPStaging\Backend\Modules\Jobs
14
*/
15
+ abstract class JobExecutable extends Job {
16
17
/**
18
* @var array
19
*/
20
protected $response = array(
21
+ "status" => false,
22
+ "percentage" => 0,
23
+ "total" => 0,
24
+ "step" => 0,
25
+ "last_msg" => '',
26
);
27
28
/**
29
* JobExecutable constructor.
30
*/
31
+ public function __construct() {
32
parent::__construct();
33
34
// Calculate total steps
35
$this->calculateTotalSteps();
36
+
37
+ // Set server settings (Do not set this globally. HS Ticket #9061)
38
+ wpstg_setup_environment();
39
}
40
41
/**
44
* @param bool $incrementCurrentStep
45
* @return array
46
*/
47
+ protected function prepareResponse( $status = false, $incrementCurrentStep = true ) {
48
+ if( $incrementCurrentStep ) {
49
$this->options->currentStep++;
50
}
51
52
$percentage = 0;
53
+ if( isset( $this->options->currentStep ) && isset( $this->options->totalSteps ) && $this->options->totalSteps > 0 ) {
54
+ $percentage = round( ($this->options->currentStep / $this->options->totalSteps) * 100 );
55
+ $percentage = (100 < $percentage) ? 100 : $percentage;
56
}
57
58
return $this->response = array(
59
+ "status" => $status,
60
+ "percentage" => $percentage,
61
+ "total" => $this->options->totalSteps,
62
+ "step" => $this->options->currentStep,
63
+ "job" => $this->options->currentJob,
64
+ "last_msg" => $this->logger->getLastLogMsg(),
65
+ "running_time" => $this->time() - time(),
66
+ "job_done" => $status
67
);
68
}
69
71
* Start Module
72
* @return object
73
*/
74
+ public function start() {
75
// Execute steps
76
$this->run();
77
78
// Save option, progress
79
$this->saveOptions();
80
81
+ return ( object ) $this->response;
82
}
83
+
84
+ /**
85
* Run Steps
86
*/
87
+ protected function run() {
88
// Execute steps
89
+ for ( $i = 0; $i < $this->options->totalSteps; $i++ ) {
90
// Job is finished or over threshold limits was hit
91
+ if( !$this->execute() ) {
92
break;
93
}
94
// Return after every step to create lower batches
95
// This also gets a smoother progress bar and to a less consumptive php cpu load
96
// This decrease performance tremendous but also lowers memory consumption
97
+ if( $this->settings->cpuLoad === 'low' ) {
98
+ return ( object ) $this->response;
99
}
100
}
101
}
112
* @return bool
113
*/
114
abstract protected function execute();
115
+ }
apps/Backend/Modules/Jobs/Multisite/Data.php CHANGED
@@ -40,12 +40,9 @@ class Data extends JobExecutable {
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;
@@ -81,10 +78,8 @@ class Data extends JobExecutable {
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,7 +93,6 @@ class Data extends JobExecutable {
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,23 +100,19 @@ class Data extends JobExecutable {
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
}
@@ -133,6 +123,7 @@ class Data extends JobExecutable {
133
*/
134
protected function isFinished() {
135
return (
136
$this->options->currentStep > $this->options->totalSteps ||
137
!method_exists( $this, "step" . $this->options->currentStep )
138
);
@@ -143,24 +134,20 @@ class Data extends JobExecutable {
143
* @return boolean
144
*/
145
protected function isRoot() {
146
-
147
// Prefix is the same as the one of live site
148
//$wpdb = WPStaging::getInstance()->get( "wpdb" );
149
if( $this->db->prefix === $this->prefix ) {
150
return true;
151
}
152
-
153
// CloneName is empty
154
$name = ( array ) $this->options->cloneDirectoryName;
155
if( empty( $name ) ) {
156
return true;
157
}
158
-
159
// Live domain === Staging domain
160
if( $this->multisiteHomeDomain . $this->options->cloneDirectoryName === $this->multisiteHomeDomain ) {
161
return true;
162
}
163
-
164
return false;
165
}
166
@@ -178,54 +165,138 @@ class Data extends JobExecutable {
178
}
179
180
/**
181
- * Return absolute destination path
182
- * @return string
183
- */
184
- // private function getAbsDestination() {
185
- // if( empty( $this->options->cloneDir ) ) {
186
- // return \WPStaging\WPStaging::getWPpath();
187
- // }
188
- // return trailingslashit( $this->options->cloneDir );
189
- // }
190
-
191
- /**
192
- * Copy wp-config.php if it is located outside of root one level up
193
- * @todo Needs some more testing before it will be released
194
* @return boolean
195
*/
196
protected function step0() {
197
- $this->log( "Preparing Data Step0: Check if wp-config.php is located in root path", Logger::TYPE_INFO );
198
-
199
- $dir = trailingslashit( dirname( ABSPATH ) );
200
-
201
- $source = $dir . 'wp-config.php';
202
-
203
$destination = $this->options->destinationDir . 'wp-config.php';
204
-
205
-
206
- // Do not do anything
207
- if( (!is_file( $source ) && !is_link( $source )) || is_file( $destination ) ) {
208
- $this->log( "Preparing Data Step0: Skip it", Logger::TYPE_INFO );
209
return true;
210
}
211
212
- // Copy target of a symbolic link
213
if( is_link( $source ) ) {
214
- $this->log( "Preparing Data Step0: Symbolic link found...", Logger::TYPE_INFO );
215
if( !@copy( readlink( $source ), $destination ) ) {
216
$errors = error_get_last();
217
- $this->log( "Preparing Data Step0: Failed to copy wp-config.php! Error: {$errors['message']} {$source} -> {$destination}", Logger::TYPE_ERROR );
218
- return true;
219
}
220
}
221
-
222
- // Copy file wp-config.php
223
if( !@copy( $source, $destination ) ) {
224
$errors = error_get_last();
225
- $this->log( "Preparing Data Step0: Failed to copy wp-config.php! Error: {$errors['message']} {$source} -> {$destination}", Logger::TYPE_ERROR );
226
- return true;
227
}
228
- $this->log( "Preparing Data Step0: Successfull", Logger::TYPE_INFO );
229
return true;
230
}
231
@@ -235,7 +306,6 @@ class Data extends JobExecutable {
235
*/
236
protected function step1() {
237
$this->log( "Preparing Data Step1: Updating siteurl and homeurl in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_INFO );
238
-
239
// Skip - Table does not exist
240
if( false === $this->isTable( $this->prefix . 'options' ) ) {
241
return true;
@@ -245,27 +315,6 @@ class Data extends JobExecutable {
245
$this->log( "Preparing Data Step1: Skipping" );
246
return true;
247
}
248
-
249
- // Installed in sub-directory
250
- // if( $this->isSubDir() ) {
251
- // $this->log( "Preparing Data Step1: Updating siteurl and homeurl to " . rtrim( $this->multisiteHomeDomain, "/" ) . '/' . $this->options->cloneDirectoryName );
252
- // // Replace URLs
253
- // $result = $this->db->query(
254
- // $this->db->prepare(
255
- // "UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'siteurl' or option_name='home'", rtrim( $this->multisiteHomeDomain, "/" ) . '/' . $this->options->cloneDirectoryName
256
- // )
257
- // );
258
- // } else
259
- // {
260
- // $this->log( "Preparing Data Step1: Updating siteurl and homeurl to " . rtrim( $this->multisiteHomeDomain, "/" ) . '/' . $this->options->cloneDirectoryName );
261
- // // Replace URLs
262
- // $result = $this->db->query(
263
- // $this->db->prepare(
264
- // "UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'siteurl' or option_name='home'", $this->multisiteHomeDomain . '/' . $this->options->cloneDirectoryName
265
- // )
266
- // );
267
- // }
268
-
269
$this->log( "Preparing Data Step1: Updating siteurl and homeurl to " . $this->getStagingSiteUrl() );
270
// Replace URLs
271
$result = $this->db->query(
@@ -273,15 +322,11 @@ class Data extends JobExecutable {
273
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'siteurl' or option_name='home'", $this->getStagingSiteUrl()
274
)
275
);
276
-
277
-
278
-
279
// All good
280
if( $result ) {
281
return true;
282
}
283
-
284
- $this->log( "Preparing Data Step1: Failed to update siteurl and homeurl in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_ERROR );
285
return true;
286
}
287
@@ -290,11 +335,10 @@ class Data extends JobExecutable {
290
* @return bool
291
*/
292
protected function step2() {
293
-
294
$this->log( "Preparing Data Step2: Updating row wpstg_is_staging_site in {$this->prefix}options {$this->db->last_error}" );
295
-
296
// Skip - Table does not exist
297
if( false === $this->isTable( $this->prefix . 'options' ) ) {
298
return true;
299
}
300
// Skip - Table is not selected or updated
@@ -302,13 +346,11 @@ class Data extends JobExecutable {
302
$this->log( "Preparing Data Step2: Skipping" );
303
return true;
304
}
305
-
306
$result = $this->db->query(
307
$this->db->prepare(
308
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'wpstg_is_staging_site'", "true"
309
)
310
);
311
-
312
// No errors but no option name such as wpstg_is_staging_site
313
if( '' === $this->db->last_error && 0 == $result ) {
314
$result = $this->db->query(
@@ -317,12 +359,10 @@ class Data extends JobExecutable {
317
)
318
);
319
}
320
-
321
// All good
322
if( $result ) {
323
return true;
324
}
325
-
326
$this->log( "Preparing Data Step2: Failed to update wpstg_is_staging_site in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_ERROR );
327
return false;
328
}
@@ -332,60 +372,55 @@ class Data extends JobExecutable {
332
* @return bool
333
*/
334
protected function step3() {
335
-
336
$this->log( "Preparing Data Step3: Updating rewrite_rules in {$this->prefix}options {$this->db->last_error}" );
337
-
338
// Skip - Table does not exist
339
if( false === $this->isTable( $this->prefix . 'options' ) ) {
340
return true;
341
}
342
-
343
// Skip - Table is not selected or updated
344
if( !in_array( $this->prefix . 'options', $this->tables ) ) {
345
$this->log( "Preparing Data Step3: Skipping" );
346
return true;
347
}
348
-
349
$result = $this->db->query(
350
$this->db->prepare(
351
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'rewrite_rules'", ' '
352
)
353
);
354
-
355
// All good
356
if( $result ) {
357
return true;
358
}
359
-
360
- $this->log( "Preparing Data Step3: Failed to update rewrite_rules in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_ERROR );
361
return true;
362
}
363
364
/**
365
- * Update Table Prefix in wp_usermeta and wp_options
366
* @return bool
367
*/
368
protected function step4() {
369
- $this->log( "Preparing Data Step4: Updating db prefix in {$this->prefix}usermeta. {$this->db->last_error}" );
370
-
371
// Skip - Table does not exist
372
if( false === $this->isTable( $this->prefix . 'usermeta' ) ) {
373
return true;
374
}
375
-
376
// Skip - Table is not selected or updated
377
if( !in_array( $this->prefix . 'usermeta', $this->tables ) ) {
378
$this->log( "Preparing Data Step4: Skipping" );
379
return true;
380
}
381
-
382
$update = $this->db->query(
383
$this->db->prepare(
384
"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 . "_%"
385
)
386
);
387
-
388
- if( !$update ) {
389
$this->log( "Preparing Data Step4: Failed to update {$this->prefix}usermeta meta_key database table prefixes; {$this->db->last_error}", Logger::TYPE_ERROR );
390
$this->returnException( "Data Crunching Step 4: Failed to update {$this->prefix}usermeta meta_key database table prefixes; {$this->db->last_error}" );
391
return false;
@@ -398,25 +433,20 @@ class Data extends JobExecutable {
398
* @return bool
399
*/
400
protected function step5() {
401
- $path = $this->options->destinationDir . "wp-config.php";
402
-
403
$this->log( "Preparing Data Step5: Updating table_prefix in {$path} to " . $this->prefix );
404
if( false === ($content = file_get_contents( $path )) ) {
405
$this->log( "Preparing Data Step5: Failed to update table_prefix in {$path}. Can't read contents", Logger::TYPE_ERROR );
406
return false;
407
}
408
-
409
// Replace table prefix
410
$content = str_replace( '$table_prefix', '$table_prefix = \'' . $this->prefix . '\';//', $content );
411
-
412
// Replace URLs
413
$content = str_replace( $this->multisiteHomeDomain, $this->getStagingSiteUrl(), $content );
414
-
415
if( false === @file_put_contents( $path, $content ) ) {
416
$this->log( "Preparing Data Step5: Failed to update $table_prefix in {$path} to " . $this->prefix . ". Can't save contents", Logger::TYPE_ERROR );
417
return false;
418
}
419
-
420
return true;
421
}
422
@@ -428,45 +458,34 @@ class Data extends JobExecutable {
428
* @return bool
429
*/
430
protected function step6() {
431
-
432
if( !$this->isSubDir() ) {
433
$this->debugLog( "Preparing Data Step6: WP installation is not in a subdirectory! All good, skipping this step" );
434
return true;
435
}
436
-
437
- $path = $this->options->destinationDir . "index.php";
438
-
439
if( false === ($content = file_get_contents( $path )) ) {
440
$this->log( "Preparing Data Step6: Failed to reset {$path} for sub directory; can't read contents", Logger::TYPE_ERROR );
441
return false;
442
}
443
-
444
-
445
if( !preg_match( "/(require(.*)wp-blog-header.php' \);)/", $content, $matches ) ) {
446
$this->log(
447
- "Preparing Data Step6: Failed to reset index.php for sub directory. Can not find line 'require(.*)wp-blog-header.php' in index.php", Logger::TYPE_ERROR
448
);
449
return false;
450
}
451
$this->log( "Preparing Data: WP installation is in a subdirectory. Progressing..." );
452
-
453
$pattern = "/require(.*) dirname(.*) __FILE__ (.*) \. '(.*)wp-blog-header.php'(.*);/";
454
-
455
$replace = "require( dirname( __FILE__ ) . '/wp-blog-header.php' ); // " . $matches[0];
456
- $replace.= " // Changed by WP-Staging";
457
-
458
-
459
-
460
if( null === ($content = preg_replace( array($pattern), $replace, $content )) ) {
461
$this->log( "Preparing Data: Failed to reset index.php for sub directory; replacement failed", Logger::TYPE_ERROR );
462
return false;
463
}
464
-
465
if( false === @file_put_contents( $path, $content ) ) {
466
$this->log( "Preparing Data: Failed to reset index.php for sub directory; can't save contents", Logger::TYPE_ERROR );
467
return false;
468
}
469
- $this->Log( "Preparing Data: Finished Step 6 successfully" );
470
return true;
471
}
472
@@ -475,33 +494,22 @@ class Data extends JobExecutable {
475
* @return bool
476
*/
477
protected function step7() {
478
-
479
$this->log( "Preparing Data Step7: Updating wpstg_rmpermalinks_executed in {$this->prefix}options {$this->db->last_error}" );
480
-
481
// Skip - Table does not exist
482
if( false === $this->isTable( $this->prefix . 'options' ) ) {
483
return true;
484
}
485
-
486
// Skip - Table is not selected or updated
487
if( !in_array( $this->prefix . 'options', $this->tables ) ) {
488
$this->log( "Preparing Data Step7: Skipping" );
489
return true;
490
}
491
-
492
$result = $this->db->query(
493
$this->db->prepare(
494
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'wpstg_rmpermalinks_executed'", ' '
495
)
496
);
497
-
498
- // All good
499
- if( $result ) {
500
- $this->Log( "Preparing Data Step7: Finished Step 7 successfully" );
501
- return true;
502
- }
503
-
504
- $this->log( "Failed to update wpstg_rmpermalinks_executed in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_WARNING );
505
return true;
506
}
507
@@ -510,32 +518,31 @@ class Data extends JobExecutable {
510
* @return bool
511
*/
512
protected function step8() {
513
-
514
$this->log( "Preparing Data Step8: Updating permalink_structure in {$this->prefix}options {$this->db->last_error}" );
515
-
516
// Skip - Table does not exist
517
if( false === $this->isTable( $this->prefix . 'options' ) ) {
518
return true;
519
}
520
-
521
// Skip - Table is not selected or updated
522
if( !in_array( $this->prefix . 'options', $this->tables ) ) {
523
$this->log( "Preparing Data Step8: Skipping" );
524
return true;
525
}
526
-
527
$result = $this->db->query(
528
$this->db->prepare(
529
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'permalink_structure'", ' '
530
)
531
);
532
-
533
// All good
534
if( $result ) {
535
- $this->Log( "Preparing Data Step8: Finished Step 8 successfully" );
536
return true;
537
}
538
-
539
$this->log( "Failed to update permalink_structure in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_ERROR );
540
return true;
541
}
@@ -545,31 +552,25 @@ class Data extends JobExecutable {
545
* @return bool
546
*/
547
protected function step9() {
548
-
549
$this->log( "Preparing Data Step9: Set staging site to noindex" );
550
-
551
if( false === $this->isTable( $this->prefix . 'options' ) ) {
552
return true;
553
}
554
-
555
// Skip - Table is not selected or updated
556
if( !in_array( $this->prefix . 'options', $this->tables ) ) {
557
$this->log( "Preparing Data Step9: Skipping" );
558
return true;
559
}
560
-
561
$result = $this->db->query(
562
$this->db->prepare(
563
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'blog_public'", '0'
564
)
565
);
566
-
567
// All good
568
if( $result ) {
569
- $this->Log( "Preparing Data Step9: Finished Step 9 successfully" );
570
return true;
571
}
572
-
573
$this->log( "Can not update staging site to noindex. Possible already done!", Logger::TYPE_WARNING );
574
return true;
575
}
@@ -579,40 +580,31 @@ class Data extends JobExecutable {
579
* @return bool
580
*/
581
protected function step10() {
582
- $path = $this->options->destinationDir . "wp-config.php";
583
-
584
$this->log( "Preparing Data Step10: Updating WP_HOME in wp-config.php to " . $this->getStagingSiteUrl() );
585
-
586
if( false === ($content = file_get_contents( $path )) ) {
587
$this->log( "Preparing Data Step10: Failed to update WP_HOME in wp-config.php. Can't read wp-config.php", Logger::TYPE_ERROR );
588
return false;
589
}
590
-
591
-
592
// Get WP_HOME from wp-config.php
593
- preg_match( "/define\s*\(\s*'WP_HOME'\s*,\s*(.*)\s*\);/", $content, $matches );
594
-
595
if( !empty( $matches[1] ) ) {
596
$matches[1];
597
-
598
- $pattern = "/define\s*\(\s*'WP_HOME'\s*,\s*(.*)\s*\);/";
599
-
600
$replace = "define('WP_HOME','" . $this->getStagingSiteUrl() . "'); // " . $matches[1];
601
- $replace.= " // Changed by WP-Staging";
602
-
603
if( null === ($content = preg_replace( array($pattern), $replace, $content )) ) {
604
- $this->log( "Preparing Data: Failed to reset index.php for sub directory; replacement failed", Logger::TYPE_ERROR );
605
return false;
606
}
607
} else {
608
$this->log( "Preparing Data Step10: WP_HOME not defined in wp-config.php. Skipping this step." );
609
}
610
-
611
if( false === @file_put_contents( $path, $content ) ) {
612
- $this->log( "Preparing Data Step11: Failed to update WP_SITEURL. Can't save contents", Logger::TYPE_ERROR );
613
return false;
614
}
615
- $this->Log( "Preparing Data: Finished Step 11 successfully" );
616
return true;
617
}
618
@@ -621,27 +613,19 @@ class Data extends JobExecutable {
621
* @return bool
622
*/
623
protected function step11() {
624
- $path = $this->options->destinationDir . "wp-config.php";
625
-
626
$this->log( "Preparing Data Step11: Updating WP_SITEURL in wp-config.php to " . $this->getStagingSiteUrl() );
627
-
628
if( false === ($content = file_get_contents( $path )) ) {
629
$this->log( "Preparing Data Step11: Failed to update WP_SITEURL in wp-config.php. Can't read wp-config.php", Logger::TYPE_ERROR );
630
return false;
631
}
632
-
633
-
634
// Get WP_SITEURL from wp-config.php
635
- preg_match( "/define\s*\(\s*'WP_SITEURL'\s*,\s*(.*)\s*\);/", $content, $matches );
636
-
637
if( !empty( $matches[1] ) ) {
638
$matches[1];
639
-
640
- $pattern = "/define\s*\(\s*'WP_SITEURL'\s*,\s*(.*)\s*\);/";
641
-
642
$replace = "define('WP_SITEURL','" . $this->getStagingSiteUrl() . "'); // " . $matches[1];
643
- $replace.= " // Changed by WP-Staging";
644
-
645
if( null === ($content = preg_replace( array($pattern), $replace, $content )) ) {
646
$this->log( "Preparing Data Step11: Failed to update WP_SITEURL", Logger::TYPE_ERROR );
647
return false;
@@ -649,13 +633,11 @@ class Data extends JobExecutable {
649
} else {
650
$this->log( "Preparing Data Step11: WP_SITEURL not defined in wp-config.php. Skipping this step." );
651
}
652
-
653
-
654
if( false === @file_put_contents( $path, $content ) ) {
655
$this->log( "Preparing Data Step11: Failed to update WP_SITEURL. Can't save contents", Logger::TYPE_ERROR );
656
return false;
657
}
658
- $this->Log( "Preparing Data: Finished Step 11 successfully" );
659
return true;
660
}
661
@@ -664,27 +646,19 @@ class Data extends JobExecutable {
664
* @return bool
665
*/
666
protected function step12() {
667
- $path = $this->options->destinationDir . "wp-config.php";
668
-
669
$this->log( "Preparing Data Step12: Updating WP_ALLOW_MULTISITE in wp-config.php to false" );
670
-
671
if( false === ($content = file_get_contents( $path )) ) {
672
$this->log( "Preparing Data Step12: Failed to update WP_ALLOW_MULTISITE in wp-config.php. Can't read wp-config.php", Logger::TYPE_ERROR );
673
return false;
674
}
675
-
676
-
677
// Get WP_SITEURL from wp-config.php
678
- preg_match( "/define\s*\(\s*'WP_ALLOW_MULTISITE'\s*,\s*(.*)\s*\);/", $content, $matches );
679
-
680
if( !empty( $matches[1] ) ) {
681
$matches[1];
682
-
683
- $pattern = "/define\s*\(\s*'WP_ALLOW_MULTISITE'\s*,\s*(.*)\s*\);/";
684
-
685
$replace = "define('WP_ALLOW_MULTISITE',false); // " . $matches[1];
686
- $replace.= " // Changed by WP-Staging";
687
-
688
if( null === ($content = preg_replace( array($pattern), $replace, $content )) ) {
689
$this->log( "Preparing Data Step12: Failed to update WP_ALLOW_MULTISITE", Logger::TYPE_ERROR );
690
return false;
@@ -692,8 +666,6 @@ class Data extends JobExecutable {
692
} else {
693
$this->log( "Preparing Data Step12: WP_ALLOW_MULTISITE not defined in wp-config.php. Skipping this step." );
694
}
695
-
696
-
697
if( false === @file_put_contents( $path, $content ) ) {
698
$this->log( "Preparing Data Step12: Failed to update WP_ALLOW_MULTISITE. Can't save contents", Logger::TYPE_ERROR );
699
return false;
@@ -707,27 +679,19 @@ class Data extends JobExecutable {
707
* @return bool
708
*/
709
protected function step13() {
710
- $path = $this->options->destinationDir . "wp-config.php";
711
-
712
$this->log( "Preparing Data Step13: Updating MULTISITE in wp-config.php to false" );
713
-
714
if( false === ($content = file_get_contents( $path )) ) {
715
$this->log( "Preparing Data Step13: Failed to update MULTISITE in wp-config.php. Can't read wp-config.php", Logger::TYPE_ERROR );
716
return false;
717
}
718
-
719
-
720
// Get WP_SITEURL from wp-config.php
721
- preg_match( "/define\s*\(\s*'MULTISITE'\s*,\s*(.*)\s*\);/", $content, $matches );
722
-
723
if( !empty( $matches[1] ) ) {
724
$matches[1];
725
-
726
- $pattern = "/define\s*\(\s*'MULTISITE'\s*,\s*(.*)\s*\);/";
727
-
728
$replace = "define('MULTISITE',false); // " . $matches[1];
729
- $replace.= " // Changed by WP-Staging";
730
-
731
if( null === ($content = preg_replace( array($pattern), $replace, $content )) ) {
732
$this->log( "Preparing Data Step13: Failed to update MULTISITE", Logger::TYPE_ERROR );
733
return false;
@@ -735,13 +699,11 @@ class Data extends JobExecutable {
735
} else {
736
$this->log( "Preparing Data Step13: MULTISITE not defined in wp-config.php. Skipping this step." );
737
}
738
-
739
-
740
if( false === @file_put_contents( $path, $content ) ) {
741
$this->log( "Preparing Data Step13: Failed to update MULTISITE. Can't save contents", Logger::TYPE_ERROR );
742
return false;
743
}
744
- $this->Log( "Preparing Data: Finished Step 13 successfully" );
745
return true;
746
}
747
@@ -750,56 +712,42 @@ class Data extends JobExecutable {
750
* Merge both arrays and copy them to the staging site into active_plugins
751
*/
752
protected function step14() {
753
-
754
-
755
- $this->log( "Data Crunching Step 14: Updating active_plugins" );
756
-
757
if( false === $this->isTable( $this->prefix . 'options' ) ) {
758
- $this->log( 'Data Crunching Step 14: Fatal Error ' . $this->prefix . 'options does not exist' );
759
- $this->returnException( 'Data Crunching Step 14: Fatal Error ' . $this->prefix . 'options does not exist' );
760
return false;
761
}
762
-
763
// Skip - Table is not selected or updated
764
if( !in_array( $this->prefix . 'options', $this->tables ) ) {
765
$this->log( "Preparing Data Step14: Skipping" );
766
return true;
767
}
768
-
769
// Get active_plugins value from sub site options table
770
$active_plugins = $this->db->get_var( "SELECT option_value FROM {$this->db->prefix}options WHERE option_name = 'active_plugins' " );
771
-
772
if( !$active_plugins ) {
773
- $this->log( "Data Crunching Step 14: Option active_plugins are empty " );
774
$active_plugins = array();
775
}
776
// Get active_sitewide_plugins value from main multisite wp_sitemeta table
777
$active_sitewide_plugins = $this->db->get_var( "SELECT meta_value FROM {$this->db->base_prefix}sitemeta WHERE meta_key = 'active_sitewide_plugins' " );
778
-
779
if( !$active_sitewide_plugins ) {
780
- $this->log( "Data Crunching Step 14: Options {$this->db->base_prefix}active_sitewide_plugins is empty " );
781
$active_sitewide_plugins = array();
782
}
783
-
784
$active_sitewide_plugins = unserialize( $active_sitewide_plugins );
785
$active_plugins = unserialize( $active_plugins );
786
-
787
- $all_plugins = array_merge( $active_plugins, array_keys( $active_sitewide_plugins ) );
788
-
789
sort( $all_plugins );
790
-
791
-
792
// Update active_plugins
793
- $update = $this->db->query(
794
"UPDATE {$this->prefix}options SET option_value = '" . serialize( $all_plugins ) . "' WHERE option_name = 'active_plugins'"
795
);
796
-
797
if( false === $update ) {
798
- $this->log( "Data Crunching Step 14: Can not update option active_plugins in {$this->prefix}options", Logger::TYPE_WARNING );
799
return false;
800
}
801
-
802
- $this->log( "Data Crunching Step 14: Successful!" );
803
return true;
804
}
805
@@ -809,48 +757,37 @@ class Data extends JobExecutable {
809
*/
810
protected function step15() {
811
$this->log( "Preparing Data Step15: Updating db prefix in {$this->prefix}options." );
812
-
813
// Skip - Table does not exist
814
if( false === $this->isTable( $this->prefix . 'options' ) ) {
815
return true;
816
}
817
-
818
// Skip - Table is not selected or updated
819
if( !in_array( $this->prefix . 'options', $this->tables ) ) {
820
$this->log( "Preparing Data Step4: Skipping" );
821
return true;
822
}
823
-
824
-
825
$this->log( "Updating db option_names in {$this->prefix}options. " );
826
-
827
// Filter the rows below. Do not update them!
828
$filters = array(
829
'wp_mail_smtp',
830
'wp_mail_smtp_version',
831
'wp_mail_smtp_debug',
832
);
833
-
834
$filters = apply_filters( 'wpstg_data_excl_rows', $filters );
835
-
836
- $where = "";
837
foreach ( $filters as $filter ) {
838
$where .= " AND option_name <> '" . $filter . "'";
839
}
840
-
841
$updateOptions = $this->db->query(
842
$this->db->prepare(
843
"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 . "_%"
844
)
845
);
846
-
847
- if( !$updateOptions ) {
848
$this->log( "Preparing Data Step15: Failed to update db option_names in {$this->prefix}options. Error: {$this->db->last_error}", Logger::TYPE_WARNING );
849
//$this->returnException( "Data Crunching Step 15: Failed to update db option_names in {$this->prefix}options. Error: {$this->db->last_error}" );
850
return true;
851
}
852
-
853
-
854
return true;
855
}
856
@@ -860,36 +797,28 @@ class Data extends JobExecutable {
860
*/
861
protected function step16() {
862
$this->log( "Preparing Data Step16: Updating upload_path {$this->prefix}options." );
863
-
864
// Skip - Table does not exist
865
if( false === $this->isTable( $this->prefix . 'options' ) ) {
866
return true;
867
}
868
-
869
$newUploadPath = $this->getNewUploadPath();
870
-
871
if( false === $newUploadPath ) {
872
$this->log( "Preparing Data Step16: Skipping" );
873
return true;
874
}
875
-
876
// Skip - Table is not selected or updated
877
if( !in_array( $this->prefix . 'options', $this->tables ) ) {
878
$this->log( "Preparing Data Step16: Skipping" );
879
return true;
880
}
881
-
882
- $error = isset( $this->db->last_error ) ? 'Last error: ' . $this->db->last_error : '';
883
-
884
$this->log( "Updating upload_path in {$this->prefix}options. {$error}" );
885
-
886
$updateOptions = $this->db->query(
887
$this->db->prepare(
888
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'upload_path'", $newUploadPath
889
)
890
);
891
-
892
- if( !$updateOptions ) {
893
$this->log( "Preparing Data Step16: Failed to update upload_path in {$this->prefix}options. {$error}", Logger::TYPE_ERROR );
894
return true;
895
}
@@ -902,27 +831,19 @@ class Data extends JobExecutable {
902
* @return bool
903
*/
904
protected function step17() {
905
- $path = $this->options->destinationDir . "wp-config.php";
906
-
907
$this->log( "Preparing Data Step17: Set WP_CACHE in wp-config.php to false" );
908
-
909
if( false === ($content = file_get_contents( $path )) ) {
910
$this->log( "Preparing Data Step17: Failed to update WP_CACHE in wp-config.php. Can't read wp-config.php", Logger::TYPE_ERROR );
911
return false;
912
}
913
-
914
-
915
// Get WP_CACHE from wp-config.php
916
- preg_match( "/define\s*\(\s*'WP_CACHE'\s*,\s*(.*)\s*\);/", $content, $matches );
917
-
918
if( !empty( $matches[1] ) ) {
919
$matches[1];
920
-
921
- $pattern = "/define\s*\(\s*'WP_CACHE'\s*,\s*(.*)\s*\);/";
922
-
923
$replace = "define('WP_CACHE',false); // " . $matches[1];
924
- $replace.= " // Changed by WP-Staging";
925
-
926
if( null === ($content = preg_replace( array($pattern), $replace, $content )) ) {
927
$this->log( "Preparing Data: Failed to change WP_CACHE", Logger::TYPE_ERROR );
928
return false;
@@ -930,7 +851,6 @@ class Data extends JobExecutable {
930
} else {
931
$this->log( "Preparing Data Step17: WP_CACHE not defined in wp-config.php. Skipping this step." );
932
}
933
-
934
if( false === @file_put_contents( $path, $content ) ) {
935
$this->log( "Preparing Data Step17: Failed to update WP_CACHE. Can't save contents", Logger::TYPE_ERROR );
936
return false;
@@ -939,21 +859,213 @@ class Data extends JobExecutable {
939
return true;
940
}
941
942
/**
943
* Get Upload Path to staging site
944
* @return boolean|string
945
*/
946
protected function getNewUploadPath() {
947
$uploadPath = get_option( 'upload_path' );
948
-
949
if( !$uploadPath ) {
950
return false;
951
}
952
-
953
- $customSlug = str_replace( \WPStaging\WPStaging::getWPpath(), '', $uploadPath );
954
-
955
$newUploadPath = \WPStaging\WPStaging::getWPpath() . $this->options->cloneDirectoryName . DIRECTORY_SEPARATOR . $customSlug;
956
-
957
return $newUploadPath;
958
}
959
@@ -962,16 +1074,18 @@ class Data extends JobExecutable {
962
* @return string
963
*/
964
protected function getStagingSiteUrl() {
965
-
966
if( !empty( $this->options->cloneHostname ) ) {
967
return $this->options->cloneHostname;
968
}
969
-
970
if( $this->isSubDir() ) {
971
- return trailingslashit( $this->multisiteHomeDomain ) . trailingslashit($this->getSubDir()) . $this->options->cloneDirectoryName;
972
- }
973
-
974
- return trailingslashit( $this->multisiteHomeDomain ) . $this->options->cloneDirectoryName;
975
}
976
977
/**
@@ -983,7 +1097,6 @@ class Data extends JobExecutable {
983
// This is happening much more often than you would expect
984
$siteurl = preg_replace( '#^https?://#', '', rtrim( get_option( 'siteurl' ), '/' ) );
985
$home = preg_replace( '#^https?://#', '', rtrim( get_option( 'home' ), '/' ) );
986
-
987
if( $home !== $siteurl ) {
988
return true;
989
}
@@ -997,11 +1110,9 @@ class Data extends JobExecutable {
997
protected function getSubDir() {
998
$home = get_option( 'home' );
999
$siteurl = get_option( 'siteurl' );
1000
-
1001
if( empty( $home ) || empty( $siteurl ) ) {
1002
return '';
1003
}
1004
-
1005
$dir = str_replace( $home, '', $siteurl );
1006
return str_replace( '/', '', $dir );
1007
}
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;
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
if( $this->isRoot() ) {
94
return false;
95
}
96
// Over limits threshold
97
if( $this->isOverThreshold() ) {
98
// Prepare response and save current progress
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
}
123
*/
124
protected function isFinished() {
125
return (
126
+ !isset( $this->options->isRunning ) ||
127
$this->options->currentStep > $this->options->totalSteps ||
128
!method_exists( $this, "step" . $this->options->currentStep )
129
);
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
165
}
166
167
/**
168
+ * Copy wp-config.php from the staging site if it is located outside of root one level up or
169
+ * copy default wp-config.php if production site uses bedrock or any other boilerplate solution that stores wp default config data elsewhere.
170
* @return boolean
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
185
+ if( $this->copy( $source, $destination ) ) {
186
+ $this->log( "Preparing Data Step0: Copy wp-config.php file from source {$source} to {$destination}", Logger::TYPE_INFO );
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 ) ) {
196
+ $this->log( "Preparing Data Step0: Can not alter db credentials in wp-config.php", Logger::TYPE_INFO );
197
+ return false;
198
+ }
199
+ }
200
+ $this->log( "Preparing Data Step0: Successful", Logger::TYPE_INFO );
201
+ return true;
202
+ }
203
204
+ /**
205
+ * Copy files with symlink support
206
+ * @param type $source
207
+ * @param type $destination
208
+ * @return boolean
209
+ */
210
+ protected function copy( $source, $destination ) {
211
+ // Copy symbolic link
212
if( is_link( $source ) ) {
213
+ $this->log( "Preparing Data: Symbolic link found...", Logger::TYPE_INFO );
214
if( !@copy( readlink( $source ), $destination ) ) {
215
$errors = error_get_last();
216
+ $this->log( "Preparing Data: Failed to copy {$source} Error: {$errors['message']} {$source} -> {$destination}", Logger::TYPE_ERROR );
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
+
229
+ /**
230
+ * Make sure wp-config.php contains correct db credentials
231
+ * @param type $source
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
244
+ define( 'DB_USER', '" . DB_USER . "' );\r\n
245
+ /** MySQL database password */\r\n
246
+ define( 'DB_PASSWORD', '" . DB_PASSWORD . "' );\r\n
247
+ /** MySQL hostname */\r\n
248
+ define( 'DB_HOST', '" . DB_HOST . "' );\r\n
249
+ /** Database Charset to use in creating database tables. */\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
+
261
+ /**
262
+ * Check if wp-config.php contains important constants
263
+ * @param type $source
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;
299
}
300
return true;
301
}
302
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
$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
"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
}
332
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" );
342
return true;
343
}
344
// Skip - Table is not selected or updated
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
)
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
* @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
}
402
403
/**
404
+ * Update Table Prefix in wp_usermeta
405
* @return bool
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}" );
426
return false;
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
* @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
473
);
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
}
488
+ $this->Log( "Preparing Data Step6: Finished successfully" );
489
return true;
490
}
491
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
}
515
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
* @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
* @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;
599
}
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
}
607
+ $this->Log( "Preparing Data Step 10: Finished successfully" );
608
return true;
609
}
610
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
} 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
}
640
+ $this->Log( "Preparing Data Step 11: Finished successfully" );
641
return true;
642
}
643
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
} 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;
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
} 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
}
706
+ $this->Log( "Preparing Data Step13: Finished successfully" );
707
return true;
708
}
709
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
}
753
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
*/
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;
824
}
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
} 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;
859
return true;
860
}
861
862
+ /**
863
+ * Add UPLOADS constant in wp-config.php or change it to correct destination (multisite type /sites/2/)
864
+ * @return bool
865
+ */
866
+ protected function step18() {
867
+ $path = $this->options->destinationDir . "wp-config.php";
868
+ $this->log( "Preparing Data Step18: Update UPLOADS constant in wp-config.php" );
869
+ if( false === ($content = file_get_contents( $path )) ) {
870
+ $this->log( "Preparing Data Step18: Failed to get UPLOADS in wp-config.php. Can't read wp-config.php", Logger::TYPE_ERROR );
871
+ return false;
872
+ }
873
+ // Get UPLOADS from wp-config.php if there is already one
874
+ preg_match( "/define\s*\(\s*['\"]UPLOADS['\"]\s*,\s*(.*)\s*\);/", $content, $matches );
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;
882
+ }
883
+ } else {
884
+ $this->log( "Preparing Data Step18: UPLOADS not defined in wp-config.php. Creating new entry." );
885
+ // Find ABSPATH and add UPLOAD constant above
886
+ preg_match( "/if\s*\(\s*\s*!\s*defined\s*\(\s*['\"]ABSPATH['\"]\s*(.*)\s*\)\s*\)/", $content, $matches );
887
+ if( !empty( $matches[0] ) ) {
888
+ $matches[0];
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;
895
+ }
896
+ } else {
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
+ }
904
+ $this->Log( "Preparing Data Step18: Finished successfully" );
905
+ return true;
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
1046
+ * @return boolean
1047
+ */
1048
+ protected function getMultisiteUploadFolder() {
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
+
1058
/**
1059
* Get Upload Path to staging site
1060
* @return boolean|string
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
* @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
1091
/**
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
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
}
apps/Backend/views/clone/ajax/process-lock.php CHANGED
@@ -7,7 +7,7 @@
7
</button>
8
9
<button type="button" id="wpstg-restart-cloning" class="wpstg-link-btn button-primary wpstg-button">
10
- <?php echo __("Start over and stop other process", "wp-staging")?>
11
</button>
12
13
7
</button>
8
9
<button type="button" id="wpstg-restart-cloning" class="wpstg-link-btn button-primary wpstg-button">
10
+ <?php echo __("Stop other process", "wp-staging")?>
11
</button>
12
13
apps/Backend/views/welcome/welcome.php CHANGED
@@ -1,7 +1,7 @@
1
<div class="" id="wpstg-welcome">
2
<div style="border: 2px solid white;padding: 20px;margin-bottom:20px;">
3
<h2 class="wpstg-h2">
4
- <span class="wpstg-heading-pro"><?php _e( 'WP Staging Pro', 'wp-staging' ); ?></span><?php _e( ' - Migrate and copy over staging site to live site', 'wp-staging' ); ?>
5
</h2>
6
<li><strong>Cloning</strong> - <?php _e( 'Create a clone of your website with a simple click', 'wp-staging' ); ?></li>
7
<li><strong>Push Changes</strong> - <?php _e( 'Copy plugin and theme files from staging to live site', 'wp-staging' ); ?></li>
1
<div class="" id="wpstg-welcome">
2
<div style="border: 2px solid white;padding: 20px;margin-bottom:20px;">
3
<h2 class="wpstg-h2">
4
+ <span class="wpstg-heading-pro"><?php _e( 'WP Staging Pro', 'wp-staging' ); ?></span><?php _e( ' - Copy Themes & Plugins from Staging to Live Site', 'wp-staging' ); ?>
5
</h2>
6
<li><strong>Cloning</strong> - <?php _e( 'Create a clone of your website with a simple click', 'wp-staging' ); ?></li>
7
<li><strong>Push Changes</strong> - <?php _e( 'Copy plugin and theme files from staging to live site', 'wp-staging' ); ?></li>
apps/Core/Utils/functions.php CHANGED
@@ -7,11 +7,11 @@
7
*/
8
function wpstg_get_permissions_for_directory() {
9
$octal = 0755;
10
- if (defined('FS_CHMOD_DIR')) {
11
$octal = FS_CHMOD_DIR;
12
}
13
14
- return apply_filters('wpstg_folder_permission', $octal);
15
}
16
17
/**
@@ -170,39 +170,87 @@ function wpstg_is_stagingsite() {
170
return true;
171
}
172
173
- if( file_exists( ABSPATH . '.wp-staging')){
174
return true;
175
}
176
177
return false;
178
}
179
180
- /**
181
- * @param string $memory
182
- * @return int
183
- */
184
- function wpstg_get_memory_in_bytes( $memory ) {
185
- // Handle unlimited ones
186
- if( 1 > ( int ) $memory ) {
187
- //return (int) $memory;
188
- // 128 MB default value
189
- return ( int ) 134217728;
190
- }
191
-
192
- $bytes = ( int ) $memory; // grab only the number
193
- $size = trim( str_replace( $bytes, null, strtolower( $memory ) ) ); // strip away number and lower-case it
194
- // Actual calculation
195
- switch ( $size ) {
196
- case 'k':
197
$bytes *= 1024;
198
break;
199
- case 'm':
200
$bytes *= (1024 * 1024);
201
break;
202
- case 'g':
203
$bytes *= (1024 * 1024 * 1024);
204
break;
205
- }
206
207
- return $bytes;
208
- }
7
*/
8
function wpstg_get_permissions_for_directory() {
9
$octal = 0755;
10
+ if( defined( 'FS_CHMOD_DIR' ) ) {
11
$octal = FS_CHMOD_DIR;
12
}
13
14
+ return apply_filters( 'wpstg_folder_permission', $octal );
15
}
16
17
/**
170
return true;
171
}
172
173
+ if( file_exists( ABSPATH . '.wp-staging' ) ) {
174
return true;
175
}
176
177
return false;
178
}
179
180
+ /**
181
+ * @param string $memory
182
+ * @return int
183
+ */
184
+ function wpstg_get_memory_in_bytes( $memory