Version Description
- New: Compatible to WP 4.9.5
- New: Allow to select and copy extra folders that are on the root level
- New: Use fully custom login form to prevent access denied issues on sites where access to wp-login.php is denied or redirection plugins are used
- Fix: Incorrect login path to staging site if WordPress is installed in subdirectory
- Fix: Login url is wrong if WP is installed in subfolder
- Fix: If PHP 5.6.34 is used, the cloning process could be unfinished due to use of private member in protected class
- Tweak: Only wp root folders are pre selected before cloning is starting
- Tweak: Change WP_HOME or WP_SITEURL constants of staging site if they are defined in wp-config.php
Download this release
Release Info
Developer | ReneHermi |
Plugin | WP Staging – DB & File Duplicator & Migration |
Version | 2.2.5 |
Comparing to | |
See all releases |
Code changes from version 2.2.4 to 2.2.5
- apps/Backend/Modules/Jobs/Data.php +147 -47
- apps/Backend/Modules/Jobs/Database.php +2 -2
- apps/Backend/Modules/Jobs/Directories.php +489 -388
- apps/Backend/Modules/Jobs/Files.php +5 -0
- apps/Backend/Modules/Jobs/Scan.php +21 -7
- apps/Backend/Modules/Jobs/SearchReplace.php +70 -15
- apps/Backend/Modules/SystemInfo.php +19 -6
- apps/Backend/public/js/wpstg-admin.js +32 -16
- apps/Backend/views/clone/ajax/scan.php +6 -11
- apps/Core/Utils/Cache.php +21 -15
- apps/Core/Utils/Strings.php +16 -0
- apps/Core/WPStaging.php +2 -2
- apps/Frontend/Frontend.php +48 -13
- apps/Frontend/loginForm.php +150 -18
- readme.txt +15 -29
- wp-staging.php +1 -1
apps/Backend/Modules/Jobs/Data.php
CHANGED
@@ -49,7 +49,7 @@ class Data extends JobExecutable
|
|
49 |
*/
|
50 |
protected function calculateTotalSteps()
|
51 |
{
|
52 |
-
$this->options->totalSteps =
|
53 |
}
|
54 |
|
55 |
/**
|
@@ -64,17 +64,6 @@ class Data extends JobExecutable
|
|
64 |
// Save option, progress
|
65 |
$this->saveOptions();
|
66 |
|
67 |
-
// Prepare response
|
68 |
-
// $this->response = array(
|
69 |
-
// "status" => true,
|
70 |
-
// "percentage" => 100,
|
71 |
-
// "total" => $this->options->totalSteps,
|
72 |
-
// "step" => $this->options->totalSteps,
|
73 |
-
// "last_msg" => $this->logger->getLastLogMsg(),
|
74 |
-
// "running_time" => $this->time() - time(),
|
75 |
-
// "job_done" => true
|
76 |
-
// );
|
77 |
-
|
78 |
return (object) $this->response;
|
79 |
}
|
80 |
|
@@ -174,29 +163,43 @@ class Data extends JobExecutable
|
|
174 |
}
|
175 |
|
176 |
/**
|
177 |
-
*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
178 |
* @return bool
|
179 |
*/
|
180 |
protected function step1() {
|
181 |
-
$this->log( "
|
182 |
|
183 |
if( false === $this->isTable( $this->prefix . 'options' ) ) {
|
184 |
return true;
|
185 |
}
|
186 |
|
187 |
// Installed in sub-directory
|
188 |
-
//if( isset( $this->settings->wpSubDirectory ) && "1" === $this->settings->wpSubDirectory ) {
|
189 |
if( $this->isSubDir() ) {
|
190 |
-
$
|
191 |
-
$this->log( "Updating siteurl and homeurl to " . get_home_url() . '/' . $subDirectory . $this->options->cloneDirectoryName );
|
192 |
// Replace URLs
|
193 |
$result = $this->db->query(
|
194 |
$this->db->prepare(
|
195 |
-
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'siteurl' or option_name='home'", get_home_url()
|
196 |
)
|
197 |
);
|
198 |
} else {
|
199 |
-
$this->log( "
|
200 |
// Replace URLs
|
201 |
$result = $this->db->query(
|
202 |
$this->db->prepare(
|
@@ -211,7 +214,7 @@ class Data extends JobExecutable
|
|
211 |
return true;
|
212 |
}
|
213 |
|
214 |
-
$this->log( "
|
215 |
return false;
|
216 |
}
|
217 |
|
@@ -222,7 +225,7 @@ class Data extends JobExecutable
|
|
222 |
protected function step2()
|
223 |
{
|
224 |
|
225 |
-
$this->log( "
|
226 |
|
227 |
if( false === $this->isTable( $this->prefix . 'options' ) ) {
|
228 |
return true;
|
@@ -252,7 +255,7 @@ class Data extends JobExecutable
|
|
252 |
return true;
|
253 |
}
|
254 |
|
255 |
-
$this->log("
|
256 |
return false;
|
257 |
}
|
258 |
|
@@ -263,7 +266,7 @@ class Data extends JobExecutable
|
|
263 |
protected function step3()
|
264 |
{
|
265 |
|
266 |
-
$this->log("
|
267 |
|
268 |
if( false === $this->isTable( $this->prefix . 'options' ) ) {
|
269 |
return true;
|
@@ -282,7 +285,7 @@ class Data extends JobExecutable
|
|
282 |
return true;
|
283 |
}
|
284 |
|
285 |
-
$this->log("Failed to update rewrite_rules in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_ERROR);
|
286 |
return true;
|
287 |
}
|
288 |
|
@@ -291,7 +294,7 @@ class Data extends JobExecutable
|
|
291 |
* @return bool
|
292 |
*/
|
293 |
protected function step4() {
|
294 |
-
$this->log( "
|
295 |
|
296 |
if( false === $this->isTable( $this->prefix . 'usermeta' ) ) {
|
297 |
return true;
|
@@ -304,11 +307,11 @@ class Data extends JobExecutable
|
|
304 |
);
|
305 |
|
306 |
if( !$resultOptions ) {
|
307 |
-
$this->log( "
|
308 |
-
return false;
|
309 |
}
|
310 |
|
311 |
-
$this->log( "Updating {$this->prefix}options
|
312 |
|
313 |
$resultUserMeta = $this->db->query(
|
314 |
$this->db->prepare(
|
@@ -317,8 +320,8 @@ class Data extends JobExecutable
|
|
317 |
);
|
318 |
|
319 |
if( !$resultUserMeta ) {
|
320 |
-
$this->log( "
|
321 |
-
return false;
|
322 |
}
|
323 |
|
324 |
return true;
|
@@ -332,10 +335,10 @@ class Data extends JobExecutable
|
|
332 |
{
|
333 |
$path = ABSPATH . $this->options->cloneDirectoryName . "/wp-config.php";
|
334 |
|
335 |
-
$this->log("
|
336 |
if (false === ($content = file_get_contents($path)))
|
337 |
{
|
338 |
-
$this->log("
|
339 |
return false;
|
340 |
}
|
341 |
|
@@ -347,7 +350,7 @@ class Data extends JobExecutable
|
|
347 |
|
348 |
if (false === @file_put_contents($path, $content))
|
349 |
{
|
350 |
-
$this->log("
|
351 |
return false;
|
352 |
}
|
353 |
|
@@ -366,7 +369,7 @@ class Data extends JobExecutable
|
|
366 |
|
367 |
if (!$this->isSubDir())
|
368 |
{
|
369 |
-
$this->debugLog("
|
370 |
return true;
|
371 |
}
|
372 |
|
@@ -374,7 +377,7 @@ class Data extends JobExecutable
|
|
374 |
|
375 |
if (false === ($content = file_get_contents($path)))
|
376 |
{
|
377 |
-
$this->log("
|
378 |
return false;
|
379 |
}
|
380 |
|
@@ -382,12 +385,12 @@ class Data extends JobExecutable
|
|
382 |
if (!preg_match("/(require(.*)wp-blog-header.php' \);)/", $content, $matches))
|
383 |
{
|
384 |
$this->log(
|
385 |
-
"
|
386 |
Logger::TYPE_ERROR
|
387 |
);
|
388 |
return false;
|
389 |
}
|
390 |
-
$this->log("
|
391 |
|
392 |
$pattern = "/require(.*) dirname(.*) __FILE__ (.*) \. '(.*)wp-blog-header.php'(.*);/";
|
393 |
|
@@ -398,16 +401,16 @@ class Data extends JobExecutable
|
|
398 |
|
399 |
if (null === ($content = preg_replace(array($pattern), $replace, $content)))
|
400 |
{
|
401 |
-
$this->log("
|
402 |
return false;
|
403 |
}
|
404 |
|
405 |
if (false === @file_put_contents($path, $content))
|
406 |
{
|
407 |
-
$this->log("
|
408 |
return false;
|
409 |
}
|
410 |
-
$this->Log("
|
411 |
return true;
|
412 |
}
|
413 |
|
@@ -418,7 +421,7 @@ class Data extends JobExecutable
|
|
418 |
protected function step7()
|
419 |
{
|
420 |
|
421 |
-
$this->log("
|
422 |
|
423 |
if( false === $this->isTable( $this->prefix . 'options' ) ) {
|
424 |
return true;
|
@@ -434,7 +437,7 @@ class Data extends JobExecutable
|
|
434 |
// All good
|
435 |
if ($result)
|
436 |
{
|
437 |
-
$this->Log("
|
438 |
return true;
|
439 |
}
|
440 |
|
@@ -449,7 +452,7 @@ class Data extends JobExecutable
|
|
449 |
protected function step8()
|
450 |
{
|
451 |
|
452 |
-
$this->log("
|
453 |
|
454 |
if( false === $this->isTable( $this->prefix . 'options' ) ) {
|
455 |
return true;
|
@@ -465,7 +468,7 @@ class Data extends JobExecutable
|
|
465 |
// All good
|
466 |
if ($result)
|
467 |
{
|
468 |
-
$this->Log("
|
469 |
return true;
|
470 |
}
|
471 |
|
@@ -479,7 +482,7 @@ class Data extends JobExecutable
|
|
479 |
protected function step9()
|
480 |
{
|
481 |
|
482 |
-
$this->log("
|
483 |
|
484 |
if( false === $this->isTable( $this->prefix . 'options' ) ) {
|
485 |
return true;
|
@@ -495,15 +498,112 @@ class Data extends JobExecutable
|
|
495 |
// All good
|
496 |
if ($result)
|
497 |
{
|
498 |
-
$this->Log("
|
499 |
return true;
|
500 |
}
|
501 |
|
502 |
-
$this->log("
|
503 |
return true;
|
504 |
}
|
505 |
|
506 |
/**
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
507 |
* Check if WP is installed in subdir
|
508 |
* @return boolean
|
509 |
*/
|
49 |
*/
|
50 |
protected function calculateTotalSteps()
|
51 |
{
|
52 |
+
$this->options->totalSteps = 11;
|
53 |
}
|
54 |
|
55 |
/**
|
64 |
// Save option, progress
|
65 |
$this->saveOptions();
|
66 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
67 |
return (object) $this->response;
|
68 |
}
|
69 |
|
163 |
}
|
164 |
|
165 |
/**
|
166 |
+
* Get the install sub directory if WP is installed in sub directory
|
167 |
+
* @return string
|
168 |
+
*/
|
169 |
+
protected function getSubDir(){
|
170 |
+
$home = get_option('home');
|
171 |
+
$siteurl = get_option('siteurl');
|
172 |
+
|
173 |
+
if (empty($home) || empty($siteurl)){
|
174 |
+
return '/';
|
175 |
+
}
|
176 |
+
|
177 |
+
$dir = str_replace($home, '', $siteurl);
|
178 |
+
return '/' . str_replace('/', '', $dir) . '/';
|
179 |
+
}
|
180 |
+
|
181 |
+
/**
|
182 |
+
* Replace "siteurl" and "home"
|
183 |
* @return bool
|
184 |
*/
|
185 |
protected function step1() {
|
186 |
+
$this->log( "Preparing Data Step1: Updating siteurl and homeurl in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_INFO );
|
187 |
|
188 |
if( false === $this->isTable( $this->prefix . 'options' ) ) {
|
189 |
return true;
|
190 |
}
|
191 |
|
192 |
// Installed in sub-directory
|
|
|
193 |
if( $this->isSubDir() ) {
|
194 |
+
$this->log( "Preparing Data Step1: Updating siteurl and homeurl to " . rtrim(get_home_url(), "/") . $this->getSubDir() . $this->options->cloneDirectoryName );
|
|
|
195 |
// Replace URLs
|
196 |
$result = $this->db->query(
|
197 |
$this->db->prepare(
|
198 |
+
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'siteurl' or option_name='home'", rtrim(get_home_url(), "/") . $this->getSubDir() . $this->options->cloneDirectoryName
|
199 |
)
|
200 |
);
|
201 |
} else {
|
202 |
+
$this->log( "Preparing Data Step1: Updating siteurl and homeurl to " . rtrim(get_home_url(), "/") . '/' . $this->options->cloneDirectoryName );
|
203 |
// Replace URLs
|
204 |
$result = $this->db->query(
|
205 |
$this->db->prepare(
|
214 |
return true;
|
215 |
}
|
216 |
|
217 |
+
$this->log( "Preparing Data Step1: Failed to update siteurl and homeurl in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_ERROR );
|
218 |
return false;
|
219 |
}
|
220 |
|
225 |
protected function step2()
|
226 |
{
|
227 |
|
228 |
+
$this->log( "Preparing Data Step2: Updating row wpstg_is_staging_site in {$this->prefix}options {$this->db->last_error}" );
|
229 |
|
230 |
if( false === $this->isTable( $this->prefix . 'options' ) ) {
|
231 |
return true;
|
255 |
return true;
|
256 |
}
|
257 |
|
258 |
+
$this->log("Preparing Data Step2: Failed to update wpstg_is_staging_site in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_ERROR);
|
259 |
return false;
|
260 |
}
|
261 |
|
266 |
protected function step3()
|
267 |
{
|
268 |
|
269 |
+
$this->log("Preparing Data Step3: Updating rewrite_rules in {$this->prefix}options {$this->db->last_error}");
|
270 |
|
271 |
if( false === $this->isTable( $this->prefix . 'options' ) ) {
|
272 |
return true;
|
285 |
return true;
|
286 |
}
|
287 |
|
288 |
+
$this->log("Preparing Data Step3: Failed to update rewrite_rules in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_ERROR);
|
289 |
return true;
|
290 |
}
|
291 |
|
294 |
* @return bool
|
295 |
*/
|
296 |
protected function step4() {
|
297 |
+
$this->log( "Preparing Data Step4: Updating db prefix in {$this->prefix}usermeta. Error: {$this->db->last_error}" );
|
298 |
|
299 |
if( false === $this->isTable( $this->prefix . 'usermeta' ) ) {
|
300 |
return true;
|
307 |
);
|
308 |
|
309 |
if( !$resultOptions ) {
|
310 |
+
$this->log( "Preparing Data Step4: Failed to update {$this->prefix}usermeta meta_key database table prefixes; {$this->db->last_error}", Logger::TYPE_ERROR );
|
311 |
+
//return false;
|
312 |
}
|
313 |
|
314 |
+
$this->log( "Updating db prefixes in {$this->prefix}options. Error: {$this->db->last_error}" );
|
315 |
|
316 |
$resultUserMeta = $this->db->query(
|
317 |
$this->db->prepare(
|
320 |
);
|
321 |
|
322 |
if( !$resultUserMeta ) {
|
323 |
+
$this->log( "Preparing Data Step4: Failed to update db prefixes in {$this->prefix}options. Error: {$this->db->last_error}", Logger::TYPE_ERROR );
|
324 |
+
//return false;
|
325 |
}
|
326 |
|
327 |
return true;
|
335 |
{
|
336 |
$path = ABSPATH . $this->options->cloneDirectoryName . "/wp-config.php";
|
337 |
|
338 |
+
$this->log("Preparing Data Step5: Updating table_prefix in {$path} to " . $this->prefix);
|
339 |
if (false === ($content = file_get_contents($path)))
|
340 |
{
|
341 |
+
$this->log("Preparing Data Step5: Failed to update table_prefix in {$path}. Can't read contents", Logger::TYPE_ERROR);
|
342 |
return false;
|
343 |
}
|
344 |
|
350 |
|
351 |
if (false === @file_put_contents($path, $content))
|
352 |
{
|
353 |
+
$this->log("Preparing Data Step5: Failed to update $table_prefix in {$path} to " .$this->prefix . ". Can't save contents", Logger::TYPE_ERROR);
|
354 |
return false;
|
355 |
}
|
356 |
|
369 |
|
370 |
if (!$this->isSubDir())
|
371 |
{
|
372 |
+
$this->debugLog("Preparing Data Step6: WP installation is not in a subdirectory! All good, skipping this step");
|
373 |
return true;
|
374 |
}
|
375 |
|
377 |
|
378 |
if (false === ($content = file_get_contents($path)))
|
379 |
{
|
380 |
+
$this->log("Preparing Data Step6: Failed to reset {$path} for sub directory; can't read contents", Logger::TYPE_ERROR);
|
381 |
return false;
|
382 |
}
|
383 |
|
385 |
if (!preg_match("/(require(.*)wp-blog-header.php' \);)/", $content, $matches))
|
386 |
{
|
387 |
$this->log(
|
388 |
+
"Preparing Data Step6: Failed to reset index.php for sub directory; wp-blog-header.php is missing",
|
389 |
Logger::TYPE_ERROR
|
390 |
);
|
391 |
return false;
|
392 |
}
|
393 |
+
$this->log("Preparing Data: WP installation is in a subdirectory. Progressing...");
|
394 |
|
395 |
$pattern = "/require(.*) dirname(.*) __FILE__ (.*) \. '(.*)wp-blog-header.php'(.*);/";
|
396 |
|
401 |
|
402 |
if (null === ($content = preg_replace(array($pattern), $replace, $content)))
|
403 |
{
|
404 |
+
$this->log("Preparing Data: Failed to reset index.php for sub directory; replacement failed", Logger::TYPE_ERROR);
|
405 |
return false;
|
406 |
}
|
407 |
|
408 |
if (false === @file_put_contents($path, $content))
|
409 |
{
|
410 |
+
$this->log("Preparing Data: Failed to reset index.php for sub directory; can't save contents", Logger::TYPE_ERROR);
|
411 |
return false;
|
412 |
}
|
413 |
+
$this->Log("Preparing Data: Finished Step 6 successfully");
|
414 |
return true;
|
415 |
}
|
416 |
|
421 |
protected function step7()
|
422 |
{
|
423 |
|
424 |
+
$this->log("Preparing Data Step7: Updating wpstg_rmpermalinks_executed in {$this->prefix}options {$this->db->last_error}");
|
425 |
|
426 |
if( false === $this->isTable( $this->prefix . 'options' ) ) {
|
427 |
return true;
|
437 |
// All good
|
438 |
if ($result)
|
439 |
{
|
440 |
+
$this->Log("Preparing Data Step7: Finished Step 7 successfully");
|
441 |
return true;
|
442 |
}
|
443 |
|
452 |
protected function step8()
|
453 |
{
|
454 |
|
455 |
+
$this->log("Preparing Data Step8: Updating permalink_structure in {$this->prefix}options {$this->db->last_error}");
|
456 |
|
457 |
if( false === $this->isTable( $this->prefix . 'options' ) ) {
|
458 |
return true;
|
468 |
// All good
|
469 |
if ($result)
|
470 |
{
|
471 |
+
$this->Log("Preparing Data Step8: Finished Step 8 successfully");
|
472 |
return true;
|
473 |
}
|
474 |
|
482 |
protected function step9()
|
483 |
{
|
484 |
|
485 |
+
$this->log("Preparing Data Step9: Set staging site to noindex");
|
486 |
|
487 |
if( false === $this->isTable( $this->prefix . 'options' ) ) {
|
488 |
return true;
|
498 |
// All good
|
499 |
if ($result)
|
500 |
{
|
501 |
+
$this->Log("Preparing Data Step9: Finished Step 9 successfully");
|
502 |
return true;
|
503 |
}
|
504 |
|
505 |
+
$this->log("Can not update staging site to noindex. Possible already done!", Logger::TYPE_WARNING);
|
506 |
return true;
|
507 |
}
|
508 |
|
509 |
/**
|
510 |
+
* Update WP_HOME in wp-config.php
|
511 |
+
* @return bool
|
512 |
+
*/
|
513 |
+
protected function step10() {
|
514 |
+
$path = ABSPATH . $this->options->cloneDirectoryName . "/wp-config.php";
|
515 |
+
|
516 |
+
$this->log( "Preparing Data Step10: Updating WP_HOME in wp-config.php to " . $this->getStagingSiteUrl() );
|
517 |
+
|
518 |
+
if( false === ($content = file_get_contents( $path )) ) {
|
519 |
+
$this->log( "Preparing Data Step10: Failed to update WP_HOME in wp-config.php. Can't read wp-config.php", Logger::TYPE_ERROR );
|
520 |
+
return false;
|
521 |
+
}
|
522 |
+
|
523 |
+
|
524 |
+
// Get WP_HOME from wp-config.php
|
525 |
+
preg_match( "/define\s*\(\s*'WP_HOME'\s*,\s*'(.*)'\s*\);/", $content, $matches );
|
526 |
+
|
527 |
+
if( !empty( $matches[1] ) ) {
|
528 |
+
$matches[1];
|
529 |
+
|
530 |
+
$pattern = "/define\s*\(\s*'WP_HOME'\s*,\s*'(.*)'\s*\);/";
|
531 |
+
|
532 |
+
$replace = "define('WP_HOME','" . $this->getStagingSiteUrl() . "'); // " . $matches[1];
|
533 |
+
$replace.= " // Changed by WP-Staging";
|
534 |
+
|
535 |
+
if( null === ($content = preg_replace( array($pattern), $replace, $content )) ) {
|
536 |
+
$this->log( "Preparing Data: Failed to reset index.php for sub directory; replacement failed", Logger::TYPE_ERROR );
|
537 |
+
return false;
|
538 |
+
}
|
539 |
+
} else {
|
540 |
+
$this->log( "Preparing Data Step10: WP_HOME not defined in wp-config.php. Skipping this step." );
|
541 |
+
}
|
542 |
+
|
543 |
+
if( false === @file_put_contents( $path, $content ) ) {
|
544 |
+
$this->log( "Preparing Data Step11: Failed to update WP_SITEURL. Can't save contents", Logger::TYPE_ERROR );
|
545 |
+
return false;
|
546 |
+
}
|
547 |
+
$this->Log( "Preparing Data: Finished Step 11 successfully" );
|
548 |
+
return true;
|
549 |
+
}
|
550 |
+
|
551 |
+
/**
|
552 |
+
* Update WP_SITEURL in wp-config.php
|
553 |
+
* @return bool
|
554 |
+
*/
|
555 |
+
protected function step11() {
|
556 |
+
$path = ABSPATH . $this->options->cloneDirectoryName . "/wp-config.php";
|
557 |
+
|
558 |
+
$this->log( "Preparing Data Step11: Updating WP_SITEURL in wp-config.php to " . $this->getStagingSiteUrl() );
|
559 |
+
|
560 |
+
if( false === ($content = file_get_contents( $path )) ) {
|
561 |
+
$this->log( "Preparing Data Step11: Failed to update WP_SITEURL in wp-config.php. Can't read wp-config.php", Logger::TYPE_ERROR );
|
562 |
+
return false;
|
563 |
+
}
|
564 |
+
|
565 |
+
|
566 |
+
// Get WP_SITEURL from wp-config.php
|
567 |
+
preg_match( "/define\s*\(\s*'WP_SITEURL'\s*,\s*'(.*)'\s*\);/", $content, $matches );
|
568 |
+
|
569 |
+
if( !empty( $matches[1] ) ) {
|
570 |
+
$matches[1];
|
571 |
+
|
572 |
+
$pattern = "/define\s*\(\s*'WP_SITEURL'\s*,\s*'(.*)'\s*\);/";
|
573 |
+
|
574 |
+
$replace = "define('WP_SITEURL','" . $this->getStagingSiteUrl() . "'); // " . $matches[1];
|
575 |
+
$replace.= " // Changed by WP-Staging";
|
576 |
+
|
577 |
+
if( null === ($content = preg_replace( array($pattern), $replace, $content )) ) {
|
578 |
+
$this->log( "Preparing Data Step11: Failed to update WP_SITEURL", Logger::TYPE_ERROR );
|
579 |
+
return false;
|
580 |
+
}
|
581 |
+
} else {
|
582 |
+
$this->log( "Preparing Data Step11: WP_SITEURL not defined in wp-config.php. Skipping this step." );
|
583 |
+
}
|
584 |
+
|
585 |
+
|
586 |
+
if( false === @file_put_contents( $path, $content ) ) {
|
587 |
+
$this->log( "Preparing Data Step11: Failed to update WP_SITEURL. Can't save contents", Logger::TYPE_ERROR );
|
588 |
+
return false;
|
589 |
+
}
|
590 |
+
$this->Log( "Preparing Data: Finished Step 11 successfully" );
|
591 |
+
return true;
|
592 |
+
}
|
593 |
+
|
594 |
+
/**
|
595 |
+
* Return URL to staging site
|
596 |
+
* @return string
|
597 |
+
*/
|
598 |
+
protected function getStagingSiteUrl() {
|
599 |
+
if( $this->isSubDir() ) {
|
600 |
+
return rtrim( get_home_url(), "/" ) . $this->getSubDir() . $this->options->cloneDirectoryName;
|
601 |
+
}
|
602 |
+
|
603 |
+
return rtrim( get_home_url(), "/" ) . '/' . $this->options->cloneDirectoryName;
|
604 |
+
}
|
605 |
+
|
606 |
+
/**
|
607 |
* Check if WP is installed in subdir
|
608 |
* @return boolean
|
609 |
*/
|
apps/Backend/Modules/Jobs/Database.php
CHANGED
@@ -147,7 +147,7 @@ class Database extends JobExecutable
|
|
147 |
{
|
148 |
$rows = $this->options->job->start+$this->settings->queryLimit;
|
149 |
$this->log(
|
150 |
-
"DB Copy: {$old} as {$new}
|
151 |
);
|
152 |
|
153 |
$limitation = '';
|
@@ -193,7 +193,7 @@ class Database extends JobExecutable
|
|
193 |
return true;
|
194 |
}
|
195 |
|
196 |
-
$this->log("DB Copy: Creating table {$new}
|
197 |
|
198 |
$this->db->query("CREATE TABLE {$new} LIKE {$old}");
|
199 |
|
147 |
{
|
148 |
$rows = $this->options->job->start+$this->settings->queryLimit;
|
149 |
$this->log(
|
150 |
+
"DB Copy: {$old} as {$new} from {$this->options->job->start} to {$rows} records"
|
151 |
);
|
152 |
|
153 |
$limitation = '';
|
193 |
return true;
|
194 |
}
|
195 |
|
196 |
+
$this->log("DB Copy: Creating table {$new}");
|
197 |
|
198 |
$this->db->query("CREATE TABLE {$new} LIKE {$old}");
|
199 |
|
apps/Backend/Modules/Jobs/Directories.php
CHANGED
@@ -3,12 +3,13 @@
|
|
3 |
namespace WPStaging\Backend\Modules\Jobs;
|
4 |
|
5 |
// No Direct Access
|
6 |
-
if
|
7 |
-
|
8 |
}
|
9 |
|
10 |
-
use WPStaging\WPStaging;
|
11 |
use WPStaging\Utils\Logger;
|
|
|
12 |
use WPStaging\Iterators\RecursiveDirectoryIterator;
|
13 |
use WPStaging\Iterators\RecursiveFilterNewLine;
|
14 |
use WPStaging\Iterators\RecursiveFilterExclude;
|
@@ -19,409 +20,509 @@ use WPStaging\Iterators\RecursiveFilterExclude;
|
|
19 |
*/
|
20 |
class Directories extends JobExecutable {
|
21 |
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
/**
|
28 |
-
* Total steps to do
|
29 |
-
* @var int
|
30 |
-
*/
|
31 |
-
private $total = 4;
|
32 |
-
private $fileHandle;
|
33 |
-
|
34 |
-
private $filename;
|
35 |
-
|
36 |
-
/**
|
37 |
-
* Initialize
|
38 |
-
*/
|
39 |
-
public function initialize() {
|
40 |
-
$this->filename = $this->cache->getCacheDir() . "files_to_copy." . $this->cache->getCacheExtension();
|
41 |
-
}
|
42 |
-
|
43 |
-
/**
|
44 |
-
* Calculate Total Steps in This Job and Assign It to $this->options->totalSteps
|
45 |
-
* @return void
|
46 |
-
*/
|
47 |
-
protected function calculateTotalSteps() {
|
48 |
-
$this->options->totalSteps = $this->total;
|
49 |
-
}
|
50 |
-
|
51 |
-
/**
|
52 |
-
* Start Module
|
53 |
-
* @return object
|
54 |
-
*/
|
55 |
-
public function start() {
|
56 |
-
|
57 |
-
// Execute steps
|
58 |
-
$this->run();
|
59 |
-
|
60 |
-
// Save option, progress
|
61 |
-
$this->saveProgress();
|
62 |
-
|
63 |
-
return (object) $this->response;
|
64 |
-
}
|
65 |
-
|
66 |
-
/**
|
67 |
-
* Step 1
|
68 |
-
* Get WP Root files
|
69 |
-
*/
|
70 |
-
private function getWpRootFiles() {
|
71 |
-
|
72 |
-
// Skip it
|
73 |
-
// if ($this->isDirectoryExcluded(ABSPATH)){
|
74 |
-
// return true;
|
75 |
-
// }
|
76 |
-
|
77 |
-
// open file handle
|
78 |
-
$files = $this->open($this->filename, 'a');
|
79 |
|
|
|
|
|
|
|
|
|
|
|
80 |
|
81 |
-
|
|
|
|
|
|
|
|
|
82 |
|
83 |
-
|
84 |
-
|
|
|
|
|
|
|
|
|
85 |
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
if ($this->write($files, $iterator->getFilename() . PHP_EOL)) {
|
92 |
-
$this->options->totalFiles++;
|
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 |
-
// Exclude uploads, plugins or themes
|
140 |
-
$iterator = new \WPStaging\Iterators\RecursiveFilterExclude($iterator, apply_filters('wpstg_exclude_content', $excludeWpContent));
|
141 |
-
// Recursively iterate over content directory
|
142 |
-
$iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::LEAVES_ONLY, \RecursiveIteratorIterator::CATCH_GET_CHILD);
|
143 |
-
|
144 |
-
$path = 'wp-content' . DIRECTORY_SEPARATOR . $iterator->getSubPathName();
|
145 |
-
$this->log( "Scanning {$path} for its sub-directories and files" );
|
146 |
-
|
147 |
-
// Write path line
|
148 |
-
foreach ($iterator as $item) {
|
149 |
-
if ($item->isFile()) {
|
150 |
-
if ($this->write($files, 'wp-content' . DIRECTORY_SEPARATOR . $iterator->getSubPathName() . PHP_EOL)) {
|
151 |
-
$this->options->totalFiles++;
|
152 |
-
|
153 |
-
// Add current file size
|
154 |
-
$this->options->totalFileSize += $iterator->getSize();
|
155 |
-
}
|
156 |
-
}
|
157 |
-
}
|
158 |
-
} catch (\Exception $e) {
|
159 |
-
//$this->returnException('Out of disk space.');
|
160 |
-
throw new \Exception('Error: ' . $e->getMessage());
|
161 |
-
} catch (\Exception $e) {
|
162 |
-
// Skip bad file permissions
|
163 |
-
}
|
164 |
-
|
165 |
-
// close the file handler
|
166 |
-
$this->close($files);
|
167 |
-
return true;
|
168 |
-
}
|
169 |
-
|
170 |
-
/**
|
171 |
-
* Step 3
|
172 |
-
* @return boolean
|
173 |
-
* @throws \Exception
|
174 |
-
*/
|
175 |
-
public function getWpIncludesFiles() {
|
176 |
-
|
177 |
-
// Skip it
|
178 |
-
if ($this->isDirectoryExcluded(ABSPATH . 'wp-includes' . DIRECTORY_SEPARATOR)){
|
179 |
-
return true;
|
180 |
-
}
|
181 |
-
|
182 |
-
// open file handle and attach data to end of file
|
183 |
-
$files = $this->open($this->filename, 'a');
|
184 |
-
|
185 |
-
try {
|
186 |
-
|
187 |
-
// Iterate over wp-admin directory
|
188 |
-
$iterator = new \WPStaging\Iterators\RecursiveDirectoryIterator(ABSPATH . 'wp-includes' . DIRECTORY_SEPARATOR);
|
189 |
-
|
190 |
-
// Exclude new line file names
|
191 |
-
$iterator = new \WPStaging\Iterators\RecursiveFilterNewLine($iterator);
|
192 |
-
|
193 |
-
// Exclude uploads, plugins or themes
|
194 |
-
//$iterator = new \WPStaging\Iterators\RecursiveFilterExclude($iterator, apply_filters('wpstg_exclude_content', $exclude_filters));
|
195 |
-
// Recursively iterate over wp-includes directory
|
196 |
-
$iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::LEAVES_ONLY, \RecursiveIteratorIterator::CATCH_GET_CHILD);
|
197 |
-
|
198 |
-
$path = ABSPATH . 'wp-includes' . DIRECTORY_SEPARATOR;
|
199 |
-
$this->log( "Scanning {$path} for its sub-directories and files" );
|
200 |
-
|
201 |
-
// Write files
|
202 |
-
foreach ($iterator as $item) {
|
203 |
-
if ($item->isFile()) {
|
204 |
-
if ($this->write($files, 'wp-includes' . DIRECTORY_SEPARATOR . $iterator->getSubPathName() . PHP_EOL)) {
|
205 |
-
$this->options->totalFiles++;
|
206 |
-
|
207 |
-
// Add current file size
|
208 |
-
$this->options->totalFileSize += $iterator->getSize();
|
209 |
-
}
|
210 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
211 |
}
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
222 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
223 |
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
*/
|
229 |
-
public function getWpAdminFiles() {
|
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 |
-
return false;
|
341 |
-
}
|
342 |
-
|
343 |
-
|
344 |
-
if ($this->options->currentStep == 0) {
|
345 |
-
$this->getWpRootFiles();
|
346 |
-
$this->prepareResponse(false, true);
|
347 |
-
return false;
|
348 |
-
}
|
349 |
-
|
350 |
-
if ($this->options->currentStep == 1) {
|
351 |
-
$this->getWpContentFiles();
|
352 |
-
$this->prepareResponse(false, true);
|
353 |
-
return false;
|
354 |
-
}
|
355 |
-
|
356 |
-
if ($this->options->currentStep == 2) {
|
357 |
-
$this->getWpIncludesFiles();
|
358 |
-
$this->prepareResponse(false, true);
|
359 |
-
return false;
|
360 |
-
}
|
361 |
-
|
362 |
-
if ($this->options->currentStep == 3) {
|
363 |
-
$this->getWpAdminFiles();
|
364 |
-
$this->prepareResponse(false, true);
|
365 |
-
return false;
|
366 |
-
}
|
367 |
-
|
368 |
-
|
369 |
-
// Prepare response
|
370 |
-
$this->prepareResponse(false, true);
|
371 |
-
// Not finished
|
372 |
-
return true;
|
373 |
-
}
|
374 |
-
|
375 |
-
/**
|
376 |
-
* Checks Whether There is Any Job to Execute or Not
|
377 |
-
* @return bool
|
378 |
-
*/
|
379 |
-
protected function isFinished() {
|
380 |
-
return (
|
381 |
-
$this->options->currentStep > $this->total ||
|
382 |
-
$this->options->currentStep == 4
|
383 |
-
);
|
384 |
-
}
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
/**
|
390 |
-
* Save files
|
391 |
-
* @return bool
|
392 |
-
*/
|
393 |
-
protected function saveProgress() {
|
394 |
-
return $this->saveOptions();
|
395 |
-
}
|
396 |
-
|
397 |
-
/**
|
398 |
-
* Get files
|
399 |
-
* @return void
|
400 |
*/
|
401 |
-
|
402 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
403 |
|
404 |
-
|
405 |
-
|
406 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
407 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
408 |
|
409 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
410 |
}
|
411 |
|
412 |
-
/**
|
413 |
-
* Check if directory is excluded
|
414 |
-
* @param string $directory
|
415 |
-
* @return bool
|
416 |
-
*/
|
417 |
-
protected function isDirectoryExcluded($directory) {
|
418 |
-
foreach ($this->options->excludedDirectories as $excludedDirectory) {
|
419 |
-
if (strpos($directory, $excludedDirectory) === 0) {
|
420 |
-
return true;
|
421 |
-
}
|
422 |
-
}
|
423 |
|
424 |
-
|
425 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
426 |
|
427 |
}
|
3 |
namespace WPStaging\Backend\Modules\Jobs;
|
4 |
|
5 |
// No Direct Access
|
6 |
+
if( !defined( "WPINC" ) ) {
|
7 |
+
die;
|
8 |
}
|
9 |
|
10 |
+
use WPStaging\WPStaging;
|
11 |
use WPStaging\Utils\Logger;
|
12 |
+
use WPStaging\Utils\Strings;
|
13 |
use WPStaging\Iterators\RecursiveDirectoryIterator;
|
14 |
use WPStaging\Iterators\RecursiveFilterNewLine;
|
15 |
use WPStaging\Iterators\RecursiveFilterExclude;
|
20 |
*/
|
21 |
class Directories extends JobExecutable {
|
22 |
|
23 |
+
/**
|
24 |
+
* @var array
|
25 |
+
*/
|
26 |
+
private $files = array();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
27 |
|
28 |
+
/**
|
29 |
+
* Total steps to do
|
30 |
+
* @var int
|
31 |
+
*/
|
32 |
+
private $total = 4;
|
33 |
|
34 |
+
/**
|
35 |
+
* path to the cache file
|
36 |
+
* @var string
|
37 |
+
*/
|
38 |
+
private $filename;
|
39 |
|
40 |
+
/**
|
41 |
+
* Initialize
|
42 |
+
*/
|
43 |
+
public function initialize() {
|
44 |
+
$this->filename = $this->cache->getCacheDir() . "files_to_copy." . $this->cache->getCacheExtension();
|
45 |
+
}
|
46 |
|
47 |
+
/**
|
48 |
+
* Calculate Total Steps in This Job and Assign It to $this->options->totalSteps
|
49 |
+
* @return void
|
50 |
+
*/
|
51 |
+
protected function calculateTotalSteps() {
|
|
|
|
|
52 |
|
53 |
+
$this->options->totalSteps = $this->total + count( $this->options->extraDirectories );
|
54 |
+
}
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Start Module
|
58 |
+
* @return object
|
59 |
+
*/
|
60 |
+
public function start() {
|
61 |
+
|
62 |
+
// Execute steps
|
63 |
+
$this->run();
|
64 |
+
|
65 |
+
// Save option, progress
|
66 |
+
$this->saveProgress();
|
67 |
+
|
68 |
+
return ( object ) $this->response;
|
69 |
+
}
|
70 |
+
|
71 |
+
/**
|
72 |
+
* Step 0
|
73 |
+
* Get WP Root files
|
74 |
+
* Does not collect any sub folders
|
75 |
+
*/
|
76 |
+
private function getWpRootFiles() {
|
77 |
+
|
78 |
+
// open file handle
|
79 |
+
$files = $this->open( $this->filename, 'a' );
|
80 |
+
|
81 |
+
|
82 |
+
try {
|
83 |
+
|
84 |
+
// Iterate over wp root directory
|
85 |
+
$iterator = new \DirectoryIterator( ABSPATH );
|
86 |
+
|
87 |
+
$this->log( "Scanning / for files" );
|
88 |
+
|
89 |
+
// Write path line
|
90 |
+
foreach ( $iterator as $item ) {
|
91 |
+
if( !$item->isDot() && $item->isFile() ) {
|
92 |
+
if( $this->write( $files, $iterator->getFilename() . PHP_EOL ) ) {
|
93 |
+
$this->options->totalFiles++;
|
94 |
+
|
95 |
+
// Add current file size
|
96 |
+
$this->options->totalFileSize += $iterator->getSize();
|
97 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
98 |
}
|
99 |
+
}
|
100 |
+
} catch ( \Exception $e ) {
|
101 |
+
$this->returnException( 'Error: ' . $e->getMessage() );
|
102 |
+
//throw new \Exception('Out of disk space.');
|
103 |
+
} catch ( \Exception $e ) {
|
104 |
+
// Skip bad file permissions
|
105 |
+
}
|
106 |
+
|
107 |
+
$this->close( $files );
|
108 |
+
return true;
|
109 |
+
}
|
110 |
+
|
111 |
+
/**
|
112 |
+
* Step 2
|
113 |
+
* Get WP Content Files
|
114 |
+
*/
|
115 |
+
private function getWpContentFiles() {
|
116 |
+
|
117 |
+
// Skip it
|
118 |
+
if( $this->isDirectoryExcluded( WP_CONTENT_DIR ) ) {
|
119 |
+
return true;
|
120 |
+
}
|
121 |
+
// open file handle
|
122 |
+
$files = $this->open( $this->filename, 'a' );
|
123 |
+
|
124 |
+
$excludeWpContent = array(
|
125 |
+
'cache',
|
126 |
+
'wps-hide-login',
|
127 |
+
'node_modules',
|
128 |
+
'nbproject'
|
129 |
+
);
|
130 |
+
|
131 |
+
try {
|
132 |
+
|
133 |
+
// Iterate over content directory
|
134 |
+
$iterator = new \WPStaging\Iterators\RecursiveDirectoryIterator( WP_CONTENT_DIR );
|
135 |
+
|
136 |
+
// Exclude new line file names
|
137 |
+
$iterator = new \WPStaging\Iterators\RecursiveFilterNewLine( $iterator );
|
138 |
+
|
139 |
+
// Exclude uploads, plugins or themes
|
140 |
+
$iterator = new \WPStaging\Iterators\RecursiveFilterExclude( $iterator, apply_filters( 'wpstg_exclude_content', $excludeWpContent ) );
|
141 |
+
// Recursively iterate over content directory
|
142 |
+
$iterator = new \RecursiveIteratorIterator( $iterator, \RecursiveIteratorIterator::LEAVES_ONLY, \RecursiveIteratorIterator::CATCH_GET_CHILD );
|
143 |
+
|
144 |
+
$this->log( "Scanning /wp-content for its sub-directories and files" );
|
145 |
+
|
146 |
+
// Write path line
|
147 |
+
foreach ( $iterator as $item ) {
|
148 |
+
if( $item->isFile() ) {
|
149 |
+
if( $this->write( $files, 'wp-content' . DIRECTORY_SEPARATOR . $iterator->getSubPathName() . PHP_EOL ) ) {
|
150 |
+
$this->options->totalFiles++;
|
151 |
+
|
152 |
+
// Add current file size
|
153 |
+
$this->options->totalFileSize += $iterator->getSize();
|
154 |
+
}
|
155 |
}
|
156 |
+
}
|
157 |
+
} catch ( \Exception $e ) {
|
158 |
+
//$this->returnException('Out of disk space.');
|
159 |
+
throw new \Exception( 'Error: ' . $e->getMessage() );
|
160 |
+
} catch ( \Exception $e ) {
|
161 |
+
// Skip bad file permissions
|
162 |
+
}
|
163 |
+
|
164 |
+
// close the file handler
|
165 |
+
$this->close( $files );
|
166 |
+
return true;
|
167 |
+
}
|
168 |
+
|
169 |
+
/**
|
170 |
+
* Step 2
|
171 |
+
* @return boolean
|
172 |
+
* @throws \Exception
|
173 |
+
*/
|
174 |
+
private function getWpIncludesFiles() {
|
175 |
+
|
176 |
+
// Skip it
|
177 |
+
if( $this->isDirectoryExcluded( ABSPATH . 'wp-includes' . DIRECTORY_SEPARATOR ) ) {
|
178 |
+
return true;
|
179 |
+
}
|
180 |
+
|
181 |
+
// open file handle and attach data to end of file
|
182 |
+
$files = $this->open( $this->filename, 'a' );
|
183 |
+
|
184 |
+
try {
|
185 |
+
|
186 |
+
// Iterate over wp-admin directory
|
187 |
+
$iterator = new \WPStaging\Iterators\RecursiveDirectoryIterator( ABSPATH . 'wp-includes' . DIRECTORY_SEPARATOR );
|
188 |
+
|
189 |
+
// Exclude new line file names
|
190 |
+
$iterator = new \WPStaging\Iterators\RecursiveFilterNewLine( $iterator );
|
191 |
+
|
192 |
+
// Exclude uploads, plugins or themes
|
193 |
+
//$iterator = new \WPStaging\Iterators\RecursiveFilterExclude($iterator, apply_filters('wpstg_exclude_content', $exclude_filters));
|
194 |
+
// Recursively iterate over wp-includes directory
|
195 |
+
$iterator = new \RecursiveIteratorIterator( $iterator, \RecursiveIteratorIterator::LEAVES_ONLY, \RecursiveIteratorIterator::CATCH_GET_CHILD );
|
196 |
+
|
197 |
+
$this->log( "Scanning /wp-includes for its sub-directories and files" );
|
198 |
+
|
199 |
+
// Write files
|
200 |
+
foreach ( $iterator as $item ) {
|
201 |
+
if( $item->isFile() ) {
|
202 |
+
if( $this->write( $files, 'wp-includes' . DIRECTORY_SEPARATOR . $iterator->getSubPathName() . PHP_EOL ) ) {
|
203 |
+
$this->options->totalFiles++;
|
204 |
+
|
205 |
+
// Add current file size
|
206 |
+
$this->options->totalFileSize += $iterator->getSize();
|
207 |
+
}
|
208 |
}
|
209 |
+
}
|
210 |
+
} catch ( \Exception $e ) {
|
211 |
+
//$this->returnException('Out of disk space.');
|
212 |
+
throw new \Exception( 'Error: ' . $e->getMessage() );
|
213 |
+
} catch ( \Exception $e ) {
|
214 |
+
// Skip bad file permissions
|
215 |
+
}
|
216 |
|
217 |
+
// close the file handler
|
218 |
+
$this->close( $files );
|
219 |
+
return true;
|
220 |
+
}
|
|
|
|
|
221 |
|
222 |
+
/**
|
223 |
+
* Step 3
|
224 |
+
* @return boolean
|
225 |
+
* @throws \Exception
|
226 |
+
*/
|
227 |
+
private function getWpAdminFiles() {
|
228 |
+
|
229 |
+
// Skip it
|
230 |
+
if( $this->isDirectoryExcluded( ABSPATH . 'wp-admin' . DIRECTORY_SEPARATOR ) ) {
|
231 |
+
return true;
|
232 |
+
}
|
233 |
+
|
234 |
+
// open file handle and attach data to end of file
|
235 |
+
$files = $this->open( $this->filename, 'a' );
|
236 |
+
|
237 |
+
try {
|
238 |
+
|
239 |
+
// Iterate over wp-admin directory
|
240 |
+
$iterator = new \WPStaging\Iterators\RecursiveDirectoryIterator( ABSPATH . 'wp-admin' . DIRECTORY_SEPARATOR );
|
241 |
+
|
242 |
+
// Exclude new line file names
|
243 |
+
$iterator = new \WPStaging\Iterators\RecursiveFilterNewLine( $iterator );
|
244 |
+
|
245 |
+
// Exclude uploads, plugins or themes
|
246 |
+
//$iterator = new \WPStaging\Iterators\RecursiveFilterExclude($iterator, apply_filters('wpstg_exclude_content', $exclude_filters));
|
247 |
+
// Recursively iterate over content directory
|
248 |
+
$iterator = new \RecursiveIteratorIterator( $iterator, \RecursiveIteratorIterator::LEAVES_ONLY, \RecursiveIteratorIterator::CATCH_GET_CHILD );
|
249 |
+
|
250 |
+
$this->log( "Scanning /wp-admin for its sub-directories and files" );
|
251 |
+
|
252 |
+
// Write path line
|
253 |
+
foreach ( $iterator as $item ) {
|
254 |
+
if( $item->isFile() ) {
|
255 |
+
if( $this->write( $files, 'wp-admin' . DIRECTORY_SEPARATOR . $iterator->getSubPathName() . PHP_EOL ) ) {
|
256 |
+
$this->options->totalFiles++;
|
257 |
+
// Add current file size
|
258 |
+
$this->options->totalFileSize += $iterator->getSize();
|
259 |
+
}
|
260 |
}
|
261 |
+
}
|
262 |
+
} catch ( \Exception $e ) {
|
263 |
+
$this->returnException( 'Error: ' . $e->getMessage() );
|
264 |
+
//throw new \Exception('Error: ' . $e->getMessage());
|
265 |
+
} catch ( \Exception $e ) {
|
266 |
+
// Skip bad file permissions
|
267 |
+
}
|
268 |
+
|
269 |
+
// close the file handler
|
270 |
+
$this->close( $files );
|
271 |
+
return true;
|
272 |
+
}
|
273 |
+
|
274 |
+
/**
|
275 |
+
* Step 4 - x
|
276 |
+
* Get extra folders of the wp root level
|
277 |
+
* Does not collect wp-includes, wp-admin and wp-content folder
|
278 |
+
*/
|
279 |
+
private function getExtraFiles( $folder ) {
|
280 |
+
|
281 |
+
|
282 |
+
// open file handle and attach data to end of file
|
283 |
+
$files = $this->open( $this->filename, 'a' );
|
284 |
+
|
285 |
+
try {
|
286 |
+
|
287 |
+
// Iterate over wp-admin directory
|
288 |
+
$iterator = new \WPStaging\Iterators\RecursiveDirectoryIterator( $folder );
|
289 |
+
|
290 |
+
// Exclude new line file names
|
291 |
+
$iterator = new \WPStaging\Iterators\RecursiveFilterNewLine( $iterator );
|
292 |
+
|
293 |
+
// Exclude wp core folders
|
294 |
+
// $exclude = array('wp-includes',
|
295 |
+
// 'wp-admin',
|
296 |
+
// 'wp-content');
|
297 |
+
//
|
298 |
+
// $excludeMore = array();
|
299 |
+
// foreach ($this->options->excludedDirectories as $key => $value){
|
300 |
+
// $excludeMore[] = $this->getLastElemAfterString('/', $value);
|
301 |
+
// }
|
302 |
+
//$exclude = array_merge($exclude, $excludeMore);
|
303 |
+
|
304 |
+
$exclude = array();
|
305 |
+
|
306 |
+
$iterator = new \WPStaging\Iterators\RecursiveFilterExclude( $iterator, $exclude );
|
307 |
+
// Recursively iterate over content directory
|
308 |
+
$iterator = new \RecursiveIteratorIterator( $iterator, \RecursiveIteratorIterator::LEAVES_ONLY, \RecursiveIteratorIterator::CATCH_GET_CHILD );
|
309 |
+
|
310 |
+
$strings = new Strings();
|
311 |
+
$this->log( "Scanning {$strings->getLastElemAfterString( '/', $folder )} for its sub-directories and files" );
|
312 |
+
|
313 |
+
// Write path line
|
314 |
+
foreach ( $iterator as $item ) {
|
315 |
+
if( $item->isFile() ) {
|
316 |
+
if( $this->write( $files, $strings->getLastElemAfterString( '/', $folder ) . DIRECTORY_SEPARATOR . $iterator->getSubPathName() . PHP_EOL ) ) {
|
317 |
+
$this->options->totalFiles++;
|
318 |
+
// Add current file size
|
319 |
+
$this->options->totalFileSize += $iterator->getSize();
|
320 |
+
}
|
321 |
}
|
322 |
+
}
|
323 |
+
} catch ( \Exception $e ) {
|
324 |
+
$this->returnException( 'Error: ' . $e->getMessage() );
|
325 |
+
} catch ( \Exception $e ) {
|
326 |
+
// Skip bad file permissions
|
327 |
+
}
|
328 |
+
|
329 |
+
// close the file handler
|
330 |
+
$this->close( $files );
|
331 |
+
return true;
|
332 |
+
|
333 |
+
|
334 |
+
// Skip it
|
335 |
+
// if ($this->isDirectoryExcluded(ABSPATH)){
|
336 |
+
// return true;
|
337 |
+
// }
|
338 |
+
// // open file handle
|
339 |
+
// $files = $this->open($this->filename, 'a');
|
340 |
+
//
|
341 |
+
//
|
342 |
+
// try {
|
343 |
+
//
|
344 |
+
// // Iterate over wp root directory
|
345 |
+
// $iterator = new \DirectoryIterator(ABSPATH);
|
346 |
+
//
|
347 |
+
// $this->log( "Scanning ".ABSPATH." for its sub-directories and files" );
|
348 |
+
//
|
349 |
+
// // Write path line
|
350 |
+
// foreach ($iterator as $item) {
|
351 |
+
// if (!$item->isDot() && $item->isFile()) {
|
352 |
+
// if ($this->write($files, $iterator->getFilename() . PHP_EOL)) {
|
353 |
+
// $this->options->totalFiles++;
|
354 |
+
//
|
355 |
+
// // Add current file size
|
356 |
+
// $this->options->totalFileSize += $iterator->getSize();
|
357 |
+
// }
|
358 |
+
// }
|
359 |
+
// }
|
360 |
+
// } catch (\Exception $e) {
|
361 |
+
// $this->returnException('Error: ' . $e->getMessage());
|
362 |
+
// //throw new \Exception('Out of disk space.');
|
363 |
+
// } catch (\Exception $e) {
|
364 |
+
// // Skip bad file permissions
|
365 |
+
// }
|
366 |
+
//
|
367 |
+
// $this->close($files);
|
368 |
+
// return true;
|
369 |
+
}
|
370 |
+
|
371 |
+
/**
|
372 |
+
* Closes a file handle
|
373 |
+
*
|
374 |
+
* @param resource $handle File handle to close
|
375 |
+
* @return boolean
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
376 |
*/
|
377 |
+
public function close( $handle ) {
|
378 |
+
return @fclose( $handle );
|
379 |
+
}
|
380 |
+
|
381 |
+
/**
|
382 |
+
* Opens a file in specified mode
|
383 |
+
*
|
384 |
+
* @param string $file Path to the file to open
|
385 |
+
* @param string $mode Mode in which to open the file
|
386 |
+
* @return resource
|
387 |
+
* @throws Exception
|
388 |
+
*/
|
389 |
+
public function open( $file, $mode ) {
|
390 |
+
|
391 |
+
$file_handle = @fopen( $file, $mode );
|
392 |
+
if( false === $file_handle ) {
|
393 |
+
$this->returnException( sprintf( __( 'Unable to open %s with mode %s', 'wpstg' ), $file, $mode ) );
|
394 |
+
//throw new Exception(sprintf(__('Unable to open %s with mode %s', 'wpstg'), $file, $mode));
|
395 |
+
}
|
396 |
|
397 |
+
return $file_handle;
|
398 |
+
}
|
399 |
+
|
400 |
+
/**
|
401 |
+
* Write contents to a file
|
402 |
+
*
|
403 |
+
* @param resource $handle File handle to write to
|
404 |
+
* @param string $content Contents to write to the file
|
405 |
+
* @return integer
|
406 |
+
* @throws Exception
|
407 |
+
* @throws Exception
|
408 |
+
*/
|
409 |
+
public function write( $handle, $content ) {
|
410 |
+
$write_result = @fwrite( $handle, $content );
|
411 |
+
if( false === $write_result ) {
|
412 |
+
if( ( $meta = \stream_get_meta_data( $handle ) ) ) {
|
413 |
+
//$this->returnException(sprintf(__('Unable to write to: %s', 'wpstg'), $meta['uri']));
|
414 |
+
throw new \Exception( sprintf( __( 'Unable to write to: %s', 'wpstg' ), $meta['uri'] ) );
|
415 |
}
|
416 |
+
} elseif( strlen( $content ) !== $write_result ) {
|
417 |
+
//$this->returnException(__('Out of disk space.', 'wpstg'));
|
418 |
+
throw new \Exception( __( 'Out of disk space.', 'wpstg' ) );
|
419 |
+
}
|
420 |
+
|
421 |
+
return $write_result;
|
422 |
+
}
|
423 |
|
424 |
+
/**
|
425 |
+
* Execute the Current Step
|
426 |
+
* Returns false when over threshold limits are hit or when the job is done, true otherwise
|
427 |
+
* @return bool
|
428 |
+
*/
|
429 |
+
protected function execute() {
|
430 |
+
|
431 |
+
// No job left to execute
|
432 |
+
if( $this->isFinished() ) {
|
433 |
+
$this->prepareResponse( true, false );
|
434 |
+
return false;
|
435 |
}
|
436 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
437 |
|
438 |
+
if( $this->options->currentStep == 0 ) {
|
439 |
+
$this->getWpRootFiles();
|
440 |
+
$this->prepareResponse( false, true );
|
441 |
+
return false;
|
442 |
+
}
|
443 |
+
|
444 |
+
if( $this->options->currentStep == 1 ) {
|
445 |
+
$this->getWpContentFiles();
|
446 |
+
$this->prepareResponse( false, true );
|
447 |
+
return false;
|
448 |
+
}
|
449 |
+
|
450 |
+
if( $this->options->currentStep == 2 ) {
|
451 |
+
$this->getWpIncludesFiles();
|
452 |
+
$this->prepareResponse( false, true );
|
453 |
+
return false;
|
454 |
+
}
|
455 |
+
|
456 |
+
if( $this->options->currentStep == 3 ) {
|
457 |
+
$this->getWpAdminFiles();
|
458 |
+
$this->prepareResponse( false, true );
|
459 |
+
return false;
|
460 |
+
}
|
461 |
+
|
462 |
+
if( isset( $this->options->extraDirectories[$this->options->currentStep - $this->total] ) ) {
|
463 |
+
$this->getExtraFiles( $this->options->extraDirectories[$this->options->currentStep - $this->total] );
|
464 |
+
$this->prepareResponse( false, true );
|
465 |
+
return false;
|
466 |
+
}
|
467 |
+
|
468 |
+
|
469 |
+
// Prepare response
|
470 |
+
$this->prepareResponse( false, true );
|
471 |
+
// Not finished
|
472 |
+
return true;
|
473 |
+
}
|
474 |
+
|
475 |
+
/**
|
476 |
+
* Checks Whether There is Any Job to Execute or Not
|
477 |
+
* @return bool
|
478 |
+
*/
|
479 |
+
protected function isFinished() {
|
480 |
+
if( $this->options->currentStep >= $this->options->totalSteps ) {
|
481 |
+
return true;
|
482 |
+
}
|
483 |
+
|
484 |
+
// return (
|
485 |
+
// //$this->options->currentStep > $this->total ||
|
486 |
+
// $this->options->currentStep >= $this->options->totalSteps
|
487 |
+
// );
|
488 |
+
}
|
489 |
+
|
490 |
+
/**
|
491 |
+
* Save files
|
492 |
+
* @return bool
|
493 |
+
*/
|
494 |
+
protected function saveProgress() {
|
495 |
+
return $this->saveOptions();
|
496 |
+
}
|
497 |
+
|
498 |
+
/**
|
499 |
+
* Get files
|
500 |
+
* @return void
|
501 |
+
*/
|
502 |
+
protected function getFiles() {
|
503 |
+
$fileName = $this->cache->getCacheDir() . "files_to_copy." . $this->cache->getCacheExtension();
|
504 |
+
|
505 |
+
if( false === ($this->files = @file_get_contents( $fileName )) ) {
|
506 |
+
$this->files = array();
|
507 |
+
return;
|
508 |
+
}
|
509 |
+
|
510 |
+
$this->files = explode( PHP_EOL, $this->files );
|
511 |
+
}
|
512 |
+
|
513 |
+
/**
|
514 |
+
* Check if directory is excluded
|
515 |
+
* @param string $directory
|
516 |
+
* @return bool
|
517 |
+
*/
|
518 |
+
protected function isDirectoryExcluded( $directory ) {
|
519 |
+
foreach ( $this->options->excludedDirectories as $excludedDirectory ) {
|
520 |
+
if( strpos( $directory, $excludedDirectory ) === 0 ) {
|
521 |
+
return true;
|
522 |
+
}
|
523 |
+
}
|
524 |
+
|
525 |
+
return false;
|
526 |
+
}
|
527 |
|
528 |
}
|
apps/Backend/Modules/Jobs/Files.php
CHANGED
@@ -340,6 +340,11 @@ class Files extends JobExecutable {
|
|
340 |
* @return bool
|
341 |
*/
|
342 |
private function isDirectoryExcluded($directory) {
|
|
|
|
|
|
|
|
|
|
|
343 |
foreach ($this->options->excludedDirectories as $excludedDirectory) {
|
344 |
if (strpos($directory, $excludedDirectory) === 0 && !$this->isExtraDirectory($directory)) {
|
345 |
return true;
|
340 |
* @return bool
|
341 |
*/
|
342 |
private function isDirectoryExcluded($directory) {
|
343 |
+
// Make sure that wp-staging-pro directory / plugin is never excluded
|
344 |
+
if (false !== strpos( $directory, 'wp-staging' ) || false !== strpos( $directory, 'wp-staging-pro' ) ){
|
345 |
+
return false;
|
346 |
+
}
|
347 |
+
|
348 |
foreach ($this->options->excludedDirectories as $excludedDirectory) {
|
349 |
if (strpos($directory, $excludedDirectory) === 0 && !$this->isExtraDirectory($directory)) {
|
350 |
return true;
|
apps/Backend/Modules/Jobs/Scan.php
CHANGED
@@ -75,6 +75,7 @@ class Scan extends Job
|
|
75 |
|
76 |
// Directories
|
77 |
$this->options->includedDirectories = array();
|
|
|
78 |
$this->options->excludedDirectories = array();
|
79 |
$this->options->extraDirectories = array();
|
80 |
$this->options->directoriesToCopy = array();
|
@@ -137,9 +138,8 @@ class Scan extends Job
|
|
137 |
$output = '';
|
138 |
foreach ($directories as $name => $directory)
|
139 |
{
|
140 |
-
|
141 |
if (!is_array($directory)) {
|
142 |
-
// Not a directory, possibly a symlink, therefore we will skip it
|
143 |
continue;
|
144 |
}
|
145 |
|
@@ -152,17 +152,31 @@ class Scan extends Job
|
|
152 |
in_array($data["path"], $this->options->includedDirectories)
|
153 |
);
|
154 |
|
155 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
156 |
|
157 |
$output .= "<div class='wpstg-dir'>";
|
158 |
-
$output .= "<input type='checkbox' class='wpstg-check-dir'";
|
159 |
|
160 |
if ($isChecked && !$isDisabled && !$forceDisabled) $output .= " checked";
|
161 |
-
if ($forceDisabled || $isDisabled) $output .= " disabled";
|
162 |
|
163 |
$output .= " name='selectedDirectories[]' value='{$data["path"]}'>";
|
164 |
|
165 |
-
$output .= "<a href='#' class='wpstg-expand-dirs";
|
166 |
if (!$isChecked || $isDisabled) $output .= " disabled";
|
167 |
$output .= "'>{$name}";
|
168 |
$output .= "</a>";
|
@@ -245,7 +259,7 @@ class Scan extends Job
|
|
245 |
// continue;
|
246 |
// }
|
247 |
// Create array of unchecked tables
|
248 |
-
if (0 !== strpos($table->Name, $wpDB->prefix))
|
249 |
{
|
250 |
$this->options->excludedTables[] = $table->Name;
|
251 |
}
|
75 |
|
76 |
// Directories
|
77 |
$this->options->includedDirectories = array();
|
78 |
+
$this->options->includedExtraDirectories= array();
|
79 |
$this->options->excludedDirectories = array();
|
80 |
$this->options->extraDirectories = array();
|
81 |
$this->options->directoriesToCopy = array();
|
138 |
$output = '';
|
139 |
foreach ($directories as $name => $directory)
|
140 |
{
|
141 |
+
// Not a directory, possibly a symlink, therefore we will skip it
|
142 |
if (!is_array($directory)) {
|
|
|
143 |
continue;
|
144 |
}
|
145 |
|
152 |
in_array($data["path"], $this->options->includedDirectories)
|
153 |
);
|
154 |
|
155 |
+
//$isDisabled = ($this->options->existingClones && isset($this->options->existingClones[$name]));
|
156 |
+
|
157 |
+
// Include wp core folders and their sub dirs.
|
158 |
+
// Exclude all other folders (default setting)
|
159 |
+
$isDisabled = ($name !== 'wp-admin' &&
|
160 |
+
$name !== 'wp-includes' &&
|
161 |
+
$name !== 'wp-content') &&
|
162 |
+
false === strpos( strrev($data["path"]), strrev("wp-admin") ) &&
|
163 |
+
false === strpos( strrev($data["path"]), strrev("wp-includes") ) &&
|
164 |
+
false === strpos( strrev($data["path"]), strrev("wp-content") )
|
165 |
+
? true : false;
|
166 |
+
|
167 |
+
// Extra class to differentiate between wp core and non core folders
|
168 |
+
$class = !$isDisabled ? 'wpstg-root' : 'wpstg-extra';
|
169 |
+
|
170 |
|
171 |
$output .= "<div class='wpstg-dir'>";
|
172 |
+
$output .= "<input type='checkbox' class='wpstg-check-dir " . $class . "'";
|
173 |
|
174 |
if ($isChecked && !$isDisabled && !$forceDisabled) $output .= " checked";
|
175 |
+
//if ($forceDisabled || $isDisabled) $output .= " disabled";
|
176 |
|
177 |
$output .= " name='selectedDirectories[]' value='{$data["path"]}'>";
|
178 |
|
179 |
+
$output .= "<a href='#' class='wpstg-expand-dirs ";
|
180 |
if (!$isChecked || $isDisabled) $output .= " disabled";
|
181 |
$output .= "'>{$name}";
|
182 |
$output .= "</a>";
|
259 |
// continue;
|
260 |
// }
|
261 |
// Create array of unchecked tables
|
262 |
+
if (!empty($wpDB->prefix) && 0 !== strpos($table->Name, $wpDB->prefix))
|
263 |
{
|
264 |
$this->options->excludedTables[] = $table->Name;
|
265 |
}
|
apps/Backend/Modules/Jobs/SearchReplace.php
CHANGED
@@ -44,6 +44,10 @@ class SearchReplace extends JobExecutable {
|
|
44 |
}
|
45 |
|
46 |
public function start() {
|
|
|
|
|
|
|
|
|
47 |
|
48 |
$this->run();
|
49 |
|
@@ -104,13 +108,13 @@ class SearchReplace extends JobExecutable {
|
|
104 |
return true;
|
105 |
}
|
106 |
|
107 |
-
private function convertExcludedTables() {
|
108 |
-
$tmp = array();
|
109 |
-
foreach ( $this->options->excludedTables as $table ) {
|
110 |
-
$tmp[] = str_replace( $this->options->prefix, $this->tmpPrefix, $table );
|
111 |
-
}
|
112 |
-
$this->options->excludedTables = $tmp;
|
113 |
-
}
|
114 |
|
115 |
/**
|
116 |
* Stop Execution immediately
|
@@ -220,15 +224,41 @@ class SearchReplace extends JobExecutable {
|
|
220 |
$pages = $this->get_pages_in_table( $table );
|
221 |
$done = false;
|
222 |
|
|
|
|
|
|
|
223 |
// Search URL example.com/staging and root path to staging site /var/www/htdocs/staging
|
224 |
$args['search_for'] = array(
|
225 |
-
|
226 |
ABSPATH
|
227 |
);
|
|
|
228 |
$args['replace_with'] = array(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
229 |
rtrim( get_home_url(), '/' ) . '/' . $this->options->cloneDirectoryName,
|
230 |
rtrim( ABSPATH, '/' ) . '/' . $this->options->cloneDirectoryName
|
231 |
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
232 |
$args['replace_guids'] = 'off';
|
233 |
$args['dry_run'] = 'off';
|
234 |
$args['case_insensitive'] = false;
|
@@ -257,7 +287,7 @@ class SearchReplace extends JobExecutable {
|
|
257 |
$current_row++;
|
258 |
$update_sql = array();
|
259 |
$where_sql = array();
|
260 |
-
$
|
261 |
|
262 |
foreach ( $columns as $column ) {
|
263 |
|
@@ -309,23 +339,21 @@ class SearchReplace extends JobExecutable {
|
|
309 |
// Something was changed
|
310 |
if( $row[$column] != $dataRow ) {
|
311 |
$update_sql[] = $column . ' = "' . $this->mysql_escape_mimic( $dataRow ) . '"';
|
312 |
-
$
|
|
|
313 |
}
|
314 |
}
|
315 |
|
316 |
// Determine what to do with updates.
|
317 |
if( $args['dry_run'] === 'on' ) {
|
318 |
// Don't do anything if a dry run
|
319 |
-
} elseif( $
|
320 |
// If there are changes to make, run the query.
|
321 |
$sql = 'UPDATE ' . $table . ' SET ' . implode( ', ', $update_sql ) . ' WHERE ' . implode( ' AND ', array_filter( $where_sql ) );
|
322 |
-
|
323 |
$result = $this->db->query( $sql );
|
324 |
|
325 |
if( !$result ) {
|
326 |
-
|
327 |
-
} else {
|
328 |
-
// Do nothing
|
329 |
}
|
330 |
}
|
331 |
} // end row loop
|
@@ -545,4 +573,31 @@ class SearchReplace extends JobExecutable {
|
|
545 |
);
|
546 |
}
|
547 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
548 |
}
|
44 |
}
|
45 |
|
46 |
public function start() {
|
47 |
+
// Skip job. Nothing to do
|
48 |
+
if ($this->options->totalSteps === 0){
|
49 |
+
$this->prepareResponse( true, false );
|
50 |
+
}
|
51 |
|
52 |
$this->run();
|
53 |
|
108 |
return true;
|
109 |
}
|
110 |
|
111 |
+
// private function convertExcludedTables() {
|
112 |
+
// $tmp = array();
|
113 |
+
// foreach ( $this->options->excludedTables as $table ) {
|
114 |
+
// $tmp[] = str_replace( $this->options->prefix, $this->tmpPrefix, $table );
|
115 |
+
// }
|
116 |
+
// $this->options->excludedTables = $tmp;
|
117 |
+
// }
|
118 |
|
119 |
/**
|
120 |
* Stop Execution immediately
|
224 |
$pages = $this->get_pages_in_table( $table );
|
225 |
$done = false;
|
226 |
|
227 |
+
|
228 |
+
if( $this->isSubDir() ) {
|
229 |
+
//$homeUrl = rtrim(get_home_url(), "/") . $this->getSubDir() . $this->options->cloneDirectoryName;
|
230 |
// Search URL example.com/staging and root path to staging site /var/www/htdocs/staging
|
231 |
$args['search_for'] = array(
|
232 |
+
rtrim(get_home_url(), "/") . $this->getSubDir(),
|
233 |
ABSPATH
|
234 |
);
|
235 |
+
|
236 |
$args['replace_with'] = array(
|
237 |
+
rtrim(get_home_url(), "/") . $this->getSubDir() . '/'. $this->options->cloneDirectoryName,
|
238 |
+
rtrim( ABSPATH, '/' ) . '/' . $this->options->cloneDirectoryName
|
239 |
+
);
|
240 |
+
} else {
|
241 |
+
$args['search_for'] = array(
|
242 |
+
rtrim(get_home_url(), '/'),
|
243 |
+
ABSPATH
|
244 |
+
);
|
245 |
+
$args['replace_with'] = array(
|
246 |
rtrim( get_home_url(), '/' ) . '/' . $this->options->cloneDirectoryName,
|
247 |
rtrim( ABSPATH, '/' ) . '/' . $this->options->cloneDirectoryName
|
248 |
);
|
249 |
+
}
|
250 |
+
|
251 |
+
// // Search URL example.com/staging and root path to staging site /var/www/htdocs/staging
|
252 |
+
// $args['search_for'] = array(
|
253 |
+
// get_home_url(),
|
254 |
+
// ABSPATH
|
255 |
+
// );
|
256 |
+
//
|
257 |
+
//
|
258 |
+
// $args['replace_with'] = array(
|
259 |
+
// rtrim( get_home_url(), '/' ) . '/' . $this->options->cloneDirectoryName,
|
260 |
+
// rtrim( ABSPATH, '/' ) . '/' . $this->options->cloneDirectoryName
|
261 |
+
// );
|
262 |
$args['replace_guids'] = 'off';
|
263 |
$args['dry_run'] = 'off';
|
264 |
$args['case_insensitive'] = false;
|
287 |
$current_row++;
|
288 |
$update_sql = array();
|
289 |
$where_sql = array();
|
290 |
+
$isUpdate = false;
|
291 |
|
292 |
foreach ( $columns as $column ) {
|
293 |
|
339 |
// Something was changed
|
340 |
if( $row[$column] != $dataRow ) {
|
341 |
$update_sql[] = $column . ' = "' . $this->mysql_escape_mimic( $dataRow ) . '"';
|
342 |
+
$isUpdate = true;
|
343 |
+
//$this->log("Changed {$update_sql[]} ", \WPStaging\Utils\Logger::TYPE_INFO);
|
344 |
}
|
345 |
}
|
346 |
|
347 |
// Determine what to do with updates.
|
348 |
if( $args['dry_run'] === 'on' ) {
|
349 |
// Don't do anything if a dry run
|
350 |
+
} elseif( $isUpdate && !empty( $where_sql ) ) {
|
351 |
// If there are changes to make, run the query.
|
352 |
$sql = 'UPDATE ' . $table . ' SET ' . implode( ', ', $update_sql ) . ' WHERE ' . implode( ' AND ', array_filter( $where_sql ) );
|
|
|
353 |
$result = $this->db->query( $sql );
|
354 |
|
355 |
if( !$result ) {
|
356 |
+
$this->log("Error updating row {$current_row}", \WPStaging\Utils\Logger::TYPE_ERROR);
|
|
|
|
|
357 |
}
|
358 |
}
|
359 |
} // end row loop
|
573 |
);
|
574 |
}
|
575 |
|
576 |
+
/**
|
577 |
+
* Check if WP is installed in subdir
|
578 |
+
* @return boolean
|
579 |
+
*/
|
580 |
+
private function isSubDir(){
|
581 |
+
if ( get_option( 'siteurl' ) !== get_option( 'home' ) ) {
|
582 |
+
return true;
|
583 |
+
}
|
584 |
+
return false;
|
585 |
+
}
|
586 |
+
|
587 |
+
/**
|
588 |
+
* Get the install sub directory if WP is installed in sub directory
|
589 |
+
* @return string
|
590 |
+
*/
|
591 |
+
private function getSubDir(){
|
592 |
+
$home = get_option('home');
|
593 |
+
$siteurl = get_option('siteurl');
|
594 |
+
|
595 |
+
if (empty($home) || empty($siteurl)){
|
596 |
+
return '/';
|
597 |
+
}
|
598 |
+
|
599 |
+
$dir = str_replace($home, '', $siteurl);
|
600 |
+
return '/' . str_replace('/', '', $dir);
|
601 |
+
}
|
602 |
+
|
603 |
}
|
apps/Backend/Modules/SystemInfo.php
CHANGED
@@ -1,4 +1,5 @@
|
|
1 |
<?php
|
|
|
2 |
namespace WPStaging\Backend\Modules;
|
3 |
|
4 |
use WPStaging\DI\InjectionAware;
|
@@ -23,7 +24,6 @@ class SystemInfo extends InjectionAware
|
|
23 |
*/
|
24 |
private $isMultiSite;
|
25 |
|
26 |
-
|
27 |
/**
|
28 |
* Initialize class
|
29 |
*/
|
@@ -45,9 +45,8 @@ class SystemInfo extends InjectionAware
|
|
45 |
* Get System Information as text
|
46 |
* @return string
|
47 |
*/
|
48 |
-
|
49 |
-
|
50 |
-
$output = "### Begin System Info ###" . PHP_EOL . PHP_EOL;
|
51 |
|
52 |
$output .= $this->wpstaging();
|
53 |
|
@@ -72,8 +71,6 @@ class SystemInfo extends InjectionAware
|
|
72 |
return $output;
|
73 |
}
|
74 |
|
75 |
-
|
76 |
-
|
77 |
/**
|
78 |
* @param string $string
|
79 |
* @return string
|
@@ -167,6 +164,12 @@ class SystemInfo extends InjectionAware
|
|
167 |
$output .= $this->info( "Version:", isset( $clone['version'] ) ? $clone['version'] : 'undefined' ) . PHP_EOL . PHP_EOL;
|
168 |
}
|
169 |
|
|
|
|
|
|
|
|
|
|
|
|
|
170 |
//$output .= PHP_EOL . PHP_EOL;
|
171 |
|
172 |
$output .= $this->info( "Plugin Version:", get_option('wpstg_version', 'undefined') );
|
@@ -274,6 +277,16 @@ class SystemInfo extends InjectionAware
|
|
274 |
|
275 |
$output .= $this->info("Table Prefix:", $tablePrefix);
|
276 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
277 |
// WP Debug
|
278 |
$output .= $this->info("WP_DEBUG:", (defined("WP_DEBUG")) ? WP_DEBUG ? "Enabled" : "Disabled" : "Not set");
|
279 |
$output .= $this->info("Memory Limit:", WP_MEMORY_LIMIT);
|
1 |
<?php
|
2 |
+
|
3 |
namespace WPStaging\Backend\Modules;
|
4 |
|
5 |
use WPStaging\DI\InjectionAware;
|
24 |
*/
|
25 |
private $isMultiSite;
|
26 |
|
|
|
27 |
/**
|
28 |
* Initialize class
|
29 |
*/
|
45 |
* Get System Information as text
|
46 |
* @return string
|
47 |
*/
|
48 |
+
public function get() {
|
49 |
+
$output = "### Begin System Info ###" . PHP_EOL . PHP_EOL;
|
|
|
50 |
|
51 |
$output .= $this->wpstaging();
|
52 |
|
71 |
return $output;
|
72 |
}
|
73 |
|
|
|
|
|
74 |
/**
|
75 |
* @param string $string
|
76 |
* @return string
|
164 |
$output .= $this->info( "Version:", isset( $clone['version'] ) ? $clone['version'] : 'undefined' ) . PHP_EOL . PHP_EOL;
|
165 |
}
|
166 |
|
167 |
+
|
168 |
+
$output .= $this->info( "Raw Clones Data:", json_encode( get_option( 'wpstg_existing_clones_beta', 'undefined' ) ) );
|
169 |
+
|
170 |
+
$output .= '' . PHP_EOL;
|
171 |
+
|
172 |
+
|
173 |
//$output .= PHP_EOL . PHP_EOL;
|
174 |
|
175 |
$output .= $this->info( "Plugin Version:", get_option('wpstg_version', 'undefined') );
|
277 |
|
278 |
$output .= $this->info("Table Prefix:", $tablePrefix);
|
279 |
|
280 |
+
// Constants
|
281 |
+
$output .= $this->info( "WP Content Path:", WP_CONTENT_DIR );
|
282 |
+
$output .= $this->info( "WP Plugin Dir:", WP_PLUGIN_DIR );
|
283 |
+
if (defined('UPLOADS'))
|
284 |
+
$output .= $this->info( "WP UPLOADS CONST:", UPLOADS );
|
285 |
+
$uploads = wp_upload_dir();
|
286 |
+
$output .= $this->info( "WP Uploads Dir:", wp_basename( $uploads['baseurl'] ) );
|
287 |
+
if (defined('WP_TEMP_DIR'))
|
288 |
+
$output .= $this->info( "WP Temp Dir:", WP_TEMP_DIR );
|
289 |
+
|
290 |
// WP Debug
|
291 |
$output .= $this->info("WP_DEBUG:", (defined("WP_DEBUG")) ? WP_DEBUG ? "Enabled" : "Disabled" : "Not set");
|
292 |
$output .= $this->info("Memory Limit:", WP_MEMORY_LIMIT);
|
apps/Backend/public/js/wpstg-admin.js
CHANGED
@@ -533,12 +533,12 @@ var WPStaging = (function ($)
|
|
533 |
{
|
534 |
var includedDirectories = [];
|
535 |
|
536 |
-
$(".wpstg-dir input:checked").each(function () {
|
537 |
var $this = $(this);
|
538 |
-
if (!$this.parent(".wpstg-dir").parents(".wpstg-dir").children(".wpstg-expand-dirs").hasClass("disabled"))
|
539 |
-
{
|
540 |
includedDirectories.push($this.val());
|
541 |
-
}
|
542 |
});
|
543 |
|
544 |
return includedDirectories;
|
@@ -552,7 +552,8 @@ var WPStaging = (function ($)
|
|
552 |
{
|
553 |
var excludedDirectories = [];
|
554 |
|
555 |
-
|
|
|
556 |
var $this = $(this);
|
557 |
//if (!$this.parent(".wpstg-dir").parents(".wpstg-dir").children(".wpstg-expand-dirs").hasClass("disabled"))
|
558 |
//{
|
@@ -562,27 +563,43 @@ var WPStaging = (function ($)
|
|
562 |
|
563 |
return excludedDirectories;
|
564 |
};
|
565 |
-
|
566 |
/**
|
567 |
-
* Get
|
|
|
568 |
* @returns {Array}
|
569 |
*/
|
570 |
var getIncludedExtraDirectories = function ()
|
571 |
{
|
572 |
var extraDirectories = [];
|
573 |
|
574 |
-
|
575 |
-
|
576 |
-
|
577 |
-
|
578 |
-
var extraDirectories = $("#wpstg_extraDirectories").val().split(/\r?\n/);
|
579 |
-
console.log(extraDirectories);
|
580 |
-
|
581 |
-
//excludedDirectories.push($this.val());
|
582 |
|
583 |
return extraDirectories;
|
584 |
};
|
585 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
586 |
|
587 |
|
588 |
/**
|
@@ -994,7 +1011,6 @@ var WPStaging = (function ($)
|
|
994 |
// Undefined Error
|
995 |
if (false === response)
|
996 |
{
|
997 |
-
showError("Unknown Error, please try again");
|
998 |
showError(
|
999 |
"Something went wrong! Error: No response. Go to WP Staging > Settings and lower 'File Copy Limit' and 'DB Query Limit'. Also set 'CPU Load Priority to low.'" +
|
1000 |
"Than try again. If that does not help, " +
|
533 |
{
|
534 |
var includedDirectories = [];
|
535 |
|
536 |
+
$(".wpstg-dir input:checked.wpstg-root").each(function () {
|
537 |
var $this = $(this);
|
538 |
+
//if (!$this.parent(".wpstg-dir").parents(".wpstg-dir").children(".wpstg-expand-dirs").hasClass("disabled"))
|
539 |
+
//{
|
540 |
includedDirectories.push($this.val());
|
541 |
+
//}
|
542 |
});
|
543 |
|
544 |
return includedDirectories;
|
552 |
{
|
553 |
var excludedDirectories = [];
|
554 |
|
555 |
+
//$(".wpstg-dir .wpstg-root input:not(:checked)").each(function () {
|
556 |
+
$(".wpstg-dir input:not(:checked).wpstg-root").each(function () {
|
557 |
var $this = $(this);
|
558 |
//if (!$this.parent(".wpstg-dir").parents(".wpstg-dir").children(".wpstg-expand-dirs").hasClass("disabled"))
|
559 |
//{
|
563 |
|
564 |
return excludedDirectories;
|
565 |
};
|
|
|
566 |
/**
|
567 |
+
* Get included extra directories of the root level
|
568 |
+
* All directories except wp-content, wp-admin, wp-includes
|
569 |
* @returns {Array}
|
570 |
*/
|
571 |
var getIncludedExtraDirectories = function ()
|
572 |
{
|
573 |
var extraDirectories = [];
|
574 |
|
575 |
+
$(".wpstg-dir input:checked.wpstg-extra").each(function () {
|
576 |
+
var $this = $(this);
|
577 |
+
extraDirectories.push($this.val());
|
578 |
+
});
|
|
|
|
|
|
|
|
|
579 |
|
580 |
return extraDirectories;
|
581 |
};
|
582 |
|
583 |
+
/**
|
584 |
+
* Get Included Extra Directories
|
585 |
+
* @returns {Array}
|
586 |
+
*/
|
587 |
+
// var getIncludedExtraDirectories = function ()
|
588 |
+
// {
|
589 |
+
// var extraDirectories = [];
|
590 |
+
//
|
591 |
+
// if (!$("#wpstg_extraDirectories").val()) {
|
592 |
+
// return extraDirectories;
|
593 |
+
// }
|
594 |
+
//
|
595 |
+
// var extraDirectories = $("#wpstg_extraDirectories").val().split(/\r?\n/);
|
596 |
+
// console.log(extraDirectories);
|
597 |
+
//
|
598 |
+
// //excludedDirectories.push($this.val());
|
599 |
+
//
|
600 |
+
// return extraDirectories;
|
601 |
+
// };
|
602 |
+
|
603 |
|
604 |
|
605 |
/**
|
1011 |
// Undefined Error
|
1012 |
if (false === response)
|
1013 |
{
|
|
|
1014 |
showError(
|
1015 |
"Something went wrong! Error: No response. Go to WP Staging > Settings and lower 'File Copy Limit' and 'DB Query Limit'. Also set 'CPU Load Priority to low.'" +
|
1016 |
"Than try again. If that does not help, " +
|
apps/Backend/views/clone/ajax/scan.php
CHANGED
@@ -60,7 +60,7 @@
|
|
60 |
|
61 |
<div class="wpstg-tab-section" id="wpstg-scanning-files">
|
62 |
<h4 style="margin:0">
|
63 |
-
<?php echo __("
|
64 |
</h4>
|
65 |
|
66 |
<?php echo $scan->directoryListing()?>
|
@@ -101,18 +101,13 @@
|
|
101 |
<div class="wpstg-tab-section" id="wpstg-advanced-settings">
|
102 |
<p>
|
103 |
<?php
|
104 |
-
_e('<strong>Important:</strong>
|
105 |
echo '<br/>';
|
106 |
-
echo sprintf(__('Set up
|
107 |
-
admin_url() . '/admin.php?page=wpstg-settings#wpstg_settings[loginSlug]'
|
|
|
108 |
);
|
109 |
-
|
110 |
-
sprintf(__('To test this you need to log out first! Than login again by using the link <a href="%1$s" target="_blank">12$s</a>.', 'wpstg'), admin_url());
|
111 |
-
echo '<br/>';
|
112 |
-
_e('If the login link does not work you <strong>must</strong> define the Login Custom Link option.', 'wpstg');
|
113 |
-
echo '<br/>';
|
114 |
-
echo '<br/>';
|
115 |
-
_e('<strong>If you are using a custom login and you do not define that setting, the staging site will not be accessable!</strong>', 'wpstg');
|
116 |
//$form = $this->di->get("forms")->get("general");
|
117 |
//echo $form->label("wpstg_settings['loginPostId']");
|
118 |
//echo $form->render("wpstg_settings['loginPostId']");
|
60 |
|
61 |
<div class="wpstg-tab-section" id="wpstg-scanning-files">
|
62 |
<h4 style="margin:0">
|
63 |
+
<?php echo __("Select folders to copy. Click on folder name to list subfolders!", "wpstg")?>
|
64 |
</h4>
|
65 |
|
66 |
<?php echo $scan->directoryListing()?>
|
101 |
<div class="wpstg-tab-section" id="wpstg-advanced-settings">
|
102 |
<p>
|
103 |
<?php
|
104 |
+
_e('<strong>Important:</strong> Are you using a custom login url?', 'wpstg');
|
105 |
echo '<br/>';
|
106 |
+
echo sprintf(__('Set up first <a href="%1$s"><strong>Login Custom Link</strong></a> if login to the admin dashboard is not reachable from the default url below:<pre>%2$s</pre>', 'wpstg'),
|
107 |
+
admin_url() . '/admin.php?page=wpstg-settings#wpstg_settings[loginSlug]',
|
108 |
+
admin_url()
|
109 |
);
|
110 |
+
_e('<strong>If you do not do that step, the staging site could be unavailable!</strong>', 'wpstg');
|
|
|
|
|
|
|
|
|
|
|
|
|
111 |
//$form = $this->di->get("forms")->get("general");
|
112 |
//echo $form->label("wpstg_settings['loginPostId']");
|
113 |
//echo $form->render("wpstg_settings['loginPostId']");
|
apps/Core/Utils/Cache.php
CHANGED
@@ -8,7 +8,6 @@ if (!defined("WPINC"))
|
|
8 |
}
|
9 |
|
10 |
use WPStaging\WPStaging;
|
11 |
-
use WPStaging\Backend\Modules\Jobs;
|
12 |
|
13 |
/**
|
14 |
* Class Cache
|
@@ -73,6 +72,7 @@ class Cache
|
|
73 |
{
|
74 |
throw new \Exception("Failed to create cache directory " . $this->cacheDir . '! Make sure folder permission is 755 and owner is correct. Should be www-data or similar.');
|
75 |
}
|
|
|
76 |
}
|
77 |
|
78 |
/**
|
@@ -112,24 +112,16 @@ class Cache
|
|
112 |
}
|
113 |
|
114 |
// Save it to file
|
115 |
-
return (file_put_contents($cacheFile, @serialize($value), LOCK_EX) !== false);
|
|
|
|
|
|
|
|
|
|
|
116 |
//return (file_put_contents($cacheFile, @serialize($value)) !== false);
|
117 |
}
|
118 |
|
119 |
/**
|
120 |
-
* Throw a errror message via json and stop further execution
|
121 |
-
* @param string $message
|
122 |
-
*/
|
123 |
-
protected function returnException($message = ''){
|
124 |
-
wp_die( json_encode(array(
|
125 |
-
'job' => isset($this->options->currentJob) ? $this->options->currentJob : '',
|
126 |
-
'status' => false,
|
127 |
-
'message' => $message,
|
128 |
-
'error' => true
|
129 |
-
)));
|
130 |
-
}
|
131 |
-
|
132 |
-
/**
|
133 |
* Checks if file is valid or not
|
134 |
* @param $cacheFileName
|
135 |
* @param bool $deleteFileIfInvalid
|
@@ -209,4 +201,18 @@ class Cache
|
|
209 |
{
|
210 |
return $this->cacheExtension;
|
211 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
212 |
}
|
8 |
}
|
9 |
|
10 |
use WPStaging\WPStaging;
|
|
|
11 |
|
12 |
/**
|
13 |
* Class Cache
|
72 |
{
|
73 |
throw new \Exception("Failed to create cache directory " . $this->cacheDir . '! Make sure folder permission is 755 and owner is correct. Should be www-data or similar.');
|
74 |
}
|
75 |
+
|
76 |
}
|
77 |
|
78 |
/**
|
112 |
}
|
113 |
|
114 |
// Save it to file
|
115 |
+
//return (file_put_contents($cacheFile, @serialize($value), LOCK_EX) !== false);
|
116 |
+
if (!file_put_contents($cacheFile, @serialize($value))){
|
117 |
+
$this->returnException(" Can't save data to: " . $cacheFile);
|
118 |
+
return false;
|
119 |
+
}
|
120 |
+
return true;
|
121 |
//return (file_put_contents($cacheFile, @serialize($value)) !== false);
|
122 |
}
|
123 |
|
124 |
/**
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
125 |
* Checks if file is valid or not
|
126 |
* @param $cacheFileName
|
127 |
* @param bool $deleteFileIfInvalid
|
201 |
{
|
202 |
return $this->cacheExtension;
|
203 |
}
|
204 |
+
|
205 |
+
|
206 |
+
/**
|
207 |
+
* Throw a errror message via json and stop further execution
|
208 |
+
* @param string $message
|
209 |
+
*/
|
210 |
+
protected function returnException($message = ''){
|
211 |
+
wp_die( json_encode(array(
|
212 |
+
'job' => isset($this->options->currentJob) ? $this->options->currentJob : '',
|
213 |
+
'status' => false,
|
214 |
+
'message' => $message,
|
215 |
+
'error' => true
|
216 |
+
)));
|
217 |
+
}
|
218 |
}
|
apps/Core/Utils/Strings.php
CHANGED
@@ -17,6 +17,10 @@ class Strings{
|
|
17 |
* @return string
|
18 |
*/
|
19 |
public function str_replace_first( $search, $replace, $subject ) {
|
|
|
|
|
|
|
|
|
20 |
$pos = strpos( $subject, $search );
|
21 |
if( $pos !== false ) {
|
22 |
return substr_replace( $subject, $replace, $pos, strlen( $search ) );
|
@@ -24,4 +28,16 @@ public function str_replace_first( $search, $replace, $subject ) {
|
|
24 |
return $subject;
|
25 |
}
|
26 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
27 |
}
|
17 |
* @return string
|
18 |
*/
|
19 |
public function str_replace_first( $search, $replace, $subject ) {
|
20 |
+
|
21 |
+
if( empty( $search ) )
|
22 |
+
return $subject;
|
23 |
+
|
24 |
$pos = strpos( $subject, $search );
|
25 |
if( $pos !== false ) {
|
26 |
return substr_replace( $subject, $replace, $pos, strlen( $search ) );
|
28 |
return $subject;
|
29 |
}
|
30 |
|
31 |
+
/**
|
32 |
+
* Get last string after last certain element in string
|
33 |
+
* Example: getLastElemAfterString('/', '/path/stagingsite/subfolder') returns 'subfolder'
|
34 |
+
* @param string $needle
|
35 |
+
* @param string $haystack
|
36 |
+
* @return string
|
37 |
+
*/
|
38 |
+
public function getLastElemAfterString( $needle, $haystack ) {
|
39 |
+
$pos = strrpos( $haystack, $needle );
|
40 |
+
return $pos === false ? $haystack : substr( $haystack, $pos + 1 );
|
41 |
+
}
|
42 |
+
|
43 |
}
|
apps/Core/WPStaging.php
CHANGED
@@ -29,7 +29,7 @@ final class WPStaging {
|
|
29 |
/**
|
30 |
* Plugin version
|
31 |
*/
|
32 |
-
const VERSION = "2.2.
|
33 |
|
34 |
/**
|
35 |
* Plugin name
|
@@ -44,7 +44,7 @@ final class WPStaging {
|
|
44 |
/**
|
45 |
* Compatible WP Version
|
46 |
*/
|
47 |
-
const WP_COMPATIBLE = "4.9.
|
48 |
|
49 |
/**
|
50 |
* Slug: Either wp-staging or wp-staging-pro
|
29 |
/**
|
30 |
* Plugin version
|
31 |
*/
|
32 |
+
const VERSION = "2.2.5";
|
33 |
|
34 |
/**
|
35 |
* Plugin name
|
44 |
/**
|
45 |
* Compatible WP Version
|
46 |
*/
|
47 |
+
const WP_COMPATIBLE = "4.9.5";
|
48 |
|
49 |
/**
|
50 |
* Slug: Either wp-staging or wp-staging-pro
|
apps/Frontend/Frontend.php
CHANGED
@@ -30,8 +30,7 @@ class Frontend extends InjectionAware {
|
|
30 |
|
31 |
$this->settings = json_decode( json_encode( get_option( "wpstg_settings", array() ) ) );
|
32 |
|
33 |
-
$this->loginSlug = isset($this->settings->loginSlug) ? $this->settings->loginSlug : '';
|
34 |
-
|
35 |
}
|
36 |
|
37 |
/**
|
@@ -65,18 +64,45 @@ class Frontend extends InjectionAware {
|
|
65 |
/**
|
66 |
* Check permissions for the page to decide whether or not to disable the page
|
67 |
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
68 |
public function checkPermissions() {
|
69 |
$this->resetPermaLinks();
|
70 |
|
71 |
-
if(
|
72 |
-
wp_die( sprintf( __( 'Access denied. <a href="%1$s">Login</a> first to access this site', 'wpstg' ), $this->getLoginUrl() ) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
73 |
|
74 |
/**
|
75 |
* Lines below are not used at the moment but are fully functional
|
76 |
*/
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
}
|
81 |
}
|
82 |
|
@@ -84,15 +110,24 @@ class Frontend extends InjectionAware {
|
|
84 |
* Get login link
|
85 |
* @return string
|
86 |
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
87 |
private function getLoginUrl() {
|
88 |
-
|
89 |
-
if( empty( $this->loginSlug ) ) {
|
90 |
-
return get_home_url() . '/wp-admin';
|
91 |
}
|
92 |
|
93 |
-
return get_home_url() . '/?' . $this->loginSlug;
|
94 |
-
}
|
95 |
-
|
96 |
/**
|
97 |
* Check if the page should be blocked
|
98 |
* @return bool
|
30 |
|
31 |
$this->settings = json_decode( json_encode( get_option( "wpstg_settings", array() ) ) );
|
32 |
|
33 |
+
$this->loginSlug = isset( $this->settings->loginSlug ) ? $this->settings->loginSlug : '';
|
|
|
34 |
}
|
35 |
|
36 |
/**
|
64 |
/**
|
65 |
* Check permissions for the page to decide whether or not to disable the page
|
66 |
*/
|
67 |
+
// public function checkPermissions() {
|
68 |
+
// $this->resetPermaLinks();
|
69 |
+
//
|
70 |
+
// if( $this->disableLogin() ) {
|
71 |
+
// wp_die( sprintf( __( 'Access denied. <a href="%1$s">Login</a> first to access this site', 'wpstg' ), $this->getLoginUrl() ) );
|
72 |
+
// }
|
73 |
+
// }
|
74 |
public function checkPermissions() {
|
75 |
$this->resetPermaLinks();
|
76 |
|
77 |
+
if($this->disableLogin() ) {
|
78 |
+
//wp_die( sprintf( __( 'Access denied. <a href="%1$s">Login</a> first to access this site', 'wpstg' ), $this->getLoginUrl() ) );
|
79 |
+
//}
|
80 |
+
$args = array(
|
81 |
+
'echo' => true,
|
82 |
+
// Default 'redirect' value takes the user back to the request URI.
|
83 |
+
'redirect' => ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'],
|
84 |
+
'form_id' => 'loginform',
|
85 |
+
'label_username' => __( 'Username or Email Address' ),
|
86 |
+
'label_password' => __( 'Password' ),
|
87 |
+
'label_remember' => __( 'Remember Me' ),
|
88 |
+
'label_log_in' => __( 'Log In' ),
|
89 |
+
'id_username' => 'user_login',
|
90 |
+
'id_password' => 'user_pass',
|
91 |
+
'id_remember' => 'rememberme',
|
92 |
+
'id_submit' => 'wp-submit',
|
93 |
+
'remember' => true,
|
94 |
+
'value_username' => '',
|
95 |
+
// Set 'value_remember' to true to default the "Remember me" checkbox to checked.
|
96 |
+
'value_remember' => false,
|
97 |
+
);
|
98 |
+
|
99 |
|
100 |
/**
|
101 |
* Lines below are not used at the moment but are fully functional
|
102 |
*/
|
103 |
+
$login = new loginForm();
|
104 |
+
$login->renderForm($args);
|
105 |
+
die();
|
106 |
}
|
107 |
}
|
108 |
|
110 |
* Get login link
|
111 |
* @return string
|
112 |
*/
|
113 |
+
// private function getLoginUrl() {
|
114 |
+
//
|
115 |
+
// if( empty( $this->loginSlug ) ) {
|
116 |
+
// //return get_home_url() . '/wp-admin';
|
117 |
+
// return get_site_url() . '/wp-admin';
|
118 |
+
//
|
119 |
+
// }
|
120 |
+
//
|
121 |
+
// return get_home_url() . '/?' . $this->loginSlug;
|
122 |
+
// }
|
123 |
+
/**
|
124 |
+
* Get path to wp-login.php
|
125 |
+
* @return string
|
126 |
+
*/
|
127 |
private function getLoginUrl() {
|
128 |
+
return get_site_url() . '/wp-login.php';
|
|
|
|
|
129 |
}
|
130 |
|
|
|
|
|
|
|
131 |
/**
|
132 |
* Check if the page should be blocked
|
133 |
* @return bool
|
apps/Frontend/loginForm.php
CHANGED
@@ -4,7 +4,57 @@ namespace WPStaging\Frontend;
|
|
4 |
|
5 |
class loginForm {
|
6 |
|
7 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8 |
$this->getHeader();
|
9 |
$this->getLoginForm();
|
10 |
$this->getFooter();
|
@@ -139,27 +189,109 @@ class loginForm {
|
|
139 |
* Render login form by using native wp function wp_login_form
|
140 |
* return string
|
141 |
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
142 |
private function getLoginForm() {
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
'
|
149 |
-
'
|
150 |
-
'
|
151 |
-
'label_username' => __( 'Username', 'wpstg' ),
|
152 |
-
'label_password' => __( 'Password', 'wpstg' ),
|
153 |
'label_remember' => __( 'Remember Me' ),
|
154 |
-
'label_log_in' => __( 'Log In
|
155 |
-
'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
156 |
);
|
157 |
-
wp_login_form( $args );
|
158 |
-
$this->getFooter();
|
159 |
-
}
|
160 |
|
161 |
-
|
162 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
163 |
}
|
164 |
|
165 |
}
|
4 |
|
5 |
class loginForm {
|
6 |
|
7 |
+
/**
|
8 |
+
*
|
9 |
+
* @var type array
|
10 |
+
*/
|
11 |
+
private $args = array();
|
12 |
+
private $error;
|
13 |
+
|
14 |
+
function __construct() {
|
15 |
+
$this->login();
|
16 |
+
}
|
17 |
+
|
18 |
+
private function login() {
|
19 |
+
|
20 |
+
|
21 |
+
if( is_user_logged_in() ) {
|
22 |
+
return false;
|
23 |
+
}
|
24 |
+
|
25 |
+
if(!isset($_POST['wpstg-username']) || !isset ($_POST['wpstg-pass'])){
|
26 |
+
return false;
|
27 |
+
}
|
28 |
+
|
29 |
+
|
30 |
+
if( isset( $_POST['wpstg-submit'] ) && (empty( $_POST['wpstg-username'] ) || empty( $_POST['wpstg-pass'] ) ) ) {
|
31 |
+
$this->error = 'No username or password given!';
|
32 |
+
return false;
|
33 |
+
}
|
34 |
+
|
35 |
+
$user_data = get_user_by( 'login', $_POST['wpstg-username'] );
|
36 |
+
|
37 |
+
if( !$user_data ) {
|
38 |
+
$user_data = get_user_by( 'email', $_POST['wpstg-username'] );
|
39 |
+
}
|
40 |
+
|
41 |
+
if( !$user_data ) {
|
42 |
+
return false;
|
43 |
+
}
|
44 |
+
|
45 |
+
if( wp_check_password( $_POST['wpstg-pass'], $user_data->user_pass, $user_data->ID ) ) {
|
46 |
+
|
47 |
+
$rememberme = isset($_POST['rememberme']) ? true : false;
|
48 |
+
|
49 |
+
wp_set_auth_cookie( $user_data->ID, $rememberme );
|
50 |
+
wp_set_current_user( $user_data->ID, $_POST['wpstg-username'] );
|
51 |
+
do_action( 'wp_login', $_POST['wpstg-username'], get_userdata( $user_data->ID ) );
|
52 |
+
header( 'Location:' . get_site_url() . '/wp-admin/' );
|
53 |
+
}
|
54 |
+
}
|
55 |
+
|
56 |
+
public function renderForm( $args = array() ) {
|
57 |
+
$this->args = $args;
|
58 |
$this->getHeader();
|
59 |
$this->getLoginForm();
|
60 |
$this->getFooter();
|
189 |
* Render login form by using native wp function wp_login_form
|
190 |
* return string
|
191 |
*/
|
192 |
+
// private function getLoginForm() {
|
193 |
+
// $this->getHeader();
|
194 |
+
// echo '<body id="error-page">';
|
195 |
+
// echo __( 'Access denied. Login to access this site', 'wpstg' );
|
196 |
+
//
|
197 |
+
// $args = array(
|
198 |
+
// 'redirect' => admin_url(),
|
199 |
+
// 'redirect' => admin_url(),
|
200 |
+
// 'form_id' => 'wpstg-loginform',
|
201 |
+
// 'label_username' => __( 'Username', 'wpstg' ),
|
202 |
+
// 'label_password' => __( 'Password', 'wpstg' ),
|
203 |
+
// 'label_remember' => __( 'Remember Me' ),
|
204 |
+
// 'label_log_in' => __( 'Log In Staging Site' ),
|
205 |
+
// 'remember' => true
|
206 |
+
// );
|
207 |
+
// wp_login_form( $args );
|
208 |
+
// $this->getFooter();
|
209 |
+
// }
|
210 |
+
|
211 |
+
private function getFooter() {
|
212 |
+
echo '</html>';
|
213 |
+
}
|
214 |
+
|
215 |
+
/**
|
216 |
+
* Provides a simple login form for use anywhere within WordPress.
|
217 |
+
*
|
218 |
+
* The login format HTML is echoed by default. Pass a false value for `$echo` to return it instead.
|
219 |
+
*
|
220 |
+
* @since 3.0.0
|
221 |
+
*
|
222 |
+
* @param array $args {
|
223 |
+
* Optional. Array of options to control the form output. Default empty array.
|
224 |
+
*
|
225 |
+
* @type bool $echo Whether to display the login form or return the form HTML code.
|
226 |
+
* Default true (echo).
|
227 |
+
* @type string $redirect URL to redirect to. Must be absolute, as in "https://example.com/mypage/".
|
228 |
+
* Default is to redirect back to the request URI.
|
229 |
+
* @type string $form_id ID attribute value for the form. Default 'loginform'.
|
230 |
+
* @type string $label_username Label for the username or email address field. Default 'Username or Email Address'.
|
231 |
+
* @type string $label_password Label for the password field. Default 'Password'.
|
232 |
+
* @type string $label_remember Label for the remember field. Default 'Remember Me'.
|
233 |
+
* @type string $label_log_in Label for the submit button. Default 'Log In'.
|
234 |
+
* @type string $id_username ID attribute value for the username field. Default 'user_login'.
|
235 |
+
* @type string $id_password ID attribute value for the password field. Default 'user_pass'.
|
236 |
+
* @type string $id_remember ID attribute value for the remember field. Default 'rememberme'.
|
237 |
+
* @type string $id_submit ID attribute value for the submit button. Default 'wp-submit'.
|
238 |
+
* @type bool $remember Whether to display the "rememberme" checkbox in the form.
|
239 |
+
* @type string $value_username Default value for the username field. Default empty.
|
240 |
+
* @type bool $value_remember Whether the "Remember Me" checkbox should be checked by default.
|
241 |
+
* Default false (unchecked).
|
242 |
+
*
|
243 |
+
* }
|
244 |
+
* @return string|void String when retrieving.
|
245 |
+
*/
|
246 |
private function getLoginForm() {
|
247 |
+
|
248 |
+
$arguments = array(
|
249 |
+
'echo' => true,
|
250 |
+
// Default 'redirect' value takes the user back to the request URI.
|
251 |
+
'redirect' => ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'],
|
252 |
+
'form_id' => 'loginform',
|
253 |
+
'label_username' => __( 'Username or Email Address' ),
|
254 |
+
'label_password' => __( 'Password' ),
|
|
|
|
|
255 |
'label_remember' => __( 'Remember Me' ),
|
256 |
+
'label_log_in' => __( 'Log In' ),
|
257 |
+
'id_username' => 'user_login',
|
258 |
+
'id_password' => 'user_pass',
|
259 |
+
'id_remember' => 'rememberme',
|
260 |
+
'id_submit' => 'wp-submit',
|
261 |
+
'remember' => true,
|
262 |
+
'value_username' => '',
|
263 |
+
// Set 'value_remember' to true to default the "Remember me" checkbox to checked.
|
264 |
+
'value_remember' => false
|
265 |
);
|
|
|
|
|
|
|
266 |
|
267 |
+
$args = empty( $this->args ) ? $arguments : $this->args;
|
268 |
+
|
269 |
+
$form = '
|
270 |
+
<form name="' . $args['form_id'] . '" id="' . $args['form_id'] . '" action="" method="post">
|
271 |
+
<p class="login-username">
|
272 |
+
<label for="' . esc_attr( $args['id_username'] ) . '">' . esc_html( $args['label_username'] ) . '</label>
|
273 |
+
<input type="text" name="wpstg-username" id="' . esc_attr( $args['id_username'] ) . '" class="input" value="' . esc_attr( $args['value_username'] ) . '" size="20" />
|
274 |
+
</p>
|
275 |
+
<p class="login-password">
|
276 |
+
<label for="' . esc_attr( $args['id_password'] ) . '">' . esc_html( $args['label_password'] ) . '</label>
|
277 |
+
<input type="password" name="wpstg-pass" id="' . esc_attr( $args['id_password'] ) . '" class="input" value="" size="20" />
|
278 |
+
</p>
|
279 |
+
' . ( $args['remember'] ? '<p class="login-remember"><label><input name="rememberme" type="checkbox" id="' . esc_attr( $args['id_remember'] ) . '" value="forever"' . ( $args['value_remember'] ? ' checked="checked"' : '' ) . ' /> ' . esc_html( $args['label_remember'] ) . '</label></p>' : '' ) . '
|
280 |
+
<p class="login-submit">
|
281 |
+
<input type="submit" name="wpstg-submit" id="' . esc_attr( $args['id_submit'] ) . '" class="button button-primary" value="' . esc_attr( $args['label_log_in'] ) . '" />
|
282 |
+
<input type="hidden" name="redirect_to" value="' . esc_url( $args['redirect'] ) . '" />
|
283 |
+
</p>
|
284 |
+
<p>
|
285 |
+
' . $this->error . '
|
286 |
+
</p>
|
287 |
+
|
288 |
+
|
289 |
+
</form>';
|
290 |
+
|
291 |
+
if( $args['echo'] )
|
292 |
+
echo $form;
|
293 |
+
else
|
294 |
+
return $form;
|
295 |
}
|
296 |
|
297 |
}
|
readme.txt
CHANGED
@@ -9,7 +9,8 @@ License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
|
9 |
Tags: staging, duplication, cloning, clone, migration, sandbox, test site, testing, backup, post, admin, administration, duplicate posts
|
10 |
Requires at least: 3.6+
|
11 |
Tested up to: 4.9
|
12 |
-
Stable tag: 2.2.
|
|
|
13 |
|
14 |
A duplicator plugin! Clone, duplicate and migrate live sites to independent staging and development sites that are available only to administrators.
|
15 |
|
@@ -145,6 +146,17 @@ https://wp-staging.com
|
|
145 |
|
146 |
== Changelog ==
|
147 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
148 |
= 2.2.4 =
|
149 |
* New: Replace even hardcoded links and server path by using search & replace through all staging site database tables
|
150 |
* New: New and improved progress bar with elapsed time
|
@@ -215,35 +227,9 @@ https://wp-staging.com
|
|
215 |
* Fix: Other staging site can be overwritten when Edit/Update clone function is executed
|
216 |
* Fix: Several improvements to improve reliability and prevent timeouts and fatal errors during cloning
|
217 |
|
218 |
-
= 2.1.2 =
|
219 |
-
* Fix: Remove LOCK_EX parameter in file_put_contents(). LOCK_EX is not working on several systems which results in cloning process timeouts
|
220 |
-
* Fix: Huge Performance improvement in copying process by removing duplicate file entries in the cache file. This also prevents weird timeout issues on some hosted websites
|
221 |
-
* Fix: Error 500 when debug mode is activated
|
222 |
-
* Fix: Limit maximum execution time to 30 seconds
|
223 |
-
* Fix: Sanitize Clone Names and Keys to fix "clone not found" issue in upgrade routine
|
224 |
-
* Fix: Do not clone the plugin wps-hide-login
|
225 |
-
* Fix: Staging sites can not be deleted if they are very big
|
226 |
-
* Fix: Link to staging site is undefined
|
227 |
-
* Tweak: Better admin message for asking for a review
|
228 |
-
* Tweak: Remove table wpstg_rmpermalinks_executed when plugin is uninstalled
|
229 |
-
* New: New setting to specify the maximum amount of files copied within one ajax call to fix godaddy and bluehost ajax 404 errors. Default 10 per batch
|
230 |
-
|
231 |
-
|
232 |
-
= 2.1.1 =
|
233 |
-
* New: Add link to tutorial explaining the process of pushing modification to the live site
|
234 |
-
|
235 |
-
= 2.1.0 =
|
236 |
-
* New: Exclude unneccessary files from cloning process: .tmp, .log, .htaccess, .git, .gitignore, desktop.ini, .DS_Store, .svn
|
237 |
-
* New: More details for debugging in Tools->System Info
|
238 |
-
* Fix: Check if tables in staging site exists before attempting to modify them
|
239 |
-
* Fix: WordPress in sub directories were not opening
|
240 |
-
* Fix: Nonce check not working if nonce life time is filtered by another plugin WP Bug: https://core.trac.wordpress.org/ticket/41617#comment:1
|
241 |
-
* Fix: Access to staging site not working, if WP_SITEURL and WP_HOME is defined in wp-config.php
|
242 |
-
* Tweak: Exclude wp-content/cache folder from copying process
|
243 |
-
|
244 |
Complete changelog: [https://wp-staging.com/changelog.txt](https://wp-staging.com/changelog.txt)
|
245 |
|
246 |
== Upgrade Notice ==
|
247 |
|
248 |
-
= 2.2.
|
249 |
-
2.2.
|
9 |
Tags: staging, duplication, cloning, clone, migration, sandbox, test site, testing, backup, post, admin, administration, duplicate posts
|
10 |
Requires at least: 3.6+
|
11 |
Tested up to: 4.9
|
12 |
+
Stable tag: 2.2.5
|
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.
|
16 |
|
146 |
|
147 |
== Changelog ==
|
148 |
|
149 |
+
= 2.2.5 =
|
150 |
+
* New: Compatible to WP 4.9.5
|
151 |
+
* New: Allow to select and copy extra folders that are on the root level
|
152 |
+
* New: Use fully custom login form to prevent access denied issues on sites where access to wp-login.php is denied or redirection plugins are used
|
153 |
+
* Fix: Incorrect login path to staging site if WordPress is installed in subdirectory
|
154 |
+
* Fix: Login url is wrong if WP is installed in subfolder
|
155 |
+
* Fix: If PHP 5.6.34 is used, the cloning process could be unfinished due to use of private member in protected class
|
156 |
+
* Tweak: Only wp root folders are pre selected before cloning is starting
|
157 |
+
* Tweak: Change WP_HOME or WP_SITEURL constants of staging site if they are defined in wp-config.php
|
158 |
+
|
159 |
+
|
160 |
= 2.2.4 =
|
161 |
* New: Replace even hardcoded links and server path by using search & replace through all staging site database tables
|
162 |
* New: New and improved progress bar with elapsed time
|
227 |
* Fix: Other staging site can be overwritten when Edit/Update clone function is executed
|
228 |
* Fix: Several improvements to improve reliability and prevent timeouts and fatal errors during cloning
|
229 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
230 |
Complete changelog: [https://wp-staging.com/changelog.txt](https://wp-staging.com/changelog.txt)
|
231 |
|
232 |
== Upgrade Notice ==
|
233 |
|
234 |
+
= 2.2.5 =
|
235 |
+
2.2.5 * New: Compatible to WP 4.9.5
|
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.2.
|
11 |
* Text Domain: wpstg
|
12 |
* Domain Path: /languages/
|
13 |
|
7 |
* Author: WP-Staging
|
8 |
* Author URI: https://wp-staging.com
|
9 |
* Contributors: ReneHermi, ilgityildirim
|
10 |
+
* Version: 2.2.5
|
11 |
* Text Domain: wpstg
|
12 |
* Domain Path: /languages/
|
13 |
|