Version Description
- Fix: Remove LOCK_EX parameter in file_put_contents(). LOCK_EX is not working on several systems which results in cloning process timeouts
- Fix: Huge Performance improvement in copying process by removing duplicate file entries in the cache file. This also prevents weird timeout issues on some hosted websites
- Fix: Error 500 when debug mode is activated
- Fix: Limit maximum execution time to 30 seconds
- Fix: Sanitize Clone Names and Keys to fix "clone not found" issue in upgrade routine
- Fix: Do not clone the plugin wps-hide-login
- Fix: Staging sites can not be deleted if they are very big
- Fix: Link to staging site is undefined
- Tweak: Better admin message for asking for a review
- Tweak: Remove table wpstg_rmpermalinks_executed when plugin is uninstalled
- New: New setting to specify the maximum amount of files copied within one ajax call to fix godaddy and bluehost ajax 404 errors. Default 10 per batch
Download this release
Release Info
Developer | ReneHermi |
Plugin | WP Staging – DB & File Duplicator & Migration |
Version | 2.1.2 |
Comparing to | |
See all releases |
Code changes from version 2.1.1 to 2.1.2
- apps/Backend/Modules/Jobs/Cloning.php +189 -189
- apps/Backend/Modules/Jobs/Delete.php +488 -426
- apps/Backend/Modules/Jobs/Directories.php +15 -6
- apps/Backend/Modules/Jobs/Files.php +287 -286
- apps/Backend/Modules/Jobs/Finish.php +261 -235
- apps/Backend/Modules/Jobs/Job.php +473 -472
- apps/Backend/Modules/SystemInfo.php +1 -0
- apps/Backend/Modules/Views/Forms/Settings.php +20 -0
- apps/Backend/Notices/Notices.php +155 -147
- apps/Backend/Upgrade/Upgrade.php +229 -214
- apps/Backend/public/js/wpstg-admin-rating.js +31 -23
- apps/Backend/public/js/wpstg-admin.js +3 -4
- apps/Backend/views/_includes/messages/rating.php +30 -30
- apps/Backend/views/clone/ajax/start.php +112 -114
- apps/Backend/views/settings/index.php +24 -3
- apps/Core/DTO/Settings.php +49 -53
- apps/Core/Utils/Cache.php +1 -0
- apps/Core/WPStaging.php +1 -1
- readme.txt +270 -258
- uninstall.php +64 -64
- wp-staging.php +1 -1
apps/Backend/Modules/Jobs/Cloning.php
CHANGED
@@ -1,190 +1,190 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WPStaging\Backend\Modules\Jobs;
|
3 |
-
|
4 |
-
use WPStaging\Backend\Modules\Jobs\Exceptions\JobNotFoundException;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class Cloning
|
8 |
-
* @package WPStaging\Backend\Modules\Jobs
|
9 |
-
*/
|
10 |
-
class Cloning extends Job
|
11 |
-
{
|
12 |
-
|
13 |
-
/**
|
14 |
-
* Save Chosen Cloning Settings
|
15 |
-
* @return bool
|
16 |
-
*/
|
17 |
-
public function save()
|
18 |
-
{
|
19 |
-
if (!isset($_POST) || !isset($_POST["cloneID"]))
|
20 |
-
{
|
21 |
-
return false;
|
22 |
-
}
|
23 |
-
|
24 |
-
// Generate Options
|
25 |
-
|
26 |
-
// Clone
|
27 |
-
$this->options->clone = $_POST["cloneID"];
|
28 |
-
$this->options->cloneDirectoryName = preg_replace("#\W+#", '-', strtolower($this->options->clone));
|
29 |
-
$this->options->cloneNumber = 1;
|
30 |
-
$this->options->includedDirectories = array();
|
31 |
-
$this->options->excludedDirectories = array();
|
32 |
-
$this->options->extraDirectories = array();
|
33 |
-
$this->options->excludedFiles = array('.htaccess', '.DS_Store', '.git', '.svn', '.tmp', 'desktop.ini', '.gitignore', '.log');
|
34 |
-
|
35 |
-
// Job
|
36 |
-
$this->options->job = new \stdClass();
|
37 |
-
|
38 |
-
if (isset($this->options->existingClones[$this->options->clone]))
|
39 |
-
{
|
40 |
-
$this->options->cloneNumber = $this->options->existingClones[$this->options->clone]->number;
|
41 |
-
}
|
42 |
-
elseif (!empty($this->options->existingClones))
|
43 |
-
{
|
44 |
-
$this->options->cloneNumber = count($this->options->existingClones)+1;
|
45 |
-
}
|
46 |
-
|
47 |
-
// Excluded Tables
|
48 |
-
if (isset($_POST["excludedTables"]) && is_array($_POST["excludedTables"]))
|
49 |
-
{
|
50 |
-
$this->options->excludedTables = $_POST["excludedTables"];
|
51 |
-
}
|
52 |
-
|
53 |
-
// Excluded Directories
|
54 |
-
if (isset($_POST["excludedDirectories"]) && is_array($_POST["excludedDirectories"]))
|
55 |
-
{
|
56 |
-
$this->options->excludedDirectories = $_POST["excludedDirectories"];
|
57 |
-
}
|
58 |
-
|
59 |
-
// Excluded Directories TOTAL
|
60 |
-
// Do not copy these folders and plugins
|
61 |
-
$excludedDirectories = array(
|
62 |
-
ABSPATH . 'wp-content' . DIRECTORY_SEPARATOR . 'cache',
|
63 |
-
ABSPATH . 'wp-content' . DIRECTORY_SEPARATOR . 'plugins' . DIRECTORY_SEPARATOR . 'wps-hide-login'
|
64 |
-
);
|
65 |
-
|
66 |
-
$this->options->excludedDirectories = array_merge($excludedDirectories, $this->options->excludedDirectories);
|
67 |
-
|
68 |
-
// Included Directories
|
69 |
-
if (isset($_POST["includedDirectories"]) && is_array($_POST["includedDirectories"]))
|
70 |
-
{
|
71 |
-
$this->options->includedDirectories = $_POST["includedDirectories"];
|
72 |
-
}
|
73 |
-
|
74 |
-
// Extra Directories
|
75 |
-
if (isset($_POST["extraDirectories"]) && !empty($_POST["extraDirectories"]) )
|
76 |
-
{
|
77 |
-
$this->options->extraDirectories = $_POST["extraDirectories"];
|
78 |
-
}
|
79 |
-
|
80 |
-
// Directories to Copy
|
81 |
-
$this->options->directoriesToCopy = array_merge(
|
82 |
-
$this->options->includedDirectories,
|
83 |
-
$this->options->extraDirectories
|
84 |
-
);
|
85 |
-
|
86 |
-
array_unshift($this->options->directoriesToCopy, ABSPATH);
|
87 |
-
|
88 |
-
// Delete files to copy listing
|
89 |
-
$this->cache->delete("files_to_copy");
|
90 |
-
|
91 |
-
return $this->saveOptions();
|
92 |
-
}
|
93 |
-
|
94 |
-
/**
|
95 |
-
* Start the cloning job
|
96 |
-
*/
|
97 |
-
public function start()
|
98 |
-
{
|
99 |
-
if (null === $this->options->currentJob)
|
100 |
-
{
|
101 |
-
$this->log("Cloning job for {$this->options->clone} finished");
|
102 |
-
return true;
|
103 |
-
}
|
104 |
-
|
105 |
-
$methodName = "job" . ucwords($this->options->currentJob);
|
106 |
-
|
107 |
-
if (!method_exists($this, $methodName))
|
108 |
-
{
|
109 |
-
$this->log("Can't execute job; Job's method {$methodName} is not found");
|
110 |
-
throw new JobNotFoundException($methodName);
|
111 |
-
}
|
112 |
-
|
113 |
-
// Call the job
|
114 |
-
//$this->log("execute job: Job's method {$methodName}");
|
115 |
-
return $this->{$methodName}();
|
116 |
-
}
|
117 |
-
|
118 |
-
/**
|
119 |
-
* @param object $response
|
120 |
-
* @param string $nextJob
|
121 |
-
* @return object
|
122 |
-
*/
|
123 |
-
private function handleJobResponse($response, $nextJob)
|
124 |
-
{
|
125 |
-
// Job is not done
|
126 |
-
if (true !== $response->status)
|
127 |
-
{
|
128 |
-
return $response;
|
129 |
-
}
|
130 |
-
|
131 |
-
$this->options->currentJob = $nextJob;
|
132 |
-
$this->options->currentStep = 0;
|
133 |
-
$this->options->totalSteps = 0;
|
134 |
-
|
135 |
-
// Save options
|
136 |
-
$this->saveOptions();
|
137 |
-
|
138 |
-
return $response;
|
139 |
-
}
|
140 |
-
|
141 |
-
/**
|
142 |
-
* Clone Database
|
143 |
-
* @return object
|
144 |
-
*/
|
145 |
-
public function jobDatabase()
|
146 |
-
{
|
147 |
-
$database = new Database();
|
148 |
-
return $this->handleJobResponse($database->start(), "directories");
|
149 |
-
}
|
150 |
-
|
151 |
-
/**
|
152 |
-
* Get All Files From Selected Directories Recursively Into a File
|
153 |
-
* @return object
|
154 |
-
*/
|
155 |
-
public function jobDirectories()
|
156 |
-
{
|
157 |
-
$directories = new Directories();
|
158 |
-
return $this->handleJobResponse($directories->start(), "files");
|
159 |
-
}
|
160 |
-
|
161 |
-
/**
|
162 |
-
* Copy Files
|
163 |
-
* @return object
|
164 |
-
*/
|
165 |
-
public function jobFiles()
|
166 |
-
{
|
167 |
-
$files = new Files();
|
168 |
-
return $this->handleJobResponse($files->start(), "data");
|
169 |
-
}
|
170 |
-
|
171 |
-
/**
|
172 |
-
* Replace Data
|
173 |
-
* @return object
|
174 |
-
*/
|
175 |
-
public function jobData()
|
176 |
-
{
|
177 |
-
$data = new Data();
|
178 |
-
return $this->handleJobResponse($data->start(), "finish");
|
179 |
-
}
|
180 |
-
|
181 |
-
/**
|
182 |
-
* Save Clone Data
|
183 |
-
* @return object
|
184 |
-
*/
|
185 |
-
public function jobFinish()
|
186 |
-
{
|
187 |
-
$finish = new Finish();
|
188 |
-
return $this->handleJobResponse($finish->start(), '');
|
189 |
-
}
|
190 |
}
|
1 |
+
<?php
|
2 |
+
namespace WPStaging\Backend\Modules\Jobs;
|
3 |
+
|
4 |
+
use WPStaging\Backend\Modules\Jobs\Exceptions\JobNotFoundException;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Cloning
|
8 |
+
* @package WPStaging\Backend\Modules\Jobs
|
9 |
+
*/
|
10 |
+
class Cloning extends Job
|
11 |
+
{
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Save Chosen Cloning Settings
|
15 |
+
* @return bool
|
16 |
+
*/
|
17 |
+
public function save()
|
18 |
+
{
|
19 |
+
if (!isset($_POST) || !isset($_POST["cloneID"]))
|
20 |
+
{
|
21 |
+
return false;
|
22 |
+
}
|
23 |
+
|
24 |
+
// Generate Options
|
25 |
+
|
26 |
+
// Clone
|
27 |
+
$this->options->clone = $_POST["cloneID"];
|
28 |
+
$this->options->cloneDirectoryName = preg_replace("#\W+#", '-', strtolower($this->options->clone));
|
29 |
+
$this->options->cloneNumber = 1;
|
30 |
+
$this->options->includedDirectories = array();
|
31 |
+
$this->options->excludedDirectories = array();
|
32 |
+
$this->options->extraDirectories = array();
|
33 |
+
$this->options->excludedFiles = array('.htaccess', '.DS_Store', '.git', '.svn', '.tmp', 'desktop.ini', '.gitignore', '.log');
|
34 |
+
|
35 |
+
// Job
|
36 |
+
$this->options->job = new \stdClass();
|
37 |
+
|
38 |
+
if (isset($this->options->existingClones[$this->options->clone]))
|
39 |
+
{
|
40 |
+
$this->options->cloneNumber = $this->options->existingClones[$this->options->clone]->number;
|
41 |
+
}
|
42 |
+
elseif (!empty($this->options->existingClones))
|
43 |
+
{
|
44 |
+
$this->options->cloneNumber = count($this->options->existingClones)+1;
|
45 |
+
}
|
46 |
+
|
47 |
+
// Excluded Tables
|
48 |
+
if (isset($_POST["excludedTables"]) && is_array($_POST["excludedTables"]))
|
49 |
+
{
|
50 |
+
$this->options->excludedTables = $_POST["excludedTables"];
|
51 |
+
}
|
52 |
+
|
53 |
+
// Excluded Directories
|
54 |
+
if (isset($_POST["excludedDirectories"]) && is_array($_POST["excludedDirectories"]))
|
55 |
+
{
|
56 |
+
$this->options->excludedDirectories = $_POST["excludedDirectories"];
|
57 |
+
}
|
58 |
+
|
59 |
+
// Excluded Directories TOTAL
|
60 |
+
// Do not copy these folders and plugins
|
61 |
+
$excludedDirectories = array(
|
62 |
+
ABSPATH . 'wp-content' . DIRECTORY_SEPARATOR . 'cache',
|
63 |
+
ABSPATH . 'wp-content' . DIRECTORY_SEPARATOR . 'plugins' . DIRECTORY_SEPARATOR . 'wps-hide-login'
|
64 |
+
);
|
65 |
+
|
66 |
+
$this->options->excludedDirectories = array_merge($excludedDirectories, $this->options->excludedDirectories);
|
67 |
+
|
68 |
+
// Included Directories
|
69 |
+
if (isset($_POST["includedDirectories"]) && is_array($_POST["includedDirectories"]))
|
70 |
+
{
|
71 |
+
$this->options->includedDirectories = $_POST["includedDirectories"];
|
72 |
+
}
|
73 |
+
|
74 |
+
// Extra Directories
|
75 |
+
if (isset($_POST["extraDirectories"]) && !empty($_POST["extraDirectories"]) )
|
76 |
+
{
|
77 |
+
$this->options->extraDirectories = $_POST["extraDirectories"];
|
78 |
+
}
|
79 |
+
|
80 |
+
// Directories to Copy
|
81 |
+
$this->options->directoriesToCopy = array_merge(
|
82 |
+
$this->options->includedDirectories,
|
83 |
+
$this->options->extraDirectories
|
84 |
+
);
|
85 |
+
|
86 |
+
array_unshift($this->options->directoriesToCopy, ABSPATH);
|
87 |
+
|
88 |
+
// Delete files to copy listing
|
89 |
+
$this->cache->delete("files_to_copy");
|
90 |
+
|
91 |
+
return $this->saveOptions();
|
92 |
+
}
|
93 |
+
|
94 |
+
/**
|
95 |
+
* Start the cloning job
|
96 |
+
*/
|
97 |
+
public function start()
|
98 |
+
{
|
99 |
+
if (null === $this->options->currentJob)
|
100 |
+
{
|
101 |
+
$this->log("Cloning job for {$this->options->clone} finished");
|
102 |
+
return true;
|
103 |
+
}
|
104 |
+
|
105 |
+
$methodName = "job" . ucwords($this->options->currentJob);
|
106 |
+
|
107 |
+
if (!method_exists($this, $methodName))
|
108 |
+
{
|
109 |
+
$this->log("Can't execute job; Job's method {$methodName} is not found");
|
110 |
+
throw new JobNotFoundException($methodName);
|
111 |
+
}
|
112 |
+
|
113 |
+
// Call the job
|
114 |
+
//$this->log("execute job: Job's method {$methodName}");
|
115 |
+
return $this->{$methodName}();
|
116 |
+
}
|
117 |
+
|
118 |
+
/**
|
119 |
+
* @param object $response
|
120 |
+
* @param string $nextJob
|
121 |
+
* @return object
|
122 |
+
*/
|
123 |
+
private function handleJobResponse($response, $nextJob)
|
124 |
+
{
|
125 |
+
// Job is not done
|
126 |
+
if (true !== $response->status)
|
127 |
+
{
|
128 |
+
return $response;
|
129 |
+
}
|
130 |
+
|
131 |
+
$this->options->currentJob = $nextJob;
|
132 |
+
$this->options->currentStep = 0;
|
133 |
+
$this->options->totalSteps = 0;
|
134 |
+
|
135 |
+
// Save options
|
136 |
+
$this->saveOptions();
|
137 |
+
|
138 |
+
return $response;
|
139 |
+
}
|
140 |
+
|
141 |
+
/**
|
142 |
+
* Clone Database
|
143 |
+
* @return object
|
144 |
+
*/
|
145 |
+
public function jobDatabase()
|
146 |
+
{
|
147 |
+
$database = new Database();
|
148 |
+
return $this->handleJobResponse($database->start(), "directories");
|
149 |
+
}
|
150 |
+
|
151 |
+
/**
|
152 |
+
* Get All Files From Selected Directories Recursively Into a File
|
153 |
+
* @return object
|
154 |
+
*/
|
155 |
+
public function jobDirectories()
|
156 |
+
{
|
157 |
+
$directories = new Directories();
|
158 |
+
return $this->handleJobResponse($directories->start(), "files");
|
159 |
+
}
|
160 |
+
|
161 |
+
/**
|
162 |
+
* Copy Files
|
163 |
+
* @return object
|
164 |
+
*/
|
165 |
+
public function jobFiles()
|
166 |
+
{
|
167 |
+
$files = new Files();
|
168 |
+
return $this->handleJobResponse($files->start(), "data");
|
169 |
+
}
|
170 |
+
|
171 |
+
/**
|
172 |
+
* Replace Data
|
173 |
+
* @return object
|
174 |
+
*/
|
175 |
+
public function jobData()
|
176 |
+
{
|
177 |
+
$data = new Data();
|
178 |
+
return $this->handleJobResponse($data->start(), "finish");
|
179 |
+
}
|
180 |
+
|
181 |
+
/**
|
182 |
+
* Save Clone Data
|
183 |
+
* @return object
|
184 |
+
*/
|
185 |
+
public function jobFinish()
|
186 |
+
{
|
187 |
+
$finish = new Finish();
|
188 |
+
return $this->handleJobResponse($finish->start(), '');
|
189 |
+
}
|
190 |
}
|
apps/Backend/Modules/Jobs/Delete.php
CHANGED
@@ -1,426 +1,488 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
use WPStaging\Utils\
|
7 |
-
use WPStaging\
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
*
|
12 |
-
|
13 |
-
|
14 |
-
{
|
15 |
-
|
16 |
-
/**
|
17 |
-
* @var false
|
18 |
-
*/
|
19 |
-
private $clone = false;
|
20 |
-
|
21 |
-
/**
|
22 |
-
* @var null|object
|
23 |
-
*/
|
24 |
-
private $tables = null;
|
25 |
-
|
26 |
-
/**
|
27 |
-
* @var object|null
|
28 |
-
*/
|
29 |
-
private $job = null;
|
30 |
-
|
31 |
-
/**
|
32 |
-
* @var bool
|
33 |
-
*/
|
34 |
-
private $forceDeleteDirectories = false;
|
35 |
-
|
36 |
-
/**
|
37 |
-
*
|
38 |
-
* @
|
39 |
-
*/
|
40 |
-
public
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
$
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
if (null === $name)
|
69 |
-
|
70 |
-
|
71 |
-
}
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
$this->clone =
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
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 |
-
|
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 |
-
if ($this->
|
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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPStaging\Backend\Modules\Jobs;
|
4 |
+
|
5 |
+
use WPStaging\Backend\Modules\Jobs\Exceptions\CloneNotFoundException;
|
6 |
+
use WPStaging\Utils\Directories;
|
7 |
+
use WPStaging\Utils\Logger;
|
8 |
+
use WPStaging\WPStaging;
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Class Delete
|
12 |
+
* @package WPStaging\Backend\Modules\Jobs
|
13 |
+
*/
|
14 |
+
class Delete extends Job {
|
15 |
+
|
16 |
+
/**
|
17 |
+
* @var false
|
18 |
+
*/
|
19 |
+
private $clone = false;
|
20 |
+
|
21 |
+
/**
|
22 |
+
* @var null|object
|
23 |
+
*/
|
24 |
+
private $tables = null;
|
25 |
+
|
26 |
+
/**
|
27 |
+
* @var object|null
|
28 |
+
*/
|
29 |
+
private $job = null;
|
30 |
+
|
31 |
+
/**
|
32 |
+
* @var bool
|
33 |
+
*/
|
34 |
+
private $forceDeleteDirectories = false;
|
35 |
+
|
36 |
+
/**
|
37 |
+
*
|
38 |
+
* @var object
|
39 |
+
*/
|
40 |
+
public $wpdb;
|
41 |
+
|
42 |
+
public function __construct() {
|
43 |
+
parent::__construct();
|
44 |
+
$this->wpdb = WPStaging::getInstance()->get("wpdb");
|
45 |
+
}
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Sets Clone and Table Records
|
49 |
+
* @param null|array $clone
|
50 |
+
*/
|
51 |
+
public function setData($clone = null) {
|
52 |
+
if (!is_array($clone)) {
|
53 |
+
$this->getCloneRecords();
|
54 |
+
} else {
|
55 |
+
$this->clone = (object) $clone;
|
56 |
+
$this->forceDeleteDirectories = true;
|
57 |
+
}
|
58 |
+
|
59 |
+
$this->getTableRecords();
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Get clone
|
64 |
+
* @param null|string $name
|
65 |
+
* @throws CloneNotFoundException
|
66 |
+
*/
|
67 |
+
private function getCloneRecords($name = null) {
|
68 |
+
if (null === $name && !isset($_POST["clone"])) {
|
69 |
+
$this->log("Clone name is not set", Logger::TYPE_FATAL);
|
70 |
+
throw new CloneNotFoundException();
|
71 |
+
}
|
72 |
+
|
73 |
+
if (null === $name) {
|
74 |
+
$name = $_POST["clone"];
|
75 |
+
}
|
76 |
+
|
77 |
+
$clones = get_option("wpstg_existing_clones_beta", array());
|
78 |
+
|
79 |
+
if (empty($clones) || !isset($clones[$name])) {
|
80 |
+
$this->log("Couldn't find clone name {$name} or no existing clone", Logger::TYPE_FATAL);
|
81 |
+
throw new CloneNotFoundException();
|
82 |
+
}
|
83 |
+
|
84 |
+
$this->clone = $clones[$name];
|
85 |
+
$this->clone["name"] = $name;
|
86 |
+
|
87 |
+
$this->clone = (object) $this->clone;
|
88 |
+
|
89 |
+
unset($clones);
|
90 |
+
}
|
91 |
+
|
92 |
+
/**
|
93 |
+
* Get Tables
|
94 |
+
*/
|
95 |
+
private function getTableRecords() {
|
96 |
+
//$wpdb = WPStaging::getInstance()->get("wpdb");
|
97 |
+
$this->wpdb = WPStaging::getInstance()->get("wpdb");
|
98 |
+
|
99 |
+
|
100 |
+
$stagingPrefix = $this->getStagingPrefix();
|
101 |
+
|
102 |
+
$tables = $this->wpdb->get_results("SHOW TABLE STATUS LIKE '{$stagingPrefix}%'");
|
103 |
+
|
104 |
+
$this->tables = array();
|
105 |
+
|
106 |
+
foreach ($tables as $table) {
|
107 |
+
$this->tables[] = array(
|
108 |
+
"name" => $table->Name,
|
109 |
+
"size" => $this->formatSize(($table->Data_length + $table->Index_length))
|
110 |
+
);
|
111 |
+
}
|
112 |
+
|
113 |
+
$this->tables = json_decode(json_encode($this->tables));
|
114 |
+
}
|
115 |
+
|
116 |
+
/**
|
117 |
+
* Check and return prefix of the staging site
|
118 |
+
*/
|
119 |
+
public function getStagingPrefix() {
|
120 |
+
// prefix not defined! Happens if staging site has ben generated with older version of wpstg
|
121 |
+
// Try to get staging prefix from wp-config.php of staging site
|
122 |
+
//wp_die($this->clone->directoryName);
|
123 |
+
if (empty($this->clone->prefix)) {
|
124 |
+
// Throw error
|
125 |
+
$path = ABSPATH . $this->clone->directoryName . "/wp-config.php";
|
126 |
+
if (false === ($content = @file_get_contents($path))) {
|
127 |
+
$this->log("Can not open {$path}. Can't read contents", Logger::TYPE_ERROR);
|
128 |
+
// Create a random prefix which hopefully never exists.
|
129 |
+
$this->clone->prefix = rand(7, 15) . '_';
|
130 |
+
} else {
|
131 |
+
|
132 |
+
// Get prefix from wp-config.php
|
133 |
+
//preg_match_all("/table_prefix\s*=\s*'(\w*)';/", $content, $matches);
|
134 |
+
preg_match("/table_prefix\s*=\s*'(\w*)';/", $content, $matches);
|
135 |
+
//wp_die(var_dump($matches));
|
136 |
+
|
137 |
+
if (!empty($matches[1])) {
|
138 |
+
$this->clone->prefix = $matches[1];
|
139 |
+
} else {
|
140 |
+
$this->log("Fatal Error: Can not delete staging site. Can not find Prefix. '{$matches[1]}'. Stopping for security reasons. Creating a new staging site will likely resolve this the next time. Contact support@wp-staging.com");
|
141 |
+
// Create a random prefix which hopefully never exists.
|
142 |
+
return $this->clone->prefix = rand(7, 15) . '_';
|
143 |
+
}
|
144 |
+
}
|
145 |
+
}
|
146 |
+
|
147 |
+
// Check if staging prefix is the same as the live prefix
|
148 |
+
if ($this->wpdb->prefix == $this->clone->prefix) {
|
149 |
+
$this->log("Fatal Error: Can not delete staging site. Prefix. '{$this->clone->prefix}' is used for the live site. Creating a new staging site will likely resolve this the next time. Stopping for security reasons. Contact support@wp-staging.com");
|
150 |
+
wp_die("Fatal Error: Can not delete staging site. Prefix. '{$this->clone->prefix}' is used for the live site. Creating a new staging site will likely resolve this the next time. Stopping for security reasons. Contact support@wp-staging.com");
|
151 |
+
}
|
152 |
+
|
153 |
+
// Else
|
154 |
+
return $this->clone->prefix;
|
155 |
+
}
|
156 |
+
|
157 |
+
/**
|
158 |
+
* Format bytes into human readable form
|
159 |
+
* @param int $bytes
|
160 |
+
* @param int $precision
|
161 |
+
* @return string
|
162 |
+
*/
|
163 |
+
public function formatSize($bytes, $precision = 2) {
|
164 |
+
if ((int) $bytes < 1) {
|
165 |
+
return '';
|
166 |
+
}
|
167 |
+
|
168 |
+
$units = array('B', "KB", "MB", "GB", "TB");
|
169 |
+
|
170 |
+
$bytes = (int) $bytes;
|
171 |
+
$base = log($bytes) / log(1000); // 1024 would be for MiB KiB etc
|
172 |
+
$pow = pow(1000, $base - floor($base)); // Same rule for 1000
|
173 |
+
|
174 |
+
return round($pow, $precision) . ' ' . $units[(int) floor($base)];
|
175 |
+
}
|
176 |
+
|
177 |
+
/**
|
178 |
+
* @return false
|
179 |
+
*/
|
180 |
+
public function getClone() {
|
181 |
+
return $this->clone;
|
182 |
+
}
|
183 |
+
|
184 |
+
/**
|
185 |
+
* @return null|object
|
186 |
+
*/
|
187 |
+
public function getTables() {
|
188 |
+
return $this->tables;
|
189 |
+
}
|
190 |
+
|
191 |
+
/**
|
192 |
+
* Start Module
|
193 |
+
* @param null|array $clone
|
194 |
+
* @return bool
|
195 |
+
*/
|
196 |
+
public function start($clone = null) {
|
197 |
+
// Set data
|
198 |
+
$this->setData($clone);
|
199 |
+
|
200 |
+
// Get the job first
|
201 |
+
$this->getJob();
|
202 |
+
|
203 |
+
$method = "delete" . ucwords($this->job->current);
|
204 |
+
return $this->{$method}();
|
205 |
+
}
|
206 |
+
|
207 |
+
/**
|
208 |
+
* Get job data
|
209 |
+
*/
|
210 |
+
private function getJob() {
|
211 |
+
$this->job = $this->cache->get("delete_job_{$this->clone->name}");
|
212 |
+
|
213 |
+
|
214 |
+
if (null !== $this->job) {
|
215 |
+
return;
|
216 |
+
}
|
217 |
+
|
218 |
+
// Generate JOB
|
219 |
+
$this->job = (object) array(
|
220 |
+
"current" => "tables",
|
221 |
+
"nextDirectoryToDelete" => $this->clone->path,
|
222 |
+
"name" => $this->clone->name
|
223 |
+
);
|
224 |
+
|
225 |
+
$this->cache->save("delete_job_{$this->clone->name}", $this->job);
|
226 |
+
}
|
227 |
+
|
228 |
+
/**
|
229 |
+
* @return bool
|
230 |
+
*/
|
231 |
+
private function updateJob() {
|
232 |
+
$this->job->nextDirectoryToDelete = trim($this->job->nextDirectoryToDelete);
|
233 |
+
return $this->cache->save("delete_job_{$this->clone->name}", $this->job);
|
234 |
+
}
|
235 |
+
|
236 |
+
/**
|
237 |
+
* @return array
|
238 |
+
*/
|
239 |
+
private function getTablesToRemove() {
|
240 |
+
$tables = $this->getTableNames();
|
241 |
+
|
242 |
+
if (!isset($_POST["excludedTables"]) || !is_array($_POST["excludedTables"]) || empty($_POST["excludedTables"])) {
|
243 |
+
return $tables;
|
244 |
+
}
|
245 |
+
|
246 |
+
return array_diff($tables, $_POST["excludedTables"]);
|
247 |
+
}
|
248 |
+
|
249 |
+
/**
|
250 |
+
* @return array
|
251 |
+
*/
|
252 |
+
private function getTableNames() {
|
253 |
+
return (!is_array($this->tables)) ? array() : array_map(function($value) {
|
254 |
+
return ($value->name);
|
255 |
+
}, $this->tables);
|
256 |
+
}
|
257 |
+
|
258 |
+
/**
|
259 |
+
* Delete Tables
|
260 |
+
*/
|
261 |
+
public function deleteTables() {
|
262 |
+
if ($this->isOverThreshold()) {
|
263 |
+
return;
|
264 |
+
}
|
265 |
+
|
266 |
+
//$wpdb = WPStaging::getInstance()->get("wpdb");
|
267 |
+
|
268 |
+
foreach ($this->getTablesToRemove() as $table) {
|
269 |
+
// PROTECTION: Never delete any table that beginns with wp prefix of live site
|
270 |
+
if ($this->startsWith($table, $this->wpdb->prefix)) {
|
271 |
+
$this->log("Fatal Error: Trying to delete table {$table} of main WP installation!", Logger::TYPE_CRITICAL);
|
272 |
+
return false;
|
273 |
+
} else {
|
274 |
+
$this->wpdb->query("DROP TABLE {$table}");
|
275 |
+
}
|
276 |
+
}
|
277 |
+
|
278 |
+
// Move on to the next
|
279 |
+
$this->job->current = "directory";
|
280 |
+
$this->updateJob();
|
281 |
+
}
|
282 |
+
|
283 |
+
/**
|
284 |
+
* Check if a strings start with a specific string
|
285 |
+
* @param string $haystack
|
286 |
+
* @param string $needle
|
287 |
+
* @return bool
|
288 |
+
*/
|
289 |
+
protected function startsWith($haystack, $needle) {
|
290 |
+
$length = strlen($needle);
|
291 |
+
return (substr($haystack, 0, $length) === $needle);
|
292 |
+
}
|
293 |
+
|
294 |
+
/**
|
295 |
+
* Delete complete directory including all files and subfolders
|
296 |
+
*
|
297 |
+
* @throws InvalidArgumentException
|
298 |
+
*/
|
299 |
+
public function deleteDirectory() {
|
300 |
+
|
301 |
+
// Finished or path does not exist
|
302 |
+
if (!is_dir($this->clone->path)) {
|
303 |
+
$this->job->current = "finish";
|
304 |
+
$this->updateJob();
|
305 |
+
return $this->returnFinish();
|
306 |
+
}
|
307 |
+
|
308 |
+
$this->log("Delete staging site: " . $this->clone->path, Logger::TYPE_INFO);
|
309 |
+
|
310 |
+
// Just to make sure the root dir is never deleted!
|
311 |
+
if ($this->clone->path === get_home_path()) {
|
312 |
+
$this->log("Fatal Error 8: Trying to delete root of WP installation!", Logger::TYPE_CRITICAL);
|
313 |
+
$this->returnException('Fatal Error 8: Trying to delete root of WP installation!');
|
314 |
+
}
|
315 |
+
|
316 |
+
// Check if threshold is reached
|
317 |
+
if ($this->isOverThreshold()) {
|
318 |
+
//$this->returnException('Maximum PHP execution time exceeded. Run again and repeat the deletion process until it is sucessfully finished.');
|
319 |
+
return;
|
320 |
+
}
|
321 |
+
|
322 |
+
$di = new \RecursiveDirectoryIterator($this->clone->path, \FilesystemIterator::SKIP_DOTS);
|
323 |
+
$ri = new \RecursiveIteratorIterator($di, \RecursiveIteratorIterator::CHILD_FIRST);
|
324 |
+
foreach ($ri as $file) {
|
325 |
+
$file->isDir() ? @rmdir($file) : unlink($file);
|
326 |
+
if ($this->isOverThreshold()) {
|
327 |
+
//$this->returnException('Maximum PHP execution time exceeded. Run again and repeat the deletion process until it is sucessfully finished.');
|
328 |
+
return;
|
329 |
+
}
|
330 |
+
}
|
331 |
+
//rmdir($this->clone->path);
|
332 |
+
// if (is_dir($this->clone->path)) {
|
333 |
+
// return $this->returnException('Unable to delete all files in folder' . $this->clone->path . '<br>Please try to delete the folder manually via FTP. Than run the delete function again.');
|
334 |
+
// } else {
|
335 |
+
// return $this->returnFinish();
|
336 |
+
// }
|
337 |
+
if (@rmdir($this->clone->path)){
|
338 |
+
return $this->returnFinish();
|
339 |
+
}
|
340 |
+
return;
|
341 |
+
|
342 |
+
|
343 |
+
|
344 |
+
}
|
345 |
+
|
346 |
+
/**
|
347 |
+
* Delete Directories
|
348 |
+
*/
|
349 |
+
public function deleteDirectory_old() {
|
350 |
+
// No deleting directories or root of this clone is deleted
|
351 |
+
if ($this->isDirectoryDeletingFinished()) {
|
352 |
+
$this->job->current = "finish";
|
353 |
+
$this->updateJob();
|
354 |
+
return;
|
355 |
+
}
|
356 |
+
|
357 |
+
$this->processDirectory($this->job->nextDirectoryToDelete);
|
358 |
+
|
359 |
+
return;
|
360 |
+
}
|
361 |
+
|
362 |
+
/**
|
363 |
+
* @return bool
|
364 |
+
*/
|
365 |
+
public function isDirectoryDeletingFinished() {
|
366 |
+
return (
|
367 |
+
(false === $this->forceDeleteDirectories && (!isset($_POST["deleteDir"]) || '1' !== $_POST["deleteDir"])) ||
|
368 |
+
!is_dir($this->clone->path) || ABSPATH === $this->job->nextDirectoryToDelete
|
369 |
+
);
|
370 |
+
}
|
371 |
+
|
372 |
+
/**
|
373 |
+
* Delete contents of the directory if there are no directories in it and then delete itself
|
374 |
+
* @param string $path
|
375 |
+
* @return mixed
|
376 |
+
*/
|
377 |
+
private function processDirectory($path) {
|
378 |
+
// We hit the limit, stop
|
379 |
+
if ($this->shouldStop($path)) {
|
380 |
+
$this->updateJob();
|
381 |
+
return false;
|
382 |
+
}
|
383 |
+
|
384 |
+
$this->totalRecursion++;
|
385 |
+
|
386 |
+
$contents = new \DirectoryIterator($path);
|
387 |
+
|
388 |
+
foreach ($contents as $content => $value) {
|
389 |
+
|
390 |
+
// Skip dots
|
391 |
+
if ($content->isDot())
|
392 |
+
|
393 |
+
|
394 |
+
// Get into the directory
|
395 |
+
if (!$content->isLink() && $content->isDir()) {
|
396 |
+
return $this->processDirectory($content->getRealPath());
|
397 |
+
}
|
398 |
+
|
399 |
+
// Delete file
|
400 |
+
if ($content->isFile()) {
|
401 |
+
@unlink($content->getRealPath());
|
402 |
+
}
|
403 |
+
}
|
404 |
+
|
405 |
+
// Delete directory
|
406 |
+
$this->job->lastDeletedDirectory = realpath($path . "/..");
|
407 |
+
@rmdir($path);
|
408 |
+
$this->updateJob();
|
409 |
+
$this->processDirectory($this->job->nextDirectoryToDelete);
|
410 |
+
}
|
411 |
+
|
412 |
+
/**
|
413 |
+
* @param string $path
|
414 |
+
* @return bool
|
415 |
+
*/
|
416 |
+
private function shouldStop($path) {
|
417 |
+
// Just to make sure the root dir is never deleted!
|
418 |
+
if ($path === get_home_path()) {
|
419 |
+
$this->log("Fatal Error: Trying to delete root of WP installation!", Logger::TYPE_CRITICAL);
|
420 |
+
return true;
|
421 |
+
}
|
422 |
+
|
423 |
+
// Check if threshold is reached and is valid dir
|
424 |
+
return (
|
425 |
+
$this->isOverThreshold() ||
|
426 |
+
!is_dir($path) ||
|
427 |
+
$this->isDirectoryDeletingFinished()
|
428 |
+
);
|
429 |
+
}
|
430 |
+
|
431 |
+
/**
|
432 |
+
* Finish / Update Existing Clones
|
433 |
+
*/
|
434 |
+
public function deleteFinish() {
|
435 |
+
$existingClones = get_option("wpstg_existing_clones_beta", array());
|
436 |
+
|
437 |
+
// Check if clones still exist
|
438 |
+
$this->log("Verifying existing clones...");
|
439 |
+
foreach ($existingClones as $name => $clone) {
|
440 |
+
if (!is_dir($clone["path"])) {
|
441 |
+
unset($existingClones[$name]);
|
442 |
+
}
|
443 |
+
}
|
444 |
+
$this->log("Existing clones verified!");
|
445 |
+
|
446 |
+
if (false === update_option("wpstg_existing_clones_beta", $existingClones)) {
|
447 |
+
$this->log("Failed to save {$this->options->clone}'s clone job data to database'");
|
448 |
+
}
|
449 |
+
|
450 |
+
// Delete cached file
|
451 |
+
$this->cache->delete("delete_job_{$this->clone->name}");
|
452 |
+
$this->cache->delete("delete_directories_{$this->clone->name}");
|
453 |
+
|
454 |
+
//return true;
|
455 |
+
$response = array('delete' => 'finished');
|
456 |
+
wp_die(json_encode($response));
|
457 |
+
}
|
458 |
+
|
459 |
+
/**
|
460 |
+
* Get json response
|
461 |
+
* return json
|
462 |
+
*/
|
463 |
+
// private function returnException($message = ''){
|
464 |
+
// wp_die( json_encode(array(
|
465 |
+
// 'job' => 'delete',
|
466 |
+
// 'status' => false,
|
467 |
+
// 'message' => $message,
|
468 |
+
// 'error' => true
|
469 |
+
// )));
|
470 |
+
// }
|
471 |
+
/**
|
472 |
+
* Get json response
|
473 |
+
* return json
|
474 |
+
*/
|
475 |
+
private function returnFinish($message = '') {
|
476 |
+
|
477 |
+
$this->deleteFinish();
|
478 |
+
|
479 |
+
wp_die(json_encode(array(
|
480 |
+
'job' => 'delete',
|
481 |
+
'status' => true,
|
482 |
+
'message' => $message,
|
483 |
+
'error' => false,
|
484 |
+
'delete' => 'finished'
|
485 |
+
)));
|
486 |
+
}
|
487 |
+
|
488 |
+
}
|
apps/Backend/Modules/Jobs/Directories.php
CHANGED
@@ -2,16 +2,14 @@
|
|
2 |
|
3 |
namespace WPStaging\Backend\Modules\Jobs;
|
4 |
|
5 |
-
//ini_set('display_startup_errors', 1);
|
6 |
-
//ini_set('display_errors', 1);
|
7 |
-
//error_reporting(-1);
|
8 |
-
|
9 |
// No Direct Access
|
10 |
if( !defined( "WPINC" ) ) {
|
11 |
die;
|
12 |
}
|
13 |
|
14 |
use WPStaging\WPStaging;
|
|
|
|
|
15 |
|
16 |
/**
|
17 |
* Class Files
|
@@ -156,6 +154,11 @@ class Directories extends JobExecutable {
|
|
156 |
|
157 |
// Add scanned directory listing
|
158 |
$this->options->scannedDirectories[] = $dir;
|
|
|
|
|
|
|
|
|
|
|
159 |
}
|
160 |
|
161 |
$this->saveOptions();
|
@@ -165,6 +168,7 @@ class Directories extends JobExecutable {
|
|
165 |
}
|
166 |
|
167 |
/**
|
|
|
168 |
* @param $directory
|
169 |
* @return bool
|
170 |
*/
|
@@ -177,8 +181,13 @@ class Directories extends JobExecutable {
|
|
177 |
foreach ( $files as $file ) {
|
178 |
$fullPath = $directory . $file;
|
179 |
|
180 |
-
//
|
181 |
-
|
|
|
|
|
|
|
|
|
|
|
182 |
$this->options->totalFiles++;
|
183 |
$this->files[] = $fullPath;
|
184 |
continue;
|
2 |
|
3 |
namespace WPStaging\Backend\Modules\Jobs;
|
4 |
|
|
|
|
|
|
|
|
|
5 |
// No Direct Access
|
6 |
if( !defined( "WPINC" ) ) {
|
7 |
die;
|
8 |
}
|
9 |
|
10 |
use WPStaging\WPStaging;
|
11 |
+
use WPStaging\Utils\Logger;
|
12 |
+
|
13 |
|
14 |
/**
|
15 |
* Class Files
|
154 |
|
155 |
// Add scanned directory listing
|
156 |
$this->options->scannedDirectories[] = $dir;
|
157 |
+
|
158 |
+
if( $this->isOverThreshold() ) {
|
159 |
+
//$this->saveProgress();
|
160 |
+
return false;
|
161 |
+
}
|
162 |
}
|
163 |
|
164 |
$this->saveOptions();
|
168 |
}
|
169 |
|
170 |
/**
|
171 |
+
* Get files from directory
|
172 |
* @param $directory
|
173 |
* @return bool
|
174 |
*/
|
181 |
foreach ( $files as $file ) {
|
182 |
$fullPath = $directory . $file;
|
183 |
|
184 |
+
// Conditions:
|
185 |
+
// - Must be valid file
|
186 |
+
// - Is readable file
|
187 |
+
// - Not collected already
|
188 |
+
// - File not excluded by another rule or condition
|
189 |
+
|
190 |
+
if( is_file( $fullPath ) && is_readable( $fullPath ) && !in_array( $fullPath, $this->files ) && !$this->isExcluded($file) ) {
|
191 |
$this->options->totalFiles++;
|
192 |
$this->files[] = $fullPath;
|
193 |
continue;
|
apps/Backend/Modules/Jobs/Files.php
CHANGED
@@ -1,287 +1,288 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WPStaging\Backend\Modules\Jobs;
|
3 |
-
|
4 |
-
// No Direct Access
|
5 |
-
use WPStaging\Utils\Logger;
|
6 |
-
|
7 |
-
if (!defined("WPINC"))
|
8 |
-
{
|
9 |
-
die;
|
10 |
-
}
|
11 |
-
|
12 |
-
/**
|
13 |
-
* Class Files
|
14 |
-
* @package WPStaging\Backend\Modules\Jobs
|
15 |
-
*/
|
16 |
-
class Files extends JobExecutable
|
17 |
-
{
|
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 = ABSPATH . $this->options->cloneDirectoryName . DIRECTORY_SEPARATOR;
|
40 |
-
|
41 |
-
$filePath = $this->cache->getCacheDir() . "files_to_copy." . $this->cache->getCacheExtension();
|
42 |
-
|
43 |
-
if (is_file($filePath))
|
44 |
-
{
|
45 |
-
$this->file = new \SplFileObject($filePath, 'r');
|
46 |
-
}
|
47 |
-
|
48 |
-
// Informational logs
|
49 |
-
if (0 == $this->options->currentStep)
|
50 |
-
{
|
51 |
-
$this->log("Copying files...");
|
52 |
-
}
|
53 |
-
|
54 |
-
$this->settings->batchSize = $this->settings->batchSize * 1000000;
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
*
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
*
|
69 |
-
*
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
$this->
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
*
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
$this->
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
$this->
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
*
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
$this->options->
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
* @
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
//
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
*
|
181 |
-
*
|
182 |
-
* @
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
$
|
188 |
-
$
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
*
|
202 |
-
* @param string $
|
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 |
-
* @param string $
|
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 |
-
* @param string $
|
258 |
-
* @param
|
259 |
-
* @
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
$
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
fclose($
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
fclose($
|
285 |
-
|
286 |
-
|
|
|
287 |
}
|
1 |
+
<?php
|
2 |
+
namespace WPStaging\Backend\Modules\Jobs;
|
3 |
+
|
4 |
+
// No Direct Access
|
5 |
+
use WPStaging\Utils\Logger;
|
6 |
+
|
7 |
+
if (!defined("WPINC"))
|
8 |
+
{
|
9 |
+
die;
|
10 |
+
}
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Class Files
|
14 |
+
* @package WPStaging\Backend\Modules\Jobs
|
15 |
+
*/
|
16 |
+
class Files extends JobExecutable
|
17 |
+
{
|
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 = ABSPATH . $this->options->cloneDirectoryName . DIRECTORY_SEPARATOR;
|
40 |
+
|
41 |
+
$filePath = $this->cache->getCacheDir() . "files_to_copy." . $this->cache->getCacheExtension();
|
42 |
+
|
43 |
+
if (is_file($filePath))
|
44 |
+
{
|
45 |
+
$this->file = new \SplFileObject($filePath, 'r');
|
46 |
+
}
|
47 |
+
|
48 |
+
// Informational logs
|
49 |
+
if (0 == $this->options->currentStep)
|
50 |
+
{
|
51 |
+
$this->log("Copying files...");
|
52 |
+
}
|
53 |
+
|
54 |
+
$this->settings->batchSize = $this->settings->batchSize * 1000000;
|
55 |
+
$this->maxFilesPerRun = $this->settings->fileLimit;
|
56 |
+
}
|
57 |
+
|
58 |
+
/**
|
59 |
+
* Calculate Total Steps in This Job and Assign It to $this->options->totalSteps
|
60 |
+
* @return void
|
61 |
+
*/
|
62 |
+
protected function calculateTotalSteps()
|
63 |
+
{
|
64 |
+
$this->options->totalSteps = ceil($this->options->totalFiles / $this->maxFilesPerRun);
|
65 |
+
}
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Execute the Current Step
|
69 |
+
* Returns false when over threshold limits are hit or when the job is done, true otherwise
|
70 |
+
* @return bool
|
71 |
+
*/
|
72 |
+
protected function execute()
|
73 |
+
{
|
74 |
+
// Finished
|
75 |
+
if ($this->isFinished())
|
76 |
+
{
|
77 |
+
$this->log("Copying files finished");
|
78 |
+
$this->prepareResponse(true, false);
|
79 |
+
return false;
|
80 |
+
}
|
81 |
+
|
82 |
+
// Get files and copy'em
|
83 |
+
if (!$this->getFilesAndCopy())
|
84 |
+
{
|
85 |
+
$this->prepareResponse(false, false);
|
86 |
+
return false;
|
87 |
+
}
|
88 |
+
|
89 |
+
// Prepare and return response
|
90 |
+
$this->prepareResponse();
|
91 |
+
|
92 |
+
// Not finished
|
93 |
+
return true;
|
94 |
+
}
|
95 |
+
|
96 |
+
/**
|
97 |
+
* Get files and copy
|
98 |
+
* @return bool
|
99 |
+
*/
|
100 |
+
private function getFilesAndCopy()
|
101 |
+
{
|
102 |
+
// Over limits threshold
|
103 |
+
if ($this->isOverThreshold())
|
104 |
+
{
|
105 |
+
// Prepare response and save current progress
|
106 |
+
$this->prepareResponse(false, false);
|
107 |
+
$this->saveOptions();
|
108 |
+
return false;
|
109 |
+
}
|
110 |
+
|
111 |
+
// Skip processed ones
|
112 |
+
if ($this->options->copiedFiles != 0)
|
113 |
+
{
|
114 |
+
$this->file->seek($this->options->copiedFiles);
|
115 |
+
}
|
116 |
+
|
117 |
+
$this->file->setFlags(\SplFileObject::SKIP_EMPTY | \SplFileObject::READ_AHEAD);
|
118 |
+
|
119 |
+
// One thousand files at a time
|
120 |
+
for ($i = 0; $i <= $this->maxFilesPerRun; $i++)
|
121 |
+
{
|
122 |
+
// End of file
|
123 |
+
if ($this->file->eof())
|
124 |
+
{
|
125 |
+
break;
|
126 |
+
}
|
127 |
+
|
128 |
+
$this->copyFile($this->file->fgets());
|
129 |
+
}
|
130 |
+
|
131 |
+
$totalFiles = $this->maxFilesPerRun + $this->options->copiedFiles;
|
132 |
+
$this->log("Total {$totalFiles} files processed");
|
133 |
+
|
134 |
+
return true;
|
135 |
+
}
|
136 |
+
|
137 |
+
/**
|
138 |
+
* Checks Whether There is Any Job to Execute or Not
|
139 |
+
* @return bool
|
140 |
+
*/
|
141 |
+
private function isFinished()
|
142 |
+
{
|
143 |
+
return (
|
144 |
+
$this->options->currentStep > $this->options->totalSteps ||
|
145 |
+
$this->options->copiedFiles >= $this->options->totalFiles
|
146 |
+
);
|
147 |
+
}
|
148 |
+
|
149 |
+
/**
|
150 |
+
* @param string $file
|
151 |
+
* @return bool
|
152 |
+
*/
|
153 |
+
private function copyFile($file)
|
154 |
+
{
|
155 |
+
$file = trim($file);
|
156 |
+
|
157 |
+
// Increment copied files whatever the result is
|
158 |
+
// This way we don't get stuck in the same step / files
|
159 |
+
$this->options->copiedFiles++;
|
160 |
+
|
161 |
+
// Invalid file, skipping it as if succeeded
|
162 |
+
if (!is_file($file) || !is_readable($file))
|
163 |
+
{
|
164 |
+
$this->log("Can't read file or file doesn't exist {$file}");
|
165 |
+
return true;
|
166 |
+
}
|
167 |
+
|
168 |
+
// Failed to get destination
|
169 |
+
if (false === ($destination = $this->getDestination($file)))
|
170 |
+
{
|
171 |
+
$this->log("Can't get the destination of {$file}");
|
172 |
+
return false;
|
173 |
+
}
|
174 |
+
|
175 |
+
// Good old PHP
|
176 |
+
return $this->copy($file, $destination);
|
177 |
+
}
|
178 |
+
|
179 |
+
/**
|
180 |
+
* Gets destination file and checks if the directory exists, if it does not attempts to create it.
|
181 |
+
* If creating destination directory fails, it returns false, gives destination full path otherwise
|
182 |
+
* @param string $file
|
183 |
+
* @return bool|string
|
184 |
+
*/
|
185 |
+
private function getDestination($file)
|
186 |
+
{
|
187 |
+
$relativePath = str_replace(ABSPATH, null, $file);
|
188 |
+
$destinationPath = $this->destination . $relativePath;
|
189 |
+
$destinationDirectory = dirname($destinationPath);
|
190 |
+
|
191 |
+
if (!is_dir($destinationDirectory) && !@mkdir($destinationDirectory, 0775, true))
|
192 |
+
{
|
193 |
+
$this->log("Destination directory doesn't exist; {$destinationDirectory}", Logger::TYPE_ERROR);
|
194 |
+
return false;
|
195 |
+
}
|
196 |
+
|
197 |
+
return $destinationPath;
|
198 |
+
}
|
199 |
+
|
200 |
+
/**
|
201 |
+
* Copy File using PHP
|
202 |
+
* @param string $file
|
203 |
+
* @param string $destination
|
204 |
+
* @return bool
|
205 |
+
*/
|
206 |
+
private function copy($file, $destination)
|
207 |
+
{
|
208 |
+
// Get file size
|
209 |
+
$fileSize = filesize($file);
|
210 |
+
|
211 |
+
// File is over batch size
|
212 |
+
if ($fileSize >= $this->settings->batchSize)
|
213 |
+
{
|
214 |
+
$this->log("Trying to copy big file {$file} -> {$destination}", Logger::TYPE_INFO);
|
215 |
+
return $this->copyBig($file, $destination, $this->settings->batchSize);
|
216 |
+
}
|
217 |
+
|
218 |
+
// Attempt to copy
|
219 |
+
if (!@copy($file, $destination))
|
220 |
+
{
|
221 |
+
$this->log("Failed to copy file to destination: {$file} -> {$destination}", Logger::TYPE_ERROR);
|
222 |
+
return false;
|
223 |
+
}
|
224 |
+
|
225 |
+
return true;
|
226 |
+
}
|
227 |
+
|
228 |
+
/**
|
229 |
+
* Copy bigger files than $this->settings->batchSize
|
230 |
+
* @param string $file
|
231 |
+
* @param string $destination
|
232 |
+
* @return bool
|
233 |
+
*
|
234 |
+
* @deprecated since version 2.0.0 (Supported only in php 5.5.11 and later)
|
235 |
+
*/
|
236 |
+
// private function copyBig($file, $destination)
|
237 |
+
// {
|
238 |
+
// $bytes = 0;
|
239 |
+
// $fileInput = new \SplFileObject($file, "rb");
|
240 |
+
// $fileOutput = new \SplFileObject($destination, 'w');
|
241 |
+
//
|
242 |
+
// $this->log("Copying big file; {$file} -> {$destination}");
|
243 |
+
//
|
244 |
+
// while (!$fileInput->eof())
|
245 |
+
// {
|
246 |
+
// $bytes += $fileOutput->fwrite($fileInput->fread($this->settings->batchSize));
|
247 |
+
// }
|
248 |
+
//
|
249 |
+
// $fileInput = null;
|
250 |
+
// $fileOutput= null;
|
251 |
+
//
|
252 |
+
// return ($bytes > 0);
|
253 |
+
// }
|
254 |
+
|
255 |
+
/**
|
256 |
+
* Copy bigger files than $this->settings->batchSize
|
257 |
+
* @param string $src
|
258 |
+
* @param string $dst
|
259 |
+
* @param int $buffersize
|
260 |
+
* @return boolean
|
261 |
+
*/
|
262 |
+
private function copyBig($src, $dst, $buffersize) {
|
263 |
+
$src = fopen($src, 'r');
|
264 |
+
$dest = fopen($dst, 'w');
|
265 |
+
|
266 |
+
// Try first method:
|
267 |
+
while (! feof($src)){
|
268 |
+
if (false === fwrite($dest, fread($src, $buffersize))){
|
269 |
+
$error = true;
|
270 |
+
}
|
271 |
+
}
|
272 |
+
// Try second method if first one failed
|
273 |
+
if (isset($error) && ($error === true)){
|
274 |
+
while(!feof($src)){
|
275 |
+
if (false === stream_copy_to_stream($src, $dest, 1024 )) {
|
276 |
+
$this->log("Can not copy big file; {$src} -> {$dest}");
|
277 |
+
fclose($src);
|
278 |
+
fclose($dest);
|
279 |
+
return false;
|
280 |
+
}
|
281 |
+
}
|
282 |
+
}
|
283 |
+
// Close any open handler
|
284 |
+
fclose($src);
|
285 |
+
fclose($dest);
|
286 |
+
return true;
|
287 |
+
}
|
288 |
}
|
apps/Backend/Modules/Jobs/Finish.php
CHANGED
@@ -1,236 +1,262 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WPStaging\Backend\Modules\Jobs;
|
3 |
-
|
4 |
-
use WPStaging\WPStaging;
|
5 |
-
|
6 |
-
//error_reporting( E_ALL );
|
7 |
-
|
8 |
-
/**
|
9 |
-
* Class Finish
|
10 |
-
* @package WPStaging\Backend\Modules\Jobs
|
11 |
-
*/
|
12 |
-
class Finish extends Job
|
13 |
-
{
|
14 |
-
|
15 |
-
|
16 |
-
*
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
$
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
*
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
$
|
76 |
-
|
77 |
-
|
78 |
-
$
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
$
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
//
|
161 |
-
//
|
162 |
-
//
|
163 |
-
//
|
164 |
-
//
|
165 |
-
//
|
166 |
-
//
|
167 |
-
//
|
168 |
-
//
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
//
|
177 |
-
//
|
178 |
-
//
|
179 |
-
//
|
180 |
-
//
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
$this->
|
190 |
-
|
191 |
-
|
192 |
-
//
|
193 |
-
if (
|
194 |
-
{
|
195 |
-
$
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
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 |
}
|
1 |
+
<?php
|
2 |
+
namespace WPStaging\Backend\Modules\Jobs;
|
3 |
+
|
4 |
+
use WPStaging\WPStaging;
|
5 |
+
|
6 |
+
//error_reporting( E_ALL );
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class Finish
|
10 |
+
* @package WPStaging\Backend\Modules\Jobs
|
11 |
+
*/
|
12 |
+
class Finish extends Job
|
13 |
+
{
|
14 |
+
/**
|
15 |
+
* Clone Key
|
16 |
+
* @var string
|
17 |
+
*/
|
18 |
+
private $clone = '';
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Start Module
|
22 |
+
* @return object
|
23 |
+
*/
|
24 |
+
public function start()
|
25 |
+
{
|
26 |
+
// sanitize the clone name before saving
|
27 |
+
$this->clone = preg_replace("#\W+#", '-', strtolower($this->options->clone));
|
28 |
+
|
29 |
+
// Delete Cache Files
|
30 |
+
$this->deleteCacheFiles();
|
31 |
+
|
32 |
+
// Prepare clone records & save scanned directories for delete job later
|
33 |
+
$this->prepareCloneDataRecords();
|
34 |
+
|
35 |
+
|
36 |
+
$return = array(
|
37 |
+
"directoryName" => $this->options->cloneDirectoryName,
|
38 |
+
"path" => ABSPATH . $this->options->cloneDirectoryName,
|
39 |
+
"url" => get_site_url() . '/' . $this->options->cloneDirectoryName,
|
40 |
+
"number" => $this->options->cloneNumber,
|
41 |
+
"version" => \WPStaging\WPStaging::VERSION,
|
42 |
+
"status" => false,
|
43 |
+
"prefix" => $this->options->prefix,
|
44 |
+
"last_msg" => $this->logger->getLastLogMsg(),
|
45 |
+
"job" => $this->options->currentJob
|
46 |
+
);
|
47 |
+
|
48 |
+
|
49 |
+
//return (object) $this->options->existingClones[$this->options->clone];
|
50 |
+
//return (object) $this->options->existingClones[$this->clone];
|
51 |
+
return (object) $return;
|
52 |
+
}
|
53 |
+
|
54 |
+
/**
|
55 |
+
* Delete Cache Files
|
56 |
+
*/
|
57 |
+
protected function deleteCacheFiles()
|
58 |
+
{
|
59 |
+
$this->log("Finish: Deleting clone job's cache files...");
|
60 |
+
|
61 |
+
// Clean cache files
|
62 |
+
$this->cache->delete("clone_options");
|
63 |
+
$this->cache->delete("files_to_copy");
|
64 |
+
|
65 |
+
$this->log("Finish: Clone job's cache files have been deleted!");
|
66 |
+
}
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Prepare clone records
|
70 |
+
* @return bool
|
71 |
+
*/
|
72 |
+
protected function prepareCloneDataRecords()
|
73 |
+
{
|
74 |
+
// Check if clones still exist
|
75 |
+
$this->log("Finish: Verifying existing clones...");
|
76 |
+
|
77 |
+
// Clone data already exists
|
78 |
+
if (isset($this->options->existingClones[$this->options->clone]))
|
79 |
+
{
|
80 |
+
$this->log("Finish: Clone data already exists, no need to update, the job finished");
|
81 |
+
return true;
|
82 |
+
}
|
83 |
+
|
84 |
+
// Save new clone data
|
85 |
+
$this->log("Finish: {$this->options->clone}'s clone job's data is not in database, generating data");
|
86 |
+
|
87 |
+
// sanitize the clone name before saving
|
88 |
+
//$clone = preg_replace("#\W+#", '-', strtolower($this->options->clone));
|
89 |
+
|
90 |
+
$this->options->existingClones[$this->clone] = array(
|
91 |
+
"directoryName" => $this->options->cloneDirectoryName,
|
92 |
+
"path" => ABSPATH . $this->options->cloneDirectoryName,
|
93 |
+
"url" => get_site_url() . '/' . $this->options->cloneDirectoryName,
|
94 |
+
"number" => $this->options->cloneNumber,
|
95 |
+
"version" => \WPStaging\WPStaging::VERSION,
|
96 |
+
"status" => false,
|
97 |
+
"prefix" => $this->options->prefix,
|
98 |
+
);
|
99 |
+
|
100 |
+
if (false === update_option("wpstg_existing_clones_beta", $this->options->existingClones))
|
101 |
+
{
|
102 |
+
$this->log("Finish: Failed to save {$this->options->clone}'s clone job data to database'");
|
103 |
+
return false;
|
104 |
+
}
|
105 |
+
|
106 |
+
// Save scanned directories for a delete job
|
107 |
+
//$this->saveScannedDirectories();
|
108 |
+
|
109 |
+
return true;
|
110 |
+
}
|
111 |
+
|
112 |
+
/**
|
113 |
+
* Save Scanned Directories for Delete Job Later
|
114 |
+
*/
|
115 |
+
// protected function saveScannedDirectories()
|
116 |
+
// {
|
117 |
+
// // Save scanned directories for delete job
|
118 |
+
// $this->cache->save("delete_directories_" . $this->options->clone, $this->options->scannedDirectories);
|
119 |
+
//
|
120 |
+
// $this->log("Successfully saved {$this->options->clone}'s clone job data to database'");
|
121 |
+
// $this->log("Cloning job has finished!");
|
122 |
+
// }
|
123 |
+
|
124 |
+
/**
|
125 |
+
* Get Upload Directory
|
126 |
+
* @return string
|
127 |
+
*/
|
128 |
+
// private function getUploadDirectory()
|
129 |
+
// {
|
130 |
+
// $wpUploadDirectory = wp_get_upload_dir();
|
131 |
+
// $uploadDirectory = $wpUploadDirectory["basedir"] . DIRECTORY_SEPARATOR . WPStaging::SLUG;
|
132 |
+
//
|
133 |
+
// // Failed to create upload directory
|
134 |
+
// if (!is_dir($uploadDirectory) && !wp_mkdir_p($uploadDirectory))
|
135 |
+
// {
|
136 |
+
// $this->log("Upload directory ({$uploadDirectory}) doesn't exist and failed to create!");
|
137 |
+
// }
|
138 |
+
//
|
139 |
+
// $uploadDirectory = apply_filters("wpstg_get_upload_dir", $uploadDirectory);
|
140 |
+
//
|
141 |
+
// return rtrim($uploadDirectory, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
|
142 |
+
// }
|
143 |
+
|
144 |
+
|
145 |
+
|
146 |
+
/**
|
147 |
+
* Get .htaccess rules
|
148 |
+
* @return string
|
149 |
+
*/
|
150 |
+
// private function getHtaccessRules()
|
151 |
+
// {
|
152 |
+
// // Prevent directory browsing and direct access to all files
|
153 |
+
// $rules = "<Files \"*\">\n";
|
154 |
+
// $rules .= "<IfModule mod_access.c>\n";
|
155 |
+
// $rules .= "Deny from all\n";
|
156 |
+
// $rules .= "</IfModule>\n";
|
157 |
+
// $rules .= "<IfModule !mod_access_compat>\n";
|
158 |
+
// $rules .= "<IfModule mod_authz_host.c>\n";
|
159 |
+
// $rules .= "Deny from all\n";
|
160 |
+
// $rules .= "</IfModule>\n";
|
161 |
+
// $rules .= "</IfModule>\n";
|
162 |
+
// $rules .= "<IfModule mod_access_compat>\n";
|
163 |
+
// $rules .= "Deny from all\n";
|
164 |
+
// $rules .= "</IfModule>\n";
|
165 |
+
// $rules .= "</Files>\n";
|
166 |
+
//
|
167 |
+
// return apply_filters("wpstg_protected_directory_htaccess_rules", $rules);
|
168 |
+
// }
|
169 |
+
|
170 |
+
/**
|
171 |
+
* Update .htaccess file and its rules
|
172 |
+
* @param string $file
|
173 |
+
* @param string $contents
|
174 |
+
* @return bool
|
175 |
+
*/
|
176 |
+
// private function updateHTAccess($file, $contents)
|
177 |
+
// {
|
178 |
+
// return (
|
179 |
+
// (!$contents || $this->getHtaccessRules() !== $contents) &&
|
180 |
+
// false === @file_put_contents($file, $this->getHtaccessRules())
|
181 |
+
// );
|
182 |
+
// }
|
183 |
+
|
184 |
+
/**
|
185 |
+
* Save HTAccess file
|
186 |
+
*/
|
187 |
+
// private function saveHTAccess()
|
188 |
+
// {
|
189 |
+
// $uploadDir = $this->getUploadDirectory();
|
190 |
+
// $htAccessFile = $uploadDir . ".htaccess";
|
191 |
+
//
|
192 |
+
// // .htaccess exists
|
193 |
+
// if (file_exists($htAccessFile))
|
194 |
+
// {
|
195 |
+
// $contents = @file_get_contents($htAccessFile);
|
196 |
+
//
|
197 |
+
// // Rules doesn't match, update .htaccess rules
|
198 |
+
// if (false === $this->updateHTAccess($htAccessFile, $contents))
|
199 |
+
// {
|
200 |
+
// $this->log("Failed to update {$htAccessFile}");
|
201 |
+
// }
|
202 |
+
// }
|
203 |
+
// // .htaccess doesn't exists and
|
204 |
+
// else if (wp_is_writable($uploadDir) && false === @file_put_contents($htAccessFile, $this->getHtaccessRules()))
|
205 |
+
// {
|
206 |
+
// $this->log("Failed to create {$htAccessFile}");
|
207 |
+
// }
|
208 |
+
// }
|
209 |
+
|
210 |
+
/**
|
211 |
+
* Save blank index file
|
212 |
+
* @return bool
|
213 |
+
*/
|
214 |
+
// private function saveBlankIndex()
|
215 |
+
// {
|
216 |
+
// $uploadDir = $this->getUploadDirectory();
|
217 |
+
// $indexFile = $uploadDir . "index.php";
|
218 |
+
//
|
219 |
+
// if (file_exists($indexFile))
|
220 |
+
// {
|
221 |
+
// return true;
|
222 |
+
// }
|
223 |
+
//
|
224 |
+
// $contents = "<?php" . PHP_EOL . "// WP-Staging protection file";
|
225 |
+
//
|
226 |
+
// if (!wp_is_writable($uploadDir) || false === @file_put_contents($indexFile, $contents))
|
227 |
+
// {
|
228 |
+
// $this->log("{$uploadDir} is not writable or couldn't generate {$indexFile}");
|
229 |
+
// return false;
|
230 |
+
// }
|
231 |
+
//
|
232 |
+
// return true;
|
233 |
+
// }
|
234 |
+
|
235 |
+
/**
|
236 |
+
* Prepare protect directories and files
|
237 |
+
* @param bool $force
|
238 |
+
*/
|
239 |
+
// protected function protectDirectoriesAndFiles($force = false)
|
240 |
+
// {
|
241 |
+
// // Don't execute
|
242 |
+
// if (true !== get_transient("wpstg_check_protection_files") && false === $force)
|
243 |
+
// {
|
244 |
+
// return;
|
245 |
+
// }
|
246 |
+
//
|
247 |
+
// // Save .htaccess file
|
248 |
+
// $this->saveHTAccess();
|
249 |
+
//
|
250 |
+
// // Save blank index.php file
|
251 |
+
// $this->saveBlankIndex();
|
252 |
+
//
|
253 |
+
// // TODO put blank index to upload directories?? Why??
|
254 |
+
//
|
255 |
+
// // Check files once a day
|
256 |
+
// set_transient("wpstg_check_protection_files", true, DAY_IN_SECONDS); // 24 hours in seconds
|
257 |
+
//
|
258 |
+
//
|
259 |
+
// }
|
260 |
+
|
261 |
+
|
262 |
}
|
apps/Backend/Modules/Jobs/Job.php
CHANGED
@@ -1,473 +1,474 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WPStaging\Backend\Modules\Jobs;
|
3 |
-
|
4 |
-
// No Direct Access
|
5 |
-
if (!defined("WPINC"))
|
6 |
-
{
|
7 |
-
die;
|
8 |
-
}
|
9 |
-
|
10 |
-
use WPStaging\Backend\Modules\Jobs\Interfaces\JobInterface;
|
11 |
-
use WPStaging\Utils\Logger;
|
12 |
-
use WPStaging\WPStaging;
|
13 |
-
use WPStaging\Utils\Cache;
|
14 |
-
|
15 |
-
/**
|
16 |
-
* Class Job
|
17 |
-
* @package WPStaging\Backend\Modules\Jobs
|
18 |
-
*/
|
19 |
-
abstract class Job implements JobInterface
|
20 |
-
{
|
21 |
-
|
22 |
-
const EXECUTION_TIME_RATIO = 0.8;
|
23 |
-
|
24 |
-
const MAX_MEMORY_RATIO = 0.8;
|
25 |
-
|
26 |
-
/**
|
27 |
-
* @var Cache
|
28 |
-
*/
|
29 |
-
protected $cache;
|
30 |
-
|
31 |
-
/**
|
32 |
-
* @var Logger
|
33 |
-
*/
|
34 |
-
protected $logger;
|
35 |
-
|
36 |
-
/**
|
37 |
-
* @var bool
|
38 |
-
*/
|
39 |
-
protected $hasLoggedFileNameSet = false;
|
40 |
-
|
41 |
-
/**
|
42 |
-
* @var object
|
43 |
-
*/
|
44 |
-
protected $options;
|
45 |
-
|
46 |
-
/**
|
47 |
-
* @var object
|
48 |
-
*/
|
49 |
-
protected $settings;
|
50 |
-
|
51 |
-
/**
|
52 |
-
* System total maximum memory consumption
|
53 |
-
* @var int
|
54 |
-
*/
|
55 |
-
protected $maxMemoryLimit;
|
56 |
-
|
57 |
-
/**
|
58 |
-
* Script maximum memory consumption
|
59 |
-
* @var int
|
60 |
-
*/
|
61 |
-
protected $memoryLimit;
|
62 |
-
|
63 |
-
/**
|
64 |
-
* @var int
|
65 |
-
*/
|
66 |
-
protected $maxExecutionTime;
|
67 |
-
|
68 |
-
|
69 |
-
/**
|
70 |
-
* @var int
|
71 |
-
*/
|
72 |
-
protected $executionLimit;
|
73 |
-
|
74 |
-
/**
|
75 |
-
* @var int
|
76 |
-
*/
|
77 |
-
protected $totalRecursion;
|
78 |
-
|
79 |
-
/**
|
80 |
-
* @var int
|
81 |
-
*/
|
82 |
-
protected $maxRecursionLimit;
|
83 |
-
|
84 |
-
/**
|
85 |
-
* @var int
|
86 |
-
*/
|
87 |
-
protected $start;
|
88 |
-
|
89 |
-
/**
|
90 |
-
* Job constructor.
|
91 |
-
*/
|
92 |
-
public function __construct()
|
93 |
-
{
|
94 |
-
// Get max limits
|
95 |
-
$this->start = $this->time();
|
96 |
-
$this->maxMemoryLimit = $this->getMemoryInBytes(@ini_get("memory_limit"));
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
if ($this->maxExecutionTime > 30)
|
101 |
-
{
|
102 |
-
$this->maxExecutionTime = 30;
|
103 |
-
}
|
104 |
-
|
105 |
-
if ($this->maxExecutionTime < 1)
|
106 |
-
{
|
107 |
-
$this->maxExecutionTime = 30;
|
108 |
-
}
|
109 |
-
|
110 |
-
|
111 |
-
// Services
|
112 |
-
$this->cache = new Cache(-1, \WPStaging\WPStaging::getContentDir());
|
113 |
-
$this->logger = WPStaging::getInstance()->get("logger");
|
114 |
-
|
115 |
-
// Settings and Options
|
116 |
-
$this->options = $this->cache->get("clone_options");
|
117 |
-
//$this->settings = json_decode(json_encode(get_option("wpstg_settings", array())));
|
118 |
-
$this->settings = (object)get_option("wpstg_settings", array());
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
// check default options
|
123 |
-
if (!$this->settings)
|
124 |
-
{
|
125 |
-
$this->options = new \stdClass();
|
126 |
-
}
|
127 |
-
|
128 |
-
if (isset($this->options->existingClones) && is_object($this->options->existingClones))
|
129 |
-
{
|
130 |
-
$this->options->existingClones = json_decode(json_encode($this->options->existingClones), true);
|
131 |
-
}
|
132 |
-
|
133 |
-
if (!isset($this->settings) || !isset($this->settings->queryLimit) || !isset($this->settings->batchSize) || !isset($this->settings->cpuLoad))
|
134 |
-
{
|
135 |
-
$this->settings = new \stdClass();
|
136 |
-
$this->setDefaultSettings();
|
137 |
-
}
|
138 |
-
|
139 |
-
// Set limits accordingly to CPU LIMITS
|
140 |
-
$this->setLimits();
|
141 |
-
|
142 |
-
$this->maxRecursionLimit = (int) ini_get("xdebug.max_nesting_level");
|
143 |
-
|
144 |
-
/*
|
145 |
-
* This is needed to make sure that maxRecursionLimit = -1
|
146 |
-
* if xdebug is not used in production env.
|
147 |
-
* For using xdebug, maxRecursionLimit must be larger
|
148 |
-
* otherwise xdebug is throwing an error 500 while debugging
|
149 |
-
*/
|
150 |
-
if ($this->maxRecursionLimit < 1)
|
151 |
-
{
|
152 |
-
$this->maxRecursionLimit = -1;
|
153 |
-
}
|
154 |
-
else
|
155 |
-
{
|
156 |
-
$this->maxRecursionLimit = $this->maxRecursionLimit - 50; // just to make sure
|
157 |
-
}
|
158 |
-
|
159 |
-
if (method_exists($this, "initialize"))
|
160 |
-
{
|
161 |
-
$this->initialize();
|
162 |
-
}
|
163 |
-
}
|
164 |
-
|
165 |
-
/**
|
166 |
-
* Job destructor
|
167 |
-
*/
|
168 |
-
public function __destruct()
|
169 |
-
{
|
170 |
-
// Commit logs
|
171 |
-
$this->logger->commit();
|
172 |
-
}
|
173 |
-
|
174 |
-
/**
|
175 |
-
* Set default settings
|
176 |
-
*/
|
177 |
-
protected function setDefaultSettings(){
|
178 |
-
$this->settings->queryLimit = "1000";
|
179 |
-
$this->settings->
|
180 |
-
$this->settings->
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
$
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
$this->
|
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 |
-
|
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 |
-
$time =
|
306 |
-
$time =
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
$this->
|
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 |
-
|
433 |
-
* @param string $
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
$this->
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
* @param string $
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
$this->
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
|
|
473 |
}
|
1 |
+
<?php
|
2 |
+
namespace WPStaging\Backend\Modules\Jobs;
|
3 |
+
|
4 |
+
// No Direct Access
|
5 |
+
if (!defined("WPINC"))
|
6 |
+
{
|
7 |
+
die;
|
8 |
+
}
|
9 |
+
|
10 |
+
use WPStaging\Backend\Modules\Jobs\Interfaces\JobInterface;
|
11 |
+
use WPStaging\Utils\Logger;
|
12 |
+
use WPStaging\WPStaging;
|
13 |
+
use WPStaging\Utils\Cache;
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Class Job
|
17 |
+
* @package WPStaging\Backend\Modules\Jobs
|
18 |
+
*/
|
19 |
+
abstract class Job implements JobInterface
|
20 |
+
{
|
21 |
+
|
22 |
+
const EXECUTION_TIME_RATIO = 0.8;
|
23 |
+
|
24 |
+
const MAX_MEMORY_RATIO = 0.8;
|
25 |
+
|
26 |
+
/**
|
27 |
+
* @var Cache
|
28 |
+
*/
|
29 |
+
protected $cache;
|
30 |
+
|
31 |
+
/**
|
32 |
+
* @var Logger
|
33 |
+
*/
|
34 |
+
protected $logger;
|
35 |
+
|
36 |
+
/**
|
37 |
+
* @var bool
|
38 |
+
*/
|
39 |
+
protected $hasLoggedFileNameSet = false;
|
40 |
+
|
41 |
+
/**
|
42 |
+
* @var object
|
43 |
+
*/
|
44 |
+
protected $options;
|
45 |
+
|
46 |
+
/**
|
47 |
+
* @var object
|
48 |
+
*/
|
49 |
+
protected $settings;
|
50 |
+
|
51 |
+
/**
|
52 |
+
* System total maximum memory consumption
|
53 |
+
* @var int
|
54 |
+
*/
|
55 |
+
protected $maxMemoryLimit;
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Script maximum memory consumption
|
59 |
+
* @var int
|
60 |
+
*/
|
61 |
+
protected $memoryLimit;
|
62 |
+
|
63 |
+
/**
|
64 |
+
* @var int
|
65 |
+
*/
|
66 |
+
protected $maxExecutionTime;
|
67 |
+
|
68 |
+
|
69 |
+
/**
|
70 |
+
* @var int
|
71 |
+
*/
|
72 |
+
protected $executionLimit;
|
73 |
+
|
74 |
+
/**
|
75 |
+
* @var int
|
76 |
+
*/
|
77 |
+
protected $totalRecursion;
|
78 |
+
|
79 |
+
/**
|
80 |
+
* @var int
|
81 |
+
*/
|
82 |
+
protected $maxRecursionLimit;
|
83 |
+
|
84 |
+
/**
|
85 |
+
* @var int
|
86 |
+
*/
|
87 |
+
protected $start;
|
88 |
+
|
89 |
+
/**
|
90 |
+
* Job constructor.
|
91 |
+
*/
|
92 |
+
public function __construct()
|
93 |
+
{
|
94 |
+
// Get max limits
|
95 |
+
$this->start = $this->time();
|
96 |
+
$this->maxMemoryLimit = $this->getMemoryInBytes(@ini_get("memory_limit"));
|
97 |
+
//$this->maxExecutionTime = (int) ini_get("max_execution_time");
|
98 |
+
$this->maxExecutionTime = (int) 30;
|
99 |
+
|
100 |
+
// if ($this->maxExecutionTime > 30)
|
101 |
+
// {
|
102 |
+
// $this->maxExecutionTime = 30;
|
103 |
+
// }
|
104 |
+
//
|
105 |
+
// if ($this->maxExecutionTime < 1)
|
106 |
+
// {
|
107 |
+
// $this->maxExecutionTime = 30;
|
108 |
+
// }
|
109 |
+
|
110 |
+
|
111 |
+
// Services
|
112 |
+
$this->cache = new Cache(-1, \WPStaging\WPStaging::getContentDir());
|
113 |
+
$this->logger = WPStaging::getInstance()->get("logger");
|
114 |
+
|
115 |
+
// Settings and Options
|
116 |
+
$this->options = $this->cache->get("clone_options");
|
117 |
+
//$this->settings = json_decode(json_encode(get_option("wpstg_settings", array())));
|
118 |
+
$this->settings = (object)get_option("wpstg_settings", array());
|
119 |
+
|
120 |
+
|
121 |
+
|
122 |
+
// check default options
|
123 |
+
if (!$this->settings)
|
124 |
+
{
|
125 |
+
$this->options = new \stdClass();
|
126 |
+
}
|
127 |
+
|
128 |
+
if (isset($this->options->existingClones) && is_object($this->options->existingClones))
|
129 |
+
{
|
130 |
+
$this->options->existingClones = json_decode(json_encode($this->options->existingClones), true);
|
131 |
+
}
|
132 |
+
|
133 |
+
if (!isset($this->settings) || !isset($this->settings->queryLimit) || !isset($this->settings->batchSize) || !isset($this->settings->cpuLoad))
|
134 |
+
{
|
135 |
+
$this->settings = new \stdClass();
|
136 |
+
$this->setDefaultSettings();
|
137 |
+
}
|
138 |
+
|
139 |
+
// Set limits accordingly to CPU LIMITS
|
140 |
+
$this->setLimits();
|
141 |
+
|
142 |
+
$this->maxRecursionLimit = (int) ini_get("xdebug.max_nesting_level");
|
143 |
+
|
144 |
+
/*
|
145 |
+
* This is needed to make sure that maxRecursionLimit = -1
|
146 |
+
* if xdebug is not used in production env.
|
147 |
+
* For using xdebug, maxRecursionLimit must be larger
|
148 |
+
* otherwise xdebug is throwing an error 500 while debugging
|
149 |
+
*/
|
150 |
+
if ($this->maxRecursionLimit < 1)
|
151 |
+
{
|
152 |
+
$this->maxRecursionLimit = -1;
|
153 |
+
}
|
154 |
+
else
|
155 |
+
{
|
156 |
+
$this->maxRecursionLimit = $this->maxRecursionLimit - 50; // just to make sure
|
157 |
+
}
|
158 |
+
|
159 |
+
if (method_exists($this, "initialize"))
|
160 |
+
{
|
161 |
+
$this->initialize();
|
162 |
+
}
|
163 |
+
}
|
164 |
+
|
165 |
+
/**
|
166 |
+
* Job destructor
|
167 |
+
*/
|
168 |
+
public function __destruct()
|
169 |
+
{
|
170 |
+
// Commit logs
|
171 |
+
$this->logger->commit();
|
172 |
+
}
|
173 |
+
|
174 |
+
/**
|
175 |
+
* Set default settings
|
176 |
+
*/
|
177 |
+
protected function setDefaultSettings(){
|
178 |
+
$this->settings->queryLimit = "1000";
|
179 |
+
$this->settings->fileCopyLimit = "10";
|
180 |
+
$this->settings->batchSize = "2";
|
181 |
+
$this->settings->cpuLoad = 'medium';
|
182 |
+
update_option('wpstg_settings', $this->settings);
|
183 |
+
}
|
184 |
+
|
185 |
+
/**
|
186 |
+
* Set limits accordingly to
|
187 |
+
*/
|
188 |
+
protected function setLimits()
|
189 |
+
{
|
190 |
+
|
191 |
+
if (!isset($this->settings->cpuLoad))
|
192 |
+
{
|
193 |
+
$this->settings->cpuLoad = "medium";
|
194 |
+
}
|
195 |
+
|
196 |
+
$memoryLimit= self::MAX_MEMORY_RATIO;
|
197 |
+
$timeLimit = self::EXECUTION_TIME_RATIO;
|
198 |
+
|
199 |
+
switch($this->settings->cpuLoad)
|
200 |
+
{
|
201 |
+
case "medium":
|
202 |
+
//$memoryLimit= $memoryLimit / 2; // 0.4
|
203 |
+
$timeLimit = $timeLimit / 2;
|
204 |
+
break;
|
205 |
+
case "low":
|
206 |
+
//$memoryLimit= $memoryLimit / 4; // 0.2
|
207 |
+
$timeLimit = $timeLimit / 4;
|
208 |
+
break;
|
209 |
+
|
210 |
+
case "fast": // 0.8
|
211 |
+
default:
|
212 |
+
break;
|
213 |
+
}
|
214 |
+
|
215 |
+
$this->memoryLimit = $this->maxMemoryLimit * $memoryLimit;
|
216 |
+
$this->executionLimit = $this->maxExecutionTime * $timeLimit;
|
217 |
+
}
|
218 |
+
|
219 |
+
/**
|
220 |
+
* Save options
|
221 |
+
* @param null|array|object $options
|
222 |
+
* @return bool
|
223 |
+
*/
|
224 |
+
protected function saveOptions($options = null)
|
225 |
+
{
|
226 |
+
// Get default options
|
227 |
+
if (null === $options)
|
228 |
+
{
|
229 |
+
$options = $this->options;
|
230 |
+
}
|
231 |
+
|
232 |
+
// Ensure that it is an object
|
233 |
+
$options = json_decode(json_encode($options));
|
234 |
+
|
235 |
+
return $this->cache->save("clone_options", $options);
|
236 |
+
}
|
237 |
+
|
238 |
+
/**
|
239 |
+
* @return object
|
240 |
+
*/
|
241 |
+
public function getOptions()
|
242 |
+
{
|
243 |
+
return $this->options;
|
244 |
+
}
|
245 |
+
|
246 |
+
/**
|
247 |
+
* @param string $memory
|
248 |
+
* @return int
|
249 |
+
*/
|
250 |
+
protected function getMemoryInBytes($memory)
|
251 |
+
{
|
252 |
+
// Handle unlimited ones
|
253 |
+
if (1 > (int) $memory)
|
254 |
+
{
|
255 |
+
return (int) $memory;
|
256 |
+
}
|
257 |
+
|
258 |
+
$bytes = (int) $memory; // grab only the number
|
259 |
+
$size = trim(str_replace($bytes, null, strtolower($memory))); // strip away number and lower-case it
|
260 |
+
|
261 |
+
// Actual calculation
|
262 |
+
switch($size)
|
263 |
+
{
|
264 |
+
case 'k':
|
265 |
+
$bytes *= 1024;
|
266 |
+
break;
|
267 |
+
case 'm':
|
268 |
+
$bytes *= (1024 * 1024);
|
269 |
+
break;
|
270 |
+
case 'g':
|
271 |
+
$bytes *= (1024 * 1024 * 1024);
|
272 |
+
break;
|
273 |
+
}
|
274 |
+
|
275 |
+
return $bytes;
|
276 |
+
}
|
277 |
+
|
278 |
+
/**
|
279 |
+
* Format bytes into ini_set favorable form
|
280 |
+
* @param int $bytes
|
281 |
+
* @return string
|
282 |
+
*/
|
283 |
+
protected function formatBytes($bytes)
|
284 |
+
{
|
285 |
+
if ((int) $bytes < 1)
|
286 |
+
{
|
287 |
+
return '';
|
288 |
+
}
|
289 |
+
|
290 |
+
$units = array('B', 'K', 'M', 'G'); // G since PHP 5.1.x so we are good!
|
291 |
+
|
292 |
+
$bytes = (int) $bytes;
|
293 |
+
$base = log($bytes) / log(1000);
|
294 |
+
$pow = pow(1000, $base - floor($base));
|
295 |
+
|
296 |
+
return round($pow, 0) . $units[(int) floor($base)];
|
297 |
+
}
|
298 |
+
|
299 |
+
/**
|
300 |
+
* Get current time in seconds
|
301 |
+
* @return float
|
302 |
+
*/
|
303 |
+
protected function time()
|
304 |
+
{
|
305 |
+
$time = microtime();
|
306 |
+
$time = explode(' ', $time);
|
307 |
+
$time = $time[1] + $time[0];
|
308 |
+
return $time;
|
309 |
+
}
|
310 |
+
|
311 |
+
/**
|
312 |
+
* @return bool
|
313 |
+
*/
|
314 |
+
protected function isOverThreshold()
|
315 |
+
{
|
316 |
+
// Check if the memory is over threshold
|
317 |
+
$usedMemory = (int) @memory_get_usage(true);
|
318 |
+
|
319 |
+
$this->debugLog('Used Memory: ' . $this->formatBytes( $usedMemory ) . ' Max Memory Limit: ' . $this->formatBytes( $this->maxMemoryLimit ) . ' Max Script Memory Limit: ' . $this->formatBytes( $this->memoryLimit), Logger::TYPE_DEBUG );
|
320 |
+
|
321 |
+
if ($usedMemory >= $this->memoryLimit)
|
322 |
+
{
|
323 |
+
$this->log('Used Memory: ' . $this->formatBytes($usedMemory) . ' Memory Limit: ' . $this->formatBytes($this->maxMemoryLimit) . ' Max Script memory limit: ' . $this->formatBytes( $this->memoryLimit ) );
|
324 |
+
$this->resetMemory();
|
325 |
+
return true;
|
326 |
+
}
|
327 |
+
|
328 |
+
if ($this->isRecursionLimit())
|
329 |
+
{
|
330 |
+
//$this->log('RESET RECURSION');
|
331 |
+
return true;
|
332 |
+
}
|
333 |
+
|
334 |
+
// Check if execution time is over threshold
|
335 |
+
///$time = round($this->start + $this->time(), 4);
|
336 |
+
$time = round($this->time() - $this->start, 4);
|
337 |
+
$this->debugLog( 'Execution time: ' . $time . ' Execution Limit' . $this->executionLimit );
|
338 |
+
if ($time >= $this->executionLimit)
|
339 |
+
{
|
340 |
+
//$this->log('RESET TIME');
|
341 |
+
return true;
|
342 |
+
}
|
343 |
+
|
344 |
+
return false;
|
345 |
+
}
|
346 |
+
|
347 |
+
/**
|
348 |
+
* Attempt to reset memory
|
349 |
+
* @return bool
|
350 |
+
*
|
351 |
+
*/
|
352 |
+
protected function resetMemory()
|
353 |
+
{
|
354 |
+
$newMemoryLimit = $this->maxMemoryLimit * 2;
|
355 |
+
|
356 |
+
// Failed to set
|
357 |
+
if (false === ini_set("memory_limit", $this->formatBytes($newMemoryLimit)))
|
358 |
+
{
|
359 |
+
$this->log('Can not free some memory', Logger::TYPE_CRITICAL);
|
360 |
+
return false;
|
361 |
+
}
|
362 |
+
|
363 |
+
// Double checking
|
364 |
+
$newMemoryLimit = $this->getMemoryInBytes(@ini_get("memory_limit"));
|
365 |
+
if ($newMemoryLimit <= $this->maxMemoryLimit)
|
366 |
+
{
|
367 |
+
return false;
|
368 |
+
}
|
369 |
+
|
370 |
+
// Set the new Maximum memory limit
|
371 |
+
$this->maxMemoryLimit = $newMemoryLimit;
|
372 |
+
|
373 |
+
// Calculate threshold limit
|
374 |
+
$this->memoryLimit = $newMemoryLimit * self::MAX_MEMORY_RATIO;
|
375 |
+
|
376 |
+
return true;
|
377 |
+
}
|
378 |
+
|
379 |
+
/**
|
380 |
+
* Attempt to reset time
|
381 |
+
* @return bool
|
382 |
+
*
|
383 |
+
* @deprecated since version 2.0.0
|
384 |
+
|
385 |
+
*/
|
386 |
+
protected function resetTime()
|
387 |
+
{
|
388 |
+
// Attempt to reset timeout
|
389 |
+
if (!@set_time_limit($this->maxExecutionTime))
|
390 |
+
{
|
391 |
+
return false;
|
392 |
+
}
|
393 |
+
|
394 |
+
// Increase execution limit
|
395 |
+
$this->executionLimit = $this->executionLimit * 2;
|
396 |
+
|
397 |
+
return true;
|
398 |
+
}
|
399 |
+
|
400 |
+
/**
|
401 |
+
* Reset time limit and memory
|
402 |
+
* @return bool
|
403 |
+
*
|
404 |
+
* @deprecated since version 2.0.0
|
405 |
+
*/
|
406 |
+
protected function reset()
|
407 |
+
{
|
408 |
+
// Attempt to reset time
|
409 |
+
if (!$this->resetTime())
|
410 |
+
{
|
411 |
+
return false;
|
412 |
+
}
|
413 |
+
|
414 |
+
// Attempt to reset memory
|
415 |
+
if (!$this->resetMemory())
|
416 |
+
{
|
417 |
+
return false;
|
418 |
+
}
|
419 |
+
|
420 |
+
return true;
|
421 |
+
}
|
422 |
+
|
423 |
+
/**
|
424 |
+
* Checks if calls are over recursion limit
|
425 |
+
* @return bool
|
426 |
+
*/
|
427 |
+
protected function isRecursionLimit()
|
428 |
+
{
|
429 |
+
return ($this->maxRecursionLimit > 0 && $this->totalRecursion >= $this->maxRecursionLimit);
|
430 |
+
}
|
431 |
+
|
432 |
+
/**
|
433 |
+
* @param string $msg
|
434 |
+
* @param string $type
|
435 |
+
*/
|
436 |
+
protected function log($msg, $type = Logger::TYPE_INFO)
|
437 |
+
{
|
438 |
+
|
439 |
+
if (!isset($this->options->clone)){
|
440 |
+
$this->options->clone = date(DATE_ATOM, mktime(0, 0, 0, 7, 1, 2000));
|
441 |
+
}
|
442 |
+
|
443 |
+
if (false === $this->hasLoggedFileNameSet && 0 < strlen($this->options->clone))
|
444 |
+
{
|
445 |
+
$this->logger->setFileName($this->options->clone);
|
446 |
+
$this->hasLoggedFileNameSet = true;
|
447 |
+
}
|
448 |
+
|
449 |
+
$this->logger->add($msg, $type);
|
450 |
+
}
|
451 |
+
/**
|
452 |
+
* @param string $msg
|
453 |
+
* @param string $type
|
454 |
+
*/
|
455 |
+
protected function debugLog($msg, $type = Logger::TYPE_INFO)
|
456 |
+
{
|
457 |
+
|
458 |
+
if (!isset($this->options->clone)){
|
459 |
+
$this->options->clone = date(DATE_ATOM, mktime(0, 0, 0, 7, 1, 2000));
|
460 |
+
}
|
461 |
+
|
462 |
+
if (false === $this->hasLoggedFileNameSet && 0 < strlen($this->options->clone))
|
463 |
+
{
|
464 |
+
$this->logger->setFileName($this->options->clone);
|
465 |
+
$this->hasLoggedFileNameSet = true;
|
466 |
+
}
|
467 |
+
|
468 |
+
|
469 |
+
if (isset($this->settings->debugMode)){
|
470 |
+
$this->logger->add($msg, $type);
|
471 |
+
}
|
472 |
+
|
473 |
+
}
|
474 |
}
|
apps/Backend/Modules/SystemInfo.php
CHANGED
@@ -143,6 +143,7 @@ class SystemInfo extends InjectionAware
|
|
143 |
|
144 |
$output = "-- WP Staging Settings" . PHP_EOL . PHP_EOL;
|
145 |
$output .= $this->info( "Query Limit:", isset( $settings->queryLimit ) ? $settings->queryLimit : 'undefined' );
|
|
|
146 |
$output .= $this->info( "Batch Size:", isset( $settings->batchSize ) ? $settings->batchSize : 'undefined' );
|
147 |
$output .= $this->info( "CPU Load:", isset( $settings->cpuLoad ) ? $settings->cpuLoad : 'undefined' );
|
148 |
$output .= $this->info( "WP in Subdir:", isset( $settings->wpSubDirectory ) ? $settings->wpSubDirectory : 'false' );
|
143 |
|
144 |
$output = "-- WP Staging Settings" . PHP_EOL . PHP_EOL;
|
145 |
$output .= $this->info( "Query Limit:", isset( $settings->queryLimit ) ? $settings->queryLimit : 'undefined' );
|
146 |
+
$output .= $this->info( "File Copy Limit:", isset( $settings->fileLimit ) ? $settings->fileLimit : 'undefined' );
|
147 |
$output .= $this->info( "Batch Size:", isset( $settings->batchSize ) ? $settings->batchSize : 'undefined' );
|
148 |
$output .= $this->info( "CPU Load:", isset( $settings->cpuLoad ) ? $settings->cpuLoad : 'undefined' );
|
149 |
$output .= $this->info( "WP in Subdir:", isset( $settings->wpSubDirectory ) ? $settings->wpSubDirectory : 'false' );
|
apps/Backend/Modules/Views/Forms/Settings.php
CHANGED
@@ -4,6 +4,7 @@ namespace WPStaging\Backend\Modules\Views\Forms;
|
|
4 |
use WPStaging\Forms\Elements\Check;
|
5 |
use WPStaging\Forms\Elements\Numerical;
|
6 |
use WPStaging\Forms\Elements\Select;
|
|
|
7 |
use WPStaging\Forms\Form;
|
8 |
use WPStaging\Backend\Modules\Views\Tabs\Tabs;
|
9 |
|
@@ -65,6 +66,24 @@ class Settings
|
|
65 |
->setDefault(isset($settings->queryLimit) ? $settings->queryLimit : 1000)
|
66 |
);
|
67 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
68 |
// File Copy Batch Size
|
69 |
$element = new Numerical(
|
70 |
"wpstg_settings[batchSize]",
|
@@ -96,6 +115,7 @@ class Settings
|
|
96 |
->setDefault(isset($settings->cpuLoad) ? $settings->cpuLoad : "fast")
|
97 |
);
|
98 |
|
|
|
99 |
// Optimizer
|
100 |
$element = new Check(
|
101 |
"wpstg_settings[optimizer]",
|
4 |
use WPStaging\Forms\Elements\Check;
|
5 |
use WPStaging\Forms\Elements\Numerical;
|
6 |
use WPStaging\Forms\Elements\Select;
|
7 |
+
use WPStaging\Forms\Elements\SelectMultiple;
|
8 |
use WPStaging\Forms\Form;
|
9 |
use WPStaging\Backend\Modules\Views\Tabs\Tabs;
|
10 |
|
66 |
->setDefault(isset($settings->queryLimit) ? $settings->queryLimit : 1000)
|
67 |
);
|
68 |
|
69 |
+
$options = array('250' => '250' ,'500' => '500', '1000' => '1000');
|
70 |
+
// DB Copy Query Limit
|
71 |
+
$element = new Select(
|
72 |
+
"wpstg_settings[fileLimit]",
|
73 |
+
$options,
|
74 |
+
array(
|
75 |
+
"class" => "medium-text",
|
76 |
+
"step" => 1,
|
77 |
+
"max" => 999999,
|
78 |
+
"min" => 0
|
79 |
+
)
|
80 |
+
);
|
81 |
+
|
82 |
+
$this->form["general"]->add(
|
83 |
+
$element->setLabel("File Copy Limit")->setDefault(isset($settings->fileLimit) ? $settings->fileLimit : 500)
|
84 |
+
);
|
85 |
+
|
86 |
+
|
87 |
// File Copy Batch Size
|
88 |
$element = new Numerical(
|
89 |
"wpstg_settings[batchSize]",
|
115 |
->setDefault(isset($settings->cpuLoad) ? $settings->cpuLoad : "fast")
|
116 |
);
|
117 |
|
118 |
+
|
119 |
// Optimizer
|
120 |
$element = new Check(
|
121 |
"wpstg_settings[optimizer]",
|
apps/Backend/Notices/Notices.php
CHANGED
@@ -1,147 +1,155 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPStaging\Backend\Notices;
|
4 |
-
|
5 |
-
/*
|
6 |
-
* Admin Notices | Warnings | Messages
|
7 |
-
*/
|
8 |
-
|
9 |
-
// No Direct Access
|
10 |
-
if( !defined( "WPINC" ) ) {
|
11 |
-
die;
|
12 |
-
}
|
13 |
-
|
14 |
-
use WPStaging\WPStaging;
|
15 |
-
|
16 |
-
/**
|
17 |
-
* Class Notices
|
18 |
-
* @package WPStaging\Backend\Notices
|
19 |
-
*/
|
20 |
-
class Notices {
|
21 |
-
|
22 |
-
/**
|
23 |
-
* @var string
|
24 |
-
*/
|
25 |
-
private $path;
|
26 |
-
|
27 |
-
/**
|
28 |
-
* @var string
|
29 |
-
*/
|
30 |
-
private $url;
|
31 |
-
|
32 |
-
public function __construct( $path, $url ) {
|
33 |
-
$this->path = $path;
|
34 |
-
$this->url = $url;
|
35 |
-
}
|
36 |
-
|
37 |
-
/**
|
38 |
-
* Check whether the page is admin page or not
|
39 |
-
* @return bool
|
40 |
-
*/
|
41 |
-
private function isAdminPage() {
|
42 |
-
$currentPage = (isset( $_GET["page"] )) ? $_GET["page"] : null;
|
43 |
-
|
44 |
-
$availablePages = array(
|
45 |
-
"wpstg-settings", "wpstg-addons", "wpstg-tools", "wpstg-clone", "wpstg_clone"
|
46 |
-
);
|
47 |
-
|
48 |
-
if( !is_admin() || !did_action( "wp_loaded" ) || !in_array( $currentPage, $availablePages, true ) ) {
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
*
|
58 |
-
* @
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
$
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPStaging\Backend\Notices;
|
4 |
+
|
5 |
+
/*
|
6 |
+
* Admin Notices | Warnings | Messages
|
7 |
+
*/
|
8 |
+
|
9 |
+
// No Direct Access
|
10 |
+
if( !defined( "WPINC" ) ) {
|
11 |
+
die;
|
12 |
+
}
|
13 |
+
|
14 |
+
use WPStaging\WPStaging;
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Class Notices
|
18 |
+
* @package WPStaging\Backend\Notices
|
19 |
+
*/
|
20 |
+
class Notices {
|
21 |
+
|
22 |
+
/**
|
23 |
+
* @var string
|
24 |
+
*/
|
25 |
+
private $path;
|
26 |
+
|
27 |
+
/**
|
28 |
+
* @var string
|
29 |
+
*/
|
30 |
+
private $url;
|
31 |
+
|
32 |
+
public function __construct( $path, $url ) {
|
33 |
+
$this->path = $path;
|
34 |
+
$this->url = $url;
|
35 |
+
}
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Check whether the page is an WP QUADS admin settings page or not
|
39 |
+
* @return bool
|
40 |
+
*/
|
41 |
+
private function isAdminPage() {
|
42 |
+
$currentPage = (isset( $_GET["page"] )) ? $_GET["page"] : null;
|
43 |
+
|
44 |
+
$availablePages = array(
|
45 |
+
"wpstg-settings", "wpstg-addons", "wpstg-tools", "wpstg-clone", "wpstg_clone"
|
46 |
+
);
|
47 |
+
|
48 |
+
//if( !is_admin() || !did_action( "wp_loaded" ) || !in_array( $currentPage, $availablePages, true ) ) {
|
49 |
+
if( !is_admin() || !in_array( $currentPage, $availablePages, true ) ) {
|
50 |
+
return false;
|
51 |
+
}
|
52 |
+
|
53 |
+
return true;
|
54 |
+
}
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Check if notice should be shown after certain days of installation
|
58 |
+
* @param int $days default 10
|
59 |
+
* @return bool
|
60 |
+
*/
|
61 |
+
private function canShow( $option, $days = 10 ) {
|
62 |
+
|
63 |
+
if( empty( $option ) ) {
|
64 |
+
return false;
|
65 |
+
}
|
66 |
+
|
67 |
+
$installDate = new \DateTime( get_option( "wpstg_installDate" ) );
|
68 |
+
$now = new \DateTime( "now" );
|
69 |
+
|
70 |
+
// Get days difference
|
71 |
+
$difference = $now->diff( $installDate )->days;
|
72 |
+
|
73 |
+
return ($days <= $difference && "no" !== get_option( $option ));
|
74 |
+
|
75 |
+
return false;
|
76 |
+
}
|
77 |
+
|
78 |
+
public function messages() {
|
79 |
+
|
80 |
+
$this->plugin_deactivated_notice();
|
81 |
+
|
82 |
+
// Do not display notices to user_roles lower than 'update_plugins'
|
83 |
+
if( !current_user_can( 'update_plugins' ) ) {
|
84 |
+
return;
|
85 |
+
}
|
86 |
+
|
87 |
+
$viewsNoticesPath = "{$this->path}views/_includes/messages/";
|
88 |
+
|
89 |
+
// Show rating review message on all admin pages
|
90 |
+
if( $this->canShow( "wpstg_rating", 7 ) ) {
|
91 |
+
require_once "{$viewsNoticesPath}rating.php";
|
92 |
+
}
|
93 |
+
|
94 |
+
|
95 |
+
// Display messages below on wp quads admin page only
|
96 |
+
if( !$this->isAdminPage() ) {
|
97 |
+
return;
|
98 |
+
}
|
99 |
+
|
100 |
+
|
101 |
+
$varsDirectory = \WPStaging\WPStaging::getContentDir();
|
102 |
+
|
103 |
+
|
104 |
+
// Poll do not show any longer
|
105 |
+
/* if( $this->canShow( "wpstg_poll", 7 ) ) {
|
106 |
+
require_once "{$viewsNoticesPath}poll.php";
|
107 |
+
} */
|
108 |
+
|
109 |
+
// Cache directory in uploads is not writable
|
110 |
+
if( !wp_is_writable( $varsDirectory ) ) {
|
111 |
+
require_once "{$viewsNoticesPath}/uploads-cache-directory-permission-problem.php";
|
112 |
+
}
|
113 |
+
// Staging directory is not writable
|
114 |
+
if( !wp_is_writable( get_home_path() ) ) {
|
115 |
+
require_once "{$viewsNoticesPath}/staging-directory-permission-problem.php";
|
116 |
+
}
|
117 |
+
|
118 |
+
// Version Control
|
119 |
+
if( version_compare( WPStaging::WP_COMPATIBLE, get_bloginfo( "version" ), "<" ) ) {
|
120 |
+
require_once "{$viewsNoticesPath}wp-version-compatible-message.php";
|
121 |
+
}
|
122 |
+
|
123 |
+
// Beta
|
124 |
+
if( false === get_option( "wpstg_beta" ) || "no" !== get_option( "wpstg_beta" ) ) {
|
125 |
+
require_once "{$viewsNoticesPath}beta.php";
|
126 |
+
}
|
127 |
+
|
128 |
+
// WP Staging Pro and Free can not be activated both
|
129 |
+
if( false !== ( $deactivatedNoticeID = get_transient( "wp_staging_deactivated_notice_id" ) ) ) {
|
130 |
+
require_once "{$viewsNoticesPath}transient.php";
|
131 |
+
delete_transient( "wp_staging_deactivated_notice_id" );
|
132 |
+
}
|
133 |
+
}
|
134 |
+
|
135 |
+
/**
|
136 |
+
* Show a message when pro or free plugin becomes deactivated
|
137 |
+
*
|
138 |
+
* @return void
|
139 |
+
*/
|
140 |
+
private function plugin_deactivated_notice() {
|
141 |
+
if( false !== ( $deactivated_notice_id = get_transient( 'wp_staging_deactivated_notice_id' ) ) ) {
|
142 |
+
if( '1' === $deactivated_notice_id ) {
|
143 |
+
$message = __( "WP Staging and WP Staging Pro cannot both be active. We've automatically deactivated WP Staging.", 'wpstg' );
|
144 |
+
} else {
|
145 |
+
$message = __( "WP Staging and WP Staging Pro cannot both be active. We've automatically deactivated WP Staging Pro.", 'wpstg' );
|
146 |
+
}
|
147 |
+
?>
|
148 |
+
<div class="updated notice is-dismissible" style="border-left: 4px solid #ffba00;">
|
149 |
+
<p><?php echo esc_html( $message ); ?></p>
|
150 |
+
</div> <?php
|
151 |
+
delete_transient( 'wp_staging_deactivated_notice_id' );
|
152 |
+
}
|
153 |
+
}
|
154 |
+
|
155 |
+
}
|
apps/Backend/Upgrade/Upgrade.php
CHANGED
@@ -1,214 +1,229 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPStaging\Backend\Upgrade;
|
4 |
-
|
5 |
-
use WPStaging\WPStaging;
|
6 |
-
use WPStaging\Utils\Logger;
|
7 |
-
|
8 |
-
/**
|
9 |
-
* Upgrade Class
|
10 |
-
* This must be loaded on every page init to ensure all settings are
|
11 |
-
* adjusted correctly and to run any upgrade process if necessary.
|
12 |
-
*/
|
13 |
-
|
14 |
-
// No Direct Access
|
15 |
-
if( !defined( "WPINC" ) ) {
|
16 |
-
die;
|
17 |
-
}
|
18 |
-
|
19 |
-
class Upgrade {
|
20 |
-
|
21 |
-
/**
|
22 |
-
* Previous Version number
|
23 |
-
* @var string
|
24 |
-
*/
|
25 |
-
private $previousVersion;
|
26 |
-
|
27 |
-
/**
|
28 |
-
* Clone data
|
29 |
-
* @var obj
|
30 |
-
*/
|
31 |
-
private $clones;
|
32 |
-
|
33 |
-
/**
|
34 |
-
* Clone data
|
35 |
-
* @var obj
|
36 |
-
*/
|
37 |
-
private $clonesBeta;
|
38 |
-
|
39 |
-
/**
|
40 |
-
* Cron data
|
41 |
-
* @var obj
|
42 |
-
*/
|
43 |
-
private $cron;
|
44 |
-
|
45 |
-
/**
|
46 |
-
* Logger
|
47 |
-
* @var obj
|
48 |
-
*/
|
49 |
-
private $logger;
|
50 |
-
|
51 |
-
public function __construct() {
|
52 |
-
|
53 |
-
// add wpstg_weekly_event to cron events
|
54 |
-
$this->cron = new \WPStaging\Cron\Cron;
|
55 |
-
|
56 |
-
// Previous version
|
57 |
-
$this->previousVersion = preg_replace( '/[^0-9.].*/', '', get_option( 'wpstg_version' ) );
|
58 |
-
|
59 |
-
// Options earlier than version 2.0.0
|
60 |
-
$this->clones = get_option( "wpstg_existing_clones", array() );
|
61 |
-
|
62 |
-
// Current options
|
63 |
-
$this->clonesBeta = get_option( "wpstg_existing_clones_beta", array() );
|
64 |
-
|
65 |
-
// Logger
|
66 |
-
$this->logger = new Logger;
|
67 |
-
}
|
68 |
-
|
69 |
-
public function doUpgrade() {
|
70 |
-
$this->upgrade2_0_3();
|
71 |
-
//$this->upgrade2_0_4();
|
72 |
-
$this->
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
$this->
|
83 |
-
$this->
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
//
|
92 |
-
//
|
93 |
-
//
|
94 |
-
//
|
95 |
-
//
|
96 |
-
//
|
97 |
-
//
|
98 |
-
// $optimizer
|
99 |
-
//
|
100 |
-
//
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
}
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPStaging\Backend\Upgrade;
|
4 |
+
|
5 |
+
use WPStaging\WPStaging;
|
6 |
+
use WPStaging\Utils\Logger;
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Upgrade Class
|
10 |
+
* This must be loaded on every page init to ensure all settings are
|
11 |
+
* adjusted correctly and to run any upgrade process if necessary.
|
12 |
+
*/
|
13 |
+
|
14 |
+
// No Direct Access
|
15 |
+
if( !defined( "WPINC" ) ) {
|
16 |
+
die;
|
17 |
+
}
|
18 |
+
|
19 |
+
class Upgrade {
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Previous Version number
|
23 |
+
* @var string
|
24 |
+
*/
|
25 |
+
private $previousVersion;
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Clone data
|
29 |
+
* @var obj
|
30 |
+
*/
|
31 |
+
private $clones;
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Clone data
|
35 |
+
* @var obj
|
36 |
+
*/
|
37 |
+
private $clonesBeta;
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Cron data
|
41 |
+
* @var obj
|
42 |
+
*/
|
43 |
+
private $cron;
|
44 |
+
|
45 |
+
/**
|
46 |
+
* Logger
|
47 |
+
* @var obj
|
48 |
+
*/
|
49 |
+
private $logger;
|
50 |
+
|
51 |
+
public function __construct() {
|
52 |
+
|
53 |
+
// add wpstg_weekly_event to cron events
|
54 |
+
$this->cron = new \WPStaging\Cron\Cron;
|
55 |
+
|
56 |
+
// Previous version
|
57 |
+
$this->previousVersion = preg_replace( '/[^0-9.].*/', '', get_option( 'wpstg_version' ) );
|
58 |
+
|
59 |
+
// Options earlier than version 2.0.0
|
60 |
+
$this->clones = get_option( "wpstg_existing_clones", array() );
|
61 |
+
|
62 |
+
// Current options
|
63 |
+
$this->clonesBeta = get_option( "wpstg_existing_clones_beta", array() );
|
64 |
+
|
65 |
+
// Logger
|
66 |
+
$this->logger = new Logger;
|
67 |
+
}
|
68 |
+
|
69 |
+
public function doUpgrade() {
|
70 |
+
$this->upgrade2_0_3();
|
71 |
+
//$this->upgrade2_0_4();
|
72 |
+
$this->upgrade2_1_2();
|
73 |
+
$this->setVersion();
|
74 |
+
}
|
75 |
+
|
76 |
+
/**
|
77 |
+
* Upgrade method 2.0.3
|
78 |
+
*/
|
79 |
+
public function upgrade2_0_3() {
|
80 |
+
// Previous version lower than 2.0.2 or new install
|
81 |
+
if( false === $this->previousVersion || version_compare( $this->previousVersion, '2.0.2', '<' ) ) {
|
82 |
+
$this->upgradeOptions();
|
83 |
+
$this->upgradeClonesBeta();
|
84 |
+
$this->upgradeNotices();
|
85 |
+
}
|
86 |
+
}
|
87 |
+
|
88 |
+
/**
|
89 |
+
* Upgrade method 2.0.4
|
90 |
+
*/
|
91 |
+
// public function upgrade2_0_4() {
|
92 |
+
// if( false === $this->previousVersion || version_compare( $this->previousVersion, '2.0.4', '<' ) ) {
|
93 |
+
//
|
94 |
+
// // Register cron job.
|
95 |
+
// $this->cron->schedule_event();
|
96 |
+
//
|
97 |
+
// // Install Optimizer
|
98 |
+
// $optimizer = new Optimizer();
|
99 |
+
// $optimizer->installOptimizer();
|
100 |
+
// }
|
101 |
+
// }
|
102 |
+
|
103 |
+
/**
|
104 |
+
* Upgrade method 2.1.2
|
105 |
+
* Sanitize the clone key value.
|
106 |
+
*/
|
107 |
+
private function upgrade2_1_2(){
|
108 |
+
if( false === $this->previousVersion || version_compare( $this->previousVersion, '2.1.7', '<' ) ) {
|
109 |
+
foreach ( $this->clonesBeta as $key => $value){
|
110 |
+
unset($this->clonesBeta[$key]);
|
111 |
+
$this->clonesBeta[preg_replace("#\W+#", '-', strtolower($key))] = $value;
|
112 |
+
}
|
113 |
+
update_option('wpstg_existing_clones_beta', $this->clonesBeta);
|
114 |
+
}
|
115 |
+
}
|
116 |
+
|
117 |
+
/**
|
118 |
+
* Upgrade routine for new install
|
119 |
+
*/
|
120 |
+
private function upgradeOptions() {
|
121 |
+
// Write some default vars
|
122 |
+
add_option( 'wpstg_installDate', date( 'Y-m-d h:i:s' ) );
|
123 |
+
}
|
124 |
+
|
125 |
+
/**
|
126 |
+
* Write new version number into db
|
127 |
+
* return bool
|
128 |
+
*/
|
129 |
+
private function setVersion() {
|
130 |
+
// Check if version number in DB is lower than version number in current plugin
|
131 |
+
if( version_compare( $this->previousVersion, \WPStaging\WPStaging::VERSION, '<' ) ) {
|
132 |
+
// Update Version number
|
133 |
+
update_option( 'wpstg_version', preg_replace( '/[^0-9.].*/', '', \WPStaging\WPStaging::VERSION ) );
|
134 |
+
// Update "upgraded from" version number
|
135 |
+
update_option( 'wpstg_version_upgraded_from', preg_replace( '/[^0-9.].*/', '', $this->previousVersion ) );
|
136 |
+
|
137 |
+
return true;
|
138 |
+
}
|
139 |
+
return false;
|
140 |
+
}
|
141 |
+
|
142 |
+
/**
|
143 |
+
* Create a new db option for beta version 2.0.2
|
144 |
+
* @return bool
|
145 |
+
*/
|
146 |
+
private function upgradeClonesBeta() {
|
147 |
+
|
148 |
+
// Copy old data to new option
|
149 |
+
//update_option( 'wpstg_existing_clones_beta', $this->clones );
|
150 |
+
|
151 |
+
$new = array();
|
152 |
+
|
153 |
+
if( empty( $this->clones ) ) {
|
154 |
+
return false;
|
155 |
+
}
|
156 |
+
|
157 |
+
|
158 |
+
foreach ( $this->clones as $key => &$value ) {
|
159 |
+
|
160 |
+
// Skip the rest of the loop if data is already compatible to wpstg 2.0.2
|
161 |
+
if( isset( $value['directoryName'] ) || !empty( $value['directoryName'] ) ) {
|
162 |
+
continue;
|
163 |
+
}
|
164 |
+
|
165 |
+
$new[$value]['directoryName'] = $value;
|
166 |
+
$new[$value]['path'] = get_home_path() . $value;
|
167 |
+
$new[$value]['url'] = get_home_url() . "/" . $value;
|
168 |
+
$new[$value]['number'] = $key + 1;
|
169 |
+
$new[$value]['version'] = $this->previousVersion;
|
170 |
+
}
|
171 |
+
unset( $value );
|
172 |
+
|
173 |
+
if( empty( $new ) || false === update_option( 'wpstg_existing_clones_beta', $new ) ) {
|
174 |
+
$this->logger->log( 'Failed to upgrade clone data from ' . $this->previousVersion . ' to ' . \WPStaging\WPStaging::VERSION );
|
175 |
+
}
|
176 |
+
}
|
177 |
+
|
178 |
+
/**
|
179 |
+
* Convert clone data from wpstg 1.x to wpstg 2.x
|
180 |
+
* Only use this later when wpstg 2.x is ready for production
|
181 |
+
*/
|
182 |
+
private function upgradeClones() {
|
183 |
+
|
184 |
+
$new = array();
|
185 |
+
|
186 |
+
if( empty( $this->clones ) ) {
|
187 |
+
return false;
|
188 |
+
}
|
189 |
+
|
190 |
+
foreach ( $this->clones as $key => &$value ) {
|
191 |
+
|
192 |
+
// Skip the rest of the loop if data is already compatible to wpstg 2.0.1
|
193 |
+
if( isset( $value['directoryName'] ) || !empty( $value['directoryName'] ) ) {
|
194 |
+
continue;
|
195 |
+
}
|
196 |
+
$new[$value]['directoryName'] = $value;
|
197 |
+
$new[$value]['path'] = get_home_path() . $value;
|
198 |
+
$new[$value]['url'] = get_home_url() . "/" . $value;
|
199 |
+
$new[$value]['number'] = $key + 1;
|
200 |
+
$new[$value]['version'] = $this->previousVersion;
|
201 |
+
}
|
202 |
+
unset( $value );
|
203 |
+
|
204 |
+
if( empty( $new ) || false === update_option( 'wpstg_existing_clones', $new ) ) {
|
205 |
+
$this->logger->log( 'Failed to upgrade clone data from ' . $this->previousVersion . ' to ' . \WPStaging\WPStaging::VERSION );
|
206 |
+
}
|
207 |
+
}
|
208 |
+
|
209 |
+
/**
|
210 |
+
* Upgrade Notices db options from wpstg 1.3 -> 2.0.1
|
211 |
+
* Fix some logical db options
|
212 |
+
*/
|
213 |
+
private function upgradeNotices() {
|
214 |
+
$poll = get_option( "wpstg_start_poll", false );
|
215 |
+
$beta = get_option( "wpstg_hide_beta", false );
|
216 |
+
$rating = get_option( "wpstg_RatingDiv", false );
|
217 |
+
|
218 |
+
if( $poll && $poll === "no" ) {
|
219 |
+
update_option( 'wpstg_poll', 'no' );
|
220 |
+
}
|
221 |
+
if( $beta && $beta === "yes" ) {
|
222 |
+
update_option( 'wpstg_beta', 'no' );
|
223 |
+
}
|
224 |
+
if( $rating && $rating === 'yes' ) {
|
225 |
+
update_option( 'wpstg_rating', 'no' );
|
226 |
+
}
|
227 |
+
}
|
228 |
+
|
229 |
+
}
|
apps/Backend/public/js/wpstg-admin-rating.js
CHANGED
@@ -1,24 +1,32 @@
|
|
1 |
-
jQuery(document).ready(function ($) {
|
2 |
-
$(".wpstg_hide_rating").click(function (e) {
|
3 |
-
e.preventDefault();
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
alert(
|
15 |
-
"
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
24 |
});
|
1 |
+
jQuery(document).ready(function ($) {
|
2 |
+
$(".wpstg_hide_rating").click(function (e) {
|
3 |
+
e.preventDefault();
|
4 |
+
|
5 |
+
$.ajax({
|
6 |
+
url: ajaxurl,
|
7 |
+
type: "POST",
|
8 |
+
data: {action: "wpstg_hide_rating"},
|
9 |
+
error: function (xhr, textStatus, errorThrown) {
|
10 |
+
console.log(xhr.status + ' ' + xhr.statusText + '---' + textStatus);
|
11 |
+
console.log(textStatus);
|
12 |
+
|
13 |
+
|
14 |
+
alert(
|
15 |
+
"Unknown error"
|
16 |
+
);
|
17 |
+
},
|
18 |
+
success: function (data) {
|
19 |
+
$(".wpstg_fivestar").slideUp("fast");
|
20 |
+
return true;
|
21 |
+
},
|
22 |
+
statusCode: {
|
23 |
+
404: function () {
|
24 |
+
alert("Something went wrong; can't find ajax request URL!");
|
25 |
+
},
|
26 |
+
500: function () {
|
27 |
+
alert("Something went wrong; internal server error while processing the request!");
|
28 |
+
}
|
29 |
+
}
|
30 |
+
});
|
31 |
+
});
|
32 |
});
|
apps/Backend/public/js/wpstg-admin.js
CHANGED
@@ -321,10 +321,9 @@ var WPStaging = (function ($)
|
|
321 |
}
|
322 |
|
323 |
showError(
|
324 |
-
"Fatal Unknown Error.
|
325 |
-
"
|
326 |
-
"<a href='https://
|
327 |
-
"in the WP Staging support forum."
|
328 |
);
|
329 |
},
|
330 |
success: function (data) {
|
321 |
}
|
322 |
|
323 |
showError(
|
324 |
+
"Fatal Unknown Error. Go to WP Staging > Settings and lower 'File Copy Limit'" +
|
325 |
+
"Than try again. If this does not help, " +
|
326 |
+
"<a href='https://wp-staging.com/support/' target='_blank'>open a support ticket</a> "
|
|
|
327 |
);
|
328 |
},
|
329 |
success: function (data) {
|
apps/Backend/views/_includes/messages/rating.php
CHANGED
@@ -1,31 +1,31 @@
|
|
1 |
-
<div class="wpstg_fivestar updated" style="box-shadow: 0 1px 1px 0 rgba(0,0,0,.1);">
|
2 |
-
<p>
|
3 |
-
Awesome, you've been using <strong>WP Staging </strong> for more than 1 week.
|
4 |
-
May I ask you to give it a <strong>5-star</strong> rating on Wordpress?
|
5 |
-
<br><br>
|
6 |
-
P.S. Looking for a way to copy plugins and theme files from staging to live site? Try out <a href="https://wp-staging.com" target="_blank">WP Staging Pro</a> <br>
|
7 |
-
</p>
|
8 |
-
|
9 |
-
<p>
|
10 |
-
<strong>Regards,<br>René Hermenau</strong>
|
11 |
-
</p>
|
12 |
-
|
13 |
-
<ul>
|
14 |
-
<li>
|
15 |
-
<a href="https://wordpress.org/support/plugin/wp-staging/reviews/?filter=5#new-post" class="thankyou" target="_new" title="Ok, you deserved it" style="font-weight:bold;">
|
16 |
-
Ok, you deserved it
|
17 |
-
</a>
|
18 |
-
</li>
|
19 |
-
<li>
|
20 |
-
<a href="javascript:void(0);" class="wpstg_hide_rating" title="I already did" style="font-weight:bold;">
|
21 |
-
I already did
|
22 |
-
</a>
|
23 |
-
</li>
|
24 |
-
<li>
|
25 |
-
<a href="javascript:void(0);" class="wpstg_hide_rating" title="No, not good enough" style="font-weight:bold;">
|
26 |
-
No, not good enough
|
27 |
-
</a>
|
28 |
-
</li>
|
29 |
-
</ul>
|
30 |
-
</div>
|
31 |
<script type="text/javascript" src="<?php echo $this->url . "js/wpstg-admin-rating.js"?>"></script>
|
1 |
+
<div class="wpstg_fivestar updated" style="box-shadow: 0 1px 1px 0 rgba(0,0,0,.1);">
|
2 |
+
<p>
|
3 |
+
Awesome, you've been using <strong>WP Staging </strong> for more than 1 week.
|
4 |
+
May I ask you to give it a <strong>5-star</strong> rating on Wordpress?
|
5 |
+
<br><br>
|
6 |
+
P.S. Looking for a way to copy plugins and theme files from staging to live site? Try out <a href="https://wp-staging.com" target="_blank">WP Staging Pro</a> <br>
|
7 |
+
</p>
|
8 |
+
|
9 |
+
<p>
|
10 |
+
<strong>Regards,<br>René Hermenau</strong>
|
11 |
+
</p>
|
12 |
+
|
13 |
+
<ul>
|
14 |
+
<li>
|
15 |
+
<a href="https://wordpress.org/support/plugin/wp-staging/reviews/?filter=5#new-post" class="thankyou" target="_new" title="Ok, you deserved it" style="font-weight:bold;">
|
16 |
+
Ok, you deserved it
|
17 |
+
</a>
|
18 |
+
</li>
|
19 |
+
<li>
|
20 |
+
<a href="javascript:void(0);" class="wpstg_hide_rating" title="I already did" style="font-weight:bold;">
|
21 |
+
I already did
|
22 |
+
</a>
|
23 |
+
</li>
|
24 |
+
<li>
|
25 |
+
<a href="javascript:void(0);" class="wpstg_hide_rating" title="No, not good enough" style="font-weight:bold;">
|
26 |
+
No, not good enough
|
27 |
+
</a>
|
28 |
+
</li>
|
29 |
+
</ul>
|
30 |
+
</div>
|
31 |
<script type="text/javascript" src="<?php echo $this->url . "js/wpstg-admin-rating.js"?>"></script>
|
apps/Backend/views/clone/ajax/start.php
CHANGED
@@ -1,115 +1,113 @@
|
|
1 |
-
<div class=successfullying-section">
|
2 |
-
<?php echo __("Copy Database Tables", "wpstg")?>
|
3 |
-
<div class="wpstg-progress-bar">
|
4 |
-
<div class="wpstg-progress" id="wpstg-db-progress" style="width:0"></div>
|
5 |
-
</div>
|
6 |
-
</div>
|
7 |
-
|
8 |
-
<div class="wpstg-cloning-section">
|
9 |
-
<?php echo __("Prepare Directories", "wpstg")?>
|
10 |
-
<div class="wpstg-progress-bar">
|
11 |
-
<div class="wpstg-progress" id="wpstg-directories-progress" style="width:0"></div>
|
12 |
-
</div>
|
13 |
-
</div>
|
14 |
-
|
15 |
-
<div class="wpstg-cloning-section">
|
16 |
-
<?php echo __("Copy Files", "wpstg")?>
|
17 |
-
<div class="wpstg-progress-bar">
|
18 |
-
<div class="wpstg-progress" id="wpstg-files-progress" style="width:0"></div>
|
19 |
-
</div>
|
20 |
-
</div>
|
21 |
-
|
22 |
-
<div class="wpstg-cloning-section">
|
23 |
-
<?php echo __("Replace Data", "wpstg")?>
|
24 |
-
<div class="wpstg-progress-bar">
|
25 |
-
<div class="wpstg-progress" id="wpstg-links-progress" style="width:0"></div>
|
26 |
-
</div>
|
27 |
-
</div>
|
28 |
-
|
29 |
-
<button type="button" id="wpstg-cancel-cloning" class="wpstg-link-btn button-primary">
|
30 |
-
<?php echo __("Cancel", "wpstg")?>
|
31 |
-
</button>
|
32 |
-
|
33 |
-
<button type="button" id="wpstg-show-log-button" class="button" data-clone="<?php echo $cloning->getOptions()->clone?>" style="margin-top: 5px;display:none;">
|
34 |
-
<?php _e('Display working log', 'wpstg')?>
|
35 |
-
</button>
|
36 |
-
|
37 |
-
<div>
|
38 |
-
<span id="wpstg-cloning-result"></span>
|
39 |
-
</div>
|
40 |
-
|
41 |
-
<div id="wpstg-finished-result">
|
42 |
-
<h3>Congratulations
|
43 |
-
</h3>
|
44 |
-
<?php
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
<br>
|
52 |
-
<?php
|
53 |
-
|
54 |
-
$url =
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
<br>
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
<br>
|
93 |
-
|
94 |
-
<
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
<br>
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
</div>
|
114 |
-
|
115 |
<div id="wpstg-log-details"></div>
|
1 |
+
<div class=successfullying-section">
|
2 |
+
<?php echo __("Copy Database Tables", "wpstg")?>
|
3 |
+
<div class="wpstg-progress-bar">
|
4 |
+
<div class="wpstg-progress" id="wpstg-db-progress" style="width:0"></div>
|
5 |
+
</div>
|
6 |
+
</div>
|
7 |
+
|
8 |
+
<div class="wpstg-cloning-section">
|
9 |
+
<?php echo __("Prepare Directories", "wpstg")?>
|
10 |
+
<div class="wpstg-progress-bar">
|
11 |
+
<div class="wpstg-progress" id="wpstg-directories-progress" style="width:0"></div>
|
12 |
+
</div>
|
13 |
+
</div>
|
14 |
+
|
15 |
+
<div class="wpstg-cloning-section">
|
16 |
+
<?php echo __("Copy Files", "wpstg")?>
|
17 |
+
<div class="wpstg-progress-bar">
|
18 |
+
<div class="wpstg-progress" id="wpstg-files-progress" style="width:0"></div>
|
19 |
+
</div>
|
20 |
+
</div>
|
21 |
+
|
22 |
+
<div class="wpstg-cloning-section">
|
23 |
+
<?php echo __("Replace Data", "wpstg")?>
|
24 |
+
<div class="wpstg-progress-bar">
|
25 |
+
<div class="wpstg-progress" id="wpstg-links-progress" style="width:0"></div>
|
26 |
+
</div>
|
27 |
+
</div>
|
28 |
+
|
29 |
+
<button type="button" id="wpstg-cancel-cloning" class="wpstg-link-btn button-primary">
|
30 |
+
<?php echo __("Cancel", "wpstg")?>
|
31 |
+
</button>
|
32 |
+
|
33 |
+
<button type="button" id="wpstg-show-log-button" class="button" data-clone="<?php echo $cloning->getOptions()->clone?>" style="margin-top: 5px;display:none;">
|
34 |
+
<?php _e('Display working log', 'wpstg')?>
|
35 |
+
</button>
|
36 |
+
|
37 |
+
<div>
|
38 |
+
<span id="wpstg-cloning-result"></span>
|
39 |
+
</div>
|
40 |
+
|
41 |
+
<div id="wpstg-finished-result">
|
42 |
+
<h3>Congratulations
|
43 |
+
</h3>
|
44 |
+
<?php
|
45 |
+
//echo ABSPATH . '<br>';
|
46 |
+
//echo get_home_path();
|
47 |
+
$subDirectory = str_replace( get_home_path(), '', ABSPATH );
|
48 |
+
$url = get_home_url() . str_replace('/', '', $subDirectory);
|
49 |
+
echo sprintf( __( 'WP Staging successfully created a staging site in a sub-directory of your main site in:<br><strong><a href="%1$s" target="_blank" id="wpstg-clone-url-1">%1$s</a></strong>', 'wpstg' ), $url );
|
50 |
+
?>
|
51 |
+
<br>
|
52 |
+
<?php //echo __('Open and access the staging site: ', 'wpstg')?>
|
53 |
+
<br>
|
54 |
+
<a href="<?php echo $url; ?>" id="wpstg-clone-url" target="_blank" class="wpstg-link-btn button-primary">
|
55 |
+
Open staging site <span style="font-size: 10px;">(login with your admin credentials)</span>
|
56 |
+
</a>
|
57 |
+
<!--<a href="" class="wpstg-link-btn button-primary" id="wpstg-remove-cloning">
|
58 |
+
<?php //echo __("Remove", "wpstg")?>
|
59 |
+
</a>//-->
|
60 |
+
<a href="" class="wpstg-link-btn button-primary" id="wpstg-home-link">
|
61 |
+
<?php echo __("Start again", "wpstg")?>
|
62 |
+
</a>
|
63 |
+
<div id="wpstg-success-notice">
|
64 |
+
<h3 style="margin-top:0px;">
|
65 |
+
<?php _e("Important Notes:", "wpstg")?>
|
66 |
+
</h3>
|
67 |
+
<ul>
|
68 |
+
<li>
|
69 |
+
<strong>1. Permalinks on your <span style="font-style:italic;">staging site</span> will be disabled for technical reasons! </strong>
|
70 |
+
<br>
|
71 |
+
Usually this is no problem for a staging website and you do not need to use permalinks!
|
72 |
+
<br>
|
73 |
+
<p>
|
74 |
+
If you really want permalinks on your staging site you need to do several modifications to your .htaccess (Apache) or *.conf (Nginx).
|
75 |
+
<br>
|
76 |
+
WP Staging can not do this modification automatically.
|
77 |
+
</p>
|
78 |
+
<p>
|
79 |
+
<strong>Read more:</strong>
|
80 |
+
<a href="http://stackoverflow.com/questions/5564881/htaccess-to-rewrite-wordpress-subdirectory-with-permalinks-to-root" target="_blank">
|
81 |
+
Changes .htaccess
|
82 |
+
</a> |
|
83 |
+
<a href="http://robido.com/nginx/nginx-wordpress-subdirectory-configuration-example/" target="_blank">
|
84 |
+
Changes nginx conf
|
85 |
+
</a>
|
86 |
+
</p>
|
87 |
+
</li>
|
88 |
+
<li>
|
89 |
+
<strong>2. Verify that you are REALLY working on your staging site and NOT on your production site if you are uncertain! </strong>
|
90 |
+
<br>
|
91 |
+
Your main and your staging site are both reachable under the same domain so
|
92 |
+
<br>
|
93 |
+
it´s easy to get confused.
|
94 |
+
<p>
|
95 |
+
To assist you we changed the name of the dashboard link to
|
96 |
+
<strong style="font-style:italic;">
|
97 |
+
"STAGING - <span class="wpstg-clone-name"><?php echo get_bloginfo("name")?></span>"
|
98 |
+
</strong>.
|
99 |
+
<br>
|
100 |
+
You will notice this new name in the admin bar:
|
101 |
+
<br><br>
|
102 |
+
<img src="<?php echo $this->url . "/img/admin_dashboard.png" ?>">
|
103 |
+
</p>
|
104 |
+
</li>
|
105 |
+
</ul>
|
106 |
+
</div>
|
107 |
+
</div>
|
108 |
+
|
109 |
+
<div id="wpstg-error-wrapper">
|
110 |
+
<div id="wpstg-error-details"></div>
|
111 |
+
</div>
|
112 |
+
|
|
|
|
|
113 |
<div id="wpstg-log-details"></div>
|
apps/Backend/views/settings/index.php
CHANGED
@@ -96,10 +96,10 @@
|
|
96 |
<span class="description">
|
97 |
Number of DB rows, that will be copied within one ajax request.
|
98 |
The higher the value the faster the database copy process.
|
99 |
-
To find out the highest possible values try a high value like 1.000 or more
|
100 |
-
until you get no more errors during
|
101 |
<br>
|
102 |
-
<strong> Default:
|
103 |
</span>
|
104 |
</div>
|
105 |
</td>
|
@@ -108,6 +108,27 @@
|
|
108 |
</td>
|
109 |
</tr>
|
110 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
111 |
<tr class="row">
|
112 |
<td class="row th">
|
113 |
<div class="col-title">
|
96 |
<span class="description">
|
97 |
Number of DB rows, that will be copied within one ajax request.
|
98 |
The higher the value the faster the database copy process.
|
99 |
+
To find out the highest possible values try a high value like 1.000 or more. If you get timeout issues, lower it
|
100 |
+
until you get no more errors during copying process.
|
101 |
<br>
|
102 |
+
<strong> Default: 1000 </strong>
|
103 |
</span>
|
104 |
</div>
|
105 |
</td>
|
108 |
</td>
|
109 |
</tr>
|
110 |
|
111 |
+
<tr class="row">
|
112 |
+
<td class="row th">
|
113 |
+
<div class="col-title">
|
114 |
+
<?php
|
115 |
+
echo $form->label("wpstg_settings[fileLimit]")
|
116 |
+
?>
|
117 |
+
<span class="description">
|
118 |
+
Number of files to copy that will be copied within one ajax request.
|
119 |
+
The higher the value the faster the file copy process.
|
120 |
+
To find out the highest possible values try a high value like 500 or more. If you get timeout issues, lower it
|
121 |
+
until you get no more errors during copying process.
|
122 |
+
<br>
|
123 |
+
<strong> Default: 500 </strong>
|
124 |
+
</span>
|
125 |
+
</div>
|
126 |
+
</td>
|
127 |
+
<td>
|
128 |
+
<?php echo $form->render("wpstg_settings[fileLimit]")?>
|
129 |
+
</td>
|
130 |
+
</tr>
|
131 |
+
|
132 |
<tr class="row">
|
133 |
<td class="row th">
|
134 |
<div class="col-title">
|
apps/Core/DTO/Settings.php
CHANGED
@@ -1,12 +1,13 @@
|
|
1 |
<?php
|
|
|
2 |
namespace WPStaging\DTO;
|
3 |
|
4 |
/**
|
5 |
* Class Settings
|
6 |
* @package WPStaging\DTO
|
7 |
*/
|
8 |
-
class Settings
|
9 |
-
|
10 |
/**
|
11 |
* @var array
|
12 |
*/
|
@@ -20,6 +21,11 @@ class Settings
|
|
20 |
/**
|
21 |
* @var int
|
22 |
*/
|
|
|
|
|
|
|
|
|
|
|
23 |
protected $batchSize;
|
24 |
|
25 |
/**
|
@@ -68,7 +74,7 @@ class Settings
|
|
68 |
public function __construct() {
|
69 |
$this->_raw = get_option( "wpstg_settings", array() );
|
70 |
|
71 |
-
if(
|
72 |
$this->hydrate( $this->_raw );
|
73 |
}
|
74 |
}
|
@@ -77,14 +83,11 @@ class Settings
|
|
77 |
* @param array $settings
|
78 |
* @return $this
|
79 |
*/
|
80 |
-
|
81 |
-
{
|
82 |
$this->_raw = $settings;
|
83 |
|
84 |
-
|
85 |
-
|
86 |
-
if (property_exists($this, $key))
|
87 |
-
{
|
88 |
$this->{$key} = $value;
|
89 |
}
|
90 |
}
|
@@ -112,168 +115,161 @@ class Settings
|
|
112 |
/**
|
113 |
* @return array
|
114 |
*/
|
115 |
-
|
116 |
-
{
|
117 |
return $this->_raw;
|
118 |
}
|
119 |
|
120 |
/**
|
121 |
* @return int
|
122 |
*/
|
123 |
-
|
124 |
-
|
125 |
-
return (int) $this->queryLimit;
|
126 |
}
|
127 |
|
128 |
/**
|
129 |
* @param int $queryLimit
|
130 |
*/
|
131 |
-
|
132 |
-
{
|
133 |
$this->queryLimit = $queryLimit;
|
134 |
}
|
135 |
|
136 |
/**
|
137 |
* @return int
|
138 |
*/
|
139 |
-
|
140 |
-
|
141 |
-
return (int) $this->batchSize;
|
142 |
}
|
143 |
|
144 |
/**
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
145 |
* @param int $batchSize
|
146 |
*/
|
147 |
-
|
148 |
-
{
|
149 |
$this->batchSize = $batchSize;
|
150 |
}
|
151 |
|
152 |
/**
|
153 |
* @return string
|
154 |
*/
|
155 |
-
|
156 |
-
{
|
157 |
return $this->cpuLoad;
|
158 |
}
|
159 |
|
160 |
/**
|
161 |
* @param string $cpuLoad
|
162 |
*/
|
163 |
-
|
164 |
-
{
|
165 |
$this->cpuLoad = $cpuLoad;
|
166 |
}
|
167 |
|
168 |
/**
|
169 |
* @return bool
|
170 |
*/
|
171 |
-
|
172 |
-
{
|
173 |
return ('1' === $this->unInstallOnDelete);
|
174 |
}
|
175 |
|
176 |
/**
|
177 |
* @param bool $unInstallOnDelete
|
178 |
*/
|
179 |
-
|
180 |
-
{
|
181 |
$this->unInstallOnDelete = $unInstallOnDelete;
|
182 |
}
|
183 |
|
184 |
/**
|
185 |
* @return bool
|
186 |
*/
|
187 |
-
|
188 |
-
{
|
189 |
return ('1' === $this->optimizer);
|
190 |
}
|
191 |
|
192 |
/**
|
193 |
* @param bool $optimizer
|
194 |
*/
|
195 |
-
|
196 |
-
{
|
197 |
$this->optimizer = $optimizer;
|
198 |
}
|
199 |
|
200 |
/**
|
201 |
* @return bool
|
202 |
*/
|
203 |
-
|
204 |
-
{
|
205 |
return ('1' === $this->disableAdminLogin);
|
206 |
}
|
207 |
|
208 |
/**
|
209 |
* @param bool $disableAdminLogin
|
210 |
*/
|
211 |
-
|
212 |
-
{
|
213 |
$this->disableAdminLogin = $disableAdminLogin;
|
214 |
}
|
215 |
|
216 |
/**
|
217 |
* @return bool
|
218 |
*/
|
219 |
-
|
220 |
-
{
|
221 |
return ('1' === $this->wpSubDirectory);
|
222 |
}
|
223 |
|
224 |
/**
|
225 |
* @param bool $wpSubDirectory
|
226 |
*/
|
227 |
-
|
228 |
-
{
|
229 |
$this->wpSubDirectory = $wpSubDirectory;
|
230 |
}
|
231 |
|
232 |
/**
|
233 |
* @return bool
|
234 |
*/
|
235 |
-
|
236 |
-
{
|
237 |
return ('1' === $this->checkDirectorySize);
|
238 |
}
|
239 |
|
240 |
/**
|
241 |
* @param bool $checkDirectorySize
|
242 |
*/
|
243 |
-
|
244 |
-
{
|
245 |
$this->checkDirectorySize = $checkDirectorySize;
|
246 |
}
|
247 |
|
248 |
/**
|
249 |
* @return bool
|
250 |
*/
|
251 |
-
|
252 |
-
{
|
253 |
return ('1' === $this->debugMode);
|
254 |
}
|
255 |
|
256 |
/**
|
257 |
* @param bool $debugMode
|
258 |
*/
|
259 |
-
|
260 |
-
{
|
261 |
$this->debugMode = $debugMode;
|
262 |
}
|
263 |
|
264 |
/**
|
265 |
* @return array
|
266 |
*/
|
267 |
-
|
268 |
-
{
|
269 |
return $this->blackListedPlugins;
|
270 |
}
|
271 |
|
272 |
/**
|
273 |
* @param array $blackListedPlugins
|
274 |
*/
|
275 |
-
|
276 |
-
{
|
277 |
$this->blackListedPlugins = $blackListedPlugins;
|
278 |
}
|
279 |
}
|
1 |
<?php
|
2 |
+
|
3 |
namespace WPStaging\DTO;
|
4 |
|
5 |
/**
|
6 |
* Class Settings
|
7 |
* @package WPStaging\DTO
|
8 |
*/
|
9 |
+
class Settings {
|
10 |
+
|
11 |
/**
|
12 |
* @var array
|
13 |
*/
|
21 |
/**
|
22 |
* @var int
|
23 |
*/
|
24 |
+
protected $fileLimit;
|
25 |
+
|
26 |
+
/**
|
27 |
+
* @var int
|
28 |
+
*/
|
29 |
protected $batchSize;
|
30 |
|
31 |
/**
|
74 |
public function __construct() {
|
75 |
$this->_raw = get_option( "wpstg_settings", array() );
|
76 |
|
77 |
+
if (!empty($this->_raw)){
|
78 |
$this->hydrate( $this->_raw );
|
79 |
}
|
80 |
}
|
83 |
* @param array $settings
|
84 |
* @return $this
|
85 |
*/
|
86 |
+
public function hydrate( $settings = array() ) {
|
|
|
87 |
$this->_raw = $settings;
|
88 |
|
89 |
+
foreach ( $settings as $key => $value ) {
|
90 |
+
if( property_exists( $this, $key ) ) {
|
|
|
|
|
91 |
$this->{$key} = $value;
|
92 |
}
|
93 |
}
|
115 |
/**
|
116 |
* @return array
|
117 |
*/
|
118 |
+
public function getRaw() {
|
|
|
119 |
return $this->_raw;
|
120 |
}
|
121 |
|
122 |
/**
|
123 |
* @return int
|
124 |
*/
|
125 |
+
public function getQueryLimit() {
|
126 |
+
return ( int ) $this->queryLimit;
|
|
|
127 |
}
|
128 |
|
129 |
/**
|
130 |
* @param int $queryLimit
|
131 |
*/
|
132 |
+
public function setQueryLimit( $queryLimit ) {
|
|
|
133 |
$this->queryLimit = $queryLimit;
|
134 |
}
|
135 |
|
136 |
/**
|
137 |
* @return int
|
138 |
*/
|
139 |
+
public function getFileLimit() {
|
140 |
+
return ( int ) $this->fileLimit;
|
|
|
141 |
}
|
142 |
|
143 |
/**
|
144 |
+
* @param int $fileCopyLimit
|
145 |
+
*/
|
146 |
+
public function setFileLimit( $fileLimit ) {
|
147 |
+
$this->fileLimit = $fileLimit;
|
148 |
+
}
|
149 |
+
|
150 |
+
/**
|
151 |
+
* @return int
|
152 |
+
*/
|
153 |
+
public function getBatchSize() {
|
154 |
+
return ( int ) $this->batchSize;
|
155 |
+
}
|
156 |
+
|
157 |
+
/**
|
158 |
* @param int $batchSize
|
159 |
*/
|
160 |
+
public function setBatchSize( $batchSize ) {
|
|
|
161 |
$this->batchSize = $batchSize;
|
162 |
}
|
163 |
|
164 |
/**
|
165 |
* @return string
|
166 |
*/
|
167 |
+
public function getCpuLoad() {
|
|
|
168 |
return $this->cpuLoad;
|
169 |
}
|
170 |
|
171 |
/**
|
172 |
* @param string $cpuLoad
|
173 |
*/
|
174 |
+
public function setCpuLoad( $cpuLoad ) {
|
|
|
175 |
$this->cpuLoad = $cpuLoad;
|
176 |
}
|
177 |
|
178 |
/**
|
179 |
* @return bool
|
180 |
*/
|
181 |
+
public function isUnInstallOnDelete() {
|
|
|
182 |
return ('1' === $this->unInstallOnDelete);
|
183 |
}
|
184 |
|
185 |
/**
|
186 |
* @param bool $unInstallOnDelete
|
187 |
*/
|
188 |
+
public function setUnInstallOnDelete( $unInstallOnDelete ) {
|
|
|
189 |
$this->unInstallOnDelete = $unInstallOnDelete;
|
190 |
}
|
191 |
|
192 |
/**
|
193 |
* @return bool
|
194 |
*/
|
195 |
+
public function isOptimizer() {
|
|
|
196 |
return ('1' === $this->optimizer);
|
197 |
}
|
198 |
|
199 |
/**
|
200 |
* @param bool $optimizer
|
201 |
*/
|
202 |
+
public function setOptimizer( $optimizer ) {
|
|
|
203 |
$this->optimizer = $optimizer;
|
204 |
}
|
205 |
|
206 |
/**
|
207 |
* @return bool
|
208 |
*/
|
209 |
+
public function isDisableAdminLogin() {
|
|
|
210 |
return ('1' === $this->disableAdminLogin);
|
211 |
}
|
212 |
|
213 |
/**
|
214 |
* @param bool $disableAdminLogin
|
215 |
*/
|
216 |
+
public function setDisableAdminLogin( $disableAdminLogin ) {
|
|
|
217 |
$this->disableAdminLogin = $disableAdminLogin;
|
218 |
}
|
219 |
|
220 |
/**
|
221 |
* @return bool
|
222 |
*/
|
223 |
+
public function isWpSubDirectory() {
|
|
|
224 |
return ('1' === $this->wpSubDirectory);
|
225 |
}
|
226 |
|
227 |
/**
|
228 |
* @param bool $wpSubDirectory
|
229 |
*/
|
230 |
+
public function setWpSubDirectory( $wpSubDirectory ) {
|
|
|
231 |
$this->wpSubDirectory = $wpSubDirectory;
|
232 |
}
|
233 |
|
234 |
/**
|
235 |
* @return bool
|
236 |
*/
|
237 |
+
public function isCheckDirectorySize() {
|
|
|
238 |
return ('1' === $this->checkDirectorySize);
|
239 |
}
|
240 |
|
241 |
/**
|
242 |
* @param bool $checkDirectorySize
|
243 |
*/
|
244 |
+
public function setCheckDirectorySize( $checkDirectorySize ) {
|
|
|
245 |
$this->checkDirectorySize = $checkDirectorySize;
|
246 |
}
|
247 |
|
248 |
/**
|
249 |
* @return bool
|
250 |
*/
|
251 |
+
public function isDebugMode() {
|
|
|
252 |
return ('1' === $this->debugMode);
|
253 |
}
|
254 |
|
255 |
/**
|
256 |
* @param bool $debugMode
|
257 |
*/
|
258 |
+
public function setDebugMode( $debugMode ) {
|
|
|
259 |
$this->debugMode = $debugMode;
|
260 |
}
|
261 |
|
262 |
/**
|
263 |
* @return array
|
264 |
*/
|
265 |
+
public function getBlackListedPlugins() {
|
|
|
266 |
return $this->blackListedPlugins;
|
267 |
}
|
268 |
|
269 |
/**
|
270 |
* @param array $blackListedPlugins
|
271 |
*/
|
272 |
+
public function setBlackListedPlugins( $blackListedPlugins ) {
|
|
|
273 |
$this->blackListedPlugins = $blackListedPlugins;
|
274 |
}
|
275 |
}
|
apps/Core/Utils/Cache.php
CHANGED
@@ -111,6 +111,7 @@ class Cache
|
|
111 |
|
112 |
// Save it to file
|
113 |
return (file_put_contents($cacheFile, @serialize($value), LOCK_EX) !== false);
|
|
|
114 |
}
|
115 |
|
116 |
/**
|
111 |
|
112 |
// Save it to file
|
113 |
return (file_put_contents($cacheFile, @serialize($value), LOCK_EX) !== false);
|
114 |
+
//return (file_put_contents($cacheFile, @serialize($value)) !== false);
|
115 |
}
|
116 |
|
117 |
/**
|
apps/Core/WPStaging.php
CHANGED
@@ -29,7 +29,7 @@ final class WPStaging {
|
|
29 |
/**
|
30 |
* Plugin version
|
31 |
*/
|
32 |
-
const VERSION = "2.1.
|
33 |
|
34 |
/**
|
35 |
* Plugin name
|
29 |
/**
|
30 |
* Plugin version
|
31 |
*/
|
32 |
+
const VERSION = "2.1.2";
|
33 |
|
34 |
/**
|
35 |
* Plugin name
|
readme.txt
CHANGED
@@ -1,258 +1,270 @@
|
|
1 |
-
=== WP Staging - DB & File Duplicator & Migration ===
|
2 |
-
|
3 |
-
Author URL: https://wordpress.org/plugins/wp-staging
|
4 |
-
Plugin URL: https://wordpress.org/plugins/wp-staging
|
5 |
-
Contributors: ReneHermi, WP-Staging
|
6 |
-
Donate link: https://wordpress.org/plugins/wp-staging
|
7 |
-
License: GPLv2 or later
|
8 |
-
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
9 |
-
Tags: staging, duplication, cloning, clone, migration, sandbox, test site, testing, backup, post, admin, administration, duplicate posts
|
10 |
-
Requires at least: 3.6+
|
11 |
-
Tested up to: 4.8
|
12 |
-
Stable tag: 2.1.
|
13 |
-
|
14 |
-
A duplicator plugin! Clone, duplicate and migrate live sites to independent staging and development sites that are available only to administrators.
|
15 |
-
|
16 |
-
== Description ==
|
17 |
-
|
18 |
-
<strong>This cloning and staging plugin is well tested but work in progress. <br><br>
|
19 |
-
If you find any issue, please open a [support ticket](https://wp-staging.com/support/ "support ticket").
|
20 |
-
</strong>
|
21 |
-
<br /><br />
|
22 |
-
<strong>Note: </strong> For pushing plugins and theme files to live site, check out [https://wp-staging.com/](https://wp-staging.com/ "WP Staging Pro")
|
23 |
-
<br /><br />
|
24 |
-
<blockquote>
|
25 |
-
<h4> WP Staging for WordPress Migration </h4>
|
26 |
-
This duplicator plugin allows you to create an staging or development environment in seconds* <br /> <br />
|
27 |
-
It creates a clone of your website into a subfolder of your main WordPress installation including an entire copy of your database.
|
28 |
-
This sounds pretty simple and yes it is! All the hard time-consumptive database and file copying stuff including url replacements is done in the background.
|
29 |
-
<br /> <br />
|
30 |
-
I created this plugin because all other solutions are way too complex, overloaded with dozens of options or having server requirements which are not available on most shared hosting solutions.
|
31 |
-
All these reasons prevent user from testing new plugins and updates first before installing them on their live website, so its time to release a plugin which has the potential to be merged into everyone´s wordpress workflow.
|
32 |
-
<br /><br />
|
33 |
-
<p><small><em>* Time of creation depends on size of your database and file size</em></small></p>
|
34 |
-
</blockquote>
|
35 |
-
|
36 |
-
WP Staging helps you to prevent your website from being broken or unavailable because of installing untested plugin updates!
|
37 |
-
|
38 |
-
[youtube https://www.youtube.com/watch?v=Ye3fC6cdB3A]
|
39 |
-
|
40 |
-
= Main Features =
|
41 |
-
|
42 |
-
* <strong>Easy: </strong> Staging migration applicable for everyone. No configuration needed!
|
43 |
-
* <strong>Fast: </strong> Migration process lasts only a few seconds or minutes, depending on the site's size and server I/O power
|
44 |
-
* <strong>Safe: </strong> Access to staging site is granted for administrators only.
|
45 |
-
<br /><br />
|
46 |
-
<strong>More safe:</strong>
|
47 |
-
<br>
|
48 |
-
* Admin bar reflects that you are working on a staging site
|
49 |
-
* Extensive logging if duplication and migration process fails.
|
50 |
-
|
51 |
-
= What does not work or is not tested when running wordpress migration? =
|
52 |
-
|
53 |
-
* Wordpress migration of wordpress multisites (not tested)
|
54 |
-
* WordPress duplicating process on windows server (not tested but will probably work)
|
55 |
-
Edit: Duplication on windows server seems to be working well: [Read more](https://wordpress.org/support/topic/wont-copy-files?replies=5 "Read more")
|
56 |
-
|
57 |
-
|
58 |
-
<strong>Change your workflow of updating themes and plugins data:</strong>
|
59 |
-
|
60 |
-
1. Use WP Staging for migration of a production website to a clone site for staging purposes
|
61 |
-
2. Customize theme, configuration and plugins or install new plugins
|
62 |
-
3. Test everything on your staging site first
|
63 |
-
4. Everything running as expected? You are on the save side for migration of all these modifications to your production site!
|
64 |
-
|
65 |
-
|
66 |
-
<h3> Why should i use a staging website? </h3>
|
67 |
-
|
68 |
-
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.
|
69 |
-
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.
|
70 |
-
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)
|
71 |
-
|
72 |
-
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
|
73 |
-
up-to-date copy of your website.
|
74 |
-
|
75 |
-
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.
|
76 |
-
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.
|
77 |
-
|
78 |
-
<strong> I think its time to change this, so i created "WP Staging" for WordPress migration of staging sites</strong>
|
79 |
-
|
80 |
-
<h3> Can´t i just use my local wordpress development copy for testing like xampp / lampp? </h3>
|
81 |
-
|
82 |
-
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
|
83 |
-
of your local copy is working on your live website exactely as you would expect it.
|
84 |
-
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
|
85 |
-
the cpu performance can lead to unexpected results on your production website.
|
86 |
-
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.
|
87 |
-
|
88 |
-
This is were WP Staging steps in... Site cloning and staging site creation simplified!
|
89 |
-
|
90 |
-
<h3>I just want to migrate the database from one installation to another</h3>
|
91 |
-
If you want to migrate your local database to a already existing production site you can use a tool like WP Migrate DB.
|
92 |
-
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.
|
93 |
-
Both tools are excellent cooperating eachother.
|
94 |
-
|
95 |
-
<h3>What are the benefits compared to a plugin like Duplicator?</h3>
|
96 |
-
At first, i love the [Duplicator plugin](https://wordpress.org/plugins/duplicator/ "Duplicator plugin"). Duplicator is a great tool for migrating from development site to production one or from production site to development one.
|
97 |
-
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.
|
98 |
-
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.
|
99 |
-
|
100 |
-
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
|
101 |
-
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!
|
102 |
-
|
103 |
-
= I need you feedback =
|
104 |
-
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:
|
105 |
-
Please open a [support request](https://wordpress.org/support/plugin/wp-staging/ "support request") 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.
|
106 |
-
|
107 |
-
|
108 |
-
= Important =
|
109 |
-
|
110 |
-
Per default the staging site will have permalinks disabled because the staging site will be cloned into a subfolder and regular permalinks are not working
|
111 |
-
without doing changes to your .htaccess or nginx.conf.
|
112 |
-
In the majority of cases this is abolutely fine for a staging platform and you still will be able to test new plugins and do some theme changes on your staging platform.
|
113 |
-
If you need the same permalink stucture on your staging platform as you have in your prodcution website you have to create a custom .htaccess for apache webserver
|
114 |
-
or to adjust your nginx.conf.
|
115 |
-
|
116 |
-
|
117 |
-
= How to install and setup? =
|
118 |
-
Install it via the admin dashboard and to 'Plugins', click 'Add New' and search the plugins for 'Staging'. Install the plugin with 'Install Now'.
|
119 |
-
After installation goto the settings page 'Staging' and do your adjustments there.
|
120 |
-
|
121 |
-
|
122 |
-
== Frequently Asked Questions ==
|
123 |
-
|
124 |
-
|
125 |
-
== Official Site ==
|
126 |
-
https://wp-staging.com
|
127 |
-
|
128 |
-
== Installation ==
|
129 |
-
1. Download the file "wp-staging" , unzip and place it in your wp-content/plugins/wp-staging folder. You can alternatively upload and install it via the WordPress plugin backend.
|
130 |
-
2. Activate the plugin through the 'Plugins' menu in WordPress.
|
131 |
-
3. Start Plugins->Staging
|
132 |
-
|
133 |
-
== Screenshots ==
|
134 |
-
|
135 |
-
1. Step 1. Create new WordPress staging site
|
136 |
-
2. Step 2. Scanning your website for files and database tables
|
137 |
-
3. Step 3. Wordpress Staging site creation in progress
|
138 |
-
4. Finish!
|
139 |
-
|
140 |
-
== Changelog ==
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
*
|
146 |
-
|
147 |
-
|
148 |
-
*
|
149 |
-
*
|
150 |
-
* Fix:
|
151 |
-
*
|
152 |
-
*
|
153 |
-
*
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
*
|
162 |
-
|
163 |
-
|
164 |
-
* Fix:
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
= 2.0.
|
173 |
-
*
|
174 |
-
|
175 |
-
|
176 |
-
*
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
*
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
*
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
*
|
196 |
-
*
|
197 |
-
|
198 |
-
= 1.1.
|
199 |
-
* Fix:
|
200 |
-
|
201 |
-
= 1.1.
|
202 |
-
* New: Tested up to
|
203 |
-
*
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
* Fix:
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
*
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
* Fix:
|
219 |
-
|
220 |
-
|
221 |
-
=
|
222 |
-
*
|
223 |
-
|
224 |
-
|
225 |
-
*
|
226 |
-
*
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
* New:
|
235 |
-
|
236 |
-
|
237 |
-
* Tweak:
|
238 |
-
* Tweak:
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
* Fix:
|
246 |
-
*
|
247 |
-
|
248 |
-
|
249 |
-
*
|
250 |
-
*
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
=== WP Staging - DB & File Duplicator & Migration ===
|
2 |
+
|
3 |
+
Author URL: https://wordpress.org/plugins/wp-staging
|
4 |
+
Plugin URL: https://wordpress.org/plugins/wp-staging
|
5 |
+
Contributors: ReneHermi, WP-Staging
|
6 |
+
Donate link: https://wordpress.org/plugins/wp-staging
|
7 |
+
License: GPLv2 or later
|
8 |
+
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
9 |
+
Tags: staging, duplication, cloning, clone, migration, sandbox, test site, testing, backup, post, admin, administration, duplicate posts
|
10 |
+
Requires at least: 3.6+
|
11 |
+
Tested up to: 4.8
|
12 |
+
Stable tag: 2.1.2
|
13 |
+
|
14 |
+
A duplicator plugin! Clone, duplicate and migrate live sites to independent staging and development sites that are available only to administrators.
|
15 |
+
|
16 |
+
== Description ==
|
17 |
+
|
18 |
+
<strong>This cloning and staging plugin is well tested but work in progress. <br><br>
|
19 |
+
If you find any issue, please open a [support ticket](https://wp-staging.com/support/ "support ticket").
|
20 |
+
</strong>
|
21 |
+
<br /><br />
|
22 |
+
<strong>Note: </strong> For pushing plugins and theme files to live site, check out [https://wp-staging.com/](https://wp-staging.com/ "WP Staging Pro")
|
23 |
+
<br /><br />
|
24 |
+
<blockquote>
|
25 |
+
<h4> WP Staging for WordPress Migration </h4>
|
26 |
+
This duplicator plugin allows you to create an staging or development environment in seconds* <br /> <br />
|
27 |
+
It creates a clone of your website into a subfolder of your main WordPress installation including an entire copy of your database.
|
28 |
+
This sounds pretty simple and yes it is! All the hard time-consumptive database and file copying stuff including url replacements is done in the background.
|
29 |
+
<br /> <br />
|
30 |
+
I created this plugin because all other solutions are way too complex, overloaded with dozens of options or having server requirements which are not available on most shared hosting solutions.
|
31 |
+
All these reasons prevent user from testing new plugins and updates first before installing them on their live website, so its time to release a plugin which has the potential to be merged into everyone´s wordpress workflow.
|
32 |
+
<br /><br />
|
33 |
+
<p><small><em>* Time of creation depends on size of your database and file size</em></small></p>
|
34 |
+
</blockquote>
|
35 |
+
|
36 |
+
WP Staging helps you to prevent your website from being broken or unavailable because of installing untested plugin updates!
|
37 |
+
|
38 |
+
[youtube https://www.youtube.com/watch?v=Ye3fC6cdB3A]
|
39 |
+
|
40 |
+
= Main Features =
|
41 |
+
|
42 |
+
* <strong>Easy: </strong> Staging migration applicable for everyone. No configuration needed!
|
43 |
+
* <strong>Fast: </strong> Migration process lasts only a few seconds or minutes, depending on the site's size and server I/O power
|
44 |
+
* <strong>Safe: </strong> Access to staging site is granted for administrators only.
|
45 |
+
<br /><br />
|
46 |
+
<strong>More safe:</strong>
|
47 |
+
<br>
|
48 |
+
* Admin bar reflects that you are working on a staging site
|
49 |
+
* Extensive logging if duplication and migration process fails.
|
50 |
+
|
51 |
+
= What does not work or is not tested when running wordpress migration? =
|
52 |
+
|
53 |
+
* Wordpress migration of wordpress multisites (not tested)
|
54 |
+
* WordPress duplicating process on windows server (not tested but will probably work)
|
55 |
+
Edit: Duplication on windows server seems to be working well: [Read more](https://wordpress.org/support/topic/wont-copy-files?replies=5 "Read more")
|
56 |
+
|
57 |
+
|
58 |
+
<strong>Change your workflow of updating themes and plugins data:</strong>
|
59 |
+
|
60 |
+
1. Use WP Staging for migration of a production website to a clone site for staging purposes
|
61 |
+
2. Customize theme, configuration and plugins or install new plugins
|
62 |
+
3. Test everything on your staging site first
|
63 |
+
4. Everything running as expected? You are on the save side for migration of all these modifications to your production site!
|
64 |
+
|
65 |
+
|
66 |
+
<h3> Why should i use a staging website? </h3>
|
67 |
+
|
68 |
+
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.
|
69 |
+
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.
|
70 |
+
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)
|
71 |
+
|
72 |
+
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
|
73 |
+
up-to-date copy of your website.
|
74 |
+
|
75 |
+
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.
|
76 |
+
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.
|
77 |
+
|
78 |
+
<strong> I think its time to change this, so i created "WP Staging" for WordPress migration of staging sites</strong>
|
79 |
+
|
80 |
+
<h3> Can´t i just use my local wordpress development copy for testing like xampp / lampp? </h3>
|
81 |
+
|
82 |
+
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
|
83 |
+
of your local copy is working on your live website exactely as you would expect it.
|
84 |
+
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
|
85 |
+
the cpu performance can lead to unexpected results on your production website.
|
86 |
+
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.
|
87 |
+
|
88 |
+
This is were WP Staging steps in... Site cloning and staging site creation simplified!
|
89 |
+
|
90 |
+
<h3>I just want to migrate the database from one installation to another</h3>
|
91 |
+
If you want to migrate your local database to a already existing production site you can use a tool like WP Migrate DB.
|
92 |
+
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.
|
93 |
+
Both tools are excellent cooperating eachother.
|
94 |
+
|
95 |
+
<h3>What are the benefits compared to a plugin like Duplicator?</h3>
|
96 |
+
At first, i love the [Duplicator plugin](https://wordpress.org/plugins/duplicator/ "Duplicator plugin"). Duplicator is a great tool for migrating from development site to production one or from production site to development one.
|
97 |
+
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.
|
98 |
+
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.
|
99 |
+
|
100 |
+
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
|
101 |
+
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!
|
102 |
+
|
103 |
+
= I need you feedback =
|
104 |
+
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:
|
105 |
+
Please open a [support request](https://wordpress.org/support/plugin/wp-staging/ "support request") 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.
|
106 |
+
|
107 |
+
|
108 |
+
= Important =
|
109 |
+
|
110 |
+
Per default the staging site will have permalinks disabled because the staging site will be cloned into a subfolder and regular permalinks are not working
|
111 |
+
without doing changes to your .htaccess or nginx.conf.
|
112 |
+
In the majority of cases this is abolutely fine for a staging platform and you still will be able to test new plugins and do some theme changes on your staging platform.
|
113 |
+
If you need the same permalink stucture on your staging platform as you have in your prodcution website you have to create a custom .htaccess for apache webserver
|
114 |
+
or to adjust your nginx.conf.
|
115 |
+
|
116 |
+
|
117 |
+
= How to install and setup? =
|
118 |
+
Install it via the admin dashboard and to 'Plugins', click 'Add New' and search the plugins for 'Staging'. Install the plugin with 'Install Now'.
|
119 |
+
After installation goto the settings page 'Staging' and do your adjustments there.
|
120 |
+
|
121 |
+
|
122 |
+
== Frequently Asked Questions ==
|
123 |
+
|
124 |
+
|
125 |
+
== Official Site ==
|
126 |
+
https://wp-staging.com
|
127 |
+
|
128 |
+
== Installation ==
|
129 |
+
1. Download the file "wp-staging" , unzip and place it in your wp-content/plugins/wp-staging folder. You can alternatively upload and install it via the WordPress plugin backend.
|
130 |
+
2. Activate the plugin through the 'Plugins' menu in WordPress.
|
131 |
+
3. Start Plugins->Staging
|
132 |
+
|
133 |
+
== Screenshots ==
|
134 |
+
|
135 |
+
1. Step 1. Create new WordPress staging site
|
136 |
+
2. Step 2. Scanning your website for files and database tables
|
137 |
+
3. Step 3. Wordpress Staging site creation in progress
|
138 |
+
4. Finish!
|
139 |
+
|
140 |
+
== Changelog ==
|
141 |
+
|
142 |
+
= 2.1.2 =
|
143 |
+
* Fix: Remove LOCK_EX parameter in file_put_contents(). LOCK_EX is not working on several systems which results in cloning process timeouts
|
144 |
+
* Fix: Huge Performance improvement in copying process by removing duplicate file entries in the cache file. This also prevents weird timeout issues on some hosted websites
|
145 |
+
* Fix: Error 500 when debug mode is activated
|
146 |
+
* Fix: Limit maximum execution time to 30 seconds
|
147 |
+
* Fix: Sanitize Clone Names and Keys to fix "clone not found" issue in upgrade routine
|
148 |
+
* Fix: Do not clone the plugin wps-hide-login
|
149 |
+
* Fix: Staging sites can not be deleted if they are very big
|
150 |
+
* Fix: Link to staging site is undefined
|
151 |
+
* Tweak: Better admin message for asking for a review
|
152 |
+
* Tweak: Remove table wpstg_rmpermalinks_executed when plugin is uninstalled
|
153 |
+
* New: New setting to specify the maximum amount of files copied within one ajax call to fix godaddy and bluehost ajax 404 errors. Default 10 per batch
|
154 |
+
|
155 |
+
|
156 |
+
= 2.1.1 =
|
157 |
+
* New: Add link to tutorial explaining the process of pushing modification to the live site
|
158 |
+
|
159 |
+
= 2.1.0 =
|
160 |
+
* New: Exclude unneccessary files from cloning process: .tmp, .log, .htaccess, .git, .gitignore, desktop.ini, .DS_Store, .svn
|
161 |
+
* New: More details for debugging in Tools->System Info
|
162 |
+
* Fix: Check if tables in staging site exists before attempting to modify them
|
163 |
+
* Fix: WordPress in sub directories were not opening
|
164 |
+
* Fix: Nonce check not working if nonce life time is filtered by another plugin WP Bug: https://core.trac.wordpress.org/ticket/41617#comment:1
|
165 |
+
* Fix: Access to staging site not working, if WP_SITEURL and WP_HOME is defined in wp-config.php
|
166 |
+
* Tweak: Exclude wp-content/cache folder from copying process
|
167 |
+
|
168 |
+
|
169 |
+
= 2.0.9 =
|
170 |
+
* Skip Version
|
171 |
+
|
172 |
+
= 2.0.8 =
|
173 |
+
* Fix: After update from wpstg 1.6.x to 2.x previous settings were not imported resulting in cancelation of cloning process. Still not fixed in 2.0.7
|
174 |
+
|
175 |
+
= 2.0.7 =
|
176 |
+
* Fix: After update from wpstg 1.6.x to 2.x previous settings were not imported resulting in cancelation of cloning process
|
177 |
+
|
178 |
+
|
179 |
+
= 2.0.6 =
|
180 |
+
* Fix: Cancel Cloning button not working
|
181 |
+
* Fix: Limit max execution time to a maximum of 30sec to prevent high memory consumption and script timeouts
|
182 |
+
|
183 |
+
|
184 |
+
= 2.0.5 =
|
185 |
+
* New: Major version - Complete rewrite of the code base
|
186 |
+
* New: Batch processing allows to clone even huge sites without any timeouts
|
187 |
+
* New: Preparation for WP QUADS PRO with ability to copy file changes back to live site
|
188 |
+
* New: Bypass (broken) third party plugins during wp staging related ajax requests to prevent processing errors. Use a mu plugin for this.
|
189 |
+
|
190 |
+
= 1.1.6 =
|
191 |
+
* New: Add download link to WP Staging Beta Version 2.0.1
|
192 |
+
|
193 |
+
= 1.1.5 =
|
194 |
+
* Fix: Admin notice is throwing a false positive write permission error
|
195 |
+
* New: Move log folder to wp-content/uploads/wp-staging/logs
|
196 |
+
* New: Tested up to WP 4.7.3
|
197 |
+
|
198 |
+
= 1.1.4 =
|
199 |
+
* Fix: Fatal error Unsupported operand types
|
200 |
+
|
201 |
+
= 1.1.3 =
|
202 |
+
* New: Tested up to wp 4.7.2
|
203 |
+
* Fix: Arrows in drop down for folder selection are distorted
|
204 |
+
* Tweak: Show working log as default to make debugging easier
|
205 |
+
|
206 |
+
= 1.1.2 =
|
207 |
+
* Fix: Settings are not deleted when plugin is removed
|
208 |
+
* Fix: Staging site is available for non administrators
|
209 |
+
|
210 |
+
= 1.1.1 =
|
211 |
+
* Fix: Change rating url
|
212 |
+
|
213 |
+
= 1.1.0 =
|
214 |
+
* New: Tested up to WP 4.6
|
215 |
+
* New: Create a poll and ask what feature is most required
|
216 |
+
|
217 |
+
= 1.0.9 =
|
218 |
+
* Fix: Undefined WPSTG() warning
|
219 |
+
* Fix: Change compatibility version to wp 4.5.3
|
220 |
+
|
221 |
+
= 1.0.8 =
|
222 |
+
* Tested up to WP 4.5.2
|
223 |
+
|
224 |
+
= 1.0.7 =
|
225 |
+
* Fix: Activation hook is not fired and staging site is not working properly
|
226 |
+
* Performance: Increase default query copy limit to 1000
|
227 |
+
|
228 |
+
= 1.0.6 =
|
229 |
+
* Fix: Uninstalling plugin throwing error
|
230 |
+
* Fix: Error permission admin notice although permission issues are correct
|
231 |
+
|
232 |
+
|
233 |
+
= 1.0.5 =
|
234 |
+
* New: Tested up to WP 4.5
|
235 |
+
* Fix: Download system log not working
|
236 |
+
* Fix: Click on Optimizer "Select all | none | invert" links leads to jumping
|
237 |
+
* Tweak: Make clear that unselecting a checkbox will exlude table or file from copy process
|
238 |
+
* Tweak: Remove unnecessary text
|
239 |
+
* Tweak: Change beta notice in dashboard. WP Staging is stable
|
240 |
+
* Tweak: Change twitter handle to @wpstg
|
241 |
+
|
242 |
+
= 1.0.3 =
|
243 |
+
* Fix: Missing const MASHFS_VERSION
|
244 |
+
* Fix: Remove error "table XY has been created, BUT inserting rows failed."
|
245 |
+
* Fix: Not tested up to 4.4.2 message shown although it's tested up to WP 4.4.2
|
246 |
+
* New: Disable either free or pro version and does not allow to have both version enabled at the same time
|
247 |
+
|
248 |
+
= 1.0.2 =
|
249 |
+
* Tweak: Change setting description of uninstall option
|
250 |
+
* Tweak: Lower tags in readme.txt
|
251 |
+
|
252 |
+
= 1.0.1 =
|
253 |
+
* New: Orange colored admin bar on staging site for better visualization and comparision between production live site and staging site
|
254 |
+
* Tweak: Remove contact link on multisite notification
|
255 |
+
|
256 |
+
= 1.0.0 =
|
257 |
+
* Fix: Do not follow symlinks during file copy process
|
258 |
+
* Fix: css error
|
259 |
+
* Fix: Show "not-compatible" notice only when blog version is higher than plugin tested version.
|
260 |
+
* Fix: undefined var $size
|
261 |
+
* Fix: Check if $path is null before writing to remaining_files.json
|
262 |
+
* Fix: $db_helper undefined message
|
263 |
+
* Fix: Skip non utf8 encoded files during copying process
|
264 |
+
|
265 |
+
Complete changelog: [https://wp-staging.com/changelog.txt](https://wp-staging.com/changelog.txt)
|
266 |
+
|
267 |
+
== Upgrade Notice ==
|
268 |
+
|
269 |
+
= 2.1.2 =
|
270 |
+
2.1.2 * Lot of modifications to increase speed and reliability for crewating staging sites
|
uninstall.php
CHANGED
@@ -14,75 +14,75 @@ use WPStaging\Backend\Optimizer\Optimizer;
|
|
14 |
* @since 0.9.0
|
15 |
*/
|
16 |
// No direct access
|
17 |
-
if(
|
18 |
exit;
|
19 |
}
|
20 |
|
21 |
class uninstall {
|
22 |
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
}
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
|
87 |
}
|
88 |
|
14 |
* @since 0.9.0
|
15 |
*/
|
16 |
// No direct access
|
17 |
+
if (!defined('WP_UNINSTALL_PLUGIN')) {
|
18 |
exit;
|
19 |
}
|
20 |
|
21 |
class uninstall {
|
22 |
|
23 |
+
public function __construct() {
|
24 |
+
|
25 |
+
// Plugin Folder Path
|
26 |
+
if (!defined('WPSTG_PLUGIN_DIR')) {
|
27 |
+
define('WPSTG_PLUGIN_DIR', plugin_dir_path(__FILE__));
|
28 |
+
}
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Path to main WP Staging class
|
32 |
+
* Make sure to not redeclare class in case free version has been installed previosly
|
33 |
+
*/
|
34 |
+
if (!class_exists('WPStaging\WPStaging')) {
|
35 |
+
require_once plugin_dir_path(__FILE__) . "apps/Core/WPStaging.php";
|
36 |
+
}
|
37 |
+
$wpStaging = \WPStaging\WPStaging::getInstance();
|
38 |
+
|
39 |
+
// Delete our must use plugin
|
40 |
+
$this->deleteMuPlugin();
|
41 |
+
|
42 |
+
$this->init();
|
43 |
+
}
|
44 |
+
|
45 |
+
private function init() {
|
46 |
+
|
47 |
+
$options = json_decode(json_encode(get_option("wpstg_settings", array())));
|
48 |
+
|
49 |
+
if (isset($options->unInstallOnDelete) && '1' === $options->unInstallOnDelete) {
|
50 |
+
// Delete options
|
51 |
+
delete_option("wpstg_version_upgraded_from");
|
52 |
+
delete_option("wpstg_version");
|
53 |
+
delete_option("wpstg_installDate");
|
54 |
+
delete_option("wpstg_firsttime");
|
55 |
+
delete_option("wpstg_is_staging_site");
|
56 |
+
delete_option("wpstg_settings");
|
57 |
+
delete_option("wpstg_rmpermalinks_executed");
|
58 |
+
|
59 |
+
/* Do not delete these fields without actually deleting the staging site
|
60 |
+
* @create a delete routine which deletes the staging sites first
|
61 |
+
*/
|
62 |
+
//delete_option( "wpstg_existing_clones" );
|
63 |
+
//delete_option( "wpstg_existing_clones_beta" );
|
64 |
+
// Old wpstg 1.3 options for admin notices
|
65 |
+
delete_option("wpstg_start_poll");
|
66 |
+
delete_option("wpstg_hide_beta");
|
67 |
+
delete_option("wpstg_RatingDiv");
|
68 |
+
|
69 |
+
// New 2.x options for admin notices
|
70 |
+
delete_option("wpstg_poll");
|
71 |
+
delete_option("wpstg_rating");
|
72 |
+
delete_option("wpstg_beta");
|
73 |
+
|
74 |
+
// Delete events
|
75 |
+
wp_clear_scheduled_hook('wpstg_weekly_event');
|
76 |
+
}
|
77 |
+
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
* delete MuPlugin
|
81 |
+
*/
|
82 |
+
private function deleteMuPlugin() {
|
83 |
+
$optimizer = new Optimizer;
|
84 |
+
$optimizer->unstallOptimizer();
|
85 |
+
}
|
86 |
|
87 |
}
|
88 |
|
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.1.
|
11 |
* Text Domain: wpstg
|
12 |
* Domain Path: /languages/
|
13 |
|
7 |
* Author: WP-Staging
|
8 |
* Author URI: https://wp-staging.com
|
9 |
* Contributors: ReneHermi, ilgityildirim
|
10 |
+
* Version: 2.1.2
|
11 |
* Text Domain: wpstg
|
12 |
* Domain Path: /languages/
|
13 |
|