Version Description
- fix: https://github.com/watchfulli/XCloner-Wordpress/issues/227
- fix: https://github.com/watchfulli/XCloner-Wordpress/issues/231
Download this release
Release Info
Developer | watchful |
Plugin | XCloner – Backup and Restore |
Version | 4.4.2 |
Comparing to | |
See all releases |
Code changes from version 4.4.1 to 4.4.2
- README.txt +6 -1
- admin/partials/remote_storage/backblaze.php +16 -0
- lib/Xcloner.php +2 -2
- lib/Xcloner_Api.php +2 -9
- lib/Xcloner_Remote_Storage.php +9 -1
- lib/Xcloner_Scheduler.php +62 -113
- vendor/autoload.php +1 -1
- vendor/composer/autoload_real.php +7 -7
- vendor/composer/autoload_static.php +5 -5
- vendor/composer/installed.php +6 -6
- xcloner.php +6 -6
README.txt
CHANGED
@@ -5,7 +5,7 @@ Tags: backup, database backup, cloud backup, WordPress backup, WordPress migrati
|
|
5 |
Requires at least: 5.1
|
6 |
Requires PHP: 7.3
|
7 |
Tested up to: 6.0
|
8 |
-
Stable tag: 4.4.
|
9 |
|
10 |
|
11 |
XCloner is a backup plugin that allows you to safely back up and restore your WordPress sites. You can send site backups to SFTP, Dropbox, Amazon, Google Drive, Backblaze and other locations.
|
@@ -117,6 +117,11 @@ Of course, schedules can be adjusted accordingly to how often you update your si
|
|
117 |
|
118 |
== Changelog ==
|
119 |
|
|
|
|
|
|
|
|
|
|
|
120 |
= 4.4.1 =
|
121 |
* minor code review
|
122 |
|
5 |
Requires at least: 5.1
|
6 |
Requires PHP: 7.3
|
7 |
Tested up to: 6.0
|
8 |
+
Stable tag: 4.4.2
|
9 |
|
10 |
|
11 |
XCloner is a backup plugin that allows you to safely back up and restore your WordPress sites. You can send site backups to SFTP, Dropbox, Amazon, Google Drive, Backblaze and other locations.
|
117 |
|
118 |
== Changelog ==
|
119 |
|
120 |
+
= 4.4.2 =
|
121 |
+
* fix: https://github.com/watchfulli/XCloner-Wordpress/issues/227
|
122 |
+
* fix: https://github.com/watchfulli/XCloner-Wordpress/issues/231
|
123 |
+
|
124 |
+
|
125 |
= 4.4.1 =
|
126 |
* minor code review
|
127 |
|
admin/partials/remote_storage/backblaze.php
CHANGED
@@ -28,6 +28,10 @@ if (!defined('WPINC')) {
|
|
28 |
<p>
|
29 |
<?php echo sprintf(__('Visit %s and get your KeyID and applicationKey.', 'xcloner-backup-and-restore'), '<a href="https://secure.backblaze.com/b2_buckets.htm" target="_blank">https://secure.backblaze.com/b2_buckets.htm</a>') ?>
|
30 |
</p>
|
|
|
|
|
|
|
|
|
31 |
</div>
|
32 |
</div>
|
33 |
|
@@ -69,6 +73,18 @@ if (!defined('WPINC')) {
|
|
69 |
</div>
|
70 |
</div>
|
71 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
72 |
<?php echo common_cleanup_html('backblaze')?>
|
73 |
|
74 |
<div class="row">
|
28 |
<p>
|
29 |
<?php echo sprintf(__('Visit %s and get your KeyID and applicationKey.', 'xcloner-backup-and-restore'), '<a href="https://secure.backblaze.com/b2_buckets.htm" target="_blank">https://secure.backblaze.com/b2_buckets.htm</a>') ?>
|
30 |
</p>
|
31 |
+
<p>
|
32 |
+
If you specify <strong>only the bucket name</strong>, you must use the <strong>master key</strong>.<br>
|
33 |
+
However, if you specify <strong>both bucket name and bucket id</strong>, you do not need the master key and can use a <strong>single-bucket key</strong>.
|
34 |
+
</p>
|
35 |
</div>
|
36 |
</div>
|
37 |
|
73 |
</div>
|
74 |
</div>
|
75 |
|
76 |
+
<div class="row">
|
77 |
+
<div class="col s12 m3 label">
|
78 |
+
<label
|
79 |
+
for="backblaze_bucket_id"><?php echo __("Backblaze Bucket ID", 'xcloner-backup-and-restore') ?></label>
|
80 |
+
</div>
|
81 |
+
<div class=" col s12 m6">
|
82 |
+
<input placeholder="<?php echo __("Backblaze Bucket ID", 'xcloner-backup-and-restore') ?>"
|
83 |
+
id="backblaze_bucket_id" type="text" name="xcloner_backblaze_bucket_id" class="validate"
|
84 |
+
value="<?php echo esc_attr(get_option("xcloner_backblaze_bucket_id")) ?>" autocomplete="off">
|
85 |
+
</div>
|
86 |
+
</div>
|
87 |
+
|
88 |
<?php echo common_cleanup_html('backblaze')?>
|
89 |
|
90 |
<div class="row">
|
lib/Xcloner.php
CHANGED
@@ -755,7 +755,7 @@ class Xcloner
|
|
755 |
}
|
756 |
|
757 |
/**
|
758 |
-
* Run the loader to execute all
|
759 |
*
|
760 |
* @since 1.0.0
|
761 |
*/
|
@@ -800,7 +800,7 @@ class Xcloner
|
|
800 |
$data['id'] = $profile_id;
|
801 |
}
|
802 |
|
803 |
-
$this->xcloner_scheduler->xcloner_scheduler_callback($data['id'], $data
|
804 |
}
|
805 |
|
806 |
/**
|
755 |
}
|
756 |
|
757 |
/**
|
758 |
+
* Run the loader to execute all the hooks with WordPress.
|
759 |
*
|
760 |
* @since 1.0.0
|
761 |
*/
|
800 |
$data['id'] = $profile_id;
|
801 |
}
|
802 |
|
803 |
+
$this->xcloner_scheduler->xcloner_scheduler_callback($data['id'], $data);
|
804 |
}
|
805 |
|
806 |
/**
|
lib/Xcloner_Api.php
CHANGED
@@ -646,10 +646,8 @@ class Xcloner_Api
|
|
646 |
$this->send_response($data, 0);
|
647 |
}
|
648 |
|
649 |
-
|
650 |
-
*
|
651 |
-
* Get schedule by id API
|
652 |
-
*
|
653 |
*/
|
654 |
public function get_schedule_by_id()
|
655 |
{
|
@@ -670,11 +668,6 @@ class Xcloner_Api
|
|
670 |
$this->send_response($data);
|
671 |
}
|
672 |
|
673 |
-
/*
|
674 |
-
*
|
675 |
-
* Get Schedule list API
|
676 |
-
*
|
677 |
-
*/
|
678 |
public function get_scheduler_list()
|
679 |
{
|
680 |
$return = array();
|
646 |
$this->send_response($data, 0);
|
647 |
}
|
648 |
|
649 |
+
/**
|
650 |
+
* @throws Exception
|
|
|
|
|
651 |
*/
|
652 |
public function get_schedule_by_id()
|
653 |
{
|
668 |
$this->send_response($data);
|
669 |
}
|
670 |
|
|
|
|
|
|
|
|
|
|
|
671 |
public function get_scheduler_list()
|
672 |
{
|
673 |
$return = array();
|
lib/Xcloner_Remote_Storage.php
CHANGED
@@ -163,6 +163,7 @@ class Xcloner_Remote_Storage
|
|
163 |
"backblaze_account_id" => "string",
|
164 |
"backblaze_application_key" => "raw",
|
165 |
"backblaze_bucket_name" => "string",
|
|
|
166 |
"backblaze_cleanup_retention_limit_days" => "float",
|
167 |
"backblaze_cleanup_exclude_days" => "string",
|
168 |
"backblaze_cleanup_retention_limit_archives" => "int",
|
@@ -671,7 +672,14 @@ class Xcloner_Remote_Storage
|
|
671 |
$this->xcloner_settings->get_xcloner_option("xcloner_backblaze_account_id"),
|
672 |
$this->xcloner_settings->get_xcloner_option("xcloner_backblaze_application_key")
|
673 |
);
|
674 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
675 |
|
676 |
$filesystem = new Filesystem($adapter, new Config([
|
677 |
'disable_asserts' => true,
|
163 |
"backblaze_account_id" => "string",
|
164 |
"backblaze_application_key" => "raw",
|
165 |
"backblaze_bucket_name" => "string",
|
166 |
+
"backblaze_bucket_id" => "string",
|
167 |
"backblaze_cleanup_retention_limit_days" => "float",
|
168 |
"backblaze_cleanup_exclude_days" => "string",
|
169 |
"backblaze_cleanup_retention_limit_archives" => "int",
|
672 |
$this->xcloner_settings->get_xcloner_option("xcloner_backblaze_account_id"),
|
673 |
$this->xcloner_settings->get_xcloner_option("xcloner_backblaze_application_key")
|
674 |
);
|
675 |
+
|
676 |
+
$bucket_id = $this->xcloner_settings->get_xcloner_option("xcloner_backblaze_bucket_id");
|
677 |
+
|
678 |
+
$adapter = new BackblazeAdapter(
|
679 |
+
$client,
|
680 |
+
$this->xcloner_settings->get_xcloner_option("xcloner_backblaze_bucket_name"),
|
681 |
+
empty($bucket_id) ? null : $bucket_id,
|
682 |
+
);
|
683 |
|
684 |
$filesystem = new Filesystem($adapter, new Config([
|
685 |
'disable_asserts' => true,
|
lib/Xcloner_Scheduler.php
CHANGED
@@ -3,54 +3,32 @@
|
|
3 |
namespace Watchfulli\XClonerCore;
|
4 |
|
5 |
use Exception;
|
|
|
|
|
|
|
|
|
6 |
|
7 |
class Xcloner_Scheduler
|
8 |
{
|
9 |
-
private $db;
|
10 |
private $scheduler_table = "xcloner_scheduler";
|
11 |
|
12 |
-
private $xcloner_remote_storage;
|
13 |
-
private $archive_system;
|
14 |
-
private $xcloner_database;
|
15 |
-
private $xcloner_settings;
|
16 |
private $logger;
|
17 |
-
private $xcloner_file_system;
|
18 |
-
private $xcloner_encryption;
|
19 |
private $xcloner_container;
|
20 |
|
21 |
private $allowed_schedules = array("hourly", "twicedaily", "daily", "weekly", "monthly");
|
22 |
|
23 |
-
/*public function __call($method, $args) {
|
24 |
-
echo "$method is not defined";
|
25 |
-
}*/
|
26 |
-
|
27 |
public function __construct(Xcloner $xcloner_container)
|
28 |
{
|
29 |
-
//global $wpdb;
|
30 |
-
|
31 |
$this->xcloner_container = $xcloner_container;
|
32 |
-
$this->xcloner_database = $this->get_xcloner_container()->get_xcloner_database();
|
33 |
-
$this->xcloner_settings = $this->xcloner_container->get_xcloner_settings();
|
34 |
|
35 |
-
$this->
|
36 |
-
$this->db->show_errors = false;
|
37 |
|
38 |
-
$this->scheduler_table = $this->
|
39 |
-
}
|
40 |
-
|
41 |
-
private function get_xcloner_container()
|
42 |
-
{
|
43 |
-
return $this->xcloner_container;
|
44 |
-
}
|
45 |
-
|
46 |
-
private function set_xcloner_container(Xcloner $container)
|
47 |
-
{
|
48 |
-
$this->xcloner_container = $container;
|
49 |
}
|
50 |
|
51 |
public function get_scheduler_list($return_only_enabled = 0)
|
52 |
{
|
53 |
-
$list = $this->
|
54 |
|
55 |
if (!$list) {
|
56 |
return array();
|
@@ -61,7 +39,7 @@ class Xcloner_Scheduler
|
|
61 |
|
62 |
foreach ($list as $res) {
|
63 |
if ($res->status) {
|
64 |
-
$res->next_run_time = wp_next_scheduled('xcloner_scheduler_' . $res->id, array($res->id)) + ($this->
|
65 |
if ($res->next_run_time) {
|
66 |
$new_list[] = $res;
|
67 |
}
|
@@ -75,14 +53,12 @@ class Xcloner_Scheduler
|
|
75 |
|
76 |
public function get_next_run_schedule()
|
77 |
{
|
78 |
-
|
79 |
-
|
80 |
-
return $list;
|
81 |
}
|
82 |
|
83 |
public function get_schedule_by_id_object($id)
|
84 |
{
|
85 |
-
$data = $this->
|
86 |
|
87 |
if (!$data) {
|
88 |
return false;
|
@@ -92,39 +68,32 @@ class Xcloner_Scheduler
|
|
92 |
}
|
93 |
|
94 |
/**
|
95 |
-
*
|
96 |
-
*
|
97 |
-
* @param [type] $id
|
98 |
-
* @return array
|
99 |
*/
|
100 |
public function get_schedule_by_id_or_name($id)
|
101 |
{
|
102 |
-
$data = $this->
|
103 |
|
104 |
if (!$data) {
|
105 |
-
|
106 |
}
|
107 |
|
108 |
return $data;
|
109 |
}
|
110 |
|
111 |
/**
|
112 |
-
*
|
113 |
-
*
|
114 |
-
* @param [type] $id
|
115 |
-
* @return array
|
116 |
*/
|
117 |
public function get_schedule_by_id($id)
|
118 |
{
|
119 |
-
$data = $this->
|
120 |
|
121 |
if (!$data) {
|
122 |
-
|
123 |
}
|
124 |
|
125 |
$params = json_decode($data['params']);
|
126 |
|
127 |
-
//print_r($params);
|
128 |
$data['params'] = "";
|
129 |
$data['backup_params'] = $params->backup_params;
|
130 |
$data['table_params'] = json_encode($params->database);
|
@@ -138,9 +107,7 @@ class Xcloner_Scheduler
|
|
138 |
$hook = 'xcloner_scheduler_' . $id;
|
139 |
wp_clear_scheduled_hook($hook, array($id));
|
140 |
|
141 |
-
|
142 |
-
|
143 |
-
return $data;
|
144 |
}
|
145 |
|
146 |
public function deactivate_wp_cron_hooks()
|
@@ -164,9 +131,9 @@ class Xcloner_Scheduler
|
|
164 |
$hook = 'xcloner_scheduler_' . $schedule->id;
|
165 |
|
166 |
//adding the xcloner_scheduler hook with xcloner_scheduler_callback callback
|
167 |
-
$this->xcloner_container->get_xcloner_loader()->add_action($hook, [$this, 'xcloner_scheduler_callback']
|
168 |
|
169 |
-
if (!wp_next_scheduled($hook, array($schedule->id))
|
170 |
if ($schedule->recurrence == "single") {
|
171 |
wp_schedule_single_event(strtotime($schedule->start_at), $hook, array($schedule->id));
|
172 |
} else {
|
@@ -209,7 +176,7 @@ class Xcloner_Scheduler
|
|
209 |
|
210 |
$schedule['status'] = 0;
|
211 |
|
212 |
-
|
213 |
$this->scheduler_table,
|
214 |
$schedule,
|
215 |
array('id' => $schedule_id),
|
@@ -218,8 +185,6 @@ class Xcloner_Scheduler
|
|
218 |
'%s'
|
219 |
)
|
220 |
);
|
221 |
-
|
222 |
-
return $update;
|
223 |
}
|
224 |
|
225 |
public function update_hash($schedule_id, $hash)
|
@@ -228,7 +193,7 @@ class Xcloner_Scheduler
|
|
228 |
|
229 |
$schedule['hash'] = $hash;
|
230 |
|
231 |
-
|
232 |
$this->scheduler_table,
|
233 |
$schedule,
|
234 |
array('id' => $schedule_id),
|
@@ -237,8 +202,6 @@ class Xcloner_Scheduler
|
|
237 |
'%s'
|
238 |
)
|
239 |
);
|
240 |
-
|
241 |
-
return $update;
|
242 |
}
|
243 |
|
244 |
public function update_last_backup($schedule_id, $last_backup)
|
@@ -249,7 +212,7 @@ class Xcloner_Scheduler
|
|
249 |
|
250 |
$schedule['last_backup'] = $last_backup;
|
251 |
|
252 |
-
|
253 |
$this->scheduler_table,
|
254 |
$schedule,
|
255 |
array('id' => $schedule_id),
|
@@ -258,21 +221,14 @@ class Xcloner_Scheduler
|
|
258 |
'%s'
|
259 |
)
|
260 |
);
|
261 |
-
|
262 |
-
return $update;
|
263 |
}
|
264 |
|
265 |
-
private function _xcloner_scheduler_callback($id, $schedule
|
266 |
{
|
267 |
set_time_limit(0);
|
268 |
|
269 |
$start_time = time();
|
270 |
|
271 |
-
if (!$xcloner) {
|
272 |
-
$xcloner = new \XCloner();
|
273 |
-
$xcloner->init();
|
274 |
-
}
|
275 |
-
$this->set_xcloner_container($xcloner);
|
276 |
$return_encrypted = array();
|
277 |
$return = array();
|
278 |
$additional = array();
|
@@ -285,25 +241,14 @@ class Xcloner_Scheduler
|
|
285 |
$schedule['name'] = 'standalone';
|
286 |
}
|
287 |
|
288 |
-
|
289 |
-
#$this->get_xcloner_container()->get_xcloner_settings()->set_hash($hash);
|
290 |
-
|
291 |
-
//$this->xcloner_settings = $this->get_xcloner_container()->get_xcloner_settings();
|
292 |
-
$this->xcloner_file_system = $this->get_xcloner_container()->get_xcloner_filesystem();
|
293 |
-
$this->xcloner_encryption = $this->get_xcloner_container()->get_xcloner_encryption();
|
294 |
-
$this->xcloner_database = $this->get_xcloner_container()->get_xcloner_database();
|
295 |
-
$this->archive_system = $this->get_xcloner_container()->get_archive_system();
|
296 |
-
$this->logger = $this->get_xcloner_container()->get_xcloner_logger()->withName("xcloner_scheduler");
|
297 |
-
$this->xcloner_remote_storage = $this->get_xcloner_container()->get_xcloner_remote_storage();
|
298 |
-
|
299 |
|
300 |
-
$this->
|
301 |
-
$this->db->show_errors = false;
|
302 |
|
303 |
-
$this->logger->info(sprintf("New schedule hash is %s", $this->
|
304 |
|
305 |
if (isset($schedule['backup_params']->diff_start_date) && $schedule['backup_params']->diff_start_date) {
|
306 |
-
$this->
|
307 |
}
|
308 |
|
309 |
|
@@ -317,21 +262,19 @@ class Xcloner_Scheduler
|
|
317 |
return;
|
318 |
}
|
319 |
|
320 |
-
|
321 |
-
|
322 |
-
//we update this only in WP mode
|
323 |
-
$this->update_hash($schedule['id'], $this->xcloner_settings->get_hash());
|
324 |
}
|
325 |
|
326 |
$this->logger->print_info(sprintf("Starting backup profile '%s'", $schedule['name']), array("CRON"));
|
327 |
|
328 |
-
$this->
|
329 |
|
330 |
$init = 1;
|
331 |
$continue = 1;
|
332 |
|
333 |
while ($continue) {
|
334 |
-
$continue = $this->
|
335 |
|
336 |
$init = 0;
|
337 |
}
|
@@ -344,7 +287,7 @@ class Xcloner_Scheduler
|
|
344 |
$return['finished'] = 0;
|
345 |
|
346 |
while (!$return['finished']) {
|
347 |
-
$return = $this->
|
348 |
$init = 0;
|
349 |
}
|
350 |
|
@@ -357,15 +300,15 @@ class Xcloner_Scheduler
|
|
357 |
$return['extra'] = array();
|
358 |
|
359 |
while (!$return['finished']) {
|
360 |
-
$return = $this->
|
361 |
$init = 0;
|
362 |
}
|
363 |
$this->logger->print_info(sprintf("File archive process FINISHED."), array("CRON"));
|
364 |
|
365 |
//getting the last backup archive file
|
366 |
-
$return['extra']['backup_parent'] = $this->
|
367 |
-
if ($this->
|
368 |
-
$return['extra']['backup_parent'] = $this->
|
369 |
}
|
370 |
|
371 |
//Updating schedule last backup archive
|
@@ -384,13 +327,13 @@ class Xcloner_Scheduler
|
|
384 |
|
385 |
$backup_file = $return['extra']['backup_parent'];
|
386 |
|
387 |
-
if ($this->
|
388 |
-
$backup_parts = $this->
|
389 |
$backup_file = $backup_parts[$part];
|
390 |
}
|
391 |
|
392 |
while (!$return_encrypted['finished']) {
|
393 |
-
$return_encrypted = $this->
|
394 |
$backup_file,
|
395 |
"",
|
396 |
"",
|
@@ -411,17 +354,17 @@ class Xcloner_Scheduler
|
|
411 |
}
|
412 |
}
|
413 |
|
414 |
-
$additional['backup_size'] = size_format($this->
|
415 |
|
416 |
//Sending backup to remote storage
|
417 |
-
if (isset($schedule['remote_storage']) && $schedule['remote_storage'] && array_key_exists($schedule['remote_storage'], $this->
|
418 |
$backup_file = $return['extra']['backup_parent'];
|
419 |
|
420 |
$this->logger->print_info(sprintf("Transferring backup to remote storage %s", strtoupper($schedule['remote_storage'])), array("CRON"));
|
421 |
|
422 |
-
if (method_exists($this->
|
423 |
call_user_func_array(array(
|
424 |
-
$this->
|
425 |
"upload_backup_to_storage"
|
426 |
), array($backup_file, $schedule['remote_storage'], $schedule['backup_params']->backup_delete_after_remote_transfer));
|
427 |
}
|
@@ -434,49 +377,55 @@ class Xcloner_Scheduler
|
|
434 |
$additional['lines_total'] = $return['extra']['lines_total'];
|
435 |
$subject = sprintf(__("%s - new backup generated %s"), $schedule['name'], $return['extra']['backup_parent']);
|
436 |
|
437 |
-
$this->
|
438 |
} catch (Exception $e) {
|
439 |
$this->logger->error($e->getMessage());
|
440 |
}
|
441 |
}
|
442 |
|
443 |
//Backup Storage Cleanup
|
444 |
-
$this->
|
445 |
|
446 |
//Filesystem Cleanup
|
447 |
-
$this->
|
448 |
|
449 |
//Removing the tmp filesystem used for backup
|
450 |
-
$this->
|
451 |
|
452 |
$this->logger->print_info(sprintf("Profile '%s' finished in %d seconds.", $schedule['name'], time() - $start_time), array("CRON"));
|
453 |
|
454 |
return $return;
|
455 |
}
|
456 |
|
457 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
458 |
{
|
459 |
-
if ($id) {
|
460 |
-
$schedule = $this->get_schedule_by_id($id);
|
461 |
-
}
|
462 |
-
|
463 |
try {
|
464 |
-
if ($
|
|
|
|
|
|
|
|
|
465 |
//we disable email notifications
|
466 |
$schedule['backup_params']->email_notification = "";
|
467 |
}
|
468 |
|
469 |
-
$this->_xcloner_scheduler_callback($id, $schedule
|
470 |
} catch (Exception $e) {
|
471 |
|
472 |
//send email to site admin if email notification is not set in the scheduler
|
473 |
if (!isset($schedule['backup_params']->email_notification) || !$schedule['backup_params']->email_notification) {
|
474 |
-
$schedule['backup_params']->email_notification = $this->
|
475 |
}
|
476 |
|
477 |
if (isset($schedule['backup_params']->email_notification) && $to = $schedule['backup_params']->email_notification) {
|
478 |
$from = "";
|
479 |
-
$this->
|
480 |
}
|
481 |
}
|
482 |
}
|
3 |
namespace Watchfulli\XClonerCore;
|
4 |
|
5 |
use Exception;
|
6 |
+
use splitbrain\PHPArchive\ArchiveCorruptedException;
|
7 |
+
use splitbrain\PHPArchive\ArchiveIllegalCompressionException;
|
8 |
+
use splitbrain\PHPArchive\ArchiveIOException;
|
9 |
+
use splitbrain\PHPArchive\FileInfoException;
|
10 |
|
11 |
class Xcloner_Scheduler
|
12 |
{
|
|
|
13 |
private $scheduler_table = "xcloner_scheduler";
|
14 |
|
|
|
|
|
|
|
|
|
15 |
private $logger;
|
|
|
|
|
16 |
private $xcloner_container;
|
17 |
|
18 |
private $allowed_schedules = array("hourly", "twicedaily", "daily", "weekly", "monthly");
|
19 |
|
|
|
|
|
|
|
|
|
20 |
public function __construct(Xcloner $xcloner_container)
|
21 |
{
|
|
|
|
|
22 |
$this->xcloner_container = $xcloner_container;
|
|
|
|
|
23 |
|
24 |
+
$this->xcloner_container->get_xcloner_database()->show_errors = false;
|
|
|
25 |
|
26 |
+
$this->scheduler_table = $this->xcloner_container->get_xcloner_settings()->get_table_prefix() . $this->scheduler_table;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
27 |
}
|
28 |
|
29 |
public function get_scheduler_list($return_only_enabled = 0)
|
30 |
{
|
31 |
+
$list = $this->xcloner_container->get_xcloner_database()->get_results("SELECT * FROM " . $this->scheduler_table);
|
32 |
|
33 |
if (!$list) {
|
34 |
return array();
|
39 |
|
40 |
foreach ($list as $res) {
|
41 |
if ($res->status) {
|
42 |
+
$res->next_run_time = wp_next_scheduled('xcloner_scheduler_' . $res->id, array($res->id)) + ($this->xcloner_container->get_xcloner_settings()->get_xcloner_option('gmt_offset') * HOUR_IN_SECONDS);
|
43 |
if ($res->next_run_time) {
|
44 |
$new_list[] = $res;
|
45 |
}
|
53 |
|
54 |
public function get_next_run_schedule()
|
55 |
{
|
56 |
+
return $this->get_scheduler_list($return_only_enabled = 1);
|
|
|
|
|
57 |
}
|
58 |
|
59 |
public function get_schedule_by_id_object($id)
|
60 |
{
|
61 |
+
$data = $this->xcloner_container->get_xcloner_database()->get_row("SELECT * FROM " . $this->scheduler_table . " WHERE id=" . $id);
|
62 |
|
63 |
if (!$data) {
|
64 |
return false;
|
68 |
}
|
69 |
|
70 |
/**
|
71 |
+
* @throws Exception
|
|
|
|
|
|
|
72 |
*/
|
73 |
public function get_schedule_by_id_or_name($id)
|
74 |
{
|
75 |
+
$data = $this->xcloner_container->get_xcloner_database()->get_row("SELECT * FROM " . $this->scheduler_table . " WHERE id='" . $id . "' or name='" . $id . "'", ARRAY_A);
|
76 |
|
77 |
if (!$data) {
|
78 |
+
throw new Exception("Schedule not found");
|
79 |
}
|
80 |
|
81 |
return $data;
|
82 |
}
|
83 |
|
84 |
/**
|
85 |
+
* @throws Exception
|
|
|
|
|
|
|
86 |
*/
|
87 |
public function get_schedule_by_id($id)
|
88 |
{
|
89 |
+
$data = $this->xcloner_container->get_xcloner_database()->get_row("SELECT * FROM " . $this->scheduler_table . " WHERE id=" . $id, ARRAY_A);
|
90 |
|
91 |
if (!$data) {
|
92 |
+
throw new Exception("Schedule not found");
|
93 |
}
|
94 |
|
95 |
$params = json_decode($data['params']);
|
96 |
|
|
|
97 |
$data['params'] = "";
|
98 |
$data['backup_params'] = $params->backup_params;
|
99 |
$data['table_params'] = json_encode($params->database);
|
107 |
$hook = 'xcloner_scheduler_' . $id;
|
108 |
wp_clear_scheduled_hook($hook, array($id));
|
109 |
|
110 |
+
return $this->xcloner_container->get_xcloner_database()->delete($this->scheduler_table, array('id' => $id));
|
|
|
|
|
111 |
}
|
112 |
|
113 |
public function deactivate_wp_cron_hooks()
|
131 |
$hook = 'xcloner_scheduler_' . $schedule->id;
|
132 |
|
133 |
//adding the xcloner_scheduler hook with xcloner_scheduler_callback callback
|
134 |
+
$this->xcloner_container->get_xcloner_loader()->add_action($hook, [$this, 'xcloner_scheduler_callback']);
|
135 |
|
136 |
+
if (!wp_next_scheduled($hook, array($schedule->id)) && $schedule->status) {
|
137 |
if ($schedule->recurrence == "single") {
|
138 |
wp_schedule_single_event(strtotime($schedule->start_at), $hook, array($schedule->id));
|
139 |
} else {
|
176 |
|
177 |
$schedule['status'] = 0;
|
178 |
|
179 |
+
return $this->xcloner_container->get_xcloner_database()->update(
|
180 |
$this->scheduler_table,
|
181 |
$schedule,
|
182 |
array('id' => $schedule_id),
|
185 |
'%s'
|
186 |
)
|
187 |
);
|
|
|
|
|
188 |
}
|
189 |
|
190 |
public function update_hash($schedule_id, $hash)
|
193 |
|
194 |
$schedule['hash'] = $hash;
|
195 |
|
196 |
+
return $this->xcloner_container->get_xcloner_database()->update(
|
197 |
$this->scheduler_table,
|
198 |
$schedule,
|
199 |
array('id' => $schedule_id),
|
202 |
'%s'
|
203 |
)
|
204 |
);
|
|
|
|
|
205 |
}
|
206 |
|
207 |
public function update_last_backup($schedule_id, $last_backup)
|
212 |
|
213 |
$schedule['last_backup'] = $last_backup;
|
214 |
|
215 |
+
return $this->xcloner_container->get_xcloner_database()->update(
|
216 |
$this->scheduler_table,
|
217 |
$schedule,
|
218 |
array('id' => $schedule_id),
|
221 |
'%s'
|
222 |
)
|
223 |
);
|
|
|
|
|
224 |
}
|
225 |
|
226 |
+
private function _xcloner_scheduler_callback($id, $schedule)
|
227 |
{
|
228 |
set_time_limit(0);
|
229 |
|
230 |
$start_time = time();
|
231 |
|
|
|
|
|
|
|
|
|
|
|
232 |
$return_encrypted = array();
|
233 |
$return = array();
|
234 |
$additional = array();
|
241 |
$schedule['name'] = 'standalone';
|
242 |
}
|
243 |
|
244 |
+
$this->logger = $this->xcloner_container->get_xcloner_logger()->withName("xcloner_scheduler");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
245 |
|
246 |
+
$this->xcloner_container->get_xcloner_database()->show_errors = false;
|
|
|
247 |
|
248 |
+
$this->logger->info(sprintf("New schedule hash is %s", $this->xcloner_container->get_xcloner_settings()->get_hash()));
|
249 |
|
250 |
if (isset($schedule['backup_params']->diff_start_date) && $schedule['backup_params']->diff_start_date) {
|
251 |
+
$this->xcloner_container->get_xcloner_filesystem()->set_diff_timestamp_start($schedule['backup_params']->diff_start_date);
|
252 |
}
|
253 |
|
254 |
|
262 |
return;
|
263 |
}
|
264 |
|
265 |
+
if (defined('DOING_CRON')) {
|
266 |
+
$this->update_hash($schedule['id'], $this->xcloner_container->get_xcloner_settings()->generate_new_hash());
|
|
|
|
|
267 |
}
|
268 |
|
269 |
$this->logger->print_info(sprintf("Starting backup profile '%s'", $schedule['name']), array("CRON"));
|
270 |
|
271 |
+
$this->xcloner_container->get_xcloner_filesystem()->set_excluded_files(json_decode($schedule['excluded_files']));
|
272 |
|
273 |
$init = 1;
|
274 |
$continue = 1;
|
275 |
|
276 |
while ($continue) {
|
277 |
+
$continue = $this->xcloner_container->get_xcloner_filesystem()->start_file_recursion($init);
|
278 |
|
279 |
$init = 0;
|
280 |
}
|
287 |
$return['finished'] = 0;
|
288 |
|
289 |
while (!$return['finished']) {
|
290 |
+
$return = $this->xcloner_container->get_xcloner_database()->start_database_recursion((array)json_decode($schedule['table_params']), $return, $init);
|
291 |
$init = 0;
|
292 |
}
|
293 |
|
300 |
$return['extra'] = array();
|
301 |
|
302 |
while (!$return['finished']) {
|
303 |
+
$return = $this->xcloner_container->get_archive_system()->start_incremental_backup((array)$schedule['backup_params'], $return['extra'], $init);
|
304 |
$init = 0;
|
305 |
}
|
306 |
$this->logger->print_info(sprintf("File archive process FINISHED."), array("CRON"));
|
307 |
|
308 |
//getting the last backup archive file
|
309 |
+
$return['extra']['backup_parent'] = $this->xcloner_container->get_archive_system()->get_archive_name_with_extension();
|
310 |
+
if ($this->xcloner_container->get_xcloner_filesystem()->is_part($this->xcloner_container->get_archive_system()->get_archive_name_with_extension())) {
|
311 |
+
$return['extra']['backup_parent'] = $this->xcloner_container->get_archive_system()->get_archive_name_multipart();
|
312 |
}
|
313 |
|
314 |
//Updating schedule last backup archive
|
327 |
|
328 |
$backup_file = $return['extra']['backup_parent'];
|
329 |
|
330 |
+
if ($this->xcloner_container->get_xcloner_filesystem()->is_multipart($return['extra']['backup_parent'])) {
|
331 |
+
$backup_parts = $this->xcloner_container->get_xcloner_filesystem()->get_multipart_files($return['extra']['backup_parent']);
|
332 |
$backup_file = $backup_parts[$part];
|
333 |
}
|
334 |
|
335 |
while (!$return_encrypted['finished']) {
|
336 |
+
$return_encrypted = $this->xcloner_container->get_xcloner_encryption()->encrypt_file(
|
337 |
$backup_file,
|
338 |
"",
|
339 |
"",
|
354 |
}
|
355 |
}
|
356 |
|
357 |
+
$additional['backup_size'] = size_format($this->xcloner_container->get_xcloner_filesystem()->get_backup_size($return['extra']['backup_parent']));
|
358 |
|
359 |
//Sending backup to remote storage
|
360 |
+
if (isset($schedule['remote_storage']) && $schedule['remote_storage'] && array_key_exists($schedule['remote_storage'], $this->xcloner_container->get_xcloner_remote_storage()->get_available_storages())) {
|
361 |
$backup_file = $return['extra']['backup_parent'];
|
362 |
|
363 |
$this->logger->print_info(sprintf("Transferring backup to remote storage %s", strtoupper($schedule['remote_storage'])), array("CRON"));
|
364 |
|
365 |
+
if (method_exists($this->xcloner_container->get_xcloner_remote_storage(), "upload_backup_to_storage")) {
|
366 |
call_user_func_array(array(
|
367 |
+
$this->xcloner_container->get_xcloner_remote_storage(),
|
368 |
"upload_backup_to_storage"
|
369 |
), array($backup_file, $schedule['remote_storage'], $schedule['backup_params']->backup_delete_after_remote_transfer));
|
370 |
}
|
377 |
$additional['lines_total'] = $return['extra']['lines_total'];
|
378 |
$subject = sprintf(__("%s - new backup generated %s"), $schedule['name'], $return['extra']['backup_parent']);
|
379 |
|
380 |
+
$this->xcloner_container->get_archive_system()->send_notification($to, $from, $subject, $return['extra']['backup_parent'], $schedule, "", $additional);
|
381 |
} catch (Exception $e) {
|
382 |
$this->logger->error($e->getMessage());
|
383 |
}
|
384 |
}
|
385 |
|
386 |
//Backup Storage Cleanup
|
387 |
+
$this->xcloner_container->get_xcloner_filesystem()->backup_storage_cleanup();
|
388 |
|
389 |
//Filesystem Cleanup
|
390 |
+
$this->xcloner_container->get_xcloner_filesystem()->cleanup_tmp_directories();
|
391 |
|
392 |
//Removing the tmp filesystem used for backup
|
393 |
+
$this->xcloner_container->get_xcloner_filesystem()->remove_tmp_filesystem();
|
394 |
|
395 |
$this->logger->print_info(sprintf("Profile '%s' finished in %d seconds.", $schedule['name'], time() - $start_time), array("CRON"));
|
396 |
|
397 |
return $return;
|
398 |
}
|
399 |
|
400 |
+
/**
|
401 |
+
* @throws ArchiveIOException
|
402 |
+
* @throws ArchiveCorruptedException
|
403 |
+
* @throws FileInfoException
|
404 |
+
* @throws ArchiveIllegalCompressionException
|
405 |
+
*/
|
406 |
+
public function xcloner_scheduler_callback($id, $schedule = "")
|
407 |
{
|
|
|
|
|
|
|
|
|
408 |
try {
|
409 |
+
if ($id) {
|
410 |
+
$schedule = $this->get_schedule_by_id($id);
|
411 |
+
}
|
412 |
+
|
413 |
+
if ($this->xcloner_container->get_xcloner_settings()->get_xcloner_option('xcloner_disable_email_notification')) {
|
414 |
//we disable email notifications
|
415 |
$schedule['backup_params']->email_notification = "";
|
416 |
}
|
417 |
|
418 |
+
$this->_xcloner_scheduler_callback($id, $schedule);
|
419 |
} catch (Exception $e) {
|
420 |
|
421 |
//send email to site admin if email notification is not set in the scheduler
|
422 |
if (!isset($schedule['backup_params']->email_notification) || !$schedule['backup_params']->email_notification) {
|
423 |
+
$schedule['backup_params']->email_notification = $this->xcloner_container->get_xcloner_settings()->get_xcloner_option('admin_email');
|
424 |
}
|
425 |
|
426 |
if (isset($schedule['backup_params']->email_notification) && $to = $schedule['backup_params']->email_notification) {
|
427 |
$from = "";
|
428 |
+
$this->xcloner_container->get_archive_system()->send_notification($to, $from, $schedule['name'] . " - backup error", "", "", $e->getMessage());
|
429 |
}
|
430 |
}
|
431 |
}
|
vendor/autoload.php
CHANGED
@@ -9,4 +9,4 @@ if (PHP_VERSION_ID < 50600) {
|
|
9 |
|
10 |
require_once __DIR__ . '/composer/autoload_real.php';
|
11 |
|
12 |
-
return
|
9 |
|
10 |
require_once __DIR__ . '/composer/autoload_real.php';
|
11 |
|
12 |
+
return ComposerAutoloaderInit238ab22fb5f7b2c52596ccc9f2b13d04::getLoader();
|
vendor/composer/autoload_real.php
CHANGED
@@ -2,7 +2,7 @@
|
|
2 |
|
3 |
// autoload_real.php @generated by Composer
|
4 |
|
5 |
-
class
|
6 |
{
|
7 |
private static $loader;
|
8 |
|
@@ -24,18 +24,18 @@ class ComposerAutoloaderInit33b98bd5608997f602482388b1d4d108
|
|
24 |
|
25 |
require __DIR__ . '/platform_check.php';
|
26 |
|
27 |
-
spl_autoload_register(array('
|
28 |
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
|
29 |
-
spl_autoload_unregister(array('
|
30 |
|
31 |
require __DIR__ . '/autoload_static.php';
|
32 |
-
call_user_func(\Composer\Autoload\
|
33 |
|
34 |
$loader->register(true);
|
35 |
|
36 |
-
$includeFiles = \Composer\Autoload\
|
37 |
foreach ($includeFiles as $fileIdentifier => $file) {
|
38 |
-
|
39 |
}
|
40 |
|
41 |
return $loader;
|
@@ -47,7 +47,7 @@ class ComposerAutoloaderInit33b98bd5608997f602482388b1d4d108
|
|
47 |
* @param string $file
|
48 |
* @return void
|
49 |
*/
|
50 |
-
function
|
51 |
{
|
52 |
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
53 |
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
|
2 |
|
3 |
// autoload_real.php @generated by Composer
|
4 |
|
5 |
+
class ComposerAutoloaderInit238ab22fb5f7b2c52596ccc9f2b13d04
|
6 |
{
|
7 |
private static $loader;
|
8 |
|
24 |
|
25 |
require __DIR__ . '/platform_check.php';
|
26 |
|
27 |
+
spl_autoload_register(array('ComposerAutoloaderInit238ab22fb5f7b2c52596ccc9f2b13d04', 'loadClassLoader'), true, true);
|
28 |
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
|
29 |
+
spl_autoload_unregister(array('ComposerAutoloaderInit238ab22fb5f7b2c52596ccc9f2b13d04', 'loadClassLoader'));
|
30 |
|
31 |
require __DIR__ . '/autoload_static.php';
|
32 |
+
call_user_func(\Composer\Autoload\ComposerStaticInit238ab22fb5f7b2c52596ccc9f2b13d04::getInitializer($loader));
|
33 |
|
34 |
$loader->register(true);
|
35 |
|
36 |
+
$includeFiles = \Composer\Autoload\ComposerStaticInit238ab22fb5f7b2c52596ccc9f2b13d04::$files;
|
37 |
foreach ($includeFiles as $fileIdentifier => $file) {
|
38 |
+
composerRequire238ab22fb5f7b2c52596ccc9f2b13d04($fileIdentifier, $file);
|
39 |
}
|
40 |
|
41 |
return $loader;
|
47 |
* @param string $file
|
48 |
* @return void
|
49 |
*/
|
50 |
+
function composerRequire238ab22fb5f7b2c52596ccc9f2b13d04($fileIdentifier, $file)
|
51 |
{
|
52 |
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
53 |
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
|
vendor/composer/autoload_static.php
CHANGED
@@ -4,7 +4,7 @@
|
|
4 |
|
5 |
namespace Composer\Autoload;
|
6 |
|
7 |
-
class
|
8 |
{
|
9 |
public static $files = array (
|
10 |
'7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php',
|
@@ -7957,10 +7957,10 @@ class ComposerStaticInit33b98bd5608997f602482388b1d4d108
|
|
7957 |
public static function getInitializer(ClassLoader $loader)
|
7958 |
{
|
7959 |
return \Closure::bind(function () use ($loader) {
|
7960 |
-
$loader->prefixLengthsPsr4 =
|
7961 |
-
$loader->prefixDirsPsr4 =
|
7962 |
-
$loader->prefixesPsr0 =
|
7963 |
-
$loader->classMap =
|
7964 |
|
7965 |
}, null, ClassLoader::class);
|
7966 |
}
|
4 |
|
5 |
namespace Composer\Autoload;
|
6 |
|
7 |
+
class ComposerStaticInit238ab22fb5f7b2c52596ccc9f2b13d04
|
8 |
{
|
9 |
public static $files = array (
|
10 |
'7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php',
|
7957 |
public static function getInitializer(ClassLoader $loader)
|
7958 |
{
|
7959 |
return \Closure::bind(function () use ($loader) {
|
7960 |
+
$loader->prefixLengthsPsr4 = ComposerStaticInit238ab22fb5f7b2c52596ccc9f2b13d04::$prefixLengthsPsr4;
|
7961 |
+
$loader->prefixDirsPsr4 = ComposerStaticInit238ab22fb5f7b2c52596ccc9f2b13d04::$prefixDirsPsr4;
|
7962 |
+
$loader->prefixesPsr0 = ComposerStaticInit238ab22fb5f7b2c52596ccc9f2b13d04::$prefixesPsr0;
|
7963 |
+
$loader->classMap = ComposerStaticInit238ab22fb5f7b2c52596ccc9f2b13d04::$classMap;
|
7964 |
|
7965 |
}, null, ClassLoader::class);
|
7966 |
}
|
vendor/composer/installed.php
CHANGED
@@ -1,9 +1,9 @@
|
|
1 |
<?php return array(
|
2 |
'root' => array(
|
3 |
'name' => 'watchfulli/xcloner-wordpress',
|
4 |
-
'pretty_version' => 'v4.4.
|
5 |
-
'version' => '4.4.
|
6 |
-
'reference' => '
|
7 |
'type' => 'library',
|
8 |
'install_path' => __DIR__ . '/../../',
|
9 |
'aliases' => array(),
|
@@ -404,9 +404,9 @@
|
|
404 |
'dev_requirement' => false,
|
405 |
),
|
406 |
'watchfulli/xcloner-wordpress' => array(
|
407 |
-
'pretty_version' => 'v4.4.
|
408 |
-
'version' => '4.4.
|
409 |
-
'reference' => '
|
410 |
'type' => 'library',
|
411 |
'install_path' => __DIR__ . '/../../',
|
412 |
'aliases' => array(),
|
1 |
<?php return array(
|
2 |
'root' => array(
|
3 |
'name' => 'watchfulli/xcloner-wordpress',
|
4 |
+
'pretty_version' => 'v4.4.2',
|
5 |
+
'version' => '4.4.2.0',
|
6 |
+
'reference' => '925987090a887d9d37cae7e5f8000a4c9037251f',
|
7 |
'type' => 'library',
|
8 |
'install_path' => __DIR__ . '/../../',
|
9 |
'aliases' => array(),
|
404 |
'dev_requirement' => false,
|
405 |
),
|
406 |
'watchfulli/xcloner-wordpress' => array(
|
407 |
+
'pretty_version' => 'v4.4.2',
|
408 |
+
'version' => '4.4.2.0',
|
409 |
+
'reference' => '925987090a887d9d37cae7e5f8000a4c9037251f',
|
410 |
'type' => 'library',
|
411 |
'install_path' => __DIR__ . '/../../',
|
412 |
'aliases' => array(),
|
xcloner.php
CHANGED
@@ -15,7 +15,7 @@
|
|
15 |
* Plugin Name: XCloner - Site Backup and Restore
|
16 |
* Plugin URI: https://xcloner.com/
|
17 |
* Description: XCloner is a tool that will help you manage your website backups, generate/restore/move so your website will be always secured! With XCloner you will be able to clone your site to any other location with just a few clicks, as well as transfer the backup archives to remote FTP, SFTP, DropBox, Amazon S3, Google Drive, WebDAV, Backblaze, Azure accounts.
|
18 |
-
* Version: 4.4.
|
19 |
* Author: watchful
|
20 |
* Author URI: https://watchful.net/
|
21 |
* License: GPL-2.0+
|
@@ -202,13 +202,13 @@ function do_cli_execution($args = array(), $opts = array())
|
|
202 |
|
203 |
// start schedule based on profile name
|
204 |
if (!empty($profile_name)) {
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
$xcloner_backup->execute_backup($profile['id']);
|
209 |
-
} else {
|
210 |
die(sprintf('Could not find profile %s', $profile_name));
|
211 |
}
|
|
|
|
|
212 |
}
|
213 |
}
|
214 |
|
15 |
* Plugin Name: XCloner - Site Backup and Restore
|
16 |
* Plugin URI: https://xcloner.com/
|
17 |
* Description: XCloner is a tool that will help you manage your website backups, generate/restore/move so your website will be always secured! With XCloner you will be able to clone your site to any other location with just a few clicks, as well as transfer the backup archives to remote FTP, SFTP, DropBox, Amazon S3, Google Drive, WebDAV, Backblaze, Azure accounts.
|
18 |
+
* Version: 4.4.2
|
19 |
* Author: watchful
|
20 |
* Author URI: https://watchful.net/
|
21 |
* License: GPL-2.0+
|
202 |
|
203 |
// start schedule based on profile name
|
204 |
if (!empty($profile_name)) {
|
205 |
+
try {
|
206 |
+
$profile = $xcloner_backup->get_xcloner_scheduler()->get_schedule_by_id_or_name($profile_name);
|
207 |
+
} catch (Exception $e) {
|
|
|
|
|
208 |
die(sprintf('Could not find profile %s', $profile_name));
|
209 |
}
|
210 |
+
|
211 |
+
$xcloner_backup->execute_backup($profile['id']);
|
212 |
}
|
213 |
}
|
214 |
|