Version Description
- New: Add new db table selection manager
- Fix: Better warning notices before updating a staging site
- Fix: Stop delete process if staging site has been deleted manually before
- Fix: Log file folder does not have correct permission 0755
- Fix: Continue cloning if siteurl & home in wp_options could not be changed
- Tweak: Better warning for update method
- Tweak: DB tables and file verification opened as default option
- Tweak: Skip rows larger than 5MB for search & replace operations to keep memory consumption low
- Tweak: clean up search & replace method
- Tweak: Better FAQ
Download this release
Release Info
Developer | ReneHermi |
Plugin | WP Staging – DB & File Duplicator & Migration |
Version | 2.4.9 |
Comparing to | |
See all releases |
Code changes from version 2.4.8 to 2.4.9
- apps/Backend/Modules/Jobs/Data.php +2 -2
- apps/Backend/Modules/Jobs/Delete.php +453 -452
- apps/Backend/Modules/Jobs/Multisite/Data.php +1 -1
- apps/Backend/Modules/Jobs/Multisite/DataExternal.php +1 -1
- apps/Backend/Modules/Jobs/Multisite/SearchReplace.php +6 -41
- apps/Backend/Modules/Jobs/Multisite/SearchReplaceExternal.php +6 -36
- apps/Backend/Modules/Jobs/Scan.php +0 -5
- apps/Backend/Modules/Jobs/SearchReplace.php +14 -1
- apps/Backend/public/css/wpstg-admin.css +10 -0
- apps/Backend/public/js/wpstg-admin.js +73 -22
- apps/Backend/views/clone/ajax/delete-confirmation.php +1 -1
- apps/Backend/views/clone/ajax/scan.php +33 -12
- apps/Backend/views/clone/includes/footer.php +1 -0
- apps/Core/Utils/Logger.php +1 -1
- apps/Core/WPStaging.php +1 -1
- readme.txt +17 -3
- wp-staging.php +2 -2
apps/Backend/Modules/Jobs/Data.php
CHANGED
@@ -273,8 +273,8 @@ class Data extends JobExecutable {
|
|
273 |
return true;
|
274 |
}
|
275 |
|
276 |
-
$this->log( "Preparing Data Step1: Failed to update siteurl and homeurl in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_ERROR );
|
277 |
-
return
|
278 |
}
|
279 |
|
280 |
/**
|
273 |
return true;
|
274 |
}
|
275 |
|
276 |
+
$this->log( "Preparing Data Step1: Failed to update siteurl and homeurl in {$this->prefix}options. Probably already did! {$this->db->last_error}", Logger::TYPE_ERROR );
|
277 |
+
return true;
|
278 |
}
|
279 |
|
280 |
/**
|
apps/Backend/Modules/Jobs/Delete.php
CHANGED
@@ -13,461 +13,462 @@ use WPStaging\WPStaging;
|
|
13 |
*/
|
14 |
class Delete extends Job {
|
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 |
-
if( false === ($content = @file_get_contents( $path )) ) {
|
174 |
-
$this->log( "Can not open {$path}. Can't read contents", Logger::TYPE_ERROR );
|
175 |
-
} else {
|
176 |
-
// Try to get prefix from wp-config.php
|
177 |
-
preg_match( "/table_prefix\s*=\s*'(\w*)';/", $content, $matches );
|
178 |
-
|
179 |
-
if( !empty( $matches[1] ) ) {
|
180 |
-
$this->clone->prefix = $matches[1];
|
181 |
} else {
|
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 |
-
|
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 |
-
if( $this->isOverThreshold() ) {
|
367 |
-
//$this->returnException('Maximum PHP execution time exceeded. Run again and repeat the deletion process until it is sucessfully finished.');
|
368 |
-
return;
|
369 |
-
}
|
370 |
-
|
371 |
-
$di = new \RecursiveDirectoryIterator( $this->clone->path, \FilesystemIterator::SKIP_DOTS );
|
372 |
-
$ri = new \RecursiveIteratorIterator( $di, \RecursiveIteratorIterator::CHILD_FIRST );
|
373 |
-
foreach ( $ri as $file ) {
|
374 |
-
//$file->isDir() ? @rmdir($file) : unlink($file);
|
375 |
-
$this->deleteFile( $file );
|
376 |
-
if( $this->isOverThreshold() ) {
|
377 |
//$this->returnException('Maximum PHP execution time exceeded. Run again and repeat the deletion process until it is sucessfully finished.');
|
378 |
return;
|
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 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
472 |
|
473 |
}
|
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 |
+
/**
|
43 |
+
*
|
44 |
+
* @var bool
|
45 |
+
*/
|
46 |
+
private $isExternal;
|
47 |
+
|
48 |
+
public function __construct( $isExternal = false ) {
|
49 |
+
parent::__construct();
|
50 |
+
$this->isExternal = $isExternal;
|
51 |
+
}
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Sets Clone and Table Records
|
55 |
+
* @param null|array $clone
|
56 |
+
*/
|
57 |
+
public function setData( $clone = null ) {
|
58 |
+
if( !is_array( $clone ) ) {
|
59 |
+
$this->getCloneRecords();
|
60 |
+
} else {
|
61 |
+
$this->clone = ( object ) $clone;
|
62 |
+
$this->forceDeleteDirectories = true;
|
63 |
+
}
|
64 |
+
|
65 |
+
if( $this->isExternalDatabase() ) {
|
66 |
+
$this->wpdb = $this->getStagingDb();
|
67 |
+
} else {
|
68 |
+
$this->wpdb = WPStaging::getInstance()->get( "wpdb" );
|
69 |
+
}
|
70 |
+
|
71 |
+
$this->getTableRecords();
|
72 |
+
}
|
73 |
+
|
74 |
+
/**
|
75 |
+
* Get database object to interact with
|
76 |
+
*/
|
77 |
+
private function getStagingDb() {
|
78 |
+
return new \wpdb( $this->clone->databaseUser, $this->clone->databasePassword, $this->clone->databaseDatabase, $this->clone->databaseServer );
|
79 |
+
}
|
80 |
+
|
81 |
+
/**
|
82 |
+
* Date database name
|
83 |
+
* @return type
|
84 |
+
*/
|
85 |
+
public function getDbName() {
|
86 |
+
return $this->wpdb->dbname;
|
87 |
+
}
|
88 |
+
|
89 |
+
/**
|
90 |
+
* Check if external database is used
|
91 |
+
* @return boolean
|
92 |
+
*/
|
93 |
+
private function isExternalDatabase() {
|
94 |
+
if( $this->isExternal ) {
|
95 |
+
return true;
|
96 |
+
}
|
97 |
+
|
98 |
+
if( !empty( $this->clone->databaseUser ) ) {
|
99 |
+
return true;
|
100 |
+
}
|
101 |
+
return false;
|
102 |
+
}
|
103 |
+
|
104 |
+
/**
|
105 |
+
* Get clone
|
106 |
+
* @param null|string $name
|
107 |
+
* @throws CloneNotFoundException
|
108 |
+
*/
|
109 |
+
private function getCloneRecords( $name = null ) {
|
110 |
+
if( null === $name && !isset( $_POST["clone"] ) ) {
|
111 |
+
$this->log( "Clone name is not set", Logger::TYPE_FATAL );
|
112 |
+
//throw new CloneNotFoundException();
|
113 |
+
$this->returnException( "Clone name is not set" );
|
114 |
+
}
|
115 |
+
|
116 |
+
if( null === $name ) {
|
117 |
+
$name = $_POST["clone"];
|
118 |
+
}
|
119 |
+
|
120 |
+
$clones = get_option( "wpstg_existing_clones_beta", array() );
|
121 |
+
|
122 |
+
if( empty( $clones ) || !isset( $clones[$name] ) ) {
|
123 |
+
$this->log( "Couldn't find clone name {$name} or no existing clone", Logger::TYPE_FATAL );
|
124 |
+
//throw new CloneNotFoundException();
|
125 |
+
$this->returnException( "Couldn't find clone name {$name} or no existing clone" );
|
126 |
+
}
|
127 |
+
|
128 |
+
$this->clone = $clones[$name];
|
129 |
+
$this->clone["name"] = $name;
|
130 |
+
|
131 |
+
$this->clone = ( object ) $this->clone;
|
132 |
+
|
133 |
+
unset( $clones );
|
134 |
+
}
|
135 |
+
|
136 |
+
/**
|
137 |
+
* Get Tables
|
138 |
+
*/
|
139 |
+
private function getTableRecords() {
|
140 |
+
|
141 |
+
$stagingPrefix = $this->getStagingPrefix();
|
142 |
+
|
143 |
+
$tables = $this->wpdb->get_results( "SHOW TABLE STATUS LIKE '{$stagingPrefix}%'" );
|
144 |
+
|
145 |
+
$this->tables = array();
|
146 |
+
|
147 |
+
foreach ( $tables as $table ) {
|
148 |
+
$this->tables[] = array(
|
149 |
+
"name" => $table->Name,
|
150 |
+
"size" => $this->formatSize( ($table->Data_length + $table->Index_length ) )
|
151 |
+
);
|
152 |
+
}
|
153 |
+
|
154 |
+
$this->tables = json_decode( json_encode( $this->tables ) );
|
155 |
+
}
|
156 |
+
|
157 |
+
/**
|
158 |
+
* Check and return prefix of the staging site
|
159 |
+
*/
|
160 |
+
public function getStagingPrefix() {
|
161 |
+
|
162 |
+
if( $this->isExternalDatabase() && !empty( $this->clone->prefix ) ) {
|
163 |
+
return $this->clone->prefix;
|
164 |
+
}
|
165 |
+
|
166 |
+
// Prefix not defined! Happens if staging site has been generated with older version of wpstg
|
167 |
+
// Try to get staging prefix from wp-config.php of staging site
|
168 |
+
if( empty( $this->clone->prefix ) ) {
|
169 |
+
// Throw error
|
170 |
+
$path = ABSPATH . $this->clone->directoryName . "/wp-config.php";
|
171 |
+
if( false === ($content = @file_get_contents( $path )) ) {
|
172 |
+
$this->log( "Can not open {$path}. Can't read contents", Logger::TYPE_ERROR );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
173 |
} else {
|
174 |
+
// Try to get prefix from wp-config.php
|
175 |
+
preg_match( "/table_prefix\s*=\s*'(\w*)';/", $content, $matches );
|
176 |
+
|
177 |
+
if( !empty( $matches[1] ) ) {
|
178 |
+
$this->clone->prefix = $matches[1];
|
179 |
+
} else {
|
180 |
+
$this->returnException( "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" );
|
181 |
+
}
|
182 |
}
|
183 |
+
}
|
184 |
+
|
185 |
+
if( empty( $this->clone->prefix ) ) {
|
186 |
+
$this->returnException( "Fatal Error: Can not delete staging site. Can not find table prefix. Contact support@wp-staging.com" );
|
187 |
+
}
|
188 |
+
|
189 |
+
// Check if staging prefix is the same as the live prefix
|
190 |
+
if( empty( $this->options->databaseUser ) && $this->wpdb->prefix == $this->clone->prefix ) {
|
191 |
+
$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" );
|
192 |
+
$this->returnException( "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" );
|
193 |
+
}
|
194 |
+
|
195 |
+
// Else
|
196 |
+
return $this->clone->prefix;
|
197 |
+
}
|
198 |
+
|
199 |
+
/**
|
200 |
+
* Format bytes into human readable form
|
201 |
+
* @param int $bytes
|
202 |
+
* @param int $precision
|
203 |
+
* @return string
|
204 |
+
*/
|
205 |
+
public function formatSize( $bytes, $precision = 2 ) {
|
206 |
+
if( ( int ) $bytes < 1 ) {
|
207 |
+
return '';
|
208 |
+
}
|
209 |
+
|
210 |
+
$units = array('B', "KB", "MB", "GB", "TB");
|
211 |
+
|
212 |
+
$bytes = ( int ) $bytes;
|
213 |
+
$base = log( $bytes ) / log( 1000 ); // 1024 would be for MiB KiB etc
|
214 |
+
$pow = pow( 1000, $base - floor( $base ) ); // Same rule for 1000
|
215 |
+
|
216 |
+
return round( $pow, $precision ) . ' ' . $units[( int ) floor( $base )];
|
217 |
+
}
|
218 |
+
|
219 |
+
/**
|
220 |
+
* @return false
|
221 |
+
*/
|
222 |
+
public function getClone() {
|
223 |
+
return $this->clone;
|
224 |
+
}
|
225 |
+
|
226 |
+
/**
|
227 |
+
* @return null|object
|
228 |
+
*/
|
229 |
+
public function getTables() {
|
230 |
+
return $this->tables;
|
231 |
+
}
|
232 |
+
|
233 |
+
/**
|
234 |
+
* Start Module
|
235 |
+
* @param null|array $clone
|
236 |
+
* @return bool
|
237 |
+
*/
|
238 |
+
public function start( $clone = null ) {
|
239 |
+
// Set data
|
240 |
+
$this->setData( $clone );
|
241 |
+
|
242 |
+
// Get the job first
|
243 |
+
$this->getJob();
|
244 |
+
|
245 |
+
$method = "delete" . ucwords( $this->job->current );
|
246 |
+
return $this->{$method}();
|
247 |
+
}
|
248 |
+
|
249 |
+
/**
|
250 |
+
* Get job data
|
251 |
+
*/
|
252 |
+
private function getJob() {
|
253 |
+
$this->job = $this->cache->get( "delete_job_{$this->clone->name}" );
|
254 |
+
|
255 |
+
|
256 |
+
if( null !== $this->job ) {
|
257 |
+
return;
|
258 |
+
}
|
259 |
+
|
260 |
+
// Generate JOB
|
261 |
+
$this->job = ( object ) array(
|
262 |
+
"current" => "tables",
|
263 |
+
"nextDirectoryToDelete" => $this->clone->path,
|
264 |
+
"name" => $this->clone->name
|
265 |
+
);
|
266 |
+
|
267 |
+
$this->cache->save( "delete_job_{$this->clone->name}", $this->job );
|
268 |
+
}
|
269 |
+
|
270 |
+
/**
|
271 |
+
* @return bool
|
272 |
+
*/
|
273 |
+
private function updateJob() {
|
274 |
+
$this->job->nextDirectoryToDelete = trim( $this->job->nextDirectoryToDelete );
|
275 |
+
return $this->cache->save( "delete_job_{$this->clone->name}", $this->job );
|
276 |
+
}
|
277 |
+
|
278 |
+
/**
|
279 |
+
* @return array
|
280 |
+
*/
|
281 |
+
private function getTablesToRemove() {
|
282 |
+
$tables = $this->getTableNames();
|
283 |
+
|
284 |
+
if( !isset( $_POST["excludedTables"] ) || !is_array( $_POST["excludedTables"] ) || empty( $_POST["excludedTables"] ) ) {
|
285 |
+
return $tables;
|
286 |
+
}
|
287 |
+
|
288 |
+
return array_diff( $tables, $_POST["excludedTables"] );
|
289 |
+
}
|
290 |
+
|
291 |
+
/**
|
292 |
+
* @return array
|
293 |
+
*/
|
294 |
+
private function getTableNames() {
|
295 |
+
return (!is_array( $this->tables )) ? array() : array_map( function($value) {
|
296 |
+
return ($value->name);
|
297 |
+
}, $this->tables );
|
298 |
+
}
|
299 |
+
|
300 |
+
/**
|
301 |
+
* Delete Tables
|
302 |
+
*/
|
303 |
+
public function deleteTables() {
|
304 |
+
if( $this->isOverThreshold() ) {
|
305 |
+
return;
|
306 |
+
}
|
307 |
+
|
308 |
+
foreach ( $this->getTablesToRemove() as $table ) {
|
309 |
+
// PROTECTION: Never delete any table that beginns with wp prefix of live site
|
310 |
+
if( !$this->isExternalDatabase() && $this->startsWith( $table, $this->wpdb->prefix ) ) {
|
311 |
+
$this->log( "Fatal Error: Trying to delete table {$table} of main WP installation!", Logger::TYPE_CRITICAL );
|
312 |
+
return false;
|
313 |
+
} else {
|
314 |
+
$this->wpdb->query( "DROP TABLE {$table}" );
|
315 |
+
}
|
316 |
+
}
|
317 |
+
|
318 |
+
// Move on to the next
|
319 |
+
$this->job->current = "directory";
|
320 |
+
$this->updateJob();
|
321 |
+
}
|
322 |
+
|
323 |
+
/**
|
324 |
+
* Check if a strings start with a specific string
|
325 |
+
* @param string $haystack
|
326 |
+
* @param string $needle
|
327 |
+
* @return bool
|
328 |
+
*/
|
329 |
+
protected function startsWith( $haystack, $needle ) {
|
330 |
+
$length = strlen( $needle );
|
331 |
+
return (substr( $haystack, 0, $length ) === $needle);
|
332 |
+
}
|
333 |
+
|
334 |
+
/**
|
335 |
+
* Delete complete directory including all files and subfolders
|
336 |
+
*
|
337 |
+
* @throws InvalidArgumentException
|
338 |
+
*/
|
339 |
+
public function deleteDirectory() {
|
340 |
+
if( $this->isFatalError() ) {
|
341 |
+
$this->returnException( 'Can not delete directory: ' . $this->clone->path . '. This seems to be the root directory. Please contact support@wp-staging.com' );
|
342 |
+
throw new \Exception( 'Can not delete directory: ' . $this->clone->path . ' This seems to be the root directory. Please contact support@wp-staging.com' );
|
343 |
+
}
|
344 |
+
// Finished or path does not exist
|
345 |
+
if(
|
346 |
+
empty( $this->clone->path ) ||
|
347 |
+
$this->clone->path == get_home_path() ||
|
348 |
+
!is_dir( $this->clone->path ) ) {
|
349 |
+
|
350 |
+
$this->job->current = "finish";
|
351 |
+
$this->updateJob();
|
352 |
+
return $this->returnFinish();
|
353 |
+
}
|
354 |
+
|
355 |
+
$this->log( "Delete staging site: " . $this->clone->path, Logger::TYPE_INFO );
|
356 |
+
|
357 |
+
// Just to make sure the root dir is never deleted!
|
358 |
+
if( $this->clone->path == get_home_path() ) {
|
359 |
+
$this->log( "Fatal Error 8: Trying to delete root of WP installation!", Logger::TYPE_CRITICAL );
|
360 |
+
$this->returnException( 'Fatal Error 8: Trying to delete root of WP installation!' );
|
361 |
+
}
|
362 |
+
|
363 |
+
// Check if threshold is reached
|
364 |
+
if( $this->isOverThreshold() ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
365 |
//$this->returnException('Maximum PHP execution time exceeded. Run again and repeat the deletion process until it is sucessfully finished.');
|
366 |
return;
|
367 |
+
}
|
368 |
+
|
369 |
+
$di = new \RecursiveDirectoryIterator( $this->clone->path, \FilesystemIterator::SKIP_DOTS );
|
370 |
+
$ri = new \RecursiveIteratorIterator( $di, \RecursiveIteratorIterator::CHILD_FIRST );
|
371 |
+
foreach ( $ri as $file ) {
|
372 |
+
//$file->isDir() ? @rmdir($file) : unlink($file);
|
373 |
+
$this->deleteFile( $file );
|
374 |
+
if( $this->isOverThreshold() ) {
|
375 |
+
//$this->returnException('Maximum PHP execution time exceeded. Run again and repeat the deletion process until it is sucessfully finished.');
|
376 |
+
return;
|
377 |
+
}
|
378 |
+
}
|
379 |
+
|
380 |
+
if( @rmdir( $this->clone->path ) ) {
|
381 |
+
return $this->returnFinish();
|
382 |
+
}
|
383 |
+
return;
|
384 |
+
}
|
385 |
+
|
386 |
+
/**
|
387 |
+
* Delete file
|
388 |
+
* @param object iterator $file
|
389 |
+
*/
|
390 |
+
private function deleteFile( $file ) {
|
391 |
+
if( !file_exists( $file ) ) {
|
392 |
+
return true;
|
393 |
+
}
|
394 |
+
if( $file->isDir() ) {
|
395 |
+
if( !@rmdir( $file ) ) {
|
396 |
+
$this->returnException( 'Permission Error: Can not delete folder ' . $file );
|
397 |
+
}
|
398 |
+
} elseif( !is_file( $file ) ) {
|
399 |
+
return false;
|
400 |
+
} else {
|
401 |
+
if( !unlink( $file ) ) {
|
402 |
+
$this->returnException( 'Permission Error: Can not delete file ' . $file );
|
403 |
+
}
|
404 |
+
}
|
405 |
+
}
|
406 |
+
|
407 |
+
/**
|
408 |
+
* @return bool
|
409 |
+
*/
|
410 |
+
public function isDirectoryDeletingFinished() {
|
411 |
+
return (
|
412 |
+
(false === $this->forceDeleteDirectories && (!isset( $_POST["deleteDir"] ) || '1' !== $_POST["deleteDir"])) ||
|
413 |
+
!is_dir( $this->clone->path ) || ABSPATH === $this->job->nextDirectoryToDelete
|
414 |
+
);
|
415 |
+
}
|
416 |
+
|
417 |
+
/**
|
418 |
+
*
|
419 |
+
* @return boolean
|
420 |
+
*/
|
421 |
+
public function isFatalError() {
|
422 |
+
$homePath = rtrim( get_home_path(), "/" );
|
423 |
+
if( rtrim( $this->clone->path, "/" ) == $homePath ) {
|
424 |
+
return true;
|
425 |
+
}
|
426 |
+
return false;
|
427 |
+
}
|
428 |
+
|
429 |
+
/**
|
430 |
+
* Finish / Update Existing Clones
|
431 |
+
*/
|
432 |
+
public function deleteFinish() {
|
433 |
+
$existingClones = get_option( "wpstg_existing_clones_beta", array() );
|
434 |
+
|
435 |
+
// Check if clones still exist
|
436 |
+
$this->log( "Verifying existing clones..." );
|
437 |
+
foreach ( $existingClones as $name => $clone ) {
|
438 |
+
if( !is_dir( $clone["path"] ) ) {
|
439 |
+
unset( $existingClones[$name] );
|
440 |
+
}
|
441 |
+
}
|
442 |
+
$this->log( "Existing clones verified!" );
|
443 |
+
|
444 |
+
if( false === update_option( "wpstg_existing_clones_beta", $existingClones ) ) {
|
445 |
+
$this->log( "Failed to save {$this->options->clone}'s clone job data to database'" );
|
446 |
+
}
|
447 |
+
|
448 |
+
// Delete cached file
|
449 |
+
$this->cache->delete( "delete_job_{$this->clone->name}" );
|
450 |
+
$this->cache->delete( "delete_directories_{$this->clone->name}" );
|
451 |
+
|
452 |
+
//return true;
|
453 |
+
$response = array('delete' => 'finished');
|
454 |
+
wp_die( json_encode( $response ) );
|
455 |
+
}
|
456 |
+
|
457 |
+
/**
|
458 |
+
* Get json response
|
459 |
+
* return json
|
460 |
+
*/
|
461 |
+
private function returnFinish( $message = '' ) {
|
462 |
+
|
463 |
+
$this->deleteFinish();
|
464 |
+
|
465 |
+
wp_die( json_encode( array(
|
466 |
+
'job' => 'delete',
|
467 |
+
'status' => true,
|
468 |
+
'message' => $message,
|
469 |
+
'error' => false,
|
470 |
+
'delete' => 'finished'
|
471 |
+
) ) );
|
472 |
+
}
|
473 |
|
474 |
}
|
apps/Backend/Modules/Jobs/Multisite/Data.php
CHANGED
@@ -282,7 +282,7 @@ class Data extends JobExecutable {
|
|
282 |
}
|
283 |
|
284 |
$this->log( "Preparing Data Step1: Failed to update siteurl and homeurl in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_ERROR );
|
285 |
-
return
|
286 |
}
|
287 |
|
288 |
/**
|
282 |
}
|
283 |
|
284 |
$this->log( "Preparing Data Step1: Failed to update siteurl and homeurl in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_ERROR );
|
285 |
+
return true;
|
286 |
}
|
287 |
|
288 |
/**
|
apps/Backend/Modules/Jobs/Multisite/DataExternal.php
CHANGED
@@ -289,7 +289,7 @@ class DataExternal extends JobExecutable {
|
|
289 |
}
|
290 |
|
291 |
$this->log( "Preparing Data Step1: Failed to update siteurl and homeurl in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_ERROR );
|
292 |
-
return
|
293 |
}
|
294 |
|
295 |
/**
|
289 |
}
|
290 |
|
291 |
$this->log( "Preparing Data Step1: Failed to update siteurl and homeurl in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_ERROR );
|
292 |
+
return true;
|
293 |
}
|
294 |
|
295 |
/**
|
apps/Backend/Modules/Jobs/Multisite/SearchReplace.php
CHANGED
@@ -327,42 +327,6 @@ class SearchReplace extends JobExecutable {
|
|
327 |
$this->getImagePathStaging()
|
328 |
);
|
329 |
|
330 |
-
|
331 |
-
##########################
|
332 |
-
// if( $this->isSubDir() ) {
|
333 |
-
// // Search URL example.com/staging and root path to staging site /var/www/htdocs/staging
|
334 |
-
// $args['search_for'] = array(
|
335 |
-
// rtrim( $this->multisiteHomeUrlWithoutScheme, "/" ) . $this->getSubDir(),
|
336 |
-
// ABSPATH,
|
337 |
-
// str_replace( '/', '\/', rtrim( $this->multisiteHomeUrlWithoutScheme, '/' ) ) . str_replace( '/', '\/', $this->getSubDir() ), // // Used by revslider and several visual editors
|
338 |
-
// $this->getImagePathLive()
|
339 |
-
// );
|
340 |
-
//
|
341 |
-
//
|
342 |
-
// $args['replace_with'] = array(
|
343 |
-
// rtrim( $this->multisiteDomainWithoutScheme, "/" ) . $this->getSubDir() . '/' . $this->options->cloneDirectoryName,
|
344 |
-
// rtrim( $this->getAbsDestination(), '/' ) . '/' . $this->options->cloneDirectoryName,
|
345 |
-
// str_replace( '/', '\/', rtrim( $this->multisiteDomainWithoutScheme, "/" ) ) . str_replace( '/', '\/', $this->getSubDir() ) . '\/' . $this->options->cloneDirectoryName, // Used by revslider and several visual editors
|
346 |
-
// $this->getImagePathStaging()
|
347 |
-
// );
|
348 |
-
// } else {
|
349 |
-
// $args['search_for'] = array(
|
350 |
-
// rtrim( $this->multisiteHomeUrlWithoutScheme, '/' ),
|
351 |
-
// ABSPATH,
|
352 |
-
// str_replace( '/', '\/', rtrim( $this->multisiteHomeUrlWithoutScheme, '/' ) ),
|
353 |
-
// $this->getImagePathLive()
|
354 |
-
// );
|
355 |
-
// $args['replace_with'] = array(
|
356 |
-
// rtrim( $this->multisiteDomainWithoutScheme, '/' ) . '/' . $this->options->cloneDirectoryName,
|
357 |
-
// rtrim( $this->getAbsDestination(), '/' ) . '/' . $this->options->cloneDirectoryName,
|
358 |
-
// str_replace( '/', '\/', rtrim( $this->multisiteDomainWithoutScheme, '/' ) ) . '\/' . $this->options->cloneDirectoryName,
|
359 |
-
// $this->getImagePathStaging()
|
360 |
-
// );
|
361 |
-
// }
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
$args['replace_guids'] = 'off';
|
367 |
$args['dry_run'] = 'off';
|
368 |
$args['case_insensitive'] = false;
|
@@ -446,10 +410,10 @@ class SearchReplace extends JobExecutable {
|
|
446 |
if( $this->options->prefix . 'options' === $table ) {
|
447 |
|
448 |
// Skip certain options
|
449 |
-
if( isset( $should_skip ) && true === $should_skip ) {
|
450 |
-
$should_skip = false;
|
451 |
-
continue;
|
452 |
-
}
|
453 |
|
454 |
// Skip this row
|
455 |
if( 'wpstg_existing_clones_beta' === $dataRow ||
|
@@ -459,7 +423,8 @@ class SearchReplace extends JobExecutable {
|
|
459 |
'siteurl' === $dataRow ||
|
460 |
'home' === $dataRow
|
461 |
) {
|
462 |
-
|
|
|
463 |
}
|
464 |
}
|
465 |
|
327 |
$this->getImagePathStaging()
|
328 |
);
|
329 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
330 |
$args['replace_guids'] = 'off';
|
331 |
$args['dry_run'] = 'off';
|
332 |
$args['case_insensitive'] = false;
|
410 |
if( $this->options->prefix . 'options' === $table ) {
|
411 |
|
412 |
// Skip certain options
|
413 |
+
// if( isset( $should_skip ) && true === $should_skip ) {
|
414 |
+
// $should_skip = false;
|
415 |
+
// continue;
|
416 |
+
// }
|
417 |
|
418 |
// Skip this row
|
419 |
if( 'wpstg_existing_clones_beta' === $dataRow ||
|
423 |
'siteurl' === $dataRow ||
|
424 |
'home' === $dataRow
|
425 |
) {
|
426 |
+
//$should_skip = true;
|
427 |
+
continue;
|
428 |
}
|
429 |
}
|
430 |
|
apps/Backend/Modules/Jobs/Multisite/SearchReplaceExternal.php
CHANGED
@@ -336,37 +336,6 @@ class SearchReplaceExternal extends JobExecutable {
|
|
336 |
$this->getImagePathStaging()
|
337 |
);
|
338 |
|
339 |
-
// if( $this->isSubDir() ) {
|
340 |
-
// // Search URL example.com/staging and root path to staging site /var/www/htdocs/staging
|
341 |
-
// $args['search_for'] = array(
|
342 |
-
// '//' . rtrim( $this->multisiteHomeUrlWithoutScheme, "/" ) . $this->getSubDir(),
|
343 |
-
// ABSPATH,
|
344 |
-
// str_replace( '/', '\/', rtrim( $this->multisiteHomeUrlWithoutScheme, '/' ) ) . str_replace( '/', '\/', $this->getSubDir() ), // // Used by revslider and several visual editors
|
345 |
-
// $this->getImagePathLive()
|
346 |
-
// );
|
347 |
-
//
|
348 |
-
//
|
349 |
-
// $args['replace_with'] = array(
|
350 |
-
// '//' . rtrim( $this->multisiteDomainWithoutScheme, "/" ) . $this->getSubDir() . '/' . $this->options->cloneDirectoryName,
|
351 |
-
// rtrim( $this->getAbsDestination(), '/' ) . '/' . $this->options->cloneDirectoryName,
|
352 |
-
// str_replace( '/', '\/', rtrim( $this->multisiteDomainWithoutScheme, "/" ) ) . str_replace( '/', '\/', $this->getSubDir() ) . '\/' . $this->options->cloneDirectoryName, // Used by revslider and several visual editors
|
353 |
-
// $this->getImagePathStaging()
|
354 |
-
// );
|
355 |
-
// } else {
|
356 |
-
// $args['search_for'] = array(
|
357 |
-
// '//' . rtrim( $this->multisiteHomeUrlWithoutScheme, '/' ),
|
358 |
-
// ABSPATH,
|
359 |
-
// str_replace( '/', '\/', rtrim( $this->multisiteHomeUrlWithoutScheme, '/' ) ),
|
360 |
-
// $this->getImagePathLive()
|
361 |
-
// );
|
362 |
-
// $args['replace_with'] = array(
|
363 |
-
// '//' . rtrim( $this->multisiteDomainWithoutScheme, '/' ) . '/' . $this->options->cloneDirectoryName,
|
364 |
-
// rtrim( $this->getAbsDestination(), '/' ) . '/' . $this->options->cloneDirectoryName,
|
365 |
-
// str_replace( '/', '\/', rtrim( $this->multisiteDomainWithoutScheme, '/' ) ) . '\/' . $this->options->cloneDirectoryName,
|
366 |
-
// $this->getImagePathStaging()
|
367 |
-
// );
|
368 |
-
// }
|
369 |
-
|
370 |
$args['replace_guids'] = 'off';
|
371 |
$args['dry_run'] = 'off';
|
372 |
$args['case_insensitive'] = false;
|
@@ -450,10 +419,10 @@ class SearchReplaceExternal extends JobExecutable {
|
|
450 |
if( $this->options->prefix . 'options' === $table ) {
|
451 |
|
452 |
// Skip certain options
|
453 |
-
if( isset( $should_skip ) && true === $should_skip ) {
|
454 |
-
$should_skip = false;
|
455 |
-
continue;
|
456 |
-
}
|
457 |
|
458 |
// Skip this row
|
459 |
if( 'wpstg_existing_clones_beta' === $dataRow ||
|
@@ -463,7 +432,8 @@ class SearchReplaceExternal extends JobExecutable {
|
|
463 |
'siteurl' === $dataRow ||
|
464 |
'home' === $dataRow
|
465 |
) {
|
466 |
-
|
|
|
467 |
}
|
468 |
}
|
469 |
|
336 |
$this->getImagePathStaging()
|
337 |
);
|
338 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
339 |
$args['replace_guids'] = 'off';
|
340 |
$args['dry_run'] = 'off';
|
341 |
$args['case_insensitive'] = false;
|
419 |
if( $this->options->prefix . 'options' === $table ) {
|
420 |
|
421 |
// Skip certain options
|
422 |
+
// if( isset( $should_skip ) && true === $should_skip ) {
|
423 |
+
// $should_skip = false;
|
424 |
+
// continue;
|
425 |
+
// }
|
426 |
|
427 |
// Skip this row
|
428 |
if( 'wpstg_existing_clones_beta' === $dataRow ||
|
432 |
'siteurl' === $dataRow ||
|
433 |
'home' === $dataRow
|
434 |
) {
|
435 |
+
//$should_skip = true;
|
436 |
+
continue;
|
437 |
}
|
438 |
}
|
439 |
|
apps/Backend/Modules/Jobs/Scan.php
CHANGED
@@ -284,7 +284,6 @@ class Scan extends Job {
|
|
284 |
if( false === ($path = $this->getPath( $directory )) ) {
|
285 |
continue;
|
286 |
}
|
287 |
-
//echo $directory . '<br>';
|
288 |
|
289 |
$this->handleDirectory( $path );
|
290 |
|
@@ -338,13 +337,9 @@ class Scan extends Job {
|
|
338 |
* Prevents open base dir restriction fatal errors
|
339 |
*/
|
340 |
|
341 |
-
//echo $directory->getRealPath() . '<br>';
|
342 |
-
//echo 'abspath: ' . \WPStaging\WPStaging::getWPpath() . '<br>';
|
343 |
-
//if( strpos( $directory->getRealPath(), ABSPATH ) !== 0 ) {
|
344 |
if( strpos( $directory->getRealPath(), \WPStaging\WPStaging::getWPpath() ) !== 0 ) {
|
345 |
return false;
|
346 |
}
|
347 |
-
//$path = str_replace( ABSPATH, null, $directory->getRealPath() );
|
348 |
$path = str_replace( \WPStaging\WPStaging::getWPpath(), null, $directory->getRealPath() );
|
349 |
|
350 |
// Using strpos() for symbolic links as they could create nasty stuff in nix stuff for directory structures
|
284 |
if( false === ($path = $this->getPath( $directory )) ) {
|
285 |
continue;
|
286 |
}
|
|
|
287 |
|
288 |
$this->handleDirectory( $path );
|
289 |
|
337 |
* Prevents open base dir restriction fatal errors
|
338 |
*/
|
339 |
|
|
|
|
|
|
|
340 |
if( strpos( $directory->getRealPath(), \WPStaging\WPStaging::getWPpath() ) !== 0 ) {
|
341 |
return false;
|
342 |
}
|
|
|
343 |
$path = str_replace( \WPStaging\WPStaging::getWPpath(), null, $directory->getRealPath() );
|
344 |
|
345 |
// Using strpos() for symbolic links as they could create nasty stuff in nix stuff for directory structures
|
apps/Backend/Modules/Jobs/SearchReplace.php
CHANGED
@@ -351,7 +351,7 @@ class SearchReplace extends JobExecutable {
|
|
351 |
'Admin_custome_login_top',
|
352 |
'Admin_custome_login_dashboard',
|
353 |
'Admin_custome_login_Version',
|
354 |
-
'upload_path'
|
355 |
);
|
356 |
|
357 |
$filter = apply_filters( 'wpstg_clone_searchreplace_excl_rows', $filter );
|
@@ -372,11 +372,24 @@ class SearchReplace extends JobExecutable {
|
|
372 |
if( isset( $row['option_name'] ) && 'on' === $args['skip_transients'] && false !== strpos( $row['option_name'], '_transient' ) ) {
|
373 |
continue;
|
374 |
}
|
|
|
|
|
|
|
|
|
|
|
375 |
|
376 |
foreach ( $columns as $column ) {
|
377 |
|
378 |
$dataRow = $row[$column];
|
379 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
380 |
if( $column == $primary_key ) {
|
381 |
$where_sql[] = $column . ' = "' . $this->mysql_escape_mimic( $dataRow ) . '"';
|
382 |
continue;
|
351 |
'Admin_custome_login_top',
|
352 |
'Admin_custome_login_dashboard',
|
353 |
'Admin_custome_login_Version',
|
354 |
+
'upload_path'
|
355 |
);
|
356 |
|
357 |
$filter = apply_filters( 'wpstg_clone_searchreplace_excl_rows', $filter );
|
372 |
if( isset( $row['option_name'] ) && 'on' === $args['skip_transients'] && false !== strpos( $row['option_name'], '_transient' ) ) {
|
373 |
continue;
|
374 |
}
|
375 |
+
// Skip rows with more than 5MB to save memory
|
376 |
+
if( isset( $row['option_value'] ) && strlen($row['option_value']) >= 5000000 ) {
|
377 |
+
continue;
|
378 |
+
}
|
379 |
+
|
380 |
|
381 |
foreach ( $columns as $column ) {
|
382 |
|
383 |
$dataRow = $row[$column];
|
384 |
|
385 |
+
|
386 |
+
// Skip rows larger than 5MB
|
387 |
+
$size = strlen($dataRow);
|
388 |
+
if ($size >= 5000000){
|
389 |
+
continue;
|
390 |
+
}
|
391 |
+
|
392 |
+
// Skip Primary key
|
393 |
if( $column == $primary_key ) {
|
394 |
$where_sql[] = $column . ' = "' . $this->mysql_escape_mimic( $dataRow ) . '"';
|
395 |
continue;
|
apps/Backend/public/css/wpstg-admin.css
CHANGED
@@ -448,6 +448,11 @@
|
|
448 |
position: relative;
|
449 |
}
|
450 |
|
|
|
|
|
|
|
|
|
|
|
451 |
.wpstg-progress-bar {
|
452 |
/*max-width: 900px;*/
|
453 |
height: 27px;
|
@@ -993,3 +998,8 @@
|
|
993 |
background-color: #f2dede;
|
994 |
border-color: #ebccd1;
|
995 |
}
|
|
|
|
|
|
|
|
|
|
448 |
position: relative;
|
449 |
}
|
450 |
|
451 |
+
#wpstg-removing-clone .wpstg-tab-section{
|
452 |
+
display: block;
|
453 |
+
}
|
454 |
+
|
455 |
+
|
456 |
.wpstg-progress-bar {
|
457 |
/*max-width: 900px;*/
|
458 |
height: 27px;
|
998 |
background-color: #f2dede;
|
999 |
border-color: #ebccd1;
|
1000 |
}
|
1001 |
+
|
1002 |
+
#wpstg_select_tables_cloning {
|
1003 |
+
height: 600px;
|
1004 |
+
font-size: 13px;
|
1005 |
+
}
|
apps/Backend/public/js/wpstg-admin.js
CHANGED
@@ -64,7 +64,7 @@ var WPStaging = (function ($)
|
|
64 |
var elements = function ()
|
65 |
{
|
66 |
var $workFlow = cache.get("#wpstg-workflow"),
|
67 |
-
isAllChecked =
|
68 |
urlSpinner = ajaxurl.replace("/admin-ajax.php", '') + "/images/spinner",
|
69 |
timer;
|
70 |
|
@@ -78,49 +78,97 @@ var WPStaging = (function ($)
|
|
78 |
ajaxSpinner = "<img src=''" + urlSpinner + "' alt='' class='ajax-spinner general-spinner' />";
|
79 |
|
80 |
$workFlow
|
81 |
-
// Check / Un-check Database Tables
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
82 |
.on("click", ".wpstg-button-unselect", function (e) {
|
83 |
e.preventDefault();
|
84 |
|
85 |
-
|
|
|
|
|
86 |
{
|
87 |
-
|
88 |
-
cache.get(".wpstg-
|
|
|
89 |
isAllChecked = true;
|
90 |
}
|
91 |
else
|
92 |
{
|
93 |
-
|
94 |
-
cache.get(".wpstg-
|
|
|
95 |
isAllChecked = false;
|
96 |
}
|
97 |
})
|
|
|
98 |
/**
|
99 |
* Select tables with certain tbl prefix
|
100 |
* @param obj e
|
101 |
* @returns {undefined}
|
102 |
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
103 |
.on("click", ".wpstg-button-select", function (e) {
|
104 |
e.preventDefault();
|
105 |
-
$(".wpstg-db-table
|
106 |
-
|
107 |
if (wpstg.isMultisite == 1) {
|
108 |
if ($(this).attr('name').match("^" + wpstg.tblprefix + "([^0-9])_*")) {
|
109 |
-
$(this).prop("
|
110 |
} else {
|
111 |
-
$(this).prop("
|
112 |
}
|
113 |
}
|
114 |
|
115 |
if (wpstg.isMultisite == 0) {
|
116 |
if ($(this).attr('name').match("^" + wpstg.tblprefix)) {
|
117 |
-
|
118 |
} else {
|
119 |
-
|
120 |
}
|
121 |
}
|
122 |
})
|
123 |
})
|
|
|
124 |
// Expand Directories
|
125 |
.on("click", ".wpstg-expand-dirs", function (e) {
|
126 |
e.preventDefault();
|
@@ -332,11 +380,6 @@ var WPStaging = (function ($)
|
|
332 |
.on("click", ".wpstg-execute-clone", function (e) {
|
333 |
e.preventDefault();
|
334 |
|
335 |
-
// if (!confirm("Are you sure you want to update the staging site? All your staging site modifications will be overwritten with the data from the live site. So make sure that your live site is up to date."))
|
336 |
-
// {
|
337 |
-
// return false;
|
338 |
-
// }
|
339 |
-
|
340 |
var clone = $(this).data("clone");
|
341 |
|
342 |
$workFlow.addClass("loading");
|
@@ -490,7 +533,7 @@ var WPStaging = (function ($)
|
|
490 |
|
491 |
if ($this.data("action") === "wpstg_update") {
|
492 |
// Update Clone - confirmed
|
493 |
-
if (!confirm("
|
494 |
{
|
495 |
return false;
|
496 |
}
|
@@ -577,21 +620,29 @@ var WPStaging = (function ($)
|
|
577 |
{
|
578 |
var includedTables = [];
|
579 |
|
580 |
-
$(".wpstg-db-table input:checked").each(function () {
|
581 |
-
includedTables.push(this.name);
|
|
|
|
|
|
|
|
|
582 |
});
|
583 |
|
584 |
return includedTables;
|
585 |
};
|
586 |
/**
|
587 |
* Get Excluded (Unchecked) Database Tables
|
|
|
588 |
* @returns {Array}
|
589 |
*/
|
590 |
var getExcludedTables = function ()
|
591 |
{
|
592 |
var excludedTables = [];
|
593 |
|
594 |
-
$(".wpstg-db-table input:not(:checked)").each(function () {
|
|
|
|
|
|
|
595 |
excludedTables.push(this.name);
|
596 |
});
|
597 |
|
64 |
var elements = function ()
|
65 |
{
|
66 |
var $workFlow = cache.get("#wpstg-workflow"),
|
67 |
+
isAllChecked = false,
|
68 |
urlSpinner = ajaxurl.replace("/admin-ajax.php", '') + "/images/spinner",
|
69 |
timer;
|
70 |
|
78 |
ajaxSpinner = "<img src=''" + urlSpinner + "' alt='' class='ajax-spinner general-spinner' />";
|
79 |
|
80 |
$workFlow
|
81 |
+
// Check / Un-check All Database Tables
|
82 |
+
// .on("click", ".wpstg-button-unselect", function (e) {
|
83 |
+
// e.preventDefault();
|
84 |
+
//
|
85 |
+
// if (false === isAllChecked)
|
86 |
+
// {
|
87 |
+
// cache.get(".wpstg-db-table-checkboxes").prop("checked", true);
|
88 |
+
// cache.get(".wpstg-button-unselect").text("Un-check All");
|
89 |
+
// isAllChecked = true;
|
90 |
+
// }
|
91 |
+
// else
|
92 |
+
// {
|
93 |
+
// cache.get(".wpstg-db-table-checkboxes").prop("checked", false);
|
94 |
+
// cache.get(".wpstg-button-unselect").text("Check All");
|
95 |
+
// isAllChecked = false;
|
96 |
+
// }
|
97 |
+
// })
|
98 |
+
// Check / Un-check All Database Tables New
|
99 |
.on("click", ".wpstg-button-unselect", function (e) {
|
100 |
e.preventDefault();
|
101 |
|
102 |
+
|
103 |
+
//if (typeof(isAllChecked) !== 'defined' || true === isAllChecked )
|
104 |
+
if (false === isAllChecked )
|
105 |
{
|
106 |
+
console.log('true');
|
107 |
+
cache.get("#wpstg_select_tables_cloning .wpstg-db-table").prop("selected", "selected");
|
108 |
+
cache.get(".wpstg-button-unselect").text("Unselect All");
|
109 |
isAllChecked = true;
|
110 |
}
|
111 |
else
|
112 |
{
|
113 |
+
console.log('false');
|
114 |
+
cache.get("#wpstg_select_tables_cloning .wpstg-db-table").prop("selected", false);
|
115 |
+
cache.get(".wpstg-button-unselect").text("Select All");
|
116 |
isAllChecked = false;
|
117 |
}
|
118 |
})
|
119 |
+
|
120 |
/**
|
121 |
* Select tables with certain tbl prefix
|
122 |
* @param obj e
|
123 |
* @returns {undefined}
|
124 |
*/
|
125 |
+
// .on("click", ".wpstg-button-select", function (e) {
|
126 |
+
// e.preventDefault();
|
127 |
+
// $(".wpstg-db-table input").each(function () {
|
128 |
+
//
|
129 |
+
// if (wpstg.isMultisite == 1) {
|
130 |
+
// if ($(this).attr('name').match("^" + wpstg.tblprefix + "([^0-9])_*")) {
|
131 |
+
// $(this).prop("checked", true);
|
132 |
+
// } else {
|
133 |
+
// $(this).prop("checked", false);
|
134 |
+
// }
|
135 |
+
// }
|
136 |
+
//
|
137 |
+
// if (wpstg.isMultisite == 0) {
|
138 |
+
// if ($(this).attr('name').match("^" + wpstg.tblprefix)) {
|
139 |
+
// $(this).prop("checked", true);
|
140 |
+
// } else {
|
141 |
+
// $(this).prop("checked", false);
|
142 |
+
// }
|
143 |
+
// }
|
144 |
+
// })
|
145 |
+
// })
|
146 |
+
/**
|
147 |
+
* Select tables with certain tbl prefix | NEW
|
148 |
+
* @param obj e
|
149 |
+
* @returns {undefined}
|
150 |
+
*/
|
151 |
.on("click", ".wpstg-button-select", function (e) {
|
152 |
e.preventDefault();
|
153 |
+
$("#wpstg_select_tables_cloning .wpstg-db-table").each(function () {
|
|
|
154 |
if (wpstg.isMultisite == 1) {
|
155 |
if ($(this).attr('name').match("^" + wpstg.tblprefix + "([^0-9])_*")) {
|
156 |
+
$(this).prop("selected", "selected");
|
157 |
} else {
|
158 |
+
$(this).prop("selected", false);
|
159 |
}
|
160 |
}
|
161 |
|
162 |
if (wpstg.isMultisite == 0) {
|
163 |
if ($(this).attr('name').match("^" + wpstg.tblprefix)) {
|
164 |
+
$(this).prop("selected", "selected");
|
165 |
} else {
|
166 |
+
$(this).prop("selected", false);
|
167 |
}
|
168 |
}
|
169 |
})
|
170 |
})
|
171 |
+
|
172 |
// Expand Directories
|
173 |
.on("click", ".wpstg-expand-dirs", function (e) {
|
174 |
e.preventDefault();
|
380 |
.on("click", ".wpstg-execute-clone", function (e) {
|
381 |
e.preventDefault();
|
382 |
|
|
|
|
|
|
|
|
|
|
|
383 |
var clone = $(this).data("clone");
|
384 |
|
385 |
$workFlow.addClass("loading");
|
533 |
|
534 |
if ($this.data("action") === "wpstg_update") {
|
535 |
// Update Clone - confirmed
|
536 |
+
if (!confirm("ATTENTION! This will overwrite your staging site with all selected data from the live site! This should be used only if you want to clone again your production site. Are you sure you want to do this? \n\nMake sure to exclude all tables and folders which you do not want to overwrite, first! \n\nDo not necessarily cancel the updating process! This can break your staging site."))
|
537 |
{
|
538 |
return false;
|
539 |
}
|
620 |
{
|
621 |
var includedTables = [];
|
622 |
|
623 |
+
// $(".wpstg-db-table input:checked").each(function () {
|
624 |
+
// includedTables.push(this.name);
|
625 |
+
// });
|
626 |
+
$("#wpstg_select_tables_cloning option:selected").each(function () {
|
627 |
+
//console.log(this);
|
628 |
+
includedTables.push(this.value);
|
629 |
});
|
630 |
|
631 |
return includedTables;
|
632 |
};
|
633 |
/**
|
634 |
* Get Excluded (Unchecked) Database Tables
|
635 |
+
* Not used anymore!
|
636 |
* @returns {Array}
|
637 |
*/
|
638 |
var getExcludedTables = function ()
|
639 |
{
|
640 |
var excludedTables = [];
|
641 |
|
642 |
+
// $(".wpstg-db-table input:not(:checked)").each(function () {
|
643 |
+
// excludedTables.push(this.name);
|
644 |
+
// });
|
645 |
+
$("#wpstg_select_tables_cloning option:not(:selected)").each(function () {
|
646 |
excludedTables.push(this.name);
|
647 |
});
|
648 |
|
apps/Backend/views/clone/ajax/delete-confirmation.php
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
<div class="wpstg-notice-alert wpstg-failed">
|
2 |
<h4 style="margin:0">
|
3 |
<?php
|
4 |
-
_e("Attention: Check carefully if
|
5 |
?>
|
6 |
</h4>
|
7 |
|
1 |
<div class="wpstg-notice-alert wpstg-failed">
|
2 |
<h4 style="margin:0">
|
3 |
<?php
|
4 |
+
_e("Attention: Check carefully if the database tables and files from the selection below are safe to delete and do not belong to your live site!", "wp-staging")
|
5 |
?>
|
6 |
</h4>
|
7 |
|
apps/Backend/views/clone/ajax/scan.php
CHANGED
@@ -15,7 +15,7 @@
|
|
15 |
<div class="wpstg-tabs-wrapper">
|
16 |
<a href="#" class="wpstg-tab-header active" data-id="#wpstg-scanning-db">
|
17 |
<span class="wpstg-tab-triangle">►</span>
|
18 |
-
<?php echo __( "
|
19 |
</a>
|
20 |
|
21 |
<div class="wpstg-tab-section" id="wpstg-scanning-db">
|
@@ -23,29 +23,50 @@
|
|
23 |
<h4 style="margin:0">
|
24 |
<?php
|
25 |
echo __(
|
26 |
-
"
|
27 |
-
)
|
|
|
|
|
|
|
|
|
|
|
|
|
28 |
?>
|
29 |
</h4>
|
30 |
<div style="margin-top:10px;margin-bottom:10px;">
|
31 |
-
<a href="#" class="wpstg-button-unselect button"
|
32 |
<a href="#" class="wpstg-button-select button"> <?php _e( WPStaging\WPStaging::getTablePrefix(), 'wp-staging' ); ?> </a>
|
33 |
</div>
|
|
|
34 |
<?php
|
35 |
foreach ( $options->tables as $table ):
|
36 |
-
|
37 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
38 |
?>
|
39 |
-
<div class="wpstg-db-table">
|
40 |
<label>
|
41 |
-
<input class="wpstg-db-table-checkboxes" type="checkbox" name="<?php echo $table->name ?>" <?php echo $attributes ?>>
|
42 |
-
<?php echo $table->name ?>
|
43 |
</label>
|
44 |
<span class="wpstg-size-info">
|
45 |
-
<?php echo $scan->formatSize( $table->size ) ?>
|
46 |
</span>
|
47 |
-
</div
|
48 |
-
<?php endforeach ?>
|
|
|
49 |
<div style="margin-top:10px;">
|
50 |
<a href="#" class="wpstg-button-unselect button"> None </a>
|
51 |
<a href="#" class="wpstg-button-select button"> <?php _e( WPStaging\WPStaging::getTablePrefix(), 'wp-staging' ); ?> </a>
|
15 |
<div class="wpstg-tabs-wrapper">
|
16 |
<a href="#" class="wpstg-tab-header active" data-id="#wpstg-scanning-db">
|
17 |
<span class="wpstg-tab-triangle">►</span>
|
18 |
+
<?php echo __( "Database Tables", "wp-staging" ) ?>
|
19 |
</a>
|
20 |
|
21 |
<div class="wpstg-tab-section" id="wpstg-scanning-db">
|
23 |
<h4 style="margin:0">
|
24 |
<?php
|
25 |
echo __(
|
26 |
+
"Select the tables you like to clone. All tables beginning with prefix '{$scan->prefix}' have been selected already.", "wp-staging"
|
27 |
+
);
|
28 |
+
?>
|
29 |
+
<p></p>
|
30 |
+
<?php
|
31 |
+
echo __(
|
32 |
+
"Select multiple tables by pressing left mouse button and moving or by pressing STRG+Left Mouse button. (Mac ⌘+Left Mouse Button)", "wp-staging"
|
33 |
+
);
|
34 |
?>
|
35 |
</h4>
|
36 |
<div style="margin-top:10px;margin-bottom:10px;">
|
37 |
+
<a href="#" class="wpstg-button-unselect button"><?php _e('Select All','wp-staging'); ?></a>
|
38 |
<a href="#" class="wpstg-button-select button"> <?php _e( WPStaging\WPStaging::getTablePrefix(), 'wp-staging' ); ?> </a>
|
39 |
</div>
|
40 |
+
<select multiple="multiple" id="wpstg_select_tables_cloning">
|
41 |
<?php
|
42 |
foreach ( $options->tables as $table ):
|
43 |
+
$attributes = !in_array( $table->name, $options->excludedTables ) && (strpos( $table->name, $db->prefix ) === 0) ? "selected='selected'" : "";
|
44 |
+
$attributes .= in_array( $table->name, $options->clonedTables ) ? "disabled" : '';
|
45 |
+
?>
|
46 |
+
<option class="wpstg-db-table" value="<?php echo $table->name ?>" name="<?php echo $table->name ?>" <?php echo $attributes ?>>
|
47 |
+
<?php echo $table->name ?> - <?php echo $scan->formatSize( $table->size ) ?>
|
48 |
+
</option>
|
49 |
+
<?php endforeach ?>
|
50 |
+
</select>
|
51 |
+
|
52 |
+
|
53 |
+
|
54 |
+
<?php
|
55 |
+
// foreach ( $options->tables as $table ):
|
56 |
+
// $attributes = in_array( $table->name, $options->excludedTables ) ? '' : "checked";
|
57 |
+
// $attributes .= in_array( $table->name, $options->clonedTables ) ? " disabled" : '';
|
58 |
?>
|
59 |
+
<!-- <div class="wpstg-db-table">
|
60 |
<label>
|
61 |
+
<input class="wpstg-db-table-checkboxes" type="checkbox" name="<?php // echo $table->name ?>" <?php // echo $attributes ?>>
|
62 |
+
<?php // echo $table->name ?>
|
63 |
</label>
|
64 |
<span class="wpstg-size-info">
|
65 |
+
<?php // echo $scan->formatSize( $table->size ) ?>
|
66 |
</span>
|
67 |
+
</div>-->
|
68 |
+
<?php // endforeach ?>
|
69 |
+
|
70 |
<div style="margin-top:10px;">
|
71 |
<a href="#" class="wpstg-button-unselect button"> None </a>
|
72 |
<a href="#" class="wpstg-button-select button"> <?php _e( WPStaging\WPStaging::getTablePrefix(), 'wp-staging' ); ?> </a>
|
apps/Backend/views/clone/includes/footer.php
CHANGED
@@ -6,6 +6,7 @@
|
|
6 |
<strong> FAQ</strong><br/>
|
7 |
- <a href="https://wp-staging.com/docs/staging-site-redirects-live-site/" target="_blank" rel="external">Can not login to staging site</a> <br/>
|
8 |
- <a href="https://wp-staging.com/docs/fix-white-or-blank-page-after-pushing-fatal-error-500/" target="_blank" rel="external">Staging site returns blank white page</a> <br/>
|
|
|
9 |
- <a href="https://wp-staging.com/docs/install-wp-staging/" target="_blank" rel="external">More</a><br/><br/>
|
10 |
<?php echo __('It still does not work?','wp-staging');?>
|
11 |
<br>
|
6 |
<strong> FAQ</strong><br/>
|
7 |
- <a href="https://wp-staging.com/docs/staging-site-redirects-live-site/" target="_blank" rel="external">Can not login to staging site</a> <br/>
|
8 |
- <a href="https://wp-staging.com/docs/fix-white-or-blank-page-after-pushing-fatal-error-500/" target="_blank" rel="external">Staging site returns blank white page</a> <br/>
|
9 |
+
- <a href="https://wp-staging.com/docs/activate-permalinks-staging-site/" target="_blank" rel="external">Activate permalinks on staging site</a> <br/>
|
10 |
- <a href="https://wp-staging.com/docs/install-wp-staging/" target="_blank" rel="external">More</a><br/><br/>
|
11 |
<?php echo __('It still does not work?','wp-staging');?>
|
12 |
<br>
|
apps/Core/Utils/Logger.php
CHANGED
@@ -79,7 +79,7 @@ class Logger
|
|
79 |
}
|
80 |
|
81 |
// If cache directory doesn't exists, create it
|
82 |
-
if (!is_dir($this->logDir) && !@mkdir($this->logDir,
|
83 |
{
|
84 |
throw new \Exception("Failed to create log directory!");
|
85 |
}
|
79 |
}
|
80 |
|
81 |
// If cache directory doesn't exists, create it
|
82 |
+
if (!is_dir($this->logDir) && !@mkdir($this->logDir, 0755, true))
|
83 |
{
|
84 |
throw new \Exception("Failed to create log directory!");
|
85 |
}
|
apps/Core/WPStaging.php
CHANGED
@@ -29,7 +29,7 @@ final class WPStaging {
|
|
29 |
/**
|
30 |
* Plugin version
|
31 |
*/
|
32 |
-
const VERSION = "2.4.
|
33 |
|
34 |
/**
|
35 |
* Plugin name
|
29 |
/**
|
30 |
* Plugin version
|
31 |
*/
|
32 |
+
const VERSION = "2.4.9";
|
33 |
|
34 |
/**
|
35 |
* Plugin name
|
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: 5.0
|
12 |
-
Stable tag: 2.4.
|
13 |
Requires PHP: 5.3
|
14 |
|
15 |
A duplicator plugin! Clone, duplicate and migrate live sites to independent staging and development sites that are available only to administrators.
|
@@ -146,6 +146,20 @@ https://wp-staging.com
|
|
146 |
|
147 |
== Changelog ==
|
148 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
149 |
= 2.4.8 =
|
150 |
* Fix: Prevent throwing error when table prefix of table usermeta can not be changed
|
151 |
* Fix: WP Staging does not run with old WordPress version 3.2
|
@@ -218,8 +232,8 @@ Complete changelog: [https://wp-staging.com/wp-staging-changelog](https://wp-sta
|
|
218 |
|
219 |
== Upgrade Notice ==
|
220 |
|
221 |
-
= 2.4.
|
222 |
* Fix: Security, prevent downloading wp staging log files by third party users from uploads folder
|
223 |
-
* New: Compatible up to WordPress 5.0.
|
224 |
|
225 |
|
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: 5.0
|
12 |
+
Stable tag: 2.4.9
|
13 |
Requires PHP: 5.3
|
14 |
|
15 |
A duplicator plugin! Clone, duplicate and migrate live sites to independent staging and development sites that are available only to administrators.
|
146 |
|
147 |
== Changelog ==
|
148 |
|
149 |
+
= 2.4.9 =
|
150 |
+
* New: Add new db table selection manager
|
151 |
+
* Fix: Better warning notices before updating a staging site
|
152 |
+
* Fix: Stop delete process if staging site has been deleted manually before
|
153 |
+
* Fix: Log file folder does not have correct permission 0755
|
154 |
+
* Fix: Continue cloning if siteurl & home in wp_options could not be changed
|
155 |
+
* Tweak: Better warning for update method
|
156 |
+
* Tweak: DB tables and file verification opened as default option
|
157 |
+
* Tweak: Skip rows larger than 5MB for search & replace operations to keep memory consumption low
|
158 |
+
* Tweak: clean up search & replace method
|
159 |
+
* Tweak: Better FAQ
|
160 |
+
|
161 |
+
|
162 |
+
|
163 |
= 2.4.8 =
|
164 |
* Fix: Prevent throwing error when table prefix of table usermeta can not be changed
|
165 |
* Fix: WP Staging does not run with old WordPress version 3.2
|
232 |
|
233 |
== Upgrade Notice ==
|
234 |
|
235 |
+
= 2.4.9 =
|
236 |
* Fix: Security, prevent downloading wp staging log files by third party users from uploads folder
|
237 |
+
* New: Compatible up to WordPress 5.0.3 Gutenberg
|
238 |
|
239 |
|
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.4.
|
11 |
* Text Domain: wp-staging
|
12 |
* Domain Path: /languages/
|
13 |
|
@@ -51,7 +51,7 @@ if( !defined( 'WPSTG_PLUGIN_URL' ) ) {
|
|
51 |
|
52 |
// Version
|
53 |
if( !defined( 'WPSTG_VERSION' ) ) {
|
54 |
-
define( 'WPSTG_VERSION', '2.4.
|
55 |
}
|
56 |
|
57 |
// Must use version of the optimizer
|
7 |
* Author: WP-Staging
|
8 |
* Author URI: https://wp-staging.com
|
9 |
* Contributors: ReneHermi, ilgityildirim
|
10 |
+
* Version: 2.4.9
|
11 |
* Text Domain: wp-staging
|
12 |
* Domain Path: /languages/
|
13 |
|
51 |
|
52 |
// Version
|
53 |
if( !defined( 'WPSTG_VERSION' ) ) {
|
54 |
+
define( 'WPSTG_VERSION', '2.4.9' );
|
55 |
}
|
56 |
|
57 |
// Must use version of the optimizer
|