Version Description
- Tweak: Lowering default performance settings for more reliability during cloning
- New: Set WP_CACHE to false in wp-config.php after cloning to prevent log in issues to staging site
- New: Compatibility mode to skip certain tables from third party plugins from beeing searched & replaced
- Fix: Do not clone db.php, object-cache.php and advanced-cache.php
- Fix: Show error message if ajax requests fail for any reason
Download this release
Release Info
Developer | ReneHermi |
Plugin | WP Staging – DB & File Duplicator & Migration |
Version | 2.3.8 |
Comparing to | |
See all releases |
Code changes from version 2.3.7 to 2.3.8
- apps/Backend/Modules/Jobs/Cloning.php +5 -0
- apps/Backend/Modules/Jobs/Data.php +43 -1
- apps/Backend/Modules/Jobs/Files.php +34 -14
- apps/Backend/Modules/Jobs/Job.php +11 -3
- apps/Backend/Modules/Jobs/Multisite/Data.php +980 -938
- apps/Backend/Modules/Jobs/Multisite/Database.php +315 -315
- apps/Backend/Modules/Jobs/Multisite/Directories.php +655 -655
- apps/Backend/Modules/Jobs/Multisite/Files.php +384 -365
- apps/Backend/Modules/Jobs/Multisite/Finish.php +115 -115
- apps/Backend/Modules/Jobs/Multisite/SearchReplace.php +776 -772
- apps/Backend/Modules/Jobs/SearchReplace.php +9 -3
- apps/Backend/Modules/Jobs/Updating.php +24 -6
- apps/Backend/Modules/Views/Forms/Settings.php +3 -5
- apps/Backend/public/js/wpstg-admin.js +14 -5
- apps/Backend/views/clone/multi-site/index.php +1 -1
- apps/Backend/views/settings/main-settings.php +4 -4
- apps/Core/WPStaging.php +1 -9
- apps/Core/thirdParty/thirdPartyCompatibility.php +33 -0
- languages/wp-staging-de_DE.po +503 -503
- languages/wp-staging-en_gb.po +417 -417
- languages/wp-staging-it.po +417 -417
- languages/wp-staging-it_1.po +417 -417
- readme.txt +10 -2
- wp-staging.php +2 -2
apps/Backend/Modules/Jobs/Cloning.php
CHANGED
@@ -47,6 +47,11 @@ class Cloning extends Job {
|
|
47 |
'.log',
|
48 |
'web.config'
|
49 |
);
|
|
|
|
|
|
|
|
|
|
|
50 |
$this->options->currentStep = 0;
|
51 |
|
52 |
|
47 |
'.log',
|
48 |
'web.config'
|
49 |
);
|
50 |
+
$this->options->excludedFilesFullPath = array(
|
51 |
+
'wp-content' . DIRECTORY_SEPARATOR . 'db.php',
|
52 |
+
'wp-content' . DIRECTORY_SEPARATOR . 'object-cache.php',
|
53 |
+
'wp-content' . DIRECTORY_SEPARATOR . 'advanced-cache.php'
|
54 |
+
);
|
55 |
$this->options->currentStep = 0;
|
56 |
|
57 |
|
apps/Backend/Modules/Jobs/Data.php
CHANGED
@@ -77,7 +77,7 @@ class Data extends JobExecutable {
|
|
77 |
* @return void
|
78 |
*/
|
79 |
protected function calculateTotalSteps() {
|
80 |
-
$this->options->totalSteps =
|
81 |
}
|
82 |
|
83 |
/**
|
@@ -759,6 +759,48 @@ class Data extends JobExecutable {
|
|
759 |
return true;
|
760 |
}
|
761 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
762 |
protected function getNewUploadPath() {
|
763 |
$uploadPath = get_option( 'upload_path' );
|
764 |
|
77 |
* @return void
|
78 |
*/
|
79 |
protected function calculateTotalSteps() {
|
80 |
+
$this->options->totalSteps = 14;
|
81 |
}
|
82 |
|
83 |
/**
|
759 |
return true;
|
760 |
}
|
761 |
|
762 |
+
/**
|
763 |
+
* Update WP_CACHE in wp-config.php
|
764 |
+
* @return bool
|
765 |
+
*/
|
766 |
+
protected function step14() {
|
767 |
+
$path = ABSPATH . $this->options->cloneDirectoryName . "/wp-config.php";
|
768 |
+
|
769 |
+
$this->log( "Preparing Data Step14: Set WP_CACHE in wp-config.php to false" );
|
770 |
+
|
771 |
+
if( false === ($content = file_get_contents( $path )) ) {
|
772 |
+
$this->log( "Preparing Data Step14: Failed to update WP_CACHE in wp-config.php. Can't read wp-config.php", Logger::TYPE_ERROR );
|
773 |
+
return false;
|
774 |
+
}
|
775 |
+
|
776 |
+
|
777 |
+
// Get WP_CACHE from wp-config.php
|
778 |
+
preg_match( "/define\s*\(\s*'WP_CACHE'\s*,\s*(.*)\s*\);/", $content, $matches );
|
779 |
+
|
780 |
+
if( !empty( $matches[1] ) ) {
|
781 |
+
$matches[1];
|
782 |
+
|
783 |
+
$pattern = "/define\s*\(\s*'WP_CACHE'\s*,\s*(.*)\s*\);/";
|
784 |
+
|
785 |
+
$replace = "define('WP_CACHE',false); // " . $matches[1];
|
786 |
+
$replace.= " // Changed by WP-Staging";
|
787 |
+
|
788 |
+
if( null === ($content = preg_replace( array($pattern), $replace, $content )) ) {
|
789 |
+
$this->log( "Preparing Data: Failed to change WP_CACHE", Logger::TYPE_ERROR );
|
790 |
+
return false;
|
791 |
+
}
|
792 |
+
} else {
|
793 |
+
$this->log( "Preparing Data Step14: WP_CACHE not defined in wp-config.php. Skipping this step." );
|
794 |
+
}
|
795 |
+
|
796 |
+
if( false === @file_put_contents( $path, $content ) ) {
|
797 |
+
$this->log( "Preparing Data Step14: Failed to update WP_CACHE. Can't save contents", Logger::TYPE_ERROR );
|
798 |
+
return false;
|
799 |
+
}
|
800 |
+
$this->Log( "Preparing Data: Finished Step 14 successfully" );
|
801 |
+
return true;
|
802 |
+
}
|
803 |
+
|
804 |
protected function getNewUploadPath() {
|
805 |
$uploadPath = get_option( 'upload_path' );
|
806 |
|
apps/Backend/Modules/Jobs/Files.php
CHANGED
@@ -161,16 +161,22 @@ class Files extends JobExecutable {
|
|
161 |
|
162 |
// Directory is excluded
|
163 |
if( $this->isDirectoryExcluded( $directory ) ) {
|
164 |
-
$this->debugLog( "
|
165 |
return false;
|
166 |
}
|
167 |
|
168 |
// File is excluded
|
169 |
if( $this->isFileExcluded( $file ) ) {
|
170 |
-
$this->debugLog( "
|
171 |
return false;
|
172 |
}
|
173 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
174 |
// File is over maximum allowed file size (8MB)
|
175 |
if( $fileSize >= $this->settings->maxFileSize * 1000000 ) {
|
176 |
$this->log( "Skipping big file: {$file}", Logger::TYPE_INFO );
|
@@ -224,7 +230,7 @@ class Files extends JobExecutable {
|
|
224 |
$destinationPath = $this->destination . $relativePath;
|
225 |
$destinationDirectory = dirname( $destinationPath );
|
226 |
|
227 |
-
if( !is_dir( $destinationDirectory ) && !@mkdir( $destinationDirectory,
|
228 |
$this->log( "Files: Can not create directory {$destinationDirectory}", Logger::TYPE_ERROR );
|
229 |
return false;
|
230 |
}
|
@@ -273,22 +279,36 @@ class Files extends JobExecutable {
|
|
273 |
* @return boolean
|
274 |
*/
|
275 |
private function isFileExcluded( $file ) {
|
276 |
-
$excluded = false;
|
277 |
-
foreach ( $this->options->excludedFiles as $excludedFile ) {
|
278 |
-
if( stripos( strrev( $file ), strrev( $excludedFile ) ) === 0 ) {
|
279 |
-
$excluded = true;
|
280 |
-
break;
|
281 |
-
}
|
282 |
-
}
|
283 |
|
|
|
|
|
|
|
284 |
// Do not copy wp-config.php if the clone gets updated. This is for security purposes,
|
285 |
// because if the updating process fails, the staging site would not be accessable any longer
|
286 |
if( isset( $this->options->mainJob ) && $this->options->mainJob == "updating" && stripos( strrev( $file ), strrev( "wp-config.php" ) ) === 0 ) {
|
287 |
-
|
|
|
288 |
}
|
289 |
|
290 |
|
291 |
-
return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
292 |
}
|
293 |
|
294 |
/**
|
@@ -337,7 +357,7 @@ class Files extends JobExecutable {
|
|
337 |
$directory = $this->sanitizeDirectorySeparator( $directory );
|
338 |
|
339 |
foreach ( $this->options->extraDirectories as $extraDirectory ) {
|
340 |
-
if( strpos( $directory, $this->sanitizeDirectorySeparator($extraDirectory) ) === 0 ) {
|
341 |
return true;
|
342 |
}
|
343 |
}
|
161 |
|
162 |
// Directory is excluded
|
163 |
if( $this->isDirectoryExcluded( $directory ) ) {
|
164 |
+
$this->debugLog( "Directory Excluded: {$file}", Logger::TYPE_INFO );
|
165 |
return false;
|
166 |
}
|
167 |
|
168 |
// File is excluded
|
169 |
if( $this->isFileExcluded( $file ) ) {
|
170 |
+
$this->debugLog( "File excluded: {$file}", Logger::TYPE_INFO );
|
171 |
return false;
|
172 |
}
|
173 |
+
|
174 |
+
// Path + File is excluded
|
175 |
+
if( $this->isFileExcludedFullPath( $file ) ) {
|
176 |
+
$this->debugLog( "File Excluded Full Path: {$file}", Logger::TYPE_INFO );
|
177 |
+
return false;
|
178 |
+
}
|
179 |
+
|
180 |
// File is over maximum allowed file size (8MB)
|
181 |
if( $fileSize >= $this->settings->maxFileSize * 1000000 ) {
|
182 |
$this->log( "Skipping big file: {$file}", Logger::TYPE_INFO );
|
230 |
$destinationPath = $this->destination . $relativePath;
|
231 |
$destinationDirectory = dirname( $destinationPath );
|
232 |
|
233 |
+
if( !is_dir( $destinationDirectory ) && !@mkdir( $destinationDirectory, 0755, true ) ) {
|
234 |
$this->log( "Files: Can not create directory {$destinationDirectory}", Logger::TYPE_ERROR );
|
235 |
return false;
|
236 |
}
|
279 |
* @return boolean
|
280 |
*/
|
281 |
private function isFileExcluded( $file ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
282 |
|
283 |
+
if( in_array( basename( $file ), $this->options->excludedFiles ) ) {
|
284 |
+
return true;
|
285 |
+
}
|
286 |
// Do not copy wp-config.php if the clone gets updated. This is for security purposes,
|
287 |
// because if the updating process fails, the staging site would not be accessable any longer
|
288 |
if( isset( $this->options->mainJob ) && $this->options->mainJob == "updating" && stripos( strrev( $file ), strrev( "wp-config.php" ) ) === 0 ) {
|
289 |
+
return true;
|
290 |
+
|
291 |
}
|
292 |
|
293 |
|
294 |
+
return false;
|
295 |
+
}
|
296 |
+
|
297 |
+
/**
|
298 |
+
* Check if certain file is excluded from copying process
|
299 |
+
*
|
300 |
+
* @param string $file filename including ending + (part) path e.g wp-content/db.php
|
301 |
+
* @return boolean
|
302 |
+
*/
|
303 |
+
private function isFileExcludedFullPath( $file ) {
|
304 |
+
// If path + file exists
|
305 |
+
foreach ($this->options->excludedFilesFullPath as $excludedFile){
|
306 |
+
if( false !== strpos( $file, $excludedFile )){
|
307 |
+
return true;
|
308 |
+
}
|
309 |
+
}
|
310 |
+
|
311 |
+
return false;
|
312 |
}
|
313 |
|
314 |
/**
|
357 |
$directory = $this->sanitizeDirectorySeparator( $directory );
|
358 |
|
359 |
foreach ( $this->options->extraDirectories as $extraDirectory ) {
|
360 |
+
if( strpos( $directory, $this->sanitizeDirectorySeparator( $extraDirectory ) ) === 0 ) {
|
361 |
return true;
|
362 |
}
|
363 |
}
|
apps/Backend/Modules/Jobs/Job.php
CHANGED
@@ -12,6 +12,8 @@ use WPStaging\Utils\Logger;
|
|
12 |
use WPStaging\WPStaging;
|
13 |
use WPStaging\Utils\Cache;
|
14 |
use WPStaging\Utils\Multisite;
|
|
|
|
|
15 |
|
16 |
/**
|
17 |
* Class Job
|
@@ -87,15 +89,21 @@ abstract class Job implements JobInterface {
|
|
87 |
|
88 |
/**
|
89 |
* Multisite home domain without scheme
|
90 |
-
* @var
|
91 |
*/
|
92 |
protected $multisiteDomainWithoutScheme;
|
93 |
|
94 |
/**
|
95 |
* Multisite home domain without scheme
|
96 |
-
* @var
|
97 |
*/
|
98 |
protected $multisiteHomeDomain;
|
|
|
|
|
|
|
|
|
|
|
|
|
99 |
|
100 |
/**
|
101 |
* @var int
|
@@ -109,12 +117,12 @@ abstract class Job implements JobInterface {
|
|
109 |
// Get max limits
|
110 |
$this->start = $this->time();
|
111 |
$this->maxMemoryLimit = $this->getMemoryInBytes( @ini_get( "memory_limit" ) );
|
|
|
112 |
|
113 |
$multisite = new Multisite;
|
114 |
$this->multisiteHomeUrlWithoutScheme = $multisite->getHomeUrlWithoutScheme();
|
115 |
$this->multisiteHomeDomain = $multisite->getHomeDomain();
|
116 |
$this->multisiteDomainWithoutScheme = $multisite->getHomeDomainWithoutScheme();
|
117 |
-
//$this->multisiteUrl = $multisite->getHomeDomain();
|
118 |
|
119 |
//$this->maxExecutionTime = (int) ini_get("max_execution_time");
|
120 |
$this->maxExecutionTime = ( int ) 30;
|
12 |
use WPStaging\WPStaging;
|
13 |
use WPStaging\Utils\Cache;
|
14 |
use WPStaging\Utils\Multisite;
|
15 |
+
use WPStaging\thirdParty\thirdPartyCompatibility;
|
16 |
+
|
17 |
|
18 |
/**
|
19 |
* Class Job
|
89 |
|
90 |
/**
|
91 |
* Multisite home domain without scheme
|
92 |
+
* @var string
|
93 |
*/
|
94 |
protected $multisiteDomainWithoutScheme;
|
95 |
|
96 |
/**
|
97 |
* Multisite home domain without scheme
|
98 |
+
* @var string
|
99 |
*/
|
100 |
protected $multisiteHomeDomain;
|
101 |
+
|
102 |
+
/**
|
103 |
+
*
|
104 |
+
* @var object
|
105 |
+
*/
|
106 |
+
protected $thirdParty;
|
107 |
|
108 |
/**
|
109 |
* @var int
|
117 |
// Get max limits
|
118 |
$this->start = $this->time();
|
119 |
$this->maxMemoryLimit = $this->getMemoryInBytes( @ini_get( "memory_limit" ) );
|
120 |
+
$this->thirdParty = new thirdPartyCompatibility($this);
|
121 |
|
122 |
$multisite = new Multisite;
|
123 |
$this->multisiteHomeUrlWithoutScheme = $multisite->getHomeUrlWithoutScheme();
|
124 |
$this->multisiteHomeDomain = $multisite->getHomeDomain();
|
125 |
$this->multisiteDomainWithoutScheme = $multisite->getHomeDomainWithoutScheme();
|
|
|
126 |
|
127 |
//$this->maxExecutionTime = (int) ini_get("max_execution_time");
|
128 |
$this->maxExecutionTime = ( int ) 30;
|
apps/Backend/Modules/Jobs/Multisite/Data.php
CHANGED
@@ -1,938 +1,980 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPStaging\Backend\Modules\Jobs\Multisite;
|
4 |
-
|
5 |
-
// No Direct Access
|
6 |
-
if( !defined( "WPINC" ) ) {
|
7 |
-
die;
|
8 |
-
}
|
9 |
-
|
10 |
-
use WPStaging\Utils\Logger;
|
11 |
-
use WPStaging\WPStaging;
|
12 |
-
use WPStaging\Utils\Helper;
|
13 |
-
use WPStaging\Utils\Multisite;
|
14 |
-
use WPStaging\Utils\Strings;
|
15 |
-
use WPStaging\Backend\Modules\Jobs\JobExecutable;
|
16 |
-
|
17 |
-
/**
|
18 |
-
* Class Data
|
19 |
-
* @package WPStaging\Backend\Modules\Jobs
|
20 |
-
*/
|
21 |
-
class Data extends JobExecutable {
|
22 |
-
|
23 |
-
/**
|
24 |
-
* @var \wpdb
|
25 |
-
*/
|
26 |
-
private $db;
|
27 |
-
|
28 |
-
/**
|
29 |
-
* @var string
|
30 |
-
*/
|
31 |
-
private $prefix;
|
32 |
-
|
33 |
-
/**
|
34 |
-
* Tables e.g wpstg3_options
|
35 |
-
* @var array
|
36 |
-
*/
|
37 |
-
private $tables;
|
38 |
-
|
39 |
-
/**
|
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 = 1;
|
52 |
-
}
|
53 |
-
}
|
54 |
-
|
55 |
-
/**
|
56 |
-
* Get a list of tables to copy
|
57 |
-
*/
|
58 |
-
private function getTables() {
|
59 |
-
$strings = new Strings();
|
60 |
-
$this->tables = array();
|
61 |
-
foreach ( $this->options->tables as $table ) {
|
62 |
-
$this->tables[] = $this->options->prefix . $strings->str_replace_first( $this->db->prefix, null, $table );
|
63 |
-
}
|
64 |
-
// Add extra global tables from main multisite (wpstgx_users and wpstgx_usermeta)
|
65 |
-
$this->tables[] = $this->options->prefix . $strings->str_replace_first( $this->db->prefix, null, 'users' );
|
66 |
-
$this->tables[] = $this->options->prefix . $strings->str_replace_first( $this->db->prefix, null, 'usermeta' );
|
67 |
-
}
|
68 |
-
|
69 |
-
/**
|
70 |
-
* Calculate Total Steps in This Job and Assign It to $this->options->totalSteps
|
71 |
-
* @return void
|
72 |
-
*/
|
73 |
-
protected function calculateTotalSteps() {
|
74 |
-
$this->options->totalSteps =
|
75 |
-
}
|
76 |
-
|
77 |
-
/**
|
78 |
-
* Start Module
|
79 |
-
* @return object
|
80 |
-
*/
|
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 |
-
|
91 |
-
/**
|
92 |
-
* Execute the Current Step
|
93 |
-
* Returns false when over threshold limits are hit or when the job is done, true otherwise
|
94 |
-
* @return bool
|
95 |
-
*/
|
96 |
-
protected function execute() {
|
97 |
-
// Fatal error. Let this happen never and break here immediately
|
98 |
-
if( $this->isRoot() ) {
|
99 |
-
return false;
|
100 |
-
}
|
101 |
-
|
102 |
-
// Over limits threshold
|
103 |
-
if( $this->isOverThreshold() ) {
|
104 |
-
// Prepare response and save current progress
|
105 |
-
$this->prepareResponse( false, false );
|
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 |
-
}
|
129 |
-
|
130 |
-
/**
|
131 |
-
* Checks Whether There is Any Job to Execute or Not
|
132 |
-
* @return bool
|
133 |
-
*/
|
134 |
-
protected function isFinished() {
|
135 |
-
return (
|
136 |
-
$this->options->currentStep > $this->options->totalSteps ||
|
137 |
-
!method_exists( $this, "step" . $this->options->currentStep )
|
138 |
-
);
|
139 |
-
}
|
140 |
-
|
141 |
-
/**
|
142 |
-
* Check if current operation is done on the root folder or on the live DB
|
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( $wpdb->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 Path === Staging path
|
160 |
-
if( $this->multisiteHomeDomain . $this->options->cloneDirectoryName === $this->multisiteHomeDomain ) {
|
161 |
-
return true;
|
162 |
-
}
|
163 |
-
|
164 |
-
return false;
|
165 |
-
}
|
166 |
-
|
167 |
-
/**
|
168 |
-
* Check if table exists
|
169 |
-
* @param string $table
|
170 |
-
* @return boolean
|
171 |
-
*/
|
172 |
-
protected function isTable( $table ) {
|
173 |
-
if( $this->db->get_var( "SHOW TABLES LIKE '{$table}'" ) != $table ) {
|
174 |
-
$this->log( "Table {$table} does not exists", Logger::TYPE_ERROR );
|
175 |
-
return false;
|
176 |
-
}
|
177 |
-
return true;
|
178 |
-
}
|
179 |
-
|
180 |
-
/**
|
181 |
-
* Get the install sub directory if WP is installed in sub directory
|
182 |
-
* @return string
|
183 |
-
*/
|
184 |
-
protected function getSubDir() {
|
185 |
-
return '/';
|
186 |
-
|
187 |
-
// $home = get_option( 'home' );
|
188 |
-
// $siteurl = get_option( 'siteurl' );
|
189 |
-
//
|
190 |
-
// if( empty( $home ) || empty( $siteurl ) ) {
|
191 |
-
// return '/';
|
192 |
-
// }
|
193 |
-
//
|
194 |
-
// $dir = str_replace( $home, '', $siteurl );
|
195 |
-
// return '/' . str_replace( '/', '', $dir ) . '/';
|
196 |
-
}
|
197 |
-
|
198 |
-
/**
|
199 |
-
* Copy wp-config.php if it is located outside of root one level up
|
200 |
-
* @todo Needs some more testing before it will be released
|
201 |
-
* @return boolean
|
202 |
-
*/
|
203 |
-
// protected function step0(){
|
204 |
-
// $this->log( "Preparing Data Step0: Check if wp-config.php is located in root path", Logger::TYPE_INFO );
|
205 |
-
//
|
206 |
-
// $dir = trailingslashit( dirname( ABSPATH ) );
|
207 |
-
//
|
208 |
-
// $source = $dir . 'wp-config.php';
|
209 |
-
//
|
210 |
-
// $destination = trailingslashit(ABSPATH) . $this->clone->cloneDirectoryName . DIRECTORY_SEPARATOR . 'wp-config.php';
|
211 |
-
//
|
212 |
-
//
|
213 |
-
// // Do not do anything
|
214 |
-
// if( (!is_file( $source ) && !is_link($source)) || is_file($destination) ) {
|
215 |
-
// $this->log( "Preparing Data Step0: Skip it", Logger::TYPE_INFO );
|
216 |
-
// return true;
|
217 |
-
// }
|
218 |
-
//
|
219 |
-
// // Copy target of a symbolic link
|
220 |
-
// if (is_link($source)){
|
221 |
-
// $this->log( "Preparing Data Step0: Symbolic link found...", Logger::TYPE_INFO );
|
222 |
-
// if (!@copy(readlink($source), $destination)) {
|
223 |
-
// $this->log("Preparing Data Step0: Failed to copy wp-config.php {$source} -> {$destination}", Logger::TYPE_ERROR);
|
224 |
-
// return true;
|
225 |
-
// }
|
226 |
-
// }
|
227 |
-
//
|
228 |
-
// // regular copy of wp-config.php
|
229 |
-
// if (!@copy($source, $destination)) {
|
230 |
-
// $this->log("Preparing Data Step0: Failed to copy wp-config.php {$source} -> {$destination}", Logger::TYPE_ERROR);
|
231 |
-
// return true;
|
232 |
-
// }
|
233 |
-
// $this->log( "Preparing Data Step0: Successfull", Logger::TYPE_INFO );
|
234 |
-
// return true;
|
235 |
-
//
|
236 |
-
// }
|
237 |
-
|
238 |
-
/**
|
239 |
-
* Replace "siteurl" and "home"
|
240 |
-
* @return bool
|
241 |
-
*/
|
242 |
-
protected function step1() {
|
243 |
-
$this->log( "Preparing Data Step1: Updating siteurl and homeurl in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_INFO );
|
244 |
-
|
245 |
-
// Skip - Table does not exist
|
246 |
-
if( false === $this->isTable( $this->prefix . 'options' ) ) {
|
247 |
-
return true;
|
248 |
-
}
|
249 |
-
// Skip - Table is not selected or updated
|
250 |
-
if( !in_array( $this->prefix . 'options', $this->tables ) ) {
|
251 |
-
$this->log( "Preparing Data Step1: Skipping" );
|
252 |
-
return true;
|
253 |
-
}
|
254 |
-
|
255 |
-
// Installed in sub-directory
|
256 |
-
if( $this->isSubDir() ) {
|
257 |
-
$this->log( "Preparing Data Step1: Updating siteurl and homeurl to " . rtrim( $this->multisiteHomeDomain, "/" ) . $this->getSubDir() . $this->options->cloneDirectoryName );
|
258 |
-
// Replace URLs
|
259 |
-
$result = $this->db->query(
|
260 |
-
$this->db->prepare(
|
261 |
-
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'siteurl' or option_name='home'", rtrim( $this->multisiteHomeDomain, "/" ) . $this->getSubDir() . $this->options->cloneDirectoryName
|
262 |
-
)
|
263 |
-
);
|
264 |
-
} else {
|
265 |
-
$this->log( "Preparing Data Step1: Updating siteurl and homeurl to " . rtrim( $this->multisiteHomeDomain, "/" ) . '/' . $this->options->cloneDirectoryName );
|
266 |
-
// Replace URLs
|
267 |
-
$result = $this->db->query(
|
268 |
-
$this->db->prepare(
|
269 |
-
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'siteurl' or option_name='home'", $this->multisiteHomeDomain . '/' . $this->options->cloneDirectoryName
|
270 |
-
)
|
271 |
-
);
|
272 |
-
}
|
273 |
-
|
274 |
-
|
275 |
-
// All good
|
276 |
-
if( $result ) {
|
277 |
-
return true;
|
278 |
-
}
|
279 |
-
|
280 |
-
$this->log( "Preparing Data Step1: Failed to update siteurl and homeurl in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_ERROR );
|
281 |
-
return false;
|
282 |
-
}
|
283 |
-
|
284 |
-
/**
|
285 |
-
* Update "wpstg_is_staging_site"
|
286 |
-
* @return bool
|
287 |
-
*/
|
288 |
-
protected function step2() {
|
289 |
-
|
290 |
-
$this->log( "Preparing Data Step2: Updating row wpstg_is_staging_site in {$this->prefix}options {$this->db->last_error}" );
|
291 |
-
|
292 |
-
// Skip - Table does not exist
|
293 |
-
if( false === $this->isTable( $this->prefix . 'options' ) ) {
|
294 |
-
return true;
|
295 |
-
}
|
296 |
-
// Skip - Table is not selected or updated
|
297 |
-
if( !in_array( $this->prefix . 'options', $this->tables ) ) {
|
298 |
-
$this->log( "Preparing Data Step2: Skipping" );
|
299 |
-
return true;
|
300 |
-
}
|
301 |
-
|
302 |
-
$result = $this->db->query(
|
303 |
-
$this->db->prepare(
|
304 |
-
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'wpstg_is_staging_site'", "true"
|
305 |
-
)
|
306 |
-
);
|
307 |
-
|
308 |
-
// No errors but no option name such as wpstg_is_staging_site
|
309 |
-
if( '' === $this->db->last_error && 0 == $result ) {
|
310 |
-
$result = $this->db->query(
|
311 |
-
$this->db->prepare(
|
312 |
-
"INSERT INTO {$this->prefix}options (option_name,option_value) VALUES ('wpstg_is_staging_site',%s)", "true"
|
313 |
-
)
|
314 |
-
);
|
315 |
-
}
|
316 |
-
|
317 |
-
// All good
|
318 |
-
if( $result ) {
|
319 |
-
return true;
|
320 |
-
}
|
321 |
-
|
322 |
-
$this->log( "Preparing Data Step2: Failed to update wpstg_is_staging_site in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_ERROR );
|
323 |
-
return false;
|
324 |
-
}
|
325 |
-
|
326 |
-
/**
|
327 |
-
* Update rewrite_rules
|
328 |
-
* @return bool
|
329 |
-
*/
|
330 |
-
protected function step3() {
|
331 |
-
|
332 |
-
$this->log( "Preparing Data Step3: Updating rewrite_rules in {$this->prefix}options {$this->db->last_error}" );
|
333 |
-
|
334 |
-
// Skip - Table does not exist
|
335 |
-
if( false === $this->isTable( $this->prefix . 'options' ) ) {
|
336 |
-
return true;
|
337 |
-
}
|
338 |
-
|
339 |
-
// Skip - Table is not selected or updated
|
340 |
-
if( !in_array( $this->prefix . 'options', $this->tables ) ) {
|
341 |
-
$this->log( "Preparing Data Step3: Skipping" );
|
342 |
-
return true;
|
343 |
-
}
|
344 |
-
|
345 |
-
$result = $this->db->query(
|
346 |
-
$this->db->prepare(
|
347 |
-
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'rewrite_rules'", ' '
|
348 |
-
)
|
349 |
-
);
|
350 |
-
|
351 |
-
// All good
|
352 |
-
if( $result ) {
|
353 |
-
return true;
|
354 |
-
}
|
355 |
-
|
356 |
-
$this->log( "Preparing Data Step3: Failed to update rewrite_rules in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_ERROR );
|
357 |
-
return true;
|
358 |
-
}
|
359 |
-
|
360 |
-
/**
|
361 |
-
* Update Table Prefix in wp_usermeta and wp_options
|
362 |
-
* @return bool
|
363 |
-
*/
|
364 |
-
protected function step4() {
|
365 |
-
$this->log( "Preparing Data Step4: Updating db prefix in {$this->prefix}usermeta. {$this->db->last_error}" );
|
366 |
-
|
367 |
-
// Skip - Table does not exist
|
368 |
-
if( false === $this->isTable( $this->prefix . 'usermeta' ) ) {
|
369 |
-
return true;
|
370 |
-
}
|
371 |
-
|
372 |
-
// Skip - Table is not selected or updated
|
373 |
-
if( !in_array( $this->prefix . 'usermeta', $this->tables ) ) {
|
374 |
-
$this->log( "Preparing Data Step4: Skipping" );
|
375 |
-
return true;
|
376 |
-
}
|
377 |
-
|
378 |
-
$update = $this->db->query(
|
379 |
-
$this->db->prepare(
|
380 |
-
"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 . "_%"
|
381 |
-
)
|
382 |
-
);
|
383 |
-
|
384 |
-
if( !$update ) {
|
385 |
-
$this->log( "Preparing Data Step4: Failed to update {$this->prefix}usermeta meta_key database table prefixes; {$this->db->last_error}", Logger::TYPE_ERROR );
|
386 |
-
$this->returnException( "Data Crunching Step 4: Failed to update {$this->prefix}usermeta meta_key database table prefixes; {$this->db->last_error}" );
|
387 |
-
return false;
|
388 |
-
}
|
389 |
-
return true;
|
390 |
-
}
|
391 |
-
|
392 |
-
/**
|
393 |
-
* Update $table_prefix in wp-config.php
|
394 |
-
* @return bool
|
395 |
-
*/
|
396 |
-
protected function step5() {
|
397 |
-
$path = ABSPATH . $this->options->cloneDirectoryName . "/wp-config.php";
|
398 |
-
|
399 |
-
$this->log( "Preparing Data Step5: Updating table_prefix in {$path} to " . $this->prefix );
|
400 |
-
if( false === ($content = file_get_contents( $path )) ) {
|
401 |
-
$this->log( "Preparing Data Step5: Failed to update table_prefix in {$path}. Can't read contents", Logger::TYPE_ERROR );
|
402 |
-
return false;
|
403 |
-
}
|
404 |
-
|
405 |
-
// Replace table prefix
|
406 |
-
$content = str_replace( '$table_prefix', '$table_prefix = \'' . $this->prefix . '\';//', $content );
|
407 |
-
|
408 |
-
// Replace URLs
|
409 |
-
$content = str_replace( $this->multisiteHomeDomain, $this->multisiteHomeDomain . '/' . $this->options->cloneDirectoryName, $content );
|
410 |
-
|
411 |
-
if( false === @file_put_contents( $path, $content ) ) {
|
412 |
-
$this->log( "Preparing Data Step5: Failed to update $table_prefix in {$path} to " . $this->prefix . ". Can't save contents", Logger::TYPE_ERROR );
|
413 |
-
return false;
|
414 |
-
}
|
415 |
-
|
416 |
-
return true;
|
417 |
-
}
|
418 |
-
|
419 |
-
/**
|
420 |
-
* Reset index.php to original file
|
421 |
-
* This is needed if live site is located in subfolder
|
422 |
-
* Check first if main wordpress is used in subfolder and index.php in parent directory
|
423 |
-
* @see: https://codex.wordpress.org/Giving_WordPress_Its_Own_Directory
|
424 |
-
* @return bool
|
425 |
-
*/
|
426 |
-
protected function step6() {
|
427 |
-
|
428 |
-
if( !$this->isSubDir() ) {
|
429 |
-
$this->debugLog( "Preparing Data Step6: WP installation is not in a subdirectory! All good, skipping this step" );
|
430 |
-
return true;
|
431 |
-
}
|
432 |
-
|
433 |
-
$path = ABSPATH . $this->options->cloneDirectoryName . "/index.php";
|
434 |
-
|
435 |
-
if( false === ($content = file_get_contents( $path )) ) {
|
436 |
-
$this->log( "Preparing Data Step6: Failed to reset {$path} for sub directory; can't read contents", Logger::TYPE_ERROR );
|
437 |
-
return false;
|
438 |
-
}
|
439 |
-
|
440 |
-
|
441 |
-
if( !preg_match( "/(require(.*)wp-blog-header.php' \);)/", $content, $matches ) ) {
|
442 |
-
$this->log(
|
443 |
-
"Preparing Data Step6: Failed to reset index.php for sub directory; wp-blog-header.php is missing", Logger::TYPE_ERROR
|
444 |
-
);
|
445 |
-
return false;
|
446 |
-
}
|
447 |
-
$this->log( "Preparing Data: WP installation is in a subdirectory. Progressing..." );
|
448 |
-
|
449 |
-
$pattern = "/require(.*) dirname(.*) __FILE__ (.*) \. '(.*)wp-blog-header.php'(.*);/";
|
450 |
-
|
451 |
-
$replace = "require( dirname( __FILE__ ) . '/wp-blog-header.php' ); // " . $matches[0];
|
452 |
-
$replace.= " // Changed by WP-Staging";
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
if( null === ($content = preg_replace( array($pattern), $replace, $content )) ) {
|
457 |
-
$this->log( "Preparing Data: Failed to reset index.php for sub directory; replacement failed", Logger::TYPE_ERROR );
|
458 |
-
return false;
|
459 |
-
}
|
460 |
-
|
461 |
-
if( false === @file_put_contents( $path, $content ) ) {
|
462 |
-
$this->log( "Preparing Data: Failed to reset index.php for sub directory; can't save contents", Logger::TYPE_ERROR );
|
463 |
-
return false;
|
464 |
-
}
|
465 |
-
$this->Log( "Preparing Data: Finished Step 6 successfully" );
|
466 |
-
return true;
|
467 |
-
}
|
468 |
-
|
469 |
-
/**
|
470 |
-
* Update wpstg_rmpermalinks_executed
|
471 |
-
* @return bool
|
472 |
-
*/
|
473 |
-
protected function step7() {
|
474 |
-
|
475 |
-
$this->log( "Preparing Data Step7: Updating wpstg_rmpermalinks_executed in {$this->prefix}options {$this->db->last_error}" );
|
476 |
-
|
477 |
-
// Skip - Table does not exist
|
478 |
-
if( false === $this->isTable( $this->prefix . 'options' ) ) {
|
479 |
-
return true;
|
480 |
-
}
|
481 |
-
|
482 |
-
// Skip - Table is not selected or updated
|
483 |
-
if( !in_array( $this->prefix . 'options', $this->tables ) ) {
|
484 |
-
$this->log( "Preparing Data Step7: Skipping" );
|
485 |
-
return true;
|
486 |
-
}
|
487 |
-
|
488 |
-
$result = $this->db->query(
|
489 |
-
$this->db->prepare(
|
490 |
-
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'wpstg_rmpermalinks_executed'", ' '
|
491 |
-
)
|
492 |
-
);
|
493 |
-
|
494 |
-
// All good
|
495 |
-
if( $result ) {
|
496 |
-
$this->Log( "Preparing Data Step7: Finished Step 7 successfully" );
|
497 |
-
return true;
|
498 |
-
}
|
499 |
-
|
500 |
-
$this->log( "Failed to update wpstg_rmpermalinks_executed in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_WARNING );
|
501 |
-
return true;
|
502 |
-
}
|
503 |
-
|
504 |
-
/**
|
505 |
-
* Update permalink_structure
|
506 |
-
* @return bool
|
507 |
-
*/
|
508 |
-
protected function step8() {
|
509 |
-
|
510 |
-
$this->log( "Preparing Data Step8: Updating permalink_structure in {$this->prefix}options {$this->db->last_error}" );
|
511 |
-
|
512 |
-
// Skip - Table does not exist
|
513 |
-
if( false === $this->isTable( $this->prefix . 'options' ) ) {
|
514 |
-
return true;
|
515 |
-
}
|
516 |
-
|
517 |
-
// Skip - Table is not selected or updated
|
518 |
-
if( !in_array( $this->prefix . 'options', $this->tables ) ) {
|
519 |
-
$this->log( "Preparing Data Step8: Skipping" );
|
520 |
-
return true;
|
521 |
-
}
|
522 |
-
|
523 |
-
$result = $this->db->query(
|
524 |
-
$this->db->prepare(
|
525 |
-
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'permalink_structure'", ' '
|
526 |
-
)
|
527 |
-
);
|
528 |
-
|
529 |
-
// All good
|
530 |
-
if( $result ) {
|
531 |
-
$this->Log( "Preparing Data Step8: Finished Step 8 successfully" );
|
532 |
-
return true;
|
533 |
-
}
|
534 |
-
|
535 |
-
$this->log( "Failed to update permalink_structure in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_ERROR );
|
536 |
-
return true;
|
537 |
-
}
|
538 |
-
|
539 |
-
/**
|
540 |
-
* Update blog_public option to not allow staging site to be indexed by search engines
|
541 |
-
* @return bool
|
542 |
-
*/
|
543 |
-
protected function step9() {
|
544 |
-
|
545 |
-
$this->log( "Preparing Data Step9: Set staging site to noindex" );
|
546 |
-
|
547 |
-
if( false === $this->isTable( $this->prefix . 'options' ) ) {
|
548 |
-
return true;
|
549 |
-
}
|
550 |
-
|
551 |
-
// Skip - Table is not selected or updated
|
552 |
-
if( !in_array( $this->prefix . 'options', $this->tables ) ) {
|
553 |
-
$this->log( "Preparing Data Step9: Skipping" );
|
554 |
-
return true;
|
555 |
-
}
|
556 |
-
|
557 |
-
$result = $this->db->query(
|
558 |
-
$this->db->prepare(
|
559 |
-
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'blog_public'", '0'
|
560 |
-
)
|
561 |
-
);
|
562 |
-
|
563 |
-
// All good
|
564 |
-
if( $result ) {
|
565 |
-
$this->Log( "Preparing Data Step9: Finished Step 9 successfully" );
|
566 |
-
return true;
|
567 |
-
}
|
568 |
-
|
569 |
-
$this->log( "Can not update staging site to noindex. Possible already done!", Logger::TYPE_WARNING );
|
570 |
-
return true;
|
571 |
-
}
|
572 |
-
|
573 |
-
/**
|
574 |
-
* Update WP_HOME in wp-config.php
|
575 |
-
* @return bool
|
576 |
-
*/
|
577 |
-
protected function step10() {
|
578 |
-
$path = ABSPATH . $this->options->cloneDirectoryName . "/wp-config.php";
|
579 |
-
|
580 |
-
$this->log( "Preparing Data Step10: Updating WP_HOME in wp-config.php to " . $this->getStagingSiteUrl() );
|
581 |
-
|
582 |
-
if( false === ($content = file_get_contents( $path )) ) {
|
583 |
-
$this->log( "Preparing Data Step10: Failed to update WP_HOME in wp-config.php. Can't read wp-config.php", Logger::TYPE_ERROR );
|
584 |
-
return false;
|
585 |
-
}
|
586 |
-
|
587 |
-
|
588 |
-
// Get WP_HOME from wp-config.php
|
589 |
-
preg_match( "/define\s*\(\s*'WP_HOME'\s*,\s*(.*)\s*\);/", $content, $matches );
|
590 |
-
|
591 |
-
if( !empty( $matches[1] ) ) {
|
592 |
-
$matches[1];
|
593 |
-
|
594 |
-
$pattern = "/define\s*\(\s*'WP_HOME'\s*,\s*(.*)\s*\);/";
|
595 |
-
|
596 |
-
$replace = "define('WP_HOME','" . $this->getStagingSiteUrl() . "'); // " . $matches[1];
|
597 |
-
$replace.= " // Changed by WP-Staging";
|
598 |
-
|
599 |
-
if( null === ($content = preg_replace( array($pattern), $replace, $content )) ) {
|
600 |
-
$this->log( "Preparing Data: Failed to reset index.php for sub directory; replacement failed", Logger::TYPE_ERROR );
|
601 |
-
return false;
|
602 |
-
}
|
603 |
-
} else {
|
604 |
-
$this->log( "Preparing Data Step10: WP_HOME not defined in wp-config.php. Skipping this step." );
|
605 |
-
}
|
606 |
-
|
607 |
-
if( false === @file_put_contents( $path, $content ) ) {
|
608 |
-
$this->log( "Preparing Data Step11: Failed to update WP_SITEURL. Can't save contents", Logger::TYPE_ERROR );
|
609 |
-
return false;
|
610 |
-
}
|
611 |
-
$this->Log( "Preparing Data: Finished Step 11 successfully" );
|
612 |
-
return true;
|
613 |
-
}
|
614 |
-
|
615 |
-
/**
|
616 |
-
* Update WP_SITEURL in wp-config.php
|
617 |
-
* @return bool
|
618 |
-
*/
|
619 |
-
protected function step11() {
|
620 |
-
$path = ABSPATH . $this->options->cloneDirectoryName . "/wp-config.php";
|
621 |
-
|
622 |
-
$this->log( "Preparing Data Step11: Updating WP_SITEURL in wp-config.php to " . $this->getStagingSiteUrl() );
|
623 |
-
|
624 |
-
if( false === ($content = file_get_contents( $path )) ) {
|
625 |
-
$this->log( "Preparing Data Step11: Failed to update WP_SITEURL in wp-config.php. Can't read wp-config.php", Logger::TYPE_ERROR );
|
626 |
-
return false;
|
627 |
-
}
|
628 |
-
|
629 |
-
|
630 |
-
// Get WP_SITEURL from wp-config.php
|
631 |
-
preg_match( "/define\s*\(\s*'WP_SITEURL'\s*,\s*(.*)\s*\);/", $content, $matches );
|
632 |
-
|
633 |
-
if( !empty( $matches[1] ) ) {
|
634 |
-
$matches[1];
|
635 |
-
|
636 |
-
$pattern = "/define\s*\(\s*'WP_SITEURL'\s*,\s*(.*)\s*\);/";
|
637 |
-
|
638 |
-
$replace = "define('WP_SITEURL','" . $this->getStagingSiteUrl() . "'); // " . $matches[1];
|
639 |
-
$replace.= " // Changed by WP-Staging";
|
640 |
-
|
641 |
-
if( null === ($content = preg_replace( array($pattern), $replace, $content )) ) {
|
642 |
-
$this->log( "Preparing Data Step11: Failed to update WP_SITEURL", Logger::TYPE_ERROR );
|
643 |
-
return false;
|
644 |
-
}
|
645 |
-
} else {
|
646 |
-
$this->log( "Preparing Data Step11: WP_SITEURL not defined in wp-config.php. Skipping this step." );
|
647 |
-
}
|
648 |
-
|
649 |
-
|
650 |
-
if( false === @file_put_contents( $path, $content ) ) {
|
651 |
-
$this->log( "Preparing Data Step11: Failed to update WP_SITEURL. Can't save contents", Logger::TYPE_ERROR );
|
652 |
-
return false;
|
653 |
-
}
|
654 |
-
$this->Log( "Preparing Data: Finished Step 11 successfully" );
|
655 |
-
return true;
|
656 |
-
}
|
657 |
-
|
658 |
-
/**
|
659 |
-
* Update WP_ALLOW_MULTISITE constant in wp-config.php
|
660 |
-
* @return bool
|
661 |
-
*/
|
662 |
-
protected function step12() {
|
663 |
-
$path = ABSPATH . $this->options->cloneDirectoryName . "/wp-config.php";
|
664 |
-
|
665 |
-
$this->log( "Preparing Data Step12: Updating WP_ALLOW_MULTISITE in wp-config.php to false" );
|
666 |
-
|
667 |
-
if( false === ($content = file_get_contents( $path )) ) {
|
668 |
-
$this->log( "Preparing Data Step12: Failed to update WP_ALLOW_MULTISITE in wp-config.php. Can't read wp-config.php", Logger::TYPE_ERROR );
|
669 |
-
return false;
|
670 |
-
}
|
671 |
-
|
672 |
-
|
673 |
-
// Get WP_SITEURL from wp-config.php
|
674 |
-
preg_match( "/define\s*\(\s*'WP_ALLOW_MULTISITE'\s*,\s*(.*)\s*\);/", $content, $matches );
|
675 |
-
|
676 |
-
if( !empty( $matches[1] ) ) {
|
677 |
-
$matches[1];
|
678 |
-
|
679 |
-
$pattern = "/define\s*\(\s*'WP_ALLOW_MULTISITE'\s*,\s*(.*)\s*\);/";
|
680 |
-
|
681 |
-
$replace = "define('WP_ALLOW_MULTISITE',false); // " . $matches[1];
|
682 |
-
$replace.= " // Changed by WP-Staging";
|
683 |
-
|
684 |
-
if( null === ($content = preg_replace( array($pattern), $replace, $content )) ) {
|
685 |
-
$this->log( "Preparing Data Step12: Failed to update WP_ALLOW_MULTISITE", Logger::TYPE_ERROR );
|
686 |
-
return false;
|
687 |
-
}
|
688 |
-
} else {
|
689 |
-
$this->log( "Preparing Data Step12: WP_ALLOW_MULTISITE not defined in wp-config.php. Skipping this step." );
|
690 |
-
}
|
691 |
-
|
692 |
-
|
693 |
-
if( false === @file_put_contents( $path, $content ) ) {
|
694 |
-
$this->log( "Preparing Data Step12: Failed to update WP_ALLOW_MULTISITE. Can't save contents", Logger::TYPE_ERROR );
|
695 |
-
return false;
|
696 |
-
}
|
697 |
-
$this->Log( "Preparing Data: Finished Step 12 successfully" );
|
698 |
-
return true;
|
699 |
-
}
|
700 |
-
|
701 |
-
/**
|
702 |
-
* Update MULTISITE constant in wp-config.php
|
703 |
-
* @return bool
|
704 |
-
*/
|
705 |
-
protected function step13() {
|
706 |
-
$path = ABSPATH . $this->options->cloneDirectoryName . "/wp-config.php";
|
707 |
-
|
708 |
-
$this->log( "Preparing Data Step13: Updating MULTISITE in wp-config.php to false" );
|
709 |
-
|
710 |
-
if( false === ($content = file_get_contents( $path )) ) {
|
711 |
-
$this->log( "Preparing Data Step13: Failed to update MULTISITE in wp-config.php. Can't read wp-config.php", Logger::TYPE_ERROR );
|
712 |
-
return false;
|
713 |
-
}
|
714 |
-
|
715 |
-
|
716 |
-
// Get WP_SITEURL from wp-config.php
|
717 |
-
preg_match( "/define\s*\(\s*'MULTISITE'\s*,\s*(.*)\s*\);/", $content, $matches );
|
718 |
-
|
719 |
-
if( !empty( $matches[1] ) ) {
|
720 |
-
$matches[1];
|
721 |
-
|
722 |
-
$pattern = "/define\s*\(\s*'MULTISITE'\s*,\s*(.*)\s*\);/";
|
723 |
-
|
724 |
-
$replace = "define('MULTISITE',false); // " . $matches[1];
|
725 |
-
$replace.= " // Changed by WP-Staging";
|
726 |
-
|
727 |
-
if( null === ($content = preg_replace( array($pattern), $replace, $content )) ) {
|
728 |
-
$this->log( "Preparing Data Step13: Failed to update MULTISITE", Logger::TYPE_ERROR );
|
729 |
-
return false;
|
730 |
-
}
|
731 |
-
} else {
|
732 |
-
$this->log( "Preparing Data Step13: MULTISITE not defined in wp-config.php. Skipping this step." );
|
733 |
-
}
|
734 |
-
|
735 |
-
|
736 |
-
if( false === @file_put_contents( $path, $content ) ) {
|
737 |
-
$this->log( "Preparing Data Step13: Failed to update MULTISITE. Can't save contents", Logger::TYPE_ERROR );
|
738 |
-
return false;
|
739 |
-
}
|
740 |
-
$this->Log( "Preparing Data: Finished Step 13 successfully" );
|
741 |
-
return true;
|
742 |
-
}
|
743 |
-
|
744 |
-
/**
|
745 |
-
* Get active_sitewide_plugins from wp_sitemeta and active_plugins from subsite
|
746 |
-
* Merge both arrays and copy them to the staging site into active_plugins
|
747 |
-
*/
|
748 |
-
protected function step14() {
|
749 |
-
|
750 |
-
|
751 |
-
$this->log( "Data Crunching Step 14: Updating active_plugins" );
|
752 |
-
|
753 |
-
if( false === $this->isTable( $this->prefix . 'options' ) ) {
|
754 |
-
$this->log( 'Data Crunching Step 14: Fatal Error ' . $this->prefix . 'options does not exist' );
|
755 |
-
$this->returnException( 'Data Crunching Step 8: Fatal Error ' . $this->prefix . 'options does not exist' );
|
756 |
-
return false;
|
757 |
-
}
|
758 |
-
|
759 |
-
// Skip - Table is not selected or updated
|
760 |
-
if( !in_array( $this->prefix . 'options', $this->tables ) ) {
|
761 |
-
$this->log( "Preparing Data Step14: Skipping" );
|
762 |
-
return true;
|
763 |
-
}
|
764 |
-
|
765 |
-
// Get active_plugins value from sub site options table
|
766 |
-
$active_plugins = $this->db->get_var( "SELECT option_value FROM {$this->db->prefix}options WHERE option_name = 'active_plugins' " );
|
767 |
-
|
768 |
-
if( !$active_plugins ) {
|
769 |
-
$this->log( "Data Crunching Step 14: Option active_plugins are empty " );
|
770 |
-
$active_plugins = array();
|
771 |
-
}
|
772 |
-
// Get active_sitewide_plugins value from main multisite wp_sitemeta table
|
773 |
-
$active_sitewide_plugins = $this->db->get_var( "SELECT meta_value FROM {$this->db->base_prefix}sitemeta WHERE meta_key = 'active_sitewide_plugins' " );
|
774 |
-
|
775 |
-
if( !$active_sitewide_plugins ) {
|
776 |
-
$this->log( "Data Crunching Step 14: Options {$this->db->base_prefix}active_sitewide_plugins is empty " );
|
777 |
-
$active_sitewide_plugins = array();
|
778 |
-
}
|
779 |
-
|
780 |
-
$active_sitewide_plugins = unserialize( $active_sitewide_plugins );
|
781 |
-
$active_plugins = unserialize( $active_plugins );
|
782 |
-
|
783 |
-
$all_plugins = array_merge( $active_plugins, array_keys( $active_sitewide_plugins ) );
|
784 |
-
|
785 |
-
sort( $all_plugins );
|
786 |
-
|
787 |
-
|
788 |
-
// Update active_plugins
|
789 |
-
$update = $this->db->query(
|
790 |
-
"UPDATE {$this->prefix}options SET option_value = '" . serialize( $all_plugins ) . "' WHERE option_name = 'active_plugins'"
|
791 |
-
);
|
792 |
-
|
793 |
-
if( false === $update ) {
|
794 |
-
$this->log( "Data Crunching Step 14: Can not update option active_plugins in {$this->prefix}options", Logger::TYPE_WARNING );
|
795 |
-
//$this->returnException( "Data Crunching Step 8: Can not update row wpstg_version in {$this->tmpPrefix}options - db error: " . $this->db->last_error );
|
796 |
-
return false;
|
797 |
-
}
|
798 |
-
|
799 |
-
$this->log( "Data Crunching Step 14: Successfull!" );
|
800 |
-
return true;
|
801 |
-
}
|
802 |
-
|
803 |
-
/**
|
804 |
-
* Update Table Prefix in wp_options
|
805 |
-
* @return bool
|
806 |
-
*/
|
807 |
-
protected function step15() {
|
808 |
-
$this->log( "Preparing Data Step15: Updating db prefix in {$this->prefix}options." );
|
809 |
-
|
810 |
-
// Skip - Table does not exist
|
811 |
-
if( false === $this->isTable( $this->prefix . 'options' ) ) {
|
812 |
-
return true;
|
813 |
-
}
|
814 |
-
|
815 |
-
// Skip - Table is not selected or updated
|
816 |
-
if( !in_array( $this->prefix . 'options', $this->tables ) ) {
|
817 |
-
$this->log( "Preparing Data Step4: Skipping" );
|
818 |
-
return true;
|
819 |
-
}
|
820 |
-
|
821 |
-
|
822 |
-
$this->log( "Updating db option_names in {$this->prefix}options. " );
|
823 |
-
|
824 |
-
// Filter the rows below. Do not update them!
|
825 |
-
$filters = array(
|
826 |
-
'wp_mail_smtp',
|
827 |
-
'wp_mail_smtp_version',
|
828 |
-
'wp_mail_smtp_debug',
|
829 |
-
);
|
830 |
-
|
831 |
-
$filters = apply_filters( 'wpstg_data_excl_rows', $filters );
|
832 |
-
|
833 |
-
$where = "";
|
834 |
-
foreach ( $filters as $filter ) {
|
835 |
-
$where .= " AND option_name <> '" . $filter . "'";
|
836 |
-
}
|
837 |
-
|
838 |
-
$updateOptions = $this->db->query(
|
839 |
-
$this->db->prepare(
|
840 |
-
"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 . "_%"
|
841 |
-
)
|
842 |
-
);
|
843 |
-
|
844 |
-
if( !$updateOptions ) {
|
845 |
-
$this->log( "Preparing Data Step15: Failed to update db option_names in {$this->prefix}options. Error: {$this->db->last_error}", Logger::TYPE_ERROR );
|
846 |
-
$this->returnException( "Data Crunching Step 15: Failed to update db option_names in {$this->prefix}options. Error: {$this->db->last_error}" );
|
847 |
-
return false;
|
848 |
-
}
|
849 |
-
|
850 |
-
return true;
|
851 |
-
}
|
852 |
-
|
853 |
-
/**
|
854 |
-
* Change upload_path in wp_options (if it is defined)
|
855 |
-
* @return bool
|
856 |
-
*/
|
857 |
-
protected function step16() {
|
858 |
-
$this->log( "Preparing Data Step16: Updating upload_path {$this->prefix}options." );
|
859 |
-
|
860 |
-
// Skip - Table does not exist
|
861 |
-
if( false === $this->isTable( $this->prefix . 'options' ) ) {
|
862 |
-
return true;
|
863 |
-
}
|
864 |
-
|
865 |
-
$newUploadPath = $this->getNewUploadPath();
|
866 |
-
|
867 |
-
if( false === $newUploadPath ) {
|
868 |
-
$this->log( "Preparing Data Step16: Skipping" );
|
869 |
-
return true;
|
870 |
-
}
|
871 |
-
|
872 |
-
// Skip - Table is not selected or updated
|
873 |
-
if( !in_array( $this->prefix . 'options', $this->tables ) ) {
|
874 |
-
$this->log( "Preparing Data Step16: Skipping" );
|
875 |
-
return true;
|
876 |
-
}
|
877 |
-
|
878 |
-
$error = isset( $this->db->last_error ) ? 'Last error: ' . $this->db->last_error : '';
|
879 |
-
|
880 |
-
$this->log( "Updating upload_path in {$this->prefix}options. {$error}" );
|
881 |
-
|
882 |
-
$updateOptions = $this->db->query(
|
883 |
-
$this->db->prepare(
|
884 |
-
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'upload_path'", $newUploadPath
|
885 |
-
)
|
886 |
-
);
|
887 |
-
|
888 |
-
if( !$updateOptions ) {
|
889 |
-
$this->log( "Preparing Data Step16: Failed to update upload_path in {$this->prefix}options. {$error}", Logger::TYPE_ERROR );
|
890 |
-
return true;
|
891 |
-
}
|
892 |
-
$this->Log( "Preparing Data: Finished Step 16 successfully" );
|
893 |
-
return true;
|
894 |
-
}
|
895 |
-
|
896 |
-
|
897 |
-
|
898 |
-
|
899 |
-
|
900 |
-
|
901 |
-
|
902 |
-
|
903 |
-
$
|
904 |
-
|
905 |
-
$
|
906 |
-
|
907 |
-
|
908 |
-
|
909 |
-
|
910 |
-
|
911 |
-
|
912 |
-
|
913 |
-
|
914 |
-
|
915 |
-
|
916 |
-
|
917 |
-
|
918 |
-
|
919 |
-
|
920 |
-
|
921 |
-
|
922 |
-
|
923 |
-
|
924 |
-
|
925 |
-
|
926 |
-
|
927 |
-
|
928 |
-
|
929 |
-
|
930 |
-
|
931 |
-
|
932 |
-
|
933 |
-
|
934 |
-
|
935 |
-
return
|
936 |
-
}
|
937 |
-
|
938 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPStaging\Backend\Modules\Jobs\Multisite;
|
4 |
+
|
5 |
+
// No Direct Access
|
6 |
+
if( !defined( "WPINC" ) ) {
|
7 |
+
die;
|
8 |
+
}
|
9 |
+
|
10 |
+
use WPStaging\Utils\Logger;
|
11 |
+
use WPStaging\WPStaging;
|
12 |
+
use WPStaging\Utils\Helper;
|
13 |
+
use WPStaging\Utils\Multisite;
|
14 |
+
use WPStaging\Utils\Strings;
|
15 |
+
use WPStaging\Backend\Modules\Jobs\JobExecutable;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Class Data
|
19 |
+
* @package WPStaging\Backend\Modules\Jobs
|
20 |
+
*/
|
21 |
+
class Data extends JobExecutable {
|
22 |
+
|
23 |
+
/**
|
24 |
+
* @var \wpdb
|
25 |
+
*/
|
26 |
+
private $db;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* @var string
|
30 |
+
*/
|
31 |
+
private $prefix;
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Tables e.g wpstg3_options
|
35 |
+
* @var array
|
36 |
+
*/
|
37 |
+
private $tables;
|
38 |
+
|
39 |
+
/**
|
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 = 1;
|
52 |
+
}
|
53 |
+
}
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Get a list of tables to copy
|
57 |
+
*/
|
58 |
+
private function getTables() {
|
59 |
+
$strings = new Strings();
|
60 |
+
$this->tables = array();
|
61 |
+
foreach ( $this->options->tables as $table ) {
|
62 |
+
$this->tables[] = $this->options->prefix . $strings->str_replace_first( $this->db->prefix, null, $table );
|
63 |
+
}
|
64 |
+
// Add extra global tables from main multisite (wpstgx_users and wpstgx_usermeta)
|
65 |
+
$this->tables[] = $this->options->prefix . $strings->str_replace_first( $this->db->prefix, null, 'users' );
|
66 |
+
$this->tables[] = $this->options->prefix . $strings->str_replace_first( $this->db->prefix, null, 'usermeta' );
|
67 |
+
}
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Calculate Total Steps in This Job and Assign It to $this->options->totalSteps
|
71 |
+
* @return void
|
72 |
+
*/
|
73 |
+
protected function calculateTotalSteps() {
|
74 |
+
$this->options->totalSteps = 17;
|
75 |
+
}
|
76 |
+
|
77 |
+
/**
|
78 |
+
* Start Module
|
79 |
+
* @return object
|
80 |
+
*/
|
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 |
+
|
91 |
+
/**
|
92 |
+
* Execute the Current Step
|
93 |
+
* Returns false when over threshold limits are hit or when the job is done, true otherwise
|
94 |
+
* @return bool
|
95 |
+
*/
|
96 |
+
protected function execute() {
|
97 |
+
// Fatal error. Let this happen never and break here immediately
|
98 |
+
if( $this->isRoot() ) {
|
99 |
+
return false;
|
100 |
+
}
|
101 |
+
|
102 |
+
// Over limits threshold
|
103 |
+
if( $this->isOverThreshold() ) {
|
104 |
+
// Prepare response and save current progress
|
105 |
+
$this->prepareResponse( false, false );
|
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 |
+
}
|
129 |
+
|
130 |
+
/**
|
131 |
+
* Checks Whether There is Any Job to Execute or Not
|
132 |
+
* @return bool
|
133 |
+
*/
|
134 |
+
protected function isFinished() {
|
135 |
+
return (
|
136 |
+
$this->options->currentStep > $this->options->totalSteps ||
|
137 |
+
!method_exists( $this, "step" . $this->options->currentStep )
|
138 |
+
);
|
139 |
+
}
|
140 |
+
|
141 |
+
/**
|
142 |
+
* Check if current operation is done on the root folder or on the live DB
|
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( $wpdb->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 Path === Staging path
|
160 |
+
if( $this->multisiteHomeDomain . $this->options->cloneDirectoryName === $this->multisiteHomeDomain ) {
|
161 |
+
return true;
|
162 |
+
}
|
163 |
+
|
164 |
+
return false;
|
165 |
+
}
|
166 |
+
|
167 |
+
/**
|
168 |
+
* Check if table exists
|
169 |
+
* @param string $table
|
170 |
+
* @return boolean
|
171 |
+
*/
|
172 |
+
protected function isTable( $table ) {
|
173 |
+
if( $this->db->get_var( "SHOW TABLES LIKE '{$table}'" ) != $table ) {
|
174 |
+
$this->log( "Table {$table} does not exists", Logger::TYPE_ERROR );
|
175 |
+
return false;
|
176 |
+
}
|
177 |
+
return true;
|
178 |
+
}
|
179 |
+
|
180 |
+
/**
|
181 |
+
* Get the install sub directory if WP is installed in sub directory
|
182 |
+
* @return string
|
183 |
+
*/
|
184 |
+
protected function getSubDir() {
|
185 |
+
return '/';
|
186 |
+
|
187 |
+
// $home = get_option( 'home' );
|
188 |
+
// $siteurl = get_option( 'siteurl' );
|
189 |
+
//
|
190 |
+
// if( empty( $home ) || empty( $siteurl ) ) {
|
191 |
+
// return '/';
|
192 |
+
// }
|
193 |
+
//
|
194 |
+
// $dir = str_replace( $home, '', $siteurl );
|
195 |
+
// return '/' . str_replace( '/', '', $dir ) . '/';
|
196 |
+
}
|
197 |
+
|
198 |
+
/**
|
199 |
+
* Copy wp-config.php if it is located outside of root one level up
|
200 |
+
* @todo Needs some more testing before it will be released
|
201 |
+
* @return boolean
|
202 |
+
*/
|
203 |
+
// protected function step0(){
|
204 |
+
// $this->log( "Preparing Data Step0: Check if wp-config.php is located in root path", Logger::TYPE_INFO );
|
205 |
+
//
|
206 |
+
// $dir = trailingslashit( dirname( ABSPATH ) );
|
207 |
+
//
|
208 |
+
// $source = $dir . 'wp-config.php';
|
209 |
+
//
|
210 |
+
// $destination = trailingslashit(ABSPATH) . $this->clone->cloneDirectoryName . DIRECTORY_SEPARATOR . 'wp-config.php';
|
211 |
+
//
|
212 |
+
//
|
213 |
+
// // Do not do anything
|
214 |
+
// if( (!is_file( $source ) && !is_link($source)) || is_file($destination) ) {
|
215 |
+
// $this->log( "Preparing Data Step0: Skip it", Logger::TYPE_INFO );
|
216 |
+
// return true;
|
217 |
+
// }
|
218 |
+
//
|
219 |
+
// // Copy target of a symbolic link
|
220 |
+
// if (is_link($source)){
|
221 |
+
// $this->log( "Preparing Data Step0: Symbolic link found...", Logger::TYPE_INFO );
|
222 |
+
// if (!@copy(readlink($source), $destination)) {
|
223 |
+
// $this->log("Preparing Data Step0: Failed to copy wp-config.php {$source} -> {$destination}", Logger::TYPE_ERROR);
|
224 |
+
// return true;
|
225 |
+
// }
|
226 |
+
// }
|
227 |
+
//
|
228 |
+
// // regular copy of wp-config.php
|
229 |
+
// if (!@copy($source, $destination)) {
|
230 |
+
// $this->log("Preparing Data Step0: Failed to copy wp-config.php {$source} -> {$destination}", Logger::TYPE_ERROR);
|
231 |
+
// return true;
|
232 |
+
// }
|
233 |
+
// $this->log( "Preparing Data Step0: Successfull", Logger::TYPE_INFO );
|
234 |
+
// return true;
|
235 |
+
//
|
236 |
+
// }
|
237 |
+
|
238 |
+
/**
|
239 |
+
* Replace "siteurl" and "home"
|
240 |
+
* @return bool
|
241 |
+
*/
|
242 |
+
protected function step1() {
|
243 |
+
$this->log( "Preparing Data Step1: Updating siteurl and homeurl in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_INFO );
|
244 |
+
|
245 |
+
// Skip - Table does not exist
|
246 |
+
if( false === $this->isTable( $this->prefix . 'options' ) ) {
|
247 |
+
return true;
|
248 |
+
}
|
249 |
+
// Skip - Table is not selected or updated
|
250 |
+
if( !in_array( $this->prefix . 'options', $this->tables ) ) {
|
251 |
+
$this->log( "Preparing Data Step1: Skipping" );
|
252 |
+
return true;
|
253 |
+
}
|
254 |
+
|
255 |
+
// Installed in sub-directory
|
256 |
+
if( $this->isSubDir() ) {
|
257 |
+
$this->log( "Preparing Data Step1: Updating siteurl and homeurl to " . rtrim( $this->multisiteHomeDomain, "/" ) . $this->getSubDir() . $this->options->cloneDirectoryName );
|
258 |
+
// Replace URLs
|
259 |
+
$result = $this->db->query(
|
260 |
+
$this->db->prepare(
|
261 |
+
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'siteurl' or option_name='home'", rtrim( $this->multisiteHomeDomain, "/" ) . $this->getSubDir() . $this->options->cloneDirectoryName
|
262 |
+
)
|
263 |
+
);
|
264 |
+
} else {
|
265 |
+
$this->log( "Preparing Data Step1: Updating siteurl and homeurl to " . rtrim( $this->multisiteHomeDomain, "/" ) . '/' . $this->options->cloneDirectoryName );
|
266 |
+
// Replace URLs
|
267 |
+
$result = $this->db->query(
|
268 |
+
$this->db->prepare(
|
269 |
+
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'siteurl' or option_name='home'", $this->multisiteHomeDomain . '/' . $this->options->cloneDirectoryName
|
270 |
+
)
|
271 |
+
);
|
272 |
+
}
|
273 |
+
|
274 |
+
|
275 |
+
// All good
|
276 |
+
if( $result ) {
|
277 |
+
return true;
|
278 |
+
}
|
279 |
+
|
280 |
+
$this->log( "Preparing Data Step1: Failed to update siteurl and homeurl in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_ERROR );
|
281 |
+
return false;
|
282 |
+
}
|
283 |
+
|
284 |
+
/**
|
285 |
+
* Update "wpstg_is_staging_site"
|
286 |
+
* @return bool
|
287 |
+
*/
|
288 |
+
protected function step2() {
|
289 |
+
|
290 |
+
$this->log( "Preparing Data Step2: Updating row wpstg_is_staging_site in {$this->prefix}options {$this->db->last_error}" );
|
291 |
+
|
292 |
+
// Skip - Table does not exist
|
293 |
+
if( false === $this->isTable( $this->prefix . 'options' ) ) {
|
294 |
+
return true;
|
295 |
+
}
|
296 |
+
// Skip - Table is not selected or updated
|
297 |
+
if( !in_array( $this->prefix . 'options', $this->tables ) ) {
|
298 |
+
$this->log( "Preparing Data Step2: Skipping" );
|
299 |
+
return true;
|
300 |
+
}
|
301 |
+
|
302 |
+
$result = $this->db->query(
|
303 |
+
$this->db->prepare(
|
304 |
+
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'wpstg_is_staging_site'", "true"
|
305 |
+
)
|
306 |
+
);
|
307 |
+
|
308 |
+
// No errors but no option name such as wpstg_is_staging_site
|
309 |
+
if( '' === $this->db->last_error && 0 == $result ) {
|
310 |
+
$result = $this->db->query(
|
311 |
+
$this->db->prepare(
|
312 |
+
"INSERT INTO {$this->prefix}options (option_name,option_value) VALUES ('wpstg_is_staging_site',%s)", "true"
|
313 |
+
)
|
314 |
+
);
|
315 |
+
}
|
316 |
+
|
317 |
+
// All good
|
318 |
+
if( $result ) {
|
319 |
+
return true;
|
320 |
+
}
|
321 |
+
|
322 |
+
$this->log( "Preparing Data Step2: Failed to update wpstg_is_staging_site in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_ERROR );
|
323 |
+
return false;
|
324 |
+
}
|
325 |
+
|
326 |
+
/**
|
327 |
+
* Update rewrite_rules
|
328 |
+
* @return bool
|
329 |
+
*/
|
330 |
+
protected function step3() {
|
331 |
+
|
332 |
+
$this->log( "Preparing Data Step3: Updating rewrite_rules in {$this->prefix}options {$this->db->last_error}" );
|
333 |
+
|
334 |
+
// Skip - Table does not exist
|
335 |
+
if( false === $this->isTable( $this->prefix . 'options' ) ) {
|
336 |
+
return true;
|
337 |
+
}
|
338 |
+
|
339 |
+
// Skip - Table is not selected or updated
|
340 |
+
if( !in_array( $this->prefix . 'options', $this->tables ) ) {
|
341 |
+
$this->log( "Preparing Data Step3: Skipping" );
|
342 |
+
return true;
|
343 |
+
}
|
344 |
+
|
345 |
+
$result = $this->db->query(
|
346 |
+
$this->db->prepare(
|
347 |
+
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'rewrite_rules'", ' '
|
348 |
+
)
|
349 |
+
);
|
350 |
+
|
351 |
+
// All good
|
352 |
+
if( $result ) {
|
353 |
+
return true;
|
354 |
+
}
|
355 |
+
|
356 |
+
$this->log( "Preparing Data Step3: Failed to update rewrite_rules in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_ERROR );
|
357 |
+
return true;
|
358 |
+
}
|
359 |
+
|
360 |
+
/**
|
361 |
+
* Update Table Prefix in wp_usermeta and wp_options
|
362 |
+
* @return bool
|
363 |
+
*/
|
364 |
+
protected function step4() {
|
365 |
+
$this->log( "Preparing Data Step4: Updating db prefix in {$this->prefix}usermeta. {$this->db->last_error}" );
|
366 |
+
|
367 |
+
// Skip - Table does not exist
|
368 |
+
if( false === $this->isTable( $this->prefix . 'usermeta' ) ) {
|
369 |
+
return true;
|
370 |
+
}
|
371 |
+
|
372 |
+
// Skip - Table is not selected or updated
|
373 |
+
if( !in_array( $this->prefix . 'usermeta', $this->tables ) ) {
|
374 |
+
$this->log( "Preparing Data Step4: Skipping" );
|
375 |
+
return true;
|
376 |
+
}
|
377 |
+
|
378 |
+
$update = $this->db->query(
|
379 |
+
$this->db->prepare(
|
380 |
+
"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 . "_%"
|
381 |
+
)
|
382 |
+
);
|
383 |
+
|
384 |
+
if( !$update ) {
|
385 |
+
$this->log( "Preparing Data Step4: Failed to update {$this->prefix}usermeta meta_key database table prefixes; {$this->db->last_error}", Logger::TYPE_ERROR );
|
386 |
+
$this->returnException( "Data Crunching Step 4: Failed to update {$this->prefix}usermeta meta_key database table prefixes; {$this->db->last_error}" );
|
387 |
+
return false;
|
388 |
+
}
|
389 |
+
return true;
|
390 |
+
}
|
391 |
+
|
392 |
+
/**
|
393 |
+
* Update $table_prefix in wp-config.php
|
394 |
+
* @return bool
|
395 |
+
*/
|
396 |
+
protected function step5() {
|
397 |
+
$path = ABSPATH . $this->options->cloneDirectoryName . "/wp-config.php";
|
398 |
+
|
399 |
+
$this->log( "Preparing Data Step5: Updating table_prefix in {$path} to " . $this->prefix );
|
400 |
+
if( false === ($content = file_get_contents( $path )) ) {
|
401 |
+
$this->log( "Preparing Data Step5: Failed to update table_prefix in {$path}. Can't read contents", Logger::TYPE_ERROR );
|
402 |
+
return false;
|
403 |
+
}
|
404 |
+
|
405 |
+
// Replace table prefix
|
406 |
+
$content = str_replace( '$table_prefix', '$table_prefix = \'' . $this->prefix . '\';//', $content );
|
407 |
+
|
408 |
+
// Replace URLs
|
409 |
+
$content = str_replace( $this->multisiteHomeDomain, $this->multisiteHomeDomain . '/' . $this->options->cloneDirectoryName, $content );
|
410 |
+
|
411 |
+
if( false === @file_put_contents( $path, $content ) ) {
|
412 |
+
$this->log( "Preparing Data Step5: Failed to update $table_prefix in {$path} to " . $this->prefix . ". Can't save contents", Logger::TYPE_ERROR );
|
413 |
+
return false;
|
414 |
+
}
|
415 |
+
|
416 |
+
return true;
|
417 |
+
}
|
418 |
+
|
419 |
+
/**
|
420 |
+
* Reset index.php to original file
|
421 |
+
* This is needed if live site is located in subfolder
|
422 |
+
* Check first if main wordpress is used in subfolder and index.php in parent directory
|
423 |
+
* @see: https://codex.wordpress.org/Giving_WordPress_Its_Own_Directory
|
424 |
+
* @return bool
|
425 |
+
*/
|
426 |
+
protected function step6() {
|
427 |
+
|
428 |
+
if( !$this->isSubDir() ) {
|
429 |
+
$this->debugLog( "Preparing Data Step6: WP installation is not in a subdirectory! All good, skipping this step" );
|
430 |
+
return true;
|
431 |
+
}
|
432 |
+
|
433 |
+
$path = ABSPATH . $this->options->cloneDirectoryName . "/index.php";
|
434 |
+
|
435 |
+
if( false === ($content = file_get_contents( $path )) ) {
|
436 |
+
$this->log( "Preparing Data Step6: Failed to reset {$path} for sub directory; can't read contents", Logger::TYPE_ERROR );
|
437 |
+
return false;
|
438 |
+
}
|
439 |
+
|
440 |
+
|
441 |
+
if( !preg_match( "/(require(.*)wp-blog-header.php' \);)/", $content, $matches ) ) {
|
442 |
+
$this->log(
|
443 |
+
"Preparing Data Step6: Failed to reset index.php for sub directory; wp-blog-header.php is missing", Logger::TYPE_ERROR
|
444 |
+
);
|
445 |
+
return false;
|
446 |
+
}
|
447 |
+
$this->log( "Preparing Data: WP installation is in a subdirectory. Progressing..." );
|
448 |
+
|
449 |
+
$pattern = "/require(.*) dirname(.*) __FILE__ (.*) \. '(.*)wp-blog-header.php'(.*);/";
|
450 |
+
|
451 |
+
$replace = "require( dirname( __FILE__ ) . '/wp-blog-header.php' ); // " . $matches[0];
|
452 |
+
$replace.= " // Changed by WP-Staging";
|
453 |
+
|
454 |
+
|
455 |
+
|
456 |
+
if( null === ($content = preg_replace( array($pattern), $replace, $content )) ) {
|
457 |
+
$this->log( "Preparing Data: Failed to reset index.php for sub directory; replacement failed", Logger::TYPE_ERROR );
|
458 |
+
return false;
|
459 |
+
}
|
460 |
+
|
461 |
+
if( false === @file_put_contents( $path, $content ) ) {
|
462 |
+
$this->log( "Preparing Data: Failed to reset index.php for sub directory; can't save contents", Logger::TYPE_ERROR );
|
463 |
+
return false;
|
464 |
+
}
|
465 |
+
$this->Log( "Preparing Data: Finished Step 6 successfully" );
|
466 |
+
return true;
|
467 |
+
}
|
468 |
+
|
469 |
+
/**
|
470 |
+
* Update wpstg_rmpermalinks_executed
|
471 |
+
* @return bool
|
472 |
+
*/
|
473 |
+
protected function step7() {
|
474 |
+
|
475 |
+
$this->log( "Preparing Data Step7: Updating wpstg_rmpermalinks_executed in {$this->prefix}options {$this->db->last_error}" );
|
476 |
+
|
477 |
+
// Skip - Table does not exist
|
478 |
+
if( false === $this->isTable( $this->prefix . 'options' ) ) {
|
479 |
+
return true;
|
480 |
+
}
|
481 |
+
|
482 |
+
// Skip - Table is not selected or updated
|
483 |
+
if( !in_array( $this->prefix . 'options', $this->tables ) ) {
|
484 |
+
$this->log( "Preparing Data Step7: Skipping" );
|
485 |
+
return true;
|
486 |
+
}
|
487 |
+
|
488 |
+
$result = $this->db->query(
|
489 |
+
$this->db->prepare(
|
490 |
+
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'wpstg_rmpermalinks_executed'", ' '
|
491 |
+
)
|
492 |
+
);
|
493 |
+
|
494 |
+
// All good
|
495 |
+
if( $result ) {
|
496 |
+
$this->Log( "Preparing Data Step7: Finished Step 7 successfully" );
|
497 |
+
return true;
|
498 |
+
}
|
499 |
+
|
500 |
+
$this->log( "Failed to update wpstg_rmpermalinks_executed in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_WARNING );
|
501 |
+
return true;
|
502 |
+
}
|
503 |
+
|
504 |
+
/**
|
505 |
+
* Update permalink_structure
|
506 |
+
* @return bool
|
507 |
+
*/
|
508 |
+
protected function step8() {
|
509 |
+
|
510 |
+
$this->log( "Preparing Data Step8: Updating permalink_structure in {$this->prefix}options {$this->db->last_error}" );
|
511 |
+
|
512 |
+
// Skip - Table does not exist
|
513 |
+
if( false === $this->isTable( $this->prefix . 'options' ) ) {
|
514 |
+
return true;
|
515 |
+
}
|
516 |
+
|
517 |
+
// Skip - Table is not selected or updated
|
518 |
+
if( !in_array( $this->prefix . 'options', $this->tables ) ) {
|
519 |
+
$this->log( "Preparing Data Step8: Skipping" );
|
520 |
+
return true;
|
521 |
+
}
|
522 |
+
|
523 |
+
$result = $this->db->query(
|
524 |
+
$this->db->prepare(
|
525 |
+
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'permalink_structure'", ' '
|
526 |
+
)
|
527 |
+
);
|
528 |
+
|
529 |
+
// All good
|
530 |
+
if( $result ) {
|
531 |
+
$this->Log( "Preparing Data Step8: Finished Step 8 successfully" );
|
532 |
+
return true;
|
533 |
+
}
|
534 |
+
|
535 |
+
$this->log( "Failed to update permalink_structure in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_ERROR );
|
536 |
+
return true;
|
537 |
+
}
|
538 |
+
|
539 |
+
/**
|
540 |
+
* Update blog_public option to not allow staging site to be indexed by search engines
|
541 |
+
* @return bool
|
542 |
+
*/
|
543 |
+
protected function step9() {
|
544 |
+
|
545 |
+
$this->log( "Preparing Data Step9: Set staging site to noindex" );
|
546 |
+
|
547 |
+
if( false === $this->isTable( $this->prefix . 'options' ) ) {
|
548 |
+
return true;
|
549 |
+
}
|
550 |
+
|
551 |
+
// Skip - Table is not selected or updated
|
552 |
+
if( !in_array( $this->prefix . 'options', $this->tables ) ) {
|
553 |
+
$this->log( "Preparing Data Step9: Skipping" );
|
554 |
+
return true;
|
555 |
+
}
|
556 |
+
|
557 |
+
$result = $this->db->query(
|
558 |
+
$this->db->prepare(
|
559 |
+
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'blog_public'", '0'
|
560 |
+
)
|
561 |
+
);
|
562 |
+
|
563 |
+
// All good
|
564 |
+
if( $result ) {
|
565 |
+
$this->Log( "Preparing Data Step9: Finished Step 9 successfully" );
|
566 |
+
return true;
|
567 |
+
}
|
568 |
+
|
569 |
+
$this->log( "Can not update staging site to noindex. Possible already done!", Logger::TYPE_WARNING );
|
570 |
+
return true;
|
571 |
+
}
|
572 |
+
|
573 |
+
/**
|
574 |
+
* Update WP_HOME in wp-config.php
|
575 |
+
* @return bool
|
576 |
+
*/
|
577 |
+
protected function step10() {
|
578 |
+
$path = ABSPATH . $this->options->cloneDirectoryName . "/wp-config.php";
|
579 |
+
|
580 |
+
$this->log( "Preparing Data Step10: Updating WP_HOME in wp-config.php to " . $this->getStagingSiteUrl() );
|
581 |
+
|
582 |
+
if( false === ($content = file_get_contents( $path )) ) {
|
583 |
+
$this->log( "Preparing Data Step10: Failed to update WP_HOME in wp-config.php. Can't read wp-config.php", Logger::TYPE_ERROR );
|
584 |
+
return false;
|
585 |
+
}
|
586 |
+
|
587 |
+
|
588 |
+
// Get WP_HOME from wp-config.php
|
589 |
+
preg_match( "/define\s*\(\s*'WP_HOME'\s*,\s*(.*)\s*\);/", $content, $matches );
|
590 |
+
|
591 |
+
if( !empty( $matches[1] ) ) {
|
592 |
+
$matches[1];
|
593 |
+
|
594 |
+
$pattern = "/define\s*\(\s*'WP_HOME'\s*,\s*(.*)\s*\);/";
|
595 |
+
|
596 |
+
$replace = "define('WP_HOME','" . $this->getStagingSiteUrl() . "'); // " . $matches[1];
|
597 |
+
$replace.= " // Changed by WP-Staging";
|
598 |
+
|
599 |
+
if( null === ($content = preg_replace( array($pattern), $replace, $content )) ) {
|
600 |
+
$this->log( "Preparing Data: Failed to reset index.php for sub directory; replacement failed", Logger::TYPE_ERROR );
|
601 |
+
return false;
|
602 |
+
}
|
603 |
+
} else {
|
604 |
+
$this->log( "Preparing Data Step10: WP_HOME not defined in wp-config.php. Skipping this step." );
|
605 |
+
}
|
606 |
+
|
607 |
+
if( false === @file_put_contents( $path, $content ) ) {
|
608 |
+
$this->log( "Preparing Data Step11: Failed to update WP_SITEURL. Can't save contents", Logger::TYPE_ERROR );
|
609 |
+
return false;
|
610 |
+
}
|
611 |
+
$this->Log( "Preparing Data: Finished Step 11 successfully" );
|
612 |
+
return true;
|
613 |
+
}
|
614 |
+
|
615 |
+
/**
|
616 |
+
* Update WP_SITEURL in wp-config.php
|
617 |
+
* @return bool
|
618 |
+
*/
|
619 |
+
protected function step11() {
|
620 |
+
$path = ABSPATH . $this->options->cloneDirectoryName . "/wp-config.php";
|
621 |
+
|
622 |
+
$this->log( "Preparing Data Step11: Updating WP_SITEURL in wp-config.php to " . $this->getStagingSiteUrl() );
|
623 |
+
|
624 |
+
if( false === ($content = file_get_contents( $path )) ) {
|
625 |
+
$this->log( "Preparing Data Step11: Failed to update WP_SITEURL in wp-config.php. Can't read wp-config.php", Logger::TYPE_ERROR );
|
626 |
+
return false;
|
627 |
+
}
|
628 |
+
|
629 |
+
|
630 |
+
// Get WP_SITEURL from wp-config.php
|
631 |
+
preg_match( "/define\s*\(\s*'WP_SITEURL'\s*,\s*(.*)\s*\);/", $content, $matches );
|
632 |
+
|
633 |
+
if( !empty( $matches[1] ) ) {
|
634 |
+
$matches[1];
|
635 |
+
|
636 |
+
$pattern = "/define\s*\(\s*'WP_SITEURL'\s*,\s*(.*)\s*\);/";
|
637 |
+
|
638 |
+
$replace = "define('WP_SITEURL','" . $this->getStagingSiteUrl() . "'); // " . $matches[1];
|
639 |
+
$replace.= " // Changed by WP-Staging";
|
640 |
+
|
641 |
+
if( null === ($content = preg_replace( array($pattern), $replace, $content )) ) {
|
642 |
+
$this->log( "Preparing Data Step11: Failed to update WP_SITEURL", Logger::TYPE_ERROR );
|
643 |
+
return false;
|
644 |
+
}
|
645 |
+
} else {
|
646 |
+
$this->log( "Preparing Data Step11: WP_SITEURL not defined in wp-config.php. Skipping this step." );
|
647 |
+
}
|
648 |
+
|
649 |
+
|
650 |
+
if( false === @file_put_contents( $path, $content ) ) {
|
651 |
+
$this->log( "Preparing Data Step11: Failed to update WP_SITEURL. Can't save contents", Logger::TYPE_ERROR );
|
652 |
+
return false;
|
653 |
+
}
|
654 |
+
$this->Log( "Preparing Data: Finished Step 11 successfully" );
|
655 |
+
return true;
|
656 |
+
}
|
657 |
+
|
658 |
+
/**
|
659 |
+
* Update WP_ALLOW_MULTISITE constant in wp-config.php
|
660 |
+
* @return bool
|
661 |
+
*/
|
662 |
+
protected function step12() {
|
663 |
+
$path = ABSPATH . $this->options->cloneDirectoryName . "/wp-config.php";
|
664 |
+
|
665 |
+
$this->log( "Preparing Data Step12: Updating WP_ALLOW_MULTISITE in wp-config.php to false" );
|
666 |
+
|
667 |
+
if( false === ($content = file_get_contents( $path )) ) {
|
668 |
+
$this->log( "Preparing Data Step12: Failed to update WP_ALLOW_MULTISITE in wp-config.php. Can't read wp-config.php", Logger::TYPE_ERROR );
|
669 |
+
return false;
|
670 |
+
}
|
671 |
+
|
672 |
+
|
673 |
+
// Get WP_SITEURL from wp-config.php
|
674 |
+
preg_match( "/define\s*\(\s*'WP_ALLOW_MULTISITE'\s*,\s*(.*)\s*\);/", $content, $matches );
|
675 |
+
|
676 |
+
if( !empty( $matches[1] ) ) {
|
677 |
+
$matches[1];
|
678 |
+
|
679 |
+
$pattern = "/define\s*\(\s*'WP_ALLOW_MULTISITE'\s*,\s*(.*)\s*\);/";
|
680 |
+
|
681 |
+
$replace = "define('WP_ALLOW_MULTISITE',false); // " . $matches[1];
|
682 |
+
$replace.= " // Changed by WP-Staging";
|
683 |
+
|
684 |
+
if( null === ($content = preg_replace( array($pattern), $replace, $content )) ) {
|
685 |
+
$this->log( "Preparing Data Step12: Failed to update WP_ALLOW_MULTISITE", Logger::TYPE_ERROR );
|
686 |
+
return false;
|
687 |
+
}
|
688 |
+
} else {
|
689 |
+
$this->log( "Preparing Data Step12: WP_ALLOW_MULTISITE not defined in wp-config.php. Skipping this step." );
|
690 |
+
}
|
691 |
+
|
692 |
+
|
693 |
+
if( false === @file_put_contents( $path, $content ) ) {
|
694 |
+
$this->log( "Preparing Data Step12: Failed to update WP_ALLOW_MULTISITE. Can't save contents", Logger::TYPE_ERROR );
|
695 |
+
return false;
|
696 |
+
}
|
697 |
+
$this->Log( "Preparing Data: Finished Step 12 successfully" );
|
698 |
+
return true;
|
699 |
+
}
|
700 |
+
|
701 |
+
/**
|
702 |
+
* Update MULTISITE constant in wp-config.php
|
703 |
+
* @return bool
|
704 |
+
*/
|
705 |
+
protected function step13() {
|
706 |
+
$path = ABSPATH . $this->options->cloneDirectoryName . "/wp-config.php";
|
707 |
+
|
708 |
+
$this->log( "Preparing Data Step13: Updating MULTISITE in wp-config.php to false" );
|
709 |
+
|
710 |
+
if( false === ($content = file_get_contents( $path )) ) {
|
711 |
+
$this->log( "Preparing Data Step13: Failed to update MULTISITE in wp-config.php. Can't read wp-config.php", Logger::TYPE_ERROR );
|
712 |
+
return false;
|
713 |
+
}
|
714 |
+
|
715 |
+
|
716 |
+
// Get WP_SITEURL from wp-config.php
|
717 |
+
preg_match( "/define\s*\(\s*'MULTISITE'\s*,\s*(.*)\s*\);/", $content, $matches );
|
718 |
+
|
719 |
+
if( !empty( $matches[1] ) ) {
|
720 |
+
$matches[1];
|
721 |
+
|
722 |
+
$pattern = "/define\s*\(\s*'MULTISITE'\s*,\s*(.*)\s*\);/";
|
723 |
+
|
724 |
+
$replace = "define('MULTISITE',false); // " . $matches[1];
|
725 |
+
$replace.= " // Changed by WP-Staging";
|
726 |
+
|
727 |
+
if( null === ($content = preg_replace( array($pattern), $replace, $content )) ) {
|
728 |
+
$this->log( "Preparing Data Step13: Failed to update MULTISITE", Logger::TYPE_ERROR );
|
729 |
+
return false;
|
730 |
+
}
|
731 |
+
} else {
|
732 |
+
$this->log( "Preparing Data Step13: MULTISITE not defined in wp-config.php. Skipping this step." );
|
733 |
+
}
|
734 |
+
|
735 |
+
|
736 |
+
if( false === @file_put_contents( $path, $content ) ) {
|
737 |
+
$this->log( "Preparing Data Step13: Failed to update MULTISITE. Can't save contents", Logger::TYPE_ERROR );
|
738 |
+
return false;
|
739 |
+
}
|
740 |
+
$this->Log( "Preparing Data: Finished Step 13 successfully" );
|
741 |
+
return true;
|
742 |
+
}
|
743 |
+
|
744 |
+
/**
|
745 |
+
* Get active_sitewide_plugins from wp_sitemeta and active_plugins from subsite
|
746 |
+
* Merge both arrays and copy them to the staging site into active_plugins
|
747 |
+
*/
|
748 |
+
protected function step14() {
|
749 |
+
|
750 |
+
|
751 |
+
$this->log( "Data Crunching Step 14: Updating active_plugins" );
|
752 |
+
|
753 |
+
if( false === $this->isTable( $this->prefix . 'options' ) ) {
|
754 |
+
$this->log( 'Data Crunching Step 14: Fatal Error ' . $this->prefix . 'options does not exist' );
|
755 |
+
$this->returnException( 'Data Crunching Step 8: Fatal Error ' . $this->prefix . 'options does not exist' );
|
756 |
+
return false;
|
757 |
+
}
|
758 |
+
|
759 |
+
// Skip - Table is not selected or updated
|
760 |
+
if( !in_array( $this->prefix . 'options', $this->tables ) ) {
|
761 |
+
$this->log( "Preparing Data Step14: Skipping" );
|
762 |
+
return true;
|
763 |
+
}
|
764 |
+
|
765 |
+
// Get active_plugins value from sub site options table
|
766 |
+
$active_plugins = $this->db->get_var( "SELECT option_value FROM {$this->db->prefix}options WHERE option_name = 'active_plugins' " );
|
767 |
+
|
768 |
+
if( !$active_plugins ) {
|
769 |
+
$this->log( "Data Crunching Step 14: Option active_plugins are empty " );
|
770 |
+
$active_plugins = array();
|
771 |
+
}
|
772 |
+
// Get active_sitewide_plugins value from main multisite wp_sitemeta table
|
773 |
+
$active_sitewide_plugins = $this->db->get_var( "SELECT meta_value FROM {$this->db->base_prefix}sitemeta WHERE meta_key = 'active_sitewide_plugins' " );
|
774 |
+
|
775 |
+
if( !$active_sitewide_plugins ) {
|
776 |
+
$this->log( "Data Crunching Step 14: Options {$this->db->base_prefix}active_sitewide_plugins is empty " );
|
777 |
+
$active_sitewide_plugins = array();
|
778 |
+
}
|
779 |
+
|
780 |
+
$active_sitewide_plugins = unserialize( $active_sitewide_plugins );
|
781 |
+
$active_plugins = unserialize( $active_plugins );
|
782 |
+
|
783 |
+
$all_plugins = array_merge( $active_plugins, array_keys( $active_sitewide_plugins ) );
|
784 |
+
|
785 |
+
sort( $all_plugins );
|
786 |
+
|
787 |
+
|
788 |
+
// Update active_plugins
|
789 |
+
$update = $this->db->query(
|
790 |
+
"UPDATE {$this->prefix}options SET option_value = '" . serialize( $all_plugins ) . "' WHERE option_name = 'active_plugins'"
|
791 |
+
);
|
792 |
+
|
793 |
+
if( false === $update ) {
|
794 |
+
$this->log( "Data Crunching Step 14: Can not update option active_plugins in {$this->prefix}options", Logger::TYPE_WARNING );
|
795 |
+
//$this->returnException( "Data Crunching Step 8: Can not update row wpstg_version in {$this->tmpPrefix}options - db error: " . $this->db->last_error );
|
796 |
+
return false;
|
797 |
+
}
|
798 |
+
|
799 |
+
$this->log( "Data Crunching Step 14: Successfull!" );
|
800 |
+
return true;
|
801 |
+
}
|
802 |
+
|
803 |
+
/**
|
804 |
+
* Update Table Prefix in wp_options
|
805 |
+
* @return bool
|
806 |
+
*/
|
807 |
+
protected function step15() {
|
808 |
+
$this->log( "Preparing Data Step15: Updating db prefix in {$this->prefix}options." );
|
809 |
+
|
810 |
+
// Skip - Table does not exist
|
811 |
+
if( false === $this->isTable( $this->prefix . 'options' ) ) {
|
812 |
+
return true;
|
813 |
+
}
|
814 |
+
|
815 |
+
// Skip - Table is not selected or updated
|
816 |
+
if( !in_array( $this->prefix . 'options', $this->tables ) ) {
|
817 |
+
$this->log( "Preparing Data Step4: Skipping" );
|
818 |
+
return true;
|
819 |
+
}
|
820 |
+
|
821 |
+
|
822 |
+
$this->log( "Updating db option_names in {$this->prefix}options. " );
|
823 |
+
|
824 |
+
// Filter the rows below. Do not update them!
|
825 |
+
$filters = array(
|
826 |
+
'wp_mail_smtp',
|
827 |
+
'wp_mail_smtp_version',
|
828 |
+
'wp_mail_smtp_debug',
|
829 |
+
);
|
830 |
+
|
831 |
+
$filters = apply_filters( 'wpstg_data_excl_rows', $filters );
|
832 |
+
|
833 |
+
$where = "";
|
834 |
+
foreach ( $filters as $filter ) {
|
835 |
+
$where .= " AND option_name <> '" . $filter . "'";
|
836 |
+
}
|
837 |
+
|
838 |
+
$updateOptions = $this->db->query(
|
839 |
+
$this->db->prepare(
|
840 |
+
"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 . "_%"
|
841 |
+
)
|
842 |
+
);
|
843 |
+
|
844 |
+
if( !$updateOptions ) {
|
845 |
+
$this->log( "Preparing Data Step15: Failed to update db option_names in {$this->prefix}options. Error: {$this->db->last_error}", Logger::TYPE_ERROR );
|
846 |
+
$this->returnException( "Data Crunching Step 15: Failed to update db option_names in {$this->prefix}options. Error: {$this->db->last_error}" );
|
847 |
+
return false;
|
848 |
+
}
|
849 |
+
|
850 |
+
return true;
|
851 |
+
}
|
852 |
+
|
853 |
+
/**
|
854 |
+
* Change upload_path in wp_options (if it is defined)
|
855 |
+
* @return bool
|
856 |
+
*/
|
857 |
+
protected function step16() {
|
858 |
+
$this->log( "Preparing Data Step16: Updating upload_path {$this->prefix}options." );
|
859 |
+
|
860 |
+
// Skip - Table does not exist
|
861 |
+
if( false === $this->isTable( $this->prefix . 'options' ) ) {
|
862 |
+
return true;
|
863 |
+
}
|
864 |
+
|
865 |
+
$newUploadPath = $this->getNewUploadPath();
|
866 |
+
|
867 |
+
if( false === $newUploadPath ) {
|
868 |
+
$this->log( "Preparing Data Step16: Skipping" );
|
869 |
+
return true;
|
870 |
+
}
|
871 |
+
|
872 |
+
// Skip - Table is not selected or updated
|
873 |
+
if( !in_array( $this->prefix . 'options', $this->tables ) ) {
|
874 |
+
$this->log( "Preparing Data Step16: Skipping" );
|
875 |
+
return true;
|
876 |
+
}
|
877 |
+
|
878 |
+
$error = isset( $this->db->last_error ) ? 'Last error: ' . $this->db->last_error : '';
|
879 |
+
|
880 |
+
$this->log( "Updating upload_path in {$this->prefix}options. {$error}" );
|
881 |
+
|
882 |
+
$updateOptions = $this->db->query(
|
883 |
+
$this->db->prepare(
|
884 |
+
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'upload_path'", $newUploadPath
|
885 |
+
)
|
886 |
+
);
|
887 |
+
|
888 |
+
if( !$updateOptions ) {
|
889 |
+
$this->log( "Preparing Data Step16: Failed to update upload_path in {$this->prefix}options. {$error}", Logger::TYPE_ERROR );
|
890 |
+
return true;
|
891 |
+
}
|
892 |
+
$this->Log( "Preparing Data: Finished Step 16 successfully" );
|
893 |
+
return true;
|
894 |
+
}
|
895 |
+
|
896 |
+
/**
|
897 |
+
* Update WP_CACHE in wp-config.php
|
898 |
+
* @return bool
|
899 |
+
*/
|
900 |
+
protected function step17() {
|
901 |
+
$path = ABSPATH . $this->options->cloneDirectoryName . "/wp-config.php";
|
902 |
+
|
903 |
+
$this->log( "Preparing Data Step17: Set WP_CACHE in wp-config.php to false");
|
904 |
+
|
905 |
+
if( false === ($content = file_get_contents( $path )) ) {
|
906 |
+
$this->log( "Preparing Data Step17: Failed to update WP_CACHE in wp-config.php. Can't read wp-config.php", Logger::TYPE_ERROR );
|
907 |
+
return false;
|
908 |
+
}
|
909 |
+
|
910 |
+
|
911 |
+
// Get WP_CACHE from wp-config.php
|
912 |
+
preg_match( "/define\s*\(\s*'WP_CACHE'\s*,\s*(.*)\s*\);/", $content, $matches );
|
913 |
+
|
914 |
+
if( !empty( $matches[1] ) ) {
|
915 |
+
$matches[1];
|
916 |
+
|
917 |
+
$pattern = "/define\s*\(\s*'WP_CACHE'\s*,\s*(.*)\s*\);/";
|
918 |
+
|
919 |
+
$replace = "define('WP_CACHE',false); // " . $matches[1];
|
920 |
+
$replace.= " // Changed by WP-Staging";
|
921 |
+
|
922 |
+
if( null === ($content = preg_replace( array($pattern), $replace, $content )) ) {
|
923 |
+
$this->log( "Preparing Data: Failed to change WP_CACHE", Logger::TYPE_ERROR );
|
924 |
+
return false;
|
925 |
+
}
|
926 |
+
} else {
|
927 |
+
$this->log( "Preparing Data Step17: WP_CACHE not defined in wp-config.php. Skipping this step." );
|
928 |
+
}
|
929 |
+
|
930 |
+
if( false === @file_put_contents( $path, $content ) ) {
|
931 |
+
$this->log( "Preparing Data Step17: Failed to update WP_CACHE. Can't save contents", Logger::TYPE_ERROR );
|
932 |
+
return false;
|
933 |
+
}
|
934 |
+
$this->Log( "Preparing Data: Finished Step 17 successfully" );
|
935 |
+
return true;
|
936 |
+
}
|
937 |
+
|
938 |
+
protected function getNewUploadPath() {
|
939 |
+
$uploadPath = get_option( 'upload_path' );
|
940 |
+
|
941 |
+
if( !$uploadPath ) {
|
942 |
+
return false;
|
943 |
+
}
|
944 |
+
|
945 |
+
$customSlug = str_replace( \WPStaging\WPStaging::getWPpath(), '', $uploadPath );
|
946 |
+
|
947 |
+
$newUploadPath = \WPStaging\WPStaging::getWPpath() . $this->options->cloneDirectoryName . DIRECTORY_SEPARATOR . $customSlug;
|
948 |
+
|
949 |
+
return $newUploadPath;
|
950 |
+
}
|
951 |
+
|
952 |
+
/**
|
953 |
+
* Return URL to staging site
|
954 |
+
* @return string
|
955 |
+
*/
|
956 |
+
protected function getStagingSiteUrl() {
|
957 |
+
if( $this->isSubDir() ) {
|
958 |
+
return rtrim( $this->multisiteHomeDomain, "/" ) . $this->getSubDir() . $this->options->cloneDirectoryName;
|
959 |
+
}
|
960 |
+
|
961 |
+
return rtrim( $this->multisiteHomeDomain, "/" ) . '/' . $this->options->cloneDirectoryName;
|
962 |
+
}
|
963 |
+
|
964 |
+
/**
|
965 |
+
* Check if WP is installed in subdir
|
966 |
+
* @return boolean
|
967 |
+
*/
|
968 |
+
protected function isSubDir() {
|
969 |
+
// Compare names without scheme to bypass cases where siteurl and home have different schemes http / https
|
970 |
+
// This is happening much more often than you would expect
|
971 |
+
$siteurl = preg_replace( '#^https?://#', '', rtrim( get_option( 'siteurl' ), '/' ) );
|
972 |
+
$home = preg_replace( '#^https?://#', '', rtrim( get_option( 'home' ), '/' ) );
|
973 |
+
|
974 |
+
if( $home !== $siteurl ) {
|
975 |
+
return true;
|
976 |
+
}
|
977 |
+
return false;
|
978 |
+
}
|
979 |
+
|
980 |
+
}
|
apps/Backend/Modules/Jobs/Multisite/Database.php
CHANGED
@@ -1,315 +1,315 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPStaging\Backend\Modules\Jobs\Multisite;
|
4 |
-
|
5 |
-
// No Direct Access
|
6 |
-
if( !defined( "WPINC" ) ) {
|
7 |
-
die;
|
8 |
-
}
|
9 |
-
|
10 |
-
use WPStaging\WPStaging;
|
11 |
-
use WPStaging\Utils\Strings;
|
12 |
-
use WPStaging\Backend\Modules\Jobs\JobExecutable;
|
13 |
-
|
14 |
-
/**
|
15 |
-
* Class Database
|
16 |
-
* @package WPStaging\Backend\Modules\Jobs
|
17 |
-
*/
|
18 |
-
class Database extends JobExecutable {
|
19 |
-
|
20 |
-
/**
|
21 |
-
* @var int
|
22 |
-
*/
|
23 |
-
private $total = 0;
|
24 |
-
|
25 |
-
/**
|
26 |
-
* @var \WPDB
|
27 |
-
*/
|
28 |
-
private $db;
|
29 |
-
|
30 |
-
/**
|
31 |
-
* Initialize
|
32 |
-
*/
|
33 |
-
public function initialize() {
|
34 |
-
// Add 2 to total table count because we need to copy two more tables from the main multisite installation wp_users and wp_usermeta
|
35 |
-
$this->total = count( $this->options->tables ) + 2;
|
36 |
-
$this->db = WPStaging::getInstance()->get( "wpdb" );
|
37 |
-
$this->isFatalError();
|
38 |
-
|
39 |
-
}
|
40 |
-
|
41 |
-
|
42 |
-
/**
|
43 |
-
* Return fatal error and stops here if subfolder already exists
|
44 |
-
* and mainJob is not updating the clone
|
45 |
-
* @return boolean
|
46 |
-
*/
|
47 |
-
private function isFatalError(){
|
48 |
-
$path = trailingslashit(get_home_path()) . $this->options->cloneDirectoryName;
|
49 |
-
if (isset($this->options->mainJob) && $this->options->mainJob !== 'updating' && is_dir($path)){
|
50 |
-
$this->returnException( " Can not continue! Change the name of the clone or delete existing folder. Then try again. Folder already exists: " . $path );
|
51 |
-
}
|
52 |
-
return false;
|
53 |
-
}
|
54 |
-
|
55 |
-
/**
|
56 |
-
* Calculate Total Steps in This Job and Assign It to $this->options->totalSteps
|
57 |
-
* @return void
|
58 |
-
*/
|
59 |
-
protected function calculateTotalSteps() {
|
60 |
-
$this->options->totalSteps = $this->total === 0 ? 1 : $this->total;
|
61 |
-
}
|
62 |
-
|
63 |
-
/**
|
64 |
-
* Execute the Current Step
|
65 |
-
* Returns false when over threshold limits are hit or when the job is done, true otherwise
|
66 |
-
* @return bool
|
67 |
-
*/
|
68 |
-
protected function execute() {
|
69 |
-
|
70 |
-
|
71 |
-
// Over limits threshold
|
72 |
-
if( $this->isOverThreshold() ) {
|
73 |
-
// Prepare response and save current progress
|
74 |
-
$this->prepareResponse( false, false );
|
75 |
-
$this->saveOptions();
|
76 |
-
return false;
|
77 |
-
}
|
78 |
-
|
79 |
-
// No more steps, finished
|
80 |
-
//if( $this->options->currentStep > $this->total || !isset( $this->options->tables[$this->options->currentStep] ) ) {
|
81 |
-
if( $this->options->currentStep > $this->total ) {
|
82 |
-
$this->prepareResponse( true, false );
|
83 |
-
return false;
|
84 |
-
}
|
85 |
-
|
86 |
-
// Copy table
|
87 |
-
//if (!$this->copyTable($this->options->tables[$this->options->currentStep]->name))
|
88 |
-
if( isset($this->options->tables[$this->options->currentStep]) && !$this->copyTable( $this->options->tables[$this->options->currentStep] ) ) {
|
89 |
-
// Prepare Response
|
90 |
-
$this->prepareResponse( false, false );
|
91 |
-
|
92 |
-
// Not finished
|
93 |
-
return true;
|
94 |
-
}
|
95 |
-
|
96 |
-
$this->copyWpUsers();
|
97 |
-
|
98 |
-
$this->copyWpUsermeta();
|
99 |
-
|
100 |
-
// Prepare Response
|
101 |
-
$this->prepareResponse();
|
102 |
-
|
103 |
-
// Not finished
|
104 |
-
return true;
|
105 |
-
}
|
106 |
-
|
107 |
-
/**
|
108 |
-
* Get new prefix for the staging site
|
109 |
-
* @return string
|
110 |
-
*/
|
111 |
-
private function getStagingPrefix() {
|
112 |
-
$stagingPrefix = $this->options->prefix;
|
113 |
-
// Make sure prefix of staging site is NEVER identical to prefix of live site!
|
114 |
-
if( $stagingPrefix == $this->db->prefix ) {
|
115 |
-
wp_die( 'Fatal error 7: The new database table prefix ' . $stagingPrefix . ' would be identical to the table prefix of the live site. Please open a support ticket at support@wp-staging.com' );
|
116 |
-
}
|
117 |
-
return $stagingPrefix;
|
118 |
-
}
|
119 |
-
|
120 |
-
/**
|
121 |
-
* No worries, SQL queries don't eat from PHP execution time!
|
122 |
-
* @param string $tableName
|
123 |
-
* @return bool
|
124 |
-
*/
|
125 |
-
private function copyTable( $tableName ) {
|
126 |
-
|
127 |
-
$strings = new Strings();
|
128 |
-
$tableName = is_object( $tableName ) ? $tableName->name : $tableName;
|
129 |
-
$newTableName = $this->getStagingPrefix() . $strings->str_replace_first( $this->db->prefix, null, $tableName );
|
130 |
-
|
131 |
-
// Drop table if necessary
|
132 |
-
$this->dropTable( $newTableName );
|
133 |
-
|
134 |
-
// Save current job
|
135 |
-
$this->setJob( $newTableName );
|
136 |
-
|
137 |
-
// Beginning of the job
|
138 |
-
if( !$this->startJob( $newTableName, $tableName ) ) {
|
139 |
-
return true;
|
140 |
-
}
|
141 |
-
|
142 |
-
// Copy data
|
143 |
-
$this->copyData( $newTableName, $tableName );
|
144 |
-
|
145 |
-
// Finish the step
|
146 |
-
return $this->finishStep();
|
147 |
-
}
|
148 |
-
|
149 |
-
/**
|
150 |
-
* Copy multisite global user table wp_users to wpstgX_users
|
151 |
-
* @return bool
|
152 |
-
*/
|
153 |
-
private function copyWpUsers() {
|
154 |
-
$strings = new Strings();
|
155 |
-
$tableName = $this->db->base_prefix . 'users';
|
156 |
-
$newTableName = $this->getStagingPrefix() . $strings->str_replace_first( $this->db->base_prefix, null, $tableName );
|
157 |
-
|
158 |
-
// Drop table if necessary
|
159 |
-
$this->dropTable( $newTableName );
|
160 |
-
|
161 |
-
// Save current job
|
162 |
-
$this->setJob( $newTableName );
|
163 |
-
|
164 |
-
// Beginning of the job
|
165 |
-
if( !$this->startJob( $newTableName, $tableName ) ) {
|
166 |
-
return true;
|
167 |
-
}
|
168 |
-
|
169 |
-
// Copy data
|
170 |
-
$this->copyData( $newTableName, $tableName );
|
171 |
-
|
172 |
-
// Finish the step
|
173 |
-
return $this->finishStep();
|
174 |
-
}
|
175 |
-
|
176 |
-
/**
|
177 |
-
* Copy multisite global user table wp_usermeta to wpstgX_users
|
178 |
-
* @return bool
|
179 |
-
*/
|
180 |
-
private function copyWpUsermeta() {
|
181 |
-
$strings = new Strings();
|
182 |
-
$tableName = $this->db->base_prefix . 'usermeta';
|
183 |
-
$newTableName = $this->getStagingPrefix() . $strings->str_replace_first( $this->db->base_prefix, null, $tableName );
|
184 |
-
|
185 |
-
// Drop table if necessary
|
186 |
-
$this->dropTable( $newTableName );
|
187 |
-
|
188 |
-
// Save current job
|
189 |
-
$this->setJob( $newTableName );
|
190 |
-
|
191 |
-
// Beginning of the job
|
192 |
-
if( !$this->startJob( $newTableName, $tableName ) ) {
|
193 |
-
return true;
|
194 |
-
}
|
195 |
-
// Copy data
|
196 |
-
$this->copyData( $newTableName, $tableName );
|
197 |
-
|
198 |
-
// Finish the step
|
199 |
-
return $this->finishStep();
|
200 |
-
}
|
201 |
-
|
202 |
-
/**
|
203 |
-
* Copy data from old table to new table
|
204 |
-
* @param string $new
|
205 |
-
* @param string $old
|
206 |
-
*/
|
207 |
-
private function copyData( $new, $old ) {
|
208 |
-
$rows = $this->options->job->start + $this->settings->queryLimit;
|
209 |
-
$this->log(
|
210 |
-
"DB Copy: {$old} as {$new} from {$this->options->job->start} to {$rows} records"
|
211 |
-
);
|
212 |
-
|
213 |
-
$limitation = '';
|
214 |
-
|
215 |
-
if( 0 < ( int ) $this->settings->queryLimit ) {
|
216 |
-
$limitation = " LIMIT {$this->settings->queryLimit} OFFSET {$this->options->job->start}";
|
217 |
-
}
|
218 |
-
|
219 |
-
$this->db->query(
|
220 |
-
"INSERT INTO {$new} SELECT * FROM {$old} {$limitation}"
|
221 |
-
);
|
222 |
-
|
223 |
-
// Set new offset
|
224 |
-
$this->options->job->start += $this->settings->queryLimit;
|
225 |
-
}
|
226 |
-
|
227 |
-
/**
|
228 |
-
* Set the job
|
229 |
-
* @param string $table
|
230 |
-
*/
|
231 |
-
private function setJob( $table ) {
|
232 |
-
if( isset( $this->options->job->current ) ) {
|
233 |
-
return;
|
234 |
-
}
|
235 |
-
|
236 |
-
$this->options->job->current = $table;
|
237 |
-
$this->options->job->start = 0;
|
238 |
-
}
|
239 |
-
|
240 |
-
/**
|
241 |
-
* Start Job
|
242 |
-
* @param string $new
|
243 |
-
* @param string $old
|
244 |
-
* @return bool
|
245 |
-
*/
|
246 |
-
private function startJob( $new, $old ) {
|
247 |
-
if( 0 != $this->options->job->start ) {
|
248 |
-
return true;
|
249 |
-
}
|
250 |
-
|
251 |
-
$this->log( "DB Copy: Creating table {$new}" );
|
252 |
-
|
253 |
-
$this->db->query( "CREATE TABLE {$new} LIKE {$old}" );
|
254 |
-
|
255 |
-
$this->options->job->total = ( int ) $this->db->get_var( "SELECT COUNT(1) FROM {$old}" );
|
256 |
-
|
257 |
-
if( 0 == $this->options->job->total ) {
|
258 |
-
$this->finishStep();
|
259 |
-
return false;
|
260 |
-
}
|
261 |
-
|
262 |
-
return true;
|
263 |
-
}
|
264 |
-
|
265 |
-
/**
|
266 |
-
* Finish the step
|
267 |
-
*/
|
268 |
-
private function finishStep() {
|
269 |
-
// This job is not finished yet
|
270 |
-
if( $this->options->job->total > $this->options->job->start ) {
|
271 |
-
return false;
|
272 |
-
}
|
273 |
-
|
274 |
-
// Add it to cloned tables listing
|
275 |
-
$this->options->clonedTables[] = isset($this->options->tables[$this->options->currentStep]) ? $this->options->tables[$this->options->currentStep] : false;
|
276 |
-
|
277 |
-
// Reset job
|
278 |
-
$this->options->job = new \stdClass();
|
279 |
-
|
280 |
-
return true;
|
281 |
-
}
|
282 |
-
|
283 |
-
/**
|
284 |
-
* Drop table if necessary
|
285 |
-
* @param string $new
|
286 |
-
*/
|
287 |
-
private function dropTable( $new ) {
|
288 |
-
$old = $this->db->get_var( $this->db->prepare( "SHOW TABLES LIKE %s", $new ) );
|
289 |
-
|
290 |
-
if( !$this->shouldDropTable( $new, $old ) ) {
|
291 |
-
return;
|
292 |
-
}
|
293 |
-
|
294 |
-
$this->log( "DB Copy: {$new} already exists, dropping it first" );
|
295 |
-
$this->db->query( "DROP TABLE {$new}" );
|
296 |
-
}
|
297 |
-
|
298 |
-
/**
|
299 |
-
* Check if table needs to be dropped
|
300 |
-
* @param string $new
|
301 |
-
* @param string $old
|
302 |
-
* @return bool
|
303 |
-
*/
|
304 |
-
private function shouldDropTable( $new, $old ) {
|
305 |
-
return (
|
306 |
-
$old === $new &&
|
307 |
-
(
|
308 |
-
!isset( $this->options->job->current ) ||
|
309 |
-
!isset( $this->options->job->start ) ||
|
310 |
-
0 == $this->options->job->start
|
311 |
-
)
|
312 |
-
);
|
313 |
-
}
|
314 |
-
|
315 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPStaging\Backend\Modules\Jobs\Multisite;
|
4 |
+
|
5 |
+
// No Direct Access
|
6 |
+
if( !defined( "WPINC" ) ) {
|
7 |
+
die;
|
8 |
+
}
|
9 |
+
|
10 |
+
use WPStaging\WPStaging;
|
11 |
+
use WPStaging\Utils\Strings;
|
12 |
+
use WPStaging\Backend\Modules\Jobs\JobExecutable;
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Class Database
|
16 |
+
* @package WPStaging\Backend\Modules\Jobs
|
17 |
+
*/
|
18 |
+
class Database extends JobExecutable {
|
19 |
+
|
20 |
+
/**
|
21 |
+
* @var int
|
22 |
+
*/
|
23 |
+
private $total = 0;
|
24 |
+
|
25 |
+
/**
|
26 |
+
* @var \WPDB
|
27 |
+
*/
|
28 |
+
private $db;
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Initialize
|
32 |
+
*/
|
33 |
+
public function initialize() {
|
34 |
+
// Add 2 to total table count because we need to copy two more tables from the main multisite installation wp_users and wp_usermeta
|
35 |
+
$this->total = count( $this->options->tables ) + 2;
|
36 |
+
$this->db = WPStaging::getInstance()->get( "wpdb" );
|
37 |
+
$this->isFatalError();
|
38 |
+
|
39 |
+
}
|
40 |
+
|
41 |
+
|
42 |
+
/**
|
43 |
+
* Return fatal error and stops here if subfolder already exists
|
44 |
+
* and mainJob is not updating the clone
|
45 |
+
* @return boolean
|
46 |
+
*/
|
47 |
+
private function isFatalError(){
|
48 |
+
$path = trailingslashit(get_home_path()) . $this->options->cloneDirectoryName;
|
49 |
+
if (isset($this->options->mainJob) && $this->options->mainJob !== 'updating' && is_dir($path)){
|
50 |
+
$this->returnException( " Can not continue! Change the name of the clone or delete existing folder. Then try again. Folder already exists: " . $path );
|
51 |
+
}
|
52 |
+
return false;
|
53 |
+
}
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Calculate Total Steps in This Job and Assign It to $this->options->totalSteps
|
57 |
+
* @return void
|
58 |
+
*/
|
59 |
+
protected function calculateTotalSteps() {
|
60 |
+
$this->options->totalSteps = $this->total === 0 ? 1 : $this->total;
|
61 |
+
}
|
62 |
+
|
63 |
+
/**
|
64 |
+
* Execute the Current Step
|
65 |
+
* Returns false when over threshold limits are hit or when the job is done, true otherwise
|
66 |
+
* @return bool
|
67 |
+
*/
|
68 |
+
protected function execute() {
|
69 |
+
|
70 |
+
|
71 |
+
// Over limits threshold
|
72 |
+
if( $this->isOverThreshold() ) {
|
73 |
+
// Prepare response and save current progress
|
74 |
+
$this->prepareResponse( false, false );
|
75 |
+
$this->saveOptions();
|
76 |
+
return false;
|
77 |
+
}
|
78 |
+
|
79 |
+
// No more steps, finished
|
80 |
+
//if( $this->options->currentStep > $this->total || !isset( $this->options->tables[$this->options->currentStep] ) ) {
|
81 |
+
if( $this->options->currentStep > $this->total ) {
|
82 |
+
$this->prepareResponse( true, false );
|
83 |
+
return false;
|
84 |
+
}
|
85 |
+
|
86 |
+
// Copy table
|
87 |
+
//if (!$this->copyTable($this->options->tables[$this->options->currentStep]->name))
|
88 |
+
if( isset($this->options->tables[$this->options->currentStep]) && !$this->copyTable( $this->options->tables[$this->options->currentStep] ) ) {
|
89 |
+
// Prepare Response
|
90 |
+
$this->prepareResponse( false, false );
|
91 |
+
|
92 |
+
// Not finished
|
93 |
+
return true;
|
94 |
+
}
|
95 |
+
|
96 |
+
$this->copyWpUsers();
|
97 |
+
|
98 |
+
$this->copyWpUsermeta();
|
99 |
+
|
100 |
+
// Prepare Response
|
101 |
+
$this->prepareResponse();
|
102 |
+
|
103 |
+
// Not finished
|
104 |
+
return true;
|
105 |
+
}
|
106 |
+
|
107 |
+
/**
|
108 |
+
* Get new prefix for the staging site
|
109 |
+
* @return string
|
110 |
+
*/
|
111 |
+
private function getStagingPrefix() {
|
112 |
+
$stagingPrefix = $this->options->prefix;
|
113 |
+
// Make sure prefix of staging site is NEVER identical to prefix of live site!
|
114 |
+
if( $stagingPrefix == $this->db->prefix ) {
|
115 |
+
wp_die( 'Fatal error 7: The new database table prefix ' . $stagingPrefix . ' would be identical to the table prefix of the live site. Please open a support ticket at support@wp-staging.com' );
|
116 |
+
}
|
117 |
+
return $stagingPrefix;
|
118 |
+
}
|
119 |
+
|
120 |
+
/**
|
121 |
+
* No worries, SQL queries don't eat from PHP execution time!
|
122 |
+
* @param string $tableName
|
123 |
+
* @return bool
|
124 |
+
*/
|
125 |
+
private function copyTable( $tableName ) {
|
126 |
+
|
127 |
+
$strings = new Strings();
|
128 |
+
$tableName = is_object( $tableName ) ? $tableName->name : $tableName;
|
129 |
+
$newTableName = $this->getStagingPrefix() . $strings->str_replace_first( $this->db->prefix, null, $tableName );
|
130 |
+
|
131 |
+
// Drop table if necessary
|
132 |
+
$this->dropTable( $newTableName );
|
133 |
+
|
134 |
+
// Save current job
|
135 |
+
$this->setJob( $newTableName );
|
136 |
+
|
137 |
+
// Beginning of the job
|
138 |
+
if( !$this->startJob( $newTableName, $tableName ) ) {
|
139 |
+
return true;
|
140 |
+
}
|
141 |
+
|
142 |
+
// Copy data
|
143 |
+
$this->copyData( $newTableName, $tableName );
|
144 |
+
|
145 |
+
// Finish the step
|
146 |
+
return $this->finishStep();
|
147 |
+
}
|
148 |
+
|
149 |
+
/**
|
150 |
+
* Copy multisite global user table wp_users to wpstgX_users
|
151 |
+
* @return bool
|
152 |
+
*/
|
153 |
+
private function copyWpUsers() {
|
154 |
+
$strings = new Strings();
|
155 |
+
$tableName = $this->db->base_prefix . 'users';
|
156 |
+
$newTableName = $this->getStagingPrefix() . $strings->str_replace_first( $this->db->base_prefix, null, $tableName );
|
157 |
+
|
158 |
+
// Drop table if necessary
|
159 |
+
$this->dropTable( $newTableName );
|
160 |
+
|
161 |
+
// Save current job
|
162 |
+
$this->setJob( $newTableName );
|
163 |
+
|
164 |
+
// Beginning of the job
|
165 |
+
if( !$this->startJob( $newTableName, $tableName ) ) {
|
166 |
+
return true;
|
167 |
+
}
|
168 |
+
|
169 |
+
// Copy data
|
170 |
+
$this->copyData( $newTableName, $tableName );
|
171 |
+
|
172 |
+
// Finish the step
|
173 |
+
return $this->finishStep();
|
174 |
+
}
|
175 |
+
|
176 |
+
/**
|
177 |
+
* Copy multisite global user table wp_usermeta to wpstgX_users
|
178 |
+
* @return bool
|
179 |
+
*/
|
180 |
+
private function copyWpUsermeta() {
|
181 |
+
$strings = new Strings();
|
182 |
+
$tableName = $this->db->base_prefix . 'usermeta';
|
183 |
+
$newTableName = $this->getStagingPrefix() . $strings->str_replace_first( $this->db->base_prefix, null, $tableName );
|
184 |
+
|
185 |
+
// Drop table if necessary
|
186 |
+
$this->dropTable( $newTableName );
|
187 |
+
|
188 |
+
// Save current job
|
189 |
+
$this->setJob( $newTableName );
|
190 |
+
|
191 |
+
// Beginning of the job
|
192 |
+
if( !$this->startJob( $newTableName, $tableName ) ) {
|
193 |
+
return true;
|
194 |
+
}
|
195 |
+
// Copy data
|
196 |
+
$this->copyData( $newTableName, $tableName );
|
197 |
+
|
198 |
+
// Finish the step
|
199 |
+
return $this->finishStep();
|
200 |
+
}
|
201 |
+
|
202 |
+
/**
|
203 |
+
* Copy data from old table to new table
|
204 |
+
* @param string $new
|
205 |
+
* @param string $old
|
206 |
+
*/
|
207 |
+
private function copyData( $new, $old ) {
|
208 |
+
$rows = $this->options->job->start + $this->settings->queryLimit;
|
209 |
+
$this->log(
|
210 |
+
"DB Copy: {$old} as {$new} from {$this->options->job->start} to {$rows} records"
|
211 |
+
);
|
212 |
+
|
213 |
+
$limitation = '';
|
214 |
+
|
215 |
+
if( 0 < ( int ) $this->settings->queryLimit ) {
|
216 |
+
$limitation = " LIMIT {$this->settings->queryLimit} OFFSET {$this->options->job->start}";
|
217 |
+
}
|
218 |
+
|
219 |
+
$this->db->query(
|
220 |
+
"INSERT INTO {$new} SELECT * FROM {$old} {$limitation}"
|
221 |
+
);
|
222 |
+
|
223 |
+
// Set new offset
|
224 |
+
$this->options->job->start += $this->settings->queryLimit;
|
225 |
+
}
|
226 |
+
|
227 |
+
/**
|
228 |
+
* Set the job
|
229 |
+
* @param string $table
|
230 |
+
*/
|
231 |
+
private function setJob( $table ) {
|
232 |
+
if( isset( $this->options->job->current ) ) {
|
233 |
+
return;
|
234 |
+
}
|
235 |
+
|
236 |
+
$this->options->job->current = $table;
|
237 |
+
$this->options->job->start = 0;
|
238 |
+
}
|
239 |
+
|
240 |
+
/**
|
241 |
+
* Start Job
|
242 |
+
* @param string $new
|
243 |
+
* @param string $old
|
244 |
+
* @return bool
|
245 |
+
*/
|
246 |
+
private function startJob( $new, $old ) {
|
247 |
+
if( 0 != $this->options->job->start ) {
|
248 |
+
return true;
|
249 |
+
}
|
250 |
+
|
251 |
+
$this->log( "DB Copy: Creating table {$new}" );
|
252 |
+
|
253 |
+
$this->db->query( "CREATE TABLE {$new} LIKE {$old}" );
|
254 |
+
|
255 |
+
$this->options->job->total = ( int ) $this->db->get_var( "SELECT COUNT(1) FROM {$old}" );
|
256 |
+
|
257 |
+
if( 0 == $this->options->job->total ) {
|
258 |
+
$this->finishStep();
|
259 |
+
return false;
|
260 |
+
}
|
261 |
+
|
262 |
+
return true;
|
263 |
+
}
|
264 |
+
|
265 |
+
/**
|
266 |
+
* Finish the step
|
267 |
+
*/
|
268 |
+
private function finishStep() {
|
269 |
+
// This job is not finished yet
|
270 |
+
if( $this->options->job->total > $this->options->job->start ) {
|
271 |
+
return false;
|
272 |
+
}
|
273 |
+
|
274 |
+
// Add it to cloned tables listing
|
275 |
+
$this->options->clonedTables[] = isset($this->options->tables[$this->options->currentStep]) ? $this->options->tables[$this->options->currentStep] : false;
|
276 |
+
|
277 |
+
// Reset job
|
278 |
+
$this->options->job = new \stdClass();
|
279 |
+
|
280 |
+
return true;
|
281 |
+
}
|
282 |
+
|
283 |
+
/**
|
284 |
+
* Drop table if necessary
|
285 |
+
* @param string $new
|
286 |
+
*/
|
287 |
+
private function dropTable( $new ) {
|
288 |
+
$old = $this->db->get_var( $this->db->prepare( "SHOW TABLES LIKE %s", $new ) );
|
289 |
+
|
290 |
+
if( !$this->shouldDropTable( $new, $old ) ) {
|
291 |
+
return;
|
292 |
+
}
|
293 |
+
|
294 |
+
$this->log( "DB Copy: {$new} already exists, dropping it first" );
|
295 |
+
$this->db->query( "DROP TABLE {$new}" );
|
296 |
+
}
|
297 |
+
|
298 |
+
/**
|
299 |
+
* Check if table needs to be dropped
|
300 |
+
* @param string $new
|
301 |
+
* @param string $old
|
302 |
+
* @return bool
|
303 |
+
*/
|
304 |
+
private function shouldDropTable( $new, $old ) {
|
305 |
+
return (
|
306 |
+
$old === $new &&
|
307 |
+
(
|
308 |
+
!isset( $this->options->job->current ) ||
|
309 |
+
!isset( $this->options->job->start ) ||
|
310 |
+
0 == $this->options->job->start
|
311 |
+
)
|
312 |
+
);
|
313 |
+
}
|
314 |
+
|
315 |
+
}
|
apps/Backend/Modules/Jobs/Multisite/Directories.php
CHANGED
@@ -1,655 +1,655 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPStaging\Backend\Modules\Jobs\Multisite;
|
4 |
-
|
5 |
-
// No Direct Access
|
6 |
-
if( !defined( "WPINC" ) ) {
|
7 |
-
die;
|
8 |
-
}
|
9 |
-
|
10 |
-
use WPStaging\WPStaging;
|
11 |
-
use WPStaging\Utils\Logger;
|
12 |
-
use WPStaging\Utils\Strings;
|
13 |
-
use WPStaging\Iterators\RecursiveDirectoryIterator;
|
14 |
-
use WPStaging\Iterators\RecursiveFilterNewLine;
|
15 |
-
use WPStaging\Iterators\RecursiveFilterExclude;
|
16 |
-
use WPStaging\Backend\Modules\Jobs\JobExecutable;
|
17 |
-
|
18 |
-
/**
|
19 |
-
* Class Files
|
20 |
-
* @package WPStaging\Backend\Modules\Directories
|
21 |
-
*/
|
22 |
-
class Directories extends JobExecutable {
|
23 |
-
|
24 |
-
/**
|
25 |
-
* @var array
|
26 |
-
*/
|
27 |
-
private $files = array();
|
28 |
-
|
29 |
-
/**
|
30 |
-
* Total steps to do
|
31 |
-
* @var int
|
32 |
-
*/
|
33 |
-
private $total = 5;
|
34 |
-
|
35 |
-
/**
|
36 |
-
* path to the cache file
|
37 |
-
* @var string
|
38 |
-
*/
|
39 |
-
private $filename;
|
40 |
-
|
41 |
-
/**
|
42 |
-
* Initialize
|
43 |
-
*/
|
44 |
-
public function initialize() {
|
45 |
-
$this->filename = $this->cache->getCacheDir() . "files_to_copy." . $this->cache->getCacheExtension();
|
46 |
-
}
|
47 |
-
|
48 |
-
/**
|
49 |
-
* Calculate Total Steps in This Job and Assign It to $this->options->totalSteps
|
50 |
-
* @return void
|
51 |
-
*/
|
52 |
-
protected function calculateTotalSteps() {
|
53 |
-
|
54 |
-
$this->options->totalSteps = $this->total + count( $this->options->extraDirectories );
|
55 |
-
}
|
56 |
-
|
57 |
-
/**
|
58 |
-
* Start Module
|
59 |
-
* @return object
|
60 |
-
*/
|
61 |
-
public function start() {
|
62 |
-
|
63 |
-
// Execute steps
|
64 |
-
$this->run();
|
65 |
-
|
66 |
-
// Save option, progress
|
67 |
-
$this->saveProgress();
|
68 |
-
|
69 |
-
return ( object ) $this->response;
|
70 |
-
}
|
71 |
-
|
72 |
-
/**
|
73 |
-
* Step 0
|
74 |
-
* Get WP Root files
|
75 |
-
* Does not collect any sub folders
|
76 |
-
*/
|
77 |
-
private function getWpRootFiles() {
|
78 |
-
|
79 |
-
// open file handle
|
80 |
-
$files = $this->open( $this->filename, 'a' );
|
81 |
-
|
82 |
-
|
83 |
-
try {
|
84 |
-
|
85 |
-
// Iterate over wp root directory
|
86 |
-
$iterator = new \DirectoryIterator( \WPStaging\WPStaging::getWPpath() );
|
87 |
-
|
88 |
-
$this->log( "Scanning / for files" );
|
89 |
-
|
90 |
-
// Write path line
|
91 |
-
foreach ( $iterator as $item ) {
|
92 |
-
if( !$item->isDot() && $item->isFile() ) {
|
93 |
-
if( $this->write( $files, $iterator->getFilename() . PHP_EOL ) ) {
|
94 |
-
$this->options->totalFiles++;
|
95 |
-
|
96 |
-
// Add current file size
|
97 |
-
$this->options->totalFileSize += $iterator->getSize();
|
98 |
-
}
|
99 |
-
}
|
100 |
-
}
|
101 |
-
} catch ( \Exception $e ) {
|
102 |
-
$this->returnException( 'Error: ' . $e->getMessage() );
|
103 |
-
} catch ( \Exception $e ) {
|
104 |
-
// Skip bad file permissions
|
105 |
-
}
|
106 |
-
|
107 |
-
$this->close( $files );
|
108 |
-
return true;
|
109 |
-
}
|
110 |
-
|
111 |
-
/**
|
112 |
-
* Step 2
|
113 |
-
* Get WP Content Files without multisite folder wp-content/uploads/sites
|
114 |
-
*/
|
115 |
-
private function getWpContentFiles() {
|
116 |
-
|
117 |
-
// Skip it
|
118 |
-
if( $this->isDirectoryExcluded( WP_CONTENT_DIR ) ) {
|
119 |
-
$this->log( "Skip " . \WPStaging\WPStaging::getWPpath() . 'wp-content' . DIRECTORY_SEPARATOR );
|
120 |
-
return true;
|
121 |
-
}
|
122 |
-
// open file handle
|
123 |
-
$files = $this->open( $this->filename, 'a' );
|
124 |
-
|
125 |
-
/**
|
126 |
-
* Excluded folders relative to the folder to iterate
|
127 |
-
*/
|
128 |
-
$excludePaths = array(
|
129 |
-
'cache',
|
130 |
-
'plugins' . DIRECTORY_SEPARATOR . 'wps-hide-login',
|
131 |
-
'uploads' . DIRECTORY_SEPARATOR . 'sites'
|
132 |
-
);
|
133 |
-
|
134 |
-
/**
|
135 |
-
* Get user excluded folders
|
136 |
-
*/
|
137 |
-
$directory = array();
|
138 |
-
foreach ( $this->options->excludedDirectories as $dir ) {
|
139 |
-
if( strpos( $dir, WP_CONTENT_DIR ) !== false ) {
|
140 |
-
$directory[] = ltrim( str_replace( WP_CONTENT_DIR, '', $dir ), '/' );
|
141 |
-
}
|
142 |
-
}
|
143 |
-
|
144 |
-
$excludePaths = array_merge( $excludePaths, $directory );
|
145 |
-
|
146 |
-
// $excludeFolders = array(
|
147 |
-
// 'cache',
|
148 |
-
// 'node_modules',
|
149 |
-
// 'nbproject',
|
150 |
-
// 'wps-hide-login'
|
151 |
-
// );
|
152 |
-
|
153 |
-
try {
|
154 |
-
|
155 |
-
// Iterate over content directory
|
156 |
-
$iterator = new \WPStaging\Iterators\RecursiveDirectoryIterator( WP_CONTENT_DIR );
|
157 |
-
|
158 |
-
// Exclude new line file names
|
159 |
-
$iterator = new \WPStaging\Iterators\RecursiveFilterNewLine( $iterator );
|
160 |
-
|
161 |
-
// Exclude sites, uploads, plugins or themes
|
162 |
-
$iterator = new \WPStaging\Iterators\RecursiveFilterExclude( $iterator, apply_filters( 'wpstg_clone_mu_excl_folders', $excludePaths ) );
|
163 |
-
// Recursively iterate over content directory
|
164 |
-
$iterator = new \RecursiveIteratorIterator( $iterator, \RecursiveIteratorIterator::LEAVES_ONLY, \RecursiveIteratorIterator::CATCH_GET_CHILD );
|
165 |
-
|
166 |
-
$this->log( "Scanning /wp-content for its sub-directories and files" );
|
167 |
-
|
168 |
-
// Write path line
|
169 |
-
foreach ( $iterator as $item ) {
|
170 |
-
if( $item->isFile() ) {
|
171 |
-
$file = 'wp-content' . DIRECTORY_SEPARATOR . $iterator->getSubPathName() . PHP_EOL;
|
172 |
-
if( $this->write( $files, $file ) ) {
|
173 |
-
$this->options->totalFiles++;
|
174 |
-
|
175 |
-
// Add current file size
|
176 |
-
$this->options->totalFileSize += $iterator->getSize();
|
177 |
-
}
|
178 |
-
}
|
179 |
-
}
|
180 |
-
} catch ( \Exception $e ) {
|
181 |
-
$this->returnException( 'Error: ' . $e->getMessage() );
|
182 |
-
//throw new \Exception( 'Error: ' . $e->getMessage() );
|
183 |
-
} catch ( \Exception $e ) {
|
184 |
-
// Skip bad file permissions
|
185 |
-
}
|
186 |
-
|
187 |
-
// close the file handler
|
188 |
-
$this->close( $files );
|
189 |
-
return true;
|
190 |
-
}
|
191 |
-
|
192 |
-
/**
|
193 |
-
* Step 2
|
194 |
-
* @return boolean
|
195 |
-
* @throws \Exception
|
196 |
-
*/
|
197 |
-
private function getWpIncludesFiles() {
|
198 |
-
|
199 |
-
// Skip it
|
200 |
-
if( $this->isDirectoryExcluded( \WPStaging\WPStaging::getWPpath() . 'wp-includes' . DIRECTORY_SEPARATOR ) ) {
|
201 |
-
$this->log( "Skip " . \WPStaging\WPStaging::getWPpath() . 'wp-includes' . DIRECTORY_SEPARATOR );
|
202 |
-
return true;
|
203 |
-
}
|
204 |
-
|
205 |
-
// open file handle and attach data to end of file
|
206 |
-
$files = $this->open( $this->filename, 'a' );
|
207 |
-
|
208 |
-
try {
|
209 |
-
|
210 |
-
// Iterate over wp-admin directory
|
211 |
-
$iterator = new \WPStaging\Iterators\RecursiveDirectoryIterator( \WPStaging\WPStaging::getWPpath() . 'wp-includes' . DIRECTORY_SEPARATOR );
|
212 |
-
|
213 |
-
// Exclude new line file names
|
214 |
-
$iterator = new \WPStaging\Iterators\RecursiveFilterNewLine( $iterator );
|
215 |
-
|
216 |
-
// Recursively iterate over wp-includes directory
|
217 |
-
$iterator = new \RecursiveIteratorIterator( $iterator, \RecursiveIteratorIterator::LEAVES_ONLY, \RecursiveIteratorIterator::CATCH_GET_CHILD );
|
218 |
-
|
219 |
-
$this->log( "Scanning /wp-includes for its sub-directories and files" );
|
220 |
-
|
221 |
-
// Write files
|
222 |
-
foreach ( $iterator as $item ) {
|
223 |
-
if( $item->isFile() ) {
|
224 |
-
if( $this->write( $files, 'wp-includes' . DIRECTORY_SEPARATOR . $iterator->getSubPathName() . PHP_EOL ) ) {
|
225 |
-
$this->options->totalFiles++;
|
226 |
-
|
227 |
-
// Add current file size
|
228 |
-
$this->options->totalFileSize += $iterator->getSize();
|
229 |
-
}
|
230 |
-
}
|
231 |
-
}
|
232 |
-
} catch ( \Exception $e ) {
|
233 |
-
//$this->returnException('Out of disk space.');
|
234 |
-
throw new \Exception( 'Error: ' . $e->getMessage() );
|
235 |
-
} catch ( \Exception $e ) {
|
236 |
-
// Skip bad file permissions
|
237 |
-
}
|
238 |
-
|
239 |
-
// close the file handler
|
240 |
-
$this->close( $files );
|
241 |
-
return true;
|
242 |
-
}
|
243 |
-
|
244 |
-
/**
|
245 |
-
* Step 3
|
246 |
-
* @return boolean
|
247 |
-
* @throws \Exception
|
248 |
-
*/
|
249 |
-
private function getWpAdminFiles() {
|
250 |
-
|
251 |
-
// Skip it
|
252 |
-
if( $this->isDirectoryExcluded( \WPStaging\WPStaging::getWPpath() . 'wp-admin' . DIRECTORY_SEPARATOR ) ) {
|
253 |
-
$this->log( "Skip " . \WPStaging\WPStaging::getWPpath() . 'wp-admin' . DIRECTORY_SEPARATOR );
|
254 |
-
return true;
|
255 |
-
}
|
256 |
-
|
257 |
-
// open file handle and attach data to end of file
|
258 |
-
$files = $this->open( $this->filename, 'a' );
|
259 |
-
|
260 |
-
try {
|
261 |
-
|
262 |
-
// Iterate over wp-admin directory
|
263 |
-
$iterator = new \WPStaging\Iterators\RecursiveDirectoryIterator( \WPStaging\WPStaging::getWPpath() . 'wp-admin' . DIRECTORY_SEPARATOR );
|
264 |
-
|
265 |
-
// Exclude new line file names
|
266 |
-
$iterator = new \WPStaging\Iterators\RecursiveFilterNewLine( $iterator );
|
267 |
-
|
268 |
-
// Recursively iterate over content directory
|
269 |
-
$iterator = new \RecursiveIteratorIterator( $iterator, \RecursiveIteratorIterator::LEAVES_ONLY, \RecursiveIteratorIterator::CATCH_GET_CHILD );
|
270 |
-
|
271 |
-
$this->log( "Scanning /wp-admin for its sub-directories and files" );
|
272 |
-
|
273 |
-
// Write path line
|
274 |
-
foreach ( $iterator as $item ) {
|
275 |
-
if( $item->isFile() ) {
|
276 |
-
if( $this->write( $files, 'wp-admin' . DIRECTORY_SEPARATOR . $iterator->getSubPathName() . PHP_EOL ) ) {
|
277 |
-
$this->options->totalFiles++;
|
278 |
-
// Add current file size
|
279 |
-
$this->options->totalFileSize += $iterator->getSize();
|
280 |
-
}
|
281 |
-
}
|
282 |
-
}
|
283 |
-
} catch ( \Exception $e ) {
|
284 |
-
$this->returnException( 'Error: ' . $e->getMessage() );
|
285 |
-
//throw new \Exception('Error: ' . $e->getMessage());
|
286 |
-
} catch ( \Exception $e ) {
|
287 |
-
// Skip bad file permissions
|
288 |
-
}
|
289 |
-
|
290 |
-
// close the file handler
|
291 |
-
$this->close( $files );
|
292 |
-
return true;
|
293 |
-
}
|
294 |
-
|
295 |
-
/**
|
296 |
-
* Step 4
|
297 |
-
* Get WP Content Uploads Files multisite folder wp-content/uploads/sites or wp-content/blogs.dir/ID/files
|
298 |
-
*/
|
299 |
-
private function getWpContentUploadsSites() {
|
300 |
-
|
301 |
-
// Skip if main site is cloned
|
302 |
-
if( is_main_site() ) {
|
303 |
-
return true;
|
304 |
-
}
|
305 |
-
|
306 |
-
$blogId = get_current_blog_id();
|
307 |
-
|
308 |
-
// Absolute path to uploads folder
|
309 |
-
//$path = WP_CONTENT_DIR . DIRECTORY_SEPARATOR . 'uploads' . DIRECTORY_SEPARATOR . 'sites' . DIRECTORY_SEPARATOR . $blogId . DIRECTORY_SEPARATOR;
|
310 |
-
$path = $this->getAbsUploadPath();
|
311 |
-
|
312 |
-
// Skip it
|
313 |
-
if( !is_dir( $path ) ) {
|
314 |
-
return true;
|
315 |
-
}
|
316 |
-
|
317 |
-
// Skip it
|
318 |
-
if( $this->isDirectoryExcluded( $path ) ) {
|
319 |
-
return true;
|
320 |
-
}
|
321 |
-
|
322 |
-
|
323 |
-
// open file handle
|
324 |
-
$files = $this->open( $this->filename, 'a' );
|
325 |
-
|
326 |
-
/**
|
327 |
-
* Excluded folders relative to the folder to iterate
|
328 |
-
*/
|
329 |
-
$excludePaths = array(
|
330 |
-
'cache',
|
331 |
-
'plugins' . DIRECTORY_SEPARATOR . 'wps-hide-login',
|
332 |
-
'uploads' . DIRECTORY_SEPARATOR . 'sites'
|
333 |
-
);
|
334 |
-
|
335 |
-
/**
|
336 |
-
* Get user excluded folders
|
337 |
-
*/
|
338 |
-
$directory = array();
|
339 |
-
foreach ( $this->options->excludedDirectories as $dir ) {
|
340 |
-
if( strpos( $dir, $path ) !== false ) {
|
341 |
-
$directory[] = ltrim( str_replace( $path, '', $dir ), '/' );
|
342 |
-
}
|
343 |
-
}
|
344 |
-
|
345 |
-
$excludePaths = array_merge( $excludePaths, $directory );
|
346 |
-
|
347 |
-
try {
|
348 |
-
|
349 |
-
// Iterate over content directory
|
350 |
-
$iterator = new \WPStaging\Iterators\RecursiveDirectoryIterator( $path );
|
351 |
-
|
352 |
-
// Exclude new line file names
|
353 |
-
$iterator = new \WPStaging\Iterators\RecursiveFilterNewLine( $iterator );
|
354 |
-
|
355 |
-
// Exclude sites, uploads, plugins or themes
|
356 |
-
$iterator = new \WPStaging\Iterators\RecursiveFilterExclude( $iterator, $excludePaths );
|
357 |
-
|
358 |
-
// Recursively iterate over content directory
|
359 |
-
$iterator = new \RecursiveIteratorIterator( $iterator, \RecursiveIteratorIterator::LEAVES_ONLY, \RecursiveIteratorIterator::CATCH_GET_CHILD );
|
360 |
-
$this->log( "Scanning /wp-content/uploads/sites/{$blogId} for its sub-directories and files" );
|
361 |
-
|
362 |
-
// Write path line
|
363 |
-
foreach ( $iterator as $item ) {
|
364 |
-
if( $item->isFile() ) {
|
365 |
-
//$file = 'wp-content' . DIRECTORY_SEPARATOR . 'uploads' . DIRECTORY_SEPARATOR . 'sites' . DIRECTORY_SEPARATOR . $blogId . DIRECTORY_SEPARATOR . $iterator->getSubPathName() . PHP_EOL;
|
366 |
-
$file = $this->getRelUploadPath() . $iterator->getSubPathName() . PHP_EOL;
|
367 |
-
if( $this->write( $files, $file ) ) {
|
368 |
-
$this->options->totalFiles++;
|
369 |
-
|
370 |
-
// Add current file size
|
371 |
-
$this->options->totalFileSize += $iterator->getSize();
|
372 |
-
}
|
373 |
-
}
|
374 |
-
}
|
375 |
-
} catch ( \Exception $e ) {
|
376 |
-
$this->returnException( 'Error: ' . $e->getMessage() );
|
377 |
-
//throw new \Exception( 'Error: ' . $e->getMessage() );
|
378 |
-
} catch ( \Exception $e ) {
|
379 |
-
// Skip bad file permissions
|
380 |
-
}
|
381 |
-
|
382 |
-
// close the file handler
|
383 |
-
$this->close( $files );
|
384 |
-
return true;
|
385 |
-
}
|
386 |
-
|
387 |
-
/**
|
388 |
-
* Get absolute path to the upload folder e.g. /srv/www/wp-content/blogs.dir/ID/files or /srv/www/wp-content/uploads/sites/ID/
|
389 |
-
* @return type
|
390 |
-
*/
|
391 |
-
private function getAbsUploadPath() {
|
392 |
-
// Check first which method is used
|
393 |
-
$uploads = wp_upload_dir();
|
394 |
-
$basedir = $uploads['basedir'];
|
395 |
-
|
396 |
-
return trailingslashit($basedir);
|
397 |
-
|
398 |
-
// if( false === strpos( $basedir, 'blogs.dir' ) ) {
|
399 |
-
// // Since WP 3.5
|
400 |
-
// return 'wp-content' . DIRECTORY_SEPARATOR . 'uploads' . DIRECTORY_SEPARATOR . 'sites' . DIRECTORY_SEPARATOR . get_current_blog_id();
|
401 |
-
// } else {
|
402 |
-
// // old blog structure
|
403 |
-
// return 'wp-content' . DIRECTORY_SEPARATOR . 'blogs.dir' . DIRECTORY_SEPARATOR . get_current_blog_id() . DIRECTORY_SEPARATOR . 'files';
|
404 |
-
// }
|
405 |
-
}
|
406 |
-
/**
|
407 |
-
* Get relative path to the upload folder like wp-content/uploads or wp-content/blogs.dir/2/files
|
408 |
-
* @return string
|
409 |
-
*/
|
410 |
-
private function getRelUploadPath() {
|
411 |
-
$uploads = wp_upload_dir();
|
412 |
-
$basedir = $uploads['basedir'];
|
413 |
-
|
414 |
-
return trailingslashit(str_replace(\WPStaging\WPStaging::getWPpath(), '', $basedir));
|
415 |
-
}
|
416 |
-
|
417 |
-
/**
|
418 |
-
* Step 5 - x
|
419 |
-
* Get extra folders of the wp root level
|
420 |
-
* Does not collect wp-includes, wp-admin and wp-content folder
|
421 |
-
*/
|
422 |
-
private function getExtraFiles( $folder ) {
|
423 |
-
|
424 |
-
|
425 |
-
// open file handle and attach data to end of file
|
426 |
-
$files = $this->open( $this->filename, 'a' );
|
427 |
-
|
428 |
-
try {
|
429 |
-
|
430 |
-
// Iterate over extra directory
|
431 |
-
$iterator = new \WPStaging\Iterators\RecursiveDirectoryIterator( $folder );
|
432 |
-
|
433 |
-
// Exclude new line file names
|
434 |
-
$iterator = new \WPStaging\Iterators\RecursiveFilterNewLine( $iterator );
|
435 |
-
|
436 |
-
// Exclude wp core folders
|
437 |
-
// $exclude = array('wp-includes',
|
438 |
-
// 'wp-admin',
|
439 |
-
// 'wp-content');
|
440 |
-
//
|
441 |
-
// $excludeMore = array();
|
442 |
-
// foreach ($this->options->excludedDirectories as $key => $value){
|
443 |
-
// $excludeMore[] = $this->getLastElemAfterString('/', $value);
|
444 |
-
// }
|
445 |
-
//$exclude = array_merge($exclude, $excludeMore);
|
446 |
-
|
447 |
-
$exclude = array();
|
448 |
-
|
449 |
-
$iterator = new \WPStaging\Iterators\RecursiveFilterExclude( $iterator, $exclude );
|
450 |
-
// Recursively iterate over content directory
|
451 |
-
$iterator = new \RecursiveIteratorIterator( $iterator, \RecursiveIteratorIterator::LEAVES_ONLY, \RecursiveIteratorIterator::CATCH_GET_CHILD );
|
452 |
-
|
453 |
-
$strings = new Strings();
|
454 |
-
$this->log( "Scanning {$strings->getLastElemAfterString( '/', $folder )} for its sub-directories and files" );
|
455 |
-
|
456 |
-
// Write path line
|
457 |
-
foreach ( $iterator as $item ) {
|
458 |
-
if( $item->isFile() ) {
|
459 |
-
//if( $this->write( $files, $strings->getLastElemAfterString( '/', $folder ) . DIRECTORY_SEPARATOR . $iterator->getSubPathName() . PHP_EOL ) ) {
|
460 |
-
if( $this->write( $files, str_replace( \WPStaging\WPStaging::getWPpath(), '', $folder ) . DIRECTORY_SEPARATOR . $iterator->getSubPathName() . PHP_EOL ) ) {
|
461 |
-
$this->options->totalFiles++;
|
462 |
-
// Add current file size
|
463 |
-
$this->options->totalFileSize += $iterator->getSize();
|
464 |
-
}
|
465 |
-
}
|
466 |
-
}
|
467 |
-
} catch ( \Exception $e ) {
|
468 |
-
$this->returnException( 'Error: ' . $e->getMessage() );
|
469 |
-
} catch ( \Exception $e ) {
|
470 |
-
// Skip bad file permissions
|
471 |
-
}
|
472 |
-
|
473 |
-
// close the file handler
|
474 |
-
$this->close( $files );
|
475 |
-
return true;
|
476 |
-
}
|
477 |
-
|
478 |
-
/**
|
479 |
-
* Closes a file handle
|
480 |
-
*
|
481 |
-
* @param resource $handle File handle to close
|
482 |
-
* @return boolean
|
483 |
-
*/
|
484 |
-
public function close( $handle ) {
|
485 |
-
return @fclose( $handle );
|
486 |
-
}
|
487 |
-
|
488 |
-
/**
|
489 |
-
* Opens a file in specified mode
|
490 |
-
*
|
491 |
-
* @param string $file Path to the file to open
|
492 |
-
* @param string $mode Mode in which to open the file
|
493 |
-
* @return resource
|
494 |
-
* @throws Exception
|
495 |
-
*/
|
496 |
-
public function open( $file, $mode ) {
|
497 |
-
|
498 |
-
$file_handle = @fopen( $file, $mode );
|
499 |
-
if( false === $file_handle ) {
|
500 |
-
$this->returnException( sprintf( __( 'Unable to open %s with mode %s', 'wp-staging' ), $file, $mode ) );
|
501 |
-
//throw new Exception(sprintf(__('Unable to open %s with mode %s', 'wp-staging'), $file, $mode));
|
502 |
-
}
|
503 |
-
|
504 |
-
return $file_handle;
|
505 |
-
}
|
506 |
-
|
507 |
-
/**
|
508 |
-
* Write contents to a file
|
509 |
-
*
|
510 |
-
* @param resource $handle File handle to write to
|
511 |
-
* @param string $content Contents to write to the file
|
512 |
-
* @return integer
|
513 |
-
* @throws Exception
|
514 |
-
* @throws Exception
|
515 |
-
*/
|
516 |
-
public function write( $handle, $content ) {
|
517 |
-
$write_result = @fwrite( $handle, $content );
|
518 |
-
if( false === $write_result ) {
|
519 |
-
if( ( $meta = \stream_get_meta_data( $handle ) ) ) {
|
520 |
-
//$this->returnException(sprintf(__('Unable to write to: %s', 'wp-staging'), $meta['uri']));
|
521 |
-
throw new \Exception( sprintf( __( 'Unable to write to: %s', 'wp-staging' ), $meta['uri'] ) );
|
522 |
-
}
|
523 |
-
} elseif( strlen( $content ) !== $write_result ) {
|
524 |
-
//$this->returnException(__('Out of disk space.', 'wp-staging'));
|
525 |
-
throw new \Exception( __( 'Out of disk space.', 'wp-staging' ) );
|
526 |
-
}
|
527 |
-
|
528 |
-
return $write_result;
|
529 |
-
}
|
530 |
-
|
531 |
-
/**
|
532 |
-
* Execute the Current Step
|
533 |
-
* Returns false when over threshold limits are hit or when the job is done, true otherwise
|
534 |
-
* @return bool
|
535 |
-
*/
|
536 |
-
protected function execute() {
|
537 |
-
|
538 |
-
// No job left to execute
|
539 |
-
if( $this->isFinished() ) {
|
540 |
-
$this->prepareResponse( true, false );
|
541 |
-
return false;
|
542 |
-
}
|
543 |
-
|
544 |
-
|
545 |
-
if( $this->options->currentStep == 0 ) {
|
546 |
-
$this->getWpRootFiles();
|
547 |
-
$this->prepareResponse( false, true );
|
548 |
-
return false;
|
549 |
-
}
|
550 |
-
|
551 |
-
if( $this->options->currentStep == 1 ) {
|
552 |
-
$this->getWpContentFiles();
|
553 |
-
$this->prepareResponse( false, true );
|
554 |
-
return false;
|
555 |
-
}
|
556 |
-
|
557 |
-
if( $this->options->currentStep == 2 ) {
|
558 |
-
$this->getWpIncludesFiles();
|
559 |
-
$this->prepareResponse( false, true );
|
560 |
-
return false;
|
561 |
-
}
|
562 |
-
|
563 |
-
if( $this->options->currentStep == 3 ) {
|
564 |
-
$this->getWpAdminFiles();
|
565 |
-
$this->prepareResponse( false, true );
|
566 |
-
return false;
|
567 |
-
}
|
568 |
-
|
569 |
-
if( $this->options->currentStep == 4 ) {
|
570 |
-
$this->getWpContentUploadsSites();
|
571 |
-
$this->prepareResponse( false, true );
|
572 |
-
return false;
|
573 |
-
}
|
574 |
-
|
575 |
-
if( isset( $this->options->extraDirectories[$this->options->currentStep - $this->total] ) ) {
|
576 |
-
$this->getExtraFiles( $this->options->extraDirectories[$this->options->currentStep - $this->total] );
|
577 |
-
$this->prepareResponse( false, true );
|
578 |
-
return false;
|
579 |
-
}
|
580 |
-
|
581 |
-
|
582 |
-
// Prepare response
|
583 |
-
$this->prepareResponse( false, true );
|
584 |
-
// Not finished
|
585 |
-
return true;
|
586 |
-
}
|
587 |
-
|
588 |
-
/**
|
589 |
-
* Checks Whether There is Any Job to Execute or Not
|
590 |
-
* @return bool
|
591 |
-
*/
|
592 |
-
protected function isFinished() {
|
593 |
-
if( $this->options->currentStep >= $this->options->totalSteps ) {
|
594 |
-
return true;
|
595 |
-
}
|
596 |
-
|
597 |
-
// return (
|
598 |
-
// //$this->options->currentStep > $this->total ||
|
599 |
-
// $this->options->currentStep >= $this->options->totalSteps
|
600 |
-
// );
|
601 |
-
}
|
602 |
-
|
603 |
-
/**
|
604 |
-
* Save files
|
605 |
-
* @return bool
|
606 |
-
*/
|
607 |
-
protected function saveProgress() {
|
608 |
-
return $this->saveOptions();
|
609 |
-
}
|
610 |
-
|
611 |
-
/**
|
612 |
-
* Get files
|
613 |
-
* @return void
|
614 |
-
*/
|
615 |
-
protected function getFiles() {
|
616 |
-
$fileName = $this->cache->getCacheDir() . "files_to_copy." . $this->cache->getCacheExtension();
|
617 |
-
|
618 |
-
if( false === ($this->files = @file_get_contents( $fileName )) ) {
|
619 |
-
$this->files = array();
|
620 |
-
return;
|
621 |
-
}
|
622 |
-
|
623 |
-
$this->files = explode( PHP_EOL, $this->files );
|
624 |
-
}
|
625 |
-
|
626 |
-
/**
|
627 |
-
* Replace forward slash with current directory separator
|
628 |
-
*
|
629 |
-
* @param string $path Path
|
630 |
-
*
|
631 |
-
* @return string
|
632 |
-
*/
|
633 |
-
private function sanitizeDirectorySeparator( $path ) {
|
634 |
-
$string = str_replace( "/", "\\", $path );
|
635 |
-
return str_replace( '\\\\', '\\', $string );
|
636 |
-
}
|
637 |
-
|
638 |
-
/**
|
639 |
-
* Check if directory is excluded
|
640 |
-
* @param string $directory
|
641 |
-
* @return bool
|
642 |
-
*/
|
643 |
-
protected function isDirectoryExcluded( $directory ) {
|
644 |
-
$directory = $this->sanitizeDirectorySeparator( $directory );
|
645 |
-
foreach ( $this->options->excludedDirectories as $excludedDirectory ) {
|
646 |
-
$excludedDirectory = $this->sanitizeDirectorySeparator( $excludedDirectory );
|
647 |
-
if( strpos( trailingslashit( $directory ), trailingslashit( $excludedDirectory ) ) === 0 ) {
|
648 |
-
return true;
|
649 |
-
}
|
650 |
-
}
|
651 |
-
|
652 |
-
return false;
|
653 |
-
}
|
654 |
-
|
655 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPStaging\Backend\Modules\Jobs\Multisite;
|
4 |
+
|
5 |
+
// No Direct Access
|
6 |
+
if( !defined( "WPINC" ) ) {
|
7 |
+
die;
|
8 |
+
}
|
9 |
+
|
10 |
+
use WPStaging\WPStaging;
|
11 |
+
use WPStaging\Utils\Logger;
|
12 |
+
use WPStaging\Utils\Strings;
|
13 |
+
use WPStaging\Iterators\RecursiveDirectoryIterator;
|
14 |
+
use WPStaging\Iterators\RecursiveFilterNewLine;
|
15 |
+
use WPStaging\Iterators\RecursiveFilterExclude;
|
16 |
+
use WPStaging\Backend\Modules\Jobs\JobExecutable;
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Class Files
|
20 |
+
* @package WPStaging\Backend\Modules\Directories
|
21 |
+
*/
|
22 |
+
class Directories extends JobExecutable {
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @var array
|
26 |
+
*/
|
27 |
+
private $files = array();
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Total steps to do
|
31 |
+
* @var int
|
32 |
+
*/
|
33 |
+
private $total = 5;
|
34 |
+
|
35 |
+
/**
|
36 |
+
* path to the cache file
|
37 |
+
* @var string
|
38 |
+
*/
|
39 |
+
private $filename;
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Initialize
|
43 |
+
*/
|
44 |
+
public function initialize() {
|
45 |
+
$this->filename = $this->cache->getCacheDir() . "files_to_copy." . $this->cache->getCacheExtension();
|
46 |
+
}
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Calculate Total Steps in This Job and Assign It to $this->options->totalSteps
|
50 |
+
* @return void
|
51 |
+
*/
|
52 |
+
protected function calculateTotalSteps() {
|
53 |
+
|
54 |
+
$this->options->totalSteps = $this->total + count( $this->options->extraDirectories );
|
55 |
+
}
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Start Module
|
59 |
+
* @return object
|
60 |
+
*/
|
61 |
+
public function start() {
|
62 |
+
|
63 |
+
// Execute steps
|
64 |
+
$this->run();
|
65 |
+
|
66 |
+
// Save option, progress
|
67 |
+
$this->saveProgress();
|
68 |
+
|
69 |
+
return ( object ) $this->response;
|
70 |
+
}
|
71 |
+
|
72 |
+
/**
|
73 |
+
* Step 0
|
74 |
+
* Get WP Root files
|
75 |
+
* Does not collect any sub folders
|
76 |
+
*/
|
77 |
+
private function getWpRootFiles() {
|
78 |
+
|
79 |
+
// open file handle
|
80 |
+
$files = $this->open( $this->filename, 'a' );
|
81 |
+
|
82 |
+
|
83 |
+
try {
|
84 |
+
|
85 |
+
// Iterate over wp root directory
|
86 |
+
$iterator = new \DirectoryIterator( \WPStaging\WPStaging::getWPpath() );
|
87 |
+
|
88 |
+
$this->log( "Scanning / for files" );
|
89 |
+
|
90 |
+
// Write path line
|
91 |
+
foreach ( $iterator as $item ) {
|
92 |
+
if( !$item->isDot() && $item->isFile() ) {
|
93 |
+
if( $this->write( $files, $iterator->getFilename() . PHP_EOL ) ) {
|
94 |
+
$this->options->totalFiles++;
|
95 |
+
|
96 |
+
// Add current file size
|
97 |
+
$this->options->totalFileSize += $iterator->getSize();
|
98 |
+
}
|
99 |
+
}
|
100 |
+
}
|
101 |
+
} catch ( \Exception $e ) {
|
102 |
+
$this->returnException( 'Error: ' . $e->getMessage() );
|
103 |
+
} catch ( \Exception $e ) {
|
104 |
+
// Skip bad file permissions
|
105 |
+
}
|
106 |
+
|
107 |
+
$this->close( $files );
|
108 |
+
return true;
|
109 |
+
}
|
110 |
+
|
111 |
+
/**
|
112 |
+
* Step 2
|
113 |
+
* Get WP Content Files without multisite folder wp-content/uploads/sites
|
114 |
+
*/
|
115 |
+
private function getWpContentFiles() {
|
116 |
+
|
117 |
+
// Skip it
|
118 |
+
if( $this->isDirectoryExcluded( WP_CONTENT_DIR ) ) {
|
119 |
+
$this->log( "Skip " . \WPStaging\WPStaging::getWPpath() . 'wp-content' . DIRECTORY_SEPARATOR );
|
120 |
+
return true;
|
121 |
+
}
|
122 |
+
// open file handle
|
123 |
+
$files = $this->open( $this->filename, 'a' );
|
124 |
+
|
125 |
+
/**
|
126 |
+
* Excluded folders relative to the folder to iterate
|
127 |
+
*/
|
128 |
+
$excludePaths = array(
|
129 |
+
'cache',
|
130 |
+
'plugins' . DIRECTORY_SEPARATOR . 'wps-hide-login',
|
131 |
+
'uploads' . DIRECTORY_SEPARATOR . 'sites'
|
132 |
+
);
|
133 |
+
|
134 |
+
/**
|
135 |
+
* Get user excluded folders
|
136 |
+
*/
|
137 |
+
$directory = array();
|
138 |
+
foreach ( $this->options->excludedDirectories as $dir ) {
|
139 |
+
if( strpos( $dir, WP_CONTENT_DIR ) !== false ) {
|
140 |
+
$directory[] = ltrim( str_replace( WP_CONTENT_DIR, '', $dir ), '/' );
|
141 |
+
}
|
142 |
+
}
|
143 |
+
|
144 |
+
$excludePaths = array_merge( $excludePaths, $directory );
|
145 |
+
|
146 |
+
// $excludeFolders = array(
|
147 |
+
// 'cache',
|
148 |
+
// 'node_modules',
|
149 |
+
// 'nbproject',
|
150 |
+
// 'wps-hide-login'
|
151 |
+
// );
|
152 |
+
|
153 |
+
try {
|
154 |
+
|
155 |
+
// Iterate over content directory
|
156 |
+
$iterator = new \WPStaging\Iterators\RecursiveDirectoryIterator( WP_CONTENT_DIR );
|
157 |
+
|
158 |
+
// Exclude new line file names
|
159 |
+
$iterator = new \WPStaging\Iterators\RecursiveFilterNewLine( $iterator );
|
160 |
+
|
161 |
+
// Exclude sites, uploads, plugins or themes
|
162 |
+
$iterator = new \WPStaging\Iterators\RecursiveFilterExclude( $iterator, apply_filters( 'wpstg_clone_mu_excl_folders', $excludePaths ) );
|
163 |
+
// Recursively iterate over content directory
|
164 |
+
$iterator = new \RecursiveIteratorIterator( $iterator, \RecursiveIteratorIterator::LEAVES_ONLY, \RecursiveIteratorIterator::CATCH_GET_CHILD );
|
165 |
+
|
166 |
+
$this->log( "Scanning /wp-content for its sub-directories and files" );
|
167 |
+
|
168 |
+
// Write path line
|
169 |
+
foreach ( $iterator as $item ) {
|
170 |
+
if( $item->isFile() ) {
|
171 |
+
$file = 'wp-content' . DIRECTORY_SEPARATOR . $iterator->getSubPathName() . PHP_EOL;
|
172 |
+
if( $this->write( $files, $file ) ) {
|
173 |
+
$this->options->totalFiles++;
|
174 |
+
|
175 |
+
// Add current file size
|
176 |
+
$this->options->totalFileSize += $iterator->getSize();
|
177 |
+
}
|
178 |
+
}
|
179 |
+
}
|
180 |
+
} catch ( \Exception $e ) {
|
181 |
+
$this->returnException( 'Error: ' . $e->getMessage() );
|
182 |
+
//throw new \Exception( 'Error: ' . $e->getMessage() );
|
183 |
+
} catch ( \Exception $e ) {
|
184 |
+
// Skip bad file permissions
|
185 |
+
}
|
186 |
+
|
187 |
+
// close the file handler
|
188 |
+
$this->close( $files );
|
189 |
+
return true;
|
190 |
+
}
|
191 |
+
|
192 |
+
/**
|
193 |
+
* Step 2
|
194 |
+
* @return boolean
|
195 |
+
* @throws \Exception
|
196 |
+
*/
|
197 |
+
private function getWpIncludesFiles() {
|
198 |
+
|
199 |
+
// Skip it
|
200 |
+
if( $this->isDirectoryExcluded( \WPStaging\WPStaging::getWPpath() . 'wp-includes' . DIRECTORY_SEPARATOR ) ) {
|
201 |
+
$this->log( "Skip " . \WPStaging\WPStaging::getWPpath() . 'wp-includes' . DIRECTORY_SEPARATOR );
|
202 |
+
return true;
|
203 |
+
}
|
204 |
+
|
205 |
+
// open file handle and attach data to end of file
|
206 |
+
$files = $this->open( $this->filename, 'a' );
|
207 |
+
|
208 |
+
try {
|
209 |
+
|
210 |
+
// Iterate over wp-admin directory
|
211 |
+
$iterator = new \WPStaging\Iterators\RecursiveDirectoryIterator( \WPStaging\WPStaging::getWPpath() . 'wp-includes' . DIRECTORY_SEPARATOR );
|
212 |
+
|
213 |
+
// Exclude new line file names
|
214 |
+
$iterator = new \WPStaging\Iterators\RecursiveFilterNewLine( $iterator );
|
215 |
+
|
216 |
+
// Recursively iterate over wp-includes directory
|
217 |
+
$iterator = new \RecursiveIteratorIterator( $iterator, \RecursiveIteratorIterator::LEAVES_ONLY, \RecursiveIteratorIterator::CATCH_GET_CHILD );
|
218 |
+
|
219 |
+
$this->log( "Scanning /wp-includes for its sub-directories and files" );
|
220 |
+
|
221 |
+
// Write files
|
222 |
+
foreach ( $iterator as $item ) {
|
223 |
+
if( $item->isFile() ) {
|
224 |
+
if( $this->write( $files, 'wp-includes' . DIRECTORY_SEPARATOR . $iterator->getSubPathName() . PHP_EOL ) ) {
|
225 |
+
$this->options->totalFiles++;
|
226 |
+
|
227 |
+
// Add current file size
|
228 |
+
$this->options->totalFileSize += $iterator->getSize();
|
229 |
+
}
|
230 |
+
}
|
231 |
+
}
|
232 |
+
} catch ( \Exception $e ) {
|
233 |
+
//$this->returnException('Out of disk space.');
|
234 |
+
throw new \Exception( 'Error: ' . $e->getMessage() );
|
235 |
+
} catch ( \Exception $e ) {
|
236 |
+
// Skip bad file permissions
|
237 |
+
}
|
238 |
+
|
239 |
+
// close the file handler
|
240 |
+
$this->close( $files );
|
241 |
+
return true;
|
242 |
+
}
|
243 |
+
|
244 |
+
/**
|
245 |
+
* Step 3
|
246 |
+
* @return boolean
|
247 |
+
* @throws \Exception
|
248 |
+
*/
|
249 |
+
private function getWpAdminFiles() {
|
250 |
+
|
251 |
+
// Skip it
|
252 |
+
if( $this->isDirectoryExcluded( \WPStaging\WPStaging::getWPpath() . 'wp-admin' . DIRECTORY_SEPARATOR ) ) {
|
253 |
+
$this->log( "Skip " . \WPStaging\WPStaging::getWPpath() . 'wp-admin' . DIRECTORY_SEPARATOR );
|
254 |
+
return true;
|
255 |
+
}
|
256 |
+
|
257 |
+
// open file handle and attach data to end of file
|
258 |
+
$files = $this->open( $this->filename, 'a' );
|
259 |
+
|
260 |
+
try {
|
261 |
+
|
262 |
+
// Iterate over wp-admin directory
|
263 |
+
$iterator = new \WPStaging\Iterators\RecursiveDirectoryIterator( \WPStaging\WPStaging::getWPpath() . 'wp-admin' . DIRECTORY_SEPARATOR );
|
264 |
+
|
265 |
+
// Exclude new line file names
|
266 |
+
$iterator = new \WPStaging\Iterators\RecursiveFilterNewLine( $iterator );
|
267 |
+
|
268 |
+
// Recursively iterate over content directory
|
269 |
+
$iterator = new \RecursiveIteratorIterator( $iterator, \RecursiveIteratorIterator::LEAVES_ONLY, \RecursiveIteratorIterator::CATCH_GET_CHILD );
|
270 |
+
|
271 |
+
$this->log( "Scanning /wp-admin for its sub-directories and files" );
|
272 |
+
|
273 |
+
// Write path line
|
274 |
+
foreach ( $iterator as $item ) {
|
275 |
+
if( $item->isFile() ) {
|
276 |
+
if( $this->write( $files, 'wp-admin' . DIRECTORY_SEPARATOR . $iterator->getSubPathName() . PHP_EOL ) ) {
|
277 |
+
$this->options->totalFiles++;
|
278 |
+
// Add current file size
|
279 |
+
$this->options->totalFileSize += $iterator->getSize();
|
280 |
+
}
|
281 |
+
}
|
282 |
+
}
|
283 |
+
} catch ( \Exception $e ) {
|
284 |
+
$this->returnException( 'Error: ' . $e->getMessage() );
|
285 |
+
//throw new \Exception('Error: ' . $e->getMessage());
|
286 |
+
} catch ( \Exception $e ) {
|
287 |
+
// Skip bad file permissions
|
288 |
+
}
|
289 |
+
|
290 |
+
// close the file handler
|
291 |
+
$this->close( $files );
|
292 |
+
return true;
|
293 |
+
}
|
294 |
+
|
295 |
+
/**
|
296 |
+
* Step 4
|
297 |
+
* Get WP Content Uploads Files multisite folder wp-content/uploads/sites or wp-content/blogs.dir/ID/files
|
298 |
+
*/
|
299 |
+
private function getWpContentUploadsSites() {
|
300 |
+
|
301 |
+
// Skip if main site is cloned
|
302 |
+
if( is_main_site() ) {
|
303 |
+
return true;
|
304 |
+
}
|
305 |
+
|
306 |
+
$blogId = get_current_blog_id();
|
307 |
+
|
308 |
+
// Absolute path to uploads folder
|
309 |
+
//$path = WP_CONTENT_DIR . DIRECTORY_SEPARATOR . 'uploads' . DIRECTORY_SEPARATOR . 'sites' . DIRECTORY_SEPARATOR . $blogId . DIRECTORY_SEPARATOR;
|
310 |
+
$path = $this->getAbsUploadPath();
|
311 |
+
|
312 |
+
// Skip it
|
313 |
+
if( !is_dir( $path ) ) {
|
314 |
+
return true;
|
315 |
+
}
|
316 |
+
|
317 |
+
// Skip it
|
318 |
+
if( $this->isDirectoryExcluded( $path ) ) {
|
319 |
+
return true;
|
320 |
+
}
|
321 |
+
|
322 |
+
|
323 |
+
// open file handle
|
324 |
+
$files = $this->open( $this->filename, 'a' );
|
325 |
+
|
326 |
+
/**
|
327 |
+
* Excluded folders relative to the folder to iterate
|
328 |
+
*/
|
329 |
+
$excludePaths = array(
|
330 |
+
'cache',
|
331 |
+
'plugins' . DIRECTORY_SEPARATOR . 'wps-hide-login',
|
332 |
+
'uploads' . DIRECTORY_SEPARATOR . 'sites'
|
333 |
+
);
|
334 |
+
|
335 |
+
/**
|
336 |
+
* Get user excluded folders
|
337 |
+
*/
|
338 |
+
$directory = array();
|
339 |
+
foreach ( $this->options->excludedDirectories as $dir ) {
|
340 |
+
if( strpos( $dir, $path ) !== false ) {
|
341 |
+
$directory[] = ltrim( str_replace( $path, '', $dir ), '/' );
|
342 |
+
}
|
343 |
+
}
|
344 |
+
|
345 |
+
$excludePaths = array_merge( $excludePaths, $directory );
|
346 |
+
|
347 |
+
try {
|
348 |
+
|
349 |
+
// Iterate over content directory
|
350 |
+
$iterator = new \WPStaging\Iterators\RecursiveDirectoryIterator( $path );
|
351 |
+
|
352 |
+
// Exclude new line file names
|
353 |
+
$iterator = new \WPStaging\Iterators\RecursiveFilterNewLine( $iterator );
|
354 |
+
|
355 |
+
// Exclude sites, uploads, plugins or themes
|
356 |
+
$iterator = new \WPStaging\Iterators\RecursiveFilterExclude( $iterator, $excludePaths );
|
357 |
+
|
358 |
+
// Recursively iterate over content directory
|
359 |
+
$iterator = new \RecursiveIteratorIterator( $iterator, \RecursiveIteratorIterator::LEAVES_ONLY, \RecursiveIteratorIterator::CATCH_GET_CHILD );
|
360 |
+
$this->log( "Scanning /wp-content/uploads/sites/{$blogId} for its sub-directories and files" );
|
361 |
+
|
362 |
+
// Write path line
|
363 |
+
foreach ( $iterator as $item ) {
|
364 |
+
if( $item->isFile() ) {
|
365 |
+
//$file = 'wp-content' . DIRECTORY_SEPARATOR . 'uploads' . DIRECTORY_SEPARATOR . 'sites' . DIRECTORY_SEPARATOR . $blogId . DIRECTORY_SEPARATOR . $iterator->getSubPathName() . PHP_EOL;
|
366 |
+
$file = $this->getRelUploadPath() . $iterator->getSubPathName() . PHP_EOL;
|
367 |
+
if( $this->write( $files, $file ) ) {
|
368 |
+
$this->options->totalFiles++;
|
369 |
+
|
370 |
+
// Add current file size
|
371 |
+
$this->options->totalFileSize += $iterator->getSize();
|
372 |
+
}
|
373 |
+
}
|
374 |
+
}
|
375 |
+
} catch ( \Exception $e ) {
|
376 |
+
$this->returnException( 'Error: ' . $e->getMessage() );
|
377 |
+
//throw new \Exception( 'Error: ' . $e->getMessage() );
|
378 |
+
} catch ( \Exception $e ) {
|
379 |
+
// Skip bad file permissions
|
380 |
+
}
|
381 |
+
|
382 |
+
// close the file handler
|
383 |
+
$this->close( $files );
|
384 |
+
return true;
|
385 |
+
}
|
386 |
+
|
387 |
+
/**
|
388 |
+
* Get absolute path to the upload folder e.g. /srv/www/wp-content/blogs.dir/ID/files or /srv/www/wp-content/uploads/sites/ID/
|
389 |
+
* @return type
|
390 |
+
*/
|
391 |
+
private function getAbsUploadPath() {
|
392 |
+
// Check first which method is used
|
393 |
+
$uploads = wp_upload_dir();
|
394 |
+
$basedir = $uploads['basedir'];
|
395 |
+
|
396 |
+
return trailingslashit($basedir);
|
397 |
+
|
398 |
+
// if( false === strpos( $basedir, 'blogs.dir' ) ) {
|
399 |
+
// // Since WP 3.5
|
400 |
+
// return 'wp-content' . DIRECTORY_SEPARATOR . 'uploads' . DIRECTORY_SEPARATOR . 'sites' . DIRECTORY_SEPARATOR . get_current_blog_id();
|
401 |
+
// } else {
|
402 |
+
// // old blog structure
|
403 |
+
// return 'wp-content' . DIRECTORY_SEPARATOR . 'blogs.dir' . DIRECTORY_SEPARATOR . get_current_blog_id() . DIRECTORY_SEPARATOR . 'files';
|
404 |
+
// }
|
405 |
+
}
|
406 |
+
/**
|
407 |
+
* Get relative path to the upload folder like wp-content/uploads or wp-content/blogs.dir/2/files
|
408 |
+
* @return string
|
409 |
+
*/
|
410 |
+
private function getRelUploadPath() {
|
411 |
+
$uploads = wp_upload_dir();
|
412 |
+
$basedir = $uploads['basedir'];
|
413 |
+
|
414 |
+
return trailingslashit(str_replace(\WPStaging\WPStaging::getWPpath(), '', $basedir));
|
415 |
+
}
|
416 |
+
|
417 |
+
/**
|
418 |
+
* Step 5 - x
|
419 |
+
* Get extra folders of the wp root level
|
420 |
+
* Does not collect wp-includes, wp-admin and wp-content folder
|
421 |
+
*/
|
422 |
+
private function getExtraFiles( $folder ) {
|
423 |
+
|
424 |
+
|
425 |
+
// open file handle and attach data to end of file
|
426 |
+
$files = $this->open( $this->filename, 'a' );
|
427 |
+
|
428 |
+
try {
|
429 |
+
|
430 |
+
// Iterate over extra directory
|
431 |
+
$iterator = new \WPStaging\Iterators\RecursiveDirectoryIterator( $folder );
|
432 |
+
|
433 |
+
// Exclude new line file names
|
434 |
+
$iterator = new \WPStaging\Iterators\RecursiveFilterNewLine( $iterator );
|
435 |
+
|
436 |
+
// Exclude wp core folders
|
437 |
+
// $exclude = array('wp-includes',
|
438 |
+
// 'wp-admin',
|
439 |
+
// 'wp-content');
|
440 |
+
//
|
441 |
+
// $excludeMore = array();
|
442 |
+
// foreach ($this->options->excludedDirectories as $key => $value){
|
443 |
+
// $excludeMore[] = $this->getLastElemAfterString('/', $value);
|
444 |
+
// }
|
445 |
+
//$exclude = array_merge($exclude, $excludeMore);
|
446 |
+
|
447 |
+
$exclude = array();
|
448 |
+
|
449 |
+
$iterator = new \WPStaging\Iterators\RecursiveFilterExclude( $iterator, $exclude );
|
450 |
+
// Recursively iterate over content directory
|
451 |
+
$iterator = new \RecursiveIteratorIterator( $iterator, \RecursiveIteratorIterator::LEAVES_ONLY, \RecursiveIteratorIterator::CATCH_GET_CHILD );
|
452 |
+
|
453 |
+
$strings = new Strings();
|
454 |
+
$this->log( "Scanning {$strings->getLastElemAfterString( '/', $folder )} for its sub-directories and files" );
|
455 |
+
|
456 |
+
// Write path line
|
457 |
+
foreach ( $iterator as $item ) {
|
458 |
+
if( $item->isFile() ) {
|
459 |
+
//if( $this->write( $files, $strings->getLastElemAfterString( '/', $folder ) . DIRECTORY_SEPARATOR . $iterator->getSubPathName() . PHP_EOL ) ) {
|
460 |
+
if( $this->write( $files, str_replace( \WPStaging\WPStaging::getWPpath(), '', $folder ) . DIRECTORY_SEPARATOR . $iterator->getSubPathName() . PHP_EOL ) ) {
|
461 |
+
$this->options->totalFiles++;
|
462 |
+
// Add current file size
|
463 |
+
$this->options->totalFileSize += $iterator->getSize();
|
464 |
+
}
|
465 |
+
}
|
466 |
+
}
|
467 |
+
} catch ( \Exception $e ) {
|
468 |
+
$this->returnException( 'Error: ' . $e->getMessage() );
|
469 |
+
} catch ( \Exception $e ) {
|
470 |
+
// Skip bad file permissions
|
471 |
+
}
|
472 |
+
|
473 |
+
// close the file handler
|
474 |
+
$this->close( $files );
|
475 |
+
return true;
|
476 |
+
}
|
477 |
+
|
478 |
+
/**
|
479 |
+
* Closes a file handle
|
480 |
+
*
|
481 |
+
* @param resource $handle File handle to close
|
482 |
+
* @return boolean
|
483 |
+
*/
|
484 |
+
public function close( $handle ) {
|
485 |
+
return @fclose( $handle );
|
486 |
+
}
|
487 |
+
|
488 |
+
/**
|
489 |
+
* Opens a file in specified mode
|
490 |
+
*
|
491 |
+
* @param string $file Path to the file to open
|
492 |
+
* @param string $mode Mode in which to open the file
|
493 |
+
* @return resource
|
494 |
+
* @throws Exception
|
495 |
+
*/
|
496 |
+
public function open( $file, $mode ) {
|
497 |
+
|
498 |
+
$file_handle = @fopen( $file, $mode );
|
499 |
+
if( false === $file_handle ) {
|
500 |
+
$this->returnException( sprintf( __( 'Unable to open %s with mode %s', 'wp-staging' ), $file, $mode ) );
|
501 |
+
//throw new Exception(sprintf(__('Unable to open %s with mode %s', 'wp-staging'), $file, $mode));
|
502 |
+
}
|
503 |
+
|
504 |
+
return $file_handle;
|
505 |
+
}
|
506 |
+
|
507 |
+
/**
|
508 |
+
* Write contents to a file
|
509 |
+
*
|
510 |
+
* @param resource $handle File handle to write to
|
511 |
+
* @param string $content Contents to write to the file
|
512 |
+
* @return integer
|
513 |
+
* @throws Exception
|
514 |
+
* @throws Exception
|
515 |
+
*/
|
516 |
+
public function write( $handle, $content ) {
|
517 |
+
$write_result = @fwrite( $handle, $content );
|
518 |
+
if( false === $write_result ) {
|
519 |
+
if( ( $meta = \stream_get_meta_data( $handle ) ) ) {
|
520 |
+
//$this->returnException(sprintf(__('Unable to write to: %s', 'wp-staging'), $meta['uri']));
|
521 |
+
throw new \Exception( sprintf( __( 'Unable to write to: %s', 'wp-staging' ), $meta['uri'] ) );
|
522 |
+
}
|
523 |
+
} elseif( strlen( $content ) !== $write_result ) {
|
524 |
+
//$this->returnException(__('Out of disk space.', 'wp-staging'));
|
525 |
+
throw new \Exception( __( 'Out of disk space.', 'wp-staging' ) );
|
526 |
+
}
|
527 |
+
|
528 |
+
return $write_result;
|
529 |
+
}
|
530 |
+
|
531 |
+
/**
|
532 |
+
* Execute the Current Step
|
533 |
+
* Returns false when over threshold limits are hit or when the job is done, true otherwise
|
534 |
+
* @return bool
|
535 |
+
*/
|
536 |
+
protected function execute() {
|
537 |
+
|
538 |
+
// No job left to execute
|
539 |
+
if( $this->isFinished() ) {
|
540 |
+
$this->prepareResponse( true, false );
|
541 |
+
return false;
|
542 |
+
}
|
543 |
+
|
544 |
+
|
545 |
+
if( $this->options->currentStep == 0 ) {
|
546 |
+
$this->getWpRootFiles();
|
547 |
+
$this->prepareResponse( false, true );
|
548 |
+
return false;
|
549 |
+
}
|
550 |
+
|
551 |
+
if( $this->options->currentStep == 1 ) {
|
552 |
+
$this->getWpContentFiles();
|
553 |
+
$this->prepareResponse( false, true );
|
554 |
+
return false;
|
555 |
+
}
|
556 |
+
|
557 |
+
if( $this->options->currentStep == 2 ) {
|
558 |
+
$this->getWpIncludesFiles();
|
559 |
+
$this->prepareResponse( false, true );
|
560 |
+
return false;
|
561 |
+
}
|
562 |
+
|
563 |
+
if( $this->options->currentStep == 3 ) {
|
564 |
+
$this->getWpAdminFiles();
|
565 |
+
$this->prepareResponse( false, true );
|
566 |
+
return false;
|
567 |
+
}
|
568 |
+
|
569 |
+
if( $this->options->currentStep == 4 ) {
|
570 |
+
$this->getWpContentUploadsSites();
|
571 |
+
$this->prepareResponse( false, true );
|
572 |
+
return false;
|
573 |
+
}
|
574 |
+
|
575 |
+
if( isset( $this->options->extraDirectories[$this->options->currentStep - $this->total] ) ) {
|
576 |
+
$this->getExtraFiles( $this->options->extraDirectories[$this->options->currentStep - $this->total] );
|
577 |
+
$this->prepareResponse( false, true );
|
578 |
+
return false;
|
579 |
+
}
|
580 |
+
|
581 |
+
|
582 |
+
// Prepare response
|
583 |
+
$this->prepareResponse( false, true );
|
584 |
+
// Not finished
|
585 |
+
return true;
|
586 |
+
}
|
587 |
+
|
588 |
+
/**
|
589 |
+
* Checks Whether There is Any Job to Execute or Not
|
590 |
+
* @return bool
|
591 |
+
*/
|
592 |
+
protected function isFinished() {
|
593 |
+
if( $this->options->currentStep >= $this->options->totalSteps ) {
|
594 |
+
return true;
|
595 |
+
}
|
596 |
+
|
597 |
+
// return (
|
598 |
+
// //$this->options->currentStep > $this->total ||
|
599 |
+
// $this->options->currentStep >= $this->options->totalSteps
|
600 |
+
// );
|
601 |
+
}
|
602 |
+
|
603 |
+
/**
|
604 |
+
* Save files
|
605 |
+
* @return bool
|
606 |
+
*/
|
607 |
+
protected function saveProgress() {
|
608 |
+
return $this->saveOptions();
|
609 |
+
}
|
610 |
+
|
611 |
+
/**
|
612 |
+
* Get files
|
613 |
+
* @return void
|
614 |
+
*/
|
615 |
+
protected function getFiles() {
|
616 |
+
$fileName = $this->cache->getCacheDir() . "files_to_copy." . $this->cache->getCacheExtension();
|
617 |
+
|
618 |
+
if( false === ($this->files = @file_get_contents( $fileName )) ) {
|
619 |
+
$this->files = array();
|
620 |
+
return;
|
621 |
+
}
|
622 |
+
|
623 |
+
$this->files = explode( PHP_EOL, $this->files );
|
624 |
+
}
|
625 |
+
|
626 |
+
/**
|
627 |
+
* Replace forward slash with current directory separator
|
628 |
+
*
|
629 |
+
* @param string $path Path
|
630 |
+
*
|
631 |
+
* @return string
|
632 |
+
*/
|
633 |
+
private function sanitizeDirectorySeparator( $path ) {
|
634 |
+
$string = str_replace( "/", "\\", $path );
|
635 |
+
return str_replace( '\\\\', '\\', $string );
|
636 |
+
}
|
637 |
+
|
638 |
+
/**
|
639 |
+
* Check if directory is excluded
|
640 |
+
* @param string $directory
|
641 |
+
* @return bool
|
642 |
+
*/
|
643 |
+
protected function isDirectoryExcluded( $directory ) {
|
644 |
+
$directory = $this->sanitizeDirectorySeparator( $directory );
|
645 |
+
foreach ( $this->options->excludedDirectories as $excludedDirectory ) {
|
646 |
+
$excludedDirectory = $this->sanitizeDirectorySeparator( $excludedDirectory );
|
647 |
+
if( strpos( trailingslashit( $directory ), trailingslashit( $excludedDirectory ) ) === 0 ) {
|
648 |
+
return true;
|
649 |
+
}
|
650 |
+
}
|
651 |
+
|
652 |
+
return false;
|
653 |
+
}
|
654 |
+
|
655 |
+
}
|
apps/Backend/Modules/Jobs/Multisite/Files.php
CHANGED
@@ -1,365 +1,384 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPStaging\Backend\Modules\Jobs\Multisite;
|
4 |
-
|
5 |
-
use WPStaging\Backend\Modules\Jobs\JobExecutable;
|
6 |
-
// No Direct Access
|
7 |
-
use WPStaging\Utils\Logger;
|
8 |
-
|
9 |
-
if( !defined( "WPINC" ) ) {
|
10 |
-
die;
|
11 |
-
}
|
12 |
-
|
13 |
-
/**
|
14 |
-
* Class Files
|
15 |
-
* @package WPStaging\Backend\Modules\Jobs
|
16 |
-
*/
|
17 |
-
class Files extends JobExecutable {
|
18 |
-
|
19 |
-
/**
|
20 |
-
* @var \SplFileObject
|
21 |
-
*/
|
22 |
-
private $file;
|
23 |
-
|
24 |
-
/**
|
25 |
-
* @var int
|
26 |
-
*/
|
27 |
-
private $maxFilesPerRun;
|
28 |
-
|
29 |
-
/**
|
30 |
-
* @var string
|
31 |
-
*/
|
32 |
-
private $destination;
|
33 |
-
|
34 |
-
/**
|
35 |
-
* Initialization
|
36 |
-
*/
|
37 |
-
public function initialize() {
|
38 |
-
|
39 |
-
$this->destination = \WPStaging\WPStaging::getWPpath() . $this->options->cloneDirectoryName . DIRECTORY_SEPARATOR;
|
40 |
-
|
41 |
-
$filePath = $this->cache->getCacheDir() . "files_to_copy." . $this->cache->getCacheExtension();
|
42 |
-
|
43 |
-
if( is_file( $filePath ) ) {
|
44 |
-
$this->file = new \SplFileObject( $filePath, 'r' );
|
45 |
-
}
|
46 |
-
|
47 |
-
// Informational logs
|
48 |
-
if( 0 == $this->options->currentStep ) {
|
49 |
-
$this->log( "Copying files..." );
|
50 |
-
}
|
51 |
-
|
52 |
-
$this->settings->batchSize = $this->settings->batchSize * 1000000;
|
53 |
-
$this->maxFilesPerRun = $this->settings->fileLimit;
|
54 |
-
}
|
55 |
-
|
56 |
-
/**
|
57 |
-
* Calculate Total Steps in This Job and Assign It to $this->options->totalSteps
|
58 |
-
* @return void
|
59 |
-
*/
|
60 |
-
protected function calculateTotalSteps() {
|
61 |
-
$this->options->totalSteps = ceil( $this->options->totalFiles / $this->maxFilesPerRun );
|
62 |
-
}
|
63 |
-
|
64 |
-
/**
|
65 |
-
* Execute the Current Step
|
66 |
-
* Returns false when over threshold limits are hit or when the job is done, true otherwise
|
67 |
-
* @return bool
|
68 |
-
*/
|
69 |
-
protected function execute() {
|
70 |
-
// Finished
|
71 |
-
if( $this->isFinished() ) {
|
72 |
-
$this->log( "Copying files finished" );
|
73 |
-
$this->prepareResponse( true, false );
|
74 |
-
return false;
|
75 |
-
}
|
76 |
-
|
77 |
-
// Get files and copy'em
|
78 |
-
if( !$this->getFilesAndCopy() ) {
|
79 |
-
$this->prepareResponse( false, false );
|
80 |
-
return false;
|
81 |
-
}
|
82 |
-
|
83 |
-
// Prepare and return response
|
84 |
-
$this->prepareResponse();
|
85 |
-
|
86 |
-
// Not finished
|
87 |
-
return true;
|
88 |
-
}
|
89 |
-
|
90 |
-
/**
|
91 |
-
* Get files and copy
|
92 |
-
* @return bool
|
93 |
-
*/
|
94 |
-
private function getFilesAndCopy() {
|
95 |
-
// Over limits threshold
|
96 |
-
if( $this->isOverThreshold() ) {
|
97 |
-
// Prepare response and save current progress
|
98 |
-
$this->prepareResponse( false, false );
|
99 |
-
$this->saveOptions();
|
100 |
-
return false;
|
101 |
-
}
|
102 |
-
|
103 |
-
// Go to last copied line and than to next one
|
104 |
-
//if ($this->options->copiedFiles != 0) {
|
105 |
-
if( isset( $this->options->copiedFiles ) && $this->options->copiedFiles != 0 ) {
|
106 |
-
$this->file->seek( $this->options->copiedFiles - 1 );
|
107 |
-
}
|
108 |
-
|
109 |
-
$this->file->setFlags( \SplFileObject::SKIP_EMPTY | \SplFileObject::READ_AHEAD );
|
110 |
-
|
111 |
-
|
112 |
-
// Loop x files at a time
|
113 |
-
for ( $i = 0; $i < $this->maxFilesPerRun; $i++ ) {
|
114 |
-
|
115 |
-
// Increment copied files
|
116 |
-
// Do this anytime to make sure to not stuck in the same step / files
|
117 |
-
$this->options->copiedFiles++;
|
118 |
-
|
119 |
-
// End of file
|
120 |
-
if( $this->file->eof() ) {
|
121 |
-
break;
|
122 |
-
}
|
123 |
-
|
124 |
-
|
125 |
-
$file = $this->file->fgets();
|
126 |
-
|
127 |
-
$this->copyFile( $file );
|
128 |
-
}
|
129 |
-
|
130 |
-
$totalFiles = $this->options->copiedFiles;
|
131 |
-
// Log this only every 50 entries to keep the log small and to not block the rendering browser
|
132 |
-
if( $this->options->copiedFiles % 50 == 0 ) {
|
133 |
-
$this->log( "Total {$totalFiles} files processed" );
|
134 |
-
}
|
135 |
-
|
136 |
-
return true;
|
137 |
-
}
|
138 |
-
|
139 |
-
/**
|
140 |
-
* Checks Whether There is Any Job to Execute or Not
|
141 |
-
* @return bool
|
142 |
-
*/
|
143 |
-
private function isFinished() {
|
144 |
-
return (
|
145 |
-
$this->options->currentStep > $this->options->totalSteps ||
|
146 |
-
$this->options->copiedFiles >= $this->options->totalFiles
|
147 |
-
);
|
148 |
-
}
|
149 |
-
|
150 |
-
/**
|
151 |
-
* @param string $file
|
152 |
-
* @return bool
|
153 |
-
*/
|
154 |
-
private function copyFile( $file ) {
|
155 |
-
$file = trim( \WPStaging\WPStaging::getWPpath() . $file );
|
156 |
-
|
157 |
-
$directory = dirname( $file );
|
158 |
-
|
159 |
-
// Get file size
|
160 |
-
$fileSize = filesize( $file );
|
161 |
-
|
162 |
-
// Directory is excluded
|
163 |
-
if( $this->isDirectoryExcluded( $directory ) ) {
|
164 |
-
$this->debugLog( "Skipping directory by rule: {$file}", Logger::TYPE_INFO );
|
165 |
-
return false;
|
166 |
-
}
|
167 |
-
|
168 |
-
// File is excluded
|
169 |
-
if( $this->isFileExcluded( $file ) ) {
|
170 |
-
$this->
|
171 |
-
return false;
|
172 |
-
}
|
173 |
-
|
174 |
-
// File is
|
175 |
-
if( $
|
176 |
-
$this->
|
177 |
-
return false;
|
178 |
-
}
|
179 |
-
|
180 |
-
//
|
181 |
-
if(
|
182 |
-
$this->log( "
|
183 |
-
return
|
184 |
-
}
|
185 |
-
|
186 |
-
//
|
187 |
-
if(
|
188 |
-
$this->log( "Can't
|
189 |
-
return
|
190 |
-
}
|
191 |
-
|
192 |
-
//
|
193 |
-
if( $
|
194 |
-
$this->log( "
|
195 |
-
return
|
196 |
-
}
|
197 |
-
|
198 |
-
//
|
199 |
-
if(
|
200 |
-
$
|
201 |
-
$this->
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
$
|
250 |
-
$
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
// Try
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
*
|
319 |
-
*
|
320 |
-
* @
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPStaging\Backend\Modules\Jobs\Multisite;
|
4 |
+
|
5 |
+
use WPStaging\Backend\Modules\Jobs\JobExecutable;
|
6 |
+
// No Direct Access
|
7 |
+
use WPStaging\Utils\Logger;
|
8 |
+
|
9 |
+
if( !defined( "WPINC" ) ) {
|
10 |
+
die;
|
11 |
+
}
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Class Files
|
15 |
+
* @package WPStaging\Backend\Modules\Jobs
|
16 |
+
*/
|
17 |
+
class Files extends JobExecutable {
|
18 |
+
|
19 |
+
/**
|
20 |
+
* @var \SplFileObject
|
21 |
+
*/
|
22 |
+
private $file;
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @var int
|
26 |
+
*/
|
27 |
+
private $maxFilesPerRun;
|
28 |
+
|
29 |
+
/**
|
30 |
+
* @var string
|
31 |
+
*/
|
32 |
+
private $destination;
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Initialization
|
36 |
+
*/
|
37 |
+
public function initialize() {
|
38 |
+
|
39 |
+
$this->destination = \WPStaging\WPStaging::getWPpath() . $this->options->cloneDirectoryName . DIRECTORY_SEPARATOR;
|
40 |
+
|
41 |
+
$filePath = $this->cache->getCacheDir() . "files_to_copy." . $this->cache->getCacheExtension();
|
42 |
+
|
43 |
+
if( is_file( $filePath ) ) {
|
44 |
+
$this->file = new \SplFileObject( $filePath, 'r' );
|
45 |
+
}
|
46 |
+
|
47 |
+
// Informational logs
|
48 |
+
if( 0 == $this->options->currentStep ) {
|
49 |
+
$this->log( "Copying files..." );
|
50 |
+
}
|
51 |
+
|
52 |
+
$this->settings->batchSize = $this->settings->batchSize * 1000000;
|
53 |
+
$this->maxFilesPerRun = $this->settings->fileLimit;
|
54 |
+
}
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Calculate Total Steps in This Job and Assign It to $this->options->totalSteps
|
58 |
+
* @return void
|
59 |
+
*/
|
60 |
+
protected function calculateTotalSteps() {
|
61 |
+
$this->options->totalSteps = ceil( $this->options->totalFiles / $this->maxFilesPerRun );
|
62 |
+
}
|
63 |
+
|
64 |
+
/**
|
65 |
+
* Execute the Current Step
|
66 |
+
* Returns false when over threshold limits are hit or when the job is done, true otherwise
|
67 |
+
* @return bool
|
68 |
+
*/
|
69 |
+
protected function execute() {
|
70 |
+
// Finished
|
71 |
+
if( $this->isFinished() ) {
|
72 |
+
$this->log( "Copying files finished" );
|
73 |
+
$this->prepareResponse( true, false );
|
74 |
+
return false;
|
75 |
+
}
|
76 |
+
|
77 |
+
// Get files and copy'em
|
78 |
+
if( !$this->getFilesAndCopy() ) {
|
79 |
+
$this->prepareResponse( false, false );
|
80 |
+
return false;
|
81 |
+
}
|
82 |
+
|
83 |
+
// Prepare and return response
|
84 |
+
$this->prepareResponse();
|
85 |
+
|
86 |
+
// Not finished
|
87 |
+
return true;
|
88 |
+
}
|
89 |
+
|
90 |
+
/**
|
91 |
+
* Get files and copy
|
92 |
+
* @return bool
|
93 |
+
*/
|
94 |
+
private function getFilesAndCopy() {
|
95 |
+
// Over limits threshold
|
96 |
+
if( $this->isOverThreshold() ) {
|
97 |
+
// Prepare response and save current progress
|
98 |
+
$this->prepareResponse( false, false );
|
99 |
+
$this->saveOptions();
|
100 |
+
return false;
|
101 |
+
}
|
102 |
+
|
103 |
+
// Go to last copied line and than to next one
|
104 |
+
//if ($this->options->copiedFiles != 0) {
|
105 |
+
if( isset( $this->options->copiedFiles ) && $this->options->copiedFiles != 0 ) {
|
106 |
+
$this->file->seek( $this->options->copiedFiles - 1 );
|
107 |
+
}
|
108 |
+
|
109 |
+
$this->file->setFlags( \SplFileObject::SKIP_EMPTY | \SplFileObject::READ_AHEAD );
|
110 |
+
|
111 |
+
|
112 |
+
// Loop x files at a time
|
113 |
+
for ( $i = 0; $i < $this->maxFilesPerRun; $i++ ) {
|
114 |
+
|
115 |
+
// Increment copied files
|
116 |
+
// Do this anytime to make sure to not stuck in the same step / files
|
117 |
+
$this->options->copiedFiles++;
|
118 |
+
|
119 |
+
// End of file
|
120 |
+
if( $this->file->eof() ) {
|
121 |
+
break;
|
122 |
+
}
|
123 |
+
|
124 |
+
|
125 |
+
$file = $this->file->fgets();
|
126 |
+
|
127 |
+
$this->copyFile( $file );
|
128 |
+
}
|
129 |
+
|
130 |
+
$totalFiles = $this->options->copiedFiles;
|
131 |
+
// Log this only every 50 entries to keep the log small and to not block the rendering browser
|
132 |
+
if( $this->options->copiedFiles % 50 == 0 ) {
|
133 |
+
$this->log( "Total {$totalFiles} files processed" );
|
134 |
+
}
|
135 |
+
|
136 |
+
return true;
|
137 |
+
}
|
138 |
+
|
139 |
+
/**
|
140 |
+
* Checks Whether There is Any Job to Execute or Not
|
141 |
+
* @return bool
|
142 |
+
*/
|
143 |
+
private function isFinished() {
|
144 |
+
return (
|
145 |
+
$this->options->currentStep > $this->options->totalSteps ||
|
146 |
+
$this->options->copiedFiles >= $this->options->totalFiles
|
147 |
+
);
|
148 |
+
}
|
149 |
+
|
150 |
+
/**
|
151 |
+
* @param string $file
|
152 |
+
* @return bool
|
153 |
+
*/
|
154 |
+
private function copyFile( $file ) {
|
155 |
+
$file = trim( \WPStaging\WPStaging::getWPpath() . $file );
|
156 |
+
|
157 |
+
$directory = dirname( $file );
|
158 |
+
|
159 |
+
// Get file size
|
160 |
+
$fileSize = filesize( $file );
|
161 |
+
|
162 |
+
// Directory is excluded
|
163 |
+
if( $this->isDirectoryExcluded( $directory ) ) {
|
164 |
+
$this->debugLog( "Skipping directory by rule: {$file}", Logger::TYPE_INFO );
|
165 |
+
return false;
|
166 |
+
}
|
167 |
+
|
168 |
+
// File is excluded
|
169 |
+
if( $this->isFileExcluded( $file ) ) {
|
170 |
+
$this->debugLog( "File Excluded: {$file}", Logger::TYPE_INFO );
|
171 |
+
return false;
|
172 |
+
}
|
173 |
+
|
174 |
+
// Path + File is excluded
|
175 |
+
if( $this->isFileExcludedFullPath( $file ) ) {
|
176 |
+
$this->debugLog( "File Excluded Full Path: {$file}", Logger::TYPE_INFO );
|
177 |
+
return false;
|
178 |
+
}
|
179 |
+
|
180 |
+
// File is over maximum allowed file size (8MB)
|
181 |
+
if( $fileSize >= $this->settings->maxFileSize * 1000000 ) {
|
182 |
+
$this->log( "Skipping big file: {$file}", Logger::TYPE_INFO );
|
183 |
+
return false;
|
184 |
+
}
|
185 |
+
|
186 |
+
// Invalid file, skipping it as if succeeded
|
187 |
+
if( !is_file( $file ) || !is_readable( $file ) ) {
|
188 |
+
$this->log( "Can't read file or file doesn't exist {$file}" );
|
189 |
+
return true;
|
190 |
+
}
|
191 |
+
|
192 |
+
// Failed to get destination
|
193 |
+
if( false === ($destination = $this->getDestination( $file )) ) {
|
194 |
+
$this->log( "Can't get the destination of {$file}" );
|
195 |
+
return false;
|
196 |
+
}
|
197 |
+
|
198 |
+
// File is over batch size
|
199 |
+
if( $fileSize >= $this->settings->batchSize ) {
|
200 |
+
$this->log( "Trying to copy big file: {$file} -> {$destination}", Logger::TYPE_INFO );
|
201 |
+
return $this->copyBig( $file, $destination, $this->settings->batchSize );
|
202 |
+
}
|
203 |
+
|
204 |
+
// Attempt to copy
|
205 |
+
if( !@copy( $file, $destination ) ) {
|
206 |
+
$errors = error_get_last();
|
207 |
+
$this->log( "Files: Failed to copy file to destination. Error: {$errors['message']} {$file} -> {$destination}", Logger::TYPE_ERROR );
|
208 |
+
return false;
|
209 |
+
}
|
210 |
+
|
211 |
+
return true;
|
212 |
+
|
213 |
+
// Good old PHP
|
214 |
+
//return $this->copy($file, $destination);
|
215 |
+
}
|
216 |
+
|
217 |
+
/**
|
218 |
+
* Gets destination file and checks if the directory exists, if it does not attempts to create it.
|
219 |
+
* If creating destination directory fails, it returns false, gives destination full path otherwise
|
220 |
+
* @param string $file
|
221 |
+
* @return bool|string
|
222 |
+
*/
|
223 |
+
private function getDestination( $file ) {
|
224 |
+
$file = $this->getMultisiteUploadFolder( $file );
|
225 |
+
$relativePath = str_replace( \WPStaging\WPStaging::getWPpath(), null, $file );
|
226 |
+
$destinationPath = $this->destination . $relativePath;
|
227 |
+
$destinationDirectory = dirname( $destinationPath );
|
228 |
+
|
229 |
+
if( !is_dir( $destinationDirectory ) && !@mkdir( $destinationDirectory, 0755, true ) ) {
|
230 |
+
$this->log( "Files: Can not create directory {$destinationDirectory}", Logger::TYPE_ERROR );
|
231 |
+
return false;
|
232 |
+
}
|
233 |
+
|
234 |
+
return $destinationPath;
|
235 |
+
}
|
236 |
+
|
237 |
+
/**
|
238 |
+
* Replace relative path of file if its located in multisite upload folder
|
239 |
+
* wp-content/uploads/sites/SITEID or old wordpress structure wp-content/blogs.dir/SITEID/files
|
240 |
+
* @return boolean
|
241 |
+
*/
|
242 |
+
private function getMultisiteUploadFolder( $file ) {
|
243 |
+
// Check first which method is used
|
244 |
+
$uploads = wp_upload_dir();
|
245 |
+
$basedir = $uploads['basedir'];
|
246 |
+
|
247 |
+
if( false === strpos( $basedir, 'blogs.dir' ) ) {
|
248 |
+
// Since WP 3.5
|
249 |
+
$search = 'wp-content' . DIRECTORY_SEPARATOR . 'uploads' . DIRECTORY_SEPARATOR . 'sites' . DIRECTORY_SEPARATOR . get_current_blog_id();
|
250 |
+
$replace = 'wp-content' . DIRECTORY_SEPARATOR . 'uploads';
|
251 |
+
$uploadsFolder = str_replace( $search, $replace, $file );
|
252 |
+
} else {
|
253 |
+
// old blog structure
|
254 |
+
$search = 'wp-content' . DIRECTORY_SEPARATOR . 'blogs.dir' . DIRECTORY_SEPARATOR . get_current_blog_id() . DIRECTORY_SEPARATOR . 'files';
|
255 |
+
$replace = 'wp-content' . DIRECTORY_SEPARATOR . 'uploads';
|
256 |
+
$uploadsFolder = str_replace( $search, $replace, $file );
|
257 |
+
}
|
258 |
+
|
259 |
+
return $uploadsFolder;
|
260 |
+
}
|
261 |
+
|
262 |
+
/**
|
263 |
+
* Copy bigger files than $this->settings->batchSize
|
264 |
+
* @param string $src
|
265 |
+
* @param string $dst
|
266 |
+
* @param int $buffersize
|
267 |
+
* @return boolean
|
268 |
+
*/
|
269 |
+
private function copyBig( $src, $dst, $buffersize ) {
|
270 |
+
$src = fopen( $src, 'r' );
|
271 |
+
$dest = fopen( $dst, 'w' );
|
272 |
+
|
273 |
+
// Try first method:
|
274 |
+
while ( !feof( $src ) ) {
|
275 |
+
if( false === fwrite( $dest, fread( $src, $buffersize ) ) ) {
|
276 |
+
$error = true;
|
277 |
+
}
|
278 |
+
}
|
279 |
+
// Try second method if first one failed
|
280 |
+
if( isset( $error ) && ($error === true) ) {
|
281 |
+
while ( !feof( $src ) ) {
|
282 |
+
if( false === stream_copy_to_stream( $src, $dest, 1024 ) ) {
|
283 |
+
$this->log( "Can not copy big file; {$src} -> {$dest}" );
|
284 |
+
fclose( $src );
|
285 |
+
fclose( $dest );
|
286 |
+
return false;
|
287 |
+
}
|
288 |
+
}
|
289 |
+
}
|
290 |
+
// Close any open handler
|
291 |
+
fclose( $src );
|
292 |
+
fclose( $dest );
|
293 |
+
return true;
|
294 |
+
}
|
295 |
+
|
296 |
+
/**
|
297 |
+
* Check if file is excluded from copying process
|
298 |
+
*
|
299 |
+
* @param string $file filename including ending
|
300 |
+
* @return boolean
|
301 |
+
*/
|
302 |
+
private function isFileExcluded( $file ) {
|
303 |
+
|
304 |
+
if( in_array( basename( $file ), $this->options->excludedFiles ) ) {
|
305 |
+
return true;
|
306 |
+
}
|
307 |
+
// Do not copy wp-config.php if the clone gets updated. This is for security purposes,
|
308 |
+
// because if the updating process fails, the staging site is not accessable any longer
|
309 |
+
if( isset( $this->options->mainJob ) && $this->options->mainJob == "updating" && stripos( strrev( $file ), strrev( "wp-config.php" ) ) === 0 ) {
|
310 |
+
return true;
|
311 |
+
}
|
312 |
+
|
313 |
+
|
314 |
+
return false;
|
315 |
+
}
|
316 |
+
|
317 |
+
/**
|
318 |
+
* Check if certain file is excluded from copying process
|
319 |
+
*
|
320 |
+
* @param string $file filename including ending + (part) path e.g wp-content/db.php
|
321 |
+
* @return boolean
|
322 |
+
*/
|
323 |
+
private function isFileExcludedFullPath( $file ) {
|
324 |
+
// If path + file exists
|
325 |
+
foreach ( $this->options->excludedFilesFullPath as $excludedFile ) {
|
326 |
+
if( false !== strpos( $file, $excludedFile ) ) {
|
327 |
+
return true;
|
328 |
+
}
|
329 |
+
}
|
330 |
+
|
331 |
+
return false;
|
332 |
+
}
|
333 |
+
|
334 |
+
/**
|
335 |
+
* Replace forward slash with current directory separator
|
336 |
+
* Windows Compatibility Fix
|
337 |
+
* @param string $path Path
|
338 |
+
*
|
339 |
+
* @return string
|
340 |
+
*/
|
341 |
+
private function sanitizeDirectorySeparator( $path ) {
|
342 |
+
$string = str_replace( "/", "\\", $path );
|
343 |
+
return str_replace( '\\\\', '\\', $string );
|
344 |
+
}
|
345 |
+
|
346 |
+
/**
|
347 |
+
* Check if directory is excluded from copying
|
348 |
+
* @param string $directory
|
349 |
+
* @return bool
|
350 |
+
*/
|
351 |
+
private function isDirectoryExcluded( $directory ) {
|
352 |
+
// Make sure that wp-staging-pro directory / plugin is never excluded
|
353 |
+
if( false !== strpos( $directory, 'wp-staging' ) || false !== strpos( $directory, 'wp-staging-pro' ) ) {
|
354 |
+
return false;
|
355 |
+
}
|
356 |
+
|
357 |
+
$directory = $this->sanitizeDirectorySeparator( $directory );
|
358 |
+
|
359 |
+
foreach ( $this->options->excludedDirectories as $excludedDirectory ) {
|
360 |
+
$excludedDirectory = $this->sanitizeDirectorySeparator( $excludedDirectory );
|
361 |
+
if( strpos( $directory, $excludedDirectory ) === 0 && !$this->isExtraDirectory( $directory ) ) {
|
362 |
+
return true;
|
363 |
+
}
|
364 |
+
}
|
365 |
+
|
366 |
+
return false;
|
367 |
+
}
|
368 |
+
|
369 |
+
/**
|
370 |
+
* Check if directory is an extra directory and should be copied
|
371 |
+
* @param string $directory
|
372 |
+
* @return boolean
|
373 |
+
*/
|
374 |
+
private function isExtraDirectory( $directory ) {
|
375 |
+
foreach ( $this->options->extraDirectories as $extraDirectory ) {
|
376 |
+
if( strpos( $directory, $extraDirectory ) === 0 ) {
|
377 |
+
return true;
|
378 |
+
}
|
379 |
+
}
|
380 |
+
|
381 |
+
return false;
|
382 |
+
}
|
383 |
+
|
384 |
+
}
|
apps/Backend/Modules/Jobs/Multisite/Finish.php
CHANGED
@@ -1,116 +1,116 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WPStaging\Backend\Modules\Jobs\Multisite;
|
3 |
-
|
4 |
-
use WPStaging\WPStaging;
|
5 |
-
use WPStaging\Backend\Modules\Jobs\Job;
|
6 |
-
use WPStaging\Utils\Multisite;
|
7 |
-
|
8 |
-
//error_reporting( E_ALL );
|
9 |
-
|
10 |
-
/**
|
11 |
-
* Class Finish
|
12 |
-
* @package WPStaging\Backend\Modules\Jobs
|
13 |
-
*/
|
14 |
-
class Finish extends Job
|
15 |
-
{
|
16 |
-
/**
|
17 |
-
* Clone Key
|
18 |
-
* @var string
|
19 |
-
*/
|
20 |
-
private $clone = '';
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
/**
|
25 |
-
* Start Module
|
26 |
-
* @return object
|
27 |
-
*/
|
28 |
-
public function start()
|
29 |
-
{
|
30 |
-
// sanitize the clone name before saving
|
31 |
-
$this->clone = preg_replace("#\W+#", '-', strtolower($this->options->clone));
|
32 |
-
|
33 |
-
// Delete Cache Files
|
34 |
-
$this->deleteCacheFiles();
|
35 |
-
|
36 |
-
// Prepare clone records & save scanned directories for delete job later
|
37 |
-
$this->prepareCloneDataRecords();
|
38 |
-
|
39 |
-
$multisite = new Multisite;
|
40 |
-
|
41 |
-
$return = array(
|
42 |
-
"directoryName" => $this->options->cloneDirectoryName,
|
43 |
-
"path" => ABSPATH . $this->options->cloneDirectoryName,
|
44 |
-
"url" => $this->multisiteHomeDomain . '/' . $this->options->cloneDirectoryName,
|
45 |
-
//"url" => $this->multisiteUrl . '/' . $this->options->cloneDirectoryName,
|
46 |
-
"number" => $this->options->cloneNumber,
|
47 |
-
"version" => \WPStaging\WPStaging::VERSION,
|
48 |
-
"status" => 'finished',
|
49 |
-
"prefix" => $this->options->prefix,
|
50 |
-
"last_msg" => $this->logger->getLastLogMsg(),
|
51 |
-
"job" => $this->options->currentJob,
|
52 |
-
"percentage" => 100
|
53 |
-
|
54 |
-
);
|
55 |
-
|
56 |
-
//$this->flush();
|
57 |
-
|
58 |
-
return (object) $return;
|
59 |
-
}
|
60 |
-
|
61 |
-
/**
|
62 |
-
* Delete Cache Files
|
63 |
-
*/
|
64 |
-
protected function deleteCacheFiles()
|
65 |
-
{
|
66 |
-
$this->log("Finish: Deleting clone job's cache files...");
|
67 |
-
|
68 |
-
// Clean cache files
|
69 |
-
$this->cache->delete("clone_options");
|
70 |
-
$this->cache->delete("files_to_copy");
|
71 |
-
|
72 |
-
$this->log("Finish: Clone job's cache files have been deleted!");
|
73 |
-
}
|
74 |
-
|
75 |
-
/**
|
76 |
-
* Prepare clone records
|
77 |
-
* @return bool
|
78 |
-
*/
|
79 |
-
protected function prepareCloneDataRecords()
|
80 |
-
{
|
81 |
-
// Check if clones still exist
|
82 |
-
$this->log("Finish: Verifying existing clones...");
|
83 |
-
|
84 |
-
// Clone data already exists
|
85 |
-
if (isset($this->options->existingClones[$this->options->clone]))
|
86 |
-
{
|
87 |
-
$this->log("Finish: Clone data already exists, no need to update, the job finished");
|
88 |
-
return true;
|
89 |
-
}
|
90 |
-
|
91 |
-
// Save new clone data
|
92 |
-
$this->log("Finish: {$this->options->clone}'s clone job's data is not in database, generating data");
|
93 |
-
|
94 |
-
// sanitize the clone name before saving
|
95 |
-
//$clone = preg_replace("#\W+#", '-', strtolower($this->options->clone));
|
96 |
-
|
97 |
-
$this->options->existingClones[$this->clone] = array(
|
98 |
-
"directoryName" => $this->options->cloneDirectoryName,
|
99 |
-
"path" => ABSPATH . $this->options->cloneDirectoryName,
|
100 |
-
//"url" => get_site_url() . '/' . $this->options->cloneDirectoryName,
|
101 |
-
"url" => $this->multisiteHomeDomain . '/' . $this->options->cloneDirectoryName,
|
102 |
-
"number" => $this->options->cloneNumber,
|
103 |
-
"version" => \WPStaging\WPStaging::VERSION,
|
104 |
-
"status" => false,
|
105 |
-
"prefix" => $this->options->prefix,
|
106 |
-
);
|
107 |
-
|
108 |
-
if (false === update_option("wpstg_existing_clones_beta", $this->options->existingClones))
|
109 |
-
{
|
110 |
-
$this->log("Finish: Failed to save {$this->options->clone}'s clone job data to database'");
|
111 |
-
return false;
|
112 |
-
}
|
113 |
-
|
114 |
-
return true;
|
115 |
-
}
|
116 |
}
|
1 |
+
<?php
|
2 |
+
namespace WPStaging\Backend\Modules\Jobs\Multisite;
|
3 |
+
|
4 |
+
use WPStaging\WPStaging;
|
5 |
+
use WPStaging\Backend\Modules\Jobs\Job;
|
6 |
+
use WPStaging\Utils\Multisite;
|
7 |
+
|
8 |
+
//error_reporting( E_ALL );
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Class Finish
|
12 |
+
* @package WPStaging\Backend\Modules\Jobs
|
13 |
+
*/
|
14 |
+
class Finish extends Job
|
15 |
+
{
|
16 |
+
/**
|
17 |
+
* Clone Key
|
18 |
+
* @var string
|
19 |
+
*/
|
20 |
+
private $clone = '';
|
21 |
+
|
22 |
+
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Start Module
|
26 |
+
* @return object
|
27 |
+
*/
|
28 |
+
public function start()
|
29 |
+
{
|
30 |
+
// sanitize the clone name before saving
|
31 |
+
$this->clone = preg_replace("#\W+#", '-', strtolower($this->options->clone));
|
32 |
+
|
33 |
+
// Delete Cache Files
|
34 |
+
$this->deleteCacheFiles();
|
35 |
+
|
36 |
+
// Prepare clone records & save scanned directories for delete job later
|
37 |
+
$this->prepareCloneDataRecords();
|
38 |
+
|
39 |
+
$multisite = new Multisite;
|
40 |
+
|
41 |
+
$return = array(
|
42 |
+
"directoryName" => $this->options->cloneDirectoryName,
|
43 |
+
"path" => ABSPATH . $this->options->cloneDirectoryName,
|
44 |
+
"url" => $this->multisiteHomeDomain . '/' . $this->options->cloneDirectoryName,
|
45 |
+
//"url" => $this->multisiteUrl . '/' . $this->options->cloneDirectoryName,
|
46 |
+
"number" => $this->options->cloneNumber,
|
47 |
+
"version" => \WPStaging\WPStaging::VERSION,
|
48 |
+
"status" => 'finished',
|
49 |
+
"prefix" => $this->options->prefix,
|
50 |
+
"last_msg" => $this->logger->getLastLogMsg(),
|
51 |
+
"job" => $this->options->currentJob,
|
52 |
+
"percentage" => 100
|
53 |
+
|
54 |
+
);
|
55 |
+
|
56 |
+
//$this->flush();
|
57 |
+
|
58 |
+
return (object) $return;
|
59 |
+
}
|
60 |
+
|
61 |
+
/**
|
62 |
+
* Delete Cache Files
|
63 |
+
*/
|
64 |
+
protected function deleteCacheFiles()
|
65 |
+
{
|
66 |
+
$this->log("Finish: Deleting clone job's cache files...");
|
67 |
+
|
68 |
+
// Clean cache files
|
69 |
+
$this->cache->delete("clone_options");
|
70 |
+
$this->cache->delete("files_to_copy");
|
71 |
+
|
72 |
+
$this->log("Finish: Clone job's cache files have been deleted!");
|
73 |
+
}
|
74 |
+
|
75 |
+
/**
|
76 |
+
* Prepare clone records
|
77 |
+
* @return bool
|
78 |
+
*/
|
79 |
+
protected function prepareCloneDataRecords()
|
80 |
+
{
|
81 |
+
// Check if clones still exist
|
82 |
+
$this->log("Finish: Verifying existing clones...");
|
83 |
+
|
84 |
+
// Clone data already exists
|
85 |
+
if (isset($this->options->existingClones[$this->options->clone]))
|
86 |
+
{
|
87 |
+
$this->log("Finish: Clone data already exists, no need to update, the job finished");
|
88 |
+
return true;
|
89 |
+
}
|
90 |
+
|
91 |
+
// Save new clone data
|
92 |
+
$this->log("Finish: {$this->options->clone}'s clone job's data is not in database, generating data");
|
93 |
+
|
94 |
+
// sanitize the clone name before saving
|
95 |
+
//$clone = preg_replace("#\W+#", '-', strtolower($this->options->clone));
|
96 |
+
|
97 |
+
$this->options->existingClones[$this->clone] = array(
|
98 |
+
"directoryName" => $this->options->cloneDirectoryName,
|
99 |
+
"path" => ABSPATH . $this->options->cloneDirectoryName,
|
100 |
+
//"url" => get_site_url() . '/' . $this->options->cloneDirectoryName,
|
101 |
+
"url" => $this->multisiteHomeDomain . '/' . $this->options->cloneDirectoryName,
|
102 |
+
"number" => $this->options->cloneNumber,
|
103 |
+
"version" => \WPStaging\WPStaging::VERSION,
|
104 |
+
"status" => false,
|
105 |
+
"prefix" => $this->options->prefix,
|
106 |
+
);
|
107 |
+
|
108 |
+
if (false === update_option("wpstg_existing_clones_beta", $this->options->existingClones))
|
109 |
+
{
|
110 |
+
$this->log("Finish: Failed to save {$this->options->clone}'s clone job data to database'");
|
111 |
+
return false;
|
112 |
+
}
|
113 |
+
|
114 |
+
return true;
|
115 |
+
}
|
116 |
}
|
apps/Backend/Modules/Jobs/Multisite/SearchReplace.php
CHANGED
@@ -1,772 +1,776 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPStaging\Backend\Modules\Jobs\Multisite;
|
4 |
-
|
5 |
-
// No Direct Access
|
6 |
-
if( !defined( "WPINC" ) ) {
|
7 |
-
die;
|
8 |
-
}
|
9 |
-
|
10 |
-
use WPStaging\WPStaging;
|
11 |
-
use WPStaging\Utils\Strings;
|
12 |
-
use WPStaging\Utils\Helper;
|
13 |
-
use WPStaging\Utils\Multisite;
|
14 |
-
use WPStaging\Backend\Modules\Jobs\JobExecutable;
|
15 |
-
|
16 |
-
/**
|
17 |
-
* Class Database
|
18 |
-
* @package WPStaging\Backend\Modules\Jobs
|
19 |
-
*/
|
20 |
-
class SearchReplace extends JobExecutable {
|
21 |
-
|
22 |
-
/**
|
23 |
-
* @var int
|
24 |
-
*/
|
25 |
-
private $total = 0;
|
26 |
-
|
27 |
-
/**
|
28 |
-
* @var \WPDB
|
29 |
-
*/
|
30 |
-
public $db;
|
31 |
-
|
32 |
-
/**
|
33 |
-
* The prefix of the new database tables which are used for the live site after updating tables
|
34 |
-
* @var string
|
35 |
-
*/
|
36 |
-
public $tmpPrefix;
|
37 |
-
|
38 |
-
/**
|
39 |
-
* Initialize
|
40 |
-
*/
|
41 |
-
public function initialize() {
|
42 |
-
$this->total = count( $this->options->tables );
|
43 |
-
$this->db = WPStaging::getInstance()->get( "wpdb" );
|
44 |
-
$this->tmpPrefix = $this->options->prefix;
|
45 |
-
}
|
46 |
-
|
47 |
-
public function start() {
|
48 |
-
// Skip job. Nothing to do
|
49 |
-
if( $this->options->totalSteps === 0 ) {
|
50 |
-
$this->prepareResponse( true, false );
|
51 |
-
}
|
52 |
-
|
53 |
-
$this->run();
|
54 |
-
|
55 |
-
// Save option, progress
|
56 |
-
$this->saveOptions();
|
57 |
-
|
58 |
-
return ( object ) $this->response;
|
59 |
-
}
|
60 |
-
|
61 |
-
/**
|
62 |
-
* Calculate Total Steps in This Job and Assign It to $this->options->totalSteps
|
63 |
-
* @return void
|
64 |
-
*/
|
65 |
-
protected function calculateTotalSteps() {
|
66 |
-
$this->options->totalSteps = $this->total;
|
67 |
-
}
|
68 |
-
|
69 |
-
/**
|
70 |
-
* Execute the Current Step
|
71 |
-
* Returns false when over threshold limits are hit or when the job is done, true otherwise
|
72 |
-
* @return bool
|
73 |
-
*/
|
74 |
-
protected function execute() {
|
75 |
-
// Over limits threshold
|
76 |
-
if( $this->isOverThreshold() ) {
|
77 |
-
// Prepare response and save current progress
|
78 |
-
$this->prepareResponse( false, false );
|
79 |
-
$this->saveOptions();
|
80 |
-
return false;
|
81 |
-
}
|
82 |
-
|
83 |
-
// No more steps, finished
|
84 |
-
if( $this->options->currentStep > $this->total || !isset( $this->options->tables[$this->options->currentStep] ) ) {
|
85 |
-
$this->prepareResponse( true, false );
|
86 |
-
return false;
|
87 |
-
}
|
88 |
-
|
89 |
-
// Table is excluded
|
90 |
-
if( in_array( $this->options->tables[$this->options->currentStep], $this->options->excludedTables ) ) {
|
91 |
-
$this->prepareResponse();
|
92 |
-
return true;
|
93 |
-
}
|
94 |
-
|
95 |
-
// Search & Replace
|
96 |
-
if( !$this->stopExecution() && !$this->updateTable( $this->options->tables[$this->options->currentStep] ) ) {
|
97 |
-
// Prepare Response
|
98 |
-
$this->prepareResponse( false, false );
|
99 |
-
|
100 |
-
// Not finished
|
101 |
-
return true;
|
102 |
-
}
|
103 |
-
|
104 |
-
|
105 |
-
// Prepare Response
|
106 |
-
$this->prepareResponse();
|
107 |
-
|
108 |
-
// Not finished
|
109 |
-
return true;
|
110 |
-
}
|
111 |
-
|
112 |
-
/**
|
113 |
-
* Stop Execution immediately
|
114 |
-
* return mixed bool | json
|
115 |
-
*/
|
116 |
-
private function stopExecution() {
|
117 |
-
if( $this->db->prefix == $this->tmpPrefix ) {
|
118 |
-
$this->returnException( 'Fatal Error 9: Prefix ' . $this->db->prefix . ' is used for the live site hence it can not be used for the staging site as well. Please ask support@wp-staging.com how to resolve this.' );
|
119 |
-
}
|
120 |
-
return false;
|
121 |
-
}
|
122 |
-
|
123 |
-
/**
|
124 |
-
* Copy Tables
|
125 |
-
* @param string $tableName
|
126 |
-
* @return bool
|
127 |
-
*/
|
128 |
-
private function updateTable( $tableName ) {
|
129 |
-
$strings = new Strings();
|
130 |
-
$table = $strings->str_replace_first( $this->db->prefix, '', $tableName );
|
131 |
-
$newTableName = $this->tmpPrefix . $table;
|
132 |
-
|
133 |
-
// Save current job
|
134 |
-
$this->setJob( $newTableName );
|
135 |
-
|
136 |
-
// Beginning of the job
|
137 |
-
if( !$this->startJob( $newTableName, $tableName ) ) {
|
138 |
-
return true;
|
139 |
-
}
|
140 |
-
// Copy data
|
141 |
-
$this->startReplace( $newTableName );
|
142 |
-
|
143 |
-
// Finis the step
|
144 |
-
return $this->finishStep();
|
145 |
-
}
|
146 |
-
|
147 |
-
/**
|
148 |
-
* Start search replace job
|
149 |
-
* @param string $new
|
150 |
-
* @param string $old
|
151 |
-
*/
|
152 |
-
private function startReplace( $new ) {
|
153 |
-
$rows = $this->options->job->start + $this->settings->querySRLimit;
|
154 |
-
$this->log(
|
155 |
-
"DB Processing: Table {$new} {$this->options->job->start} to {$rows} records"
|
156 |
-
);
|
157 |
-
|
158 |
-
// Search & Replace
|
159 |
-
$this->searchReplace( $new, $rows, array() );
|
160 |
-
|
161 |
-
// Set new offset
|
162 |
-
$this->options->job->start += $this->settings->querySRLimit;
|
163 |
-
}
|
164 |
-
|
165 |
-
/**
|
166 |
-
* Returns the number of pages in a table.
|
167 |
-
* @access public
|
168 |
-
* @return int
|
169 |
-
*/
|
170 |
-
private function get_pages_in_table( $table ) {
|
171 |
-
$table = esc_sql( $table );
|
172 |
-
$rows = $this->db->get_var( "SELECT COUNT(*) FROM $table" );
|
173 |
-
$pages = ceil( $rows / $this->settings->querySRLimit );
|
174 |
-
return absint( $pages );
|
175 |
-
}
|
176 |
-
|
177 |
-
/**
|
178 |
-
* Gets the columns in a table.
|
179 |
-
* @access public
|
180 |
-
* @param string $table The table to check.
|
181 |
-
* @return array
|
182 |
-
*/
|
183 |
-
private function get_columns( $table ) {
|
184 |
-
$primary_key = null;
|
185 |
-
$columns = array();
|
186 |
-
$fields = $this->db->get_results( 'DESCRIBE ' . $table );
|
187 |
-
if( is_array( $fields ) ) {
|
188 |
-
foreach ( $fields as $column ) {
|
189 |
-
$columns[] = $column->Field;
|
190 |
-
if( $column->Key == 'PRI' ) {
|
191 |
-
$primary_key = $column->Field;
|
192 |
-
}
|
193 |
-
}
|
194 |
-
}
|
195 |
-
return array($primary_key, $columns);
|
196 |
-
}
|
197 |
-
|
198 |
-
/**
|
199 |
-
* Adapated from interconnect/it's search/replace script, adapted from Better Search Replace
|
200 |
-
*
|
201 |
-
* Modified to use WordPress wpdb functions instead of PHP's native mysql/pdo functions,
|
202 |
-
* and to be compatible with batch processing.
|
203 |
-
*
|
204 |
-
* @link https://interconnectit.com/products/search-and-replace-for-wordpress-databases/
|
205 |
-
*
|
206 |
-
* @access public
|
207 |
-
* @param string $table The table to run the replacement on.
|
208 |
-
* @param int $page The page/block to begin the query on.
|
209 |
-
* @param array $args An associative array containing arguements for this run.
|
210 |
-
* @return array
|
211 |
-
*/
|
212 |
-
private function searchReplace( $table, $page, $args ) {
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
rtrim( $this->
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
$
|
258 |
-
|
259 |
-
|
260 |
-
$args['
|
261 |
-
|
262 |
-
|
263 |
-
$args =
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
//
|
270 |
-
|
271 |
-
|
272 |
-
//
|
273 |
-
//
|
274 |
-
//
|
275 |
-
|
276 |
-
$
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
$
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
'
|
290 |
-
'
|
291 |
-
'
|
292 |
-
'
|
293 |
-
'
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
'
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
//
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
$
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
'wp-content' . DIRECTORY_SEPARATOR . '
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
*
|
452 |
-
*
|
453 |
-
*
|
454 |
-
*
|
455 |
-
*
|
456 |
-
*
|
457 |
-
*
|
458 |
-
* @
|
459 |
-
* @param
|
460 |
-
*
|
461 |
-
* @
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
$data
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
$
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
}
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
//
|
511 |
-
//
|
512 |
-
//
|
513 |
-
//
|
514 |
-
//
|
515 |
-
//
|
516 |
-
//
|
517 |
-
//
|
518 |
-
//
|
519 |
-
//
|
520 |
-
// $data
|
521 |
-
//
|
522 |
-
//
|
523 |
-
//
|
524 |
-
//
|
525 |
-
//
|
526 |
-
//
|
527 |
-
//
|
528 |
-
//
|
529 |
-
//
|
530 |
-
//
|
531 |
-
//
|
532 |
-
//
|
533 |
-
//
|
534 |
-
//
|
535 |
-
//
|
536 |
-
//
|
537 |
-
//
|
538 |
-
//
|
539 |
-
//
|
540 |
-
//
|
541 |
-
//
|
542 |
-
//
|
543 |
-
//
|
544 |
-
// $data =
|
545 |
-
// }
|
546 |
-
// }
|
547 |
-
//
|
548 |
-
//
|
549 |
-
//
|
550 |
-
// }
|
551 |
-
//
|
552 |
-
//
|
553 |
-
//
|
554 |
-
//
|
555 |
-
//
|
556 |
-
//
|
557 |
-
|
558 |
-
|
559 |
-
|
560 |
-
|
561 |
-
|
562 |
-
|
563 |
-
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
|
569 |
-
//
|
570 |
-
// $
|
571 |
-
//
|
572 |
-
//
|
573 |
-
//
|
574 |
-
//
|
575 |
-
//
|
576 |
-
//
|
577 |
-
//
|
578 |
-
//
|
579 |
-
//
|
580 |
-
//
|
581 |
-
//
|
582 |
-
//
|
583 |
-
//
|
584 |
-
//
|
585 |
-
//
|
586 |
-
|
587 |
-
|
588 |
-
|
589 |
-
|
590 |
-
|
591 |
-
|
592 |
-
*
|
593 |
-
|
594 |
-
|
595 |
-
|
596 |
-
|
597 |
-
|
598 |
-
|
599 |
-
|
600 |
-
|
601 |
-
|
602 |
-
|
603 |
-
|
604 |
-
|
605 |
-
|
606 |
-
|
607 |
-
|
608 |
-
|
609 |
-
|
610 |
-
*
|
611 |
-
*
|
612 |
-
|
613 |
-
|
614 |
-
|
615 |
-
|
616 |
-
|
617 |
-
|
618 |
-
|
619 |
-
|
620 |
-
|
621 |
-
|
622 |
-
|
623 |
-
|
624 |
-
|
625 |
-
|
626 |
-
|
627 |
-
|
628 |
-
|
629 |
-
*
|
630 |
-
*
|
631 |
-
*
|
632 |
-
* @
|
633 |
-
|
634 |
-
|
635 |
-
|
636 |
-
|
637 |
-
|
638 |
-
|
639 |
-
|
640 |
-
|
641 |
-
|
642 |
-
|
643 |
-
|
644 |
-
|
645 |
-
|
646 |
-
|
647 |
-
|
648 |
-
|
649 |
-
|
650 |
-
|
651 |
-
|
652 |
-
|
653 |
-
|
654 |
-
|
655 |
-
|
656 |
-
|
657 |
-
|
658 |
-
|
659 |
-
|
660 |
-
|
661 |
-
|
662 |
-
|
663 |
-
|
664 |
-
|
665 |
-
$this->options->job->current
|
666 |
-
|
667 |
-
|
668 |
-
|
669 |
-
|
670 |
-
|
671 |
-
|
672 |
-
|
673 |
-
|
674 |
-
|
675 |
-
|
676 |
-
|
677 |
-
|
678 |
-
|
679 |
-
|
680 |
-
|
681 |
-
|
682 |
-
|
683 |
-
|
684 |
-
|
685 |
-
|
686 |
-
|
687 |
-
|
688 |
-
|
689 |
-
|
690 |
-
|
691 |
-
|
692 |
-
|
693 |
-
|
694 |
-
|
695 |
-
|
696 |
-
|
697 |
-
|
698 |
-
|
699 |
-
|
700 |
-
|
701 |
-
|
702 |
-
|
703 |
-
|
704 |
-
|
705 |
-
|
706 |
-
|
707 |
-
|
708 |
-
|
709 |
-
|
710 |
-
|
711 |
-
|
712 |
-
|
713 |
-
|
714 |
-
|
715 |
-
|
716 |
-
|
717 |
-
|
718 |
-
|
719 |
-
|
720 |
-
|
721 |
-
|
722 |
-
|
723 |
-
|
724 |
-
|
725 |
-
|
726 |
-
|
727 |
-
|
728 |
-
|
729 |
-
|
730 |
-
|
731 |
-
|
732 |
-
|
733 |
-
|
734 |
-
|
735 |
-
|
736 |
-
|
737 |
-
)
|
738 |
-
|
739 |
-
|
740 |
-
|
741 |
-
|
742 |
-
|
743 |
-
|
744 |
-
|
745 |
-
|
746 |
-
|
747 |
-
|
748 |
-
|
749 |
-
|
750 |
-
|
751 |
-
|
752 |
-
|
753 |
-
|
754 |
-
|
755 |
-
|
756 |
-
|
757 |
-
|
758 |
-
|
759 |
-
|
760 |
-
|
761 |
-
|
762 |
-
|
763 |
-
|
764 |
-
|
765 |
-
|
766 |
-
|
767 |
-
|
768 |
-
|
769 |
-
|
770 |
-
|
771 |
-
|
772 |
-
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPStaging\Backend\Modules\Jobs\Multisite;
|
4 |
+
|
5 |
+
// No Direct Access
|
6 |
+
if( !defined( "WPINC" ) ) {
|
7 |
+
die;
|
8 |
+
}
|
9 |
+
|
10 |
+
use WPStaging\WPStaging;
|
11 |
+
use WPStaging\Utils\Strings;
|
12 |
+
use WPStaging\Utils\Helper;
|
13 |
+
use WPStaging\Utils\Multisite;
|
14 |
+
use WPStaging\Backend\Modules\Jobs\JobExecutable;
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Class Database
|
18 |
+
* @package WPStaging\Backend\Modules\Jobs
|
19 |
+
*/
|
20 |
+
class SearchReplace extends JobExecutable {
|
21 |
+
|
22 |
+
/**
|
23 |
+
* @var int
|
24 |
+
*/
|
25 |
+
private $total = 0;
|
26 |
+
|
27 |
+
/**
|
28 |
+
* @var \WPDB
|
29 |
+
*/
|
30 |
+
public $db;
|
31 |
+
|
32 |
+
/**
|
33 |
+
* The prefix of the new database tables which are used for the live site after updating tables
|
34 |
+
* @var string
|
35 |
+
*/
|
36 |
+
public $tmpPrefix;
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Initialize
|
40 |
+
*/
|
41 |
+
public function initialize() {
|
42 |
+
$this->total = count( $this->options->tables );
|
43 |
+
$this->db = WPStaging::getInstance()->get( "wpdb" );
|
44 |
+
$this->tmpPrefix = $this->options->prefix;
|
45 |
+
}
|
46 |
+
|
47 |
+
public function start() {
|
48 |
+
// Skip job. Nothing to do
|
49 |
+
if( $this->options->totalSteps === 0 ) {
|
50 |
+
$this->prepareResponse( true, false );
|
51 |
+
}
|
52 |
+
|
53 |
+
$this->run();
|
54 |
+
|
55 |
+
// Save option, progress
|
56 |
+
$this->saveOptions();
|
57 |
+
|
58 |
+
return ( object ) $this->response;
|
59 |
+
}
|
60 |
+
|
61 |
+
/**
|
62 |
+
* Calculate Total Steps in This Job and Assign It to $this->options->totalSteps
|
63 |
+
* @return void
|
64 |
+
*/
|
65 |
+
protected function calculateTotalSteps() {
|
66 |
+
$this->options->totalSteps = $this->total;
|
67 |
+
}
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Execute the Current Step
|
71 |
+
* Returns false when over threshold limits are hit or when the job is done, true otherwise
|
72 |
+
* @return bool
|
73 |
+
*/
|
74 |
+
protected function execute() {
|
75 |
+
// Over limits threshold
|
76 |
+
if( $this->isOverThreshold() ) {
|
77 |
+
// Prepare response and save current progress
|
78 |
+
$this->prepareResponse( false, false );
|
79 |
+
$this->saveOptions();
|
80 |
+
return false;
|
81 |
+
}
|
82 |
+
|
83 |
+
// No more steps, finished
|
84 |
+
if( $this->options->currentStep > $this->total || !isset( $this->options->tables[$this->options->currentStep] ) ) {
|
85 |
+
$this->prepareResponse( true, false );
|
86 |
+
return false;
|
87 |
+
}
|
88 |
+
|
89 |
+
// Table is excluded
|
90 |
+
if( in_array( $this->options->tables[$this->options->currentStep], $this->options->excludedTables ) ) {
|
91 |
+
$this->prepareResponse();
|
92 |
+
return true;
|
93 |
+
}
|
94 |
+
|
95 |
+
// Search & Replace
|
96 |
+
if( !$this->stopExecution() && !$this->updateTable( $this->options->tables[$this->options->currentStep] ) ) {
|
97 |
+
// Prepare Response
|
98 |
+
$this->prepareResponse( false, false );
|
99 |
+
|
100 |
+
// Not finished
|
101 |
+
return true;
|
102 |
+
}
|
103 |
+
|
104 |
+
|
105 |
+
// Prepare Response
|
106 |
+
$this->prepareResponse();
|
107 |
+
|
108 |
+
// Not finished
|
109 |
+
return true;
|
110 |
+
}
|
111 |
+
|
112 |
+
/**
|
113 |
+
* Stop Execution immediately
|
114 |
+
* return mixed bool | json
|
115 |
+
*/
|
116 |
+
private function stopExecution() {
|
117 |
+
if( $this->db->prefix == $this->tmpPrefix ) {
|
118 |
+
$this->returnException( 'Fatal Error 9: Prefix ' . $this->db->prefix . ' is used for the live site hence it can not be used for the staging site as well. Please ask support@wp-staging.com how to resolve this.' );
|
119 |
+
}
|
120 |
+
return false;
|
121 |
+
}
|
122 |
+
|
123 |
+
/**
|
124 |
+
* Copy Tables
|
125 |
+
* @param string $tableName
|
126 |
+
* @return bool
|
127 |
+
*/
|
128 |
+
private function updateTable( $tableName ) {
|
129 |
+
$strings = new Strings();
|
130 |
+
$table = $strings->str_replace_first( $this->db->prefix, '', $tableName );
|
131 |
+
$newTableName = $this->tmpPrefix . $table;
|
132 |
+
|
133 |
+
// Save current job
|
134 |
+
$this->setJob( $newTableName );
|
135 |
+
|
136 |
+
// Beginning of the job
|
137 |
+
if( !$this->startJob( $newTableName, $tableName ) ) {
|
138 |
+
return true;
|
139 |
+
}
|
140 |
+
// Copy data
|
141 |
+
$this->startReplace( $newTableName );
|
142 |
+
|
143 |
+
// Finis the step
|
144 |
+
return $this->finishStep();
|
145 |
+
}
|
146 |
+
|
147 |
+
/**
|
148 |
+
* Start search replace job
|
149 |
+
* @param string $new
|
150 |
+
* @param string $old
|
151 |
+
*/
|
152 |
+
private function startReplace( $new ) {
|
153 |
+
$rows = $this->options->job->start + $this->settings->querySRLimit;
|
154 |
+
$this->log(
|
155 |
+
"DB Processing: Table {$new} {$this->options->job->start} to {$rows} records"
|
156 |
+
);
|
157 |
+
|
158 |
+
// Search & Replace
|
159 |
+
$this->searchReplace( $new, $rows, array() );
|
160 |
+
|
161 |
+
// Set new offset
|
162 |
+
$this->options->job->start += $this->settings->querySRLimit;
|
163 |
+
}
|
164 |
+
|
165 |
+
/**
|
166 |
+
* Returns the number of pages in a table.
|
167 |
+
* @access public
|
168 |
+
* @return int
|
169 |
+
*/
|
170 |
+
private function get_pages_in_table( $table ) {
|
171 |
+
$table = esc_sql( $table );
|
172 |
+
$rows = $this->db->get_var( "SELECT COUNT(*) FROM $table" );
|
173 |
+
$pages = ceil( $rows / $this->settings->querySRLimit );
|
174 |
+
return absint( $pages );
|
175 |
+
}
|
176 |
+
|
177 |
+
/**
|
178 |
+
* Gets the columns in a table.
|
179 |
+
* @access public
|
180 |
+
* @param string $table The table to check.
|
181 |
+
* @return array
|
182 |
+
*/
|
183 |
+
private function get_columns( $table ) {
|
184 |
+
$primary_key = null;
|
185 |
+
$columns = array();
|
186 |
+
$fields = $this->db->get_results( 'DESCRIBE ' . $table );
|
187 |
+
if( is_array( $fields ) ) {
|
188 |
+
foreach ( $fields as $column ) {
|
189 |
+
$columns[] = $column->Field;
|
190 |
+
if( $column->Key == 'PRI' ) {
|
191 |
+
$primary_key = $column->Field;
|
192 |
+
}
|
193 |
+
}
|
194 |
+
}
|
195 |
+
return array($primary_key, $columns);
|
196 |
+
}
|
197 |
+
|
198 |
+
/**
|
199 |
+
* Adapated from interconnect/it's search/replace script, adapted from Better Search Replace
|
200 |
+
*
|
201 |
+
* Modified to use WordPress wpdb functions instead of PHP's native mysql/pdo functions,
|
202 |
+
* and to be compatible with batch processing.
|
203 |
+
*
|
204 |
+
* @link https://interconnectit.com/products/search-and-replace-for-wordpress-databases/
|
205 |
+
*
|
206 |
+
* @access public
|
207 |
+
* @param string $table The table to run the replacement on.
|
208 |
+
* @param int $page The page/block to begin the query on.
|
209 |
+
* @param array $args An associative array containing arguements for this run.
|
210 |
+
* @return array
|
211 |
+
*/
|
212 |
+
private function searchReplace( $table, $page, $args ) {
|
213 |
+
|
214 |
+
if( $this->thirdParty->isSearchReplaceExcluded( $table ) ) {
|
215 |
+
$this->log( "DB Processing: Skip {$table}", \WPStaging\Utils\Logger::TYPE_INFO );
|
216 |
+
return true;
|
217 |
+
}
|
218 |
+
|
219 |
+
// Load up the default settings for this chunk.
|
220 |
+
$table = esc_sql( $table );
|
221 |
+
$current_page = $this->options->job->start + $this->settings->querySRLimit;
|
222 |
+
$pages = $this->get_pages_in_table( $table );
|
223 |
+
//$done = false;
|
224 |
+
|
225 |
+
|
226 |
+
if( $this->isSubDir() ) {
|
227 |
+
// Search URL example.com/staging and root path to staging site /var/www/htdocs/staging
|
228 |
+
$args['search_for'] = array(
|
229 |
+
rtrim( $this->multisiteHomeUrlWithoutScheme, "/" ) . $this->getSubDir(),
|
230 |
+
ABSPATH,
|
231 |
+
str_replace( '/', '\/', rtrim( $this->multisiteHomeUrlWithoutScheme, '/' ) ) . str_replace( '/', '\/', $this->getSubDir() ), // // Used by revslider and several visual editors
|
232 |
+
$this->getImagePathLive()
|
233 |
+
);
|
234 |
+
|
235 |
+
|
236 |
+
$args['replace_with'] = array(
|
237 |
+
rtrim( $this->multisiteDomainWithoutScheme, "/" ) . $this->getSubDir() . '/' . $this->options->cloneDirectoryName,
|
238 |
+
rtrim( ABSPATH, '/' ) . '/' . $this->options->cloneDirectoryName,
|
239 |
+
str_replace( '/', '\/', rtrim( $this->multisiteDomainWithoutScheme, "/" ) ) . str_replace( '/', '\/', $this->getSubDir() ) . '\/' . $this->options->cloneDirectoryName, // Used by revslider and several visual editors
|
240 |
+
$this->getImagePathStaging()
|
241 |
+
);
|
242 |
+
} else {
|
243 |
+
$args['search_for'] = array(
|
244 |
+
rtrim( $this->multisiteHomeUrlWithoutScheme, '/' ),
|
245 |
+
ABSPATH,
|
246 |
+
str_replace( '/', '\/', rtrim( $this->multisiteHomeUrlWithoutScheme, '/' ) ),
|
247 |
+
$this->getImagePathLive()
|
248 |
+
);
|
249 |
+
$args['replace_with'] = array(
|
250 |
+
rtrim( $this->multisiteDomainWithoutScheme, '/' ) . '/' . $this->options->cloneDirectoryName,
|
251 |
+
rtrim( ABSPATH, '/' ) . '/' . $this->options->cloneDirectoryName,
|
252 |
+
str_replace( '/', '\/', rtrim( $this->multisiteDomainWithoutScheme, '/' ) ) . '\/' . $this->options->cloneDirectoryName,
|
253 |
+
$this->getImagePathStaging()
|
254 |
+
);
|
255 |
+
}
|
256 |
+
|
257 |
+
//$this->log( 'Search: ' . $this->multisiteHomeUrlWithoutScheme . ' Replace: ' . rtrim( $this->multisiteDomainWithoutScheme, '/' ) . '/' . $this->options->cloneDirectoryName );
|
258 |
+
|
259 |
+
|
260 |
+
$args['replace_guids'] = 'off';
|
261 |
+
$args['dry_run'] = 'off';
|
262 |
+
$args['case_insensitive'] = false;
|
263 |
+
$args['replace_guids'] = 'off';
|
264 |
+
$args['replace_mails'] = 'off';
|
265 |
+
|
266 |
+
// Allow filtering of search & replace parameters
|
267 |
+
$args = apply_filters( 'wpstg_clone_searchreplace_params', $args );
|
268 |
+
|
269 |
+
// Get a list of columns in this table.
|
270 |
+
list( $primary_key, $columns ) = $this->get_columns( $table );
|
271 |
+
|
272 |
+
// Bail out early if there isn't a primary key.
|
273 |
+
// We commented this to search & replace through tables which have no primary keys like wp_revslider_slides
|
274 |
+
// @todo test this carefully. If it causes (performance) issues we need to activate it again!
|
275 |
+
// @since 2.4.4
|
276 |
+
// if( null === $primary_key ) {
|
277 |
+
// return false;
|
278 |
+
// }
|
279 |
+
|
280 |
+
$current_row = 0;
|
281 |
+
$start = $this->options->job->start;
|
282 |
+
$end = $this->settings->querySRLimit;
|
283 |
+
|
284 |
+
// Grab the content of the table.
|
285 |
+
$data = $this->db->get_results( "SELECT * FROM $table LIMIT $start, $end", ARRAY_A );
|
286 |
+
|
287 |
+
// Filter certain rows option_name in wpstg_options
|
288 |
+
$filter = array(
|
289 |
+
'Admin_custome_login_Slidshow',
|
290 |
+
'Admin_custome_login_Social',
|
291 |
+
'Admin_custome_login_logo',
|
292 |
+
'Admin_custome_login_text',
|
293 |
+
'Admin_custome_login_login',
|
294 |
+
'Admin_custome_login_top',
|
295 |
+
'Admin_custome_login_dashboard',
|
296 |
+
'Admin_custome_login_Version',
|
297 |
+
'upload_path',
|
298 |
+
);
|
299 |
+
|
300 |
+
apply_filters( 'wpstg_clone_searchreplace_excl_rows', $filter );
|
301 |
+
|
302 |
+
// Loop through the data.
|
303 |
+
foreach ( $data as $row ) {
|
304 |
+
$current_row++;
|
305 |
+
$update_sql = array();
|
306 |
+
$where_sql = array();
|
307 |
+
$upd = false;
|
308 |
+
|
309 |
+
// Skip rows below
|
310 |
+
if( isset( $row['option_name'] ) && in_array( $row['option_name'], $filter ) ) {
|
311 |
+
continue;
|
312 |
+
}
|
313 |
+
|
314 |
+
// Skip rows with transients (They can store huge data and we need to save memory)
|
315 |
+
if( isset( $row['option_name'] ) && strpos( $row['option_name'], '_transient' ) === 0 ) {
|
316 |
+
continue;
|
317 |
+
}
|
318 |
+
|
319 |
+
|
320 |
+
foreach ( $columns as $column ) {
|
321 |
+
|
322 |
+
$dataRow = $row[$column];
|
323 |
+
|
324 |
+
if( $column == $primary_key ) {
|
325 |
+
$where_sql[] = $column . ' = "' . $this->mysql_escape_mimic( $dataRow ) . '"';
|
326 |
+
continue;
|
327 |
+
}
|
328 |
+
|
329 |
+
// Skip GUIDs by default.
|
330 |
+
if( 'on' !== $args['replace_guids'] && 'guid' == $column ) {
|
331 |
+
continue;
|
332 |
+
}
|
333 |
+
|
334 |
+
|
335 |
+
// Skip mail addresses
|
336 |
+
if( 'off' === $args['replace_mails'] && false !== strpos( $dataRow, '@' . $this->multisiteDomainWithoutScheme ) ) {
|
337 |
+
continue;
|
338 |
+
}
|
339 |
+
|
340 |
+
// Check options table
|
341 |
+
if( $this->options->prefix . 'options' === $table ) {
|
342 |
+
|
343 |
+
// Skip certain options
|
344 |
+
if( isset( $should_skip ) && true === $should_skip ) {
|
345 |
+
$should_skip = false;
|
346 |
+
continue;
|
347 |
+
}
|
348 |
+
|
349 |
+
// Skip this row
|
350 |
+
if( 'wpstg_existing_clones_beta' === $dataRow ||
|
351 |
+
'wpstg_existing_clones' === $dataRow ||
|
352 |
+
'wpstg_settings' === $dataRow ||
|
353 |
+
'wpstg_license_status' === $dataRow ||
|
354 |
+
'siteurl' === $dataRow ||
|
355 |
+
'home' === $dataRow
|
356 |
+
) {
|
357 |
+
$should_skip = true;
|
358 |
+
}
|
359 |
+
}
|
360 |
+
|
361 |
+
// Check the path delimiter for / or \/ and remove one of those which prevents from resulting in wrong syntax like domain.com/staging\/.
|
362 |
+
// 1. local.wordpress.test -> local.wordpress.test/staging
|
363 |
+
// 2. local.wordpress.test\/ -> local.wordpress.test\/staging\/
|
364 |
+
$tmp = $args;
|
365 |
+
if( false === strpos( $dataRow, $tmp['search_for'][0] ) ) {
|
366 |
+
array_shift( $tmp['search_for'] ); // rtrim( $this->homeUrl, '/' ),
|
367 |
+
array_shift( $tmp['replace_with'] ); // rtrim( $this->homeUrl, '/' ) . '/' . $this->options->cloneDirectoryName,
|
368 |
+
} else {
|
369 |
+
unset( $tmp['search_for'][1] );
|
370 |
+
unset( $tmp['replace_with'][1] );
|
371 |
+
// recount array
|
372 |
+
$tmp['search_for'] = array_values( $tmp['search_for'] );
|
373 |
+
$tmp['replace_with'] = array_values( $tmp['replace_with'] );
|
374 |
+
}
|
375 |
+
|
376 |
+
// Run a search replace on the data row and respect the serialisation.
|
377 |
+
$i = 0;
|
378 |
+
foreach ( $tmp['search_for'] as $replace ) {
|
379 |
+
//$this->log( "Search for: {$tmp['search_for'][$i]} Replace with {$tmp['replace_with'][$i]}", \WPStaging\Utils\Logger::TYPE_ERROR );
|
380 |
+
$dataRow = $this->recursive_unserialize_replace( $tmp['search_for'][$i], $tmp['replace_with'][$i], $dataRow, false, $args['case_insensitive'] );
|
381 |
+
$i++;
|
382 |
+
}
|
383 |
+
unset( $replace );
|
384 |
+
unset( $i );
|
385 |
+
unset( $tmp );
|
386 |
+
|
387 |
+
// Something was changed
|
388 |
+
if( $row[$column] != $dataRow ) {
|
389 |
+
$update_sql[] = $column . ' = "' . $this->mysql_escape_mimic( $dataRow ) . '"';
|
390 |
+
$upd = true;
|
391 |
+
}
|
392 |
+
}
|
393 |
+
|
394 |
+
// Determine what to do with updates.
|
395 |
+
if( $args['dry_run'] === 'on' ) {
|
396 |
+
// Don't do anything if a dry run
|
397 |
+
} elseif( $upd && !empty( $where_sql ) ) {
|
398 |
+
// If there are changes to make, run the query.
|
399 |
+
$sql = 'UPDATE ' . $table . ' SET ' . implode( ', ', $update_sql ) . ' WHERE ' . implode( ' AND ', array_filter( $where_sql ) );
|
400 |
+
$result = $this->db->query( $sql );
|
401 |
+
|
402 |
+
if( !$result ) {
|
403 |
+
$this->log( "Error updating row {$current_row} SQL: {$sql}", \WPStaging\Utils\Logger::TYPE_ERROR );
|
404 |
+
}
|
405 |
+
}
|
406 |
+
} // end row loop
|
407 |
+
unset( $row );
|
408 |
+
unset( $update_sql );
|
409 |
+
unset( $where_sql );
|
410 |
+
unset( $sql );
|
411 |
+
|
412 |
+
|
413 |
+
// DB Flush
|
414 |
+
$this->db->flush();
|
415 |
+
return true;
|
416 |
+
}
|
417 |
+
|
418 |
+
/**
|
419 |
+
* Get path to multisite image folder e.g. wp-content/blogs.dir/ID/files or wp-content/uploads/sites/ID
|
420 |
+
* @return string
|
421 |
+
*/
|
422 |
+
private function getImagePathLive() {
|
423 |
+
// Check first which structure is used
|
424 |
+
$uploads = wp_upload_dir();
|
425 |
+
$basedir = $uploads['basedir'];
|
426 |
+
$blogId = get_current_blog_id();
|
427 |
+
|
428 |
+
if( false === strpos( $basedir, 'blogs.dir' ) ) {
|
429 |
+
// Since WP 3.5
|
430 |
+
$path = $blogId > 1 ?
|
431 |
+
'wp-content' . DIRECTORY_SEPARATOR . 'uploads' . DIRECTORY_SEPARATOR . 'sites' . DIRECTORY_SEPARATOR . get_current_blog_id() . DIRECTORY_SEPARATOR :
|
432 |
+
'wp-content' . DIRECTORY_SEPARATOR . 'uploads' . DIRECTORY_SEPARATOR;
|
433 |
+
} else {
|
434 |
+
// old blog structure
|
435 |
+
$path = $blogId > 1 ?
|
436 |
+
'wp-content' . DIRECTORY_SEPARATOR . 'blogs.dir' . DIRECTORY_SEPARATOR . get_current_blog_id() . DIRECTORY_SEPARATOR . 'files' . DIRECTORY_SEPARATOR :
|
437 |
+
'wp-content' . DIRECTORY_SEPARATOR . 'uploads' . DIRECTORY_SEPARATOR;
|
438 |
+
}
|
439 |
+
return $path;
|
440 |
+
}
|
441 |
+
|
442 |
+
/**
|
443 |
+
* Get path to staging site image path wp-content/uploads
|
444 |
+
* @return string
|
445 |
+
*/
|
446 |
+
private function getImagePathStaging() {
|
447 |
+
return 'wp-content' . DIRECTORY_SEPARATOR . 'uploads' . DIRECTORY_SEPARATOR;
|
448 |
+
}
|
449 |
+
|
450 |
+
/**
|
451 |
+
* Adapted from interconnect/it's search/replace script.
|
452 |
+
*
|
453 |
+
* @link https://interconnectit.com/products/search-and-replace-for-wordpress-databases/
|
454 |
+
*
|
455 |
+
* Take a serialised array and unserialise it replacing elements as needed and
|
456 |
+
* unserialising any subordinate arrays and performing the replace on those too.
|
457 |
+
*
|
458 |
+
* @access private
|
459 |
+
* @param string $from String we're looking to replace.
|
460 |
+
* @param string $to What we want it to be replaced with
|
461 |
+
* @param array $data Used to pass any subordinate arrays back to in.
|
462 |
+
* @param boolean $serialized Does the array passed via $data need serialising.
|
463 |
+
* @param sting|boolean $case_insensitive Set to 'on' if we should ignore case, false otherwise.
|
464 |
+
*
|
465 |
+
* @return string|array The original array with all elements replaced as needed.
|
466 |
+
*/
|
467 |
+
private function recursive_unserialize_replace( $from = '', $to = '', $data = '', $serialized = false, $case_insensitive = false ) {
|
468 |
+
try {
|
469 |
+
// Some unserialized data cannot be re-serialized eg. SimpleXMLElements
|
470 |
+
if( is_serialized( $data ) && ( $unserialized = @unserialize( $data ) ) !== false ) {
|
471 |
+
$data = $this->recursive_unserialize_replace( $from, $to, $unserialized, true, $case_insensitive );
|
472 |
+
} elseif( is_array( $data ) ) {
|
473 |
+
$tmp = array();
|
474 |
+
foreach ( $data as $key => $value ) {
|
475 |
+
$tmp[$key] = $this->recursive_unserialize_replace( $from, $to, $value, false, $case_insensitive );
|
476 |
+
}
|
477 |
+
|
478 |
+
$data = $tmp;
|
479 |
+
unset( $tmp );
|
480 |
+
} elseif( is_object( $data ) ) {
|
481 |
+
$tmp = $data;
|
482 |
+
$props = get_object_vars( $data );
|
483 |
+
foreach ( $props as $key => $value ) {
|
484 |
+
if( $key === '' || ord( $key[0] ) === 0 ) {
|
485 |
+
continue;
|
486 |
+
}
|
487 |
+
$tmp->$key = $this->recursive_unserialize_replace( $from, $to, $value, false, $case_insensitive );
|
488 |
+
}
|
489 |
+
|
490 |
+
$data = $tmp;
|
491 |
+
unset( $tmp );
|
492 |
+
} else {
|
493 |
+
if( is_string( $data ) ) {
|
494 |
+
if( !empty( $from ) && !empty( $to ) ) {
|
495 |
+
$data = $this->str_replace( $from, $to, $data, $case_insensitive );
|
496 |
+
}
|
497 |
+
}
|
498 |
+
}
|
499 |
+
|
500 |
+
if( $serialized ) {
|
501 |
+
return serialize( $data );
|
502 |
+
}
|
503 |
+
} catch ( Exception $error ) {
|
504 |
+
|
505 |
+
}
|
506 |
+
|
507 |
+
return $data;
|
508 |
+
}
|
509 |
+
|
510 |
+
// private function recursive_unserialize_replace_( $from = '', $to = '', $data = '', $serialised = false, $case_insensitive = false ) {
|
511 |
+
// try {
|
512 |
+
//
|
513 |
+
// // Check first if its an object and repair it if necessary
|
514 |
+
// //$data = $this->fixObject($data);
|
515 |
+
//
|
516 |
+
// if( is_string( $data ) && !is_serialized_string( $data ) && ( $unserialized = $this->unserialize( $data ) ) !== false ) {
|
517 |
+
// $data = $this->recursive_unserialize_replace( $from, $to, $unserialized, true, $case_insensitive );
|
518 |
+
// } elseif( is_array( $data ) ) {
|
519 |
+
// $_tmp = array();
|
520 |
+
// foreach ( $data as $key => $value ) {
|
521 |
+
// $_tmp[$key] = $this->recursive_unserialize_replace( $from, $to, $value, false, $case_insensitive );
|
522 |
+
// }
|
523 |
+
//
|
524 |
+
// $data = $_tmp;
|
525 |
+
// unset( $_tmp );
|
526 |
+
// }
|
527 |
+
//
|
528 |
+
// // Submitted by Tina Matter
|
529 |
+
// elseif( $this->isValidObject( $data ) ) {
|
530 |
+
// $_tmp = $data; // new $data_class( );
|
531 |
+
// $props = get_object_vars( $data );
|
532 |
+
// foreach ( $props as $key => $value ) {
|
533 |
+
// if( $key === '' || ord( $key[0] ) === 0 ) {
|
534 |
+
// continue;
|
535 |
+
// }
|
536 |
+
// $_tmp->$key = $this->recursive_unserialize_replace( $from, $to, $value, false, $case_insensitive );
|
537 |
+
// }
|
538 |
+
//
|
539 |
+
// $data = $_tmp;
|
540 |
+
// unset( $_tmp );
|
541 |
+
// } elseif( is_serialized_string( $data ) ) {
|
542 |
+
// if( false !== ($data = $this->unserialize( $data )) ) {
|
543 |
+
// $data = $this->str_replace( $from, $to, $data, $case_insensitive );
|
544 |
+
// $data = serialize( $data );
|
545 |
+
// }
|
546 |
+
// } else {
|
547 |
+
// if( is_string( $data ) ) {
|
548 |
+
// $data = $this->str_replace( $from, $to, $data, $case_insensitive );
|
549 |
+
// }
|
550 |
+
// }
|
551 |
+
//
|
552 |
+
// if( $serialised ) {
|
553 |
+
// return serialize( $data );
|
554 |
+
// }
|
555 |
+
// } catch ( Exception $error ) {
|
556 |
+
//
|
557 |
+
// }
|
558 |
+
//
|
559 |
+
// return $data;
|
560 |
+
// }
|
561 |
+
|
562 |
+
|
563 |
+
|
564 |
+
/**
|
565 |
+
* Check if the object is a valid one and not __PHP_Incomplete_Class_Name
|
566 |
+
* Can not use is_object alone because in php 7.2 it's returning true even though object is __PHP_Incomplete_Class_Name
|
567 |
+
* @return boolean
|
568 |
+
*/
|
569 |
+
// private function isValidObject( $data ) {
|
570 |
+
// if( !is_object( $data ) || gettype( $data ) != 'object' ) {
|
571 |
+
// return false;
|
572 |
+
// }
|
573 |
+
//
|
574 |
+
// $invalid_class_props = get_object_vars( $data );
|
575 |
+
//
|
576 |
+
// if( !isset( $invalid_class_props['__PHP_Incomplete_Class_Name'] ) ) {
|
577 |
+
// // Assume it must be an valid object
|
578 |
+
// return true;
|
579 |
+
// }
|
580 |
+
//
|
581 |
+
// $invalid_object_class = $invalid_class_props['__PHP_Incomplete_Class_Name'];
|
582 |
+
//
|
583 |
+
// if( !empty( $invalid_object_class ) ) {
|
584 |
+
// return false;
|
585 |
+
// }
|
586 |
+
//
|
587 |
+
// // Assume it must be an valid object
|
588 |
+
// return true;
|
589 |
+
// }
|
590 |
+
|
591 |
+
/**
|
592 |
+
* Mimics the mysql_real_escape_string function. Adapted from a post by 'feedr' on php.net.
|
593 |
+
* @link http://php.net/manual/en/function.mysql-real-escape-string.php#101248
|
594 |
+
* @access public
|
595 |
+
* @param string $input The string to escape.
|
596 |
+
* @return string
|
597 |
+
*/
|
598 |
+
private function mysql_escape_mimic( $input ) {
|
599 |
+
if( is_array( $input ) ) {
|
600 |
+
return array_map( __METHOD__, $input );
|
601 |
+
}
|
602 |
+
if( !empty( $input ) && is_string( $input ) ) {
|
603 |
+
return str_replace( array('\\', "\0", "\n", "\r", "'", '"', "\x1a"), array('\\\\', '\\0', '\\n', '\\r', "\\'", '\\"', '\\Z'), $input );
|
604 |
+
}
|
605 |
+
|
606 |
+
return $input;
|
607 |
+
}
|
608 |
+
|
609 |
+
/**
|
610 |
+
* Return unserialized object or array
|
611 |
+
*
|
612 |
+
* @param string $serialized_string Serialized string.
|
613 |
+
* @param string $method The name of the caller method.
|
614 |
+
*
|
615 |
+
* @return mixed, false on failure
|
616 |
+
*/
|
617 |
+
private static function unserialize( $serialized_string ) {
|
618 |
+
if( !is_serialized( $serialized_string ) ) {
|
619 |
+
return false;
|
620 |
+
}
|
621 |
+
|
622 |
+
$serialized_string = trim( $serialized_string );
|
623 |
+
$unserialized_string = @unserialize( $serialized_string );
|
624 |
+
|
625 |
+
return $unserialized_string;
|
626 |
+
}
|
627 |
+
|
628 |
+
/**
|
629 |
+
* Wrapper for str_replace
|
630 |
+
*
|
631 |
+
* @param string $from
|
632 |
+
* @param string $to
|
633 |
+
* @param string $data
|
634 |
+
* @param string|bool $case_insensitive
|
635 |
+
*
|
636 |
+
* @return string
|
637 |
+
*/
|
638 |
+
private function str_replace( $from, $to, $data, $case_insensitive = false ) {
|
639 |
+
|
640 |
+
// Add filter
|
641 |
+
$excludes = apply_filters( 'wpstg_clone_searchreplace_excl', array() );
|
642 |
+
|
643 |
+
// Build pattern
|
644 |
+
$regexExclude = '';
|
645 |
+
foreach ( $excludes as $exclude ) {
|
646 |
+
$regexExclude .= $exclude . '(*SKIP)(FAIL)|';
|
647 |
+
}
|
648 |
+
|
649 |
+
if( 'on' === $case_insensitive ) {
|
650 |
+
//$data = str_ireplace( $from, $to, $data );
|
651 |
+
$data = preg_replace( '#' . $regexExclude . preg_quote( $from ) . '#i', $to, $data );
|
652 |
+
} else {
|
653 |
+
//$data = str_replace( $from, $to, $data );
|
654 |
+
$data = preg_replace( '#' . $regexExclude . preg_quote( $from ) . '#', $to, $data );
|
655 |
+
}
|
656 |
+
|
657 |
+
return $data;
|
658 |
+
}
|
659 |
+
|
660 |
+
/**
|
661 |
+
* Set the job
|
662 |
+
* @param string $table
|
663 |
+
*/
|
664 |
+
private function setJob( $table ) {
|
665 |
+
if( !empty( $this->options->job->current ) ) {
|
666 |
+
return;
|
667 |
+
}
|
668 |
+
|
669 |
+
$this->options->job->current = $table;
|
670 |
+
$this->options->job->start = 0;
|
671 |
+
}
|
672 |
+
|
673 |
+
/**
|
674 |
+
* Start Job
|
675 |
+
* @param string $new
|
676 |
+
* @param string $old
|
677 |
+
* @return bool
|
678 |
+
*/
|
679 |
+
private function startJob( $new, $old ) {
|
680 |
+
if( 0 != $this->options->job->start ) {
|
681 |
+
return true;
|
682 |
+
}
|
683 |
+
|
684 |
+
$this->options->job->total = ( int ) $this->db->get_var( "SELECT COUNT(1) FROM {$old}" );
|
685 |
+
|
686 |
+
if( 0 == $this->options->job->total ) {
|
687 |
+
$this->finishStep();
|
688 |
+
return false;
|
689 |
+
}
|
690 |
+
|
691 |
+
return true;
|
692 |
+
}
|
693 |
+
|
694 |
+
/**
|
695 |
+
* Finish the step
|
696 |
+
*/
|
697 |
+
private function finishStep() {
|
698 |
+
// This job is not finished yet
|
699 |
+
if( $this->options->job->total > $this->options->job->start ) {
|
700 |
+
return false;
|
701 |
+
}
|
702 |
+
|
703 |
+
// Add it to cloned tables listing
|
704 |
+
$this->options->clonedTables[] = $this->options->tables[$this->options->currentStep];
|
705 |
+
|
706 |
+
// Reset job
|
707 |
+
$this->options->job = new \stdClass();
|
708 |
+
|
709 |
+
return true;
|
710 |
+
}
|
711 |
+
|
712 |
+
/**
|
713 |
+
* Drop table if necessary
|
714 |
+
* @param string $new
|
715 |
+
*/
|
716 |
+
private function dropTable( $new ) {
|
717 |
+
$old = $this->db->get_var( $this->db->prepare( "SHOW TABLES LIKE %s", $new ) );
|
718 |
+
|
719 |
+
if( !$this->shouldDropTable( $new, $old ) ) {
|
720 |
+
return;
|
721 |
+
}
|
722 |
+
|
723 |
+
$this->log( "DB Processing: {$new} already exists, dropping it first" );
|
724 |
+
$this->db->query( "DROP TABLE {$new}" );
|
725 |
+
}
|
726 |
+
|
727 |
+
/**
|
728 |
+
* Check if table needs to be dropped
|
729 |
+
* @param string $new
|
730 |
+
* @param string $old
|
731 |
+
* @return bool
|
732 |
+
*/
|
733 |
+
private function shouldDropTable( $new, $old ) {
|
734 |
+
return (
|
735 |
+
$old == $new &&
|
736 |
+
(
|
737 |
+
!isset( $this->options->job->current ) ||
|
738 |
+
!isset( $this->options->job->start ) ||
|
739 |
+
0 == $this->options->job->start
|
740 |
+
)
|
741 |
+
);
|
742 |
+
}
|
743 |
+
|
744 |
+
/**
|
745 |
+
* Check if WP is installed in subdir
|
746 |
+
* @return boolean
|
747 |
+
*/
|
748 |
+
private function isSubDir() {
|
749 |
+
// Compare names without scheme to bypass cases where siteurl and home have different schemes http / https
|
750 |
+
// This is happening much more often than you would expect
|
751 |
+
$siteurl = preg_replace( '#^https?://#', '', rtrim( get_option( 'siteurl' ), '/' ) );
|
752 |
+
$home = preg_replace( '#^https?://#', '', rtrim( get_option( 'home' ), '/' ) );
|
753 |
+
|
754 |
+
if( $home !== $siteurl ) {
|
755 |
+
return true;
|
756 |
+
}
|
757 |
+
return false;
|
758 |
+
}
|
759 |
+
|
760 |
+
/**
|
761 |
+
* Get the install sub directory if WP is installed in sub directory
|
762 |
+
* @return string
|
763 |
+
*/
|
764 |
+
private function getSubDir() {
|
765 |
+
$home = get_option( 'home' );
|
766 |
+
$siteurl = get_option( 'siteurl' );
|
767 |
+
|
768 |
+
if( empty( $home ) || empty( $siteurl ) ) {
|
769 |
+
return '/';
|
770 |
+
}
|
771 |
+
|
772 |
+
$dir = str_replace( $home, '', $siteurl );
|
773 |
+
return '/' . str_replace( '/', '', $dir );
|
774 |
+
}
|
775 |
+
|
776 |
+
}
|
apps/Backend/Modules/Jobs/SearchReplace.php
CHANGED
@@ -216,8 +216,13 @@ class SearchReplace extends JobExecutable {
|
|
216 |
* @return array
|
217 |
*/
|
218 |
private function searchReplace( $table, $page, $args ) {
|
219 |
-
|
220 |
-
|
|
|
|
|
|
|
|
|
|
|
221 |
// Load up the default settings for this chunk.
|
222 |
$table = esc_sql( $table );
|
223 |
$current_page = $this->options->job->start + $this->settings->querySRLimit;
|
@@ -299,7 +304,7 @@ class SearchReplace extends JobExecutable {
|
|
299 |
|
300 |
// Loop through the data.
|
301 |
foreach ( $data as $row ) {
|
302 |
-
|
303 |
$update_sql = array();
|
304 |
$where_sql = array();
|
305 |
$upd = false;
|
@@ -684,4 +689,5 @@ class SearchReplace extends JobExecutable {
|
|
684 |
return '/' . str_replace( '/', '', $dir );
|
685 |
}
|
686 |
|
|
|
687 |
}
|
216 |
* @return array
|
217 |
*/
|
218 |
private function searchReplace( $table, $page, $args ) {
|
219 |
+
|
220 |
+
if( $this->thirdParty->isSearchReplaceExcluded($table) ) {
|
221 |
+
$this->log( "DB Processing: Skip {$table}", \WPStaging\Utils\Logger::TYPE_INFO );
|
222 |
+
return true;
|
223 |
+
}
|
224 |
+
|
225 |
+
|
226 |
// Load up the default settings for this chunk.
|
227 |
$table = esc_sql( $table );
|
228 |
$current_page = $this->options->job->start + $this->settings->querySRLimit;
|
304 |
|
305 |
// Loop through the data.
|
306 |
foreach ( $data as $row ) {
|
307 |
+
$current_row++;
|
308 |
$update_sql = array();
|
309 |
$where_sql = array();
|
310 |
$upd = false;
|
689 |
return '/' . str_replace( '/', '', $dir );
|
690 |
}
|
691 |
|
692 |
+
|
693 |
}
|
apps/Backend/Modules/Jobs/Updating.php
CHANGED
@@ -41,7 +41,25 @@ class Updating extends Job {
|
|
41 |
$this->options->includedDirectories = array();
|
42 |
$this->options->excludedDirectories = array();
|
43 |
$this->options->extraDirectories = array();
|
44 |
-
$this->options->excludedFiles = array(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
45 |
|
46 |
// Define mainJob to differentiate between cloning, updating and pushing
|
47 |
$this->options->mainJob = 'updating';
|
@@ -194,7 +212,7 @@ class Updating extends Job {
|
|
194 |
if( is_multisite() ) {
|
195 |
$database = new muDatabase();
|
196 |
} else {
|
197 |
-
|
198 |
}
|
199 |
return $this->handleJobResponse( $database->start(), "directories" );
|
200 |
}
|
@@ -207,7 +225,7 @@ class Updating extends Job {
|
|
207 |
if( is_multisite() ) {
|
208 |
$directories = new muDirectories();
|
209 |
} else {
|
210 |
-
|
211 |
}
|
212 |
return $this->handleJobResponse( $directories->start(), "files" );
|
213 |
}
|
@@ -220,7 +238,7 @@ class Updating extends Job {
|
|
220 |
if( is_multisite() ) {
|
221 |
$files = new muFiles();
|
222 |
} else {
|
223 |
-
|
224 |
}
|
225 |
return $this->handleJobResponse( $files->start(), "data" );
|
226 |
}
|
@@ -233,7 +251,7 @@ class Updating extends Job {
|
|
233 |
if( is_multisite() ) {
|
234 |
$data = new muData();
|
235 |
} else {
|
236 |
-
|
237 |
}
|
238 |
return $this->handleJobResponse( $data->start(), "finish" );
|
239 |
}
|
@@ -246,7 +264,7 @@ class Updating extends Job {
|
|
246 |
if( is_multisite() ) {
|
247 |
$finish = new muFinish();
|
248 |
} else {
|
249 |
-
|
250 |
}
|
251 |
$finish = new Finish();
|
252 |
return $this->handleJobResponse( $finish->start(), '' );
|
41 |
$this->options->includedDirectories = array();
|
42 |
$this->options->excludedDirectories = array();
|
43 |
$this->options->extraDirectories = array();
|
44 |
+
$this->options->excludedFiles = array(
|
45 |
+
'.htaccess',
|
46 |
+
'.DS_Store',
|
47 |
+
'.git',
|
48 |
+
'.svn',
|
49 |
+
'.tmp',
|
50 |
+
'desktop.ini',
|
51 |
+
'.gitignore',
|
52 |
+
'.log',
|
53 |
+
'db.php',
|
54 |
+
'object-cache.php'
|
55 |
+
);
|
56 |
+
|
57 |
+
$this->options->excludedFilesFullPath = array(
|
58 |
+
'wp-content' . DIRECTORY_SEPARATOR . 'db.php',
|
59 |
+
'wp-content' . DIRECTORY_SEPARATOR . 'object-cache.php',
|
60 |
+
'wp-content' . DIRECTORY_SEPARATOR . 'advanced-cache.php'
|
61 |
+
);
|
62 |
+
|
63 |
|
64 |
// Define mainJob to differentiate between cloning, updating and pushing
|
65 |
$this->options->mainJob = 'updating';
|
212 |
if( is_multisite() ) {
|
213 |
$database = new muDatabase();
|
214 |
} else {
|
215 |
+
$database = new Database();
|
216 |
}
|
217 |
return $this->handleJobResponse( $database->start(), "directories" );
|
218 |
}
|
225 |
if( is_multisite() ) {
|
226 |
$directories = new muDirectories();
|
227 |
} else {
|
228 |
+
$directories = new Directories();
|
229 |
}
|
230 |
return $this->handleJobResponse( $directories->start(), "files" );
|
231 |
}
|
238 |
if( is_multisite() ) {
|
239 |
$files = new muFiles();
|
240 |
} else {
|
241 |
+
$files = new Files();
|
242 |
}
|
243 |
return $this->handleJobResponse( $files->start(), "data" );
|
244 |
}
|
251 |
if( is_multisite() ) {
|
252 |
$data = new muData();
|
253 |
} else {
|
254 |
+
$data = new Data();
|
255 |
}
|
256 |
return $this->handleJobResponse( $data->start(), "finish" );
|
257 |
}
|
264 |
if( is_multisite() ) {
|
265 |
$finish = new muFinish();
|
266 |
} else {
|
267 |
+
$finish = new Finish();
|
268 |
}
|
269 |
$finish = new Finish();
|
270 |
return $this->handleJobResponse( $finish->start(), '' );
|
apps/Backend/Modules/Views/Forms/Settings.php
CHANGED
@@ -59,7 +59,7 @@ class Settings {
|
|
59 |
|
60 |
$this->form["general"]->add(
|
61 |
$element->setLabel( "DB Copy Query Limit" )
|
62 |
-
->setDefault( isset( $settings->queryLimit ) ? $settings->queryLimit :
|
63 |
);
|
64 |
// DB Search & Replace Query Limit
|
65 |
$element = new Numerical(
|
@@ -88,9 +88,7 @@ class Settings {
|
|
88 |
);
|
89 |
|
90 |
$this->form["general"]->add(
|
91 |
-
$element->setLabel( "File Copy Limit" )
|
92 |
-
->setDefault( isset( $settings->fileLimit ) ? $settings->fileLimit : 1 )
|
93 |
-
|
94 |
);
|
95 |
|
96 |
|
@@ -135,7 +133,7 @@ class Settings {
|
|
135 |
|
136 |
$this->form["general"]->add(
|
137 |
$element->setLabel( "CPU Load Priority" )
|
138 |
-
->setDefault( isset( $settings->cpuLoad ) ? $settings->cpuLoad : "
|
139 |
);
|
140 |
|
141 |
|
59 |
|
60 |
$this->form["general"]->add(
|
61 |
$element->setLabel( "DB Copy Query Limit" )
|
62 |
+
->setDefault( isset( $settings->queryLimit ) ? $settings->queryLimit : 10000 )
|
63 |
);
|
64 |
// DB Search & Replace Query Limit
|
65 |
$element = new Numerical(
|
88 |
);
|
89 |
|
90 |
$this->form["general"]->add(
|
91 |
+
$element->setLabel( "File Copy Limit" )->setDefault( isset( $settings->fileLimit ) ? $settings->fileLimit : '50' )
|
|
|
|
|
92 |
);
|
93 |
|
94 |
|
133 |
|
134 |
$this->form["general"]->add(
|
135 |
$element->setLabel( "CPU Load Priority" )
|
136 |
+
->setDefault( isset( $settings->cpuLoad ) ? $settings->cpuLoad : "low" )
|
137 |
);
|
138 |
|
139 |
|
apps/Backend/public/js/wpstg-admin.js
CHANGED
@@ -399,14 +399,15 @@ var WPStaging = (function ($)
|
|
399 |
console.log(xhr.status + ' ' + xhr.statusText + '---' + textStatus);
|
400 |
console.log(textStatus);
|
401 |
|
402 |
-
if (false === showErrors)
|
403 |
-
{
|
404 |
-
return false;
|
405 |
-
}
|
406 |
|
|
|
407 |
|
408 |
showError(
|
409 |
-
"Fatal
|
410 |
);
|
411 |
},
|
412 |
success: function (data) {
|
@@ -434,6 +435,14 @@ var WPStaging = (function ($)
|
|
434 |
obj.error = 'custom error';
|
435 |
return JSON.stringify(obj);
|
436 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
437 |
}
|
438 |
}
|
439 |
});
|
399 |
console.log(xhr.status + ' ' + xhr.statusText + '---' + textStatus);
|
400 |
console.log(textStatus);
|
401 |
|
402 |
+
// if (false === showErrors)
|
403 |
+
// {
|
404 |
+
// return false;
|
405 |
+
// }
|
406 |
|
407 |
+
var errorCode = "undefined" === typeof(xhr.status) ? "Unknown" : xhr.status;
|
408 |
|
409 |
showError(
|
410 |
+
"Fatal Error: "+ errorCode +" Please try the <a href='https://wp-staging.com/docs/wp-staging-settings-for-small-servers/' target='_blank'>WP Staging Small Server Settings</a> or submit an error report."
|
411 |
);
|
412 |
},
|
413 |
success: function (data) {
|
435 |
obj.error = 'custom error';
|
436 |
return JSON.stringify(obj);
|
437 |
|
438 |
+
},
|
439 |
+
429: function () {
|
440 |
+
showError("It looks like your server is rate limiting ajax requests. Please try to resume after a minute. If this still not works try the <a href='https://wp-staging.com/docs/wp-staging-settings-for-small-servers/' target='_blank'>WP Staging Small Server Settings</a> or submit an error report.\n\ ");
|
441 |
+
var obj = new Object();
|
442 |
+
obj.status = false;
|
443 |
+
obj.error = 'custom error';
|
444 |
+
return JSON.stringify(obj);
|
445 |
+
|
446 |
}
|
447 |
}
|
448 |
});
|
apps/Backend/views/clone/multi-site/index.php
CHANGED
@@ -1,3 +1,3 @@
|
|
1 |
<span class="wpstg-notice-alert" style="margin-top:20px;">
|
2 |
-
<?php echo __(
|
3 |
</span>
|
1 |
<span class="wpstg-notice-alert" style="margin-top:20px;">
|
2 |
+
<?php echo sprintf(__('WordPress Multisite is not supported! Upgrade to <a href="%s" target="_blank">WP Staging Pro</a>', 'wp-staging'), 'https://wp-staging.com/')?>
|
3 |
</span>
|
apps/Backend/views/settings/main-settings.php
CHANGED
@@ -98,7 +98,7 @@
|
|
98 |
To find out the highest possible values try a high value like 1.000 or more. If you get timeout issues, lower it
|
99 |
until you get no more errors during copying process.", "wp-staging" ); ?>
|
100 |
<br>
|
101 |
-
<strong> Default:
|
102 |
</span>
|
103 |
</div>
|
104 |
</td>
|
@@ -139,7 +139,7 @@
|
|
139 |
until you get no more errors during copying process.", "wp-staging" ); ?>
|
140 |
<br>
|
141 |
<br>
|
142 |
-
<?php _e( "<strong>Important:</strong> If CPU Load Priority is <strong>Low</strong> set a file copy limit value of
|
143 |
<br>
|
144 |
<br>
|
145 |
<strong> Default: 1 </strong>
|
@@ -157,7 +157,7 @@
|
|
157 |
<?php echo $form->label( "wpstg_settings[maxFileSize]" ) ?>
|
158 |
<span class="description">
|
159 |
<?php _e( "Maximum size of the files which are allowed to copy. All files larger than this value will be skipped.
|
160 |
-
Note: Increase this option only if you have a good reason. Files larger than a few megabytes are in 99% of all cases
|
161 |
<br>
|
162 |
<strong>Default:</strong> 8 MB
|
163 |
</span>
|
@@ -198,7 +198,7 @@
|
|
198 |
(e.g. <strong>authorization error</strong>).
|
199 |
Using a lower value results in lower cpu load on your server but also slower staging site creation.", "wp-staging" ); ?>
|
200 |
<br>
|
201 |
-
<strong>Default: </strong>
|
202 |
</span>
|
203 |
</div>
|
204 |
</td>
|
98 |
To find out the highest possible values try a high value like 1.000 or more. If you get timeout issues, lower it
|
99 |
until you get no more errors during copying process.", "wp-staging" ); ?>
|
100 |
<br>
|
101 |
+
<strong> Default: 10000 </strong>
|
102 |
</span>
|
103 |
</div>
|
104 |
</td>
|
139 |
until you get no more errors during copying process.", "wp-staging" ); ?>
|
140 |
<br>
|
141 |
<br>
|
142 |
+
<?php _e( "<strong>Important:</strong> If CPU Load Priority is <strong>Low</strong> set a file copy limit value of 50 or higher! Otherwise file copying process takes a lot of time.", "wp-staging" ); ?>
|
143 |
<br>
|
144 |
<br>
|
145 |
<strong> Default: 1 </strong>
|
157 |
<?php echo $form->label( "wpstg_settings[maxFileSize]" ) ?>
|
158 |
<span class="description">
|
159 |
<?php _e( "Maximum size of the files which are allowed to copy. All files larger than this value will be skipped.
|
160 |
+
Note: Increase this option only if you have a good reason. Files larger than a few megabytes are in 99% of all cases log and backup files which are not needed on a staging site.", "wp-staging" ); ?>
|
161 |
<br>
|
162 |
<strong>Default:</strong> 8 MB
|
163 |
</span>
|
198 |
(e.g. <strong>authorization error</strong>).
|
199 |
Using a lower value results in lower cpu load on your server but also slower staging site creation.", "wp-staging" ); ?>
|
200 |
<br>
|
201 |
+
<strong>Default: </strong> Low
|
202 |
</span>
|
203 |
</div>
|
204 |
</td>
|
apps/Core/WPStaging.php
CHANGED
@@ -29,7 +29,7 @@ final class WPStaging {
|
|
29 |
/**
|
30 |
* Plugin version
|
31 |
*/
|
32 |
-
const VERSION = "2.3.
|
33 |
|
34 |
/**
|
35 |
* Plugin name
|
@@ -77,10 +77,6 @@ final class WPStaging {
|
|
77 |
*/
|
78 |
private function __construct() {
|
79 |
|
80 |
-
//$file = WP_PLUGIN_DIR . DIRECTORY_SEPARATOR . self::SLUG . DIRECTORY_SEPARATOR . self::SLUG . ".php";
|
81 |
-
// Activation Hook
|
82 |
-
//register_activation_hook( __FILE__, array($this, "onActivation") );
|
83 |
-
|
84 |
$this->registerMain();
|
85 |
$this->registerNamespaces();
|
86 |
$this->loadLanguages();
|
@@ -103,10 +99,6 @@ final class WPStaging {
|
|
103 |
/**
|
104 |
* Method to be executed upon activation of the plugin
|
105 |
*/
|
106 |
-
// public function onActivation() {
|
107 |
-
// $Activation = new \WPStaging\Backend\Activation\Activation();
|
108 |
-
// $Activation->install_dependancies();
|
109 |
-
// }
|
110 |
|
111 |
public function registerMain() {
|
112 |
// Slug of the plugin
|
29 |
/**
|
30 |
* Plugin version
|
31 |
*/
|
32 |
+
const VERSION = "2.3.8";
|
33 |
|
34 |
/**
|
35 |
* Plugin name
|
77 |
*/
|
78 |
private function __construct() {
|
79 |
|
|
|
|
|
|
|
|
|
80 |
$this->registerMain();
|
81 |
$this->registerNamespaces();
|
82 |
$this->loadLanguages();
|
99 |
/**
|
100 |
* Method to be executed upon activation of the plugin
|
101 |
*/
|
|
|
|
|
|
|
|
|
102 |
|
103 |
public function registerMain() {
|
104 |
// Slug of the plugin
|
apps/Core/thirdParty/thirdPartyCompatibility.php
ADDED
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPStaging\thirdParty;
|
4 |
+
|
5 |
+
use WPStaging\DI\InjectionAware;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Methods to use for third party plugin compatibility
|
9 |
+
*
|
10 |
+
* @author IronMan
|
11 |
+
*/
|
12 |
+
class thirdPartyCompatibility extends InjectionAware
|
13 |
+
{
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Define a list of tables which should not run through search & replace method
|
17 |
+
* @param string table name e.g. wpsptg1_cerber_files or wpstgtmp_4_cerber_files
|
18 |
+
* @return array
|
19 |
+
*/
|
20 |
+
public function isSearchReplaceExcluded($table) {
|
21 |
+
$excludedTables = array(
|
22 |
+
'_cerber_files', // Cerber Security Plugin
|
23 |
+
);
|
24 |
+
|
25 |
+
foreach($excludedTables as $excludedTable){
|
26 |
+
if( false !== strpos($table, $excludedTable) ){
|
27 |
+
return true;
|
28 |
+
}
|
29 |
+
}
|
30 |
+
return false;
|
31 |
+
}
|
32 |
+
|
33 |
+
}
|
languages/wp-staging-de_DE.po
CHANGED
@@ -1,504 +1,504 @@
|
|
1 |
-
# Translation of Plugins - WP Staging – DB & File Duplicator & Migration - Stable (latest release) in German
|
2 |
-
# This file is distributed under the same license as the Plugins - WP Staging – DB & File Duplicator & Migration - Stable (latest release) package.
|
3 |
-
msgid ""
|
4 |
-
msgstr ""
|
5 |
-
"PO-Revision-Date: 2018-08-24 20:55:04+0000\n"
|
6 |
-
"MIME-Version: 1.0\n"
|
7 |
-
"Content-Type: text/plain; charset=UTF-8\n"
|
8 |
-
"Content-Transfer-Encoding: 8bit\n"
|
9 |
-
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
10 |
-
"X-Generator: GlotPress/2.4.0-alpha\n"
|
11 |
-
"Language: de\n"
|
12 |
-
"Project-Id-Version: Plugins - WP Staging – DB & File Duplicator & Migration - Stable (latest release)\n"
|
13 |
-
|
14 |
-
#. Author URI of the plugin/theme
|
15 |
-
msgid "https://wp-staging.com"
|
16 |
-
msgstr "https://wp-staging.com"
|
17 |
-
|
18 |
-
#. Author of the plugin/theme
|
19 |
-
msgid "WP-Staging"
|
20 |
-
msgstr "WP-Staging"
|
21 |
-
|
22 |
-
#. Description of the plugin/theme
|
23 |
-
msgid "Create a staging clone site for testing & developing"
|
24 |
-
msgstr "Erstelle eine Klon Webseite zum Testen und Entwickeln"
|
25 |
-
|
26 |
-
#. Plugin URI of the plugin/theme
|
27 |
-
msgid "https://wordpress.org/plugins/wp-staging"
|
28 |
-
msgstr "https://wordpress.org/plugins/wp-staging"
|
29 |
-
|
30 |
-
#: apps/Frontend/Frontend.php:88 apps/Frontend/loginForm.php:256
|
31 |
-
msgid "Log In"
|
32 |
-
msgstr "Anmelden"
|
33 |
-
|
34 |
-
#: apps/Frontend/Frontend.php:87 apps/Frontend/loginForm.php:255
|
35 |
-
msgid "Remember Me"
|
36 |
-
msgstr "Erinnere mich"
|
37 |
-
|
38 |
-
#: apps/Frontend/Frontend.php:86 apps/Frontend/loginForm.php:254
|
39 |
-
msgid "Password"
|
40 |
-
msgstr "Erinnere mich"
|
41 |
-
|
42 |
-
#: apps/Frontend/Frontend.php:85 apps/Frontend/loginForm.php:253
|
43 |
-
msgid "Username or Email Address"
|
44 |
-
msgstr "Benutzername oder E-Mail Adresse"
|
45 |
-
|
46 |
-
#: apps/Core/Utils/Report.php:31
|
47 |
-
msgid "Please accept our privacy policy."
|
48 |
-
msgstr "Bitte akzeptiere unsere Datenschutzvereinbarung"
|
49 |
-
|
50 |
-
#: apps/Core/Utils/Report.php:29
|
51 |
-
msgid "Please enter your issue."
|
52 |
-
msgstr "Bitte beschreibe Dein Problem"
|
53 |
-
|
54 |
-
#: apps/Core/Utils/Report.php:27
|
55 |
-
msgid "Email address is not valid."
|
56 |
-
msgstr "E-Mail Addresse ist nicht gültig"
|
57 |
-
|
58 |
-
#: apps/Core/Cron/Cron.php:35
|
59 |
-
msgid "Once a month"
|
60 |
-
msgstr "Einmal im Monat"
|
61 |
-
|
62 |
-
#: apps/Core/Cron/Cron.php:30
|
63 |
-
msgid "Once Weekly"
|
64 |
-
msgstr "Einmal wöchentlich"
|
65 |
-
|
66 |
-
#: apps/Backend/views/welcome/welcome.php:13
|
67 |
-
msgid "Comes with our 30-day no questions asked money back guarantee"
|
68 |
-
msgstr "Kommt mit unserer 30-Tage Geld zurück Garantie"
|
69 |
-
|
70 |
-
#: apps/Backend/views/welcome/welcome.php:10
|
71 |
-
msgid "WP Staging is coded well for protection of your data"
|
72 |
-
msgstr "WP Staging wurde sorgfältig entwickelt um Deine Daten zu schützen"
|
73 |
-
|
74 |
-
#: apps/Backend/views/welcome/welcome.php:9
|
75 |
-
msgid "Cloning process is fast and does not slow down website loading"
|
76 |
-
msgstr "Der Klonvorgang ist schnell und beeinflusst nicht die Webseite Ladezeit"
|
77 |
-
|
78 |
-
#: apps/Backend/views/welcome/welcome.php:8
|
79 |
-
msgid "Staging Site is available to authenticated users only"
|
80 |
-
msgstr "Staging Webseite ist nur für berechtigte Benutzer verfügbar"
|
81 |
-
|
82 |
-
#: apps/Backend/views/welcome/welcome.php:7
|
83 |
-
msgid "Copy plugin and theme files from staging to live site"
|
84 |
-
msgstr "Kopiere Plugin und Theme Dateien von der Staging auf die Live Seite"
|
85 |
-
|
86 |
-
#: apps/Backend/views/welcome/welcome.php:6
|
87 |
-
msgid "Create a clone of your website with a simple click"
|
88 |
-
msgstr "Erstelle einen Klon Deiner Webseite mit einem einfachen Klick"
|
89 |
-
|
90 |
-
#: apps/Backend/views/welcome/welcome.php:4
|
91 |
-
msgid " - Copy Themes & Plugins from Staging to Live Site"
|
92 |
-
msgstr "Kopiere Themes & Plugins von der Staging auf die Live Seite"
|
93 |
-
|
94 |
-
#: apps/Backend/views/welcome/welcome.php:4
|
95 |
-
msgid "WP Staging Pro"
|
96 |
-
msgstr "WP Staging Pro"
|
97 |
-
|
98 |
-
#: apps/Backend/views/tools/tabs/import_export.php:52
|
99 |
-
msgid "Import"
|
100 |
-
msgstr "Importieren"
|
101 |
-
|
102 |
-
#: apps/Backend/views/tools/tabs/import_export.php:33
|
103 |
-
msgid "Import Settings"
|
104 |
-
msgstr "Importiere Einstellungen"
|
105 |
-
|
106 |
-
#: apps/Backend/views/tools/tabs/import_export.php:22
|
107 |
-
msgid "Export"
|
108 |
-
msgstr "Exportieren"
|
109 |
-
|
110 |
-
#: apps/Backend/views/tools/tabs/import_export.php:5
|
111 |
-
msgid "Export Settings"
|
112 |
-
msgstr "Exportiere Einstellungen"
|
113 |
-
|
114 |
-
#: apps/Backend/views/settings/main-settings.php:290
|
115 |
-
msgid ""
|
116 |
-
"Check this box if you like WP Staging to check sizes of each directory on scanning process.\n"
|
117 |
-
" <br>\n"
|
118 |
-
" Warning this may cause timeout problems in big directory / file structures."
|
119 |
-
msgstr "Lasse WP Staging die Ordnergrösse bei jedem Scan Prozess überprüfen<br>Achtung, dies könnte bei großen Ordner / Datei Strukturen zu Timeout Problemen führen."
|
120 |
-
|
121 |
-
#: apps/Backend/views/settings/main-settings.php:275
|
122 |
-
msgid ""
|
123 |
-
"Check this box if you like WP Staging to completely remove all of its data when the plugin is deleted.\n"
|
124 |
-
" This will not remove staging sites files or database tables."
|
125 |
-
msgstr "Lösche alle Einstellungen beim Löschen des Plugins"
|
126 |
-
|
127 |
-
#: apps/Backend/views/settings/main-settings.php:261
|
128 |
-
msgid "The Optimizer is a mu plugin which disables all other plugins during WP Staging processing. Usually this makes the cloning process more reliable. If you experience issues, disable the Optimizer."
|
129 |
-
msgstr "Der Optimizer ist ein mu Plugin welches alle anderen Plugins während des Klonvorgangs deaktiviert. Gewöhnlich macht das den Klonvorgang sehr viel zuverlässiger. Deaktiviere diese Option wenn etwas nicht funktioniert."
|
130 |
-
|
131 |
-
#: apps/Backend/views/settings/main-settings.php:246
|
132 |
-
msgid ""
|
133 |
-
"This will enable an extended debug mode which creates additional entries\n"
|
134 |
-
" in <strong>wp-content/uploads/wp-staging/logs/logfile.log</strong>.\n"
|
135 |
-
" Please enable this when we ask you to do so."
|
136 |
-
msgstr "Dieser Modus schreibt zusätzliche Einträge in die Logdatei <strong>wp-content/uploads/wp-staging/logs/logfile.log</strong> Bitte aktiviere diesen Modus wenn Du ein Support Ticket eröffnest und wir Dich darum bitten."
|
137 |
-
|
138 |
-
#: apps/Backend/views/settings/main-settings.php:196
|
139 |
-
msgid ""
|
140 |
-
"Using high will result in fast as possible processing but the cpu load\n"
|
141 |
-
" increases and it's also possible that staging process gets interrupted because of too many ajax requests\n"
|
142 |
-
" (e.g. <strong>authorization error</strong>).\n"
|
143 |
-
" Using a lower value results in lower cpu load on your server but also slower staging site creation."
|
144 |
-
msgstr "Die Verwendung von \"High\" erstellt die Staging Seite am schnellsten aber die CPU Load erhöht sich und es ist möglich, dass der Staging Prozess aufgrund zu vieler Ajax Anfragen durch einen Timeout unterbrochen wird.Die Verwendungung einer niedrigeren Einstellung führt zu einer geringeren CPU Load, aber auch zu einer langsameren Verarbeitung."
|
145 |
-
|
146 |
-
#: apps/Backend/views/settings/main-settings.php:175
|
147 |
-
msgid ""
|
148 |
-
"Buffer size for the file copy process in megabyte.\n"
|
149 |
-
" The higher the value the faster large files are copied.\n"
|
150 |
-
" To find out the highest possible values try a high one and lower it until\n"
|
151 |
-
" you get no errors during file copy process. Usually this value correlates directly\n"
|
152 |
-
" with the memory consumption of php so make sure that\n"
|
153 |
-
" it does not exceed any php.ini max_memory limits."
|
154 |
-
msgstr "Buffer Grösse für den Datei Kopiervorgang in Megabyte. Je größer der Wert, desto schneller werden große Dateien kopiert. Größere Werte beeinflussen auch die maximale Speicherauslastung von PHP und sollte daher nicht zu gross gewählt werden."
|
155 |
-
|
156 |
-
#: apps/Backend/views/settings/main-settings.php:159
|
157 |
-
msgid ""
|
158 |
-
"Maximum size of the files which are allowed to copy. All files larger than this value will be skipped. \n"
|
159 |
-
" Note: Increase this option only if you have a good reason. Files larger than a few megabytes are in 99% of all cases logging and backup files which are not needed on a staging site."
|
160 |
-
msgstr "Maximale Dateigrösse welche noch kopiert wird. Alle Dateien größer als dieser Wert werden übersprungen. Hinweis: Erhöhe diese Option nur wenn Du einen guten Grund dazu hast. Dateien größer als ein einige Megabyte sind in 99% aller Fälle Log und Backup Dateien welche für eine Staging Seite nicht notwendig sind."
|
161 |
-
|
162 |
-
#: apps/Backend/views/settings/main-settings.php:142
|
163 |
-
msgid "<strong>Important:</strong> If CPU Load Priority is <strong>Low</strong> set a file copy limit value of 10 or higher! Otherwise file copying process takes a lot of time."
|
164 |
-
msgstr "<strong>Achtung</strong> Wenn die CPU Load Priority <strong>Low</strong> ist, setze das Datei Kopierlimit auf 10 oder höher! Andernfalls wird der Kopiervorgang sehr langsam sein."
|
165 |
-
|
166 |
-
#: apps/Backend/views/settings/main-settings.php:136
|
167 |
-
msgid ""
|
168 |
-
"Number of files to copy that will be copied within one ajax request.\n"
|
169 |
-
" The higher the value the faster the file copy process.\n"
|
170 |
-
" To find out the highest possible values try a high value like 500 or more. If you get timeout issues, lower it\n"
|
171 |
-
" until you get no more errors during copying process."
|
172 |
-
msgstr "Anzahl der Dateien, die mit einer Ajax Abfrage kopiert werden. Je höher der Wert, desto schneller ist der Kopiervorgang. "
|
173 |
-
|
174 |
-
#: apps/Backend/views/settings/main-settings.php:116
|
175 |
-
msgid ""
|
176 |
-
"Number of DB rows, that are processed within one ajax query.\n"
|
177 |
-
" The higher the value the faster the database search & replace process.\n"
|
178 |
-
" This is a high memory consumptive process. If you get timeouts lower this value!"
|
179 |
-
msgstr "Anzahl der Datenbank Einträge welche zugleich verarbeitet werden. Je grösser der Wert desto schneller ist der Suchen & Ersetzen Prozess."
|
180 |
-
|
181 |
-
#: apps/Backend/views/settings/main-settings.php:96
|
182 |
-
msgid ""
|
183 |
-
"Number of DB rows, that are copied within one ajax query.\n"
|
184 |
-
" The higher the value the faster the database copy process.\n"
|
185 |
-
" To find out the highest possible values try a high value like 1.000 or more. If you get timeout issues, lower it\n"
|
186 |
-
" until you get no more errors during copying process."
|
187 |
-
msgstr "Anzahl der Datenbank Einträge, die zugleich kopiert werden. Je höher der Wert, desto schneller wird die Datenbank kopiert. "
|
188 |
-
|
189 |
-
#: apps/Backend/views/clone/single-site/index.php:16
|
190 |
-
msgid "Report Issue"
|
191 |
-
msgstr "Fehlermeldung"
|
192 |
-
|
193 |
-
#: apps/Backend/views/clone/single-site/index.php:12
|
194 |
-
msgid "Cloning"
|
195 |
-
msgstr "Klonen"
|
196 |
-
|
197 |
-
#: apps/Backend/views/clone/single-site/index.php:8
|
198 |
-
msgid "Scanning"
|
199 |
-
msgstr "Scannen"
|
200 |
-
|
201 |
-
#: apps/Backend/views/clone/single-site/index.php:4
|
202 |
-
msgid "Overview"
|
203 |
-
msgstr "Überblick"
|
204 |
-
|
205 |
-
#: apps/Backend/views/clone/multi-site/index.php:2
|
206 |
-
msgid "WordPress Multisite is currently not supported!"
|
207 |
-
msgstr "WordPress Multisite wird nur WP Staging Pro unterstützt. "
|
208 |
-
|
209 |
-
#: apps/Backend/views/clone/ajax/update.php:17
|
210 |
-
msgid "Cancel Update"
|
211 |
-
msgstr "Abbruch Klonvorgang"
|
212 |
-
|
213 |
-
#: apps/Backend/views/clone/ajax/start.php:51
|
214 |
-
msgid "Important Notes:"
|
215 |
-
msgstr "Wichtige Hinweise"
|
216 |
-
|
217 |
-
#: apps/Backend/views/clone/ajax/start.php:47
|
218 |
-
msgid "Start again"
|
219 |
-
msgstr "Starte Neu"
|
220 |
-
|
221 |
-
#: apps/Backend/views/clone/ajax/start.php:35
|
222 |
-
msgid "WP Staging successfully created a staging site in a sub-directory of your main site accessable from:<br><strong><a href=\"%1$s\" target=\"_blank\" id=\"wpstg-clone-url-1\">%1$s</a></strong>"
|
223 |
-
msgstr ""
|
224 |
-
"WP Staging hat erfolgreich eine Staging Seite erstellt. Erreichbar über \n"
|
225 |
-
"<br><strong><a href=\"%1$s\" target=\"_blank\" id=\"wpstg-clone-url-1\">%1$s</a></strong>"
|
226 |
-
|
227 |
-
#: apps/Backend/views/clone/ajax/start.php:21
|
228 |
-
#: apps/Backend/views/clone/ajax/update.php:21
|
229 |
-
msgid "Display working log"
|
230 |
-
msgstr "Öffne Log Fenster"
|
231 |
-
|
232 |
-
#: apps/Backend/views/clone/ajax/start.php:2
|
233 |
-
#: apps/Backend/views/clone/ajax/update.php:2
|
234 |
-
msgid "Processing, please wait..."
|
235 |
-
msgstr "Verarbeite, bitte warten..."
|
236 |
-
|
237 |
-
#: apps/Backend/views/clone/ajax/single-overview.php:36
|
238 |
-
msgid "Delete"
|
239 |
-
msgstr "Löschen"
|
240 |
-
|
241 |
-
#: apps/Backend/views/clone/ajax/single-overview.php:32
|
242 |
-
msgid "Update"
|
243 |
-
msgstr "Aktualisieren"
|
244 |
-
|
245 |
-
#: apps/Backend/views/clone/ajax/single-overview.php:28
|
246 |
-
msgid "Open"
|
247 |
-
msgstr "Öffnen"
|
248 |
-
|
249 |
-
#: apps/Backend/views/clone/ajax/single-overview.php:11
|
250 |
-
msgid "Your Staging Sites:"
|
251 |
-
msgstr "Deine Staging Seiten"
|
252 |
-
|
253 |
-
#: apps/Backend/views/clone/ajax/single-overview.php:3
|
254 |
-
msgid "Create new staging site"
|
255 |
-
msgstr "Erstelle neue Staging Seite"
|
256 |
-
|
257 |
-
#: apps/Backend/views/clone/ajax/scan.php:142
|
258 |
-
msgid "Check Disk Space"
|
259 |
-
msgstr "Überprüfe Speicherplatz"
|
260 |
-
|
261 |
-
#: apps/Backend/views/clone/ajax/scan.php:134
|
262 |
-
msgid "Start Cloning"
|
263 |
-
msgstr "Starte Klonen"
|
264 |
-
|
265 |
-
#: apps/Backend/views/clone/ajax/scan.php:127
|
266 |
-
msgid "Update Clone"
|
267 |
-
msgstr "Aktualisiere Klon"
|
268 |
-
|
269 |
-
#: apps/Backend/views/clone/ajax/scan.php:121
|
270 |
-
msgid "Back"
|
271 |
-
msgstr "Zurück"
|
272 |
-
|
273 |
-
#: apps/Backend/views/clone/ajax/scan.php:110
|
274 |
-
msgid "<strong>If you do not do that step, the staging site could be unavailable!</strong>"
|
275 |
-
msgstr "<strong>Wenn Du diesen Schritt nicht durchführst könnte die Staging Seite nicht verfügbar sein</strong>"
|
276 |
-
|
277 |
-
#: apps/Backend/views/clone/ajax/scan.php:106
|
278 |
-
msgid "Set up first <a href=\"%1$s\"><strong>Login Custom Link</strong></a> if login to the admin dashboard is not reachable from the default url below:<pre>%2$s</pre>"
|
279 |
-
msgstr "Erstelle zunächst einen <a href=\"%1$s\"><strong>Login Custom Link</strong></a> wenn der Login auf das admin Dashboard nicht von der Default URL verfügbar ist:<pre>%2$s</pre>"
|
280 |
-
|
281 |
-
#: apps/Backend/views/clone/ajax/scan.php:104
|
282 |
-
msgid "<strong>Important:</strong> Are you using a custom login url?"
|
283 |
-
msgstr "<strong>Wichtig:</strong>Verwendest Du eine benutzerdefinierte Login URL?"
|
284 |
-
|
285 |
-
#: apps/Backend/views/clone/ajax/scan.php:89
|
286 |
-
msgid "All files will be copied to: "
|
287 |
-
msgstr "Alle Dateien werden kopiert nach:"
|
288 |
-
|
289 |
-
#: apps/Backend/views/clone/ajax/scan.php:69
|
290 |
-
msgid "Extra directories to copy"
|
291 |
-
msgstr "Extra Ordner zum Kopieren"
|
292 |
-
|
293 |
-
#: apps/Backend/views/clone/ajax/scan.php:63
|
294 |
-
msgid "Select folders to copy. Click on folder name to list subfolders!"
|
295 |
-
msgstr "Wähle Ordner zum Kopieren aus. Klicke auf Ordnernamen um Unterordner aufzulisten."
|
296 |
-
|
297 |
-
#: apps/Backend/views/clone/ajax/scan.php:58
|
298 |
-
msgid "Files"
|
299 |
-
msgstr "Dateien"
|
300 |
-
|
301 |
-
#: apps/Backend/views/clone/ajax/scan.php:17
|
302 |
-
msgid "DB Tables"
|
303 |
-
msgstr "Datenbank Tabellen"
|
304 |
-
|
305 |
-
#: apps/Backend/views/clone/ajax/scan.php:2
|
306 |
-
msgid "Staging Site Name:"
|
307 |
-
msgstr "Staging Seite Bezeichnung:"
|
308 |
-
|
309 |
-
#: apps/Backend/views/clone/ajax/delete-confirmation.php:85
|
310 |
-
msgid "Remove"
|
311 |
-
msgstr "Entferne"
|
312 |
-
|
313 |
-
#: apps/Backend/views/clone/ajax/delete-confirmation.php:81
|
314 |
-
#: apps/Backend/views/clone/ajax/start.php:17
|
315 |
-
msgid "Cancel"
|
316 |
-
msgstr "Abbruch"
|
317 |
-
|
318 |
-
#: apps/Backend/views/clone/ajax/delete-confirmation.php:66
|
319 |
-
msgid "The folder below and all of its subfolders will be deleted. Unselect the checkbox for not deleting the files."
|
320 |
-
msgstr "Der ausgewählte Ordner und alle Unterordner werden gelöscht. Abwählen um die Dateien nicht zu löschen."
|
321 |
-
|
322 |
-
#: apps/Backend/views/clone/ajax/delete-confirmation.php:60
|
323 |
-
msgid "Files to remove"
|
324 |
-
msgstr "Dateien die entfernt werden"
|
325 |
-
|
326 |
-
#: apps/Backend/views/clone/ajax/delete-confirmation.php:36
|
327 |
-
msgid "Unselect database tables you do not want to delete:"
|
328 |
-
msgstr "Wähle die Datenbank Tabellen ab, welche nicht gelöscht werden sollen"
|
329 |
-
|
330 |
-
#: apps/Backend/views/clone/ajax/delete-confirmation.php:30
|
331 |
-
msgid "DB tables to remove"
|
332 |
-
msgstr "Datenbank Tabellen die entfernt werden"
|
333 |
-
|
334 |
-
#: apps/Backend/views/clone/ajax/delete-confirmation.php:9
|
335 |
-
msgid "Clone name:"
|
336 |
-
msgstr "Klon Bezeichnung"
|
337 |
-
|
338 |
-
#: apps/Backend/views/clone/ajax/delete-confirmation.php:4
|
339 |
-
msgid "Attention: Check carefully if these database tables and files are safe to delete and do not belong to your live site!"
|
340 |
-
msgstr "Achtung: Überprüfe sorgfältig ob diese Datenbank Tabellen und Dateien sicher gelöscht werden dürfen und nicht zu Deiner Live Seite gehören!"
|
341 |
-
|
342 |
-
#: apps/Backend/views/_includes/report-issue.php:26
|
343 |
-
msgid "Send Issue"
|
344 |
-
msgstr "Abschicken"
|
345 |
-
|
346 |
-
#: apps/Backend/views/_includes/report-issue.php:20
|
347 |
-
msgid "By submitting, I accept the <a href=\"https://wp-staging.com/privacy-policy/\" target=\"_blank\">Privacy Policy</a> and consent that my email will be stored and processed for the purposes of proving support."
|
348 |
-
msgstr "Mit Übertragen akzeptiere ich die <a href=\"https://wp-staging.com/privacy-policy/\" target=\"_blank\">Datenschutz Vereinbarung</a> und erlaube, dass meine E-Mail Adresse gespeichert und verarbeitet wird um meine Support Anfrage zu beantworten."
|
349 |
-
|
350 |
-
#: apps/Backend/views/_includes/report-issue.php:12
|
351 |
-
msgid "Optional: Submit the <a href=\"%s\" target=\"_blank\">System Log</a>. This helps us to resolve your technical issues."
|
352 |
-
msgstr "Optional: Übertrage das <a href=\"%s\" target=\"_blank\">System Log</a>. Das hilft und Dein technisches Anliegen zu lösen."
|
353 |
-
|
354 |
-
#: apps/Backend/views/_includes/messages/staging-directory-permission-problem.php:4
|
355 |
-
msgid ""
|
356 |
-
"WP Staging Folder Permission error:</strong>\n"
|
357 |
-
" %1$s is not write and/or readable.\n"
|
358 |
-
" <br>\n"
|
359 |
-
" Check if the folder <strong>%1$s</strong> is writeable by php user www-data.\n"
|
360 |
-
" File permissions should be chmod 755 or 777."
|
361 |
-
msgstr ""
|
362 |
-
"WP Staging Dateirechte Fehler:</strong>\n"
|
363 |
-
" %1$s ist nicht schreib und/oder lesbar.\n"
|
364 |
-
" <br>\n"
|
365 |
-
" Überprüfe ob der Ordner <strong>%1$s</strong> beschreibbar ist vom PHP Benutzer www-data.\n"
|
366 |
-
" File permissions should be chmod 755 or 777."
|
367 |
-
|
368 |
-
#: apps/Backend/views/_includes/messages/rating.php:27
|
369 |
-
msgid "No, not good enough"
|
370 |
-
msgstr "Nein, nicht gut genug"
|
371 |
-
|
372 |
-
#: apps/Backend/views/_includes/messages/rating.php:22
|
373 |
-
msgid "I already did"
|
374 |
-
msgstr "Habe ich schon getan"
|
375 |
-
|
376 |
-
#: apps/Backend/views/_includes/messages/rating.php:17
|
377 |
-
msgid "Ok, you deserved it"
|
378 |
-
msgstr "Ok, hast Du verdient"
|
379 |
-
|
380 |
-
#: apps/Backend/views/_includes/messages/rating.php:5
|
381 |
-
msgid ""
|
382 |
-
"P.S. Looking for a way to migrate the staging site database and copy plugins and theme files from staging to live site?<br/>\n"
|
383 |
-
" Try out <a href=\"%1$s\" target=\"_blank\" style=\"color:white;font-weight:bold;\">WP Staging Pro</a>\n"
|
384 |
-
" "
|
385 |
-
msgstr ""
|
386 |
-
"P.S. Suchst Du einen Weg die Staging Seite auf Deine Live Seite zu übertragen?<br/>\n"
|
387 |
-
"Probiere <a href=\"%1$s\" target=\"_blank\" style=\"color:white;font-weight:bold;\">WP Staging Pro</a>\n"
|
388 |
-
" aus"
|
389 |
-
|
390 |
-
#: apps/Backend/views/_includes/messages/rating.php:2
|
391 |
-
msgid ""
|
392 |
-
" Awesome, you've been using <strong>WP Staging </strong> for more than 1 week.\n"
|
393 |
-
" May I ask you to give it a <strong>5-star</strong> rating on Wordpress?"
|
394 |
-
msgstr "Toll, Du verwendest <strong>WP Staging</strong> seit mehr als eine Woche. Darf ich Dich bitten eine 5-Sterne Bewertung auf WordPress.org abzugeben?"
|
395 |
-
|
396 |
-
#: apps/Backend/views/_includes/header.php:28
|
397 |
-
#: apps/Backend/views/settings/main-settings.php:29
|
398 |
-
msgid "Share on Facebook"
|
399 |
-
msgstr "Teile auf Facebook"
|
400 |
-
|
401 |
-
#: apps/Backend/views/_includes/header.php:21
|
402 |
-
#: apps/Backend/views/settings/main-settings.php:22
|
403 |
-
msgid "Follow @wpstaging"
|
404 |
-
msgstr "Folge @wpstaging"
|
405 |
-
|
406 |
-
#: apps/Backend/views/_includes/header.php:14
|
407 |
-
#: apps/Backend/views/settings/main-settings.php:15
|
408 |
-
msgid "Tweet #wpstaging"
|
409 |
-
msgstr "Tweet #wpstaging"
|
410 |
-
|
411 |
-
#: apps/Backend/Pluginmeta/Pluginmeta.php:63
|
412 |
-
msgid "Start Now"
|
413 |
-
msgstr "Jetzt Starten"
|
414 |
-
|
415 |
-
#: apps/Backend/Notices/Notices.php:145
|
416 |
-
#: apps/Backend/views/_includes/messages/transient.php:7
|
417 |
-
msgid "WP Staging and WP Staging Pro cannot both be active. We've automatically deactivated WP Staging Pro."
|
418 |
-
msgstr "WP Staging und WP Staging Pro können nicht beide gleichzeitig aktiv sein. Wir haben WP Staging Pro daher deaktiviert."
|
419 |
-
|
420 |
-
#: apps/Backend/Notices/Notices.php:143
|
421 |
-
#: apps/Backend/views/_includes/messages/transient.php:6
|
422 |
-
msgid "WP Staging and WP Staging Pro cannot both be active. We've automatically deactivated WP Staging."
|
423 |
-
msgstr "WP Staging und WP Staging Pro können nicht beide gleichzeitig aktiv sein. Wir haben WP Staging daher deaktiviert."
|
424 |
-
|
425 |
-
#: apps/Backend/Modules/Jobs/Directories.php:421
|
426 |
-
#: apps/Backend/Modules/Jobs/Multisite/Directories.php:485
|
427 |
-
msgid "Out of disk space."
|
428 |
-
msgstr "Kein freier Speicherplatz verfügbar"
|
429 |
-
|
430 |
-
#: apps/Backend/Modules/Jobs/Directories.php:417
|
431 |
-
#: apps/Backend/Modules/Jobs/Multisite/Directories.php:481
|
432 |
-
msgid "Unable to write to: %s"
|
433 |
-
msgstr "Nicht möglich in %s zu schreiben"
|
434 |
-
|
435 |
-
#: apps/Backend/Modules/Jobs/Directories.php:396
|
436 |
-
#: apps/Backend/Modules/Jobs/Multisite/Directories.php:460
|
437 |
-
msgid "Unable to open %s with mode %s"
|
438 |
-
msgstr "Kann nicht öffnen %s mit Modus %s"
|
439 |
-
|
440 |
-
#: apps/Backend/Administrator.php:296
|
441 |
-
msgid "Please upload a file to import"
|
442 |
-
msgstr "Bitte lade eine Datei zum importieren hoch"
|
443 |
-
|
444 |
-
#: apps/Backend/Administrator.php:246
|
445 |
-
msgid "System Info"
|
446 |
-
msgstr "System Info"
|
447 |
-
|
448 |
-
#: apps/Backend/Administrator.php:245
|
449 |
-
msgid "Import/Export"
|
450 |
-
msgstr "Import/Export"
|
451 |
-
|
452 |
-
#: apps/Backend/Administrator.php:208
|
453 |
-
msgid "General"
|
454 |
-
msgstr "Allgemein"
|
455 |
-
|
456 |
-
#: apps/Backend/Administrator.php:197
|
457 |
-
msgid "License"
|
458 |
-
msgstr "Lizenz"
|
459 |
-
|
460 |
-
#: apps/Backend/Administrator.php:197
|
461 |
-
msgid "WP Staging License"
|
462 |
-
msgstr "WP Staging Lizenz"
|
463 |
-
|
464 |
-
#: apps/Backend/Administrator.php:191
|
465 |
-
msgid "Get WP Staging Pro"
|
466 |
-
msgstr "Erhalte WP Staging Pro"
|
467 |
-
|
468 |
-
#: apps/Backend/Administrator.php:191
|
469 |
-
msgid "WP Staging Welcome"
|
470 |
-
msgstr "WP Staging Willkommen"
|
471 |
-
|
472 |
-
#: apps/Backend/Administrator.php:187
|
473 |
-
msgid "Tools"
|
474 |
-
msgstr "Werkzeuge"
|
475 |
-
|
476 |
-
#: apps/Backend/Administrator.php:187
|
477 |
-
msgid "WP Staging Tools"
|
478 |
-
msgstr "WP Staging Werkzeuge"
|
479 |
-
|
480 |
-
#: apps/Backend/Administrator.php:182 apps/Backend/Pluginmeta/Pluginmeta.php:42
|
481 |
-
msgid "Settings"
|
482 |
-
msgstr "Einstellungen"
|
483 |
-
|
484 |
-
#: apps/Backend/Administrator.php:182
|
485 |
-
msgid "WP Staging Settings"
|
486 |
-
msgstr "WP Staging Einstellungen"
|
487 |
-
|
488 |
-
#: apps/Backend/Administrator.php:177
|
489 |
-
msgid "Sites / Start"
|
490 |
-
msgstr "Seiten / Start"
|
491 |
-
|
492 |
-
#: apps/Backend/Administrator.php:177
|
493 |
-
msgid "WP Staging Jobs"
|
494 |
-
msgstr "WP Staging Jobs"
|
495 |
-
|
496 |
-
#. #-#-#-#-# wp-staging-code.pot (WP Staging 2.3.5) #-#-#-#-#
|
497 |
-
#. Plugin Name of the plugin/theme
|
498 |
-
#: apps/Backend/Administrator.php:172
|
499 |
-
msgid "WP Staging"
|
500 |
-
msgstr "WP Staging"
|
501 |
-
|
502 |
-
#: apps/Backend/Administrator.php:142
|
503 |
-
msgid "Settings updated."
|
504 |
msgstr "Einstellungen aktualisiert"
|
1 |
+
# Translation of Plugins - WP Staging – DB & File Duplicator & Migration - Stable (latest release) in German
|
2 |
+
# This file is distributed under the same license as the Plugins - WP Staging – DB & File Duplicator & Migration - Stable (latest release) package.
|
3 |
+
msgid ""
|
4 |
+
msgstr ""
|
5 |
+
"PO-Revision-Date: 2018-08-24 20:55:04+0000\n"
|
6 |
+
"MIME-Version: 1.0\n"
|
7 |
+
"Content-Type: text/plain; charset=UTF-8\n"
|
8 |
+
"Content-Transfer-Encoding: 8bit\n"
|
9 |
+
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
10 |
+
"X-Generator: GlotPress/2.4.0-alpha\n"
|
11 |
+
"Language: de\n"
|
12 |
+
"Project-Id-Version: Plugins - WP Staging – DB & File Duplicator & Migration - Stable (latest release)\n"
|
13 |
+
|
14 |
+
#. Author URI of the plugin/theme
|
15 |
+
msgid "https://wp-staging.com"
|
16 |
+
msgstr "https://wp-staging.com"
|
17 |
+
|
18 |
+
#. Author of the plugin/theme
|
19 |
+
msgid "WP-Staging"
|
20 |
+
msgstr "WP-Staging"
|
21 |
+
|
22 |
+
#. Description of the plugin/theme
|
23 |
+
msgid "Create a staging clone site for testing & developing"
|
24 |
+
msgstr "Erstelle eine Klon Webseite zum Testen und Entwickeln"
|
25 |
+
|
26 |
+
#. Plugin URI of the plugin/theme
|
27 |
+
msgid "https://wordpress.org/plugins/wp-staging"
|
28 |
+
msgstr "https://wordpress.org/plugins/wp-staging"
|
29 |
+
|
30 |
+
#: apps/Frontend/Frontend.php:88 apps/Frontend/loginForm.php:256
|
31 |
+
msgid "Log In"
|
32 |
+
msgstr "Anmelden"
|
33 |
+
|
34 |
+
#: apps/Frontend/Frontend.php:87 apps/Frontend/loginForm.php:255
|
35 |
+
msgid "Remember Me"
|
36 |
+
msgstr "Erinnere mich"
|
37 |
+
|
38 |
+
#: apps/Frontend/Frontend.php:86 apps/Frontend/loginForm.php:254
|
39 |
+
msgid "Password"
|
40 |
+
msgstr "Erinnere mich"
|
41 |
+
|
42 |
+
#: apps/Frontend/Frontend.php:85 apps/Frontend/loginForm.php:253
|
43 |
+
msgid "Username or Email Address"
|
44 |
+
msgstr "Benutzername oder E-Mail Adresse"
|
45 |
+
|
46 |
+
#: apps/Core/Utils/Report.php:31
|
47 |
+
msgid "Please accept our privacy policy."
|
48 |
+
msgstr "Bitte akzeptiere unsere Datenschutzvereinbarung"
|
49 |
+
|
50 |
+
#: apps/Core/Utils/Report.php:29
|
51 |
+
msgid "Please enter your issue."
|
52 |
+
msgstr "Bitte beschreibe Dein Problem"
|
53 |
+
|
54 |
+
#: apps/Core/Utils/Report.php:27
|
55 |
+
msgid "Email address is not valid."
|
56 |
+
msgstr "E-Mail Addresse ist nicht gültig"
|
57 |
+
|
58 |
+
#: apps/Core/Cron/Cron.php:35
|
59 |
+
msgid "Once a month"
|
60 |
+
msgstr "Einmal im Monat"
|
61 |
+
|
62 |
+
#: apps/Core/Cron/Cron.php:30
|
63 |
+
msgid "Once Weekly"
|
64 |
+
msgstr "Einmal wöchentlich"
|
65 |
+
|
66 |
+
#: apps/Backend/views/welcome/welcome.php:13
|
67 |
+
msgid "Comes with our 30-day no questions asked money back guarantee"
|
68 |
+
msgstr "Kommt mit unserer 30-Tage Geld zurück Garantie"
|
69 |
+
|
70 |
+
#: apps/Backend/views/welcome/welcome.php:10
|
71 |
+
msgid "WP Staging is coded well for protection of your data"
|
72 |
+
msgstr "WP Staging wurde sorgfältig entwickelt um Deine Daten zu schützen"
|
73 |
+
|
74 |
+
#: apps/Backend/views/welcome/welcome.php:9
|
75 |
+
msgid "Cloning process is fast and does not slow down website loading"
|
76 |
+
msgstr "Der Klonvorgang ist schnell und beeinflusst nicht die Webseite Ladezeit"
|
77 |
+
|
78 |
+
#: apps/Backend/views/welcome/welcome.php:8
|
79 |
+
msgid "Staging Site is available to authenticated users only"
|
80 |
+
msgstr "Staging Webseite ist nur für berechtigte Benutzer verfügbar"
|
81 |
+
|
82 |
+
#: apps/Backend/views/welcome/welcome.php:7
|
83 |
+
msgid "Copy plugin and theme files from staging to live site"
|
84 |
+
msgstr "Kopiere Plugin und Theme Dateien von der Staging auf die Live Seite"
|
85 |
+
|
86 |
+
#: apps/Backend/views/welcome/welcome.php:6
|
87 |
+
msgid "Create a clone of your website with a simple click"
|
88 |
+
msgstr "Erstelle einen Klon Deiner Webseite mit einem einfachen Klick"
|
89 |
+
|
90 |
+
#: apps/Backend/views/welcome/welcome.php:4
|
91 |
+
msgid " - Copy Themes & Plugins from Staging to Live Site"
|
92 |
+
msgstr "Kopiere Themes & Plugins von der Staging auf die Live Seite"
|
93 |
+
|
94 |
+
#: apps/Backend/views/welcome/welcome.php:4
|
95 |
+
msgid "WP Staging Pro"
|
96 |
+
msgstr "WP Staging Pro"
|
97 |
+
|
98 |
+
#: apps/Backend/views/tools/tabs/import_export.php:52
|
99 |
+
msgid "Import"
|
100 |
+
msgstr "Importieren"
|
101 |
+
|
102 |
+
#: apps/Backend/views/tools/tabs/import_export.php:33
|
103 |
+
msgid "Import Settings"
|
104 |
+
msgstr "Importiere Einstellungen"
|
105 |
+
|
106 |
+
#: apps/Backend/views/tools/tabs/import_export.php:22
|
107 |
+
msgid "Export"
|
108 |
+
msgstr "Exportieren"
|
109 |
+
|
110 |
+
#: apps/Backend/views/tools/tabs/import_export.php:5
|
111 |
+
msgid "Export Settings"
|
112 |
+
msgstr "Exportiere Einstellungen"
|
113 |
+
|
114 |
+
#: apps/Backend/views/settings/main-settings.php:290
|
115 |
+
msgid ""
|
116 |
+
"Check this box if you like WP Staging to check sizes of each directory on scanning process.\n"
|
117 |
+
" <br>\n"
|
118 |
+
" Warning this may cause timeout problems in big directory / file structures."
|
119 |
+
msgstr "Lasse WP Staging die Ordnergrösse bei jedem Scan Prozess überprüfen<br>Achtung, dies könnte bei großen Ordner / Datei Strukturen zu Timeout Problemen führen."
|
120 |
+
|
121 |
+
#: apps/Backend/views/settings/main-settings.php:275
|
122 |
+
msgid ""
|
123 |
+
"Check this box if you like WP Staging to completely remove all of its data when the plugin is deleted.\n"
|
124 |
+
" This will not remove staging sites files or database tables."
|
125 |
+
msgstr "Lösche alle Einstellungen beim Löschen des Plugins"
|
126 |
+
|
127 |
+
#: apps/Backend/views/settings/main-settings.php:261
|
128 |
+
msgid "The Optimizer is a mu plugin which disables all other plugins during WP Staging processing. Usually this makes the cloning process more reliable. If you experience issues, disable the Optimizer."
|
129 |
+
msgstr "Der Optimizer ist ein mu Plugin welches alle anderen Plugins während des Klonvorgangs deaktiviert. Gewöhnlich macht das den Klonvorgang sehr viel zuverlässiger. Deaktiviere diese Option wenn etwas nicht funktioniert."
|
130 |
+
|
131 |
+
#: apps/Backend/views/settings/main-settings.php:246
|
132 |
+
msgid ""
|
133 |
+
"This will enable an extended debug mode which creates additional entries\n"
|
134 |
+
" in <strong>wp-content/uploads/wp-staging/logs/logfile.log</strong>.\n"
|
135 |
+
" Please enable this when we ask you to do so."
|
136 |
+
msgstr "Dieser Modus schreibt zusätzliche Einträge in die Logdatei <strong>wp-content/uploads/wp-staging/logs/logfile.log</strong> Bitte aktiviere diesen Modus wenn Du ein Support Ticket eröffnest und wir Dich darum bitten."
|
137 |
+
|
138 |
+
#: apps/Backend/views/settings/main-settings.php:196
|
139 |
+
msgid ""
|
140 |
+
"Using high will result in fast as possible processing but the cpu load\n"
|
141 |
+
" increases and it's also possible that staging process gets interrupted because of too many ajax requests\n"
|
142 |
+
" (e.g. <strong>authorization error</strong>).\n"
|
143 |
+
" Using a lower value results in lower cpu load on your server but also slower staging site creation."
|
144 |
+
msgstr "Die Verwendung von \"High\" erstellt die Staging Seite am schnellsten aber die CPU Load erhöht sich und es ist möglich, dass der Staging Prozess aufgrund zu vieler Ajax Anfragen durch einen Timeout unterbrochen wird.Die Verwendungung einer niedrigeren Einstellung führt zu einer geringeren CPU Load, aber auch zu einer langsameren Verarbeitung."
|
145 |
+
|
146 |
+
#: apps/Backend/views/settings/main-settings.php:175
|
147 |
+
msgid ""
|
148 |
+
"Buffer size for the file copy process in megabyte.\n"
|
149 |
+
" The higher the value the faster large files are copied.\n"
|
150 |
+
" To find out the highest possible values try a high one and lower it until\n"
|
151 |
+
" you get no errors during file copy process. Usually this value correlates directly\n"
|
152 |
+
" with the memory consumption of php so make sure that\n"
|
153 |
+
" it does not exceed any php.ini max_memory limits."
|
154 |
+
msgstr "Buffer Grösse für den Datei Kopiervorgang in Megabyte. Je größer der Wert, desto schneller werden große Dateien kopiert. Größere Werte beeinflussen auch die maximale Speicherauslastung von PHP und sollte daher nicht zu gross gewählt werden."
|
155 |
+
|
156 |
+
#: apps/Backend/views/settings/main-settings.php:159
|
157 |
+
msgid ""
|
158 |
+
"Maximum size of the files which are allowed to copy. All files larger than this value will be skipped. \n"
|
159 |
+
" Note: Increase this option only if you have a good reason. Files larger than a few megabytes are in 99% of all cases logging and backup files which are not needed on a staging site."
|
160 |
+
msgstr "Maximale Dateigrösse welche noch kopiert wird. Alle Dateien größer als dieser Wert werden übersprungen. Hinweis: Erhöhe diese Option nur wenn Du einen guten Grund dazu hast. Dateien größer als ein einige Megabyte sind in 99% aller Fälle Log und Backup Dateien welche für eine Staging Seite nicht notwendig sind."
|
161 |
+
|
162 |
+
#: apps/Backend/views/settings/main-settings.php:142
|
163 |
+
msgid "<strong>Important:</strong> If CPU Load Priority is <strong>Low</strong> set a file copy limit value of 10 or higher! Otherwise file copying process takes a lot of time."
|
164 |
+
msgstr "<strong>Achtung</strong> Wenn die CPU Load Priority <strong>Low</strong> ist, setze das Datei Kopierlimit auf 10 oder höher! Andernfalls wird der Kopiervorgang sehr langsam sein."
|
165 |
+
|
166 |
+
#: apps/Backend/views/settings/main-settings.php:136
|
167 |
+
msgid ""
|
168 |
+
"Number of files to copy that will be copied within one ajax request.\n"
|
169 |
+
" The higher the value the faster the file copy process.\n"
|
170 |
+
" To find out the highest possible values try a high value like 500 or more. If you get timeout issues, lower it\n"
|
171 |
+
" until you get no more errors during copying process."
|
172 |
+
msgstr "Anzahl der Dateien, die mit einer Ajax Abfrage kopiert werden. Je höher der Wert, desto schneller ist der Kopiervorgang. "
|
173 |
+
|
174 |
+
#: apps/Backend/views/settings/main-settings.php:116
|
175 |
+
msgid ""
|
176 |
+
"Number of DB rows, that are processed within one ajax query.\n"
|
177 |
+
" The higher the value the faster the database search & replace process.\n"
|
178 |
+
" This is a high memory consumptive process. If you get timeouts lower this value!"
|
179 |
+
msgstr "Anzahl der Datenbank Einträge welche zugleich verarbeitet werden. Je grösser der Wert desto schneller ist der Suchen & Ersetzen Prozess."
|
180 |
+
|
181 |
+
#: apps/Backend/views/settings/main-settings.php:96
|
182 |
+
msgid ""
|
183 |
+
"Number of DB rows, that are copied within one ajax query.\n"
|
184 |
+
" The higher the value the faster the database copy process.\n"
|
185 |
+
" To find out the highest possible values try a high value like 1.000 or more. If you get timeout issues, lower it\n"
|
186 |
+
" until you get no more errors during copying process."
|
187 |
+
msgstr "Anzahl der Datenbank Einträge, die zugleich kopiert werden. Je höher der Wert, desto schneller wird die Datenbank kopiert. "
|
188 |
+
|
189 |
+
#: apps/Backend/views/clone/single-site/index.php:16
|
190 |
+
msgid "Report Issue"
|
191 |
+
msgstr "Fehlermeldung"
|
192 |
+
|
193 |
+
#: apps/Backend/views/clone/single-site/index.php:12
|
194 |
+
msgid "Cloning"
|
195 |
+
msgstr "Klonen"
|
196 |
+
|
197 |
+
#: apps/Backend/views/clone/single-site/index.php:8
|
198 |
+
msgid "Scanning"
|
199 |
+
msgstr "Scannen"
|
200 |
+
|
201 |
+
#: apps/Backend/views/clone/single-site/index.php:4
|
202 |
+
msgid "Overview"
|
203 |
+
msgstr "Überblick"
|
204 |
+
|
205 |
+
#: apps/Backend/views/clone/multi-site/index.php:2
|
206 |
+
msgid "WordPress Multisite is currently not supported!"
|
207 |
+
msgstr "WordPress Multisite wird nur WP Staging Pro unterstützt. "
|
208 |
+
|
209 |
+
#: apps/Backend/views/clone/ajax/update.php:17
|
210 |
+
msgid "Cancel Update"
|
211 |
+
msgstr "Abbruch Klonvorgang"
|
212 |
+
|
213 |
+
#: apps/Backend/views/clone/ajax/start.php:51
|
214 |
+
msgid "Important Notes:"
|
215 |
+
msgstr "Wichtige Hinweise"
|
216 |
+
|
217 |
+
#: apps/Backend/views/clone/ajax/start.php:47
|
218 |
+
msgid "Start again"
|
219 |
+
msgstr "Starte Neu"
|
220 |
+
|
221 |
+
#: apps/Backend/views/clone/ajax/start.php:35
|
222 |
+
msgid "WP Staging successfully created a staging site in a sub-directory of your main site accessable from:<br><strong><a href=\"%1$s\" target=\"_blank\" id=\"wpstg-clone-url-1\">%1$s</a></strong>"
|
223 |
+
msgstr ""
|
224 |
+
"WP Staging hat erfolgreich eine Staging Seite erstellt. Erreichbar über \n"
|
225 |
+
"<br><strong><a href=\"%1$s\" target=\"_blank\" id=\"wpstg-clone-url-1\">%1$s</a></strong>"
|
226 |
+
|
227 |
+
#: apps/Backend/views/clone/ajax/start.php:21
|
228 |
+
#: apps/Backend/views/clone/ajax/update.php:21
|
229 |
+
msgid "Display working log"
|
230 |
+
msgstr "Öffne Log Fenster"
|
231 |
+
|
232 |
+
#: apps/Backend/views/clone/ajax/start.php:2
|
233 |
+
#: apps/Backend/views/clone/ajax/update.php:2
|
234 |
+
msgid "Processing, please wait..."
|
235 |
+
msgstr "Verarbeite, bitte warten..."
|
236 |
+
|
237 |
+
#: apps/Backend/views/clone/ajax/single-overview.php:36
|
238 |
+
msgid "Delete"
|
239 |
+
msgstr "Löschen"
|
240 |
+
|
241 |
+
#: apps/Backend/views/clone/ajax/single-overview.php:32
|
242 |
+
msgid "Update"
|
243 |
+
msgstr "Aktualisieren"
|
244 |
+
|
245 |
+
#: apps/Backend/views/clone/ajax/single-overview.php:28
|
246 |
+
msgid "Open"
|
247 |
+
msgstr "Öffnen"
|
248 |
+
|
249 |
+
#: apps/Backend/views/clone/ajax/single-overview.php:11
|
250 |
+
msgid "Your Staging Sites:"
|
251 |
+
msgstr "Deine Staging Seiten"
|
252 |
+
|
253 |
+
#: apps/Backend/views/clone/ajax/single-overview.php:3
|
254 |
+
msgid "Create new staging site"
|
255 |
+
msgstr "Erstelle neue Staging Seite"
|
256 |
+
|
257 |
+
#: apps/Backend/views/clone/ajax/scan.php:142
|
258 |
+
msgid "Check Disk Space"
|
259 |
+
msgstr "Überprüfe Speicherplatz"
|
260 |
+
|
261 |
+
#: apps/Backend/views/clone/ajax/scan.php:134
|
262 |
+
msgid "Start Cloning"
|
263 |
+
msgstr "Starte Klonen"
|
264 |
+
|
265 |
+
#: apps/Backend/views/clone/ajax/scan.php:127
|
266 |
+
msgid "Update Clone"
|
267 |
+
msgstr "Aktualisiere Klon"
|
268 |
+
|
269 |
+
#: apps/Backend/views/clone/ajax/scan.php:121
|
270 |
+
msgid "Back"
|
271 |
+
msgstr "Zurück"
|
272 |
+
|
273 |
+
#: apps/Backend/views/clone/ajax/scan.php:110
|
274 |
+
msgid "<strong>If you do not do that step, the staging site could be unavailable!</strong>"
|
275 |
+
msgstr "<strong>Wenn Du diesen Schritt nicht durchführst könnte die Staging Seite nicht verfügbar sein</strong>"
|
276 |
+
|
277 |
+
#: apps/Backend/views/clone/ajax/scan.php:106
|
278 |
+
msgid "Set up first <a href=\"%1$s\"><strong>Login Custom Link</strong></a> if login to the admin dashboard is not reachable from the default url below:<pre>%2$s</pre>"
|
279 |
+
msgstr "Erstelle zunächst einen <a href=\"%1$s\"><strong>Login Custom Link</strong></a> wenn der Login auf das admin Dashboard nicht von der Default URL verfügbar ist:<pre>%2$s</pre>"
|
280 |
+
|
281 |
+
#: apps/Backend/views/clone/ajax/scan.php:104
|
282 |
+
msgid "<strong>Important:</strong> Are you using a custom login url?"
|
283 |
+
msgstr "<strong>Wichtig:</strong>Verwendest Du eine benutzerdefinierte Login URL?"
|
284 |
+
|
285 |
+
#: apps/Backend/views/clone/ajax/scan.php:89
|
286 |
+
msgid "All files will be copied to: "
|
287 |
+
msgstr "Alle Dateien werden kopiert nach:"
|
288 |
+
|
289 |
+
#: apps/Backend/views/clone/ajax/scan.php:69
|
290 |
+
msgid "Extra directories to copy"
|
291 |
+
msgstr "Extra Ordner zum Kopieren"
|
292 |
+
|
293 |
+
#: apps/Backend/views/clone/ajax/scan.php:63
|
294 |
+
msgid "Select folders to copy. Click on folder name to list subfolders!"
|
295 |
+
msgstr "Wähle Ordner zum Kopieren aus. Klicke auf Ordnernamen um Unterordner aufzulisten."
|
296 |
+
|
297 |
+
#: apps/Backend/views/clone/ajax/scan.php:58
|
298 |
+
msgid "Files"
|
299 |
+
msgstr "Dateien"
|
300 |
+
|
301 |
+
#: apps/Backend/views/clone/ajax/scan.php:17
|
302 |
+
msgid "DB Tables"
|
303 |
+
msgstr "Datenbank Tabellen"
|
304 |
+
|
305 |
+
#: apps/Backend/views/clone/ajax/scan.php:2
|
306 |
+
msgid "Staging Site Name:"
|
307 |
+
msgstr "Staging Seite Bezeichnung:"
|
308 |
+
|
309 |
+
#: apps/Backend/views/clone/ajax/delete-confirmation.php:85
|
310 |
+
msgid "Remove"
|
311 |
+
msgstr "Entferne"
|
312 |
+
|
313 |
+
#: apps/Backend/views/clone/ajax/delete-confirmation.php:81
|
314 |
+
#: apps/Backend/views/clone/ajax/start.php:17
|
315 |
+
msgid "Cancel"
|
316 |
+
msgstr "Abbruch"
|
317 |
+
|
318 |
+
#: apps/Backend/views/clone/ajax/delete-confirmation.php:66
|
319 |
+
msgid "The folder below and all of its subfolders will be deleted. Unselect the checkbox for not deleting the files."
|
320 |
+
msgstr "Der ausgewählte Ordner und alle Unterordner werden gelöscht. Abwählen um die Dateien nicht zu löschen."
|
321 |
+
|
322 |
+
#: apps/Backend/views/clone/ajax/delete-confirmation.php:60
|
323 |
+
msgid "Files to remove"
|
324 |
+
msgstr "Dateien die entfernt werden"
|
325 |
+
|
326 |
+
#: apps/Backend/views/clone/ajax/delete-confirmation.php:36
|
327 |
+
msgid "Unselect database tables you do not want to delete:"
|
328 |
+
msgstr "Wähle die Datenbank Tabellen ab, welche nicht gelöscht werden sollen"
|
329 |
+
|
330 |
+
#: apps/Backend/views/clone/ajax/delete-confirmation.php:30
|
331 |
+
msgid "DB tables to remove"
|
332 |
+
msgstr "Datenbank Tabellen die entfernt werden"
|
333 |
+
|
334 |
+
#: apps/Backend/views/clone/ajax/delete-confirmation.php:9
|
335 |
+
msgid "Clone name:"
|
336 |
+
msgstr "Klon Bezeichnung"
|
337 |
+
|
338 |
+
#: apps/Backend/views/clone/ajax/delete-confirmation.php:4
|
339 |
+
msgid "Attention: Check carefully if these database tables and files are safe to delete and do not belong to your live site!"
|
340 |
+
msgstr "Achtung: Überprüfe sorgfältig ob diese Datenbank Tabellen und Dateien sicher gelöscht werden dürfen und nicht zu Deiner Live Seite gehören!"
|
341 |
+
|
342 |
+
#: apps/Backend/views/_includes/report-issue.php:26
|
343 |
+
msgid "Send Issue"
|
344 |
+
msgstr "Abschicken"
|
345 |
+
|
346 |
+
#: apps/Backend/views/_includes/report-issue.php:20
|
347 |
+
msgid "By submitting, I accept the <a href=\"https://wp-staging.com/privacy-policy/\" target=\"_blank\">Privacy Policy</a> and consent that my email will be stored and processed for the purposes of proving support."
|
348 |
+
msgstr "Mit Übertragen akzeptiere ich die <a href=\"https://wp-staging.com/privacy-policy/\" target=\"_blank\">Datenschutz Vereinbarung</a> und erlaube, dass meine E-Mail Adresse gespeichert und verarbeitet wird um meine Support Anfrage zu beantworten."
|
349 |
+
|
350 |
+
#: apps/Backend/views/_includes/report-issue.php:12
|
351 |
+
msgid "Optional: Submit the <a href=\"%s\" target=\"_blank\">System Log</a>. This helps us to resolve your technical issues."
|
352 |
+
msgstr "Optional: Übertrage das <a href=\"%s\" target=\"_blank\">System Log</a>. Das hilft und Dein technisches Anliegen zu lösen."
|
353 |
+
|
354 |
+
#: apps/Backend/views/_includes/messages/staging-directory-permission-problem.php:4
|
355 |
+
msgid ""
|
356 |
+
"WP Staging Folder Permission error:</strong>\n"
|
357 |
+
" %1$s is not write and/or readable.\n"
|
358 |
+
" <br>\n"
|
359 |
+
" Check if the folder <strong>%1$s</strong> is writeable by php user www-data.\n"
|
360 |
+
" File permissions should be chmod 755 or 777."
|
361 |
+
msgstr ""
|
362 |
+
"WP Staging Dateirechte Fehler:</strong>\n"
|
363 |
+
" %1$s ist nicht schreib und/oder lesbar.\n"
|
364 |
+
" <br>\n"
|
365 |
+
" Überprüfe ob der Ordner <strong>%1$s</strong> beschreibbar ist vom PHP Benutzer www-data.\n"
|
366 |
+
" File permissions should be chmod 755 or 777."
|
367 |
+
|
368 |
+
#: apps/Backend/views/_includes/messages/rating.php:27
|
369 |
+
msgid "No, not good enough"
|
370 |
+
msgstr "Nein, nicht gut genug"
|
371 |
+
|
372 |
+
#: apps/Backend/views/_includes/messages/rating.php:22
|
373 |
+
msgid "I already did"
|
374 |
+
msgstr "Habe ich schon getan"
|
375 |
+
|
376 |
+
#: apps/Backend/views/_includes/messages/rating.php:17
|
377 |
+
msgid "Ok, you deserved it"
|
378 |
+
msgstr "Ok, hast Du verdient"
|
379 |
+
|
380 |
+
#: apps/Backend/views/_includes/messages/rating.php:5
|
381 |
+
msgid ""
|
382 |
+
"P.S. Looking for a way to migrate the staging site database and copy plugins and theme files from staging to live site?<br/>\n"
|
383 |
+
" Try out <a href=\"%1$s\" target=\"_blank\" style=\"color:white;font-weight:bold;\">WP Staging Pro</a>\n"
|
384 |
+
" "
|
385 |
+
msgstr ""
|
386 |
+
"P.S. Suchst Du einen Weg die Staging Seite auf Deine Live Seite zu übertragen?<br/>\n"
|
387 |
+
"Probiere <a href=\"%1$s\" target=\"_blank\" style=\"color:white;font-weight:bold;\">WP Staging Pro</a>\n"
|
388 |
+
" aus"
|
389 |
+
|
390 |
+
#: apps/Backend/views/_includes/messages/rating.php:2
|
391 |
+
msgid ""
|
392 |
+
" Awesome, you've been using <strong>WP Staging </strong> for more than 1 week.\n"
|
393 |
+
" May I ask you to give it a <strong>5-star</strong> rating on Wordpress?"
|
394 |
+
msgstr "Toll, Du verwendest <strong>WP Staging</strong> seit mehr als eine Woche. Darf ich Dich bitten eine 5-Sterne Bewertung auf WordPress.org abzugeben?"
|
395 |
+
|
396 |
+
#: apps/Backend/views/_includes/header.php:28
|
397 |
+
#: apps/Backend/views/settings/main-settings.php:29
|
398 |
+
msgid "Share on Facebook"
|
399 |
+
msgstr "Teile auf Facebook"
|
400 |
+
|
401 |
+
#: apps/Backend/views/_includes/header.php:21
|
402 |
+
#: apps/Backend/views/settings/main-settings.php:22
|
403 |
+
msgid "Follow @wpstaging"
|
404 |
+
msgstr "Folge @wpstaging"
|
405 |
+
|
406 |
+
#: apps/Backend/views/_includes/header.php:14
|
407 |
+
#: apps/Backend/views/settings/main-settings.php:15
|
408 |
+
msgid "Tweet #wpstaging"
|
409 |
+
msgstr "Tweet #wpstaging"
|
410 |
+
|
411 |
+
#: apps/Backend/Pluginmeta/Pluginmeta.php:63
|
412 |
+
msgid "Start Now"
|
413 |
+
msgstr "Jetzt Starten"
|
414 |
+
|
415 |
+
#: apps/Backend/Notices/Notices.php:145
|
416 |
+
#: apps/Backend/views/_includes/messages/transient.php:7
|
417 |
+
msgid "WP Staging and WP Staging Pro cannot both be active. We've automatically deactivated WP Staging Pro."
|
418 |
+
msgstr "WP Staging und WP Staging Pro können nicht beide gleichzeitig aktiv sein. Wir haben WP Staging Pro daher deaktiviert."
|
419 |
+
|
420 |
+
#: apps/Backend/Notices/Notices.php:143
|
421 |
+
#: apps/Backend/views/_includes/messages/transient.php:6
|
422 |
+
msgid "WP Staging and WP Staging Pro cannot both be active. We've automatically deactivated WP Staging."
|
423 |
+
msgstr "WP Staging und WP Staging Pro können nicht beide gleichzeitig aktiv sein. Wir haben WP Staging daher deaktiviert."
|
424 |
+
|
425 |
+
#: apps/Backend/Modules/Jobs/Directories.php:421
|
426 |
+
#: apps/Backend/Modules/Jobs/Multisite/Directories.php:485
|
427 |
+
msgid "Out of disk space."
|
428 |
+
msgstr "Kein freier Speicherplatz verfügbar"
|
429 |
+
|
430 |
+
#: apps/Backend/Modules/Jobs/Directories.php:417
|
431 |
+
#: apps/Backend/Modules/Jobs/Multisite/Directories.php:481
|
432 |
+
msgid "Unable to write to: %s"
|
433 |
+
msgstr "Nicht möglich in %s zu schreiben"
|
434 |
+
|
435 |
+
#: apps/Backend/Modules/Jobs/Directories.php:396
|
436 |
+
#: apps/Backend/Modules/Jobs/Multisite/Directories.php:460
|
437 |
+
msgid "Unable to open %s with mode %s"
|
438 |
+
msgstr "Kann nicht öffnen %s mit Modus %s"
|
439 |
+
|
440 |
+
#: apps/Backend/Administrator.php:296
|
441 |
+
msgid "Please upload a file to import"
|
442 |
+
msgstr "Bitte lade eine Datei zum importieren hoch"
|
443 |
+
|
444 |
+
#: apps/Backend/Administrator.php:246
|
445 |
+
msgid "System Info"
|
446 |
+
msgstr "System Info"
|
447 |
+
|
448 |
+
#: apps/Backend/Administrator.php:245
|
449 |
+
msgid "Import/Export"
|
450 |
+
msgstr "Import/Export"
|
451 |
+
|
452 |
+
#: apps/Backend/Administrator.php:208
|
453 |
+
msgid "General"
|
454 |
+
msgstr "Allgemein"
|
455 |
+
|
456 |
+
#: apps/Backend/Administrator.php:197
|
457 |
+
msgid "License"
|
458 |
+
msgstr "Lizenz"
|
459 |
+
|
460 |
+
#: apps/Backend/Administrator.php:197
|
461 |
+
msgid "WP Staging License"
|
462 |
+
msgstr "WP Staging Lizenz"
|
463 |
+
|
464 |
+
#: apps/Backend/Administrator.php:191
|
465 |
+
msgid "Get WP Staging Pro"
|
466 |
+
msgstr "Erhalte WP Staging Pro"
|
467 |
+
|
468 |
+
#: apps/Backend/Administrator.php:191
|
469 |
+
msgid "WP Staging Welcome"
|
470 |
+
msgstr "WP Staging Willkommen"
|
471 |
+
|
472 |
+
#: apps/Backend/Administrator.php:187
|
473 |
+
msgid "Tools"
|
474 |
+
msgstr "Werkzeuge"
|
475 |
+
|
476 |
+
#: apps/Backend/Administrator.php:187
|
477 |
+
msgid "WP Staging Tools"
|
478 |
+
msgstr "WP Staging Werkzeuge"
|
479 |
+
|
480 |
+
#: apps/Backend/Administrator.php:182 apps/Backend/Pluginmeta/Pluginmeta.php:42
|
481 |
+
msgid "Settings"
|
482 |
+
msgstr "Einstellungen"
|
483 |
+
|
484 |
+
#: apps/Backend/Administrator.php:182
|
485 |
+
msgid "WP Staging Settings"
|
486 |
+
msgstr "WP Staging Einstellungen"
|
487 |
+
|
488 |
+
#: apps/Backend/Administrator.php:177
|
489 |
+
msgid "Sites / Start"
|
490 |
+
msgstr "Seiten / Start"
|
491 |
+
|
492 |
+
#: apps/Backend/Administrator.php:177
|
493 |
+
msgid "WP Staging Jobs"
|
494 |
+
msgstr "WP Staging Jobs"
|
495 |
+
|
496 |
+
#. #-#-#-#-# wp-staging-code.pot (WP Staging 2.3.5) #-#-#-#-#
|
497 |
+
#. Plugin Name of the plugin/theme
|
498 |
+
#: apps/Backend/Administrator.php:172
|
499 |
+
msgid "WP Staging"
|
500 |
+
msgstr "WP Staging"
|
501 |
+
|
502 |
+
#: apps/Backend/Administrator.php:142
|
503 |
+
msgid "Settings updated."
|
504 |
msgstr "Einstellungen aktualisiert"
|
languages/wp-staging-en_gb.po
CHANGED
@@ -1,418 +1,418 @@
|
|
1 |
-
# Translation of Plugins - WP Staging – DB & File Duplicator & Migration - Stable Readme (latest release) in English (UK)
|
2 |
-
# This file is distributed under the same license as the Plugins - WP Staging – DB & File Duplicator & Migration - Stable Readme (latest release) package.
|
3 |
-
msgid ""
|
4 |
-
msgstr ""
|
5 |
-
"PO-Revision-Date: 2015-12-01 15:35:13+0000\n"
|
6 |
-
"MIME-Version: 1.0\n"
|
7 |
-
"Content-Type: text/plain; charset=UTF-8\n"
|
8 |
-
"Content-Transfer-Encoding: 8bit\n"
|
9 |
-
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
10 |
-
"X-Generator: GlotPress/2.4.0-alpha\n"
|
11 |
-
"Language: en_GB\n"
|
12 |
-
"Project-Id-Version: Plugins - WP Staging – DB & File Duplicator & Migration - Stable Readme (latest release)\n"
|
13 |
-
|
14 |
-
#. Short description.
|
15 |
-
msgid "A duplicator plugin! Clone, duplicate and migrate live sites to independent staging and development sites that are available only to administrators."
|
16 |
-
msgstr ""
|
17 |
-
|
18 |
-
#. Plugin name.
|
19 |
-
msgid "WP Staging - DB & File Duplicator & Migration"
|
20 |
-
msgstr ""
|
21 |
-
|
22 |
-
#. Found in changelog list item.
|
23 |
-
msgid "Fix: Missing http(s) scheme after cloning multisites results in not working clones"
|
24 |
-
msgstr ""
|
25 |
-
|
26 |
-
#. Found in changelog list item.
|
27 |
-
msgid "New: Support for Windows Azure cloud servers"
|
28 |
-
msgstr ""
|
29 |
-
|
30 |
-
#. Found in changelog list item.
|
31 |
-
msgid "Fix: Do not search & replace mail addresses"
|
32 |
-
msgstr ""
|
33 |
-
|
34 |
-
#. Found in changelog list item.
|
35 |
-
msgid "Fix: Remove term 'Error' from login page"
|
36 |
-
msgstr ""
|
37 |
-
|
38 |
-
#. Found in changelog list item.
|
39 |
-
msgid "New: Login options not needed any more - removed"
|
40 |
-
msgstr ""
|
41 |
-
|
42 |
-
#. Found in changelog list item.
|
43 |
-
msgid "New: Detect if wp-config.php has been moved one folder level up"
|
44 |
-
msgstr ""
|
45 |
-
|
46 |
-
#. Found in changelog list item.
|
47 |
-
msgid "New: Better error reporting"
|
48 |
-
msgstr ""
|
49 |
-
|
50 |
-
#. Found in changelog list item.
|
51 |
-
msgid "New: Compatible up to WordPress 4.9.8"
|
52 |
-
msgstr ""
|
53 |
-
|
54 |
-
#. Found in changelog list item.
|
55 |
-
msgid "New: Setting to specify the maximum allowed file size to copy"
|
56 |
-
msgstr ""
|
57 |
-
|
58 |
-
#. Found in changelog list item.
|
59 |
-
msgid "Fix: Search & replace path not correct if scheme http/https is not identical in wp-config and db wp_options"
|
60 |
-
msgstr ""
|
61 |
-
|
62 |
-
#. Found in changelog list item.
|
63 |
-
msgid "Fix: Creating a new clone resets the custom wp staging user settings. E.g. ignores authentication setting"
|
64 |
-
msgstr ""
|
65 |
-
|
66 |
-
#. Found in changelog list item.
|
67 |
-
msgid "Tweak: Remove certain debugging notices from the default log window"
|
68 |
-
msgstr ""
|
69 |
-
|
70 |
-
#. Found in changelog list item.
|
71 |
-
msgid "Tweaks: remove term \"error\" from several log entries"
|
72 |
-
msgstr ""
|
73 |
-
|
74 |
-
#. Found in changelog list item.
|
75 |
-
msgid "Fix: Search & Replace not working if serialized object contains __PHP_Incomplete_Class_Name"
|
76 |
-
msgstr ""
|
77 |
-
|
78 |
-
#. Found in changelog list item.
|
79 |
-
msgid "Fix: Skip search & replace for objects where key is null"
|
80 |
-
msgstr ""
|
81 |
-
|
82 |
-
#. Found in changelog list item.
|
83 |
-
msgid "Fix: Parameter must be an array or an object that implements Callable"
|
84 |
-
msgstr ""
|
85 |
-
|
86 |
-
#. Found in changelog list item.
|
87 |
-
msgid "Fix: wp-config.php not copied when previous clone updating process has been failed"
|
88 |
-
msgstr ""
|
89 |
-
|
90 |
-
#. Found in changelog list item.
|
91 |
-
msgid "Fix: Undefined object $this->tables"
|
92 |
-
msgstr ""
|
93 |
-
|
94 |
-
#. Found in changelog list item.
|
95 |
-
msgid "Fix: Can not open upload folder in file selection menu"
|
96 |
-
msgstr ""
|
97 |
-
|
98 |
-
#. Found in changelog list item.
|
99 |
-
msgid "Fix: Progress bar not shown as intented for clone updating process"
|
100 |
-
msgstr ""
|
101 |
-
|
102 |
-
#. Found in changelog list item.
|
103 |
-
msgid "Fix: If cloning update process is interupted it may happen that staging site is not available any longer. (Updating the clone does not copy index.php to staging site again)"
|
104 |
-
msgstr ""
|
105 |
-
|
106 |
-
#. Found in changelog list item.
|
107 |
-
msgid "Fix: Progress bar for step 'database' is not filling up to 100%"
|
108 |
-
msgstr ""
|
109 |
-
|
110 |
-
#. Found in changelog list item.
|
111 |
-
msgid "New: Use the new progress bar for clone updating process"
|
112 |
-
msgstr ""
|
113 |
-
|
114 |
-
#. Found in changelog list item.
|
115 |
-
msgid "New: Add multisite informations in system info log"
|
116 |
-
msgstr ""
|
117 |
-
|
118 |
-
#. Found in changelog list item.
|
119 |
-
msgid "New: Option to allow adjustment of the allowed maximum size of files that are going to be copied while cloning."
|
120 |
-
msgstr ""
|
121 |
-
|
122 |
-
#. Found in changelog list item.
|
123 |
-
msgid "Security: Do not allow to create a new staging site into a subfolder which already exists"
|
124 |
-
msgstr ""
|
125 |
-
|
126 |
-
#. Found in changelog list item.
|
127 |
-
msgid "Fix: Missing trailingslash results to wrong absolute paths in database after Search & Replace operation "
|
128 |
-
msgstr ""
|
129 |
-
|
130 |
-
#. Found in changelog list item.
|
131 |
-
msgid "New: Compatible to WordPress 4.9.6"
|
132 |
-
msgstr ""
|
133 |
-
|
134 |
-
#. Found in changelog list item.
|
135 |
-
msgid "New: Add new setting which allow to specify the search & replace processing query limit"
|
136 |
-
msgstr ""
|
137 |
-
|
138 |
-
#. Found in changelog list item.
|
139 |
-
msgid "New: Supports search & replace for revslider image slider and several visual editors which are using non default serialized data"
|
140 |
-
msgstr ""
|
141 |
-
|
142 |
-
#. Found in changelog list item.
|
143 |
-
msgid "New: Add filter 'wpstg_fiter_search_replace_rows' to exclude certain tables from search & replace"
|
144 |
-
msgstr ""
|
145 |
-
|
146 |
-
#. Found in changelog list item.
|
147 |
-
msgid "New: Add datetime timestamp internally to clone. (Used in WP Staging pro)"
|
148 |
-
msgstr ""
|
149 |
-
|
150 |
-
#. Found in changelog list item.
|
151 |
-
msgid "New: Support for custom upload folder. For instance, if upload folder has been renamed and removed outsite wp-content folder"
|
152 |
-
msgstr ""
|
153 |
-
|
154 |
-
#. Found in changelog list item.
|
155 |
-
msgid "New: Exclude tables for plugin wp_mail_smtp"
|
156 |
-
msgstr ""
|
157 |
-
|
158 |
-
#. Found in changelog list item.
|
159 |
-
msgid "New: Add filter 'wpstg_filter_options_replace' to exclude certain tables from updating while cloning"
|
160 |
-
msgstr ""
|
161 |
-
|
162 |
-
#. Found in changelog list item.
|
163 |
-
msgid "Fix: WP_SITEURL & WP_HOME not replaced if constant contains php generated string"
|
164 |
-
msgstr ""
|
165 |
-
|
166 |
-
#. Found in changelog list item.
|
167 |
-
msgid "Fix: Serialize replace is not working properly for serialized strings"
|
168 |
-
msgstr ""
|
169 |
-
|
170 |
-
#. Found in faq list item.
|
171 |
-
msgid ""
|
172 |
-
"I can not login to the staging site\n"
|
173 |
-
"If you are using a security plugin like All In One WP Security & Firewall you need to install latest version of WP Staging. \n"
|
174 |
-
"Go to WP Staging > Settings and add the slug to the custom login page which you set up in All In One WP Security & Firewall plugin."
|
175 |
-
msgstr ""
|
176 |
-
|
177 |
-
#. Found in installation list item, faq list item.
|
178 |
-
msgid "Upload and install it via the WordPress plugin backend wp-admin > plugins > add new > uploads"
|
179 |
-
msgstr ""
|
180 |
-
|
181 |
-
#. Found in installation list item, faq list item.
|
182 |
-
msgid "Download the file \"wp-staging.zip\":"
|
183 |
-
msgstr ""
|
184 |
-
|
185 |
-
#. Found in description paragraph.
|
186 |
-
msgid ""
|
187 |
-
"Permalinks are disabled on the staging site because the staging site is cloned into a subfolder and permalinks are not working on all systems\n"
|
188 |
-
"without doing changes to the .htaccess (Apache server) or nginx.conf (Nginx Server).\n"
|
189 |
-
"<a href=\"https://wp-staging.com/docs/activate-permalinks-staging-site/\" title=\"activate permalinks on staging site\">Read here</a> how to activate permalinks on the staging site."
|
190 |
-
msgstr ""
|
191 |
-
|
192 |
-
#. Found in description list item.
|
193 |
-
msgid "New: Compatible to All In One WP Security & Firewall"
|
194 |
-
msgstr ""
|
195 |
-
|
196 |
-
#. Found in description paragraph.
|
197 |
-
msgid "Note: WordPress 5.0 will be shipped with a new visual editor called Gutenberg. Use WP Staging to check if Gutenberg editor is working as intended on your website and that all used plugins are compatible with that new editor."
|
198 |
-
msgstr ""
|
199 |
-
|
200 |
-
#. Found in changelog paragraph.
|
201 |
-
msgid "Complete changelog: <a href=\"https://wp-staging.com/changelog.txt\">https://wp-staging.com/changelog.txt</a>"
|
202 |
-
msgstr ""
|
203 |
-
|
204 |
-
#. Found in description paragraph.
|
205 |
-
msgid "https://wp-staging.com"
|
206 |
-
msgstr ""
|
207 |
-
|
208 |
-
#. Found in description paragraph.
|
209 |
-
msgid ""
|
210 |
-
"<strong>This cloning and staging plugin is well tested and work in progress. <br /><br />\n"
|
211 |
-
"If you find any issue, please open a <a href=\"https://wp-staging.com/support/\" title=\"support ticket\">support ticket</a>.\n"
|
212 |
-
"</strong>\n"
|
213 |
-
"<br /><br />\n"
|
214 |
-
"<strong>Note: </strong> For pushing & migrating plugins and theme files to live site, check out the pro version <a href=\"https://wp-staging.com/\" title=\"WP Staging Pro\">https://wp-staging.com/</a>\n"
|
215 |
-
"<br /><br />"
|
216 |
-
msgstr ""
|
217 |
-
|
218 |
-
#. Found in faq header.
|
219 |
-
msgid "Installation Instructions"
|
220 |
-
msgstr ""
|
221 |
-
|
222 |
-
#. Found in description list item.
|
223 |
-
msgid ""
|
224 |
-
"WordPress duplicating process on windows server (not tested but will probably work) \n"
|
225 |
-
"Edit: Duplication on windows server seems to be working well: <a href=\"https://wordpress.org/support/topic/wont-copy-files?replies=5\" title=\"Read more\">Read more</a> "
|
226 |
-
msgstr ""
|
227 |
-
|
228 |
-
#. Found in description list item.
|
229 |
-
msgid ""
|
230 |
-
"<strong>Safe: </strong> Access to staging site is granted for administrators only.\n"
|
231 |
-
"<br /><br />\n"
|
232 |
-
"<strong>More safe:</strong> \n"
|
233 |
-
"<br />"
|
234 |
-
msgstr ""
|
235 |
-
|
236 |
-
#. Found in description paragraph.
|
237 |
-
msgid "[youtube https://www.youtube.com/watch?v=Ye3fC6cdB3A]"
|
238 |
-
msgstr ""
|
239 |
-
|
240 |
-
#. Found in description header.
|
241 |
-
msgid "Official Site"
|
242 |
-
msgstr ""
|
243 |
-
|
244 |
-
#. Found in installation list item, faq list item.
|
245 |
-
msgid "Activate the plugin through the 'Plugins' menu in WordPress."
|
246 |
-
msgstr "Activate the plugin through the 'Plugins' menu in WordPress."
|
247 |
-
|
248 |
-
#. Found in description paragraph.
|
249 |
-
msgid ""
|
250 |
-
"Install it via the admin dashboard and to 'Plugins', click 'Add New' and search the plugins for 'Staging'. Install the plugin with 'Install Now'.\n"
|
251 |
-
"After installation goto the settings page 'Staging' and do your adjustments there."
|
252 |
-
msgstr ""
|
253 |
-
|
254 |
-
#. Found in description paragraph.
|
255 |
-
msgid ""
|
256 |
-
"This plugin has been done in hundreds of hours to work on even the smallest shared webhosting package but i am limited in testing this only on a handful of different server so i need your help:\n"
|
257 |
-
"Please open a <a href=\"https://wordpress.org/support/plugin/wp-staging/\" title=\"support request\">support request</a> and describe your problem exactely. In wp-content/wp-staging/logs you find extended logfiles. Have a look at them and let me know the error-thrown lines."
|
258 |
-
msgstr ""
|
259 |
-
|
260 |
-
#. Found in description paragraph.
|
261 |
-
msgid ""
|
262 |
-
"So, if you have created a local or webhosted development site and you need to migrate this site the first time to your production domain than you are doing nothing wrong with using\n"
|
263 |
-
"the Duplicator plugin! If you need all you latest production data like posts, updated plugins, theme data and styles in a testing environment than i recommend to use WP Staging instead!"
|
264 |
-
msgstr ""
|
265 |
-
|
266 |
-
#. Found in description paragraph.
|
267 |
-
msgid ""
|
268 |
-
"At first, i love the <a href=\"https://wordpress.org/plugins/duplicator/\" title=\"Duplicator plugin\">Duplicator plugin</a>. Duplicator is a great tool for migrating from development site to production one or from production site to development one. \n"
|
269 |
-
"The downside is that Duplicator needs adjustments, manually interventions and prerequirements for this. Duplicator also needs some skills to be able to create a development / staging site, where WP Staging does not need more than a click from you.\n"
|
270 |
-
"However, Duplicator is best placed to be a tool for first-time creation of your production site. This is something where it is very handy and powerful."
|
271 |
-
msgstr ""
|
272 |
-
|
273 |
-
#. Found in description paragraph.
|
274 |
-
msgid ""
|
275 |
-
"If you want to migrate your local database to a already existing production site you can use a tool like WP Migrate DB.\n"
|
276 |
-
"WP Staging is only for creating a staging site with latest data from your production site. So it goes the opposite way of WP Migrate DB.\n"
|
277 |
-
"Both tools are excellent cooperating eachother."
|
278 |
-
msgstr ""
|
279 |
-
|
280 |
-
#. Found in description paragraph.
|
281 |
-
msgid "This is were WP Staging steps in... Site cloning and staging site creation simplified!"
|
282 |
-
msgstr ""
|
283 |
-
|
284 |
-
#. Found in description paragraph.
|
285 |
-
msgid ""
|
286 |
-
"Nope! If your local hardware and software environment is not a 100% exact clone of your production server there is NO guarantee that every aspect \n"
|
287 |
-
"of your local copy is working on your live website exactely as you would expect it. \n"
|
288 |
-
"There are some obvious things like differences in the config of php and the server you are running but even such non obvious settings like the amount of ram or the \n"
|
289 |
-
"the cpu performance can lead to unexpected results on your production website. \n"
|
290 |
-
"There are dozens of other possible cause of failure which can not be handled well when you are testing your changes on a local staging platform."
|
291 |
-
msgstr ""
|
292 |
-
|
293 |
-
#. Found in description paragraph.
|
294 |
-
msgid "<strong> I think its time to change this, so i created \"WP Staging\" for WordPress migration of staging sites</strong>"
|
295 |
-
msgstr ""
|
296 |
-
|
297 |
-
#. Found in description paragraph.
|
298 |
-
msgid ""
|
299 |
-
"Some people are also afraid of installing plugins updates because they follow the rule \"never touch a running system\" with having in mind that untested updates are increasing the risk of breaking their site.\n"
|
300 |
-
"I totally understand this and i am guilty as well here, but unfortunately this leads to one of the main reasons why WordPress installations are often outdated, not updated at all and unsecure due to this non-update behavior."
|
301 |
-
msgstr ""
|
302 |
-
|
303 |
-
#. Found in description paragraph.
|
304 |
-
msgid ""
|
305 |
-
"Testing a plugin update before installing it in live environment isn´t done very often by most user because existing staging solutions are too complex and need a lot of time to create a \n"
|
306 |
-
"up-to-date copy of your website."
|
307 |
-
msgstr ""
|
308 |
-
|
309 |
-
#. Found in description paragraph.
|
310 |
-
msgid ""
|
311 |
-
"Plugin updates and theme customizations should be tested on a staging platform first. Its recommended to have the staging platform on the same server where the production website is located.\n"
|
312 |
-
"When you run a plugin update or plan to install a new one, it is a necessary task to check first the modifications on a clone of your production website.\n"
|
313 |
-
"This makes sure that any modifications is working on your website without throwing unexpected errors or preventing your site from loading. (Better known as the wordpress blank page error)"
|
314 |
-
msgstr ""
|
315 |
-
|
316 |
-
#. Found in description paragraph.
|
317 |
-
msgid "<strong>Change your workflow of updating themes and plugins data:</strong>"
|
318 |
-
msgstr ""
|
319 |
-
|
320 |
-
#. Found in description paragraph.
|
321 |
-
msgid "WP Staging helps you to prevent your website from being broken or unavailable because of installing untested plugin updates!"
|
322 |
-
msgstr ""
|
323 |
-
|
324 |
-
#. Found in description paragraph.
|
325 |
-
msgid "<em>* Time of creation depends on size of your database and file size</em>"
|
326 |
-
msgstr ""
|
327 |
-
|
328 |
-
#. Found in description list item.
|
329 |
-
msgid "Everything running as expected? You are on the save side for migration of all these modifications to your production site!"
|
330 |
-
msgstr ""
|
331 |
-
|
332 |
-
#. Found in description list item.
|
333 |
-
msgid "Test everything on your staging site first"
|
334 |
-
msgstr ""
|
335 |
-
|
336 |
-
#. Found in description list item.
|
337 |
-
msgid "Customize theme, configuration and plugins or install new plugins"
|
338 |
-
msgstr ""
|
339 |
-
|
340 |
-
#. Found in description list item.
|
341 |
-
msgid "Use WP Staging for migration of a production website to a clone site for staging purposes"
|
342 |
-
msgstr ""
|
343 |
-
|
344 |
-
#. Found in description list item.
|
345 |
-
msgid "Wordpress migration of wordpress multisites (not tested)"
|
346 |
-
msgstr ""
|
347 |
-
|
348 |
-
#. Found in description list item.
|
349 |
-
msgid "Extensive logging if duplication or migration process should fail."
|
350 |
-
msgstr ""
|
351 |
-
|
352 |
-
#. Found in description list item.
|
353 |
-
msgid "Admin bar reflects that you are working on a staging site"
|
354 |
-
msgstr ""
|
355 |
-
|
356 |
-
#. Found in description list item.
|
357 |
-
msgid "<strong>Fast: </strong> Migration process lasts only a few seconds or minutes, depending on the site's size and server I/O power"
|
358 |
-
msgstr ""
|
359 |
-
|
360 |
-
#. Found in description list item.
|
361 |
-
msgid "<strong>Easy: </strong> Staging migration applicable for everyone. No configuration needed!"
|
362 |
-
msgstr ""
|
363 |
-
|
364 |
-
#. Found in description header.
|
365 |
-
msgid "How to install and setup?"
|
366 |
-
msgstr ""
|
367 |
-
|
368 |
-
#. Found in description header.
|
369 |
-
msgid "Important"
|
370 |
-
msgstr ""
|
371 |
-
|
372 |
-
#. Found in description header.
|
373 |
-
msgid "I need you feedback"
|
374 |
-
msgstr ""
|
375 |
-
|
376 |
-
#. Found in description header.
|
377 |
-
msgid "What are the benefits compared to a plugin like Duplicator?"
|
378 |
-
msgstr ""
|
379 |
-
|
380 |
-
#. Found in description header.
|
381 |
-
msgid "I just want to migrate the database from one installation to another"
|
382 |
-
msgstr ""
|
383 |
-
|
384 |
-
#. Found in description header.
|
385 |
-
msgid " Can´t i just use my local wordpress development copy for testing like xampp / lampp? "
|
386 |
-
msgstr ""
|
387 |
-
|
388 |
-
#. Found in description header.
|
389 |
-
msgid " Why should i use a staging website? "
|
390 |
-
msgstr ""
|
391 |
-
|
392 |
-
#. Found in description header.
|
393 |
-
msgid "What does not work or is not tested when running wordpress migration?"
|
394 |
-
msgstr ""
|
395 |
-
|
396 |
-
#. Found in description header.
|
397 |
-
msgid "Main Features"
|
398 |
-
msgstr ""
|
399 |
-
|
400 |
-
#. Found in description header.
|
401 |
-
msgid " WP Staging for WordPress Migration "
|
402 |
-
msgstr ""
|
403 |
-
|
404 |
-
#. Screenshot description.
|
405 |
-
msgid "Finish!"
|
406 |
-
msgstr ""
|
407 |
-
|
408 |
-
#. Screenshot description.
|
409 |
-
msgid "Step 3. Wordpress Staging site creation in progress"
|
410 |
-
msgstr ""
|
411 |
-
|
412 |
-
#. Screenshot description.
|
413 |
-
msgid "Step 2. Scanning your website for files and database tables"
|
414 |
-
msgstr ""
|
415 |
-
|
416 |
-
#. Screenshot description.
|
417 |
-
msgid "Step 1. Create new WordPress staging site"
|
418 |
msgstr ""
|
1 |
+
# Translation of Plugins - WP Staging – DB & File Duplicator & Migration - Stable Readme (latest release) in English (UK)
|
2 |
+
# This file is distributed under the same license as the Plugins - WP Staging – DB & File Duplicator & Migration - Stable Readme (latest release) package.
|
3 |
+
msgid ""
|
4 |
+
msgstr ""
|
5 |
+
"PO-Revision-Date: 2015-12-01 15:35:13+0000\n"
|
6 |
+
"MIME-Version: 1.0\n"
|
7 |
+
"Content-Type: text/plain; charset=UTF-8\n"
|
8 |
+
"Content-Transfer-Encoding: 8bit\n"
|
9 |
+
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
10 |
+
"X-Generator: GlotPress/2.4.0-alpha\n"
|
11 |
+
"Language: en_GB\n"
|
12 |
+
"Project-Id-Version: Plugins - WP Staging – DB & File Duplicator & Migration - Stable Readme (latest release)\n"
|
13 |
+
|
14 |
+
#. Short description.
|
15 |
+
msgid "A duplicator plugin! Clone, duplicate and migrate live sites to independent staging and development sites that are available only to administrators."
|
16 |
+
msgstr ""
|
17 |
+
|
18 |
+
#. Plugin name.
|
19 |
+
msgid "WP Staging - DB & File Duplicator & Migration"
|
20 |
+
msgstr ""
|
21 |
+
|
22 |
+
#. Found in changelog list item.
|
23 |
+
msgid "Fix: Missing http(s) scheme after cloning multisites results in not working clones"
|
24 |
+
msgstr ""
|
25 |
+
|
26 |
+
#. Found in changelog list item.
|
27 |
+
msgid "New: Support for Windows Azure cloud servers"
|
28 |
+
msgstr ""
|
29 |
+
|
30 |
+
#. Found in changelog list item.
|
31 |
+
msgid "Fix: Do not search & replace mail addresses"
|
32 |
+
msgstr ""
|
33 |
+
|
34 |
+
#. Found in changelog list item.
|
35 |
+
msgid "Fix: Remove term 'Error' from login page"
|
36 |
+
msgstr ""
|
37 |
+
|
38 |
+
#. Found in changelog list item.
|
39 |
+
msgid "New: Login options not needed any more - removed"
|
40 |
+
msgstr ""
|
41 |
+
|
42 |
+
#. Found in changelog list item.
|
43 |
+
msgid "New: Detect if wp-config.php has been moved one folder level up"
|
44 |
+
msgstr ""
|
45 |
+
|
46 |
+
#. Found in changelog list item.
|
47 |
+
msgid "New: Better error reporting"
|
48 |
+
msgstr ""
|
49 |
+
|
50 |
+
#. Found in changelog list item.
|
51 |
+
msgid "New: Compatible up to WordPress 4.9.8"
|
52 |
+
msgstr ""
|
53 |
+
|
54 |
+
#. Found in changelog list item.
|
55 |
+
msgid "New: Setting to specify the maximum allowed file size to copy"
|
56 |
+
msgstr ""
|
57 |
+
|
58 |
+
#. Found in changelog list item.
|
59 |
+
msgid "Fix: Search & replace path not correct if scheme http/https is not identical in wp-config and db wp_options"
|
60 |
+
msgstr ""
|
61 |
+
|
62 |
+
#. Found in changelog list item.
|
63 |
+
msgid "Fix: Creating a new clone resets the custom wp staging user settings. E.g. ignores authentication setting"
|
64 |
+
msgstr ""
|
65 |
+
|
66 |
+
#. Found in changelog list item.
|
67 |
+
msgid "Tweak: Remove certain debugging notices from the default log window"
|
68 |
+
msgstr ""
|
69 |
+
|
70 |
+
#. Found in changelog list item.
|
71 |
+
msgid "Tweaks: remove term \"error\" from several log entries"
|
72 |
+
msgstr ""
|
73 |
+
|
74 |
+
#. Found in changelog list item.
|
75 |
+
msgid "Fix: Search & Replace not working if serialized object contains __PHP_Incomplete_Class_Name"
|
76 |
+
msgstr ""
|
77 |
+
|
78 |
+
#. Found in changelog list item.
|
79 |
+
msgid "Fix: Skip search & replace for objects where key is null"
|
80 |
+
msgstr ""
|
81 |
+
|
82 |
+
#. Found in changelog list item.
|
83 |
+
msgid "Fix: Parameter must be an array or an object that implements Callable"
|
84 |
+
msgstr ""
|
85 |
+
|
86 |
+
#. Found in changelog list item.
|
87 |
+
msgid "Fix: wp-config.php not copied when previous clone updating process has been failed"
|
88 |
+
msgstr ""
|
89 |
+
|
90 |
+
#. Found in changelog list item.
|
91 |
+
msgid "Fix: Undefined object $this->tables"
|
92 |
+
msgstr ""
|
93 |
+
|
94 |
+
#. Found in changelog list item.
|
95 |
+
msgid "Fix: Can not open upload folder in file selection menu"
|
96 |
+
msgstr ""
|
97 |
+
|
98 |
+
#. Found in changelog list item.
|
99 |
+
msgid "Fix: Progress bar not shown as intented for clone updating process"
|
100 |
+
msgstr ""
|
101 |
+
|
102 |
+
#. Found in changelog list item.
|
103 |
+
msgid "Fix: If cloning update process is interupted it may happen that staging site is not available any longer. (Updating the clone does not copy index.php to staging site again)"
|
104 |
+
msgstr ""
|
105 |
+
|
106 |
+
#. Found in changelog list item.
|
107 |
+
msgid "Fix: Progress bar for step 'database' is not filling up to 100%"
|
108 |
+
msgstr ""
|
109 |
+
|
110 |
+
#. Found in changelog list item.
|
111 |
+
msgid "New: Use the new progress bar for clone updating process"
|
112 |
+
msgstr ""
|
113 |
+
|
114 |
+
#. Found in changelog list item.
|
115 |
+
msgid "New: Add multisite informations in system info log"
|
116 |
+
msgstr ""
|
117 |
+
|
118 |
+
#. Found in changelog list item.
|
119 |
+
msgid "New: Option to allow adjustment of the allowed maximum size of files that are going to be copied while cloning."
|
120 |
+
msgstr ""
|
121 |
+
|
122 |
+
#. Found in changelog list item.
|
123 |
+
msgid "Security: Do not allow to create a new staging site into a subfolder which already exists"
|
124 |
+
msgstr ""
|
125 |
+
|
126 |
+
#. Found in changelog list item.
|
127 |
+
msgid "Fix: Missing trailingslash results to wrong absolute paths in database after Search & Replace operation "
|
128 |
+
msgstr ""
|
129 |
+
|
130 |
+
#. Found in changelog list item.
|
131 |
+
msgid "New: Compatible to WordPress 4.9.6"
|
132 |
+
msgstr ""
|
133 |
+
|
134 |
+
#. Found in changelog list item.
|
135 |
+
msgid "New: Add new setting which allow to specify the search & replace processing query limit"
|
136 |
+
msgstr ""
|
137 |
+
|
138 |
+
#. Found in changelog list item.
|
139 |
+
msgid "New: Supports search & replace for revslider image slider and several visual editors which are using non default serialized data"
|
140 |
+
msgstr ""
|
141 |
+
|
142 |
+
#. Found in changelog list item.
|
143 |
+
msgid "New: Add filter 'wpstg_fiter_search_replace_rows' to exclude certain tables from search & replace"
|
144 |
+
msgstr ""
|
145 |
+
|
146 |
+
#. Found in changelog list item.
|
147 |
+
msgid "New: Add datetime timestamp internally to clone. (Used in WP Staging pro)"
|
148 |
+
msgstr ""
|
149 |
+
|
150 |
+
#. Found in changelog list item.
|
151 |
+
msgid "New: Support for custom upload folder. For instance, if upload folder has been renamed and removed outsite wp-content folder"
|
152 |
+
msgstr ""
|
153 |
+
|
154 |
+
#. Found in changelog list item.
|
155 |
+
msgid "New: Exclude tables for plugin wp_mail_smtp"
|
156 |
+
msgstr ""
|
157 |
+
|
158 |
+
#. Found in changelog list item.
|
159 |
+
msgid "New: Add filter 'wpstg_filter_options_replace' to exclude certain tables from updating while cloning"
|
160 |
+
msgstr ""
|
161 |
+
|
162 |
+
#. Found in changelog list item.
|
163 |
+
msgid "Fix: WP_SITEURL & WP_HOME not replaced if constant contains php generated string"
|
164 |
+
msgstr ""
|
165 |
+
|
166 |
+
#. Found in changelog list item.
|
167 |
+
msgid "Fix: Serialize replace is not working properly for serialized strings"
|
168 |
+
msgstr ""
|
169 |
+
|
170 |
+
#. Found in faq list item.
|
171 |
+
msgid ""
|
172 |
+
"I can not login to the staging site\n"
|
173 |
+
"If you are using a security plugin like All In One WP Security & Firewall you need to install latest version of WP Staging. \n"
|
174 |
+
"Go to WP Staging > Settings and add the slug to the custom login page which you set up in All In One WP Security & Firewall plugin."
|
175 |
+
msgstr ""
|
176 |
+
|
177 |
+
#. Found in installation list item, faq list item.
|
178 |
+
msgid "Upload and install it via the WordPress plugin backend wp-admin > plugins > add new > uploads"
|
179 |
+
msgstr ""
|
180 |
+
|
181 |
+
#. Found in installation list item, faq list item.
|
182 |
+
msgid "Download the file \"wp-staging.zip\":"
|
183 |
+
msgstr ""
|
184 |
+
|
185 |
+
#. Found in description paragraph.
|
186 |
+
msgid ""
|
187 |
+
"Permalinks are disabled on the staging site because the staging site is cloned into a subfolder and permalinks are not working on all systems\n"
|
188 |
+
"without doing changes to the .htaccess (Apache server) or nginx.conf (Nginx Server).\n"
|
189 |
+
"<a href=\"https://wp-staging.com/docs/activate-permalinks-staging-site/\" title=\"activate permalinks on staging site\">Read here</a> how to activate permalinks on the staging site."
|
190 |
+
msgstr ""
|
191 |
+
|
192 |
+
#. Found in description list item.
|
193 |
+
msgid "New: Compatible to All In One WP Security & Firewall"
|
194 |
+
msgstr ""
|
195 |
+
|
196 |
+
#. Found in description paragraph.
|
197 |
+
msgid "Note: WordPress 5.0 will be shipped with a new visual editor called Gutenberg. Use WP Staging to check if Gutenberg editor is working as intended on your website and that all used plugins are compatible with that new editor."
|
198 |
+
msgstr ""
|
199 |
+
|
200 |
+
#. Found in changelog paragraph.
|
201 |
+
msgid "Complete changelog: <a href=\"https://wp-staging.com/changelog.txt\">https://wp-staging.com/changelog.txt</a>"
|
202 |
+
msgstr ""
|
203 |
+
|
204 |
+
#. Found in description paragraph.
|
205 |
+
msgid "https://wp-staging.com"
|
206 |
+
msgstr ""
|
207 |
+
|
208 |
+
#. Found in description paragraph.
|
209 |
+
msgid ""
|
210 |
+
"<strong>This cloning and staging plugin is well tested and work in progress. <br /><br />\n"
|
211 |
+
"If you find any issue, please open a <a href=\"https://wp-staging.com/support/\" title=\"support ticket\">support ticket</a>.\n"
|
212 |
+
"</strong>\n"
|
213 |
+
"<br /><br />\n"
|
214 |
+
"<strong>Note: </strong> For pushing & migrating plugins and theme files to live site, check out the pro version <a href=\"https://wp-staging.com/\" title=\"WP Staging Pro\">https://wp-staging.com/</a>\n"
|
215 |
+
"<br /><br />"
|
216 |
+
msgstr ""
|
217 |
+
|
218 |
+
#. Found in faq header.
|
219 |
+
msgid "Installation Instructions"
|
220 |
+
msgstr ""
|
221 |
+
|
222 |
+
#. Found in description list item.
|
223 |
+
msgid ""
|
224 |
+
"WordPress duplicating process on windows server (not tested but will probably work) \n"
|
225 |
+
"Edit: Duplication on windows server seems to be working well: <a href=\"https://wordpress.org/support/topic/wont-copy-files?replies=5\" title=\"Read more\">Read more</a> "
|
226 |
+
msgstr ""
|
227 |
+
|
228 |
+
#. Found in description list item.
|
229 |
+
msgid ""
|
230 |
+
"<strong>Safe: </strong> Access to staging site is granted for administrators only.\n"
|
231 |
+
"<br /><br />\n"
|
232 |
+
"<strong>More safe:</strong> \n"
|
233 |
+
"<br />"
|
234 |
+
msgstr ""
|
235 |
+
|
236 |
+
#. Found in description paragraph.
|
237 |
+
msgid "[youtube https://www.youtube.com/watch?v=Ye3fC6cdB3A]"
|
238 |
+
msgstr ""
|
239 |
+
|
240 |
+
#. Found in description header.
|
241 |
+
msgid "Official Site"
|
242 |
+
msgstr ""
|
243 |
+
|
244 |
+
#. Found in installation list item, faq list item.
|
245 |
+
msgid "Activate the plugin through the 'Plugins' menu in WordPress."
|
246 |
+
msgstr "Activate the plugin through the 'Plugins' menu in WordPress."
|
247 |
+
|
248 |
+
#. Found in description paragraph.
|
249 |
+
msgid ""
|
250 |
+
"Install it via the admin dashboard and to 'Plugins', click 'Add New' and search the plugins for 'Staging'. Install the plugin with 'Install Now'.\n"
|
251 |
+
"After installation goto the settings page 'Staging' and do your adjustments there."
|
252 |
+
msgstr ""
|
253 |
+
|
254 |
+
#. Found in description paragraph.
|
255 |
+
msgid ""
|
256 |
+
"This plugin has been done in hundreds of hours to work on even the smallest shared webhosting package but i am limited in testing this only on a handful of different server so i need your help:\n"
|
257 |
+
"Please open a <a href=\"https://wordpress.org/support/plugin/wp-staging/\" title=\"support request\">support request</a> and describe your problem exactely. In wp-content/wp-staging/logs you find extended logfiles. Have a look at them and let me know the error-thrown lines."
|
258 |
+
msgstr ""
|
259 |
+
|
260 |
+
#. Found in description paragraph.
|
261 |
+
msgid ""
|
262 |
+
"So, if you have created a local or webhosted development site and you need to migrate this site the first time to your production domain than you are doing nothing wrong with using\n"
|
263 |
+
"the Duplicator plugin! If you need all you latest production data like posts, updated plugins, theme data and styles in a testing environment than i recommend to use WP Staging instead!"
|
264 |
+
msgstr ""
|
265 |
+
|
266 |
+
#. Found in description paragraph.
|
267 |
+
msgid ""
|
268 |
+
"At first, i love the <a href=\"https://wordpress.org/plugins/duplicator/\" title=\"Duplicator plugin\">Duplicator plugin</a>. Duplicator is a great tool for migrating from development site to production one or from production site to development one. \n"
|
269 |
+
"The downside is that Duplicator needs adjustments, manually interventions and prerequirements for this. Duplicator also needs some skills to be able to create a development / staging site, where WP Staging does not need more than a click from you.\n"
|
270 |
+
"However, Duplicator is best placed to be a tool for first-time creation of your production site. This is something where it is very handy and powerful."
|
271 |
+
msgstr ""
|
272 |
+
|
273 |
+
#. Found in description paragraph.
|
274 |
+
msgid ""
|
275 |
+
"If you want to migrate your local database to a already existing production site you can use a tool like WP Migrate DB.\n"
|
276 |
+
"WP Staging is only for creating a staging site with latest data from your production site. So it goes the opposite way of WP Migrate DB.\n"
|
277 |
+
"Both tools are excellent cooperating eachother."
|
278 |
+
msgstr ""
|
279 |
+
|
280 |
+
#. Found in description paragraph.
|
281 |
+
msgid "This is were WP Staging steps in... Site cloning and staging site creation simplified!"
|
282 |
+
msgstr ""
|
283 |
+
|
284 |
+
#. Found in description paragraph.
|
285 |
+
msgid ""
|
286 |
+
"Nope! If your local hardware and software environment is not a 100% exact clone of your production server there is NO guarantee that every aspect \n"
|
287 |
+
"of your local copy is working on your live website exactely as you would expect it. \n"
|
288 |
+
"There are some obvious things like differences in the config of php and the server you are running but even such non obvious settings like the amount of ram or the \n"
|
289 |
+
"the cpu performance can lead to unexpected results on your production website. \n"
|
290 |
+
"There are dozens of other possible cause of failure which can not be handled well when you are testing your changes on a local staging platform."
|
291 |
+
msgstr ""
|
292 |
+
|
293 |
+
#. Found in description paragraph.
|
294 |
+
msgid "<strong> I think its time to change this, so i created \"WP Staging\" for WordPress migration of staging sites</strong>"
|
295 |
+
msgstr ""
|
296 |
+
|
297 |
+
#. Found in description paragraph.
|
298 |
+
msgid ""
|
299 |
+
"Some people are also afraid of installing plugins updates because they follow the rule \"never touch a running system\" with having in mind that untested updates are increasing the risk of breaking their site.\n"
|
300 |
+
"I totally understand this and i am guilty as well here, but unfortunately this leads to one of the main reasons why WordPress installations are often outdated, not updated at all and unsecure due to this non-update behavior."
|
301 |
+
msgstr ""
|
302 |
+
|
303 |
+
#. Found in description paragraph.
|
304 |
+
msgid ""
|
305 |
+
"Testing a plugin update before installing it in live environment isn´t done very often by most user because existing staging solutions are too complex and need a lot of time to create a \n"
|
306 |
+
"up-to-date copy of your website."
|
307 |
+
msgstr ""
|
308 |
+
|
309 |
+
#. Found in description paragraph.
|
310 |
+
msgid ""
|
311 |
+
"Plugin updates and theme customizations should be tested on a staging platform first. Its recommended to have the staging platform on the same server where the production website is located.\n"
|
312 |
+
"When you run a plugin update or plan to install a new one, it is a necessary task to check first the modifications on a clone of your production website.\n"
|
313 |
+
"This makes sure that any modifications is working on your website without throwing unexpected errors or preventing your site from loading. (Better known as the wordpress blank page error)"
|
314 |
+
msgstr ""
|
315 |
+
|
316 |
+
#. Found in description paragraph.
|
317 |
+
msgid "<strong>Change your workflow of updating themes and plugins data:</strong>"
|
318 |
+
msgstr ""
|
319 |
+
|
320 |
+
#. Found in description paragraph.
|
321 |
+
msgid "WP Staging helps you to prevent your website from being broken or unavailable because of installing untested plugin updates!"
|
322 |
+
msgstr ""
|
323 |
+
|
324 |
+
#. Found in description paragraph.
|
325 |
+
msgid "<em>* Time of creation depends on size of your database and file size</em>"
|
326 |
+
msgstr ""
|
327 |
+
|
328 |
+
#. Found in description list item.
|
329 |
+
msgid "Everything running as expected? You are on the save side for migration of all these modifications to your production site!"
|
330 |
+
msgstr ""
|
331 |
+
|
332 |
+
#. Found in description list item.
|
333 |
+
msgid "Test everything on your staging site first"
|
334 |
+
msgstr ""
|
335 |
+
|
336 |
+
#. Found in description list item.
|
337 |
+
msgid "Customize theme, configuration and plugins or install new plugins"
|
338 |
+
msgstr ""
|
339 |
+
|
340 |
+
#. Found in description list item.
|
341 |
+
msgid "Use WP Staging for migration of a production website to a clone site for staging purposes"
|
342 |
+
msgstr ""
|
343 |
+
|
344 |
+
#. Found in description list item.
|
345 |
+
msgid "Wordpress migration of wordpress multisites (not tested)"
|
346 |
+
msgstr ""
|
347 |
+
|
348 |
+
#. Found in description list item.
|
349 |
+
msgid "Extensive logging if duplication or migration process should fail."
|
350 |
+
msgstr ""
|
351 |
+
|
352 |
+
#. Found in description list item.
|
353 |
+
msgid "Admin bar reflects that you are working on a staging site"
|
354 |
+
msgstr ""
|
355 |
+
|
356 |
+
#. Found in description list item.
|
357 |
+
msgid "<strong>Fast: </strong> Migration process lasts only a few seconds or minutes, depending on the site's size and server I/O power"
|
358 |
+
msgstr ""
|
359 |
+
|
360 |
+
#. Found in description list item.
|
361 |
+
msgid "<strong>Easy: </strong> Staging migration applicable for everyone. No configuration needed!"
|
362 |
+
msgstr ""
|
363 |
+
|
364 |
+
#. Found in description header.
|
365 |
+
msgid "How to install and setup?"
|
366 |
+
msgstr ""
|
367 |
+
|
368 |
+
#. Found in description header.
|
369 |
+
msgid "Important"
|
370 |
+
msgstr ""
|
371 |
+
|
372 |
+
#. Found in description header.
|
373 |
+
msgid "I need you feedback"
|
374 |
+
msgstr ""
|
375 |
+
|
376 |
+
#. Found in description header.
|
377 |
+
msgid "What are the benefits compared to a plugin like Duplicator?"
|
378 |
+
msgstr ""
|
379 |
+
|
380 |
+
#. Found in description header.
|
381 |
+
msgid "I just want to migrate the database from one installation to another"
|
382 |
+
msgstr ""
|
383 |
+
|
384 |
+
#. Found in description header.
|
385 |
+
msgid " Can´t i just use my local wordpress development copy for testing like xampp / lampp? "
|
386 |
+
msgstr ""
|
387 |
+
|
388 |
+
#. Found in description header.
|
389 |
+
msgid " Why should i use a staging website? "
|
390 |
+
msgstr ""
|
391 |
+
|
392 |
+
#. Found in description header.
|
393 |
+
msgid "What does not work or is not tested when running wordpress migration?"
|
394 |
+
msgstr ""
|
395 |
+
|
396 |
+
#. Found in description header.
|
397 |
+
msgid "Main Features"
|
398 |
+
msgstr ""
|
399 |
+
|
400 |
+
#. Found in description header.
|
401 |
+
msgid " WP Staging for WordPress Migration "
|
402 |
+
msgstr ""
|
403 |
+
|
404 |
+
#. Screenshot description.
|
405 |
+
msgid "Finish!"
|
406 |
+
msgstr ""
|
407 |
+
|
408 |
+
#. Screenshot description.
|
409 |
+
msgid "Step 3. Wordpress Staging site creation in progress"
|
410 |
+
msgstr ""
|
411 |
+
|
412 |
+
#. Screenshot description.
|
413 |
+
msgid "Step 2. Scanning your website for files and database tables"
|
414 |
+
msgstr ""
|
415 |
+
|
416 |
+
#. Screenshot description.
|
417 |
+
msgid "Step 1. Create new WordPress staging site"
|
418 |
msgstr ""
|
languages/wp-staging-it.po
CHANGED
@@ -1,418 +1,418 @@
|
|
1 |
-
# Translation of Plugins - WP Staging – DB & File Duplicator & Migration - Stable Readme (latest release) in Italian
|
2 |
-
# This file is distributed under the same license as the Plugins - WP Staging – DB & File Duplicator & Migration - Stable Readme (latest release) package.
|
3 |
-
msgid ""
|
4 |
-
msgstr ""
|
5 |
-
"PO-Revision-Date: 2015-12-01 15:35:13+0000\n"
|
6 |
-
"MIME-Version: 1.0\n"
|
7 |
-
"Content-Type: text/plain; charset=UTF-8\n"
|
8 |
-
"Content-Transfer-Encoding: 8bit\n"
|
9 |
-
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
10 |
-
"X-Generator: GlotPress/2.4.0-alpha\n"
|
11 |
-
"Language: it\n"
|
12 |
-
"Project-Id-Version: Plugins - WP Staging – DB & File Duplicator & Migration - Stable Readme (latest release)\n"
|
13 |
-
|
14 |
-
#. Short description.
|
15 |
-
msgid "A duplicator plugin! Clone, duplicate and migrate live sites to independent staging and development sites that are available only to administrators."
|
16 |
-
msgstr ""
|
17 |
-
|
18 |
-
#. Plugin name.
|
19 |
-
msgid "WP Staging - DB & File Duplicator & Migration"
|
20 |
-
msgstr ""
|
21 |
-
|
22 |
-
#. Found in changelog list item.
|
23 |
-
msgid "Fix: Missing http(s) scheme after cloning multisites results in not working clones"
|
24 |
-
msgstr ""
|
25 |
-
|
26 |
-
#. Found in changelog list item.
|
27 |
-
msgid "New: Support for Windows Azure cloud servers"
|
28 |
-
msgstr ""
|
29 |
-
|
30 |
-
#. Found in changelog list item.
|
31 |
-
msgid "Fix: Do not search & replace mail addresses"
|
32 |
-
msgstr ""
|
33 |
-
|
34 |
-
#. Found in changelog list item.
|
35 |
-
msgid "Fix: Remove term 'Error' from login page"
|
36 |
-
msgstr ""
|
37 |
-
|
38 |
-
#. Found in changelog list item.
|
39 |
-
msgid "New: Login options not needed any more - removed"
|
40 |
-
msgstr ""
|
41 |
-
|
42 |
-
#. Found in changelog list item.
|
43 |
-
msgid "New: Detect if wp-config.php has been moved one folder level up"
|
44 |
-
msgstr ""
|
45 |
-
|
46 |
-
#. Found in changelog list item.
|
47 |
-
msgid "New: Better error reporting"
|
48 |
-
msgstr ""
|
49 |
-
|
50 |
-
#. Found in changelog list item.
|
51 |
-
msgid "New: Compatible up to WordPress 4.9.8"
|
52 |
-
msgstr ""
|
53 |
-
|
54 |
-
#. Found in changelog list item.
|
55 |
-
msgid "New: Setting to specify the maximum allowed file size to copy"
|
56 |
-
msgstr ""
|
57 |
-
|
58 |
-
#. Found in changelog list item.
|
59 |
-
msgid "Fix: Search & replace path not correct if scheme http/https is not identical in wp-config and db wp_options"
|
60 |
-
msgstr ""
|
61 |
-
|
62 |
-
#. Found in changelog list item.
|
63 |
-
msgid "Fix: Creating a new clone resets the custom wp staging user settings. E.g. ignores authentication setting"
|
64 |
-
msgstr ""
|
65 |
-
|
66 |
-
#. Found in changelog list item.
|
67 |
-
msgid "Tweak: Remove certain debugging notices from the default log window"
|
68 |
-
msgstr ""
|
69 |
-
|
70 |
-
#. Found in changelog list item.
|
71 |
-
msgid "Tweaks: remove term \"error\" from several log entries"
|
72 |
-
msgstr ""
|
73 |
-
|
74 |
-
#. Found in changelog list item.
|
75 |
-
msgid "Fix: Search & Replace not working if serialized object contains __PHP_Incomplete_Class_Name"
|
76 |
-
msgstr ""
|
77 |
-
|
78 |
-
#. Found in changelog list item.
|
79 |
-
msgid "Fix: Skip search & replace for objects where key is null"
|
80 |
-
msgstr ""
|
81 |
-
|
82 |
-
#. Found in changelog list item.
|
83 |
-
msgid "Fix: Parameter must be an array or an object that implements Callable"
|
84 |
-
msgstr ""
|
85 |
-
|
86 |
-
#. Found in changelog list item.
|
87 |
-
msgid "Fix: wp-config.php not copied when previous clone updating process has been failed"
|
88 |
-
msgstr ""
|
89 |
-
|
90 |
-
#. Found in changelog list item.
|
91 |
-
msgid "Fix: Undefined object $this->tables"
|
92 |
-
msgstr ""
|
93 |
-
|
94 |
-
#. Found in changelog list item.
|
95 |
-
msgid "Fix: Can not open upload folder in file selection menu"
|
96 |
-
msgstr ""
|
97 |
-
|
98 |
-
#. Found in changelog list item.
|
99 |
-
msgid "Fix: Progress bar not shown as intented for clone updating process"
|
100 |
-
msgstr ""
|
101 |
-
|
102 |
-
#. Found in changelog list item.
|
103 |
-
msgid "Fix: If cloning update process is interupted it may happen that staging site is not available any longer. (Updating the clone does not copy index.php to staging site again)"
|
104 |
-
msgstr ""
|
105 |
-
|
106 |
-
#. Found in changelog list item.
|
107 |
-
msgid "Fix: Progress bar for step 'database' is not filling up to 100%"
|
108 |
-
msgstr ""
|
109 |
-
|
110 |
-
#. Found in changelog list item.
|
111 |
-
msgid "New: Use the new progress bar for clone updating process"
|
112 |
-
msgstr ""
|
113 |
-
|
114 |
-
#. Found in changelog list item.
|
115 |
-
msgid "New: Add multisite informations in system info log"
|
116 |
-
msgstr ""
|
117 |
-
|
118 |
-
#. Found in changelog list item.
|
119 |
-
msgid "New: Option to allow adjustment of the allowed maximum size of files that are going to be copied while cloning."
|
120 |
-
msgstr ""
|
121 |
-
|
122 |
-
#. Found in changelog list item.
|
123 |
-
msgid "Security: Do not allow to create a new staging site into a subfolder which already exists"
|
124 |
-
msgstr ""
|
125 |
-
|
126 |
-
#. Found in changelog list item.
|
127 |
-
msgid "Fix: Missing trailingslash results to wrong absolute paths in database after Search & Replace operation "
|
128 |
-
msgstr ""
|
129 |
-
|
130 |
-
#. Found in changelog list item.
|
131 |
-
msgid "New: Compatible to WordPress 4.9.6"
|
132 |
-
msgstr ""
|
133 |
-
|
134 |
-
#. Found in changelog list item.
|
135 |
-
msgid "New: Add new setting which allow to specify the search & replace processing query limit"
|
136 |
-
msgstr ""
|
137 |
-
|
138 |
-
#. Found in changelog list item.
|
139 |
-
msgid "New: Supports search & replace for revslider image slider and several visual editors which are using non default serialized data"
|
140 |
-
msgstr ""
|
141 |
-
|
142 |
-
#. Found in changelog list item.
|
143 |
-
msgid "New: Add filter 'wpstg_fiter_search_replace_rows' to exclude certain tables from search & replace"
|
144 |
-
msgstr ""
|
145 |
-
|
146 |
-
#. Found in changelog list item.
|
147 |
-
msgid "New: Add datetime timestamp internally to clone. (Used in WP Staging pro)"
|
148 |
-
msgstr ""
|
149 |
-
|
150 |
-
#. Found in changelog list item.
|
151 |
-
msgid "New: Support for custom upload folder. For instance, if upload folder has been renamed and removed outsite wp-content folder"
|
152 |
-
msgstr ""
|
153 |
-
|
154 |
-
#. Found in changelog list item.
|
155 |
-
msgid "New: Exclude tables for plugin wp_mail_smtp"
|
156 |
-
msgstr ""
|
157 |
-
|
158 |
-
#. Found in changelog list item.
|
159 |
-
msgid "New: Add filter 'wpstg_filter_options_replace' to exclude certain tables from updating while cloning"
|
160 |
-
msgstr ""
|
161 |
-
|
162 |
-
#. Found in changelog list item.
|
163 |
-
msgid "Fix: WP_SITEURL & WP_HOME not replaced if constant contains php generated string"
|
164 |
-
msgstr ""
|
165 |
-
|
166 |
-
#. Found in changelog list item.
|
167 |
-
msgid "Fix: Serialize replace is not working properly for serialized strings"
|
168 |
-
msgstr ""
|
169 |
-
|
170 |
-
#. Found in faq list item.
|
171 |
-
msgid ""
|
172 |
-
"I can not login to the staging site\n"
|
173 |
-
"If you are using a security plugin like All In One WP Security & Firewall you need to install latest version of WP Staging. \n"
|
174 |
-
"Go to WP Staging > Settings and add the slug to the custom login page which you set up in All In One WP Security & Firewall plugin."
|
175 |
-
msgstr ""
|
176 |
-
|
177 |
-
#. Found in installation list item, faq list item.
|
178 |
-
msgid "Upload and install it via the WordPress plugin backend wp-admin > plugins > add new > uploads"
|
179 |
-
msgstr ""
|
180 |
-
|
181 |
-
#. Found in installation list item, faq list item.
|
182 |
-
msgid "Download the file \"wp-staging.zip\":"
|
183 |
-
msgstr ""
|
184 |
-
|
185 |
-
#. Found in description paragraph.
|
186 |
-
msgid ""
|
187 |
-
"Permalinks are disabled on the staging site because the staging site is cloned into a subfolder and permalinks are not working on all systems\n"
|
188 |
-
"without doing changes to the .htaccess (Apache server) or nginx.conf (Nginx Server).\n"
|
189 |
-
"<a href=\"https://wp-staging.com/docs/activate-permalinks-staging-site/\" title=\"activate permalinks on staging site\">Read here</a> how to activate permalinks on the staging site."
|
190 |
-
msgstr ""
|
191 |
-
|
192 |
-
#. Found in description list item.
|
193 |
-
msgid "New: Compatible to All In One WP Security & Firewall"
|
194 |
-
msgstr ""
|
195 |
-
|
196 |
-
#. Found in description paragraph.
|
197 |
-
msgid "Note: WordPress 5.0 will be shipped with a new visual editor called Gutenberg. Use WP Staging to check if Gutenberg editor is working as intended on your website and that all used plugins are compatible with that new editor."
|
198 |
-
msgstr ""
|
199 |
-
|
200 |
-
#. Found in changelog paragraph.
|
201 |
-
msgid "Complete changelog: <a href=\"https://wp-staging.com/changelog.txt\">https://wp-staging.com/changelog.txt</a>"
|
202 |
-
msgstr ""
|
203 |
-
|
204 |
-
#. Found in description paragraph.
|
205 |
-
msgid "https://wp-staging.com"
|
206 |
-
msgstr ""
|
207 |
-
|
208 |
-
#. Found in description paragraph.
|
209 |
-
msgid ""
|
210 |
-
"<strong>This cloning and staging plugin is well tested and work in progress. <br /><br />\n"
|
211 |
-
"If you find any issue, please open a <a href=\"https://wp-staging.com/support/\" title=\"support ticket\">support ticket</a>.\n"
|
212 |
-
"</strong>\n"
|
213 |
-
"<br /><br />\n"
|
214 |
-
"<strong>Note: </strong> For pushing & migrating plugins and theme files to live site, check out the pro version <a href=\"https://wp-staging.com/\" title=\"WP Staging Pro\">https://wp-staging.com/</a>\n"
|
215 |
-
"<br /><br />"
|
216 |
-
msgstr ""
|
217 |
-
|
218 |
-
#. Found in faq header.
|
219 |
-
msgid "Installation Instructions"
|
220 |
-
msgstr ""
|
221 |
-
|
222 |
-
#. Found in description list item.
|
223 |
-
msgid ""
|
224 |
-
"WordPress duplicating process on windows server (not tested but will probably work) \n"
|
225 |
-
"Edit: Duplication on windows server seems to be working well: <a href=\"https://wordpress.org/support/topic/wont-copy-files?replies=5\" title=\"Read more\">Read more</a> "
|
226 |
-
msgstr ""
|
227 |
-
|
228 |
-
#. Found in description list item.
|
229 |
-
msgid ""
|
230 |
-
"<strong>Safe: </strong> Access to staging site is granted for administrators only.\n"
|
231 |
-
"<br /><br />\n"
|
232 |
-
"<strong>More safe:</strong> \n"
|
233 |
-
"<br />"
|
234 |
-
msgstr ""
|
235 |
-
|
236 |
-
#. Found in description paragraph.
|
237 |
-
msgid "[youtube https://www.youtube.com/watch?v=Ye3fC6cdB3A]"
|
238 |
-
msgstr ""
|
239 |
-
|
240 |
-
#. Found in description header.
|
241 |
-
msgid "Official Site"
|
242 |
-
msgstr ""
|
243 |
-
|
244 |
-
#. Found in installation list item, faq list item.
|
245 |
-
msgid "Activate the plugin through the 'Plugins' menu in WordPress."
|
246 |
-
msgstr "Attivare il plugin tramite il menu 'Plugin' di WordPress"
|
247 |
-
|
248 |
-
#. Found in description paragraph.
|
249 |
-
msgid ""
|
250 |
-
"Install it via the admin dashboard and to 'Plugins', click 'Add New' and search the plugins for 'Staging'. Install the plugin with 'Install Now'.\n"
|
251 |
-
"After installation goto the settings page 'Staging' and do your adjustments there."
|
252 |
-
msgstr ""
|
253 |
-
|
254 |
-
#. Found in description paragraph.
|
255 |
-
msgid ""
|
256 |
-
"This plugin has been done in hundreds of hours to work on even the smallest shared webhosting package but i am limited in testing this only on a handful of different server so i need your help:\n"
|
257 |
-
"Please open a <a href=\"https://wordpress.org/support/plugin/wp-staging/\" title=\"support request\">support request</a> and describe your problem exactely. In wp-content/wp-staging/logs you find extended logfiles. Have a look at them and let me know the error-thrown lines."
|
258 |
-
msgstr ""
|
259 |
-
|
260 |
-
#. Found in description paragraph.
|
261 |
-
msgid ""
|
262 |
-
"So, if you have created a local or webhosted development site and you need to migrate this site the first time to your production domain than you are doing nothing wrong with using\n"
|
263 |
-
"the Duplicator plugin! If you need all you latest production data like posts, updated plugins, theme data and styles in a testing environment than i recommend to use WP Staging instead!"
|
264 |
-
msgstr ""
|
265 |
-
|
266 |
-
#. Found in description paragraph.
|
267 |
-
msgid ""
|
268 |
-
"At first, i love the <a href=\"https://wordpress.org/plugins/duplicator/\" title=\"Duplicator plugin\">Duplicator plugin</a>. Duplicator is a great tool for migrating from development site to production one or from production site to development one. \n"
|
269 |
-
"The downside is that Duplicator needs adjustments, manually interventions and prerequirements for this. Duplicator also needs some skills to be able to create a development / staging site, where WP Staging does not need more than a click from you.\n"
|
270 |
-
"However, Duplicator is best placed to be a tool for first-time creation of your production site. This is something where it is very handy and powerful."
|
271 |
-
msgstr ""
|
272 |
-
|
273 |
-
#. Found in description paragraph.
|
274 |
-
msgid ""
|
275 |
-
"If you want to migrate your local database to a already existing production site you can use a tool like WP Migrate DB.\n"
|
276 |
-
"WP Staging is only for creating a staging site with latest data from your production site. So it goes the opposite way of WP Migrate DB.\n"
|
277 |
-
"Both tools are excellent cooperating eachother."
|
278 |
-
msgstr ""
|
279 |
-
|
280 |
-
#. Found in description paragraph.
|
281 |
-
msgid "This is were WP Staging steps in... Site cloning and staging site creation simplified!"
|
282 |
-
msgstr ""
|
283 |
-
|
284 |
-
#. Found in description paragraph.
|
285 |
-
msgid ""
|
286 |
-
"Nope! If your local hardware and software environment is not a 100% exact clone of your production server there is NO guarantee that every aspect \n"
|
287 |
-
"of your local copy is working on your live website exactely as you would expect it. \n"
|
288 |
-
"There are some obvious things like differences in the config of php and the server you are running but even such non obvious settings like the amount of ram or the \n"
|
289 |
-
"the cpu performance can lead to unexpected results on your production website. \n"
|
290 |
-
"There are dozens of other possible cause of failure which can not be handled well when you are testing your changes on a local staging platform."
|
291 |
-
msgstr ""
|
292 |
-
|
293 |
-
#. Found in description paragraph.
|
294 |
-
msgid "<strong> I think its time to change this, so i created \"WP Staging\" for WordPress migration of staging sites</strong>"
|
295 |
-
msgstr ""
|
296 |
-
|
297 |
-
#. Found in description paragraph.
|
298 |
-
msgid ""
|
299 |
-
"Some people are also afraid of installing plugins updates because they follow the rule \"never touch a running system\" with having in mind that untested updates are increasing the risk of breaking their site.\n"
|
300 |
-
"I totally understand this and i am guilty as well here, but unfortunately this leads to one of the main reasons why WordPress installations are often outdated, not updated at all and unsecure due to this non-update behavior."
|
301 |
-
msgstr ""
|
302 |
-
|
303 |
-
#. Found in description paragraph.
|
304 |
-
msgid ""
|
305 |
-
"Testing a plugin update before installing it in live environment isn´t done very often by most user because existing staging solutions are too complex and need a lot of time to create a \n"
|
306 |
-
"up-to-date copy of your website."
|
307 |
-
msgstr ""
|
308 |
-
|
309 |
-
#. Found in description paragraph.
|
310 |
-
msgid ""
|
311 |
-
"Plugin updates and theme customizations should be tested on a staging platform first. Its recommended to have the staging platform on the same server where the production website is located.\n"
|
312 |
-
"When you run a plugin update or plan to install a new one, it is a necessary task to check first the modifications on a clone of your production website.\n"
|
313 |
-
"This makes sure that any modifications is working on your website without throwing unexpected errors or preventing your site from loading. (Better known as the wordpress blank page error)"
|
314 |
-
msgstr ""
|
315 |
-
|
316 |
-
#. Found in description paragraph.
|
317 |
-
msgid "<strong>Change your workflow of updating themes and plugins data:</strong>"
|
318 |
-
msgstr ""
|
319 |
-
|
320 |
-
#. Found in description paragraph.
|
321 |
-
msgid "WP Staging helps you to prevent your website from being broken or unavailable because of installing untested plugin updates!"
|
322 |
-
msgstr ""
|
323 |
-
|
324 |
-
#. Found in description paragraph.
|
325 |
-
msgid "<em>* Time of creation depends on size of your database and file size</em>"
|
326 |
-
msgstr ""
|
327 |
-
|
328 |
-
#. Found in description list item.
|
329 |
-
msgid "Everything running as expected? You are on the save side for migration of all these modifications to your production site!"
|
330 |
-
msgstr ""
|
331 |
-
|
332 |
-
#. Found in description list item.
|
333 |
-
msgid "Test everything on your staging site first"
|
334 |
-
msgstr ""
|
335 |
-
|
336 |
-
#. Found in description list item.
|
337 |
-
msgid "Customize theme, configuration and plugins or install new plugins"
|
338 |
-
msgstr ""
|
339 |
-
|
340 |
-
#. Found in description list item.
|
341 |
-
msgid "Use WP Staging for migration of a production website to a clone site for staging purposes"
|
342 |
-
msgstr ""
|
343 |
-
|
344 |
-
#. Found in description list item.
|
345 |
-
msgid "Wordpress migration of wordpress multisites (not tested)"
|
346 |
-
msgstr ""
|
347 |
-
|
348 |
-
#. Found in description list item.
|
349 |
-
msgid "Extensive logging if duplication or migration process should fail."
|
350 |
-
msgstr ""
|
351 |
-
|
352 |
-
#. Found in description list item.
|
353 |
-
msgid "Admin bar reflects that you are working on a staging site"
|
354 |
-
msgstr ""
|
355 |
-
|
356 |
-
#. Found in description list item.
|
357 |
-
msgid "<strong>Fast: </strong> Migration process lasts only a few seconds or minutes, depending on the site's size and server I/O power"
|
358 |
-
msgstr ""
|
359 |
-
|
360 |
-
#. Found in description list item.
|
361 |
-
msgid "<strong>Easy: </strong> Staging migration applicable for everyone. No configuration needed!"
|
362 |
-
msgstr ""
|
363 |
-
|
364 |
-
#. Found in description header.
|
365 |
-
msgid "How to install and setup?"
|
366 |
-
msgstr ""
|
367 |
-
|
368 |
-
#. Found in description header.
|
369 |
-
msgid "Important"
|
370 |
-
msgstr "Wichtig"
|
371 |
-
|
372 |
-
#. Found in description header.
|
373 |
-
msgid "I need you feedback"
|
374 |
-
msgstr ""
|
375 |
-
|
376 |
-
#. Found in description header.
|
377 |
-
msgid "What are the benefits compared to a plugin like Duplicator?"
|
378 |
-
msgstr ""
|
379 |
-
|
380 |
-
#. Found in description header.
|
381 |
-
msgid "I just want to migrate the database from one installation to another"
|
382 |
-
msgstr ""
|
383 |
-
|
384 |
-
#. Found in description header.
|
385 |
-
msgid " Can´t i just use my local wordpress development copy for testing like xampp / lampp? "
|
386 |
-
msgstr ""
|
387 |
-
|
388 |
-
#. Found in description header.
|
389 |
-
msgid " Why should i use a staging website? "
|
390 |
-
msgstr ""
|
391 |
-
|
392 |
-
#. Found in description header.
|
393 |
-
msgid "What does not work or is not tested when running wordpress migration?"
|
394 |
-
msgstr ""
|
395 |
-
|
396 |
-
#. Found in description header.
|
397 |
-
msgid "Main Features"
|
398 |
-
msgstr ""
|
399 |
-
|
400 |
-
#. Found in description header.
|
401 |
-
msgid " WP Staging for WordPress Migration "
|
402 |
-
msgstr ""
|
403 |
-
|
404 |
-
#. Screenshot description.
|
405 |
-
msgid "Finish!"
|
406 |
-
msgstr ""
|
407 |
-
|
408 |
-
#. Screenshot description.
|
409 |
-
msgid "Step 3. Wordpress Staging site creation in progress"
|
410 |
-
msgstr ""
|
411 |
-
|
412 |
-
#. Screenshot description.
|
413 |
-
msgid "Step 2. Scanning your website for files and database tables"
|
414 |
-
msgstr ""
|
415 |
-
|
416 |
-
#. Screenshot description.
|
417 |
-
msgid "Step 1. Create new WordPress staging site"
|
418 |
msgstr ""
|
1 |
+
# Translation of Plugins - WP Staging – DB & File Duplicator & Migration - Stable Readme (latest release) in Italian
|
2 |
+
# This file is distributed under the same license as the Plugins - WP Staging – DB & File Duplicator & Migration - Stable Readme (latest release) package.
|
3 |
+
msgid ""
|
4 |
+
msgstr ""
|
5 |
+
"PO-Revision-Date: 2015-12-01 15:35:13+0000\n"
|
6 |
+
"MIME-Version: 1.0\n"
|
7 |
+
"Content-Type: text/plain; charset=UTF-8\n"
|
8 |
+
"Content-Transfer-Encoding: 8bit\n"
|
9 |
+
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
10 |
+
"X-Generator: GlotPress/2.4.0-alpha\n"
|
11 |
+
"Language: it\n"
|
12 |
+
"Project-Id-Version: Plugins - WP Staging – DB & File Duplicator & Migration - Stable Readme (latest release)\n"
|
13 |
+
|
14 |
+
#. Short description.
|
15 |
+
msgid "A duplicator plugin! Clone, duplicate and migrate live sites to independent staging and development sites that are available only to administrators."
|
16 |
+
msgstr ""
|
17 |
+
|
18 |
+
#. Plugin name.
|
19 |
+
msgid "WP Staging - DB & File Duplicator & Migration"
|
20 |
+
msgstr ""
|
21 |
+
|
22 |
+
#. Found in changelog list item.
|
23 |
+
msgid "Fix: Missing http(s) scheme after cloning multisites results in not working clones"
|
24 |
+
msgstr ""
|
25 |
+
|
26 |
+
#. Found in changelog list item.
|
27 |
+
msgid "New: Support for Windows Azure cloud servers"
|
28 |
+
msgstr ""
|
29 |
+
|
30 |
+
#. Found in changelog list item.
|
31 |
+
msgid "Fix: Do not search & replace mail addresses"
|
32 |
+
msgstr ""
|
33 |
+
|
34 |
+
#. Found in changelog list item.
|
35 |
+
msgid "Fix: Remove term 'Error' from login page"
|
36 |
+
msgstr ""
|
37 |
+
|
38 |
+
#. Found in changelog list item.
|
39 |
+
msgid "New: Login options not needed any more - removed"
|
40 |
+
msgstr ""
|
41 |
+
|
42 |
+
#. Found in changelog list item.
|
43 |
+
msgid "New: Detect if wp-config.php has been moved one folder level up"
|
44 |
+
msgstr ""
|
45 |
+
|
46 |
+
#. Found in changelog list item.
|
47 |
+
msgid "New: Better error reporting"
|
48 |
+
msgstr ""
|
49 |
+
|
50 |
+
#. Found in changelog list item.
|
51 |
+
msgid "New: Compatible up to WordPress 4.9.8"
|
52 |
+
msgstr ""
|
53 |
+
|
54 |
+
#. Found in changelog list item.
|
55 |
+
msgid "New: Setting to specify the maximum allowed file size to copy"
|
56 |
+
msgstr ""
|
57 |
+
|
58 |
+
#. Found in changelog list item.
|
59 |
+
msgid "Fix: Search & replace path not correct if scheme http/https is not identical in wp-config and db wp_options"
|
60 |
+
msgstr ""
|
61 |
+
|
62 |
+
#. Found in changelog list item.
|
63 |
+
msgid "Fix: Creating a new clone resets the custom wp staging user settings. E.g. ignores authentication setting"
|
64 |
+
msgstr ""
|
65 |
+
|
66 |
+
#. Found in changelog list item.
|
67 |
+
msgid "Tweak: Remove certain debugging notices from the default log window"
|
68 |
+
msgstr ""
|
69 |
+
|
70 |
+
#. Found in changelog list item.
|
71 |
+
msgid "Tweaks: remove term \"error\" from several log entries"
|
72 |
+
msgstr ""
|
73 |
+
|
74 |
+
#. Found in changelog list item.
|
75 |
+
msgid "Fix: Search & Replace not working if serialized object contains __PHP_Incomplete_Class_Name"
|
76 |
+
msgstr ""
|
77 |
+
|
78 |
+
#. Found in changelog list item.
|
79 |
+
msgid "Fix: Skip search & replace for objects where key is null"
|
80 |
+
msgstr ""
|
81 |
+
|
82 |
+
#. Found in changelog list item.
|
83 |
+
msgid "Fix: Parameter must be an array or an object that implements Callable"
|
84 |
+
msgstr ""
|
85 |
+
|
86 |
+
#. Found in changelog list item.
|
87 |
+
msgid "Fix: wp-config.php not copied when previous clone updating process has been failed"
|
88 |
+
msgstr ""
|
89 |
+
|
90 |
+
#. Found in changelog list item.
|
91 |
+
msgid "Fix: Undefined object $this->tables"
|
92 |
+
msgstr ""
|
93 |
+
|
94 |
+
#. Found in changelog list item.
|
95 |
+
msgid "Fix: Can not open upload folder in file selection menu"
|
96 |
+
msgstr ""
|
97 |
+
|
98 |
+
#. Found in changelog list item.
|
99 |
+
msgid "Fix: Progress bar not shown as intented for clone updating process"
|
100 |
+
msgstr ""
|
101 |
+
|
102 |
+
#. Found in changelog list item.
|
103 |
+
msgid "Fix: If cloning update process is interupted it may happen that staging site is not available any longer. (Updating the clone does not copy index.php to staging site again)"
|
104 |
+
msgstr ""
|
105 |
+
|
106 |
+
#. Found in changelog list item.
|
107 |
+
msgid "Fix: Progress bar for step 'database' is not filling up to 100%"
|
108 |
+
msgstr ""
|
109 |
+
|
110 |
+
#. Found in changelog list item.
|
111 |
+
msgid "New: Use the new progress bar for clone updating process"
|
112 |
+
msgstr ""
|
113 |
+
|
114 |
+
#. Found in changelog list item.
|
115 |
+
msgid "New: Add multisite informations in system info log"
|
116 |
+
msgstr ""
|
117 |
+
|
118 |
+
#. Found in changelog list item.
|
119 |
+
msgid "New: Option to allow adjustment of the allowed maximum size of files that are going to be copied while cloning."
|
120 |
+
msgstr ""
|
121 |
+
|
122 |
+
#. Found in changelog list item.
|
123 |
+
msgid "Security: Do not allow to create a new staging site into a subfolder which already exists"
|
124 |
+
msgstr ""
|
125 |
+
|
126 |
+
#. Found in changelog list item.
|
127 |
+
msgid "Fix: Missing trailingslash results to wrong absolute paths in database after Search & Replace operation "
|
128 |
+
msgstr ""
|
129 |
+
|
130 |
+
#. Found in changelog list item.
|
131 |
+
msgid "New: Compatible to WordPress 4.9.6"
|
132 |
+
msgstr ""
|
133 |
+
|
134 |
+
#. Found in changelog list item.
|
135 |
+
msgid "New: Add new setting which allow to specify the search & replace processing query limit"
|
136 |
+
msgstr ""
|
137 |
+
|
138 |
+
#. Found in changelog list item.
|
139 |
+
msgid "New: Supports search & replace for revslider image slider and several visual editors which are using non default serialized data"
|
140 |
+
msgstr ""
|
141 |
+
|
142 |
+
#. Found in changelog list item.
|
143 |
+
msgid "New: Add filter 'wpstg_fiter_search_replace_rows' to exclude certain tables from search & replace"
|
144 |
+
msgstr ""
|
145 |
+
|
146 |
+
#. Found in changelog list item.
|
147 |
+
msgid "New: Add datetime timestamp internally to clone. (Used in WP Staging pro)"
|
148 |
+
msgstr ""
|
149 |
+
|
150 |
+
#. Found in changelog list item.
|
151 |
+
msgid "New: Support for custom upload folder. For instance, if upload folder has been renamed and removed outsite wp-content folder"
|
152 |
+
msgstr ""
|
153 |
+
|
154 |
+
#. Found in changelog list item.
|
155 |
+
msgid "New: Exclude tables for plugin wp_mail_smtp"
|
156 |
+
msgstr ""
|
157 |
+
|
158 |
+
#. Found in changelog list item.
|
159 |
+
msgid "New: Add filter 'wpstg_filter_options_replace' to exclude certain tables from updating while cloning"
|
160 |
+
msgstr ""
|
161 |
+
|
162 |
+
#. Found in changelog list item.
|
163 |
+
msgid "Fix: WP_SITEURL & WP_HOME not replaced if constant contains php generated string"
|
164 |
+
msgstr ""
|
165 |
+
|
166 |
+
#. Found in changelog list item.
|
167 |
+
msgid "Fix: Serialize replace is not working properly for serialized strings"
|
168 |
+
msgstr ""
|
169 |
+
|
170 |
+
#. Found in faq list item.
|
171 |
+
msgid ""
|
172 |
+
"I can not login to the staging site\n"
|
173 |
+
"If you are using a security plugin like All In One WP Security & Firewall you need to install latest version of WP Staging. \n"
|
174 |
+
"Go to WP Staging > Settings and add the slug to the custom login page which you set up in All In One WP Security & Firewall plugin."
|
175 |
+
msgstr ""
|
176 |
+
|
177 |
+
#. Found in installation list item, faq list item.
|
178 |
+
msgid "Upload and install it via the WordPress plugin backend wp-admin > plugins > add new > uploads"
|
179 |
+
msgstr ""
|
180 |
+
|
181 |
+
#. Found in installation list item, faq list item.
|
182 |
+
msgid "Download the file \"wp-staging.zip\":"
|
183 |
+
msgstr ""
|
184 |
+
|
185 |
+
#. Found in description paragraph.
|
186 |
+
msgid ""
|
187 |
+
"Permalinks are disabled on the staging site because the staging site is cloned into a subfolder and permalinks are not working on all systems\n"
|
188 |
+
"without doing changes to the .htaccess (Apache server) or nginx.conf (Nginx Server).\n"
|
189 |
+
"<a href=\"https://wp-staging.com/docs/activate-permalinks-staging-site/\" title=\"activate permalinks on staging site\">Read here</a> how to activate permalinks on the staging site."
|
190 |
+
msgstr ""
|
191 |
+
|
192 |
+
#. Found in description list item.
|
193 |
+
msgid "New: Compatible to All In One WP Security & Firewall"
|
194 |
+
msgstr ""
|
195 |
+
|
196 |
+
#. Found in description paragraph.
|
197 |
+
msgid "Note: WordPress 5.0 will be shipped with a new visual editor called Gutenberg. Use WP Staging to check if Gutenberg editor is working as intended on your website and that all used plugins are compatible with that new editor."
|
198 |
+
msgstr ""
|
199 |
+
|
200 |
+
#. Found in changelog paragraph.
|
201 |
+
msgid "Complete changelog: <a href=\"https://wp-staging.com/changelog.txt\">https://wp-staging.com/changelog.txt</a>"
|
202 |
+
msgstr ""
|
203 |
+
|
204 |
+
#. Found in description paragraph.
|
205 |
+
msgid "https://wp-staging.com"
|
206 |
+
msgstr ""
|
207 |
+
|
208 |
+
#. Found in description paragraph.
|
209 |
+
msgid ""
|
210 |
+
"<strong>This cloning and staging plugin is well tested and work in progress. <br /><br />\n"
|
211 |
+
"If you find any issue, please open a <a href=\"https://wp-staging.com/support/\" title=\"support ticket\">support ticket</a>.\n"
|
212 |
+
"</strong>\n"
|
213 |
+
"<br /><br />\n"
|
214 |
+
"<strong>Note: </strong> For pushing & migrating plugins and theme files to live site, check out the pro version <a href=\"https://wp-staging.com/\" title=\"WP Staging Pro\">https://wp-staging.com/</a>\n"
|
215 |
+
"<br /><br />"
|
216 |
+
msgstr ""
|
217 |
+
|
218 |
+
#. Found in faq header.
|
219 |
+
msgid "Installation Instructions"
|
220 |
+
msgstr ""
|
221 |
+
|
222 |
+
#. Found in description list item.
|
223 |
+
msgid ""
|
224 |
+
"WordPress duplicating process on windows server (not tested but will probably work) \n"
|
225 |
+
"Edit: Duplication on windows server seems to be working well: <a href=\"https://wordpress.org/support/topic/wont-copy-files?replies=5\" title=\"Read more\">Read more</a> "
|
226 |
+
msgstr ""
|
227 |
+
|
228 |
+
#. Found in description list item.
|
229 |
+
msgid ""
|
230 |
+
"<strong>Safe: </strong> Access to staging site is granted for administrators only.\n"
|
231 |
+
"<br /><br />\n"
|
232 |
+
"<strong>More safe:</strong> \n"
|
233 |
+
"<br />"
|
234 |
+
msgstr ""
|
235 |
+
|
236 |
+
#. Found in description paragraph.
|
237 |
+
msgid "[youtube https://www.youtube.com/watch?v=Ye3fC6cdB3A]"
|
238 |
+
msgstr ""
|
239 |
+
|
240 |
+
#. Found in description header.
|
241 |
+
msgid "Official Site"
|
242 |
+
msgstr ""
|
243 |
+
|
244 |
+
#. Found in installation list item, faq list item.
|
245 |
+
msgid "Activate the plugin through the 'Plugins' menu in WordPress."
|
246 |
+
msgstr "Attivare il plugin tramite il menu 'Plugin' di WordPress"
|
247 |
+
|
248 |
+
#. Found in description paragraph.
|
249 |
+
msgid ""
|
250 |
+
"Install it via the admin dashboard and to 'Plugins', click 'Add New' and search the plugins for 'Staging'. Install the plugin with 'Install Now'.\n"
|
251 |
+
"After installation goto the settings page 'Staging' and do your adjustments there."
|
252 |
+
msgstr ""
|
253 |
+
|
254 |
+
#. Found in description paragraph.
|
255 |
+
msgid ""
|
256 |
+
"This plugin has been done in hundreds of hours to work on even the smallest shared webhosting package but i am limited in testing this only on a handful of different server so i need your help:\n"
|
257 |
+
"Please open a <a href=\"https://wordpress.org/support/plugin/wp-staging/\" title=\"support request\">support request</a> and describe your problem exactely. In wp-content/wp-staging/logs you find extended logfiles. Have a look at them and let me know the error-thrown lines."
|
258 |
+
msgstr ""
|
259 |
+
|
260 |
+
#. Found in description paragraph.
|
261 |
+
msgid ""
|
262 |
+
"So, if you have created a local or webhosted development site and you need to migrate this site the first time to your production domain than you are doing nothing wrong with using\n"
|
263 |
+
"the Duplicator plugin! If you need all you latest production data like posts, updated plugins, theme data and styles in a testing environment than i recommend to use WP Staging instead!"
|
264 |
+
msgstr ""
|
265 |
+
|
266 |
+
#. Found in description paragraph.
|
267 |
+
msgid ""
|
268 |
+
"At first, i love the <a href=\"https://wordpress.org/plugins/duplicator/\" title=\"Duplicator plugin\">Duplicator plugin</a>. Duplicator is a great tool for migrating from development site to production one or from production site to development one. \n"
|
269 |
+
"The downside is that Duplicator needs adjustments, manually interventions and prerequirements for this. Duplicator also needs some skills to be able to create a development / staging site, where WP Staging does not need more than a click from you.\n"
|
270 |
+
"However, Duplicator is best placed to be a tool for first-time creation of your production site. This is something where it is very handy and powerful."
|
271 |
+
msgstr ""
|
272 |
+
|
273 |
+
#. Found in description paragraph.
|
274 |
+
msgid ""
|
275 |
+
"If you want to migrate your local database to a already existing production site you can use a tool like WP Migrate DB.\n"
|
276 |
+
"WP Staging is only for creating a staging site with latest data from your production site. So it goes the opposite way of WP Migrate DB.\n"
|
277 |
+
"Both tools are excellent cooperating eachother."
|
278 |
+
msgstr ""
|
279 |
+
|
280 |
+
#. Found in description paragraph.
|
281 |
+
msgid "This is were WP Staging steps in... Site cloning and staging site creation simplified!"
|
282 |
+
msgstr ""
|
283 |
+
|
284 |
+
#. Found in description paragraph.
|
285 |
+
msgid ""
|
286 |
+
"Nope! If your local hardware and software environment is not a 100% exact clone of your production server there is NO guarantee that every aspect \n"
|
287 |
+
"of your local copy is working on your live website exactely as you would expect it. \n"
|
288 |
+
"There are some obvious things like differences in the config of php and the server you are running but even such non obvious settings like the amount of ram or the \n"
|
289 |
+
"the cpu performance can lead to unexpected results on your production website. \n"
|
290 |
+
"There are dozens of other possible cause of failure which can not be handled well when you are testing your changes on a local staging platform."
|
291 |
+
msgstr ""
|
292 |
+
|
293 |
+
#. Found in description paragraph.
|
294 |
+
msgid "<strong> I think its time to change this, so i created \"WP Staging\" for WordPress migration of staging sites</strong>"
|
295 |
+
msgstr ""
|
296 |
+
|
297 |
+
#. Found in description paragraph.
|
298 |
+
msgid ""
|
299 |
+
"Some people are also afraid of installing plugins updates because they follow the rule \"never touch a running system\" with having in mind that untested updates are increasing the risk of breaking their site.\n"
|
300 |
+
"I totally understand this and i am guilty as well here, but unfortunately this leads to one of the main reasons why WordPress installations are often outdated, not updated at all and unsecure due to this non-update behavior."
|
301 |
+
msgstr ""
|
302 |
+
|
303 |
+
#. Found in description paragraph.
|
304 |
+
msgid ""
|
305 |
+
"Testing a plugin update before installing it in live environment isn´t done very often by most user because existing staging solutions are too complex and need a lot of time to create a \n"
|
306 |
+
"up-to-date copy of your website."
|
307 |
+
msgstr ""
|
308 |
+
|
309 |
+
#. Found in description paragraph.
|
310 |
+
msgid ""
|
311 |
+
"Plugin updates and theme customizations should be tested on a staging platform first. Its recommended to have the staging platform on the same server where the production website is located.\n"
|
312 |
+
"When you run a plugin update or plan to install a new one, it is a necessary task to check first the modifications on a clone of your production website.\n"
|
313 |
+
"This makes sure that any modifications is working on your website without throwing unexpected errors or preventing your site from loading. (Better known as the wordpress blank page error)"
|
314 |
+
msgstr ""
|
315 |
+
|
316 |
+
#. Found in description paragraph.
|
317 |
+
msgid "<strong>Change your workflow of updating themes and plugins data:</strong>"
|
318 |
+
msgstr ""
|
319 |
+
|
320 |
+
#. Found in description paragraph.
|
321 |
+
msgid "WP Staging helps you to prevent your website from being broken or unavailable because of installing untested plugin updates!"
|
322 |
+
msgstr ""
|
323 |
+
|
324 |
+
#. Found in description paragraph.
|
325 |
+
msgid "<em>* Time of creation depends on size of your database and file size</em>"
|
326 |
+
msgstr ""
|
327 |
+
|
328 |
+
#. Found in description list item.
|
329 |
+
msgid "Everything running as expected? You are on the save side for migration of all these modifications to your production site!"
|
330 |
+
msgstr ""
|
331 |
+
|
332 |
+
#. Found in description list item.
|
333 |
+
msgid "Test everything on your staging site first"
|
334 |
+
msgstr ""
|
335 |
+
|
336 |
+
#. Found in description list item.
|
337 |
+
msgid "Customize theme, configuration and plugins or install new plugins"
|
338 |
+
msgstr ""
|
339 |
+
|
340 |
+
#. Found in description list item.
|
341 |
+
msgid "Use WP Staging for migration of a production website to a clone site for staging purposes"
|
342 |
+
msgstr ""
|
343 |
+
|
344 |
+
#. Found in description list item.
|
345 |
+
msgid "Wordpress migration of wordpress multisites (not tested)"
|
346 |
+
msgstr ""
|
347 |
+
|
348 |
+
#. Found in description list item.
|
349 |
+
msgid "Extensive logging if duplication or migration process should fail."
|
350 |
+
msgstr ""
|
351 |
+
|
352 |
+
#. Found in description list item.
|
353 |
+
msgid "Admin bar reflects that you are working on a staging site"
|
354 |
+
msgstr ""
|
355 |
+
|
356 |
+
#. Found in description list item.
|
357 |
+
msgid "<strong>Fast: </strong> Migration process lasts only a few seconds or minutes, depending on the site's size and server I/O power"
|
358 |
+
msgstr ""
|
359 |
+
|
360 |
+
#. Found in description list item.
|
361 |
+
msgid "<strong>Easy: </strong> Staging migration applicable for everyone. No configuration needed!"
|
362 |
+
msgstr ""
|
363 |
+
|
364 |
+
#. Found in description header.
|
365 |
+
msgid "How to install and setup?"
|
366 |
+
msgstr ""
|
367 |
+
|
368 |
+
#. Found in description header.
|
369 |
+
msgid "Important"
|
370 |
+
msgstr "Wichtig"
|
371 |
+
|
372 |
+
#. Found in description header.
|
373 |
+
msgid "I need you feedback"
|
374 |
+
msgstr ""
|
375 |
+
|
376 |
+
#. Found in description header.
|
377 |
+
msgid "What are the benefits compared to a plugin like Duplicator?"
|
378 |
+
msgstr ""
|
379 |
+
|
380 |
+
#. Found in description header.
|
381 |
+
msgid "I just want to migrate the database from one installation to another"
|
382 |
+
msgstr ""
|
383 |
+
|
384 |
+
#. Found in description header.
|
385 |
+
msgid " Can´t i just use my local wordpress development copy for testing like xampp / lampp? "
|
386 |
+
msgstr ""
|
387 |
+
|
388 |
+
#. Found in description header.
|
389 |
+
msgid " Why should i use a staging website? "
|
390 |
+
msgstr ""
|
391 |
+
|
392 |
+
#. Found in description header.
|
393 |
+
msgid "What does not work or is not tested when running wordpress migration?"
|
394 |
+
msgstr ""
|
395 |
+
|
396 |
+
#. Found in description header.
|
397 |
+
msgid "Main Features"
|
398 |
+
msgstr ""
|
399 |
+
|
400 |
+
#. Found in description header.
|
401 |
+
msgid " WP Staging for WordPress Migration "
|
402 |
+
msgstr ""
|
403 |
+
|
404 |
+
#. Screenshot description.
|
405 |
+
msgid "Finish!"
|
406 |
+
msgstr ""
|
407 |
+
|
408 |
+
#. Screenshot description.
|
409 |
+
msgid "Step 3. Wordpress Staging site creation in progress"
|
410 |
+
msgstr ""
|
411 |
+
|
412 |
+
#. Screenshot description.
|
413 |
+
msgid "Step 2. Scanning your website for files and database tables"
|
414 |
+
msgstr ""
|
415 |
+
|
416 |
+
#. Screenshot description.
|
417 |
+
msgid "Step 1. Create new WordPress staging site"
|
418 |
msgstr ""
|
languages/wp-staging-it_1.po
CHANGED
@@ -1,418 +1,418 @@
|
|
1 |
-
# Translation of Plugins - WP Staging – DB & File Duplicator & Migration - Stable Readme (latest release) in Italian
|
2 |
-
# This file is distributed under the same license as the Plugins - WP Staging – DB & File Duplicator & Migration - Stable Readme (latest release) package.
|
3 |
-
msgid ""
|
4 |
-
msgstr ""
|
5 |
-
"PO-Revision-Date: 2015-12-01 15:35:13+0000\n"
|
6 |
-
"MIME-Version: 1.0\n"
|
7 |
-
"Content-Type: text/plain; charset=UTF-8\n"
|
8 |
-
"Content-Transfer-Encoding: 8bit\n"
|
9 |
-
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
10 |
-
"X-Generator: GlotPress/2.4.0-alpha\n"
|
11 |
-
"Language: it\n"
|
12 |
-
"Project-Id-Version: Plugins - WP Staging – DB & File Duplicator & Migration - Stable Readme (latest release)\n"
|
13 |
-
|
14 |
-
#. Short description.
|
15 |
-
msgid "A duplicator plugin! Clone, duplicate and migrate live sites to independent staging and development sites that are available only to administrators."
|
16 |
-
msgstr ""
|
17 |
-
|
18 |
-
#. Plugin name.
|
19 |
-
msgid "WP Staging - DB & File Duplicator & Migration"
|
20 |
-
msgstr ""
|
21 |
-
|
22 |
-
#. Found in changelog list item.
|
23 |
-
msgid "Fix: Missing http(s) scheme after cloning multisites results in not working clones"
|
24 |
-
msgstr ""
|
25 |
-
|
26 |
-
#. Found in changelog list item.
|
27 |
-
msgid "New: Support for Windows Azure cloud servers"
|
28 |
-
msgstr ""
|
29 |
-
|
30 |
-
#. Found in changelog list item.
|
31 |
-
msgid "Fix: Do not search & replace mail addresses"
|
32 |
-
msgstr ""
|
33 |
-
|
34 |
-
#. Found in changelog list item.
|
35 |
-
msgid "Fix: Remove term 'Error' from login page"
|
36 |
-
msgstr ""
|
37 |
-
|
38 |
-
#. Found in changelog list item.
|
39 |
-
msgid "New: Login options not needed any more - removed"
|
40 |
-
msgstr ""
|
41 |
-
|
42 |
-
#. Found in changelog list item.
|
43 |
-
msgid "New: Detect if wp-config.php has been moved one folder level up"
|
44 |
-
msgstr ""
|
45 |
-
|
46 |
-
#. Found in changelog list item.
|
47 |
-
msgid "New: Better error reporting"
|
48 |
-
msgstr ""
|
49 |
-
|
50 |
-
#. Found in changelog list item.
|
51 |
-
msgid "New: Compatible up to WordPress 4.9.8"
|
52 |
-
msgstr ""
|
53 |
-
|
54 |
-
#. Found in changelog list item.
|
55 |
-
msgid "New: Setting to specify the maximum allowed file size to copy"
|
56 |
-
msgstr ""
|
57 |
-
|
58 |
-
#. Found in changelog list item.
|
59 |
-
msgid "Fix: Search & replace path not correct if scheme http/https is not identical in wp-config and db wp_options"
|
60 |
-
msgstr ""
|
61 |
-
|
62 |
-
#. Found in changelog list item.
|
63 |
-
msgid "Fix: Creating a new clone resets the custom wp staging user settings. E.g. ignores authentication setting"
|
64 |
-
msgstr ""
|
65 |
-
|
66 |
-
#. Found in changelog list item.
|
67 |
-
msgid "Tweak: Remove certain debugging notices from the default log window"
|
68 |
-
msgstr ""
|
69 |
-
|
70 |
-
#. Found in changelog list item.
|
71 |
-
msgid "Tweaks: remove term \"error\" from several log entries"
|
72 |
-
msgstr ""
|
73 |
-
|
74 |
-
#. Found in changelog list item.
|
75 |
-
msgid "Fix: Search & Replace not working if serialized object contains __PHP_Incomplete_Class_Name"
|
76 |
-
msgstr ""
|
77 |
-
|
78 |
-
#. Found in changelog list item.
|
79 |
-
msgid "Fix: Skip search & replace for objects where key is null"
|
80 |
-
msgstr ""
|
81 |
-
|
82 |
-
#. Found in changelog list item.
|
83 |
-
msgid "Fix: Parameter must be an array or an object that implements Callable"
|
84 |
-
msgstr ""
|
85 |
-
|
86 |
-
#. Found in changelog list item.
|
87 |
-
msgid "Fix: wp-config.php not copied when previous clone updating process has been failed"
|
88 |
-
msgstr ""
|
89 |
-
|
90 |
-
#. Found in changelog list item.
|
91 |
-
msgid "Fix: Undefined object $this->tables"
|
92 |
-
msgstr ""
|
93 |
-
|
94 |
-
#. Found in changelog list item.
|
95 |
-
msgid "Fix: Can not open upload folder in file selection menu"
|
96 |
-
msgstr ""
|
97 |
-
|
98 |
-
#. Found in changelog list item.
|
99 |
-
msgid "Fix: Progress bar not shown as intented for clone updating process"
|
100 |
-
msgstr ""
|
101 |
-
|
102 |
-
#. Found in changelog list item.
|
103 |
-
msgid "Fix: If cloning update process is interupted it may happen that staging site is not available any longer. (Updating the clone does not copy index.php to staging site again)"
|
104 |
-
msgstr ""
|
105 |
-
|
106 |
-
#. Found in changelog list item.
|
107 |
-
msgid "Fix: Progress bar for step 'database' is not filling up to 100%"
|
108 |
-
msgstr ""
|
109 |
-
|
110 |
-
#. Found in changelog list item.
|
111 |
-
msgid "New: Use the new progress bar for clone updating process"
|
112 |
-
msgstr ""
|
113 |
-
|
114 |
-
#. Found in changelog list item.
|
115 |
-
msgid "New: Add multisite informations in system info log"
|
116 |
-
msgstr ""
|
117 |
-
|
118 |
-
#. Found in changelog list item.
|
119 |
-
msgid "New: Option to allow adjustment of the allowed maximum size of files that are going to be copied while cloning."
|
120 |
-
msgstr ""
|
121 |
-
|
122 |
-
#. Found in changelog list item.
|
123 |
-
msgid "Security: Do not allow to create a new staging site into a subfolder which already exists"
|
124 |
-
msgstr ""
|
125 |
-
|
126 |
-
#. Found in changelog list item.
|
127 |
-
msgid "Fix: Missing trailingslash results to wrong absolute paths in database after Search & Replace operation "
|
128 |
-
msgstr ""
|
129 |
-
|
130 |
-
#. Found in changelog list item.
|
131 |
-
msgid "New: Compatible to WordPress 4.9.6"
|
132 |
-
msgstr ""
|
133 |
-
|
134 |
-
#. Found in changelog list item.
|
135 |
-
msgid "New: Add new setting which allow to specify the search & replace processing query limit"
|
136 |
-
msgstr ""
|
137 |
-
|
138 |
-
#. Found in changelog list item.
|
139 |
-
msgid "New: Supports search & replace for revslider image slider and several visual editors which are using non default serialized data"
|
140 |
-
msgstr ""
|
141 |
-
|
142 |
-
#. Found in changelog list item.
|
143 |
-
msgid "New: Add filter 'wpstg_fiter_search_replace_rows' to exclude certain tables from search & replace"
|
144 |
-
msgstr ""
|
145 |
-
|
146 |
-
#. Found in changelog list item.
|
147 |
-
msgid "New: Add datetime timestamp internally to clone. (Used in WP Staging pro)"
|
148 |
-
msgstr ""
|
149 |
-
|
150 |
-
#. Found in changelog list item.
|
151 |
-
msgid "New: Support for custom upload folder. For instance, if upload folder has been renamed and removed outsite wp-content folder"
|
152 |
-
msgstr ""
|
153 |
-
|
154 |
-
#. Found in changelog list item.
|
155 |
-
msgid "New: Exclude tables for plugin wp_mail_smtp"
|
156 |
-
msgstr ""
|
157 |
-
|
158 |
-
#. Found in changelog list item.
|
159 |
-
msgid "New: Add filter 'wpstg_filter_options_replace' to exclude certain tables from updating while cloning"
|
160 |
-
msgstr ""
|
161 |
-
|
162 |
-
#. Found in changelog list item.
|
163 |
-
msgid "Fix: WP_SITEURL & WP_HOME not replaced if constant contains php generated string"
|
164 |
-
msgstr ""
|
165 |
-
|
166 |
-
#. Found in changelog list item.
|
167 |
-
msgid "Fix: Serialize replace is not working properly for serialized strings"
|
168 |
-
msgstr ""
|
169 |
-
|
170 |
-
#. Found in faq list item.
|
171 |
-
msgid ""
|
172 |
-
"I can not login to the staging site\n"
|
173 |
-
"If you are using a security plugin like All In One WP Security & Firewall you need to install latest version of WP Staging. \n"
|
174 |
-
"Go to WP Staging > Settings and add the slug to the custom login page which you set up in All In One WP Security & Firewall plugin."
|
175 |
-
msgstr ""
|
176 |
-
|
177 |
-
#. Found in installation list item, faq list item.
|
178 |
-
msgid "Upload and install it via the WordPress plugin backend wp-admin > plugins > add new > uploads"
|
179 |
-
msgstr ""
|
180 |
-
|
181 |
-
#. Found in installation list item, faq list item.
|
182 |
-
msgid "Download the file \"wp-staging.zip\":"
|
183 |
-
msgstr ""
|
184 |
-
|
185 |
-
#. Found in description paragraph.
|
186 |
-
msgid ""
|
187 |
-
"Permalinks are disabled on the staging site because the staging site is cloned into a subfolder and permalinks are not working on all systems\n"
|
188 |
-
"without doing changes to the .htaccess (Apache server) or nginx.conf (Nginx Server).\n"
|
189 |
-
"<a href=\"https://wp-staging.com/docs/activate-permalinks-staging-site/\" title=\"activate permalinks on staging site\">Read here</a> how to activate permalinks on the staging site."
|
190 |
-
msgstr ""
|
191 |
-
|
192 |
-
#. Found in description list item.
|
193 |
-
msgid "New: Compatible to All In One WP Security & Firewall"
|
194 |
-
msgstr ""
|
195 |
-
|
196 |
-
#. Found in description paragraph.
|
197 |
-
msgid "Note: WordPress 5.0 will be shipped with a new visual editor called Gutenberg. Use WP Staging to check if Gutenberg editor is working as intended on your website and that all used plugins are compatible with that new editor."
|
198 |
-
msgstr ""
|
199 |
-
|
200 |
-
#. Found in changelog paragraph.
|
201 |
-
msgid "Complete changelog: <a href=\"https://wp-staging.com/changelog.txt\">https://wp-staging.com/changelog.txt</a>"
|
202 |
-
msgstr ""
|
203 |
-
|
204 |
-
#. Found in description paragraph.
|
205 |
-
msgid "https://wp-staging.com"
|
206 |
-
msgstr ""
|
207 |
-
|
208 |
-
#. Found in description paragraph.
|
209 |
-
msgid ""
|
210 |
-
"<strong>This cloning and staging plugin is well tested and work in progress. <br /><br />\n"
|
211 |
-
"If you find any issue, please open a <a href=\"https://wp-staging.com/support/\" title=\"support ticket\">support ticket</a>.\n"
|
212 |
-
"</strong>\n"
|
213 |
-
"<br /><br />\n"
|
214 |
-
"<strong>Note: </strong> For pushing & migrating plugins and theme files to live site, check out the pro version <a href=\"https://wp-staging.com/\" title=\"WP Staging Pro\">https://wp-staging.com/</a>\n"
|
215 |
-
"<br /><br />"
|
216 |
-
msgstr ""
|
217 |
-
|
218 |
-
#. Found in faq header.
|
219 |
-
msgid "Installation Instructions"
|
220 |
-
msgstr ""
|
221 |
-
|
222 |
-
#. Found in description list item.
|
223 |
-
msgid ""
|
224 |
-
"WordPress duplicating process on windows server (not tested but will probably work) \n"
|
225 |
-
"Edit: Duplication on windows server seems to be working well: <a href=\"https://wordpress.org/support/topic/wont-copy-files?replies=5\" title=\"Read more\">Read more</a> "
|
226 |
-
msgstr ""
|
227 |
-
|
228 |
-
#. Found in description list item.
|
229 |
-
msgid ""
|
230 |
-
"<strong>Safe: </strong> Access to staging site is granted for administrators only.\n"
|
231 |
-
"<br /><br />\n"
|
232 |
-
"<strong>More safe:</strong> \n"
|
233 |
-
"<br />"
|
234 |
-
msgstr ""
|
235 |
-
|
236 |
-
#. Found in description paragraph.
|
237 |
-
msgid "[youtube https://www.youtube.com/watch?v=Ye3fC6cdB3A]"
|
238 |
-
msgstr ""
|
239 |
-
|
240 |
-
#. Found in description header.
|
241 |
-
msgid "Official Site"
|
242 |
-
msgstr ""
|
243 |
-
|
244 |
-
#. Found in installation list item, faq list item.
|
245 |
-
msgid "Activate the plugin through the 'Plugins' menu in WordPress."
|
246 |
-
msgstr "Attivare il plugin tramite il menu 'Plugin' di WordPress"
|
247 |
-
|
248 |
-
#. Found in description paragraph.
|
249 |
-
msgid ""
|
250 |
-
"Install it via the admin dashboard and to 'Plugins', click 'Add New' and search the plugins for 'Staging'. Install the plugin with 'Install Now'.\n"
|
251 |
-
"After installation goto the settings page 'Staging' and do your adjustments there."
|
252 |
-
msgstr ""
|
253 |
-
|
254 |
-
#. Found in description paragraph.
|
255 |
-
msgid ""
|
256 |
-
"This plugin has been done in hundreds of hours to work on even the smallest shared webhosting package but i am limited in testing this only on a handful of different server so i need your help:\n"
|
257 |
-
"Please open a <a href=\"https://wordpress.org/support/plugin/wp-staging/\" title=\"support request\">support request</a> and describe your problem exactely. In wp-content/wp-staging/logs you find extended logfiles. Have a look at them and let me know the error-thrown lines."
|
258 |
-
msgstr ""
|
259 |
-
|
260 |
-
#. Found in description paragraph.
|
261 |
-
msgid ""
|
262 |
-
"So, if you have created a local or webhosted development site and you need to migrate this site the first time to your production domain than you are doing nothing wrong with using\n"
|
263 |
-
"the Duplicator plugin! If you need all you latest production data like posts, updated plugins, theme data and styles in a testing environment than i recommend to use WP Staging instead!"
|
264 |
-
msgstr ""
|
265 |
-
|
266 |
-
#. Found in description paragraph.
|
267 |
-
msgid ""
|
268 |
-
"At first, i love the <a href=\"https://wordpress.org/plugins/duplicator/\" title=\"Duplicator plugin\">Duplicator plugin</a>. Duplicator is a great tool for migrating from development site to production one or from production site to development one. \n"
|
269 |
-
"The downside is that Duplicator needs adjustments, manually interventions and prerequirements for this. Duplicator also needs some skills to be able to create a development / staging site, where WP Staging does not need more than a click from you.\n"
|
270 |
-
"However, Duplicator is best placed to be a tool for first-time creation of your production site. This is something where it is very handy and powerful."
|
271 |
-
msgstr ""
|
272 |
-
|
273 |
-
#. Found in description paragraph.
|
274 |
-
msgid ""
|
275 |
-
"If you want to migrate your local database to a already existing production site you can use a tool like WP Migrate DB.\n"
|
276 |
-
"WP Staging is only for creating a staging site with latest data from your production site. So it goes the opposite way of WP Migrate DB.\n"
|
277 |
-
"Both tools are excellent cooperating eachother."
|
278 |
-
msgstr ""
|
279 |
-
|
280 |
-
#. Found in description paragraph.
|
281 |
-
msgid "This is were WP Staging steps in... Site cloning and staging site creation simplified!"
|
282 |
-
msgstr ""
|
283 |
-
|
284 |
-
#. Found in description paragraph.
|
285 |
-
msgid ""
|
286 |
-
"Nope! If your local hardware and software environment is not a 100% exact clone of your production server there is NO guarantee that every aspect \n"
|
287 |
-
"of your local copy is working on your live website exactely as you would expect it. \n"
|
288 |
-
"There are some obvious things like differences in the config of php and the server you are running but even such non obvious settings like the amount of ram or the \n"
|
289 |
-
"the cpu performance can lead to unexpected results on your production website. \n"
|
290 |
-
"There are dozens of other possible cause of failure which can not be handled well when you are testing your changes on a local staging platform."
|
291 |
-
msgstr ""
|
292 |
-
|
293 |
-
#. Found in description paragraph.
|
294 |
-
msgid "<strong> I think its time to change this, so i created \"WP Staging\" for WordPress migration of staging sites</strong>"
|
295 |
-
msgstr ""
|
296 |
-
|
297 |
-
#. Found in description paragraph.
|
298 |
-
msgid ""
|
299 |
-
"Some people are also afraid of installing plugins updates because they follow the rule \"never touch a running system\" with having in mind that untested updates are increasing the risk of breaking their site.\n"
|
300 |
-
"I totally understand this and i am guilty as well here, but unfortunately this leads to one of the main reasons why WordPress installations are often outdated, not updated at all and unsecure due to this non-update behavior."
|
301 |
-
msgstr ""
|
302 |
-
|
303 |
-
#. Found in description paragraph.
|
304 |
-
msgid ""
|
305 |
-
"Testing a plugin update before installing it in live environment isn´t done very often by most user because existing staging solutions are too complex and need a lot of time to create a \n"
|
306 |
-
"up-to-date copy of your website."
|
307 |
-
msgstr ""
|
308 |
-
|
309 |
-
#. Found in description paragraph.
|
310 |
-
msgid ""
|
311 |
-
"Plugin updates and theme customizations should be tested on a staging platform first. Its recommended to have the staging platform on the same server where the production website is located.\n"
|
312 |
-
"When you run a plugin update or plan to install a new one, it is a necessary task to check first the modifications on a clone of your production website.\n"
|
313 |
-
"This makes sure that any modifications is working on your website without throwing unexpected errors or preventing your site from loading. (Better known as the wordpress blank page error)"
|
314 |
-
msgstr ""
|
315 |
-
|
316 |
-
#. Found in description paragraph.
|
317 |
-
msgid "<strong>Change your workflow of updating themes and plugins data:</strong>"
|
318 |
-
msgstr ""
|
319 |
-
|
320 |
-
#. Found in description paragraph.
|
321 |
-
msgid "WP Staging helps you to prevent your website from being broken or unavailable because of installing untested plugin updates!"
|
322 |
-
msgstr ""
|
323 |
-
|
324 |
-
#. Found in description paragraph.
|
325 |
-
msgid "<em>* Time of creation depends on size of your database and file size</em>"
|
326 |
-
msgstr ""
|
327 |
-
|
328 |
-
#. Found in description list item.
|
329 |
-
msgid "Everything running as expected? You are on the save side for migration of all these modifications to your production site!"
|
330 |
-
msgstr ""
|
331 |
-
|
332 |
-
#. Found in description list item.
|
333 |
-
msgid "Test everything on your staging site first"
|
334 |
-
msgstr ""
|
335 |
-
|
336 |
-
#. Found in description list item.
|
337 |
-
msgid "Customize theme, configuration and plugins or install new plugins"
|
338 |
-
msgstr ""
|
339 |
-
|
340 |
-
#. Found in description list item.
|
341 |
-
msgid "Use WP Staging for migration of a production website to a clone site for staging purposes"
|
342 |
-
msgstr ""
|
343 |
-
|
344 |
-
#. Found in description list item.
|
345 |
-
msgid "Wordpress migration of wordpress multisites (not tested)"
|
346 |
-
msgstr ""
|
347 |
-
|
348 |
-
#. Found in description list item.
|
349 |
-
msgid "Extensive logging if duplication or migration process should fail."
|
350 |
-
msgstr ""
|
351 |
-
|
352 |
-
#. Found in description list item.
|
353 |
-
msgid "Admin bar reflects that you are working on a staging site"
|
354 |
-
msgstr ""
|
355 |
-
|
356 |
-
#. Found in description list item.
|
357 |
-
msgid "<strong>Fast: </strong> Migration process lasts only a few seconds or minutes, depending on the site's size and server I/O power"
|
358 |
-
msgstr ""
|
359 |
-
|
360 |
-
#. Found in description list item.
|
361 |
-
msgid "<strong>Easy: </strong> Staging migration applicable for everyone. No configuration needed!"
|
362 |
-
msgstr ""
|
363 |
-
|
364 |
-
#. Found in description header.
|
365 |
-
msgid "How to install and setup?"
|
366 |
-
msgstr ""
|
367 |
-
|
368 |
-
#. Found in description header.
|
369 |
-
msgid "Important"
|
370 |
-
msgstr "Wichtig"
|
371 |
-
|
372 |
-
#. Found in description header.
|
373 |
-
msgid "I need you feedback"
|
374 |
-
msgstr ""
|
375 |
-
|
376 |
-
#. Found in description header.
|
377 |
-
msgid "What are the benefits compared to a plugin like Duplicator?"
|
378 |
-
msgstr ""
|
379 |
-
|
380 |
-
#. Found in description header.
|
381 |
-
msgid "I just want to migrate the database from one installation to another"
|
382 |
-
msgstr ""
|
383 |
-
|
384 |
-
#. Found in description header.
|
385 |
-
msgid " Can´t i just use my local wordpress development copy for testing like xampp / lampp? "
|
386 |
-
msgstr ""
|
387 |
-
|
388 |
-
#. Found in description header.
|
389 |
-
msgid " Why should i use a staging website? "
|
390 |
-
msgstr ""
|
391 |
-
|
392 |
-
#. Found in description header.
|
393 |
-
msgid "What does not work or is not tested when running wordpress migration?"
|
394 |
-
msgstr ""
|
395 |
-
|
396 |
-
#. Found in description header.
|
397 |
-
msgid "Main Features"
|
398 |
-
msgstr ""
|
399 |
-
|
400 |
-
#. Found in description header.
|
401 |
-
msgid " WP Staging for WordPress Migration "
|
402 |
-
msgstr ""
|
403 |
-
|
404 |
-
#. Screenshot description.
|
405 |
-
msgid "Finish!"
|
406 |
-
msgstr ""
|
407 |
-
|
408 |
-
#. Screenshot description.
|
409 |
-
msgid "Step 3. Wordpress Staging site creation in progress"
|
410 |
-
msgstr ""
|
411 |
-
|
412 |
-
#. Screenshot description.
|
413 |
-
msgid "Step 2. Scanning your website for files and database tables"
|
414 |
-
msgstr ""
|
415 |
-
|
416 |
-
#. Screenshot description.
|
417 |
-
msgid "Step 1. Create new WordPress staging site"
|
418 |
msgstr ""
|
1 |
+
# Translation of Plugins - WP Staging – DB & File Duplicator & Migration - Stable Readme (latest release) in Italian
|
2 |
+
# This file is distributed under the same license as the Plugins - WP Staging – DB & File Duplicator & Migration - Stable Readme (latest release) package.
|
3 |
+
msgid ""
|
4 |
+
msgstr ""
|
5 |
+
"PO-Revision-Date: 2015-12-01 15:35:13+0000\n"
|
6 |
+
"MIME-Version: 1.0\n"
|
7 |
+
"Content-Type: text/plain; charset=UTF-8\n"
|
8 |
+
"Content-Transfer-Encoding: 8bit\n"
|
9 |
+
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
10 |
+
"X-Generator: GlotPress/2.4.0-alpha\n"
|
11 |
+
"Language: it\n"
|
12 |
+
"Project-Id-Version: Plugins - WP Staging – DB & File Duplicator & Migration - Stable Readme (latest release)\n"
|
13 |
+
|
14 |
+
#. Short description.
|
15 |
+
msgid "A duplicator plugin! Clone, duplicate and migrate live sites to independent staging and development sites that are available only to administrators."
|
16 |
+
msgstr ""
|
17 |
+
|
18 |
+
#. Plugin name.
|
19 |
+
msgid "WP Staging - DB & File Duplicator & Migration"
|
20 |
+
msgstr ""
|
21 |
+
|
22 |
+
#. Found in changelog list item.
|
23 |
+
msgid "Fix: Missing http(s) scheme after cloning multisites results in not working clones"
|
24 |
+
msgstr ""
|
25 |
+
|
26 |
+
#. Found in changelog list item.
|
27 |
+
msgid "New: Support for Windows Azure cloud servers"
|
28 |
+
msgstr ""
|
29 |
+
|
30 |
+
#. Found in changelog list item.
|
31 |
+
msgid "Fix: Do not search & replace mail addresses"
|
32 |
+
msgstr ""
|
33 |
+
|
34 |
+
#. Found in changelog list item.
|
35 |
+
msgid "Fix: Remove term 'Error' from login page"
|
36 |
+
msgstr ""
|
37 |
+
|
38 |
+
#. Found in changelog list item.
|
39 |
+
msgid "New: Login options not needed any more - removed"
|
40 |
+
msgstr ""
|
41 |
+
|
42 |
+
#. Found in changelog list item.
|
43 |
+
msgid "New: Detect if wp-config.php has been moved one folder level up"
|
44 |
+
msgstr ""
|
45 |
+
|
46 |
+
#. Found in changelog list item.
|
47 |
+
msgid "New: Better error reporting"
|
48 |
+
msgstr ""
|
49 |
+
|
50 |
+
#. Found in changelog list item.
|
51 |
+
msgid "New: Compatible up to WordPress 4.9.8"
|
52 |
+
msgstr ""
|
53 |
+
|
54 |
+
#. Found in changelog list item.
|
55 |
+
msgid "New: Setting to specify the maximum allowed file size to copy"
|
56 |
+
msgstr ""
|
57 |
+
|
58 |
+
#. Found in changelog list item.
|
59 |
+
msgid "Fix: Search & replace path not correct if scheme http/https is not identical in wp-config and db wp_options"
|
60 |
+
msgstr ""
|
61 |
+
|
62 |
+
#. Found in changelog list item.
|
63 |
+
msgid "Fix: Creating a new clone resets the custom wp staging user settings. E.g. ignores authentication setting"
|
64 |
+
msgstr ""
|
65 |
+
|
66 |
+
#. Found in changelog list item.
|
67 |
+
msgid "Tweak: Remove certain debugging notices from the default log window"
|
68 |
+
msgstr ""
|
69 |
+
|
70 |
+
#. Found in changelog list item.
|
71 |
+
msgid "Tweaks: remove term \"error\" from several log entries"
|
72 |
+
msgstr ""
|
73 |
+
|
74 |
+
#. Found in changelog list item.
|
75 |
+
msgid "Fix: Search & Replace not working if serialized object contains __PHP_Incomplete_Class_Name"
|
76 |
+
msgstr ""
|
77 |
+
|
78 |
+
#. Found in changelog list item.
|
79 |
+
msgid "Fix: Skip search & replace for objects where key is null"
|
80 |
+
msgstr ""
|
81 |
+
|
82 |
+
#. Found in changelog list item.
|
83 |
+
msgid "Fix: Parameter must be an array or an object that implements Callable"
|
84 |
+
msgstr ""
|
85 |
+
|
86 |
+
#. Found in changelog list item.
|
87 |
+
msgid "Fix: wp-config.php not copied when previous clone updating process has been failed"
|
88 |
+
msgstr ""
|
89 |
+
|
90 |
+
#. Found in changelog list item.
|
91 |
+
msgid "Fix: Undefined object $this->tables"
|
92 |
+
msgstr ""
|
93 |
+
|
94 |
+
#. Found in changelog list item.
|
95 |
+
msgid "Fix: Can not open upload folder in file selection menu"
|
96 |
+
msgstr ""
|
97 |
+
|
98 |
+
#. Found in changelog list item.
|
99 |
+
msgid "Fix: Progress bar not shown as intented for clone updating process"
|
100 |
+
msgstr ""
|
101 |
+
|
102 |
+
#. Found in changelog list item.
|
103 |
+
msgid "Fix: If cloning update process is interupted it may happen that staging site is not available any longer. (Updating the clone does not copy index.php to staging site again)"
|
104 |
+
msgstr ""
|
105 |
+
|
106 |
+
#. Found in changelog list item.
|
107 |
+
msgid "Fix: Progress bar for step 'database' is not filling up to 100%"
|
108 |
+
msgstr ""
|
109 |
+
|
110 |
+
#. Found in changelog list item.
|
111 |
+
msgid "New: Use the new progress bar for clone updating process"
|
112 |
+
msgstr ""
|
113 |
+
|
114 |
+
#. Found in changelog list item.
|
115 |
+
msgid "New: Add multisite informations in system info log"
|
116 |
+
msgstr ""
|
117 |
+
|
118 |
+
#. Found in changelog list item.
|
119 |
+
msgid "New: Option to allow adjustment of the allowed maximum size of files that are going to be copied while cloning."
|
120 |
+
msgstr ""
|
121 |
+
|
122 |
+
#. Found in changelog list item.
|
123 |
+
msgid "Security: Do not allow to create a new staging site into a subfolder which already exists"
|
124 |
+
msgstr ""
|
125 |
+
|
126 |
+
#. Found in changelog list item.
|
127 |
+
msgid "Fix: Missing trailingslash results to wrong absolute paths in database after Search & Replace operation "
|
128 |
+
msgstr ""
|
129 |
+
|
130 |
+
#. Found in changelog list item.
|
131 |
+
msgid "New: Compatible to WordPress 4.9.6"
|
132 |
+
msgstr ""
|
133 |
+
|
134 |
+
#. Found in changelog list item.
|
135 |
+
msgid "New: Add new setting which allow to specify the search & replace processing query limit"
|
136 |
+
msgstr ""
|
137 |
+
|
138 |
+
#. Found in changelog list item.
|
139 |
+
msgid "New: Supports search & replace for revslider image slider and several visual editors which are using non default serialized data"
|
140 |
+
msgstr ""
|
141 |
+
|
142 |
+
#. Found in changelog list item.
|
143 |
+
msgid "New: Add filter 'wpstg_fiter_search_replace_rows' to exclude certain tables from search & replace"
|
144 |
+
msgstr ""
|
145 |
+
|
146 |
+
#. Found in changelog list item.
|
147 |
+
msgid "New: Add datetime timestamp internally to clone. (Used in WP Staging pro)"
|
148 |
+
msgstr ""
|
149 |
+
|
150 |
+
#. Found in changelog list item.
|
151 |
+
msgid "New: Support for custom upload folder. For instance, if upload folder has been renamed and removed outsite wp-content folder"
|
152 |
+
msgstr ""
|
153 |
+
|
154 |
+
#. Found in changelog list item.
|
155 |
+
msgid "New: Exclude tables for plugin wp_mail_smtp"
|
156 |
+
msgstr ""
|
157 |
+
|
158 |
+
#. Found in changelog list item.
|
159 |
+
msgid "New: Add filter 'wpstg_filter_options_replace' to exclude certain tables from updating while cloning"
|
160 |
+
msgstr ""
|
161 |
+
|
162 |
+
#. Found in changelog list item.
|
163 |
+
msgid "Fix: WP_SITEURL & WP_HOME not replaced if constant contains php generated string"
|
164 |
+
msgstr ""
|
165 |
+
|
166 |
+
#. Found in changelog list item.
|
167 |
+
msgid "Fix: Serialize replace is not working properly for serialized strings"
|
168 |
+
msgstr ""
|
169 |
+
|
170 |
+
#. Found in faq list item.
|
171 |
+
msgid ""
|
172 |
+
"I can not login to the staging site\n"
|
173 |
+
"If you are using a security plugin like All In One WP Security & Firewall you need to install latest version of WP Staging. \n"
|
174 |
+
"Go to WP Staging > Settings and add the slug to the custom login page which you set up in All In One WP Security & Firewall plugin."
|
175 |
+
msgstr ""
|
176 |
+
|
177 |
+
#. Found in installation list item, faq list item.
|
178 |
+
msgid "Upload and install it via the WordPress plugin backend wp-admin > plugins > add new > uploads"
|
179 |
+
msgstr ""
|
180 |
+
|
181 |
+
#. Found in installation list item, faq list item.
|
182 |
+
msgid "Download the file \"wp-staging.zip\":"
|
183 |
+
msgstr ""
|
184 |
+
|
185 |
+
#. Found in description paragraph.
|
186 |
+
msgid ""
|
187 |
+
"Permalinks are disabled on the staging site because the staging site is cloned into a subfolder and permalinks are not working on all systems\n"
|
188 |
+
"without doing changes to the .htaccess (Apache server) or nginx.conf (Nginx Server).\n"
|
189 |
+
"<a href=\"https://wp-staging.com/docs/activate-permalinks-staging-site/\" title=\"activate permalinks on staging site\">Read here</a> how to activate permalinks on the staging site."
|
190 |
+
msgstr ""
|
191 |
+
|
192 |
+
#. Found in description list item.
|
193 |
+
msgid "New: Compatible to All In One WP Security & Firewall"
|
194 |
+
msgstr ""
|
195 |
+
|
196 |
+
#. Found in description paragraph.
|
197 |
+
msgid "Note: WordPress 5.0 will be shipped with a new visual editor called Gutenberg. Use WP Staging to check if Gutenberg editor is working as intended on your website and that all used plugins are compatible with that new editor."
|
198 |
+
msgstr ""
|
199 |
+
|
200 |
+
#. Found in changelog paragraph.
|
201 |
+
msgid "Complete changelog: <a href=\"https://wp-staging.com/changelog.txt\">https://wp-staging.com/changelog.txt</a>"
|
202 |
+
msgstr ""
|
203 |
+
|
204 |
+
#. Found in description paragraph.
|
205 |
+
msgid "https://wp-staging.com"
|
206 |
+
msgstr ""
|
207 |
+
|
208 |
+
#. Found in description paragraph.
|
209 |
+
msgid ""
|
210 |
+
"<strong>This cloning and staging plugin is well tested and work in progress. <br /><br />\n"
|
211 |
+
"If you find any issue, please open a <a href=\"https://wp-staging.com/support/\" title=\"support ticket\">support ticket</a>.\n"
|
212 |
+
"</strong>\n"
|
213 |
+
"<br /><br />\n"
|
214 |
+
"<strong>Note: </strong> For pushing & migrating plugins and theme files to live site, check out the pro version <a href=\"https://wp-staging.com/\" title=\"WP Staging Pro\">https://wp-staging.com/</a>\n"
|
215 |
+
"<br /><br />"
|
216 |
+
msgstr ""
|
217 |
+
|
218 |
+
#. Found in faq header.
|
219 |
+
msgid "Installation Instructions"
|
220 |
+
msgstr ""
|
221 |
+
|
222 |
+
#. Found in description list item.
|
223 |
+
msgid ""
|
224 |
+
"WordPress duplicating process on windows server (not tested but will probably work) \n"
|
225 |
+
"Edit: Duplication on windows server seems to be working well: <a href=\"https://wordpress.org/support/topic/wont-copy-files?replies=5\" title=\"Read more\">Read more</a> "
|
226 |
+
msgstr ""
|
227 |
+
|
228 |
+
#. Found in description list item.
|
229 |
+
msgid ""
|
230 |
+
"<strong>Safe: </strong> Access to staging site is granted for administrators only.\n"
|
231 |
+
"<br /><br />\n"
|
232 |
+
"<strong>More safe:</strong> \n"
|
233 |
+
"<br />"
|
234 |
+
msgstr ""
|
235 |
+
|
236 |
+
#. Found in description paragraph.
|
237 |
+
msgid "[youtube https://www.youtube.com/watch?v=Ye3fC6cdB3A]"
|
238 |
+
msgstr ""
|
239 |
+
|
240 |
+
#. Found in description header.
|
241 |
+
msgid "Official Site"
|
242 |
+
msgstr ""
|
243 |
+
|
244 |
+
#. Found in installation list item, faq list item.
|
245 |
+
msgid "Activate the plugin through the 'Plugins' menu in WordPress."
|
246 |
+
msgstr "Attivare il plugin tramite il menu 'Plugin' di WordPress"
|
247 |
+
|
248 |
+
#. Found in description paragraph.
|
249 |
+
msgid ""
|
250 |
+
"Install it via the admin dashboard and to 'Plugins', click 'Add New' and search the plugins for 'Staging'. Install the plugin with 'Install Now'.\n"
|
251 |
+
"After installation goto the settings page 'Staging' and do your adjustments there."
|
252 |
+
msgstr ""
|
253 |
+
|
254 |
+
#. Found in description paragraph.
|
255 |
+
msgid ""
|
256 |
+
"This plugin has been done in hundreds of hours to work on even the smallest shared webhosting package but i am limited in testing this only on a handful of different server so i need your help:\n"
|
257 |
+
"Please open a <a href=\"https://wordpress.org/support/plugin/wp-staging/\" title=\"support request\">support request</a> and describe your problem exactely. In wp-content/wp-staging/logs you find extended logfiles. Have a look at them and let me know the error-thrown lines."
|
258 |
+
msgstr ""
|
259 |
+
|
260 |
+
#. Found in description paragraph.
|
261 |
+
msgid ""
|
262 |
+
"So, if you have created a local or webhosted development site and you need to migrate this site the first time to your production domain than you are doing nothing wrong with using\n"
|
263 |
+
"the Duplicator plugin! If you need all you latest production data like posts, updated plugins, theme data and styles in a testing environment than i recommend to use WP Staging instead!"
|
264 |
+
msgstr ""
|
265 |
+
|
266 |
+
#. Found in description paragraph.
|
267 |
+
msgid ""
|
268 |
+
"At first, i love the <a href=\"https://wordpress.org/plugins/duplicator/\" title=\"Duplicator plugin\">Duplicator plugin</a>. Duplicator is a great tool for migrating from development site to production one or from production site to development one. \n"
|
269 |
+
"The downside is that Duplicator needs adjustments, manually interventions and prerequirements for this. Duplicator also needs some skills to be able to create a development / staging site, where WP Staging does not need more than a click from you.\n"
|
270 |
+
"However, Duplicator is best placed to be a tool for first-time creation of your production site. This is something where it is very handy and powerful."
|
271 |
+
msgstr ""
|
272 |
+
|
273 |
+
#. Found in description paragraph.
|
274 |
+
msgid ""
|
275 |
+
"If you want to migrate your local database to a already existing production site you can use a tool like WP Migrate DB.\n"
|
276 |
+
"WP Staging is only for creating a staging site with latest data from your production site. So it goes the opposite way of WP Migrate DB.\n"
|
277 |
+
"Both tools are excellent cooperating eachother."
|
278 |
+
msgstr ""
|
279 |
+
|
280 |
+
#. Found in description paragraph.
|
281 |
+
msgid "This is were WP Staging steps in... Site cloning and staging site creation simplified!"
|
282 |
+
msgstr ""
|
283 |
+
|
284 |
+
#. Found in description paragraph.
|
285 |
+
msgid ""
|
286 |
+
"Nope! If your local hardware and software environment is not a 100% exact clone of your production server there is NO guarantee that every aspect \n"
|
287 |
+
"of your local copy is working on your live website exactely as you would expect it. \n"
|
288 |
+
"There are some obvious things like differences in the config of php and the server you are running but even such non obvious settings like the amount of ram or the \n"
|
289 |
+
"the cpu performance can lead to unexpected results on your production website. \n"
|
290 |
+
"There are dozens of other possible cause of failure which can not be handled well when you are testing your changes on a local staging platform."
|
291 |
+
msgstr ""
|
292 |
+
|
293 |
+
#. Found in description paragraph.
|
294 |
+
msgid "<strong> I think its time to change this, so i created \"WP Staging\" for WordPress migration of staging sites</strong>"
|
295 |
+
msgstr ""
|
296 |
+
|
297 |
+
#. Found in description paragraph.
|
298 |
+
msgid ""
|
299 |
+
"Some people are also afraid of installing plugins updates because they follow the rule \"never touch a running system\" with having in mind that untested updates are increasing the risk of breaking their site.\n"
|
300 |
+
"I totally understand this and i am guilty as well here, but unfortunately this leads to one of the main reasons why WordPress installations are often outdated, not updated at all and unsecure due to this non-update behavior."
|
301 |
+
msgstr ""
|
302 |
+
|
303 |
+
#. Found in description paragraph.
|
304 |
+
msgid ""
|
305 |
+
"Testing a plugin update before installing it in live environment isn´t done very often by most user because existing staging solutions are too complex and need a lot of time to create a \n"
|
306 |
+
"up-to-date copy of your website."
|
307 |
+
msgstr ""
|
308 |
+
|
309 |
+
#. Found in description paragraph.
|
310 |
+
msgid ""
|
311 |
+
"Plugin updates and theme customizations should be tested on a staging platform first. Its recommended to have the staging platform on the same server where the production website is located.\n"
|
312 |
+
"When you run a plugin update or plan to install a new one, it is a necessary task to check first the modifications on a clone of your production website.\n"
|
313 |
+
"This makes sure that any modifications is working on your website without throwing unexpected errors or preventing your site from loading. (Better known as the wordpress blank page error)"
|
314 |
+
msgstr ""
|
315 |
+
|
316 |
+
#. Found in description paragraph.
|
317 |
+
msgid "<strong>Change your workflow of updating themes and plugins data:</strong>"
|
318 |
+
msgstr ""
|
319 |
+
|
320 |
+
#. Found in description paragraph.
|
321 |
+
msgid "WP Staging helps you to prevent your website from being broken or unavailable because of installing untested plugin updates!"
|
322 |
+
msgstr ""
|
323 |
+
|
324 |
+
#. Found in description paragraph.
|
325 |
+
msgid "<em>* Time of creation depends on size of your database and file size</em>"
|
326 |
+
msgstr ""
|
327 |
+
|
328 |
+
#. Found in description list item.
|
329 |
+
msgid "Everything running as expected? You are on the save side for migration of all these modifications to your production site!"
|
330 |
+
msgstr ""
|
331 |
+
|
332 |
+
#. Found in description list item.
|
333 |
+
msgid "Test everything on your staging site first"
|
334 |
+
msgstr ""
|
335 |
+
|
336 |
+
#. Found in description list item.
|
337 |
+
msgid "Customize theme, configuration and plugins or install new plugins"
|
338 |
+
msgstr ""
|
339 |
+
|
340 |
+
#. Found in description list item.
|
341 |
+
msgid "Use WP Staging for migration of a production website to a clone site for staging purposes"
|
342 |
+
msgstr ""
|
343 |
+
|
344 |
+
#. Found in description list item.
|
345 |
+
msgid "Wordpress migration of wordpress multisites (not tested)"
|
346 |
+
msgstr ""
|
347 |
+
|
348 |
+
#. Found in description list item.
|
349 |
+
msgid "Extensive logging if duplication or migration process should fail."
|
350 |
+
msgstr ""
|
351 |
+
|
352 |
+
#. Found in description list item.
|
353 |
+
msgid "Admin bar reflects that you are working on a staging site"
|
354 |
+
msgstr ""
|
355 |
+
|
356 |
+
#. Found in description list item.
|
357 |
+
msgid "<strong>Fast: </strong> Migration process lasts only a few seconds or minutes, depending on the site's size and server I/O power"
|
358 |
+
msgstr ""
|
359 |
+
|
360 |
+
#. Found in description list item.
|
361 |
+
msgid "<strong>Easy: </strong> Staging migration applicable for everyone. No configuration needed!"
|
362 |
+
msgstr ""
|
363 |
+
|
364 |
+
#. Found in description header.
|
365 |
+
msgid "How to install and setup?"
|
366 |
+
msgstr ""
|
367 |
+
|
368 |
+
#. Found in description header.
|
369 |
+
msgid "Important"
|
370 |
+
msgstr "Wichtig"
|
371 |
+
|
372 |
+
#. Found in description header.
|
373 |
+
msgid "I need you feedback"
|
374 |
+
msgstr ""
|
375 |
+
|
376 |
+
#. Found in description header.
|
377 |
+
msgid "What are the benefits compared to a plugin like Duplicator?"
|
378 |
+
msgstr ""
|
379 |
+
|
380 |
+
#. Found in description header.
|
381 |
+
msgid "I just want to migrate the database from one installation to another"
|
382 |
+
msgstr ""
|
383 |
+
|
384 |
+
#. Found in description header.
|
385 |
+
msgid " Can´t i just use my local wordpress development copy for testing like xampp / lampp? "
|
386 |
+
msgstr ""
|
387 |
+
|
388 |
+
#. Found in description header.
|
389 |
+
msgid " Why should i use a staging website? "
|
390 |
+
msgstr ""
|
391 |
+
|
392 |
+
#. Found in description header.
|
393 |
+
msgid "What does not work or is not tested when running wordpress migration?"
|
394 |
+
msgstr ""
|
395 |
+
|
396 |
+
#. Found in description header.
|
397 |
+
msgid "Main Features"
|
398 |
+
msgstr ""
|
399 |
+
|
400 |
+
#. Found in description header.
|
401 |
+
msgid " WP Staging for WordPress Migration "
|
402 |
+
msgstr ""
|
403 |
+
|
404 |
+
#. Screenshot description.
|
405 |
+
msgid "Finish!"
|
406 |
+
msgstr ""
|
407 |
+
|
408 |
+
#. Screenshot description.
|
409 |
+
msgid "Step 3. Wordpress Staging site creation in progress"
|
410 |
+
msgstr ""
|
411 |
+
|
412 |
+
#. Screenshot description.
|
413 |
+
msgid "Step 2. Scanning your website for files and database tables"
|
414 |
+
msgstr ""
|
415 |
+
|
416 |
+
#. Screenshot description.
|
417 |
+
msgid "Step 1. Create new WordPress staging site"
|
418 |
msgstr ""
|
readme.txt
CHANGED
@@ -9,7 +9,7 @@ License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
|
9 |
Tags: staging, duplication, cloning, clone, migration, sandbox, test site, testing, backup, post, admin, administration, duplicate posts
|
10 |
Requires at least: 3.6+
|
11 |
Tested up to: 4.9
|
12 |
-
Stable tag: 2.3.
|
13 |
Requires PHP: 5.3
|
14 |
|
15 |
A duplicator plugin! Clone, duplicate and migrate live sites to independent staging and development sites that are available only to administrators.
|
@@ -146,6 +146,14 @@ https://wp-staging.com
|
|
146 |
|
147 |
== Changelog ==
|
148 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
149 |
= 2.3.7 =
|
150 |
* New: Increase cloning performance
|
151 |
* New: Show admin notice if php version and wordpress version do not meet requirements.
|
@@ -194,6 +202,6 @@ Complete changelog: [https://wp-staging.com/wp-staging-changelog](https://wp-sta
|
|
194 |
|
195 |
== Upgrade Notice ==
|
196 |
|
197 |
-
= 2.3.
|
198 |
* New: Compatible to WordPress 4.9.8. Important fixes!
|
199 |
|
9 |
Tags: staging, duplication, cloning, clone, migration, sandbox, test site, testing, backup, post, admin, administration, duplicate posts
|
10 |
Requires at least: 3.6+
|
11 |
Tested up to: 4.9
|
12 |
+
Stable tag: 2.3.8
|
13 |
Requires PHP: 5.3
|
14 |
|
15 |
A duplicator plugin! Clone, duplicate and migrate live sites to independent staging and development sites that are available only to administrators.
|
146 |
|
147 |
== Changelog ==
|
148 |
|
149 |
+
= 2.3.8 =
|
150 |
+
* Tweak: Lowering default performance settings for more reliability during cloning
|
151 |
+
* New: Set WP_CACHE to false in wp-config.php after cloning to prevent log in issues to staging site
|
152 |
+
* New: Compatibility mode to skip certain tables from third party plugins from beeing searched & replaced
|
153 |
+
* Fix: Do not clone db.php, object-cache.php and advanced-cache.php
|
154 |
+
* Fix: Show error message if ajax requests fail for any reason
|
155 |
+
|
156 |
+
|
157 |
= 2.3.7 =
|
158 |
* New: Increase cloning performance
|
159 |
* New: Show admin notice if php version and wordpress version do not meet requirements.
|
202 |
|
203 |
== Upgrade Notice ==
|
204 |
|
205 |
+
= 2.3.8 =
|
206 |
* New: Compatible to WordPress 4.9.8. Important fixes!
|
207 |
|
wp-staging.php
CHANGED
@@ -7,7 +7,7 @@
|
|
7 |
* Author: WP-Staging
|
8 |
* Author URI: https://wp-staging.com
|
9 |
* Contributors: ReneHermi, ilgityildirim
|
10 |
-
* Version: 2.3.
|
11 |
* Text Domain: wp-staging
|
12 |
* Domain Path: /languages/
|
13 |
|
@@ -51,7 +51,7 @@ if( !defined( 'WPSTG_PLUGIN_URL' ) ) {
|
|
51 |
|
52 |
// Version
|
53 |
if( !defined( 'WPSTGPRO_VERSION' ) ) {
|
54 |
-
define( 'WPSTGPRO_VERSION', '2.3.
|
55 |
}
|
56 |
|
57 |
/**
|
7 |
* Author: WP-Staging
|
8 |
* Author URI: https://wp-staging.com
|
9 |
* Contributors: ReneHermi, ilgityildirim
|
10 |
+
* Version: 2.3.8
|
11 |
* Text Domain: wp-staging
|
12 |
* Domain Path: /languages/
|
13 |
|
51 |
|
52 |
// Version
|
53 |
if( !defined( 'WPSTGPRO_VERSION' ) ) {
|
54 |
+
define( 'WPSTGPRO_VERSION', '2.3.8' );
|
55 |
}
|
56 |
|
57 |
/**
|