Version Description
- Fix: If WPML is used the live site is not reachable
- Fix: Can not disable optimizer
- Fix: Stop cloning if wp_usermeta or wp_options can not be adapted
- Fix: All methods should be private in class SearchReplace
- Fix: PHP 7.2 is not countable warning
- Fix: PHP 7.2 can not replace data in objects when object is incomplete (_PHP_IncompleteClass_Name)
- 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
- New: Link to support section
Download this release
Release Info
Developer | ReneHermi |
Plugin | WP Staging – DB & File Duplicator & Migration |
Version | 2.2.6 |
Comparing to | |
See all releases |
Code changes from version 2.2.5 to 2.2.6
- apps/Backend/Modules/Jobs/Data.php +429 -451
- apps/Backend/Modules/Jobs/Files.php +0 -5
- apps/Backend/Modules/Jobs/Scan.php +3 -2
- apps/Backend/Modules/Jobs/SearchReplace.php +70 -39
- apps/Backend/Modules/SystemInfo.php +16 -8
- apps/Backend/Modules/Views/Forms/Settings.php +2 -3
- apps/Backend/Upgrade/Upgrade.php +7 -54
- apps/Backend/views/_includes/header.php +1 -1
- apps/Backend/views/clone/includes/footer.php +1 -0
- apps/Backend/views/settings/index.php +0 -23
- apps/Core/DTO/Settings.php +15 -13
- apps/Core/Utils/Helper.php +71 -0
- apps/Core/WPStaging.php +1 -1
- readme.txt +12 -1
- wp-staging.php +1 -1
apps/Backend/Modules/Jobs/Data.php
CHANGED
@@ -1,188 +1,189 @@
|
|
1 |
<?php
|
|
|
2 |
namespace WPStaging\Backend\Modules\Jobs;
|
3 |
|
4 |
// No Direct Access
|
5 |
-
if
|
6 |
-
|
7 |
-
die;
|
8 |
}
|
9 |
|
10 |
use WPStaging\Utils\Logger;
|
11 |
use WPStaging\WPStaging;
|
|
|
12 |
|
13 |
/**
|
14 |
* Class Data
|
15 |
* @package WPStaging\Backend\Modules\Jobs
|
16 |
*/
|
17 |
-
class Data extends JobExecutable
|
18 |
-
{
|
19 |
-
|
20 |
-
/**
|
21 |
-
* @var \wpdb
|
22 |
-
*/
|
23 |
-
private $db;
|
24 |
-
|
25 |
-
/**
|
26 |
-
* @var string
|
27 |
-
*/
|
28 |
-
private $prefix;
|
29 |
-
|
30 |
-
/**
|
31 |
-
* Initialize
|
32 |
-
*/
|
33 |
-
public function initialize()
|
34 |
-
{
|
35 |
-
$this->db = WPStaging::getInstance()->get("wpdb");
|
36 |
-
|
37 |
-
$this->prefix = $this->options->prefix;
|
38 |
-
|
39 |
-
// Fix current step
|
40 |
-
if (0 == $this->options->currentStep)
|
41 |
-
{
|
42 |
-
$this->options->currentStep = 1;
|
43 |
-
}
|
44 |
-
}
|
45 |
-
|
46 |
-
/**
|
47 |
-
* Calculate Total Steps in This Job and Assign It to $this->options->totalSteps
|
48 |
-
* @return void
|
49 |
-
*/
|
50 |
-
protected function calculateTotalSteps()
|
51 |
-
{
|
52 |
-
$this->options->totalSteps = 11;
|
53 |
-
}
|
54 |
-
|
55 |
-
/**
|
56 |
-
* Start Module
|
57 |
-
* @return object
|
58 |
-
*/
|
59 |
-
public function start()
|
60 |
-
{
|
61 |
-
// Execute steps
|
62 |
-
$this->run();
|
63 |
-
|
64 |
-
// Save option, progress
|
65 |
-
$this->saveOptions();
|
66 |
-
|
67 |
-
return (object) $this->response;
|
68 |
-
}
|
69 |
-
|
70 |
-
/**
|
71 |
-
* Execute the Current Step
|
72 |
-
* Returns false when over threshold limits are hit or when the job is done, true otherwise
|
73 |
-
* @return bool
|
74 |
-
*/
|
75 |
-
protected function execute()
|
76 |
-
{
|
77 |
-
// Fatal error. Let this happen never and break here immediately
|
78 |
-
if ($this->isRoot()){
|
79 |
-
return false;
|
80 |
-
}
|
81 |
-
|
82 |
-
// Over limits threshold
|
83 |
-
if ($this->isOverThreshold())
|
84 |
-
{
|
85 |
-
// Prepare response and save current progress
|
86 |
-
$this->prepareResponse(false, false);
|
87 |
-
$this->saveOptions();
|
88 |
-
return false;
|
89 |
-
}
|
90 |
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
return false;
|
96 |
-
}
|
97 |
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
159 |
$this->log( "Table {$table} does not exists", Logger::TYPE_ERROR );
|
160 |
return false;
|
161 |
}
|
162 |
return true;
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
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' ) ) {
|
@@ -191,19 +192,19 @@ class Data extends JobExecutable
|
|
191 |
|
192 |
// Installed in sub-directory
|
193 |
if( $this->isSubDir() ) {
|
194 |
-
$this->log( "Preparing Data Step1: Updating siteurl and homeurl to " . rtrim(
|
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(
|
199 |
)
|
200 |
);
|
201 |
} else {
|
202 |
-
$this->log( "Preparing Data Step1: Updating siteurl and homeurl to " . rtrim(
|
203 |
// Replace URLs
|
204 |
$result = $this->db->query(
|
205 |
$this->db->prepare(
|
206 |
-
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'siteurl' or option_name='home'",
|
207 |
)
|
208 |
);
|
209 |
}
|
@@ -219,298 +220,274 @@ class Data extends JobExecutable
|
|
219 |
}
|
220 |
|
221 |
/**
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
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;
|
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 |
-
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;
|
273 |
}
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
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;
|
301 |
}
|
302 |
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
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(
|
318 |
-
"UPDATE {$this->prefix}options SET option_name= replace(option_name, %s, %s) WHERE option_name LIKE %s", $this->db->prefix, $this->prefix, $this->db->prefix . "_%"
|
319 |
-
)
|
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;
|
328 |
-
}
|
329 |
-
|
330 |
-
/**
|
331 |
-
* Update $table_prefix in wp-config.php
|
332 |
-
* @return bool
|
333 |
-
*/
|
334 |
-
protected function step5()
|
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 |
-
|
345 |
-
// Replace table prefix
|
346 |
-
$content = str_replace('$table_prefix', '$table_prefix = \'' . $this->prefix . '\';//', $content);
|
347 |
-
|
348 |
-
// Replace URLs
|
349 |
-
$content = str_replace(get_home_url(), get_home_url() . '/' . $this->options->cloneDirectoryName, $content);
|
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 |
-
|
357 |
-
return true;
|
358 |
-
}
|
359 |
-
|
360 |
-
/**
|
361 |
-
* Reset index.php to original file
|
362 |
-
* This is needed if live site is located in subfolder
|
363 |
-
* Check first if main wordpress is used in subfolder and index.php in parent directory
|
364 |
-
* @see: https://codex.wordpress.org/Giving_WordPress_Its_Own_Directory
|
365 |
-
* @return bool
|
366 |
-
*/
|
367 |
-
protected function step6()
|
368 |
-
{
|
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 |
-
|
376 |
-
$path = ABSPATH . $this->options->cloneDirectoryName . "/index.php";
|
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 |
|
|
|
|
|
|
|
|
|
|
|
384 |
|
385 |
-
|
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 |
-
|
|
|
|
|
|
|
|
|
396 |
|
397 |
-
|
398 |
-
|
|
|
|
|
|
|
399 |
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
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 |
-
|
417 |
-
/**
|
418 |
-
* Update wpstg_rmpermalinks_executed
|
419 |
-
* @return bool
|
420 |
-
*/
|
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;
|
428 |
-
}
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
$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;
|
459 |
}
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
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;
|
489 |
}
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
*/
|
513 |
-
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() );
|
@@ -549,10 +526,10 @@ class Data extends JobExecutable
|
|
549 |
}
|
550 |
|
551 |
/**
|
552 |
-
|
553 |
-
|
554 |
-
|
555 |
-
|
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() );
|
@@ -597,20 +574,21 @@ class Data extends JobExecutable
|
|
597 |
*/
|
598 |
protected function getStagingSiteUrl() {
|
599 |
if( $this->isSubDir() ) {
|
600 |
-
return rtrim(
|
601 |
}
|
602 |
|
603 |
-
return rtrim(
|
604 |
}
|
605 |
|
606 |
/**
|
607 |
-
|
608 |
-
|
609 |
-
|
610 |
-
|
611 |
-
|
612 |
-
|
613 |
-
|
614 |
-
|
615 |
-
|
616 |
-
|
|
1 |
<?php
|
2 |
+
|
3 |
namespace WPStaging\Backend\Modules\Jobs;
|
4 |
|
5 |
// No Direct Access
|
6 |
+
if( !defined( "WPINC" ) ) {
|
7 |
+
die;
|
|
|
8 |
}
|
9 |
|
10 |
use WPStaging\Utils\Logger;
|
11 |
use WPStaging\WPStaging;
|
12 |
+
use WPStaging\Utils\Helper;
|
13 |
|
14 |
/**
|
15 |
* Class Data
|
16 |
* @package WPStaging\Backend\Modules\Jobs
|
17 |
*/
|
18 |
+
class Data extends JobExecutable {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
|
20 |
+
/**
|
21 |
+
* @var \wpdb
|
22 |
+
*/
|
23 |
+
private $db;
|
|
|
|
|
24 |
|
25 |
+
/**
|
26 |
+
* @var string
|
27 |
+
*/
|
28 |
+
private $prefix;
|
29 |
+
|
30 |
+
/**
|
31 |
+
*
|
32 |
+
* @var string
|
33 |
+
*/
|
34 |
+
private $homeUrl;
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Initialize
|
38 |
+
*/
|
39 |
+
public function initialize() {
|
40 |
+
$this->db = WPStaging::getInstance()->get( "wpdb" );
|
41 |
+
|
42 |
+
$this->prefix = $this->options->prefix;
|
43 |
+
|
44 |
+
$helper = new Helper();
|
45 |
+
|
46 |
+
$this->homeUrl = $helper->get_home_url();
|
47 |
+
|
48 |
+
|
49 |
+
// Fix current step
|
50 |
+
if( 0 == $this->options->currentStep ) {
|
51 |
+
$this->options->currentStep = 1;
|
52 |
+
}
|
53 |
+
}
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Calculate Total Steps in This Job and Assign It to $this->options->totalSteps
|
57 |
+
* @return void
|
58 |
+
*/
|
59 |
+
protected function calculateTotalSteps() {
|
60 |
+
$this->options->totalSteps = 11;
|
61 |
+
}
|
62 |
+
|
63 |
+
/**
|
64 |
+
* Start Module
|
65 |
+
* @return object
|
66 |
+
*/
|
67 |
+
public function start() {
|
68 |
+
// Execute steps
|
69 |
+
$this->run();
|
70 |
+
|
71 |
+
// Save option, progress
|
72 |
+
$this->saveOptions();
|
73 |
+
|
74 |
+
return ( object ) $this->response;
|
75 |
+
}
|
76 |
+
|
77 |
+
/**
|
78 |
+
* Execute the Current Step
|
79 |
+
* Returns false when over threshold limits are hit or when the job is done, true otherwise
|
80 |
+
* @return bool
|
81 |
+
*/
|
82 |
+
protected function execute() {
|
83 |
+
// Fatal error. Let this happen never and break here immediately
|
84 |
+
if( $this->isRoot() ) {
|
85 |
+
return false;
|
86 |
+
}
|
87 |
+
|
88 |
+
// Over limits threshold
|
89 |
+
if( $this->isOverThreshold() ) {
|
90 |
+
// Prepare response and save current progress
|
91 |
+
$this->prepareResponse( false, false );
|
92 |
+
$this->saveOptions();
|
93 |
+
return false;
|
94 |
+
}
|
95 |
+
|
96 |
+
// No more steps, finished
|
97 |
+
if( $this->isFinished() ) {
|
98 |
+
$this->prepareResponse( true, false );
|
99 |
+
return false;
|
100 |
+
}
|
101 |
+
|
102 |
+
// Execute step
|
103 |
+
$stepMethodName = "step" . $this->options->currentStep;
|
104 |
+
if( !$this->{$stepMethodName}() ) {
|
105 |
+
$this->prepareResponse( false, false );
|
106 |
+
return false;
|
107 |
+
}
|
108 |
+
|
109 |
+
// Prepare Response
|
110 |
+
$this->prepareResponse();
|
111 |
+
|
112 |
+
// Not finished
|
113 |
+
return true;
|
114 |
+
}
|
115 |
+
|
116 |
+
/**
|
117 |
+
* Checks Whether There is Any Job to Execute or Not
|
118 |
+
* @return bool
|
119 |
+
*/
|
120 |
+
protected function isFinished() {
|
121 |
+
return (
|
122 |
+
$this->options->currentStep > $this->options->totalSteps ||
|
123 |
+
!method_exists( $this, "step" . $this->options->currentStep )
|
124 |
+
);
|
125 |
+
}
|
126 |
+
|
127 |
+
/**
|
128 |
+
* Check if current operation is done on the root folder or on the live DB
|
129 |
+
* @return boolean
|
130 |
+
*/
|
131 |
+
protected function isRoot() {
|
132 |
+
|
133 |
+
// Prefix is the same as the one of live site
|
134 |
+
$wpdb = WPStaging::getInstance()->get( "wpdb" );
|
135 |
+
if( $wpdb->prefix === $this->prefix ) {
|
136 |
+
return true;
|
137 |
+
}
|
138 |
+
|
139 |
+
// CloneName is empty
|
140 |
+
$name = ( array ) $this->options->cloneDirectoryName;
|
141 |
+
if( empty( $name ) ) {
|
142 |
+
return true;
|
143 |
+
}
|
144 |
+
|
145 |
+
// Live Path === Staging path
|
146 |
+
if( $this->homeUrl . $this->options->cloneDirectoryName === $this->homeUrl ) {
|
147 |
+
return true;
|
148 |
+
}
|
149 |
+
|
150 |
+
return false;
|
151 |
+
}
|
152 |
+
|
153 |
+
/**
|
154 |
+
* Check if table exists
|
155 |
+
* @param string $table
|
156 |
+
* @return boolean
|
157 |
+
*/
|
158 |
+
protected function isTable( $table ) {
|
159 |
+
if( $this->db->get_var( "SHOW TABLES LIKE '{$table}'" ) != $table ) {
|
160 |
$this->log( "Table {$table} does not exists", Logger::TYPE_ERROR );
|
161 |
return false;
|
162 |
}
|
163 |
return true;
|
164 |
+
}
|
165 |
+
|
166 |
+
/**
|
167 |
+
* Get the install sub directory if WP is installed in sub directory
|
168 |
+
* @return string
|
169 |
+
*/
|
170 |
+
protected function getSubDir() {
|
171 |
+
$home = get_option( 'home' );
|
172 |
+
$siteurl = get_option( 'siteurl' );
|
173 |
+
|
174 |
+
if( empty( $home ) || empty( $siteurl ) ) {
|
175 |
+
return '/';
|
176 |
+
}
|
177 |
+
|
178 |
+
$dir = str_replace( $home, '', $siteurl );
|
179 |
+
return '/' . str_replace( '/', '', $dir ) . '/';
|
180 |
+
}
|
181 |
+
|
182 |
+
/**
|
183 |
+
* Replace "siteurl" and "home"
|
184 |
+
* @return bool
|
185 |
+
*/
|
186 |
+
protected function step1() {
|
187 |
$this->log( "Preparing Data Step1: Updating siteurl and homeurl in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_INFO );
|
188 |
|
189 |
if( false === $this->isTable( $this->prefix . 'options' ) ) {
|
192 |
|
193 |
// Installed in sub-directory
|
194 |
if( $this->isSubDir() ) {
|
195 |
+
$this->log( "Preparing Data Step1: Updating siteurl and homeurl to " . rtrim( $this->homeUrl, "/" ) . $this->getSubDir() . $this->options->cloneDirectoryName );
|
196 |
// Replace URLs
|
197 |
$result = $this->db->query(
|
198 |
$this->db->prepare(
|
199 |
+
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'siteurl' or option_name='home'", rtrim( $this->homeUrl, "/" ) . $this->getSubDir() . $this->options->cloneDirectoryName
|
200 |
)
|
201 |
);
|
202 |
} else {
|
203 |
+
$this->log( "Preparing Data Step1: Updating siteurl and homeurl to " . rtrim( $this->homeUrl, "/" ) . '/' . $this->options->cloneDirectoryName );
|
204 |
// Replace URLs
|
205 |
$result = $this->db->query(
|
206 |
$this->db->prepare(
|
207 |
+
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'siteurl' or option_name='home'", $this->homeUrl . '/' . $this->options->cloneDirectoryName
|
208 |
)
|
209 |
);
|
210 |
}
|
220 |
}
|
221 |
|
222 |
/**
|
223 |
+
* Update "wpstg_is_staging_site"
|
224 |
+
* @return bool
|
225 |
+
*/
|
226 |
+
protected function step2() {
|
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;
|
232 |
}
|
233 |
|
234 |
+
$result = $this->db->query(
|
235 |
+
$this->db->prepare(
|
236 |
+
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'wpstg_is_staging_site'", "true"
|
237 |
+
)
|
238 |
+
);
|
239 |
+
|
240 |
+
// No errors but no option name such as wpstg_is_staging_site
|
241 |
+
if( '' === $this->db->last_error && 0 == $result ) {
|
242 |
+
$result = $this->db->query(
|
243 |
+
$this->db->prepare(
|
244 |
+
"INSERT INTO {$this->prefix}options (option_name,option_value) VALUES ('wpstg_is_staging_site',%s)", "true"
|
245 |
+
)
|
246 |
+
);
|
247 |
+
}
|
248 |
+
|
249 |
+
// All good
|
250 |
+
if( $result ) {
|
251 |
+
return true;
|
252 |
+
}
|
253 |
+
|
254 |
+
$this->log( "Preparing Data Step2: Failed to update wpstg_is_staging_site in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_ERROR );
|
255 |
+
return false;
|
256 |
+
}
|
257 |
+
|
258 |
+
/**
|
259 |
+
* Update rewrite_rules
|
260 |
+
* @return bool
|
261 |
+
*/
|
262 |
+
protected function step3() {
|
263 |
+
|
264 |
+
$this->log( "Preparing Data Step3: Updating rewrite_rules in {$this->prefix}options {$this->db->last_error}" );
|
265 |
+
|
|
|
|
|
|
|
|
|
|
|
266 |
if( false === $this->isTable( $this->prefix . 'options' ) ) {
|
267 |
return true;
|
268 |
}
|
269 |
+
|
270 |
+
$result = $this->db->query(
|
271 |
+
$this->db->prepare(
|
272 |
+
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'rewrite_rules'", ' '
|
273 |
+
)
|
274 |
+
);
|
275 |
+
|
276 |
+
// All good
|
277 |
+
if( $result ) {
|
278 |
+
return true;
|
279 |
+
}
|
280 |
+
|
281 |
+
$this->log( "Preparing Data Step3: Failed to update rewrite_rules in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_ERROR );
|
282 |
+
return true;
|
283 |
+
}
|
284 |
+
|
285 |
+
/**
|
286 |
+
* Update Table Prefix in meta_keys
|
287 |
+
* @return bool
|
288 |
+
*/
|
289 |
+
protected function step4() {
|
290 |
+
$this->log( "Preparing Data Step4: Updating db prefix in {$this->prefix}usermeta. Error: {$this->db->last_error}" );
|
|
|
|
|
291 |
|
292 |
if( false === $this->isTable( $this->prefix . 'usermeta' ) ) {
|
293 |
return true;
|
294 |
}
|
295 |
|
296 |
+
$update = $this->db->query(
|
297 |
+
$this->db->prepare(
|
298 |
+
"UPDATE {$this->prefix}usermeta SET meta_key = replace(meta_key, %s, %s) WHERE meta_key LIKE %s", $this->db->prefix, $this->prefix, $this->db->prefix . "_%"
|
299 |
+
)
|
300 |
+
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
301 |
|
302 |
+
if( !$update ) {
|
303 |
+
$this->log( "Preparing Data Step4: Failed to update {$this->prefix}usermeta meta_key database table prefixes; {$this->db->last_error}", Logger::TYPE_ERROR );
|
304 |
+
$this->returnException( "Data Crunching Step 4: Failed to update {$this->prefix}usermeta meta_key database table prefixes; {$this->db->last_error}" );
|
305 |
+
return false;
|
306 |
+
}
|
307 |
|
308 |
+
$this->log( "Updating db prefixes in {$this->prefix}options. Error: {$this->db->last_error}" );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
309 |
|
310 |
+
$resultUserMeta = $this->db->query(
|
311 |
+
$this->db->prepare(
|
312 |
+
"UPDATE {$this->prefix}options SET option_name= replace(option_name, %s, %s) WHERE option_name LIKE %s", $this->db->prefix, $this->prefix, $this->db->prefix . "_%"
|
313 |
+
)
|
314 |
+
);
|
315 |
|
316 |
+
if( !$resultUserMeta ) {
|
317 |
+
$this->log( "Preparing Data Step4: Failed to update db prefixes in {$this->prefix}options. Error: {$this->db->last_error}", Logger::TYPE_ERROR );
|
318 |
+
$this->returnException( "Data Crunching Step 4: Failed to update db prefixes in {$this->prefix}options. Error: {$this->db->last_error}" );
|
319 |
+
return false;
|
320 |
+
}
|
321 |
|
322 |
+
return true;
|
323 |
+
}
|
324 |
+
|
325 |
+
/**
|
326 |
+
* Update $table_prefix in wp-config.php
|
327 |
+
* @return bool
|
328 |
+
*/
|
329 |
+
protected function step5() {
|
330 |
+
$path = ABSPATH . $this->options->cloneDirectoryName . "/wp-config.php";
|
331 |
+
|
332 |
+
$this->log( "Preparing Data Step5: Updating table_prefix in {$path} to " . $this->prefix );
|
333 |
+
if( false === ($content = file_get_contents( $path )) ) {
|
334 |
+
$this->log( "Preparing Data Step5: Failed to update table_prefix in {$path}. Can't read contents", Logger::TYPE_ERROR );
|
335 |
+
return false;
|
336 |
+
}
|
337 |
+
|
338 |
+
// Replace table prefix
|
339 |
+
$content = str_replace( '$table_prefix', '$table_prefix = \'' . $this->prefix . '\';//', $content );
|
340 |
+
|
341 |
+
// Replace URLs
|
342 |
+
$content = str_replace( $this->homeUrl, $this->homeUrl . '/' . $this->options->cloneDirectoryName, $content );
|
343 |
+
|
344 |
+
if( false === @file_put_contents( $path, $content ) ) {
|
345 |
+
$this->log( "Preparing Data Step5: Failed to update $table_prefix in {$path} to " . $this->prefix . ". Can't save contents", Logger::TYPE_ERROR );
|
346 |
+
return false;
|
347 |
+
}
|
348 |
+
|
349 |
+
return true;
|
350 |
+
}
|
351 |
+
|
352 |
+
/**
|
353 |
+
* Reset index.php to original file
|
354 |
+
* This is needed if live site is located in subfolder
|
355 |
+
* Check first if main wordpress is used in subfolder and index.php in parent directory
|
356 |
+
* @see: https://codex.wordpress.org/Giving_WordPress_Its_Own_Directory
|
357 |
+
* @return bool
|
358 |
+
*/
|
359 |
+
protected function step6() {
|
360 |
+
|
361 |
+
if( !$this->isSubDir() ) {
|
362 |
+
$this->debugLog( "Preparing Data Step6: WP installation is not in a subdirectory! All good, skipping this step" );
|
363 |
+
return true;
|
364 |
+
}
|
365 |
+
|
366 |
+
$path = ABSPATH . $this->options->cloneDirectoryName . "/index.php";
|
367 |
+
|
368 |
+
if( false === ($content = file_get_contents( $path )) ) {
|
369 |
+
$this->log( "Preparing Data Step6: Failed to reset {$path} for sub directory; can't read contents", Logger::TYPE_ERROR );
|
370 |
+
return false;
|
371 |
+
}
|
372 |
+
|
373 |
+
|
374 |
+
if( !preg_match( "/(require(.*)wp-blog-header.php' \);)/", $content, $matches ) ) {
|
375 |
+
$this->log(
|
376 |
+
"Preparing Data Step6: Failed to reset index.php for sub directory; wp-blog-header.php is missing", Logger::TYPE_ERROR
|
377 |
+
);
|
378 |
+
return false;
|
379 |
+
}
|
380 |
+
$this->log( "Preparing Data: WP installation is in a subdirectory. Progressing..." );
|
381 |
+
|
382 |
+
$pattern = "/require(.*) dirname(.*) __FILE__ (.*) \. '(.*)wp-blog-header.php'(.*);/";
|
383 |
+
|
384 |
+
$replace = "require( dirname( __FILE__ ) . '/wp-blog-header.php' ); // " . $matches[0];
|
385 |
+
$replace.= " // Changed by WP-Staging";
|
386 |
+
|
387 |
+
|
388 |
+
|
389 |
+
if( null === ($content = preg_replace( array($pattern), $replace, $content )) ) {
|
390 |
+
$this->log( "Preparing Data: Failed to reset index.php for sub directory; replacement failed", Logger::TYPE_ERROR );
|
391 |
+
return false;
|
392 |
+
}
|
393 |
+
|
394 |
+
if( false === @file_put_contents( $path, $content ) ) {
|
395 |
+
$this->log( "Preparing Data: Failed to reset index.php for sub directory; can't save contents", Logger::TYPE_ERROR );
|
396 |
+
return false;
|
397 |
+
}
|
398 |
+
$this->Log( "Preparing Data: Finished Step 6 successfully" );
|
399 |
+
return true;
|
400 |
+
}
|
401 |
+
|
402 |
+
/**
|
403 |
+
* Update wpstg_rmpermalinks_executed
|
404 |
+
* @return bool
|
405 |
+
*/
|
406 |
+
protected function step7() {
|
407 |
+
|
408 |
+
$this->log( "Preparing Data Step7: Updating wpstg_rmpermalinks_executed in {$this->prefix}options {$this->db->last_error}" );
|
409 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
410 |
if( false === $this->isTable( $this->prefix . 'options' ) ) {
|
411 |
return true;
|
412 |
+
}
|
413 |
+
|
414 |
+
$result = $this->db->query(
|
415 |
+
$this->db->prepare(
|
416 |
+
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'wpstg_rmpermalinks_executed'", ' '
|
417 |
+
)
|
418 |
+
);
|
419 |
+
|
420 |
+
// All good
|
421 |
+
if( $result ) {
|
422 |
+
$this->Log( "Preparing Data Step7: Finished Step 7 successfully" );
|
423 |
+
return true;
|
424 |
+
}
|
425 |
+
|
426 |
+
$this->log( "Failed to update wpstg_rmpermalinks_executed in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_WARNING );
|
427 |
+
return true;
|
428 |
+
}
|
429 |
+
|
430 |
+
/**
|
431 |
+
* Update permalink_structure
|
432 |
+
* @return bool
|
433 |
+
*/
|
434 |
+
protected function step8() {
|
435 |
+
|
436 |
+
$this->log( "Preparing Data Step8: Updating permalink_structure in {$this->prefix}options {$this->db->last_error}" );
|
437 |
+
|
|
|
|
|
|
|
438 |
if( false === $this->isTable( $this->prefix . 'options' ) ) {
|
439 |
return true;
|
440 |
}
|
441 |
+
|
442 |
+
$result = $this->db->query(
|
443 |
+
$this->db->prepare(
|
444 |
+
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'permalink_structure'", ' '
|
445 |
+
)
|
446 |
+
);
|
447 |
+
|
448 |
+
// All good
|
449 |
+
if( $result ) {
|
450 |
+
$this->Log( "Preparing Data Step8: Finished Step 8 successfully" );
|
451 |
+
return true;
|
452 |
+
}
|
453 |
+
|
454 |
+
$this->log( "Failed to update permalink_structure in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_ERROR );
|
455 |
+
return true;
|
456 |
+
}
|
457 |
+
|
458 |
+
/**
|
459 |
+
* Update blog_public option to not allow staging site to be indexed by search engines
|
460 |
+
* @return bool
|
461 |
+
*/
|
462 |
+
protected function step9() {
|
463 |
+
|
464 |
+
$this->log( "Preparing Data Step9: Set staging site to noindex" );
|
465 |
+
|
|
|
|
|
466 |
if( false === $this->isTable( $this->prefix . 'options' ) ) {
|
467 |
return true;
|
468 |
}
|
469 |
+
|
470 |
+
$result = $this->db->query(
|
471 |
+
$this->db->prepare(
|
472 |
+
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'blog_public'", '0'
|
473 |
+
)
|
474 |
+
);
|
475 |
+
|
476 |
+
// All good
|
477 |
+
if( $result ) {
|
478 |
+
$this->Log( "Preparing Data Step9: Finished Step 9 successfully" );
|
479 |
+
return true;
|
480 |
+
}
|
481 |
+
|
482 |
+
$this->log( "Can not update staging site to noindex. Possible already done!", Logger::TYPE_WARNING );
|
483 |
+
return true;
|
484 |
+
}
|
485 |
+
|
486 |
+
/**
|
487 |
+
* Update WP_HOME in wp-config.php
|
488 |
+
* @return bool
|
489 |
+
*/
|
490 |
+
protected function step10() {
|
|
|
|
|
491 |
$path = ABSPATH . $this->options->cloneDirectoryName . "/wp-config.php";
|
492 |
|
493 |
$this->log( "Preparing Data Step10: Updating WP_HOME in wp-config.php to " . $this->getStagingSiteUrl() );
|
526 |
}
|
527 |
|
528 |
/**
|
529 |
+
* Update WP_SITEURL in wp-config.php
|
530 |
+
* @return bool
|
531 |
+
*/
|
532 |
+
protected function step11() {
|
533 |
$path = ABSPATH . $this->options->cloneDirectoryName . "/wp-config.php";
|
534 |
|
535 |
$this->log( "Preparing Data Step11: Updating WP_SITEURL in wp-config.php to " . $this->getStagingSiteUrl() );
|
574 |
*/
|
575 |
protected function getStagingSiteUrl() {
|
576 |
if( $this->isSubDir() ) {
|
577 |
+
return rtrim( $this->homeUrl, "/" ) . $this->getSubDir() . $this->options->cloneDirectoryName;
|
578 |
}
|
579 |
|
580 |
+
return rtrim( $this->homeUrl, "/" ) . '/' . $this->options->cloneDirectoryName;
|
581 |
}
|
582 |
|
583 |
/**
|
584 |
+
* Check if WP is installed in subdir
|
585 |
+
* @return boolean
|
586 |
+
*/
|
587 |
+
protected function isSubDir() {
|
588 |
+
if( get_option( 'siteurl' ) !== get_option( 'home' ) ) {
|
589 |
+
return true;
|
590 |
+
}
|
591 |
+
return false;
|
592 |
+
}
|
593 |
+
|
594 |
+
}
|
apps/Backend/Modules/Jobs/Files.php
CHANGED
@@ -25,11 +25,6 @@ class Files extends JobExecutable {
|
|
25 |
*/
|
26 |
private $maxFilesPerRun;
|
27 |
|
28 |
-
/**
|
29 |
-
* File Object
|
30 |
-
*/
|
31 |
-
//private $verifyFiles = array();
|
32 |
-
|
33 |
/**
|
34 |
* @var string
|
35 |
*/
|
25 |
*/
|
26 |
private $maxFilesPerRun;
|
27 |
|
|
|
|
|
|
|
|
|
|
|
28 |
/**
|
29 |
* @var string
|
30 |
*/
|
apps/Backend/Modules/Jobs/Scan.php
CHANGED
@@ -358,9 +358,10 @@ class Scan extends Job
|
|
358 |
protected function handleDirectory($path)
|
359 |
{
|
360 |
$directoryArray = explode(DIRECTORY_SEPARATOR, $path);
|
361 |
-
$total = count($directoryArray);
|
362 |
|
363 |
-
|
|
|
364 |
{
|
365 |
return;
|
366 |
}
|
358 |
protected function handleDirectory($path)
|
359 |
{
|
360 |
$directoryArray = explode(DIRECTORY_SEPARATOR, $path);
|
361 |
+
$total = is_array($directoryArray) || $directoryArray instanceof Countable ? count($directoryArray) : 0;
|
362 |
|
363 |
+
|
364 |
+
if ($total < 1)
|
365 |
{
|
366 |
return;
|
367 |
}
|
apps/Backend/Modules/Jobs/SearchReplace.php
CHANGED
@@ -9,6 +9,7 @@ if( !defined( "WPINC" ) ) {
|
|
9 |
|
10 |
use WPStaging\WPStaging;
|
11 |
use WPStaging\Utils\Strings;
|
|
|
12 |
|
13 |
/**
|
14 |
* Class Database
|
@@ -26,6 +27,14 @@ class SearchReplace extends JobExecutable {
|
|
26 |
*/
|
27 |
public $db;
|
28 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
29 |
/**
|
30 |
* The prefix of the new database tables which are used for the live site after updating tables
|
31 |
* @var string
|
@@ -40,7 +49,8 @@ class SearchReplace extends JobExecutable {
|
|
40 |
$this->db = WPStaging::getInstance()->get( "wpdb" );
|
41 |
//$this->tmpPrefix = 'wpstgtmp_';
|
42 |
$this->tmpPrefix = $this->options->prefix;
|
43 |
-
|
|
|
44 |
}
|
45 |
|
46 |
public function start() {
|
@@ -159,7 +169,7 @@ class SearchReplace extends JobExecutable {
|
|
159 |
private function startReplace( $new ) {
|
160 |
$rows = $this->options->job->start + $this->settings->queryLimit;
|
161 |
$this->log(
|
162 |
-
|
163 |
);
|
164 |
|
165 |
// Search & Replace
|
@@ -174,7 +184,7 @@ class SearchReplace extends JobExecutable {
|
|
174 |
* @access public
|
175 |
* @return int
|
176 |
*/
|
177 |
-
|
178 |
$table = esc_sql( $table );
|
179 |
$rows = $this->db->get_var( "SELECT COUNT(*) FROM $table" );
|
180 |
$pages = ceil( $rows / $this->settings->queryLimit );
|
@@ -187,7 +197,7 @@ class SearchReplace extends JobExecutable {
|
|
187 |
* @param string $table The table to check.
|
188 |
* @return array
|
189 |
*/
|
190 |
-
|
191 |
$primary_key = null;
|
192 |
$columns = array();
|
193 |
$fields = $this->db->get_results( 'DESCRIBE ' . $table );
|
@@ -218,45 +228,46 @@ class SearchReplace extends JobExecutable {
|
|
218 |
*/
|
219 |
private function searchReplace( $table, $page, $args ) {
|
220 |
|
|
|
221 |
// Load up the default settings for this chunk.
|
222 |
$table = esc_sql( $table );
|
223 |
$current_page = $this->options->job->start + $this->settings->queryLimit;
|
224 |
$pages = $this->get_pages_in_table( $table );
|
225 |
-
|
226 |
|
227 |
|
228 |
if( $this->isSubDir() ) {
|
229 |
-
//$homeUrl = rtrim(
|
230 |
// Search URL example.com/staging and root path to staging site /var/www/htdocs/staging
|
231 |
$args['search_for'] = array(
|
232 |
-
rtrim(
|
233 |
ABSPATH
|
234 |
);
|
235 |
|
236 |
$args['replace_with'] = array(
|
237 |
-
rtrim(
|
238 |
rtrim( ABSPATH, '/' ) . '/' . $this->options->cloneDirectoryName
|
239 |
);
|
240 |
} else {
|
241 |
$args['search_for'] = array(
|
242 |
-
rtrim(
|
243 |
ABSPATH
|
244 |
);
|
245 |
$args['replace_with'] = array(
|
246 |
-
|
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 |
-
//
|
254 |
// ABSPATH
|
255 |
// );
|
256 |
//
|
257 |
//
|
258 |
// $args['replace_with'] = array(
|
259 |
-
// rtrim(
|
260 |
// rtrim( ABSPATH, '/' ) . '/' . $this->options->cloneDirectoryName
|
261 |
// );
|
262 |
$args['replace_guids'] = 'off';
|
@@ -267,9 +278,6 @@ class SearchReplace extends JobExecutable {
|
|
267 |
// Get a list of columns in this table.
|
268 |
list( $primary_key, $columns ) = $this->get_columns( $table );
|
269 |
|
270 |
-
$this->log( "DB Processing: Table {$table}" );
|
271 |
-
|
272 |
-
|
273 |
// Bail out early if there isn't a primary key.
|
274 |
if( null === $primary_key ) {
|
275 |
return false;
|
@@ -287,7 +295,7 @@ class SearchReplace extends JobExecutable {
|
|
287 |
$current_row++;
|
288 |
$update_sql = array();
|
289 |
$where_sql = array();
|
290 |
-
$
|
291 |
|
292 |
foreach ( $columns as $column ) {
|
293 |
|
@@ -329,39 +337,36 @@ class SearchReplace extends JobExecutable {
|
|
329 |
$i = 0;
|
330 |
foreach ( $args['search_for'] as $replace ) {
|
331 |
$dataRow = $this->recursive_unserialize_replace( $args['search_for'][$i], $args['replace_with'][$i], $dataRow, false, $args['case_insensitive'] );
|
332 |
-
// Do not uncomment line below! Will lead to memory issues and timeouts
|
333 |
-
//$this->debugLog('DB Processing: '.$table.' - Replace ' . $args['search_for'][$i] . ' with ' . $args['replace_with'][$i]);
|
334 |
$i++;
|
335 |
}
|
336 |
-
unset
|
337 |
-
unset
|
338 |
|
339 |
// Something was changed
|
340 |
if( $row[$column] != $dataRow ) {
|
341 |
$update_sql[] = $column . ' = "' . $this->mysql_escape_mimic( $dataRow ) . '"';
|
342 |
-
$
|
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( $
|
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
|
360 |
-
unset
|
361 |
|
362 |
-
if( $current_page >= $pages - 1 ) {
|
363 |
-
$done = true;
|
364 |
-
}
|
365 |
|
366 |
// DB Flush
|
367 |
$this->db->flush();
|
@@ -401,8 +406,7 @@ class SearchReplace extends JobExecutable {
|
|
401 |
}
|
402 |
|
403 |
// Submitted by Tina Matter
|
404 |
-
elseif(
|
405 |
-
// $data_class = get_class( $data );
|
406 |
$_tmp = $data; // new $data_class( );
|
407 |
$props = get_object_vars( $data );
|
408 |
foreach ( $props as $key => $value ) {
|
@@ -432,6 +436,33 @@ class SearchReplace extends JobExecutable {
|
|
432 |
return $data;
|
433 |
}
|
434 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
435 |
/**
|
436 |
* Mimics the mysql_real_escape_string function. Adapted from a post by 'feedr' on php.net.
|
437 |
* @link http://php.net/manual/en/function.mysql-real-escape-string.php#101248
|
@@ -439,7 +470,7 @@ class SearchReplace extends JobExecutable {
|
|
439 |
* @param string $input The string to escape.
|
440 |
* @return string
|
441 |
*/
|
442 |
-
|
443 |
if( is_array( $input ) ) {
|
444 |
return array_map( __METHOD__, $input );
|
445 |
}
|
@@ -458,7 +489,7 @@ class SearchReplace extends JobExecutable {
|
|
458 |
*
|
459 |
* @return mixed, false on failure
|
460 |
*/
|
461 |
-
|
462 |
if( !is_serialized( $serialized_string ) ) {
|
463 |
return false;
|
464 |
}
|
@@ -479,7 +510,7 @@ class SearchReplace extends JobExecutable {
|
|
479 |
*
|
480 |
* @return string
|
481 |
*/
|
482 |
-
|
483 |
if( 'on' === $case_insensitive ) {
|
484 |
$data = str_ireplace( $from, $to, $data );
|
485 |
} else {
|
@@ -588,16 +619,16 @@ class SearchReplace extends JobExecutable {
|
|
588 |
* Get the install sub directory if WP is installed in sub directory
|
589 |
* @return string
|
590 |
*/
|
591 |
-
|
592 |
-
|
593 |
-
|
594 |
|
595 |
-
|
596 |
return '/';
|
597 |
}
|
598 |
|
599 |
-
|
600 |
-
|
601 |
}
|
602 |
|
603 |
}
|
9 |
|
10 |
use WPStaging\WPStaging;
|
11 |
use WPStaging\Utils\Strings;
|
12 |
+
use WPStaging\Utils\Helper;
|
13 |
|
14 |
/**
|
15 |
* Class Database
|
27 |
*/
|
28 |
public $db;
|
29 |
|
30 |
+
|
31 |
+
/**
|
32 |
+
*
|
33 |
+
* @var string
|
34 |
+
*/
|
35 |
+
private $homeUrl;
|
36 |
+
|
37 |
+
|
38 |
/**
|
39 |
* The prefix of the new database tables which are used for the live site after updating tables
|
40 |
* @var string
|
49 |
$this->db = WPStaging::getInstance()->get( "wpdb" );
|
50 |
//$this->tmpPrefix = 'wpstgtmp_';
|
51 |
$this->tmpPrefix = $this->options->prefix;
|
52 |
+
$helper = new Helper();
|
53 |
+
$this->homeUrl = $helper->get_home_url();
|
54 |
}
|
55 |
|
56 |
public function start() {
|
169 |
private function startReplace( $new ) {
|
170 |
$rows = $this->options->job->start + $this->settings->queryLimit;
|
171 |
$this->log(
|
172 |
+
"DB Processing: Table {$new} {$this->options->job->start} to {$rows} records"
|
173 |
);
|
174 |
|
175 |
// Search & Replace
|
184 |
* @access public
|
185 |
* @return int
|
186 |
*/
|
187 |
+
private function get_pages_in_table( $table ) {
|
188 |
$table = esc_sql( $table );
|
189 |
$rows = $this->db->get_var( "SELECT COUNT(*) FROM $table" );
|
190 |
$pages = ceil( $rows / $this->settings->queryLimit );
|
197 |
* @param string $table The table to check.
|
198 |
* @return array
|
199 |
*/
|
200 |
+
private function get_columns( $table ) {
|
201 |
$primary_key = null;
|
202 |
$columns = array();
|
203 |
$fields = $this->db->get_results( 'DESCRIBE ' . $table );
|
228 |
*/
|
229 |
private function searchReplace( $table, $page, $args ) {
|
230 |
|
231 |
+
|
232 |
// Load up the default settings for this chunk.
|
233 |
$table = esc_sql( $table );
|
234 |
$current_page = $this->options->job->start + $this->settings->queryLimit;
|
235 |
$pages = $this->get_pages_in_table( $table );
|
236 |
+
//$done = false;
|
237 |
|
238 |
|
239 |
if( $this->isSubDir() ) {
|
240 |
+
//$homeUrl = rtrim($this->homeUrl, "/") . $this->getSubDir() . $this->options->cloneDirectoryName;
|
241 |
// Search URL example.com/staging and root path to staging site /var/www/htdocs/staging
|
242 |
$args['search_for'] = array(
|
243 |
+
rtrim( $this->homeUrl, "/" ) . $this->getSubDir(),
|
244 |
ABSPATH
|
245 |
);
|
246 |
|
247 |
$args['replace_with'] = array(
|
248 |
+
rtrim( $this->homeUrl, "/" ) . $this->getSubDir() . '/' . $this->options->cloneDirectoryName,
|
249 |
rtrim( ABSPATH, '/' ) . '/' . $this->options->cloneDirectoryName
|
250 |
);
|
251 |
} else {
|
252 |
$args['search_for'] = array(
|
253 |
+
rtrim( $this->homeUrl, '/' ),
|
254 |
ABSPATH
|
255 |
);
|
256 |
$args['replace_with'] = array(
|
257 |
+
rtrim( $this->homeUrl, '/' ) . '/' . $this->options->cloneDirectoryName,
|
258 |
rtrim( ABSPATH, '/' ) . '/' . $this->options->cloneDirectoryName
|
259 |
);
|
260 |
}
|
261 |
|
262 |
// // Search URL example.com/staging and root path to staging site /var/www/htdocs/staging
|
263 |
// $args['search_for'] = array(
|
264 |
+
// $this->homeUrl,
|
265 |
// ABSPATH
|
266 |
// );
|
267 |
//
|
268 |
//
|
269 |
// $args['replace_with'] = array(
|
270 |
+
// rtrim( $this->homeUrl, '/' ) . '/' . $this->options->cloneDirectoryName,
|
271 |
// rtrim( ABSPATH, '/' ) . '/' . $this->options->cloneDirectoryName
|
272 |
// );
|
273 |
$args['replace_guids'] = 'off';
|
278 |
// Get a list of columns in this table.
|
279 |
list( $primary_key, $columns ) = $this->get_columns( $table );
|
280 |
|
|
|
|
|
|
|
281 |
// Bail out early if there isn't a primary key.
|
282 |
if( null === $primary_key ) {
|
283 |
return false;
|
295 |
$current_row++;
|
296 |
$update_sql = array();
|
297 |
$where_sql = array();
|
298 |
+
$upd = false;
|
299 |
|
300 |
foreach ( $columns as $column ) {
|
301 |
|
337 |
$i = 0;
|
338 |
foreach ( $args['search_for'] as $replace ) {
|
339 |
$dataRow = $this->recursive_unserialize_replace( $args['search_for'][$i], $args['replace_with'][$i], $dataRow, false, $args['case_insensitive'] );
|
|
|
|
|
340 |
$i++;
|
341 |
}
|
342 |
+
unset( $replace );
|
343 |
+
unset( $i );
|
344 |
|
345 |
// Something was changed
|
346 |
if( $row[$column] != $dataRow ) {
|
347 |
$update_sql[] = $column . ' = "' . $this->mysql_escape_mimic( $dataRow ) . '"';
|
348 |
+
$upd = true;
|
|
|
349 |
}
|
350 |
}
|
351 |
|
352 |
// Determine what to do with updates.
|
353 |
if( $args['dry_run'] === 'on' ) {
|
354 |
// Don't do anything if a dry run
|
355 |
+
} elseif( $upd && !empty( $where_sql ) ) {
|
356 |
// If there are changes to make, run the query.
|
357 |
$sql = 'UPDATE ' . $table . ' SET ' . implode( ', ', $update_sql ) . ' WHERE ' . implode( ' AND ', array_filter( $where_sql ) );
|
358 |
$result = $this->db->query( $sql );
|
359 |
|
360 |
if( !$result ) {
|
361 |
+
$this->log( "Error updating row {$current_row}", \WPStaging\Utils\Logger::TYPE_ERROR );
|
362 |
}
|
363 |
}
|
364 |
} // end row loop
|
365 |
+
unset( $row );
|
366 |
|
367 |
+
// if( $current_page >= $pages - 1 ) {
|
368 |
+
// $done = true;
|
369 |
+
// }
|
370 |
|
371 |
// DB Flush
|
372 |
$this->db->flush();
|
406 |
}
|
407 |
|
408 |
// Submitted by Tina Matter
|
409 |
+
elseif( $this->isValidObject($data) ) {
|
|
|
410 |
$_tmp = $data; // new $data_class( );
|
411 |
$props = get_object_vars( $data );
|
412 |
foreach ( $props as $key => $value ) {
|
436 |
return $data;
|
437 |
}
|
438 |
|
439 |
+
/**
|
440 |
+
* Check if the object is a valid one and not __PHP_Incomplete_Class_Name
|
441 |
+
* Can not use is_object alone because in php 7.2 it's returning true even though object is __PHP_Incomplete_Class_Name
|
442 |
+
* @return boolean
|
443 |
+
*/
|
444 |
+
private function isValidObject($data){
|
445 |
+
if( !is_object( $data ) || gettype( $data ) != 'object' ) {
|
446 |
+
return false;
|
447 |
+
}
|
448 |
+
|
449 |
+
$invalid_class_props = get_object_vars( $data );
|
450 |
+
|
451 |
+
if (!isset($invalid_class_props['__PHP_Incomplete_Class_Name'])){
|
452 |
+
// Assume it must be an valid object
|
453 |
+
return true;
|
454 |
+
}
|
455 |
+
|
456 |
+
$invalid_object_class = $invalid_class_props['__PHP_Incomplete_Class_Name'];
|
457 |
+
|
458 |
+
if( !empty( $invalid_object_class ) ) {
|
459 |
+
return false;
|
460 |
+
}
|
461 |
+
|
462 |
+
// Assume it must be an valid object
|
463 |
+
return true;
|
464 |
+
}
|
465 |
+
|
466 |
/**
|
467 |
* Mimics the mysql_real_escape_string function. Adapted from a post by 'feedr' on php.net.
|
468 |
* @link http://php.net/manual/en/function.mysql-real-escape-string.php#101248
|
470 |
* @param string $input The string to escape.
|
471 |
* @return string
|
472 |
*/
|
473 |
+
private function mysql_escape_mimic( $input ) {
|
474 |
if( is_array( $input ) ) {
|
475 |
return array_map( __METHOD__, $input );
|
476 |
}
|
489 |
*
|
490 |
* @return mixed, false on failure
|
491 |
*/
|
492 |
+
private static function unserialize( $serialized_string ) {
|
493 |
if( !is_serialized( $serialized_string ) ) {
|
494 |
return false;
|
495 |
}
|
510 |
*
|
511 |
* @return string
|
512 |
*/
|
513 |
+
private function str_replace( $from, $to, $data, $case_insensitive = false ) {
|
514 |
if( 'on' === $case_insensitive ) {
|
515 |
$data = str_ireplace( $from, $to, $data );
|
516 |
} else {
|
619 |
* Get the install sub directory if WP is installed in sub directory
|
620 |
* @return string
|
621 |
*/
|
622 |
+
private function getSubDir() {
|
623 |
+
$home = get_option( 'home' );
|
624 |
+
$siteurl = get_option( 'siteurl' );
|
625 |
|
626 |
+
if( empty( $home ) || empty( $siteurl ) ) {
|
627 |
return '/';
|
628 |
}
|
629 |
|
630 |
+
$dir = str_replace( $home, '', $siteurl );
|
631 |
+
return '/' . str_replace( '/', '', $dir );
|
632 |
}
|
633 |
|
634 |
}
|
apps/Backend/Modules/SystemInfo.php
CHANGED
@@ -5,6 +5,7 @@ namespace WPStaging\Backend\Modules;
|
|
5 |
use WPStaging\DI\InjectionAware;
|
6 |
use WPStaging\Library\Browser;
|
7 |
use WPStaging\WPStaging;
|
|
|
8 |
|
9 |
// No Direct Access
|
10 |
if (!defined("WPINC"))
|
@@ -25,11 +26,18 @@ class SystemInfo extends InjectionAware
|
|
25 |
private $isMultiSite;
|
26 |
|
27 |
/**
|
|
|
|
|
|
|
|
|
|
|
|
|
28 |
* Initialize class
|
29 |
*/
|
30 |
public function initialize()
|
31 |
{
|
32 |
$this->isMultiSite = is_multisite();
|
|
|
33 |
}
|
34 |
|
35 |
/**
|
@@ -112,14 +120,14 @@ class SystemInfo extends InjectionAware
|
|
112 |
* Site Information
|
113 |
* @return string
|
114 |
*/
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
|
124 |
return apply_filters("wpstg_sysinfo_after_site_info", $output);
|
125 |
}
|
5 |
use WPStaging\DI\InjectionAware;
|
6 |
use WPStaging\Library\Browser;
|
7 |
use WPStaging\WPStaging;
|
8 |
+
use WPStaging\Utils;
|
9 |
|
10 |
// No Direct Access
|
11 |
if (!defined("WPINC"))
|
26 |
private $isMultiSite;
|
27 |
|
28 |
/**
|
29 |
+
*
|
30 |
+
* @var obj
|
31 |
+
*/
|
32 |
+
private $helper;
|
33 |
+
|
34 |
+
/**
|
35 |
* Initialize class
|
36 |
*/
|
37 |
public function initialize()
|
38 |
{
|
39 |
$this->isMultiSite = is_multisite();
|
40 |
+
$this->helper = new Utils\Helper();
|
41 |
}
|
42 |
|
43 |
/**
|
120 |
* Site Information
|
121 |
* @return string
|
122 |
*/
|
123 |
+
public function site() {
|
124 |
+
$output = "-- Site Info" . PHP_EOL . PHP_EOL;
|
125 |
+
$output .= $this->info( "Site URL:", site_url() );
|
126 |
+
$output .= $this->info( "Home URL:", $this->helper->get_home_url() );
|
127 |
+
$output .= $this->info( "Home Path:", get_home_path() );
|
128 |
+
$output .= $this->info( "ABSPATH:", ABSPATH );
|
129 |
+
$output .= $this->info( "Installed in subdir:", ( $this->isSubDir() ? 'Yes' : 'No' ) );
|
130 |
+
$output .= $this->info( "Multisite:", ($this->isMultiSite ? "Yes" : "No" ) );
|
131 |
|
132 |
return apply_filters("wpstg_sysinfo_after_site_info", $output);
|
133 |
}
|
apps/Backend/Modules/Views/Forms/Settings.php
CHANGED
@@ -74,8 +74,7 @@ class Settings {
|
|
74 |
);
|
75 |
|
76 |
$this->form["general"]->add(
|
77 |
-
$element->setLabel( "File Copy Limit" )
|
78 |
-
->setDefault( isset( $settings->fileLimit ) ? $settings->fileLimit : 1 )
|
79 |
);
|
80 |
|
81 |
|
@@ -104,7 +103,7 @@ class Settings {
|
|
104 |
);
|
105 |
|
106 |
$this->form["general"]->add(
|
107 |
-
$element->setLabel( "CPU
|
108 |
->setDefault( isset( $settings->cpuLoad ) ? $settings->cpuLoad : "fast" )
|
109 |
);
|
110 |
|
74 |
);
|
75 |
|
76 |
$this->form["general"]->add(
|
77 |
+
$element->setLabel( "File Copy Limit" )->setDefault( isset( $settings->fileLimit ) ? $settings->fileLimit : 1 )
|
|
|
78 |
);
|
79 |
|
80 |
|
103 |
);
|
104 |
|
105 |
$this->form["general"]->add(
|
106 |
+
$element->setLabel( "CPU Load Priority" )
|
107 |
->setDefault( isset( $settings->cpuLoad ) ? $settings->cpuLoad : "fast" )
|
108 |
);
|
109 |
|
apps/Backend/Upgrade/Upgrade.php
CHANGED
@@ -4,14 +4,13 @@ namespace WPStaging\Backend\Upgrade;
|
|
4 |
|
5 |
use WPStaging\WPStaging;
|
6 |
use WPStaging\Utils\Logger;
|
7 |
-
|
8 |
|
9 |
/**
|
10 |
* Upgrade Class
|
11 |
* This must be loaded on every page init to ensure all settings are
|
12 |
* adjusted correctly and to run any upgrade process if necessary.
|
13 |
*/
|
14 |
-
|
15 |
// No Direct Access
|
16 |
if( !defined( "WPINC" ) ) {
|
17 |
die;
|
@@ -31,12 +30,6 @@ class Upgrade {
|
|
31 |
*/
|
32 |
private $clones;
|
33 |
|
34 |
-
/**
|
35 |
-
* Clone data
|
36 |
-
* @var obj
|
37 |
-
*/
|
38 |
-
//private $clonesBeta;
|
39 |
-
|
40 |
/**
|
41 |
* Cron data
|
42 |
* @var obj
|
@@ -55,7 +48,6 @@ class Upgrade {
|
|
55 |
*/
|
56 |
private $db;
|
57 |
|
58 |
-
|
59 |
public function __construct() {
|
60 |
|
61 |
// add wpstg_weekly_event to cron events
|
@@ -98,7 +90,7 @@ class Upgrade {
|
|
98 |
// Current options
|
99 |
$sites = get_option( "wpstg_existing_clones_beta", array() );
|
100 |
|
101 |
-
if
|
102 |
return;
|
103 |
}
|
104 |
|
@@ -118,8 +110,6 @@ class Upgrade {
|
|
118 |
}
|
119 |
}
|
120 |
|
121 |
-
|
122 |
-
|
123 |
/**
|
124 |
* Check and return prefix of the staging site
|
125 |
* @param string $directory
|
@@ -149,7 +139,6 @@ class Upgrade {
|
|
149 |
}
|
150 |
}
|
151 |
|
152 |
-
|
153 |
/**
|
154 |
* Upgrade method 2.0.3
|
155 |
*/
|
@@ -214,12 +203,10 @@ class Upgrade {
|
|
214 |
*/
|
215 |
private function upgradeClonesBeta() {
|
216 |
|
217 |
-
// Get options
|
218 |
-
$this->clones = get_option( "wpstg_existing_clones", array() );
|
219 |
|
220 |
-
|
221 |
|
222 |
-
|
223 |
return false;
|
224 |
}
|
225 |
|
@@ -233,11 +220,11 @@ class Upgrade {
|
|
233 |
|
234 |
$new[$value]['directoryName'] = $value;
|
235 |
$new[$value]['path'] = get_home_path() . $value;
|
236 |
-
$
|
|
|
237 |
$new[$value]['number'] = $key + 1;
|
238 |
$new[$value]['version'] = $this->previousVersion;
|
239 |
-
|
240 |
-
|
241 |
}
|
242 |
unset( $value );
|
243 |
|
@@ -246,40 +233,6 @@ class Upgrade {
|
|
246 |
}
|
247 |
}
|
248 |
|
249 |
-
/**
|
250 |
-
* Convert clone data from wpstg 1.x to wpstg 2.x
|
251 |
-
* Only use this later when wpstg 2.x is ready for production
|
252 |
-
*/
|
253 |
-
// private function upgradeClones() {
|
254 |
-
//
|
255 |
-
// $new = array();
|
256 |
-
//
|
257 |
-
// // Get options
|
258 |
-
// $this->clones = get_option( "wpstg_existing_clones", array() );
|
259 |
-
//
|
260 |
-
// if( empty( $this->clones ) ) {
|
261 |
-
// return false;
|
262 |
-
// }
|
263 |
-
//
|
264 |
-
// foreach ( $this->clones as $key => &$value ) {
|
265 |
-
//
|
266 |
-
// // Skip the rest of the loop if data is already compatible to wpstg 2.0.1
|
267 |
-
// if( isset( $value['directoryName'] ) || !empty( $value['directoryName'] ) ) {
|
268 |
-
// continue;
|
269 |
-
// }
|
270 |
-
// $new[$value]['directoryName'] = $value;
|
271 |
-
// $new[$value]['path'] = get_home_path() . $value;
|
272 |
-
// $new[$value]['url'] = get_home_url() . "/" . $value;
|
273 |
-
// $new[$value]['number'] = $key + 1;
|
274 |
-
// $new[$value]['version'] = $this->previousVersion;
|
275 |
-
// }
|
276 |
-
// unset( $value );
|
277 |
-
//
|
278 |
-
// if( empty( $new ) || false === update_option( 'wpstg_existing_clones', $new ) ) {
|
279 |
-
// $this->logger->log( 'Failed to upgrade clone data from ' . $this->previousVersion . ' to ' . \WPStaging\WPStaging::VERSION );
|
280 |
-
// }
|
281 |
-
// }
|
282 |
-
|
283 |
/**
|
284 |
* Upgrade Notices db options from wpstg 1.3 -> 2.0.1
|
285 |
* Fix some logical db options
|
4 |
|
5 |
use WPStaging\WPStaging;
|
6 |
use WPStaging\Utils\Logger;
|
7 |
+
use WPStaging\Utils\Helper;
|
8 |
|
9 |
/**
|
10 |
* Upgrade Class
|
11 |
* This must be loaded on every page init to ensure all settings are
|
12 |
* adjusted correctly and to run any upgrade process if necessary.
|
13 |
*/
|
|
|
14 |
// No Direct Access
|
15 |
if( !defined( "WPINC" ) ) {
|
16 |
die;
|
30 |
*/
|
31 |
private $clones;
|
32 |
|
|
|
|
|
|
|
|
|
|
|
|
|
33 |
/**
|
34 |
* Cron data
|
35 |
* @var obj
|
48 |
*/
|
49 |
private $db;
|
50 |
|
|
|
51 |
public function __construct() {
|
52 |
|
53 |
// add wpstg_weekly_event to cron events
|
90 |
// Current options
|
91 |
$sites = get_option( "wpstg_existing_clones_beta", array() );
|
92 |
|
93 |
+
if( false === $sites || count($sites) === 0 ) {
|
94 |
return;
|
95 |
}
|
96 |
|
110 |
}
|
111 |
}
|
112 |
|
|
|
|
|
113 |
/**
|
114 |
* Check and return prefix of the staging site
|
115 |
* @param string $directory
|
139 |
}
|
140 |
}
|
141 |
|
|
|
142 |
/**
|
143 |
* Upgrade method 2.0.3
|
144 |
*/
|
203 |
*/
|
204 |
private function upgradeClonesBeta() {
|
205 |
|
|
|
|
|
206 |
|
207 |
+
$new = array();
|
208 |
|
209 |
+
if( empty( $this->clones ) || count( $this->clones ) === 0 ) {
|
210 |
return false;
|
211 |
}
|
212 |
|
220 |
|
221 |
$new[$value]['directoryName'] = $value;
|
222 |
$new[$value]['path'] = get_home_path() . $value;
|
223 |
+
$helper = new Helper();
|
224 |
+
$new[$value]['url'] = $helper->get_home_url() . "/" . $value;
|
225 |
$new[$value]['number'] = $key + 1;
|
226 |
$new[$value]['version'] = $this->previousVersion;
|
227 |
+
//$new[$value]['prefix'] = $value;
|
|
|
228 |
}
|
229 |
unset( $value );
|
230 |
|
233 |
}
|
234 |
}
|
235 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
236 |
/**
|
237 |
* Upgrade Notices db options from wpstg 1.3 -> 2.0.1
|
238 |
* Fix some logical db options
|
apps/Backend/views/_includes/header.php
CHANGED
@@ -32,6 +32,6 @@
|
|
32 |
</div>
|
33 |
<div style="font-size:14px;">
|
34 |
Tutorial: <a href="https://wp-staging.com/docs/copy-staging-site-to-live-site/" target="_blank">Learn how to push changes to live website</a>
|
35 |
-
<span style="float:right;"><a href="https://wordpress.org/support/plugin/wp-staging/reviews/?filter=5" target="_blank" rel="external noopener">Rate
|
36 |
</div>
|
37 |
</div>
|
32 |
</div>
|
33 |
<div style="font-size:14px;">
|
34 |
Tutorial: <a href="https://wp-staging.com/docs/copy-staging-site-to-live-site/" target="_blank">Learn how to push changes to live website</a>
|
35 |
+
<span style="float:right;"><a href="https://wordpress.org/support/plugin/wp-staging/reviews/?filter=5" target="_blank" rel="external noopener">Rate it ★★★</a></span>
|
36 |
</div>
|
37 |
</div>
|
apps/Backend/views/clone/includes/footer.php
CHANGED
@@ -1,3 +1,4 @@
|
|
|
|
1 |
<div id="wpstg-error-wrapper">
|
2 |
<div id="wpstg-error-details"></div>
|
3 |
</div>
|
1 |
+
<div style="clear:both;">Something not working? Open a <a href="https://wp-staging.com/support" target="_blank" rel="external nofollow"> support ticket</a> and we help you fixing it quickly.</div>
|
2 |
<div id="wpstg-error-wrapper">
|
3 |
<div id="wpstg-error-details"></div>
|
4 |
</div>
|
apps/Backend/views/settings/index.php
CHANGED
@@ -167,29 +167,6 @@
|
|
167 |
<?php echo $form->render( "wpstg_settings[cpuLoad]" ) ?>
|
168 |
</td>
|
169 |
</tr>
|
170 |
-
<!-- Deactivated -->
|
171 |
-
<tr class="row" style="display:none;">
|
172 |
-
<td class="row th">
|
173 |
-
<div class="col-title">
|
174 |
-
<?php echo $form->label( "wpstg_settings[optimizer]" ) ?>
|
175 |
-
<span class="description">
|
176 |
-
Select the plugins that should be disabled during build process of the staging site.
|
177 |
-
Some plugins slow down the copy process and add overhead to each request, requiring extra CPU and memory consumption.
|
178 |
-
Some of them can interfere with cloning process and cause them to fail, so we recommend to select all plugins here.
|
179 |
-
|
180 |
-
<br><br>
|
181 |
-
<strong>Note:</strong> This does not disable plugins on your staging site. You have to disable them there separately.
|
182 |
-
</span>
|
183 |
-
</div>
|
184 |
-
</td>
|
185 |
-
<td>
|
186 |
-
<?php echo $form->render( "wpstg_settings[optimizer]" ) ?>
|
187 |
-
<div id="wpstg_pluginListing" style="display:none">
|
188 |
-
<?php echo $form->render( "wpstg_settings[blackListedPlugins][]" ) ?>
|
189 |
-
</div>
|
190 |
-
</td>
|
191 |
-
</tr>
|
192 |
-
|
193 |
<tr class="row">
|
194 |
<td class="row th">
|
195 |
<div class="col-title">
|
167 |
<?php echo $form->render( "wpstg_settings[cpuLoad]" ) ?>
|
168 |
</td>
|
169 |
</tr>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
170 |
<tr class="row">
|
171 |
<td class="row th">
|
172 |
<div class="col-title">
|
apps/Core/DTO/Settings.php
CHANGED
@@ -63,11 +63,13 @@ class Settings {
|
|
63 |
*/
|
64 |
protected $debugMode;
|
65 |
|
|
|
66 |
/**
|
67 |
* @var array
|
68 |
*/
|
69 |
protected $blackListedPlugins = array();
|
70 |
|
|
|
71 |
/**
|
72 |
* Settings constructor.
|
73 |
*/
|
@@ -98,19 +100,19 @@ class Settings {
|
|
98 |
/**
|
99 |
* @return bool
|
100 |
*/
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
|
115 |
/**
|
116 |
* @return array
|
63 |
*/
|
64 |
protected $debugMode;
|
65 |
|
66 |
+
|
67 |
/**
|
68 |
* @var array
|
69 |
*/
|
70 |
protected $blackListedPlugins = array();
|
71 |
|
72 |
+
|
73 |
/**
|
74 |
* Settings constructor.
|
75 |
*/
|
100 |
/**
|
101 |
* @return bool
|
102 |
*/
|
103 |
+
public function save() {
|
104 |
+
$data = array();
|
105 |
+
|
106 |
+
foreach ( get_object_vars( $this ) as $key => $value ) {
|
107 |
+
if( 0 == strpos( $key, '_' ) ) {
|
108 |
+
continue;
|
109 |
+
}
|
110 |
+
|
111 |
+
$data[$key] = $value;
|
112 |
+
}
|
113 |
+
|
114 |
+
return update_option( "wpstg_settings", $data );
|
115 |
+
}
|
116 |
|
117 |
/**
|
118 |
* @return array
|
apps/Core/Utils/Helper.php
ADDED
@@ -0,0 +1,71 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPStaging\Utils;
|
4 |
+
|
5 |
+
// No Direct Access
|
6 |
+
if (!defined("WPINC"))
|
7 |
+
{
|
8 |
+
die;
|
9 |
+
}
|
10 |
+
|
11 |
+
class Helper {
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Retrieves the URL for a given site where the front end is accessible.
|
15 |
+
* This is from WordPress source 4.9.5/src/wp-includes/link-template.php
|
16 |
+
* home_url filter has been removed here to make sure that wpml can not overwrite that value!
|
17 |
+
*
|
18 |
+
* Returns the 'home' option with the appropriate protocol. The protocol will be 'https'
|
19 |
+
* if is_ssl() evaluates to true; otherwise, it will be the same as the 'home' option.
|
20 |
+
* If `$scheme` is 'http' or 'https', is_ssl() is overridden.
|
21 |
+
*
|
22 |
+
* @since 3.0.0
|
23 |
+
*
|
24 |
+
* @global string $pagenow
|
25 |
+
*
|
26 |
+
* @param int $blog_id Optional. Site ID. Default null (current site).
|
27 |
+
* @param string $path Optional. Path relative to the home URL. Default empty.
|
28 |
+
* @param string|null $scheme Optional. Scheme to give the home URL context. Accepts
|
29 |
+
* 'http', 'https', 'relative', 'rest', or null. Default null.
|
30 |
+
* @return string Home URL link with optional path appended.
|
31 |
+
*/
|
32 |
+
public function get_home_url( $blog_id = null, $path = '', $scheme = null ) {
|
33 |
+
global $pagenow;
|
34 |
+
|
35 |
+
$orig_scheme = $scheme;
|
36 |
+
|
37 |
+
if( empty( $blog_id ) || !is_multisite() ) {
|
38 |
+
$url = get_option( 'home' );
|
39 |
+
} else {
|
40 |
+
switch_to_blog( $blog_id );
|
41 |
+
$url = get_option( 'home' );
|
42 |
+
restore_current_blog();
|
43 |
+
}
|
44 |
+
|
45 |
+
if( !in_array( $scheme, array('http', 'https', 'relative') ) ) {
|
46 |
+
if( is_ssl() && !is_admin() && 'wp-login.php' !== $pagenow )
|
47 |
+
$scheme = 'https';
|
48 |
+
else
|
49 |
+
$scheme = parse_url( $url, PHP_URL_SCHEME );
|
50 |
+
}
|
51 |
+
|
52 |
+
$url = set_url_scheme( $url, $scheme );
|
53 |
+
|
54 |
+
if( $path && is_string( $path ) )
|
55 |
+
$url .= '/' . ltrim( $path, '/' );
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Filters the home URL.
|
59 |
+
*
|
60 |
+
* @since 3.0.0
|
61 |
+
*
|
62 |
+
* @param string $url The complete home URL including scheme and path.
|
63 |
+
* @param string $path Path relative to the home URL. Blank string if no path is specified.
|
64 |
+
* @param string|null $orig_scheme Scheme to give the home URL context. Accepts 'http', 'https',
|
65 |
+
* 'relative', 'rest', or null.
|
66 |
+
* @param int|null $blog_id Site ID, or null for the current site.
|
67 |
+
*/
|
68 |
+
return $url;
|
69 |
+
}
|
70 |
+
|
71 |
+
}
|
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
|
29 |
/**
|
30 |
* Plugin version
|
31 |
*/
|
32 |
+
const VERSION = "2.2.6";
|
33 |
|
34 |
/**
|
35 |
* Plugin name
|
readme.txt
CHANGED
@@ -9,7 +9,7 @@ License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
|
9 |
Tags: staging, duplication, cloning, clone, migration, sandbox, test site, testing, backup, post, admin, administration, duplicate posts
|
10 |
Requires at least: 3.6+
|
11 |
Tested up to: 4.9
|
12 |
-
Stable tag: 2.2.
|
13 |
Requires PHP: 5.3
|
14 |
|
15 |
A duplicator plugin! Clone, duplicate and migrate live sites to independent staging and development sites that are available only to administrators.
|
@@ -146,6 +146,17 @@ https://wp-staging.com
|
|
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
|
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.6
|
13 |
Requires PHP: 5.3
|
14 |
|
15 |
A duplicator plugin! Clone, duplicate and migrate live sites to independent staging and development sites that are available only to administrators.
|
146 |
|
147 |
== Changelog ==
|
148 |
|
149 |
+
= 2.2.6 =
|
150 |
+
* Fix: If WPML is used the live site is not reachable
|
151 |
+
* Fix: Can not disable optimizer
|
152 |
+
* Fix: Stop cloning if wp_usermeta or wp_options can not be adapted
|
153 |
+
* Fix: All methods should be private in class SearchReplace
|
154 |
+
* Fix: PHP 7.2 is not countable warning
|
155 |
+
* Fix: PHP 7.2 can not replace data in objects when object is incomplete (__PHP_Incomplete_Class_Name)
|
156 |
+
* 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
|
157 |
+
* New: Link to support section
|
158 |
+
|
159 |
+
|
160 |
= 2.2.5 =
|
161 |
* New: Compatible to WP 4.9.5
|
162 |
* New: Allow to select and copy extra folders that are on the root level
|
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.6
|
11 |
* Text Domain: wpstg
|
12 |
* Domain Path: /languages/
|
13 |
|