Version Description
- New: Exclude unneccessary files from cloning process: .tmp, .log, .htaccess, .git, .gitignore, desktop.ini, .DS_Store, .svn
- New: More details for debugging in Tools->System Info
- Fix: Check if tables in staging site exists before attempting to modify them
- Fix: WordPress in sub directories were not opening
- Tweak: Exclude wp-content/cache folder from copying process
Download this release
Release Info
Developer | ReneHermi |
Plugin | WP Staging – DB & File Duplicator & Migration |
Version | 2.0.9 |
Comparing to | |
See all releases |
Code changes from version 2.0.8 to 2.0.9
- apps/Backend/Modules/Jobs/Cloning.php +11 -7
- apps/Backend/Modules/Jobs/Data.php +66 -22
- apps/Backend/Modules/Jobs/Delete_deprecated.php +0 -397
- apps/Backend/Modules/Jobs/Delete_new.php +0 -382
- apps/Backend/Modules/Jobs/Delete_old.php +0 -367
- apps/Backend/Modules/Jobs/Directories.php +39 -8
- apps/Backend/Modules/SystemInfo.php +54 -2
- apps/Backend/public/css/wpstg-admin.css +1 -1
- apps/Backend/public/js/wpstg-admin.js +1 -1
- apps/Backend/views/clone/ajax/start.php +8 -2
- apps/Core/DTO/Settings.php +20 -22
- apps/Core/WPStaging.php +2 -2
- readme.txt +8 -1
- wp-staging.php +1 -1
apps/Backend/Modules/Jobs/Cloning.php
CHANGED
@@ -3,10 +3,6 @@ namespace WPStaging\Backend\Modules\Jobs;
|
|
3 |
|
4 |
use WPStaging\Backend\Modules\Jobs\Exceptions\JobNotFoundException;
|
5 |
|
6 |
-
//ini_set('display_startup_errors', 1);
|
7 |
-
//ini_set('display_errors', 1);
|
8 |
-
//error_reporting(-1);
|
9 |
-
|
10 |
/**
|
11 |
* Class Cloning
|
12 |
* @package WPStaging\Backend\Modules\Jobs
|
@@ -34,6 +30,7 @@ class Cloning extends Job
|
|
34 |
$this->options->includedDirectories = array();
|
35 |
$this->options->excludedDirectories = array();
|
36 |
$this->options->extraDirectories = array();
|
|
|
37 |
|
38 |
// Job
|
39 |
$this->options->job = new \stdClass();
|
@@ -58,6 +55,15 @@ class Cloning extends Job
|
|
58 |
{
|
59 |
$this->options->excludedDirectories = $_POST["excludedDirectories"];
|
60 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
61 |
|
62 |
// Included Directories
|
63 |
if (isset($_POST["includedDirectories"]) && is_array($_POST["includedDirectories"]))
|
@@ -78,9 +84,7 @@ class Cloning extends Job
|
|
78 |
);
|
79 |
|
80 |
array_unshift($this->options->directoriesToCopy, ABSPATH);
|
81 |
-
|
82 |
-
//var_dump($this->options->directoriesToCopy);
|
83 |
-
|
84 |
// Delete files to copy listing
|
85 |
$this->cache->delete("files_to_copy");
|
86 |
|
3 |
|
4 |
use WPStaging\Backend\Modules\Jobs\Exceptions\JobNotFoundException;
|
5 |
|
|
|
|
|
|
|
|
|
6 |
/**
|
7 |
* Class Cloning
|
8 |
* @package WPStaging\Backend\Modules\Jobs
|
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();
|
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"]))
|
84 |
);
|
85 |
|
86 |
array_unshift($this->options->directoriesToCopy, ABSPATH);
|
87 |
+
|
|
|
|
|
88 |
// Delete files to copy listing
|
89 |
$this->cache->delete("files_to_copy");
|
90 |
|
apps/Backend/Modules/Jobs/Data.php
CHANGED
@@ -157,39 +157,74 @@ class Data extends JobExecutable
|
|
157 |
|
158 |
return false;
|
159 |
}
|
160 |
-
|
|
|
161 |
/**
|
162 |
-
*
|
163 |
-
* @
|
|
|
164 |
*/
|
165 |
-
protected function
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'siteurl' or option_name='home'",
|
172 |
-
get_home_url() . '/' . $this->options->cloneDirectoryName
|
173 |
-
)
|
174 |
-
);
|
175 |
-
|
176 |
-
// All good
|
177 |
-
if ($result)
|
178 |
-
{
|
179 |
-
return true;
|
180 |
-
}
|
181 |
-
|
182 |
-
$this->log("Failed to update siteurl and homeurl in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_ERROR);
|
183 |
-
return false;
|
184 |
}
|
185 |
|
186 |
/**
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
187 |
* Update "wpstg_is_staging_site"
|
188 |
* @return bool
|
189 |
*/
|
190 |
protected function step2()
|
191 |
{
|
|
|
192 |
$this->log( "Updating row wpstg_is_staging_site in {$this->prefix}options {$this->db->last_error}" );
|
|
|
|
|
|
|
|
|
193 |
|
194 |
$result = $this->db->query(
|
195 |
$this->db->prepare(
|
@@ -225,8 +260,13 @@ class Data extends JobExecutable
|
|
225 |
*/
|
226 |
protected function step3()
|
227 |
{
|
|
|
228 |
$this->log("Updating rewrite_rules in {$this->prefix}options {$this->db->last_error}");
|
229 |
|
|
|
|
|
|
|
|
|
230 |
$result = $this->db->query(
|
231 |
$this->db->prepare(
|
232 |
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'rewrite_rules'",
|
@@ -250,6 +290,10 @@ class Data extends JobExecutable
|
|
250 |
*/
|
251 |
protected function step4() {
|
252 |
$this->log( "Updating {$this->prefix}usermeta db prefix {$this->db->last_error}" );
|
|
|
|
|
|
|
|
|
253 |
|
254 |
$resultOptions = $this->db->query(
|
255 |
$this->db->prepare(
|
157 |
|
158 |
return false;
|
159 |
}
|
160 |
+
|
161 |
+
|
162 |
/**
|
163 |
+
* Check if table exists
|
164 |
+
* @param string $table
|
165 |
+
* @return boolean
|
166 |
*/
|
167 |
+
protected function isTable($table){
|
168 |
+
if($this->db->get_var("SHOW TABLES LIKE '{$table}'") != $table ){
|
169 |
+
$this->log( "Table {$table} does not exists", Logger::TYPE_ERROR );
|
170 |
+
return false;
|
171 |
+
}
|
172 |
+
return true;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
173 |
}
|
174 |
|
175 |
/**
|
176 |
+
* Replace "siteurl"
|
177 |
+
* @return bool
|
178 |
+
*/
|
179 |
+
protected function step1() {
|
180 |
+
$this->log( "Updating siteurl and homeurl in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_INFO );
|
181 |
+
|
182 |
+
if( false === $this->isTable( $this->prefix . 'options' ) ) {
|
183 |
+
return true;
|
184 |
+
}
|
185 |
+
|
186 |
+
// Installed in sub-directory
|
187 |
+
if( isset( $this->settings->wpSubDirectory ) && "1" === $this->settings->wpSubDirectory ) {
|
188 |
+
$subDirectory = str_replace( get_home_path(), '', ABSPATH );
|
189 |
+
$this->log( "Updating siteurl and homeurl to " . get_home_url() . '/' . $subDirectory . $this->options->cloneDirectoryName );
|
190 |
+
// Replace URLs
|
191 |
+
$result = $this->db->query(
|
192 |
+
$this->db->prepare(
|
193 |
+
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'siteurl' or option_name='home'", get_home_url() . '/' . $subDirectory . $this->options->cloneDirectoryName
|
194 |
+
)
|
195 |
+
);
|
196 |
+
} else {
|
197 |
+
$this->log( "Updating siteurl and homeurl to " . get_home_url() . '/' . $this->options->cloneDirectoryName );
|
198 |
+
// Replace URLs
|
199 |
+
$result = $this->db->query(
|
200 |
+
$this->db->prepare(
|
201 |
+
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'siteurl' or option_name='home'", get_home_url() . '/' . $this->options->cloneDirectoryName
|
202 |
+
)
|
203 |
+
);
|
204 |
+
}
|
205 |
+
|
206 |
+
|
207 |
+
// All good
|
208 |
+
if( $result ) {
|
209 |
+
return true;
|
210 |
+
}
|
211 |
+
|
212 |
+
$this->log( "Failed to update siteurl and homeurl in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_ERROR );
|
213 |
+
return false;
|
214 |
+
}
|
215 |
+
|
216 |
+
/**
|
217 |
* Update "wpstg_is_staging_site"
|
218 |
* @return bool
|
219 |
*/
|
220 |
protected function step2()
|
221 |
{
|
222 |
+
|
223 |
$this->log( "Updating row wpstg_is_staging_site in {$this->prefix}options {$this->db->last_error}" );
|
224 |
+
|
225 |
+
if( false === $this->isTable( $this->prefix . 'options' ) ) {
|
226 |
+
return true;
|
227 |
+
}
|
228 |
|
229 |
$result = $this->db->query(
|
230 |
$this->db->prepare(
|
260 |
*/
|
261 |
protected function step3()
|
262 |
{
|
263 |
+
|
264 |
$this->log("Updating rewrite_rules in {$this->prefix}options {$this->db->last_error}");
|
265 |
|
266 |
+
if( false === $this->isTable( $this->prefix . 'options' ) ) {
|
267 |
+
return true;
|
268 |
+
}
|
269 |
+
|
270 |
$result = $this->db->query(
|
271 |
$this->db->prepare(
|
272 |
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'rewrite_rules'",
|
290 |
*/
|
291 |
protected function step4() {
|
292 |
$this->log( "Updating {$this->prefix}usermeta db prefix {$this->db->last_error}" );
|
293 |
+
|
294 |
+
if( false === $this->isTable( $this->prefix . 'usermeta' ) ) {
|
295 |
+
return true;
|
296 |
+
}
|
297 |
|
298 |
$resultOptions = $this->db->query(
|
299 |
$this->db->prepare(
|
apps/Backend/Modules/Jobs/Delete_deprecated.php
DELETED
@@ -1,397 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WPStaging\Backend\Modules\Jobs;
|
3 |
-
|
4 |
-
use WPStaging\Backend\Modules\Jobs\Exceptions\CloneNotFoundException;
|
5 |
-
//use WPStaging\Utils\Directories;
|
6 |
-
use WPStaging\Utils\Logger;
|
7 |
-
use WPStaging\WPStaging;
|
8 |
-
|
9 |
-
/**
|
10 |
-
* Class Delete
|
11 |
-
* @package WPStaging\Backend\Modules\Jobs
|
12 |
-
*/
|
13 |
-
class Delete_deprecated extends Job
|
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 |
-
* Sets Clone and Table Records
|
38 |
-
* @param null|array $clone
|
39 |
-
*/
|
40 |
-
public function setData($clone = null)
|
41 |
-
{
|
42 |
-
if (!is_array($clone))
|
43 |
-
{
|
44 |
-
$this->getCloneRecords();
|
45 |
-
}
|
46 |
-
else
|
47 |
-
{
|
48 |
-
$this->clone = (object) $clone;
|
49 |
-
$this->forceDeleteDirectories = true;
|
50 |
-
}
|
51 |
-
|
52 |
-
$this->getTableRecords();
|
53 |
-
}
|
54 |
-
|
55 |
-
/**
|
56 |
-
* Get clone
|
57 |
-
* @param null|string $name
|
58 |
-
* @throws CloneNotFoundException
|
59 |
-
*/
|
60 |
-
private function getCloneRecords($name = null)
|
61 |
-
{
|
62 |
-
if (null === $name && !isset($_POST["clone"]))
|
63 |
-
{
|
64 |
-
$this->log("Clone name is not set", Logger::TYPE_FATAL);
|
65 |
-
throw new CloneNotFoundException();
|
66 |
-
}
|
67 |
-
|
68 |
-
if (null === $name)
|
69 |
-
{
|
70 |
-
$name = $_POST["clone"];
|
71 |
-
}
|
72 |
-
|
73 |
-
$clones = get_option("wpstg_existing_clones_beta", array());
|
74 |
-
|
75 |
-
if (empty($clones) || !isset($clones[$name]))
|
76 |
-
{
|
77 |
-
$this->log("Couldn't find clone name {$name} or no existing clone", Logger::TYPE_FATAL);
|
78 |
-
throw new CloneNotFoundException();
|
79 |
-
}
|
80 |
-
|
81 |
-
$this->clone = $clones[$name];
|
82 |
-
$this->clone["name"] = $name;
|
83 |
-
// $this->clone["size"] = null;
|
84 |
-
//
|
85 |
-
// if (isset($this->settings->checkDirectorySize) || '1' === $this->settings->checkDirectorySize)
|
86 |
-
// {
|
87 |
-
// $directories = new Directories();
|
88 |
-
// $this->clone["size"] = $this->formatSize($directories->size($this->clone));
|
89 |
-
// unset($directories);
|
90 |
-
// }
|
91 |
-
|
92 |
-
$this->clone = (object) $this->clone;
|
93 |
-
|
94 |
-
unset($clones);
|
95 |
-
}
|
96 |
-
|
97 |
-
/**
|
98 |
-
* Get Tables
|
99 |
-
*/
|
100 |
-
private function getTableRecords()
|
101 |
-
{
|
102 |
-
$wpdb = WPStaging::getInstance()->get("wpdb");
|
103 |
-
|
104 |
-
// if ($this->clone['version']){
|
105 |
-
//
|
106 |
-
// }
|
107 |
-
|
108 |
-
$tables = $wpdb->get_results("SHOW TABLE STATUS LIKE 'wpstg{$this->clone->number}_%'");
|
109 |
-
|
110 |
-
$this->tables = array();
|
111 |
-
|
112 |
-
foreach ($tables as $table)
|
113 |
-
{
|
114 |
-
$this->tables[] = array(
|
115 |
-
"name" => $table->Name,
|
116 |
-
"size" => $this->formatSize(($table->Data_length + $table->Index_length))
|
117 |
-
);
|
118 |
-
}
|
119 |
-
|
120 |
-
$this->tables = json_decode(json_encode($this->tables));
|
121 |
-
}
|
122 |
-
|
123 |
-
/**
|
124 |
-
* Format bytes into human readable form
|
125 |
-
* @param int $bytes
|
126 |
-
* @param int $precision
|
127 |
-
* @return string
|
128 |
-
*/
|
129 |
-
public function formatSize($bytes, $precision = 2)
|
130 |
-
{
|
131 |
-
if ((int) $bytes < 1)
|
132 |
-
{
|
133 |
-
return '';
|
134 |
-
}
|
135 |
-
|
136 |
-
$units = array('B', "KB", "MB", "GB", "TB");
|
137 |
-
|
138 |
-
$bytes = (int) $bytes;
|
139 |
-
$base = log($bytes) / log(1000); // 1024 would be for MiB KiB etc
|
140 |
-
$pow = pow(1000, $base - floor($base)); // Same rule for 1000
|
141 |
-
|
142 |
-
return round($pow, $precision) . ' ' . $units[(int) floor($base)];
|
143 |
-
}
|
144 |
-
|
145 |
-
/**
|
146 |
-
* @return false
|
147 |
-
*/
|
148 |
-
public function getClone()
|
149 |
-
{
|
150 |
-
return $this->clone;
|
151 |
-
}
|
152 |
-
|
153 |
-
/**
|
154 |
-
* @return null|object
|
155 |
-
*/
|
156 |
-
public function getTables()
|
157 |
-
{
|
158 |
-
return $this->tables;
|
159 |
-
}
|
160 |
-
|
161 |
-
/**
|
162 |
-
* Start Module
|
163 |
-
* @param null|array $clone
|
164 |
-
* @return bool
|
165 |
-
*/
|
166 |
-
public function start($clone = null)
|
167 |
-
{
|
168 |
-
// Set data
|
169 |
-
$this->setData($clone);
|
170 |
-
|
171 |
-
// Get the job first
|
172 |
-
$this->getJob();
|
173 |
-
|
174 |
-
$method = "delete" . ucwords($this->job->current);
|
175 |
-
return $this->{$method}();
|
176 |
-
}
|
177 |
-
|
178 |
-
/**
|
179 |
-
* Get job data
|
180 |
-
*/
|
181 |
-
private function getJob()
|
182 |
-
{
|
183 |
-
$this->job = $this->cache->get("delete_job_{$this->clone->name}");
|
184 |
-
|
185 |
-
if (null !== $this->job)
|
186 |
-
{
|
187 |
-
return;
|
188 |
-
}
|
189 |
-
|
190 |
-
// Generate JOB
|
191 |
-
$this->job = (object) array(
|
192 |
-
"current" => "tables",
|
193 |
-
"nextDirectoryToDelete" => $this->clone->path
|
194 |
-
);
|
195 |
-
|
196 |
-
$this->cache->save("delete_job_{$this->clone->name}", $this->job);
|
197 |
-
}
|
198 |
-
|
199 |
-
/**
|
200 |
-
* @return bool
|
201 |
-
*/
|
202 |
-
private function updateJob()
|
203 |
-
{
|
204 |
-
$this->job->nextDirectoryToDelete = trim($this->job->nextDirectoryToDelete);
|
205 |
-
return $this->cache->save("delete_job_{$this->clone->name}", $this->job);
|
206 |
-
}
|
207 |
-
|
208 |
-
/**
|
209 |
-
* @return array
|
210 |
-
*/
|
211 |
-
private function getTablesToRemove()
|
212 |
-
{
|
213 |
-
$tables = $this->getTableNames();
|
214 |
-
|
215 |
-
if (!isset($_POST["excludedTables"]) || !is_array($_POST["excludedTables"]) || empty($_POST["excludedTables"]))
|
216 |
-
{
|
217 |
-
return $tables;
|
218 |
-
}
|
219 |
-
|
220 |
-
return array_diff($tables, $_POST["excludedTables"]);
|
221 |
-
}
|
222 |
-
|
223 |
-
/**
|
224 |
-
* @return array
|
225 |
-
*/
|
226 |
-
private function getTableNames()
|
227 |
-
{
|
228 |
-
return (!is_array($this->tables)) ? array() : array_map(function($value) {
|
229 |
-
return ($value->name);
|
230 |
-
}, $this->tables);
|
231 |
-
}
|
232 |
-
|
233 |
-
/**
|
234 |
-
* Delete Tables
|
235 |
-
*/
|
236 |
-
public function deleteTables()
|
237 |
-
{
|
238 |
-
if ($this->isOverThreshold())
|
239 |
-
{
|
240 |
-
return;
|
241 |
-
}
|
242 |
-
|
243 |
-
$wpdb = WPStaging::getInstance()->get("wpdb");
|
244 |
-
|
245 |
-
foreach ($this->getTablesToRemove() as $table)
|
246 |
-
{
|
247 |
-
// PROTECTION: Never delete any table that beginns with wp prefix of live site
|
248 |
-
if($this->startsWith($table, $wpdb->prefix)){
|
249 |
-
$this->log("Fatal Error: Trying to delete table {$table} of main WP installation!", Logger::TYPE_CRITICAL);
|
250 |
-
return false;
|
251 |
-
} else{
|
252 |
-
$wpdb->query("DROP TABLE {$table}");
|
253 |
-
}
|
254 |
-
}
|
255 |
-
|
256 |
-
// Move on to the next
|
257 |
-
$this->job->current = "directory";
|
258 |
-
$this->updateJob();
|
259 |
-
}
|
260 |
-
|
261 |
-
/**
|
262 |
-
* Check if a strings start with a specific string
|
263 |
-
* @param string $haystack
|
264 |
-
* @param string $needle
|
265 |
-
* @return bool
|
266 |
-
*/
|
267 |
-
protected function startsWith($haystack, $needle)
|
268 |
-
{
|
269 |
-
$length = strlen($needle);
|
270 |
-
return (substr($haystack, 0, $length) === $needle);
|
271 |
-
}
|
272 |
-
|
273 |
-
/**
|
274 |
-
* Delete Directories
|
275 |
-
*/
|
276 |
-
public function deleteDirectory()
|
277 |
-
{
|
278 |
-
// No deleting directories or root of this clone is deleted
|
279 |
-
if ($this->isDirectoryDeletingFinished())
|
280 |
-
{
|
281 |
-
$this->job->current = "finish";
|
282 |
-
$this->updateJob();
|
283 |
-
return;
|
284 |
-
}
|
285 |
-
|
286 |
-
$this->processDirectory($this->job->nextDirectoryToDelete);
|
287 |
-
|
288 |
-
return;
|
289 |
-
}
|
290 |
-
|
291 |
-
/**
|
292 |
-
* @return bool
|
293 |
-
*/
|
294 |
-
public function isDirectoryDeletingFinished()
|
295 |
-
{
|
296 |
-
return (
|
297 |
-
(false === $this->forceDeleteDirectories && (!isset($_POST["deleteDir"]) || '1' !== $_POST["deleteDir"])) ||
|
298 |
-
!is_dir($this->clone->path) || ABSPATH === $this->job->nextDirectoryToDelete
|
299 |
-
);
|
300 |
-
}
|
301 |
-
|
302 |
-
/**
|
303 |
-
* Delete contents of the directory if there are no directories in it and then delete itself
|
304 |
-
* @param string $path
|
305 |
-
* @return mixed
|
306 |
-
*/
|
307 |
-
private function processDirectory($path)
|
308 |
-
{
|
309 |
-
// We hit the limit, stop
|
310 |
-
if ($this->shouldStop($path))
|
311 |
-
{
|
312 |
-
$this->updateJob();
|
313 |
-
return false;
|
314 |
-
}
|
315 |
-
|
316 |
-
$this->totalRecursion++;
|
317 |
-
|
318 |
-
$contents = new \DirectoryIterator($path);
|
319 |
-
|
320 |
-
foreach ($contents as $content)
|
321 |
-
{
|
322 |
-
// Skip dots
|
323 |
-
if ($content->isDot())
|
324 |
-
{
|
325 |
-
continue;
|
326 |
-
}
|
327 |
-
|
328 |
-
// Get into the directory
|
329 |
-
if (!$content->isLink() && $content->isDir())
|
330 |
-
{
|
331 |
-
return $this->processDirectory($content->getRealPath());
|
332 |
-
}
|
333 |
-
|
334 |
-
// Delete file
|
335 |
-
if ($content->isFile())
|
336 |
-
{
|
337 |
-
@unlink($content->getRealPath());
|
338 |
-
}
|
339 |
-
}
|
340 |
-
|
341 |
-
// Delete directory
|
342 |
-
$this->job->lastDeletedDirectory = realpath($path . "/..");
|
343 |
-
@rmdir($path);
|
344 |
-
$this->updateJob();
|
345 |
-
$this->processDirectory($this->job->nextDirectoryToDelete);
|
346 |
-
}
|
347 |
-
|
348 |
-
/**
|
349 |
-
* @param string $path
|
350 |
-
* @return bool
|
351 |
-
*/
|
352 |
-
private function shouldStop($path)
|
353 |
-
{
|
354 |
-
// Just to make sure the root dir is never deleted!
|
355 |
-
if ($path === get_home_path()){
|
356 |
-
$this->log("Fatal Error: Trying to delete root of WP installation!", Logger::TYPE_CRITICAL);
|
357 |
-
return true;
|
358 |
-
}
|
359 |
-
|
360 |
-
// Check if threshold is reached and is valid dir
|
361 |
-
return (
|
362 |
-
$this->isOverThreshold() ||
|
363 |
-
!is_dir($path) ||
|
364 |
-
$this->isDirectoryDeletingFinished()
|
365 |
-
);
|
366 |
-
}
|
367 |
-
|
368 |
-
/**
|
369 |
-
* Finish / Update Existing Clones
|
370 |
-
*/
|
371 |
-
public function deleteFinish()
|
372 |
-
{
|
373 |
-
$existingClones = get_option("wpstg_existing_clones_beta", array());
|
374 |
-
|
375 |
-
// Check if clones still exist
|
376 |
-
$this->log("Verifying existing clones...");
|
377 |
-
foreach ($existingClones as $name => $clone)
|
378 |
-
{
|
379 |
-
if (!is_dir($clone["path"]))
|
380 |
-
{
|
381 |
-
unset($existingClones[$name]);
|
382 |
-
}
|
383 |
-
}
|
384 |
-
$this->log("Existing clones verified!");
|
385 |
-
|
386 |
-
if (false === update_option("wpstg_existing_clones_beta", $existingClones))
|
387 |
-
{
|
388 |
-
$this->log("Failed to save {$this->options->clone}'s clone job data to database'");
|
389 |
-
}
|
390 |
-
|
391 |
-
// Delete cached file
|
392 |
-
$this->cache->delete("delete_job_{$this->clone->name}");
|
393 |
-
$this->cache->delete("delete_directories_{$this->clone->name}");
|
394 |
-
|
395 |
-
return true;
|
396 |
-
}
|
397 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
apps/Backend/Modules/Jobs/Delete_new.php
DELETED
@@ -1,382 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WPStaging\Backend\Modules\Jobs;
|
3 |
-
|
4 |
-
use WPStaging\Backend\Modules\Jobs\Exceptions\CloneNotFoundException;
|
5 |
-
//use WPStaging\Utils\Directories;
|
6 |
-
use WPStaging\Utils\Logger;
|
7 |
-
use WPStaging\WPStaging;
|
8 |
-
|
9 |
-
/**
|
10 |
-
* Class Delete
|
11 |
-
* @package WPStaging\Backend\Modules\Jobs
|
12 |
-
*/
|
13 |
-
class Delete_new extends Job
|
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 |
-
* Sets Clone and Table Records
|
38 |
-
* @param null|array $clone
|
39 |
-
*/
|
40 |
-
public function setData($clone = null)
|
41 |
-
{
|
42 |
-
if (!is_array($clone))
|
43 |
-
{
|
44 |
-
$this->getCloneRecords();
|
45 |
-
}
|
46 |
-
else
|
47 |
-
{
|
48 |
-
$this->clone = (object) $clone;
|
49 |
-
$this->forceDeleteDirectories = true;
|
50 |
-
}
|
51 |
-
|
52 |
-
$this->getTableRecords();
|
53 |
-
}
|
54 |
-
|
55 |
-
/**
|
56 |
-
* Get clone
|
57 |
-
* @param null|string $name
|
58 |
-
* @throws CloneNotFoundException
|
59 |
-
*/
|
60 |
-
private function getCloneRecords($name = null)
|
61 |
-
{
|
62 |
-
if (null === $name && !isset($_POST["clone"]))
|
63 |
-
{
|
64 |
-
$this->log("Clone name is not set", Logger::TYPE_FATAL);
|
65 |
-
throw new CloneNotFoundException();
|
66 |
-
}
|
67 |
-
|
68 |
-
if (null === $name)
|
69 |
-
{
|
70 |
-
$name = $_POST["clone"];
|
71 |
-
}
|
72 |
-
|
73 |
-
$clones = get_option("wpstg_existing_clones_beta", array());
|
74 |
-
|
75 |
-
if (empty($clones) || !isset($clones[$name]))
|
76 |
-
{
|
77 |
-
$this->log("Couldn't find clone name {$name} or no existing clone", Logger::TYPE_FATAL);
|
78 |
-
throw new CloneNotFoundException();
|
79 |
-
}
|
80 |
-
|
81 |
-
$this->clone = $clones[$name];
|
82 |
-
$this->clone["name"] = $name;
|
83 |
-
$this->clone = (object) $this->clone;
|
84 |
-
|
85 |
-
unset($clones);
|
86 |
-
}
|
87 |
-
|
88 |
-
/**
|
89 |
-
* Get Tables
|
90 |
-
*/
|
91 |
-
private function getTableRecords()
|
92 |
-
{
|
93 |
-
$wpdb = WPStaging::getInstance()->get("wpdb");
|
94 |
-
|
95 |
-
$tables = $wpdb->get_results("SHOW TABLE STATUS LIKE 'wpstg{$this->clone->number}_%'");
|
96 |
-
|
97 |
-
$this->tables = array();
|
98 |
-
|
99 |
-
foreach ($tables as $table)
|
100 |
-
{
|
101 |
-
$this->tables[] = array(
|
102 |
-
"name" => $table->Name,
|
103 |
-
"size" => $this->formatSize(($table->Data_length + $table->Index_length))
|
104 |
-
);
|
105 |
-
}
|
106 |
-
|
107 |
-
$this->tables = json_decode(json_encode($this->tables));
|
108 |
-
}
|
109 |
-
|
110 |
-
/**
|
111 |
-
* @return false
|
112 |
-
*/
|
113 |
-
public function getClone()
|
114 |
-
{
|
115 |
-
return $this->clone;
|
116 |
-
}
|
117 |
-
|
118 |
-
/**
|
119 |
-
* @return null|object
|
120 |
-
*/
|
121 |
-
public function getTables()
|
122 |
-
{
|
123 |
-
return $this->tables;
|
124 |
-
}
|
125 |
-
|
126 |
-
/**
|
127 |
-
* Start Module
|
128 |
-
* @param null|array $clone
|
129 |
-
* @return bool
|
130 |
-
*/
|
131 |
-
public function start($clone = null)
|
132 |
-
{
|
133 |
-
// Set data
|
134 |
-
$this->setData($clone);
|
135 |
-
|
136 |
-
// Get the job first
|
137 |
-
$this->getJob();
|
138 |
-
|
139 |
-
$method = "delete" . ucwords($this->job->current);
|
140 |
-
return $this->{$method}();
|
141 |
-
}
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
/**
|
146 |
-
* Get job data
|
147 |
-
*/
|
148 |
-
private function getJob()
|
149 |
-
{
|
150 |
-
$this->job = $this->cache->get("delete_job_{$this->clone->name}");
|
151 |
-
|
152 |
-
if (null !== $this->job)
|
153 |
-
{
|
154 |
-
return;
|
155 |
-
}
|
156 |
-
|
157 |
-
// Generate JOB
|
158 |
-
$this->job = (object) array(
|
159 |
-
"current" => "tables",
|
160 |
-
"nextDirectoryToDelete" => $this->clone->path
|
161 |
-
);
|
162 |
-
|
163 |
-
$this->cache->save("delete_job_{$this->clone->name}", $this->job);
|
164 |
-
}
|
165 |
-
|
166 |
-
/**
|
167 |
-
* Delete Directories
|
168 |
-
*/
|
169 |
-
// public function deleteDirectory()
|
170 |
-
// {
|
171 |
-
// // No deleting directories or root of this clone is deleted
|
172 |
-
// if ($this->isDirectoryDeletingFinished())
|
173 |
-
// {
|
174 |
-
// $this->job->current = "finish";
|
175 |
-
// $this->updateJob();
|
176 |
-
// return;
|
177 |
-
// }
|
178 |
-
//
|
179 |
-
// $this->processDirectory($this->job->nextDirectoryToDelete);
|
180 |
-
//
|
181 |
-
// return;
|
182 |
-
// }
|
183 |
-
|
184 |
-
public function deleteDirectory(){
|
185 |
-
// Just to make sure the root dir is never deleted!
|
186 |
-
if ($this->clone->path === get_home_path()){
|
187 |
-
$this->log("Fatal Error: Trying to delete root of WP installation!", Logger::TYPE_CRITICAL);
|
188 |
-
return false;
|
189 |
-
}
|
190 |
-
|
191 |
-
$files = glob($this->clone->path . '/*');
|
192 |
-
foreach ($files as $file) {
|
193 |
-
is_dir($file) ? $this->deleteDirectory($file) : unlink($file);
|
194 |
-
}
|
195 |
-
rmdir($path);
|
196 |
-
$this->processDirectory($this->job->nextDirectoryToDelete);
|
197 |
-
return;
|
198 |
-
}
|
199 |
-
|
200 |
-
/**
|
201 |
-
* @return bool
|
202 |
-
*/
|
203 |
-
private function updateJob()
|
204 |
-
{
|
205 |
-
$this->job->nextDirectoryToDelete = trim($this->job->nextDirectoryToDelete);
|
206 |
-
return $this->cache->save("delete_job_{$this->clone->name}", $this->job);
|
207 |
-
}
|
208 |
-
|
209 |
-
/**
|
210 |
-
* @return array
|
211 |
-
*/
|
212 |
-
private function getTablesToRemove()
|
213 |
-
{
|
214 |
-
$tables = $this->getTableNames();
|
215 |
-
|
216 |
-
if (!isset($_POST["excludedTables"]) || !is_array($_POST["excludedTables"]) || empty($_POST["excludedTables"]))
|
217 |
-
{
|
218 |
-
return $tables;
|
219 |
-
}
|
220 |
-
|
221 |
-
return array_diff($tables, $_POST["excludedTables"]);
|
222 |
-
}
|
223 |
-
|
224 |
-
/**
|
225 |
-
* @return array
|
226 |
-
*/
|
227 |
-
private function getTableNames()
|
228 |
-
{
|
229 |
-
return (!is_array($this->tables)) ? array() : array_map(function($value) {
|
230 |
-
return ($value->name);
|
231 |
-
}, $this->tables);
|
232 |
-
}
|
233 |
-
|
234 |
-
/**
|
235 |
-
* Delete Tables
|
236 |
-
*/
|
237 |
-
public function deleteTables()
|
238 |
-
{
|
239 |
-
if ($this->isOverThreshold())
|
240 |
-
{
|
241 |
-
return;
|
242 |
-
}
|
243 |
-
|
244 |
-
$wpdb = WPStaging::getInstance()->get("wpdb");
|
245 |
-
|
246 |
-
foreach ($this->getTablesToRemove() as $table)
|
247 |
-
{
|
248 |
-
// PROTECTION: Never delete any table that beginns with wp prefix of live site
|
249 |
-
if($this->startsWith($table, $wpdb->prefix)){
|
250 |
-
$this->log("Fatal Error: Trying to delete table {$table} of main WP installation!", Logger::TYPE_CRITICAL);
|
251 |
-
return false;
|
252 |
-
} else{
|
253 |
-
$wpdb->query("DROP TABLE {$table}");
|
254 |
-
}
|
255 |
-
}
|
256 |
-
|
257 |
-
// Move on to the next
|
258 |
-
$this->job->current = "directory";
|
259 |
-
$this->updateJob();
|
260 |
-
}
|
261 |
-
|
262 |
-
/**
|
263 |
-
* Check if a strings start with a specific string
|
264 |
-
* @param string $haystack
|
265 |
-
* @param string $needle
|
266 |
-
* @return bool
|
267 |
-
*/
|
268 |
-
protected function startsWith($haystack, $needle)
|
269 |
-
{
|
270 |
-
$length = strlen($needle);
|
271 |
-
return (substr($haystack, 0, $length) === $needle);
|
272 |
-
}
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
/**
|
277 |
-
* @return bool
|
278 |
-
*/
|
279 |
-
public function isDirectoryDeletingFinished()
|
280 |
-
{
|
281 |
-
return (
|
282 |
-
(false === $this->forceDeleteDirectories && (!isset($_POST["deleteDir"]) || '1' !== $_POST["deleteDir"])) ||
|
283 |
-
!is_dir($this->clone->path) || ABSPATH === $this->job->nextDirectoryToDelete
|
284 |
-
);
|
285 |
-
}
|
286 |
-
|
287 |
-
/**
|
288 |
-
* Delete contents of the directory if there are no directories in it and then delete itself
|
289 |
-
* @param string $path
|
290 |
-
* @return mixed
|
291 |
-
*/
|
292 |
-
private function processDirectory($path)
|
293 |
-
{
|
294 |
-
// We hit the limit, stop
|
295 |
-
if ($this->shouldStop($path))
|
296 |
-
{
|
297 |
-
$this->updateJob();
|
298 |
-
return false;
|
299 |
-
}
|
300 |
-
|
301 |
-
$this->totalRecursion++;
|
302 |
-
|
303 |
-
$contents = new \DirectoryIterator($path);
|
304 |
-
|
305 |
-
foreach ($contents as $content)
|
306 |
-
{
|
307 |
-
// Skip dots
|
308 |
-
if ($content->isDot())
|
309 |
-
{
|
310 |
-
continue;
|
311 |
-
}
|
312 |
-
|
313 |
-
// Get into the directory
|
314 |
-
if (!$content->isLink() && $content->isDir())
|
315 |
-
{
|
316 |
-
return $this->processDirectory($content->getRealPath());
|
317 |
-
}
|
318 |
-
|
319 |
-
// Delete file
|
320 |
-
if ($content->isFile())
|
321 |
-
{
|
322 |
-
@unlink($content->getRealPath());
|
323 |
-
}
|
324 |
-
}
|
325 |
-
|
326 |
-
// Delete directory
|
327 |
-
$this->job->lastDeletedDirectory = realpath($path . "/..");
|
328 |
-
@rmdir($path);
|
329 |
-
$this->updateJob();
|
330 |
-
$this->processDirectory($this->job->nextDirectoryToDelete);
|
331 |
-
}
|
332 |
-
|
333 |
-
/**
|
334 |
-
* @param string $path
|
335 |
-
* @return bool
|
336 |
-
*/
|
337 |
-
private function shouldStop($path)
|
338 |
-
{
|
339 |
-
// Just to make sure the root dir is never deleted!
|
340 |
-
if ($path === get_home_path()){
|
341 |
-
$this->log("Fatal Error: Trying to delete root of WP installation!", Logger::TYPE_CRITICAL);
|
342 |
-
return true;
|
343 |
-
}
|
344 |
-
|
345 |
-
// Check if threshold is reached and is valid dir
|
346 |
-
return (
|
347 |
-
$this->isOverThreshold() ||
|
348 |
-
!is_dir($path) ||
|
349 |
-
$this->isDirectoryDeletingFinished()
|
350 |
-
);
|
351 |
-
}
|
352 |
-
|
353 |
-
/**
|
354 |
-
* Finish / Update Existing Clones
|
355 |
-
*/
|
356 |
-
public function deleteFinish()
|
357 |
-
{
|
358 |
-
$existingClones = get_option("wpstg_existing_clones_beta", array());
|
359 |
-
|
360 |
-
// Check if clones still exist
|
361 |
-
$this->log("Verifying existing clones...");
|
362 |
-
foreach ($existingClones as $name => $clone)
|
363 |
-
{
|
364 |
-
if (!is_dir($clone["path"]))
|
365 |
-
{
|
366 |
-
unset($existingClones[$name]);
|
367 |
-
}
|
368 |
-
}
|
369 |
-
$this->log("Existing clones verified!");
|
370 |
-
|
371 |
-
if (false === update_option("wpstg_existing_clones_beta", $existingClones))
|
372 |
-
{
|
373 |
-
$this->log("Failed to save {$this->options->clone}'s clone job data to database'");
|
374 |
-
}
|
375 |
-
|
376 |
-
// Delete cached file
|
377 |
-
$this->cache->delete("delete_job_{$this->clone->name}");
|
378 |
-
$this->cache->delete("delete_directories_{$this->clone->name}");
|
379 |
-
|
380 |
-
return true;
|
381 |
-
}
|
382 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
apps/Backend/Modules/Jobs/Delete_old.php
DELETED
@@ -1,367 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WPStaging\Backend\Modules\Jobs;
|
3 |
-
|
4 |
-
use WPStaging\Backend\Modules\Jobs\Exceptions\CloneNotFoundException;
|
5 |
-
use WPStaging\Utils\Directories;
|
6 |
-
use WPStaging\Utils\Logger;
|
7 |
-
use WPStaging\WPStaging;
|
8 |
-
|
9 |
-
/**
|
10 |
-
* Class Delete
|
11 |
-
* @package WPStaging\Backend\Modules\Jobs
|
12 |
-
*/
|
13 |
-
class Delete_old extends Job
|
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 |
-
* Sets Clone and Table Records
|
38 |
-
* @param null|array $clone
|
39 |
-
*/
|
40 |
-
public function setData($clone = null)
|
41 |
-
{
|
42 |
-
if (!is_array($clone))
|
43 |
-
{
|
44 |
-
$this->getCloneRecords();
|
45 |
-
}
|
46 |
-
else
|
47 |
-
{
|
48 |
-
$this->clone = (object) $clone;
|
49 |
-
$this->forceDeleteDirectories = true;
|
50 |
-
}
|
51 |
-
|
52 |
-
$this->getTableRecords();
|
53 |
-
}
|
54 |
-
|
55 |
-
/**
|
56 |
-
* Get clone
|
57 |
-
* @param null|string $name
|
58 |
-
* @throws CloneNotFoundException
|
59 |
-
*/
|
60 |
-
private function getCloneRecords($name = null)
|
61 |
-
{
|
62 |
-
if (null === $name && !isset($_POST["clone"]))
|
63 |
-
{
|
64 |
-
$this->log("Clone name is not set", Logger::TYPE_FATAL);
|
65 |
-
throw new CloneNotFoundException();
|
66 |
-
}
|
67 |
-
|
68 |
-
if (null === $name)
|
69 |
-
{
|
70 |
-
$name = $_POST["clone"];
|
71 |
-
}
|
72 |
-
|
73 |
-
$clones = get_option("wpstg_existing_clones_beta", array());
|
74 |
-
|
75 |
-
if (empty($clones) || !isset($clones[$name]))
|
76 |
-
{
|
77 |
-
$this->log("Couldn't find clone name {$name} or no existing clone", Logger::TYPE_FATAL);
|
78 |
-
throw new CloneNotFoundException();
|
79 |
-
}
|
80 |
-
|
81 |
-
$this->clone = $clones[$name];
|
82 |
-
$this->clone["name"] = $name;
|
83 |
-
$this->clone["size"] = null;
|
84 |
-
|
85 |
-
if (isset($this->settings->checkDirectorySize) || '1' === $this->settings->checkDirectorySize)
|
86 |
-
{
|
87 |
-
$directories = new Directories();
|
88 |
-
$this->clone["size"] = $this->formatSize($directories->size($this->clone));
|
89 |
-
unset($directories);
|
90 |
-
}
|
91 |
-
|
92 |
-
$this->clone = (object) $this->clone;
|
93 |
-
|
94 |
-
unset($clones);
|
95 |
-
}
|
96 |
-
|
97 |
-
/**
|
98 |
-
* Get Tables
|
99 |
-
*/
|
100 |
-
private function getTableRecords()
|
101 |
-
{
|
102 |
-
$wpdb = WPStaging::getInstance()->get("wpdb");
|
103 |
-
$tables = $wpdb->get_results("SHOW TABLE STATUS LIKE 'wpstg{$this->clone->number}_%'");
|
104 |
-
|
105 |
-
$this->tables = array();
|
106 |
-
|
107 |
-
foreach ($tables as $table)
|
108 |
-
{
|
109 |
-
$this->tables[] = array(
|
110 |
-
"name" => $table->Name,
|
111 |
-
"size" => $this->formatSize(($table->Data_length + $table->Index_length))
|
112 |
-
);
|
113 |
-
}
|
114 |
-
|
115 |
-
$this->tables = json_decode(json_encode($this->tables));
|
116 |
-
}
|
117 |
-
|
118 |
-
/**
|
119 |
-
* Format bytes into human readable form
|
120 |
-
* @param int $bytes
|
121 |
-
* @param int $precision
|
122 |
-
* @return string
|
123 |
-
*/
|
124 |
-
public function formatSize($bytes, $precision = 2)
|
125 |
-
{
|
126 |
-
if ((int) $bytes < 1)
|
127 |
-
{
|
128 |
-
return '';
|
129 |
-
}
|
130 |
-
|
131 |
-
$units = array('B', "KB", "MB", "GB", "TB");
|
132 |
-
|
133 |
-
$bytes = (int) $bytes;
|
134 |
-
$base = log($bytes) / log(1000); // 1024 would be for MiB KiB etc
|
135 |
-
$pow = pow(1000, $base - floor($base)); // Same rule for 1000
|
136 |
-
|
137 |
-
return round($pow, $precision) . ' ' . $units[(int) floor($base)];
|
138 |
-
}
|
139 |
-
|
140 |
-
/**
|
141 |
-
* @return false
|
142 |
-
*/
|
143 |
-
public function getClone()
|
144 |
-
{
|
145 |
-
return $this->clone;
|
146 |
-
}
|
147 |
-
|
148 |
-
/**
|
149 |
-
* @return null|object
|
150 |
-
*/
|
151 |
-
public function getTables()
|
152 |
-
{
|
153 |
-
return $this->tables;
|
154 |
-
}
|
155 |
-
|
156 |
-
/**
|
157 |
-
* Start Module
|
158 |
-
* @param null|array $clone
|
159 |
-
* @return bool
|
160 |
-
*/
|
161 |
-
public function start($clone = null)
|
162 |
-
{
|
163 |
-
// Set data
|
164 |
-
$this->setData($clone);
|
165 |
-
|
166 |
-
// Get the job first
|
167 |
-
$this->getJob();
|
168 |
-
|
169 |
-
$method = "delete" . ucwords($this->job->current);
|
170 |
-
return $this->{$method}();
|
171 |
-
}
|
172 |
-
|
173 |
-
/**
|
174 |
-
* Get job data
|
175 |
-
*/
|
176 |
-
private function getJob()
|
177 |
-
{
|
178 |
-
$this->job = $this->cache->get("delete_job_{$this->clone->name}");
|
179 |
-
|
180 |
-
if (null !== $this->job)
|
181 |
-
{
|
182 |
-
return;
|
183 |
-
}
|
184 |
-
|
185 |
-
// Generate JOB
|
186 |
-
$this->job = (object) array(
|
187 |
-
"current" => "tables",
|
188 |
-
"nextDirectoryToDelete" => $this->clone->path
|
189 |
-
);
|
190 |
-
|
191 |
-
$this->cache->save("delete_job_{$this->clone->name}", $this->job);
|
192 |
-
}
|
193 |
-
|
194 |
-
/**
|
195 |
-
* @return bool
|
196 |
-
*/
|
197 |
-
private function updateJob()
|
198 |
-
{
|
199 |
-
$this->job->nextDirectoryToDelete = trim($this->job->nextDirectoryToDelete);
|
200 |
-
return $this->cache->save("delete_job_{$this->clone->name}", $this->job);
|
201 |
-
}
|
202 |
-
|
203 |
-
/**
|
204 |
-
* @return array
|
205 |
-
*/
|
206 |
-
private function getTablesToRemove()
|
207 |
-
{
|
208 |
-
$tables = $this->getTableNames();
|
209 |
-
|
210 |
-
if (!isset($_POST["excludedTables"]) || !is_array($_POST["excludedTables"]) || empty($_POST["excludedTables"]))
|
211 |
-
{
|
212 |
-
return $tables;
|
213 |
-
}
|
214 |
-
|
215 |
-
return array_diff($tables, $_POST["excludedTables"]);
|
216 |
-
}
|
217 |
-
|
218 |
-
/**
|
219 |
-
* @return array
|
220 |
-
*/
|
221 |
-
private function getTableNames()
|
222 |
-
{
|
223 |
-
return (!is_array($this->tables)) ? array() : array_map(function($value) {
|
224 |
-
return ($value->name);
|
225 |
-
}, $this->tables);
|
226 |
-
}
|
227 |
-
|
228 |
-
/**
|
229 |
-
* Delete Tables
|
230 |
-
*/
|
231 |
-
public function deleteTables()
|
232 |
-
{
|
233 |
-
if ($this->isOverThreshold())
|
234 |
-
{
|
235 |
-
return;
|
236 |
-
}
|
237 |
-
|
238 |
-
$wpdb = WPStaging::getInstance()->get("wpdb");
|
239 |
-
|
240 |
-
foreach ($this->getTablesToRemove() as $table)
|
241 |
-
{
|
242 |
-
$wpdb->query("DROP TABLE {$table}");
|
243 |
-
}
|
244 |
-
|
245 |
-
// Move on to the next
|
246 |
-
$this->job->current = "directory";
|
247 |
-
$this->updateJob();
|
248 |
-
}
|
249 |
-
|
250 |
-
/**
|
251 |
-
* Delete Directories
|
252 |
-
*/
|
253 |
-
public function deleteDirectory()
|
254 |
-
{
|
255 |
-
// No deleting directories or root of this clone is deleted
|
256 |
-
if ($this->isDirectoryDeletingFinished())
|
257 |
-
{
|
258 |
-
$this->job->current = "finish";
|
259 |
-
$this->updateJob();
|
260 |
-
return;
|
261 |
-
}
|
262 |
-
|
263 |
-
$this->processDirectory($this->job->nextDirectoryToDelete);
|
264 |
-
|
265 |
-
return;
|
266 |
-
}
|
267 |
-
|
268 |
-
/**
|
269 |
-
* @return bool
|
270 |
-
*/
|
271 |
-
public function isDirectoryDeletingFinished()
|
272 |
-
{
|
273 |
-
return (
|
274 |
-
(false === $this->forceDeleteDirectories && (!isset($_POST["deleteDir"]) || '1' !== $_POST["deleteDir"])) ||
|
275 |
-
!is_dir($this->clone->path) || ABSPATH === $this->job->nextDirectoryToDelete
|
276 |
-
);
|
277 |
-
}
|
278 |
-
|
279 |
-
/**
|
280 |
-
* Delete contents of the directory if there are no directories in it and then delete itself
|
281 |
-
* @param string $path
|
282 |
-
* @return mixed
|
283 |
-
*/
|
284 |
-
private function processDirectory($path)
|
285 |
-
{
|
286 |
-
// We hit the limit, stop
|
287 |
-
if ($this->shouldStop($path))
|
288 |
-
{
|
289 |
-
$this->updateJob();
|
290 |
-
return false;
|
291 |
-
}
|
292 |
-
|
293 |
-
$this->totalRecursion++;
|
294 |
-
|
295 |
-
$contents = new \DirectoryIterator($path);
|
296 |
-
|
297 |
-
foreach ($contents as $content)
|
298 |
-
{
|
299 |
-
// Skip dots
|
300 |
-
if ($content->isDot())
|
301 |
-
{
|
302 |
-
continue;
|
303 |
-
}
|
304 |
-
|
305 |
-
// Get into the directory
|
306 |
-
if (!$content->isLink() && $content->isDir())
|
307 |
-
{
|
308 |
-
return $this->processDirectory($content->getRealPath());
|
309 |
-
}
|
310 |
-
|
311 |
-
// Delete file
|
312 |
-
if ($content->isFile())
|
313 |
-
{
|
314 |
-
@unlink($content->getRealPath());
|
315 |
-
}
|
316 |
-
}
|
317 |
-
|
318 |
-
// Delete directory
|
319 |
-
$this->job->lastDeletedDirectory = realpath($path . "/..");
|
320 |
-
@rmdir($path);
|
321 |
-
$this->updateJob();
|
322 |
-
$this->processDirectory($this->job->nextDirectoryToDelete);
|
323 |
-
}
|
324 |
-
|
325 |
-
/**
|
326 |
-
* @param string $path
|
327 |
-
* @return bool
|
328 |
-
*/
|
329 |
-
private function shouldStop($path)
|
330 |
-
{
|
331 |
-
return (
|
332 |
-
$this->isOverThreshold() ||
|
333 |
-
!is_dir($path) ||
|
334 |
-
$this->isDirectoryDeletingFinished()
|
335 |
-
);
|
336 |
-
}
|
337 |
-
|
338 |
-
/**
|
339 |
-
* Finish / Update Existing Clones
|
340 |
-
*/
|
341 |
-
public function deleteFinish()
|
342 |
-
{
|
343 |
-
$existingClones = get_option("wpstg_existing_clones_beta", array());
|
344 |
-
|
345 |
-
// Check if clones still exist
|
346 |
-
$this->log("Verifying existing clones...");
|
347 |
-
foreach ($existingClones as $name => $clone)
|
348 |
-
{
|
349 |
-
if (!is_dir($clone["path"]))
|
350 |
-
{
|
351 |
-
unset($existingClones[$name]);
|
352 |
-
}
|
353 |
-
}
|
354 |
-
$this->log("Existing clones verified!");
|
355 |
-
|
356 |
-
if (false === update_option("wpstg_existing_clones_beta", $existingClones))
|
357 |
-
{
|
358 |
-
$this->log("Failed to save {$this->options->clone}'s clone job data to database'");
|
359 |
-
}
|
360 |
-
|
361 |
-
// Delete cached file
|
362 |
-
$this->cache->delete("delete_job_{$this->clone->name}");
|
363 |
-
$this->cache->delete("delete_directories_{$this->clone->name}");
|
364 |
-
|
365 |
-
return true;
|
366 |
-
}
|
367 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
apps/Backend/Modules/Jobs/Directories.php
CHANGED
@@ -125,7 +125,6 @@ class Directories extends JobExecutable {
|
|
125 |
|
126 |
if( $this->isOverThreshold() ) {
|
127 |
//$this->saveProgress();
|
128 |
-
|
129 |
return false;
|
130 |
}
|
131 |
|
@@ -172,26 +171,41 @@ class Directories extends JobExecutable {
|
|
172 |
protected function getFilesFromDirectory( $directory ) {
|
173 |
$this->totalRecursion++;
|
174 |
|
175 |
-
//
|
176 |
$files = array_diff( scandir( $directory ), array('.', "..") );
|
177 |
|
178 |
foreach ( $files as $file ) {
|
179 |
$fullPath = $directory . $file;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
180 |
|
|
|
181 |
if( is_dir( $fullPath ) && !in_array( $fullPath, $this->options->directoriesToCopy ) && !$this->isDirectoryExcluded( $fullPath ) ) {
|
182 |
$this->options->directoriesToCopy[] = $fullPath;
|
183 |
|
184 |
-
return $this->getFilesFromSubDirectories( $fullPath );
|
185 |
//continue;
|
186 |
-
|
187 |
-
|
188 |
-
if( !is_file( $fullPath ) || in_array( $fullPath, $this->files ) ) {
|
189 |
continue;
|
190 |
}
|
191 |
|
192 |
-
$this->
|
|
|
|
|
193 |
|
194 |
-
$this->
|
|
|
|
|
195 |
|
196 |
/**
|
197 |
* Test and measure if its faster to copy at the same time while the array with folders is generated
|
@@ -349,5 +363,22 @@ class Directories extends JobExecutable {
|
|
349 |
|
350 |
return $destinationPath;
|
351 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
352 |
|
353 |
}
|
125 |
|
126 |
if( $this->isOverThreshold() ) {
|
127 |
//$this->saveProgress();
|
|
|
128 |
return false;
|
129 |
}
|
130 |
|
171 |
protected function getFilesFromDirectory( $directory ) {
|
172 |
$this->totalRecursion++;
|
173 |
|
174 |
+
// Get only files
|
175 |
$files = array_diff( scandir( $directory ), array('.', "..") );
|
176 |
|
177 |
foreach ( $files as $file ) {
|
178 |
$fullPath = $directory . $file;
|
179 |
+
|
180 |
+
// It's a readable valid file and not excluded for copying
|
181 |
+
if( is_file( $fullPath ) && !$this->isExcluded($file) ) {
|
182 |
+
$this->options->totalFiles++;
|
183 |
+
$this->files[] = $fullPath;
|
184 |
+
continue;
|
185 |
+
}
|
186 |
+
// It's a valid file but not readable
|
187 |
+
if( is_file( $fullPath ) && !is_readable( $fullPath ) ) {
|
188 |
+
$this->debugLog('File {$fullPath} is not readable', Logger::TYPE_DEBUG );
|
189 |
+
continue;
|
190 |
+
}
|
191 |
|
192 |
+
// Iterate and loop through if it's a directory and if it's not excluded
|
193 |
if( is_dir( $fullPath ) && !in_array( $fullPath, $this->options->directoriesToCopy ) && !$this->isDirectoryExcluded( $fullPath ) ) {
|
194 |
$this->options->directoriesToCopy[] = $fullPath;
|
195 |
|
196 |
+
//return $this->getFilesFromSubDirectories( $fullPath );
|
197 |
//continue;
|
198 |
+
$this->getFilesFromSubDirectories( $fullPath );
|
|
|
|
|
199 |
continue;
|
200 |
}
|
201 |
|
202 |
+
// if( !is_file( $fullPath ) || in_array( $fullPath, $this->files ) ) {
|
203 |
+
// continue;
|
204 |
+
// }
|
205 |
|
206 |
+
// $this->options->totalFiles++;
|
207 |
+
//
|
208 |
+
// $this->files[] = $fullPath;
|
209 |
|
210 |
/**
|
211 |
* Test and measure if its faster to copy at the same time while the array with folders is generated
|
363 |
|
364 |
return $destinationPath;
|
365 |
}
|
366 |
+
|
367 |
+
/**
|
368 |
+
* Check if filename is excluded for cloning process
|
369 |
+
*
|
370 |
+
* @param string $file filename including ending
|
371 |
+
* @return boolean
|
372 |
+
*/
|
373 |
+
private function isExcluded( $file ) {
|
374 |
+
$excluded = false;
|
375 |
+
foreach ( $this->options->excludedFiles as $excludedFile ) {
|
376 |
+
if (stripos(strrev($file), strrev($excludedFile)) === 0) {
|
377 |
+
$excluded = true;
|
378 |
+
break;
|
379 |
+
}
|
380 |
+
}
|
381 |
+
return $excluded;
|
382 |
+
}
|
383 |
|
384 |
}
|
apps/Backend/Modules/SystemInfo.php
CHANGED
@@ -22,6 +22,7 @@ class SystemInfo extends InjectionAware
|
|
22 |
* @var bool
|
23 |
*/
|
24 |
private $isMultiSite;
|
|
|
25 |
|
26 |
/**
|
27 |
* Initialize class
|
@@ -48,6 +49,8 @@ class SystemInfo extends InjectionAware
|
|
48 |
{
|
49 |
$output = "### Begin System Info ###" . PHP_EOL . PHP_EOL;
|
50 |
|
|
|
|
|
51 |
$output .= $this->site();
|
52 |
|
53 |
$output .= $this->browser();
|
@@ -68,6 +71,8 @@ class SystemInfo extends InjectionAware
|
|
68 |
|
69 |
return $output;
|
70 |
}
|
|
|
|
|
71 |
|
72 |
/**
|
73 |
* @param string $string
|
@@ -86,7 +91,7 @@ class SystemInfo extends InjectionAware
|
|
86 |
*/
|
87 |
public function info($title, $value)
|
88 |
{
|
89 |
-
return str_pad($title,
|
90 |
}
|
91 |
|
92 |
/**
|
@@ -121,8 +126,55 @@ class SystemInfo extends InjectionAware
|
|
121 |
|
122 |
return apply_filters("wpstg_sysinfo_after_site_info", $output);
|
123 |
}
|
124 |
-
|
125 |
/**
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
126 |
* Browser Information
|
127 |
* @return string
|
128 |
*/
|
22 |
* @var bool
|
23 |
*/
|
24 |
private $isMultiSite;
|
25 |
+
|
26 |
|
27 |
/**
|
28 |
* Initialize class
|
49 |
{
|
50 |
$output = "### Begin System Info ###" . PHP_EOL . PHP_EOL;
|
51 |
|
52 |
+
$output .= $this->wpstaging();
|
53 |
+
|
54 |
$output .= $this->site();
|
55 |
|
56 |
$output .= $this->browser();
|
71 |
|
72 |
return $output;
|
73 |
}
|
74 |
+
|
75 |
+
|
76 |
|
77 |
/**
|
78 |
* @param string $string
|
91 |
*/
|
92 |
public function info($title, $value)
|
93 |
{
|
94 |
+
return str_pad($title, 56, ' ', STR_PAD_RIGHT) . $value . PHP_EOL;
|
95 |
}
|
96 |
|
97 |
/**
|
126 |
|
127 |
return apply_filters("wpstg_sysinfo_after_site_info", $output);
|
128 |
}
|
129 |
+
|
130 |
/**
|
131 |
+
* Wp Staging plugin Information
|
132 |
+
* @return string
|
133 |
+
*/
|
134 |
+
public function wpstaging() {
|
135 |
+
// Get wpstg settings
|
136 |
+
$settings = ( object ) get_option( 'wpstg_settings', array() );
|
137 |
+
|
138 |
+
// Clones data < 1.6.x
|
139 |
+
$clones = ( object ) get_option( 'wpstg_existing_clones', array() );
|
140 |
+
// Clones data version > 2.x
|
141 |
+
$clonesBeta = get_option( 'wpstg_existing_clones_beta' );
|
142 |
+
|
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' );
|
149 |
+
|
150 |
+
$output .= PHP_EOL . PHP_EOL . "-- Available Sites Version < 1.6.x" . PHP_EOL . PHP_EOL;
|
151 |
+
|
152 |
+
$i = 1;
|
153 |
+
foreach ( $clones as $key => $value ) {
|
154 |
+
$output .= $this->info( "Site name & subfolder :", $value );
|
155 |
+
}
|
156 |
+
$output .= PHP_EOL . PHP_EOL . "-- Available Sites Version > 2.0.x" . PHP_EOL . PHP_EOL;
|
157 |
+
|
158 |
+
foreach ( $clonesBeta as $key => $clone ) {
|
159 |
+
$output .= $this->info( "Number:", isset( $clone['number'] ) ? $clone['number'] : 'undefined' );
|
160 |
+
$output .= $this->info( "directoryName:", isset( $clone['directoryName'] ) ? $clone['directoryName'] : 'undefined' );
|
161 |
+
$output .= $this->info( "Path:", isset( $clone['path'] ) ? $clone['path'] : 'undefined' );
|
162 |
+
$output .= $this->info( "URL:", isset( $clone['url'] ) ? $clone['url'] : 'undefined' );
|
163 |
+
$output .= $this->info( "Version:", isset( $clone['version'] ) ? $clone['version'] : 'undefined' ) . PHP_EOL . PHP_EOL;
|
164 |
+
}
|
165 |
+
|
166 |
+
//$output .= PHP_EOL . PHP_EOL;
|
167 |
+
|
168 |
+
$output .= $this->info( "Plugin Version:", get_option('wpstg_version', 'undefined') );
|
169 |
+
$output .= $this->info( "Install Date:", get_option('wpstg_installDate', 'undefined') );
|
170 |
+
$output .= $this->info( "Upgraded from:", get_option('wpstg_version_upgraded_from', 'undefined') );
|
171 |
+
$output .= $this->info( "Is Staging Site:", get_option('wpstg_is_staging_site', 'undefined') ) . PHP_EOL . PHP_EOL;
|
172 |
+
|
173 |
+
|
174 |
+
return apply_filters( "wpstg_sysinfo_after_wpstaging_info", $output );
|
175 |
+
}
|
176 |
+
|
177 |
+
/**
|
178 |
* Browser Information
|
179 |
* @return string
|
180 |
*/
|
apps/Backend/public/css/wpstg-admin.css
CHANGED
@@ -642,7 +642,7 @@ color:#777777;
|
|
642 |
}
|
643 |
|
644 |
.wpstg-sysinfo {
|
645 |
-
width:
|
646 |
height: 500px;
|
647 |
}
|
648 |
|
642 |
}
|
643 |
|
644 |
.wpstg-sysinfo {
|
645 |
+
width:700px;
|
646 |
height: 500px;
|
647 |
}
|
648 |
|
apps/Backend/public/js/wpstg-admin.js
CHANGED
@@ -322,7 +322,7 @@ var WPStaging = (function ($)
|
|
322 |
|
323 |
showError(
|
324 |
"Fatal Unknown Error. This should not happen." +
|
325 |
-
"
|
326 |
"<a href='https://wordpress.org/support/plugin/wp-staging' target='_blank'>Open a ticket</a> " +
|
327 |
"in the WP Staging support forum."
|
328 |
);
|
322 |
|
323 |
showError(
|
324 |
"Fatal Unknown Error. This should not happen." +
|
325 |
+
"Plese try again. If this does not help, " +
|
326 |
"<a href='https://wordpress.org/support/plugin/wp-staging' target='_blank'>Open a ticket</a> " +
|
327 |
"in the WP Staging support forum."
|
328 |
);
|
apps/Backend/views/clone/ajax/start.php
CHANGED
@@ -42,12 +42,18 @@
|
|
42 |
<h3>Congratulations
|
43 |
</h3>
|
44 |
<?php
|
45 |
-
|
|
|
|
|
46 |
?>
|
47 |
<br>
|
48 |
<?php //echo __('Open and access the staging site: ', 'wpstg')?>
|
49 |
<br>
|
50 |
-
|
|
|
|
|
|
|
|
|
51 |
Open staging site <span style="font-size: 10px;">(login with your admin credentials)</span>
|
52 |
</a>
|
53 |
<!--<a href="" class="wpstg-link-btn button-primary" id="wpstg-remove-cloning">
|
42 |
<h3>Congratulations
|
43 |
</h3>
|
44 |
<?php
|
45 |
+
$subDirectory = str_replace( get_home_path(), '', ABSPATH );
|
46 |
+
$url = get_home_url() . '/' . str_replace('/', '', $subDirectory);
|
47 |
+
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 );
|
48 |
?>
|
49 |
<br>
|
50 |
<?php //echo __('Open and access the staging site: ', 'wpstg')?>
|
51 |
<br>
|
52 |
+
<?php
|
53 |
+
$subDirectory = str_replace( get_home_path(), '', ABSPATH );
|
54 |
+
$url = get_home_url() . $subDirectory;
|
55 |
+
?>
|
56 |
+
<a href="<?php echo $url; ?>" id="wpstg-clone-url" target="_blank" class="wpstg-link-btn button-primary">
|
57 |
Open staging site <span style="font-size: 10px;">(login with your admin credentials)</span>
|
58 |
</a>
|
59 |
<!--<a href="" class="wpstg-link-btn button-primary" id="wpstg-remove-cloning">
|
apps/Core/DTO/Settings.php
CHANGED
@@ -65,14 +65,15 @@ class Settings
|
|
65 |
/**
|
66 |
* Settings constructor.
|
67 |
*/
|
68 |
-
public function __construct()
|
69 |
-
|
70 |
-
$this->_raw = get_option("wpstg_settings", array());
|
71 |
|
72 |
-
|
73 |
-
|
|
|
|
|
74 |
|
75 |
-
|
76 |
* @param array $settings
|
77 |
* @return $this
|
78 |
*/
|
@@ -94,22 +95,19 @@ class Settings
|
|
94 |
/**
|
95 |
* @return bool
|
96 |
*/
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
return update_option("wpstg_settings", $data);
|
112 |
-
}
|
113 |
|
114 |
/**
|
115 |
* @return array
|
65 |
/**
|
66 |
* Settings constructor.
|
67 |
*/
|
68 |
+
public function __construct() {
|
69 |
+
$this->_raw = get_option( "wpstg_settings", array() );
|
|
|
70 |
|
71 |
+
if( !empty( $this->_raw ) ) {
|
72 |
+
$this->hydrate( $this->_raw );
|
73 |
+
}
|
74 |
+
}
|
75 |
|
76 |
+
/**
|
77 |
* @param array $settings
|
78 |
* @return $this
|
79 |
*/
|
95 |
/**
|
96 |
* @return bool
|
97 |
*/
|
98 |
+
// public function save() {
|
99 |
+
// $data = array();
|
100 |
+
//
|
101 |
+
// foreach ( get_object_vars( $this ) as $key => $value ) {
|
102 |
+
// if( 0 == strpos( $key, '_' ) ) {
|
103 |
+
// continue;
|
104 |
+
// }
|
105 |
+
//
|
106 |
+
// $data[$key] = $value;
|
107 |
+
// }
|
108 |
+
//
|
109 |
+
// return update_option( "wpstg_settings", $data );
|
110 |
+
// }
|
|
|
|
|
|
|
111 |
|
112 |
/**
|
113 |
* @return array
|
apps/Core/WPStaging.php
CHANGED
@@ -29,7 +29,7 @@ final class WPStaging {
|
|
29 |
/**
|
30 |
* Plugin version
|
31 |
*/
|
32 |
-
const VERSION = "2.0.
|
33 |
|
34 |
/**
|
35 |
* Plugin name
|
@@ -44,7 +44,7 @@ final class WPStaging {
|
|
44 |
/**
|
45 |
* Compatible WP Version
|
46 |
*/
|
47 |
-
const WP_COMPATIBLE = "4.8";
|
48 |
|
49 |
/**
|
50 |
* Slug: Either wp-staging or wp-staging-pro
|
29 |
/**
|
30 |
* Plugin version
|
31 |
*/
|
32 |
+
const VERSION = "2.0.9";
|
33 |
|
34 |
/**
|
35 |
* Plugin name
|
44 |
/**
|
45 |
* Compatible WP Version
|
46 |
*/
|
47 |
+
const WP_COMPATIBLE = "4.8.4";
|
48 |
|
49 |
/**
|
50 |
* Slug: Either wp-staging or wp-staging-pro
|
readme.txt
CHANGED
@@ -9,7 +9,7 @@ License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
|
9 |
Tags: staging, duplication, cloning, clone, migration, sandbox, test site, testing, backup, post, admin, administration, duplicate posts
|
10 |
Requires at least: 3.6+
|
11 |
Tested up to: 4.8
|
12 |
-
Stable tag: 2.0.
|
13 |
|
14 |
A duplicator plugin! Clone, duplicate and migrate live sites to independent staging and development sites that are available only to administrators.
|
15 |
|
@@ -141,6 +141,13 @@ https://wp-staging.com
|
|
141 |
|
142 |
|
143 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
144 |
= 2.0.8 =
|
145 |
* 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
|
146 |
|
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.0.9
|
13 |
|
14 |
A duplicator plugin! Clone, duplicate and migrate live sites to independent staging and development sites that are available only to administrators.
|
15 |
|
141 |
|
142 |
|
143 |
|
144 |
+
= 2.0.9 =
|
145 |
+
* New: Exclude unneccessary files from cloning process: .tmp, .log, .htaccess, .git, .gitignore, desktop.ini, .DS_Store, .svn
|
146 |
+
* New: More details for debugging in Tools->System Info
|
147 |
+
* Fix: Check if tables in staging site exists before attempting to modify them
|
148 |
+
* Fix: WordPress in sub directories were not opening
|
149 |
+
* Tweak: Exclude wp-content/cache folder from copying process
|
150 |
+
|
151 |
= 2.0.8 =
|
152 |
* 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
|
153 |
|
wp-staging.php
CHANGED
@@ -6,7 +6,7 @@
|
|
6 |
* Description: Create a staging clone site for testing & developing
|
7 |
* Author: WP-Staging, René Hermenau, Ilgıt Yıldırım
|
8 |
* Author URI: https://wordpress.org/plugins/wp-staging
|
9 |
-
* Version: 2.0.
|
10 |
* Text Domain: wpstg
|
11 |
* Domain Path: /languages/
|
12 |
|
6 |
* Description: Create a staging clone site for testing & developing
|
7 |
* Author: WP-Staging, René Hermenau, Ilgıt Yıldırım
|
8 |
* Author URI: https://wordpress.org/plugins/wp-staging
|
9 |
+
* Version: 2.0.9
|
10 |
* Text Domain: wpstg
|
11 |
* Domain Path: /languages/
|
12 |
|