PluginProbe ʕ •ᴥ•ʔ
Backup Migration / 1.4.9
Backup Migration v1.4.9
2.1.6 2.1.5.2 trunk 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.6.1 1.4.7 1.4.8 1.4.9 1.4.9.1 2.0.0 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.5.1
backup-backup / includes / backup-process.php
backup-backup / includes Last commit date
banner 11 months ago bodies 11 months ago check 11 months ago cli 11 months ago cron 11 months ago dashboard 11 months ago database 11 months ago external 11 months ago extracter 11 months ago htaccess 11 months ago notices 11 months ago progress 11 months ago scanner 11 months ago staging 11 months ago traits 11 months ago uploader 11 months ago zipper 11 months ago .htaccess 11 months ago activation.php 11 months ago ajax.php 11 months ago ajax_offline.php 11 months ago analyst.php 11 months ago backup-process.php 11 months ago class-backup-method-mananger.php 11 months ago cli-handler.php 11 months ago compatibility.php 11 months ago config.php 11 months ago constants.php 11 months ago initializer.php 11 months ago logger.php 11 months ago offline.php 11 months ago
backup-process.php
1332 lines
1 <?php
2
3 // Namespace
4 namespace BMI\Plugin\Heart;
5
6 // Usage
7 use BMI\Plugin\BMI_Logger AS Logger;
8 use BMI\Plugin\Progress\BMI_ZipProgress AS Output;
9 use BMI\Plugin\Checker\System_Info as SI;
10 use BMI\Plugin\Dashboard as Dashboard;
11 use BMI\Plugin\Database\BMI_Database as Database;
12 use BMI\Plugin\Database\BMI_Database_Exporter as BetterDatabaseExport;
13 use BMI\Plugin\Backup_Migration_Plugin as BMP;
14 use BMI\Plugin\BMI_Pro_Core as Pro_Core;
15 use BMI\Plugin AS BMI;
16
17 // Exit on direct access
18 if (!defined('ABSPATH')) exit;
19
20 // Fixes for some cases
21 require_once BMI_INCLUDES . '/compatibility.php';
22
23 /**
24 * Main class to handle heartbeat of the backup
25 */
26 class BMI_Backup_Heart {
27
28 public $it;
29 public $dbit;
30 public $abs;
31 public $dir;
32 public $url;
33 public $curl;
34 public $config;
35 public $content;
36 public $backups;
37 public $dblast;
38 public $output;
39 public $useragent;
40 public $remote_settings;
41
42 public $identy;
43 public $manifest;
44 public $backupname;
45 public $safelimit;
46 public $total_files;
47 public $rev;
48 public $backupstart;
49 public $filessofar;
50 public $identyfile;
51 public $browserSide;
52
53 public $identyFolder;
54 public $fileList;
55 public $dbfile;
56 public $db_dir_v2;
57 public $db_v2_engine;
58
59 public $final_made;
60 public $final_batch;
61 public $dbitJustFinished;
62 public $lock_cli;
63 public $startOfBatch;
64 public $beatSent = false;
65 public $errorSent = false;
66 public $statusSent = false;
67 public $backupSize = 0;
68
69 public $_zip;
70 public $_lib;
71 public $batches_left;
72 public $shutdownAlreadyInited = false;
73 public $res = [ 'status' => 'success', 'default' => true ];
74
75 // Prepare the request details
76 function __construct($curlIdenty = false, $config = false, $content = false, $backups = false, $abs = false, $dir = false, $remote_settings = []) {
77
78 if (!defined('BMI_CLI_REQUEST')) {
79 define('BMI_CLI_REQUEST', false);
80 }
81
82 $curl = false;
83 if ($curlIdenty != false) $curl = true;
84
85 $remote_settings = $this->getRemoteSettings($curlIdenty, $curl);
86 $this->remote_settings = $remote_settings;
87 if (sizeof($remote_settings) === 0) return;
88
89 $this->setupConstants();
90
91 $this->it = $remote_settings['it'];
92 $this->dbit = $remote_settings['dbit'];
93 $this->abs = $abs;
94 $this->dir = $dir;
95 $this->curl = $curl;
96 $this->config = $config;
97 $this->content = $content;
98 $this->backups = $backups;
99 $this->dblast = $remote_settings['dblast'];
100 $this->useragent = $remote_settings['useragent'];
101
102 $this->identy = $remote_settings['identy'];
103 $this->manifest = $remote_settings['manifest'];
104 $this->backupname = $remote_settings['backupname'];
105 $this->safelimit = intval($remote_settings['safelimit']);
106 $this->total_files = $remote_settings['total_files'];
107 $this->rev = intval($remote_settings['rev']);
108 $this->backupstart = $remote_settings['start'];
109 $this->filessofar = intval($remote_settings['filessofar']);
110 $this->identyfile = BMI_TMP . DIRECTORY_SEPARATOR . '.' . $this->identy;
111 $this->browserSide = (isset($remote_settings['browser']) && ($remote_settings['browser'] === true || $remote_settings['browser'] === 'true')) ? true : false;
112
113 if ($curl) {
114 // Here we could use nonces, but well, WordPress can't handle nonces in such scenario due to the way its generated
115 // We still use "nonce" here to bypass some security plugins as they may block the URL if the nonce string does not exist in such URL
116 $this->url = get_home_url(null, sprintf('/?backup-migration=CURL_BACKUP&backup-id=%s&_wpnonce=%s&t=%s&sk=%s', $this->identy, 'Wn19dnWuq', time(), Dashboard\bmi_get_config('REQUEST:SECRET')));
117 } else {
118 $this->url = null;
119 }
120
121 $this->identyFolder = BMI_TMP . DIRECTORY_SEPARATOR . 'bg-' . $this->identy;
122 $this->fileList = BMI_TMP . DIRECTORY_SEPARATOR . 'files_latest.list';
123 $this->dbfile = BMI_TMP . DIRECTORY_SEPARATOR . 'bmi_database_backup.sql';
124 $this->db_dir_v2 = BMI_TMP . DIRECTORY_SEPARATOR . 'db_tables';
125 $this->db_v2_engine = false;
126
127 $this->final_made = $remote_settings['final_made'];
128 $this->final_batch = $remote_settings['final_batch'];
129 $this->dbitJustFinished = $remote_settings['dbitJustFinished'];
130 $this->backupSize = 0;
131 if (isset($remote_settings['backupSize']))
132 $this->backupSize = $remote_settings['backupSize'];
133
134 $this->startOfBatch = time();
135 if (isset($remote_settings['startOfBatch']))
136 $this->startOfBatch = $remote_settings['startOfBatch'];
137
138 $this->lock_cli = BMI_BACKUPS . '/.backup_cli_lock';
139 if ($this->it > 1) @touch($this->lock_cli);
140
141 if ($this->isFunctionEnabled('ini_set') && $this->isFunctionEnabled('session_status') && session_status() != PHP_SESSION_ACTIVE) {
142 ini_set('display_errors', 1);
143 ini_set('error_reporting', E_ALL);
144 ini_set('log_errors', 1);
145 ini_set('error_log', BMI_CONFIG_DIR . '/background-errors.log');
146 }
147
148 }
149
150 // Get "remote_settings" from file created by the server
151 public function getRemoteSettings($curlIdenty, $curl = false) : array {
152 $settings_name = 'currentBackupConfig.' . 'php';
153 $settings_path = BMP::fixSlashes(BMI_TMP . DIRECTORY_SEPARATOR . $settings_name);
154
155 if (!file_exists($settings_path) && $curl) {
156 Logger::error('Settings path does not exist for backup-process.php');
157 return [];
158 }
159
160 if (!file_exists($settings_path)) {
161 Logger::error('Config file does not exist, please try to run the backup process once again.');
162 return $this->send_error('Config file does not exist, please try to run the backup process once again.', true);
163 }
164
165 $remote_settings = file_get_contents($settings_path);
166 $remote_settings = (array) json_decode(substr($remote_settings, 8));
167
168 if (!isset($remote_settings['identy'])) {
169 Logger::error('Identy is not set in the config, which prevents backup-process.php from running.');
170 return [];
171 }
172
173 if ($curl && $curlIdenty != $remote_settings['identy']) {
174 Logger::error('backup-process.php runs via CURL but the identy provided by CURL does not match config.');
175 return [];
176 }
177
178 return $remote_settings;
179 }
180
181 // Save remote setting for next batch
182 public function saveRemoteSettings() {
183 $settings_name = 'currentBackupConfig.' . 'php';
184 $settings_path = BMP::fixSlashes(BMI_TMP . DIRECTORY_SEPARATOR . $settings_name);
185
186 $this->remote_settings['identy'] = $this->identy;
187 $this->remote_settings['manifest'] = $this->manifest;
188 $this->remote_settings['backupname'] = $this->backupname;
189 $this->remote_settings['safelimit'] = $this->safelimit;
190 $this->remote_settings['total_files'] = $this->total_files;
191 $this->remote_settings['rev'] = $this->rev;
192 $this->remote_settings['start'] = $this->backupstart;
193 $this->remote_settings['filessofar'] = $this->filessofar;
194 $this->remote_settings['browser'] = $this->browserSide;
195 $this->remote_settings['it'] = $this->it;
196 $this->remote_settings['dbit'] = $this->dbit;
197 $this->remote_settings['dblast'] = $this->dblast;
198 $this->remote_settings['final_made'] = $this->final_made;
199 $this->remote_settings['final_batch'] = $this->final_batch;
200 $this->remote_settings['dbitJustFinished'] = $this->dbitJustFinished;
201 $this->remote_settings['startOfBatch'] = $this->startOfBatch;
202 $this->remote_settings['backupSize'] = $this->backupSize;
203
204 if (file_exists($settings_path)) @unlink($settings_path);
205 file_put_contents($settings_path, '<?php //' . json_encode($this->remote_settings));
206 }
207
208 // Setup constants and handle request
209 public function setupConstants() {
210
211 if (!defined('BMI_CURL_REQUEST')) define('BMI_CURL_REQUEST', true);
212 if (!defined('BMI_CLI_REQUEST')) define('BMI_CLI_REQUEST', false);
213 if (!defined('BMI_SAFELIMIT')) define('BMI_SAFELIMIT', intval($this->remote_settings['safelimit']));
214
215 if ($this->isFunctionEnabled('ignore_user_abort')) @ignore_user_abort(true);
216 if ($this->isFunctionEnabled('set_time_limit')) @set_time_limit(259200);
217 if ($this->isFunctionEnabled('ini_set') && $this->isFunctionEnabled('session_status') && session_status() != PHP_SESSION_ACTIVE) {
218 @ini_set('max_input_time', '259200');
219 @ini_set('max_execution_time', '259200');
220 }
221
222 if (!isset($this->remote_settings['browser'])) $this->remote_settings['browser'] = false;
223
224 // Don't block server handler
225 // if ($this->isFunctionEnabled('session_write_close')) @session_write_close();
226
227 }
228
229 // Make sure it's impossible to unlink some files
230 public function unlinksafe($path) {
231
232 if (substr($path, 0, 7) == 'file://') {
233 $path = substr($path, 7);
234 }
235
236 $path = realpath($path);
237 if ($path === false) return;
238 if (strpos($path, 'wp-config.php') !== false) return;
239 if (substr($path, -8) == '/backups') return;
240
241 @unlink('file://' . $path);
242
243 }
244
245 // Human size from bytes
246 public static function humanSize($bytes) {
247 if (is_int($bytes)) {
248 $label = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
249 for ($i = 0; $bytes >= 1024 && $i < (count($label) - 1); $bytes /= 1024, $i++);
250
251 return (round($bytes, 2) . " " . $label[$i]);
252 } else return $bytes;
253 }
254
255 // Create new process
256 public function send_beat($manual = false, &$logger = null) {
257
258 if ($this->beatSent) return;
259 $this->beatSent = true;
260
261 if (is_null($logger)) $this->load_logger();
262 else if ($logger instanceof Output) $this->output = $logger;
263
264 try {
265
266 $header = array(
267 'Content-Accept:*/*',
268 'Access-Control-Allow-Origin:*'
269 );
270
271 $this->saveRemoteSettings();
272 $c = curl_init();
273 curl_setopt($c, CURLOPT_POST, 1);
274 curl_setopt($c, CURLOPT_COOKIESESSION, false);
275 curl_setopt($c, CURLOPT_TIMEOUT, 20);
276 curl_setopt($c, CURLOPT_VERBOSE, false);
277 curl_setopt($c, CURLOPT_HEADER, false);
278 curl_setopt($c, CURLOPT_URL, $this->url);
279 curl_setopt($c, CURLOPT_FOLLOWLOCATION, 1);
280 curl_setopt($c, CURLOPT_MAXREDIRS, 10);
281 curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
282 curl_setopt($c, CURLOPT_SSL_VERIFYHOST, 0);
283 curl_setopt($c, CURLOPT_SSL_VERIFYPEER, 0);
284 curl_setopt($c, CURLOPT_HTTPHEADER, $header);
285 curl_setopt($c, CURLOPT_CUSTOMREQUEST, 'POST');
286 curl_setopt($c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
287 curl_setopt($c, CURLOPT_USERAGENT, $this->useragent);
288
289 $r = curl_exec($c);
290
291 if ($manual === true && $logger !== null) {
292 if ($r === false) {
293 if (intval(curl_errno($c)) !== 28) {
294 Logger::error(print_r(curl_getinfo($c), true));
295 Logger::error(curl_errno($c) . ': ' . curl_error($c));
296 $this->output->log('There was something wrong with the request:', 'WARN');
297 $this->output->log(curl_errno($c) . ': ' . curl_error($c), 'WARN');
298 }
299 } else {
300 $this->output->log('Request sent successfully, without error returned.', 'SUCCESS');
301 }
302 }
303
304 curl_close($c);
305 if (isset($this->output)) $this->output->end();
306
307 } catch (\Exception $e) {
308
309 error_log($e->getMessage());
310 $this->output->log($e->getMessage(), 'ERROR');
311 if (isset($this->output)) $this->output->end();
312
313 } catch (\Throwable $e) {
314
315 error_log($e->getMessage());
316 $this->output->log($e->getMessage(), 'ERROR');
317 if (isset($this->output)) $this->output->end();
318
319 }
320
321 }
322
323 // Load backup logger
324 public function load_logger() {
325
326 if ($this->output instanceof Output) return;
327
328 require_once BMI_INCLUDES . '/logger.php';
329 require_once BMI_INCLUDES . '/progress/logger-only.php';
330
331 $this->output = new Output();
332 $this->output->start();
333
334 }
335
336 // Remove common files
337 public function remove_commons() {
338
339 if (is_null($this->fileList)) return;
340
341 // Remove list if exists
342 $identyfile = $this->identyfile;
343 $logfile = BMI_TMP . DIRECTORY_SEPARATOR . 'bmi_logs_this_backup.log';
344 $clidata = BMI_TMP . DIRECTORY_SEPARATOR . 'bmi_cli_data.json';
345 $settings_path = BMI_TMP . DIRECTORY_SEPARATOR . 'currentBackupConfig.php';
346 if (file_exists($this->fileList)) $this->unlinksafe($this->fileList);
347 if (file_exists($this->dbfile)) $this->unlinksafe($this->dbfile);
348 if (file_exists($this->manifest)) $this->unlinksafe($this->manifest);
349 if (file_exists($logfile)) $this->unlinksafe($logfile);
350 if (file_exists($clidata)) $this->unlinksafe($clidata);
351 if (file_exists($identyfile)) $this->unlinksafe($identyfile);
352 if (file_exists($identyfile . '-running')) $this->unlinksafe($identyfile . '-running');
353 if (file_exists($this->lock_cli)) $this->unlinksafe($this->lock_cli);
354 if (file_exists($settings_path)) $this->unlinksafe($settings_path);
355
356 // Remove backup
357 if (file_exists(BMI_BACKUPS . '/.running')) $this->unlinksafe(BMI_BACKUPS . '/.running');
358 if (file_exists(BMI_BACKUPS . '/.space_check')) $this->unlinksafe(BMI_BACKUPS . '/.space_check');
359 if (file_exists(BMI_BACKUPS . '/.abort')) $this->unlinksafe(BMI_BACKUPS . '/.abort');
360 if (file_exists(BMI_BACKUPS . '/.last_triggered')) $this->unlinksafe(BMI_BACKUPS . '/.last_triggered');
361
362 // Remove group folder
363 if (file_exists($this->identyFolder)) {
364 $files = glob($this->identyFolder . '/*');
365 foreach ($files as $file) if (is_file($file)) $this->unlinksafe($file);
366 @rmdir($this->identyFolder);
367 }
368
369 // Remove tmp database files
370 if (file_exists($this->db_dir_v2) && is_dir($this->db_dir_v2)) {
371 $files = glob($this->db_dir_v2 . '/*');
372 foreach ($files as $file) if (is_file($file)) $this->unlinksafe($file);
373 if (is_dir($this->db_dir_v2)) @rmdir($this->db_dir_v2);
374 }
375
376 }
377
378 // Make success
379 public function send_success() {
380
381 $this->load_logger();
382
383 // Display the success
384 $this->output->log('Backup completed successfully!', 'SUCCESS');
385 $this->output->log('#001', 'END-CODE');
386
387 // Remove common files
388 $this->remove_commons();
389
390 // End logger
391 if (isset($this->output)) @$this->output->end();
392
393 $this->actionsAfterProcess(true);
394 $this->it += 1;
395
396 // Set header for browser
397 if ($this->browserSide) {
398
399 // Content finished
400 $this->sendResponse(true);
401
402 }
403
404 // End the process
405 exit;
406
407 }
408
409 // Make error
410 public function send_error($reason = false, $abort = false) {
411
412 if ($this->errorSent) return;
413 $this->errorSent = true;
414
415 $this->load_logger();
416
417 // Log error
418 $this->output->log('Something went wrong with background process... ' . '(part: ' . $this->it . ')', 'ERROR');
419 if ($reason !== false) $this->output->log('Reason: ' . $reason, 'ERROR');
420 $this->output->log('Removing backup files... ', 'ERROR');
421
422 // Remove common files
423 $this->remove_commons();
424
425 // Remove backup
426 if (file_exists(BMI_BACKUPS . DIRECTORY_SEPARATOR . $this->backupname)) $this->unlinksafe(BMI_BACKUPS . DIRECTORY_SEPARATOR . $this->backupname);
427
428 // Abort step
429 $this->output->log('Aborting backup... ', 'STEP');
430 if ($abort === false) $this->output->log('#002', 'END-CODE');
431 else $this->output->log('#004', 'END-CODE');
432 if (isset($this->output)) @$this->output->end();
433
434 $this->actionsAfterProcess();
435 $this->it += 1;
436
437 // Set header for browser
438 if ($this->browserSide) {
439
440 // Content finished
441 $this->sendResponse(false, true);
442
443 }
444 exit;
445
446 }
447
448 // Group files for batches
449 public function make_file_groups() {
450
451 if (!(file_exists($this->fileList) && is_readable($this->fileList))) {
452 return $this->send_error('File list is not accessible or does not exist, try to run your backup process once again.', true);
453 }
454
455 $this->output->log('Making batches for each process...', 'STEP');
456 $list_path = $this->fileList;
457
458 $file = fopen($list_path, 'r');
459 $this->output->log('Reading list file...', 'INFO');
460 $first_line = explode('_', fgets($file));
461 $files = intval($first_line[0]);
462 $firstmax = intval($first_line[1]);
463
464 if ($files > 0) {
465 $batches = 100;
466 if ($files <= 200) $batches = 100;
467 if ($files > 200) $batches = 400;
468 if ($files > 1600) $batches = 600;
469 if ($files > 3200) $batches = 1000;
470 if ($files > 6400) $batches = 2000;
471 if ($files > 12800) $batches = 4000;
472 if ($files > 25600) $batches = 5000;
473 if ($files > 30500) $batches = 10000;
474 if ($files > 60500) $batches = 20000;
475 if ($files > 90500) $batches = 40000;
476 if ($files > 100000) $batches = 60000;
477 if ($files > 150000) $batches = 80000;
478
479 $this->output->log('Each batch will contain up to ' . $batches . ' files.', 'INFO');
480 $this->output->log('Large files takes more time, you will be notified about those.', 'INFO');
481
482 $folder = $this->identyFolder;
483 if (!(file_exists($folder) && is_dir($file))) {
484 @mkdir($folder, 0755, true);
485 }
486
487 $limitcrl = 96;
488 if (BMI_CLI_REQUEST === true) {
489 $limitcrl = 512;
490 if ($files > 30000) $limitcrl = 1024;
491 }
492
493 $i = 0; $bigs = 0; $prev = 0; $currsize = 0;
494 while (($line = fgets($file)) !== false) {
495
496 $line = explode(',', $line);
497 $last = sizeof($line) - 1;
498 $size = intval($line[$last]);
499 unset($line[$last]);
500 $line = implode(',', $line);
501
502 $i++;
503 if ($firstmax != -1 && $i > $firstmax) $bigs++;
504 $suffix = intval(ceil(abs($i / $batches))) + $bigs;
505
506 if ($prev == $suffix) {
507 $currsize += $size;
508 } else {
509 $currsize = $size;
510 $prev = $suffix;
511 }
512
513 $skip = false;
514 if ($currsize > ($limitcrl * (1024 * 1024))) $skip = true;
515
516 $groupFile = $folder . DIRECTORY_SEPARATOR . $this->identy . '-' . $suffix . '.files';
517 $group = fopen($groupFile, 'a');
518 fwrite($group, $line . ',' . $size . "\r\n");
519 fclose($group);
520
521 if ($skip === true) $bigs++;
522 unset($line);
523
524 }
525
526 fclose($file);
527 if (file_exists($this->fileList)) $this->unlinksafe($this->fileList);
528
529 } else {
530
531 $this->output->log('No file found to be backed up, omitting files.', 'INFO');
532
533 }
534
535 if (file_exists($this->fileList)) $this->unlinksafe($this->fileList);
536 $this->output->log('Batches completed...', 'SUCCESS');
537
538 }
539
540 // Final batch
541 public function get_final_batch() {
542
543 $db_root_dir = BMI_TMP . DIRECTORY_SEPARATOR;
544 $logs = $db_root_dir . 'bmi_logs_this_backup.log';
545 $_manifest = $this->manifest;
546
547 if (strpos($logs, 'file://') !== false) $logs = substr($logs, 7);
548 if (strpos($_manifest, 'file://') !== false) $_manifest = substr($_manifest, 7);
549
550 $log_file = fopen($logs, 'w');
551 fwrite($log_file, file_get_contents(BMI_BACKUPS . DIRECTORY_SEPARATOR . 'latest.log'));
552 fclose($log_file);
553 $files = [$logs, $_manifest];
554
555 return $files;
556
557 }
558
559 // Final logs
560 public function log_final_batch() {
561
562 $this->output->log('Finalizing backup', 'STEP');
563 $this->output->log('Closing files and archives', 'STEP');
564 $this->output->log('Archiving of ' . $this->total_files . ' files took: ' . number_format(microtime(true) - floatval($this->backupstart), 2) . 's', 'INFO');
565
566 if (!BMI_CLI_REQUEST) {
567 if (!$this->browserSide) sleep(1);
568 }
569
570 if (file_exists(BMI_BACKUPS . '/.abort')) {
571 $this->send_error('Backup aborted manually by user.', true);
572 return;
573 }
574
575 $this->send_success();
576
577 }
578
579 // Load batch
580 public function load_batch() {
581
582 if (!(file_exists($this->identyFolder) && is_dir($this->identyFolder))) {
583 return $this->send_error('Temporary directory does not exist, please start the backup once again.', true);
584 }
585
586 $allFiles = scandir($this->identyFolder);
587 $files = array_slice((array) $allFiles, 2);
588 if (sizeof($files) > 0) {
589
590 $largest = $files[0]; $prev_size = 0;
591 for ($i = 0; $i < sizeof($files); ++$i) {
592 $curr_size = filesize($this->identyFolder . DIRECTORY_SEPARATOR . $files[$i]);
593 if ($curr_size > $prev_size) {
594 $largest = $files[$i];
595 $prev_size = $curr_size;
596 }
597 }
598 $this->batches_left = sizeof($files);
599
600 if (sizeof($files) == 1) {
601 $this->final_batch = true;
602 }
603
604 return $this->identyFolder . DIRECTORY_SEPARATOR . $largest;
605
606 } else {
607
608 $this->log_final_batch();
609 return false;
610
611 }
612
613 }
614
615 // Cut Path for ZIP structure
616 public function cutDir($file) {
617
618 if (substr($file, -4) === '.sql') {
619
620 if ($this->db_v2_engine == true) {
621
622 $path = 'db_tables' . DIRECTORY_SEPARATOR . basename($file);
623
624 } else {
625
626 $path = basename($file);
627
628 }
629
630 } else {
631
632 $path = basename($file);
633
634 }
635
636 $path = str_replace('\\', '/', $path);
637 return $path;
638
639 }
640
641 // Add files to ZIP – The Backup
642 public function add_files($files = [], $file_list = false, $final = false, $dbLog = false) {
643
644 try {
645
646 $zipArchive = false;
647 if (class_exists('\ZipArchive') || class_exists('ZipArchive')) {
648 if (!isset($this->_zip)) {
649 $this->_zip = new \ZipArchive();
650 }
651
652 if ($this->_zip) {
653 $zipArchive = true;
654 } else {
655 $zipArchive = false;
656 }
657 }
658
659 // Check if PclZip exists
660 if ($zipArchive === false) {
661 if (!class_exists('PclZip')) {
662 if (!defined('PCLZIP_TEMPORARY_DIR')) {
663 $bmi_tmp_dir = BMI_TMP;
664 if (!file_exists($bmi_tmp_dir)) {
665 @mkdir($bmi_tmp_dir, 0775, true);
666 }
667
668 define('PCLZIP_TEMPORARY_DIR', $bmi_tmp_dir . DIRECTORY_SEPARATOR . 'bmi-');
669 }
670
671 if (!defined('PCLZIP_READ_BLOCK_SIZE')) {
672 define('PCLZIP_READ_BLOCK_SIZE', 32768);
673 }
674 }
675
676 // Require the LIB and check if it's compatible
677 $alternative = dirname($this->dir) . '/backup-backup-pro/includes/pcl.php';
678 if ($this->rev === 2 || !file_exists($alternative)) {
679 require_once ABSPATH . 'wp-admin/includes/class-pclzip.php';
680 } else {
681 require_once $alternative;
682 if ($this->it === 1) {
683 $this->output->log('Using dedicated PclZIP for Premium Users.', 'INFO');
684 if ($dbLog == true) {
685 $this->output->log('Adding database SQL file(s) to the backup file.', 'STEP');
686 }
687 }
688 }
689
690 // Get/Create the Archive
691 if (!isset($this->_lib)) {
692 $this->_lib = new \PclZip(BMI_BACKUPS . DIRECTORY_SEPARATOR . $this->backupname);
693 }
694
695 if (!$this->_lib) {
696 $this->send_error('PHP-ZIP: Permission Denied or zlib cannot be found');
697 return;
698 }
699
700 } else {
701
702 $backupPath = BMI_BACKUPS . DIRECTORY_SEPARATOR . $this->backupname;
703 if (BMI_CLI_REQUEST) {
704 if (!isset($this->zip_initialized)) {
705 if (file_exists($backupPath)) $this->_zip->open($backupPath);
706 else $this->_zip->open($backupPath, \ZipArchive::CREATE);
707 }
708 } else {
709 if (file_exists($backupPath)) $this->_zip->open($backupPath);
710 else $this->_zip->open($backupPath, \ZipArchive::CREATE);
711 }
712
713 if ($this->it === 1) {
714 $this->output->log('Using ZipArchive extension for this backup process.', 'INFO');
715 if ($dbLog == true) {
716 $this->output->log('Adding database SQL file(s) to the backup file.', 'STEP');
717 }
718 }
719
720 }
721
722 if (sizeof($files) <= 0) {
723 return false;
724 }
725
726 $back = 0;
727 $files = array_filter($files, function ($path) {
728 if (is_readable($path) && file_exists($path) && !is_link($path)) return true;
729 else {
730 $this->output->log("Excluding file that cannot be read: " . $path, 'warn');
731 return false;
732 }
733 });
734
735 $_abspath = ABSPATH;
736 $_bmi_tmp = BMI_TMP;
737 $_wp_content = WP_CONTENT_DIR;
738 if (strpos($_abspath, 'file://') !== false) $_abspath = substr($_abspath, 7);
739 if (strpos($_bmi_tmp, 'file://') !== false) $_bmi_tmp = substr($_bmi_tmp, 7);
740 if (strpos($_wp_content, 'file://') !== false) $_wp_content = substr($_wp_content, 7);
741
742 $needManipulation = false;
743 if ( strpos($_wp_content, $_abspath) === false ) {
744 $needManipulation = true;
745 }
746
747 // Add files
748 if ($final || $dbLog) {
749
750 if ($zipArchive) {
751 for ($i = 0; $i < sizeof($files); ++$i) {
752
753 // Add the file
754 if (is_dir($files[$i])) {
755 $this->_zip->addEmptyDir($this->cutDir($files[$i]));
756 } else {
757 $this->_zip->addFile($files[$i], $this->cutDir($files[$i]));
758 }
759
760 }
761 } else {
762
763 // Final configuration
764 if (sizeof($files) > 0) {
765 $back = $this->_lib->add($files, PCLZIP_OPT_REMOVE_PATH, $_bmi_tmp . DIRECTORY_SEPARATOR, PCLZIP_OPT_ADD_TEMP_FILE_ON, PCLZIP_OPT_TEMP_FILE_THRESHOLD, $this->safelimit);
766 }
767
768 }
769
770 if ($dbLog === false) {
771 $this->final_made = true;
772 }
773
774 } else {
775
776 if ($zipArchive) {
777
778 for ($i = 0; $i < sizeof($files); ++$i) {
779
780 if ($needManipulation) {
781 if (strpos($files[$i], $_wp_content) !== false) {
782 $path = 'wordpress' . DIRECTORY_SEPARATOR . 'wp-content' . DIRECTORY_SEPARATOR . substr($files[$i], strlen($_wp_content));
783 } else {
784 $path = 'wordpress' . DIRECTORY_SEPARATOR . substr($files[$i], strlen($_abspath));
785 }
786 } else {
787 $path = 'wordpress' . DIRECTORY_SEPARATOR . substr($files[$i], strlen($_abspath));
788 }
789
790 $path = BMP::fixSlashes($path);
791
792 // Add the file
793 if (is_dir($files[$i])) {
794 $this->_zip->addEmptyDir($path);
795 } else {
796 $this->_zip->addFile($files[$i], $path);
797 }
798
799 }
800
801 } else {
802
803 if ($needManipulation) {
804 $coreFiles = [];
805 $contentFiles = [];
806 foreach ($files as $file) {
807 if (strpos($file, $_wp_content) !== false) {
808 $contentFiles[] = $file;
809 } else {
810 $coreFiles[] = $file;
811 }
812 }
813
814 $back_1 = $this->_lib->add($coreFiles, PCLZIP_OPT_REMOVE_PATH, $_abspath, PCLZIP_OPT_ADD_PATH, 'wordpress' . DIRECTORY_SEPARATOR, PCLZIP_OPT_ADD_TEMP_FILE_ON, PCLZIP_OPT_TEMP_FILE_THRESHOLD, $this->safelimit);
815 $back_2 = $this->_lib->add($contentFiles, PCLZIP_OPT_REMOVE_PATH, $_wp_content, PCLZIP_OPT_ADD_PATH, 'wordpress' . DIRECTORY_SEPARATOR . 'wp-content' . DIRECTORY_SEPARATOR, PCLZIP_OPT_ADD_TEMP_FILE_ON, PCLZIP_OPT_TEMP_FILE_THRESHOLD, $this->safelimit);
816 $back = $back_1 && $back_2;
817
818 } else {
819 $back = $this->_lib->add($files, PCLZIP_OPT_REMOVE_PATH, $_abspath, PCLZIP_OPT_ADD_PATH, 'wordpress' . DIRECTORY_SEPARATOR, PCLZIP_OPT_ADD_TEMP_FILE_ON, PCLZIP_OPT_TEMP_FILE_THRESHOLD, $this->safelimit);
820 }
821
822 }
823
824 }
825
826 // Check if there was any error
827 touch(BMI_BACKUPS . '/.running');
828 if ($zipArchive) {
829 if (!BMI_CLI_REQUEST || $final) {
830 $result = $this->_zip->close();
831
832 if ($result === true) {
833
834 // Remove batch
835 if ($file_list && file_exists($file_list)) {
836 $this->unlinksafe($file_list);
837 }
838
839 } else {
840 $this->output->log('not_enough_space', 'verbose');
841
842 $this->send_error('Error, there is most likely not enough space for the backup.');
843 return false;
844
845 }
846 } else {
847
848 // Remove batch
849 if ($file_list && file_exists($file_list)) {
850 $this->unlinksafe($file_list);
851 }
852
853 }
854 } else {
855
856 if ($back == 0) {
857
858 $this->send_error($this->_lib->errorInfo(true));
859 return false;
860
861 } else {
862
863 if ($file_list && file_exists($file_list)) {
864 $this->unlinksafe($file_list);
865 }
866
867 }
868
869 }
870
871 } catch (\Exception $e) {
872
873 error_log($e->getMessage());
874 $this->send_error($e->getMessage());
875 return false;
876
877 } catch (\Throwable $e) {
878
879 error_log($e->getMessage());
880 $this->send_error($e->getMessage());
881 return false;
882
883 }
884
885 }
886
887 // ZIP one of the grouped files
888 public function zip_batch() {
889
890 $_dbfile = $this->dbfile;
891 $_db_dir_v2 = $this->db_dir_v2;
892 if (strpos($_dbfile, 'file://') !== false) $_dbfile = substr($_dbfile, 7);
893 if (strpos($_db_dir_v2, 'file://') !== false) $_db_dir_v2 = substr($_db_dir_v2, 7);
894
895 if ($this->it === 1) {
896
897 $files = [];
898 if (file_exists($this->dbfile)) {
899 $files[] = $_dbfile;
900 } elseif (file_exists($this->db_dir_v2) && is_dir($this->db_dir_v2)) {
901 $this->db_v2_engine = true;
902 $db_files = scandir($this->db_dir_v2);
903 foreach ($db_files as $i => $name) {
904 if (!($name == '.' || $name == '..')) {
905 $files[] = $_db_dir_v2 . DIRECTORY_SEPARATOR . $name;
906 }
907 }
908 }
909
910 if (sizeof($files) > 0) {
911 $this->add_files($files, false, false, true);
912 $this->output->log('Database added to the backup file.', 'SUCCESS');
913 $this->output->log('Performing site files backup...', 'STEP');
914 return true;
915 }
916
917 $this->output->log('Performing site files backup...', 'STEP');
918
919 }
920
921 $list_file = $this->load_batch();
922 if ($list_file === false) return true;
923 $files = explode("\r\n", file_get_contents($list_file));
924
925 $total_size = 0;
926 $parsed_files = [];
927
928 $absWo = ABSPATH;
929 $wpcDirWo = WP_CONTENT_DIR;
930
931 if (strpos($absWo, 'file://') !== false) $absWo = substr(ABSPATH, 7);
932 if (strpos($wpcDirWo, 'file://') !== false) $wpcDirWo = substr(WP_CONTENT_DIR, 7);
933
934 for ($i = 0; $i < sizeof($files); ++$i) {
935 if (strlen(trim($files[$i])) <= 1) {
936 $this->total_files--;
937 continue;
938 }
939
940 $files[$i] = explode(',', $files[$i]);
941 $last = sizeof($files[$i]) - 1;
942 $size = intval($files[$i][$last]);
943 unset($files[$i][$last]);
944 $files[$i] = implode(',', $files[$i]);
945
946 $file = null;
947 if ($files[$i][0] . $files[$i][1] . $files[$i][2] === '@1@') {
948 $file = $wpcDirWo . DIRECTORY_SEPARATOR . substr($files[$i], 3);
949 } else if ($files[$i][0] . $files[$i][1] . $files[$i][2] === '@2@') {
950 $file = $absWo . DIRECTORY_SEPARATOR . substr($files[$i], 3);
951 } else {
952 $file = $files[$i];
953 }
954
955 if (!file_exists($file)) {
956 $this->output->log('Removing this file from backup (it does not exist anymore): ' . $file, 'WARN');
957 $this->total_files--;
958 continue;
959 }
960
961 // if (filesize($file) === 0) {
962 // $this->output->log('Removing this file from backup (file size is equal to 0 bytes): ' . $file, 'WARN');
963 // $this->total_files--;
964 // continue;
965 // }
966
967 $parsed_files[] = $file;
968 $total_size += $size;
969 unset($file);
970 }
971
972 unset($files);
973 if (sizeof($parsed_files) === 1) {
974 $this->output->log('Adding: ' . sizeof($parsed_files) . ' file...' . ' [Size: ' . $this->humanSize($total_size) . ']', 'INFO');
975 $this->output->log('Alone-file mode for: ' . $parsed_files[0] . ' file...', 'INFO');
976 } else $this->output->log('Adding: ' . sizeof($parsed_files) . ' files...' . ' [Size: ' . $this->humanSize($total_size) . ']', 'INFO');
977
978 if ((60 * (1024 * 1024)) < $total_size) $this->output->log('Current batch is quite large, it may take some time...', 'WARN');
979
980 $this->add_files($parsed_files, $list_file);
981 $this->filessofar += sizeof($parsed_files);
982
983 $currentBackupSize = filesize(BMI_BACKUPS . DIRECTORY_SEPARATOR . $this->backupname);
984 $this->output->progress($this->filessofar . '/' . $this->total_files);
985 $this->output->log('Milestone: ' . $this->filessofar . '/' . $this->total_files . ' [' . $this->batches_left . ' batches left]', 'SUCCESS');
986 $this->output->log('Backup file size: ' . $this->humanSize($currentBackupSize), 'VERBOSE');
987 $this->output->log('Time since last batch: ' . (time() - $this->startOfBatch) . ' seconds.', 'VERBOSE');
988 $this->startOfBatch = time();
989
990 if ($this->backupSize > $currentBackupSize)
991 return $this->send_error('Backup size is smaller than it should be, it has been damaged, it may not be restorable, abort recommended.', true);
992
993 $this->backupSize = $currentBackupSize;
994
995 if ($this->final_batch === true) {
996 $this->output->log('Adding final files to this batch...', 'STEP');
997 $this->output->log('Adding manifest as addition...', 'INFO');
998
999 $additionalFiles = $this->get_final_batch();
1000 $this->add_files($additionalFiles, false, true);
1001 $this->log_final_batch();
1002 return true;
1003 }
1004
1005 }
1006
1007 // Shutdown callback
1008 public function shutdown() {
1009
1010 if ($this->shutdownAlreadyInited) return;
1011 $this->shutdownAlreadyInited = true;
1012
1013 // Check if there was any error
1014 $err = error_get_last();
1015 if ($err != null) {
1016 Logger::error('Shuted down');
1017 Logger::error(print_r($err, true));
1018 $this->output->log('Background process had some issues, more details printed to global logs.', 'WARN');
1019 }
1020
1021 // Remove lock
1022 if (BMI_CLI_REQUEST && $this->lock_cli && file_exists($this->lock_cli)) {
1023 $this->unlinksafe($this->lock_cli);
1024 }
1025
1026 // Send next beat to handle next batch
1027 if (BMI_CLI_REQUEST) {
1028 $this->res = [ 'status' => 'success' ];
1029 return true;
1030 }
1031
1032 if (file_exists($this->identyfile)) {
1033
1034 // Set header for browser
1035 if ($this->browserSide) {
1036
1037 $this->saveRemoteSettings();
1038
1039 // Content finished
1040 $this->sendResponse(false);
1041
1042 } else {
1043
1044 $this->send_beat();
1045
1046 }
1047
1048 } else {
1049 if (!$this->statusSent && !isset($GLOBALS['BMI::RESPONSE::SENT'])) {
1050 $this->statusSent = true;
1051 return BMP::res([ 'status' => 'success' ]);
1052 }
1053 }
1054
1055 }
1056
1057 public function sendResponse($finish = false, $error = false) {
1058 $res = [
1059 'status' => 'success',
1060 'backup_completed' => (($finish == true) ? 'true' : 'false'),
1061 'backup_process_error' => (($error == true) ? 'true' : 'false')
1062 ];
1063
1064 if ($error == true)
1065 $res['status'] = 'error';
1066
1067 $this->res = $res;
1068
1069 if (!$this->statusSent && !isset($GLOBALS['BMI::RESPONSE::SENT'])) {
1070 $this->statusSent = true;
1071 BMP::res($res);
1072 }
1073
1074 return $res;
1075 }
1076
1077 // Handle received batch
1078 public function handle_batch() {
1079
1080 // Check if aborted
1081 if (file_exists(BMI_BACKUPS . '/.abort')) {
1082 if (!isset($this->output)) $this->load_logger();
1083 $this->res = [ 'status' => 'error' ];
1084 $this->send_error('Backup aborted manually by user.', true);
1085 return;
1086 }
1087
1088 // Check if it was triggered by verified user
1089 if (!file_exists($this->identyfile)) {
1090 $this->res = [ 'status' => 'error' ];
1091 return;
1092 }
1093
1094 // Register shutdown
1095 register_shutdown_function([$this, 'shutdown']);
1096
1097 // Load logger
1098 $this->load_logger();
1099
1100 set_error_handler(function ($errno, $errstr, $errfile, $errline) {
1101 Logger::error('Bypasser error:');
1102 Logger::error($errno . ' - ' . $errstr);
1103 Logger::error($errfile . ' - ' . $errline);
1104
1105 $this->load_logger();
1106 $this->output->log('Bypasser error:', 'ERROR');
1107 $this->output->log($errno . ' - ' . $errstr, 'ERROR');
1108 $this->output->log($errfile . ' - ' . $errline, 'ERROR');
1109
1110 $this->res = [ 'status' => 'error' ];
1111 return;
1112 }, E_ERROR);
1113
1114 // Notice parent script
1115 touch($this->identyfile . '-running');
1116 touch(BMI_BACKUPS . '/.running');
1117
1118 // CLI case
1119 if (BMI_CLI_REQUEST) {
1120
1121 $this->output->log('Starting database backup exporter', 'STEP');
1122 $this->output->log('Database exporter started via CLI', 'VERBOSE');
1123 while ($this->dbit !== -1) {
1124 $this->databaseBackupMaker();
1125 }
1126
1127 // Log
1128 $this->output->log("PHP CLI initialized - process ran successfully", 'SUCCESS');
1129 $this->make_file_groups();
1130
1131 // Make ZIP
1132 $this->output->log('Making archive...', 'STEP');
1133 while (!$this->final_made) {
1134 touch($this->identyfile . '-running');
1135 touch(BMI_BACKUPS . '/.running');
1136 $this->it += 1;
1137 $this->zip_batch();
1138 }
1139
1140 } else {
1141
1142 // Background
1143 if ($this->dbit !== -1) {
1144
1145 if ($this->dbit === 0) {
1146 $this->output->log('Background process initialized', 'SUCCESS');
1147 $this->output->log('Starting database backup exporter', 'STEP');
1148 $this->output->log('Database exporter started via WEB REQUESTS', 'VERBOSE');
1149 }
1150
1151 $this->databaseBackupMaker();
1152 return $this->res;
1153
1154 } else {
1155
1156 if ($this->it === 0) {
1157
1158 $this->make_file_groups();
1159 $this->it += 1;
1160 $this->output->log('Making archive...', 'STEP');
1161
1162 } else {
1163
1164 $this->zip_batch();
1165 $this->it += 1;
1166
1167 }
1168
1169 }
1170
1171 }
1172
1173 }
1174
1175 public function fixSlashes($str, $slash = false) {
1176 // Old version
1177 // $str = str_replace('\\\\', DIRECTORY_SEPARATOR, $str);
1178 // $str = str_replace('\\', DIRECTORY_SEPARATOR, $str);
1179 // $str = str_replace('\/', DIRECTORY_SEPARATOR, $str);
1180 // $str = str_replace('/', DIRECTORY_SEPARATOR, $str);
1181
1182 // if ($str[strlen($str) - 1] == DIRECTORY_SEPARATOR) {
1183 // $str = substr($str, 0, -1);
1184 // }
1185
1186 // Since 1.3.2
1187 $protocol = '';
1188 if ($slash == false) $slash = DIRECTORY_SEPARATOR;
1189 if (substr($str, 0, 7) == 'http://') $protocol = 'http://';
1190 else if (substr($str, 0, 8) == 'https://') $protocol = 'https://';
1191
1192 $str = substr($str, strlen($protocol));
1193 $str = preg_replace('/[\\\\\/]+/', $slash, $str);
1194 $str = rtrim($str, '/\\' );
1195
1196 return $protocol . $str;
1197 }
1198
1199 public function isFunctionEnabled($func) {
1200 $disabled = explode(',', ini_get('disable_functions'));
1201 $isDisabled = in_array($func, $disabled);
1202 if (!$isDisabled && function_exists($func)) return true;
1203 else return false;
1204 }
1205
1206 // Database batch maker and dumper
1207 // We need WP instance for that to get access to wpdb
1208 public function databaseBackupMaker() {
1209
1210 if ($this->dbit === -1) {
1211 $this->res = [ 'status' => 'error' ];
1212 return;
1213 }
1214
1215 // DB File Name for that type of backup
1216 $dbbackupname = 'bmi_database_backup.sql';
1217 $database_file = $this->fixSlashes(BMI_TMP . DIRECTORY_SEPARATOR . $dbbackupname);
1218 $shouldBackupDB = apply_filters('bmip_database_backup', Dashboard\bmi_get_config('BACKUP:DATABASE') == 'true');
1219 if ( $shouldBackupDB ) {
1220
1221 if (Dashboard\bmi_get_config('OTHER:BACKUP:DB:SINGLE:FILE') == 'true') {
1222
1223 // Require Database Manager
1224 require_once BMI_INCLUDES . DIRECTORY_SEPARATOR . 'database' . DIRECTORY_SEPARATOR . 'manager.php';
1225
1226 // Log what's going on
1227 $this->output->log('Making single-file database backup (using deprecated engine, due to used settings)', 'STEP');
1228
1229 // Get database dump
1230 $databaser = new Database(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);
1231 $databaser->exportDatabase($dbbackupname);
1232 $this->output->log("Database size: " . $this->humanSize(filesize($database_file)), 'INFO');
1233 $this->output->log('Database (single-file) backup finished.', 'SUCCESS');
1234
1235 $this->dbitJustFinished = true;
1236 $this->dbit = -1;
1237
1238 $this->res = [ 'status' => 'success' ];
1239 return true;
1240
1241 } else {
1242
1243 // Log what's going on
1244 if ($this->dbit === 0) {
1245 $this->output->log("Making database backup (using v3 engine, requires at least v1.2.2 to restore)", 'STEP');
1246 $this->output->log("Iterating database...", 'INFO');
1247 }
1248
1249 // Require Database Manager
1250 require_once BMI_INCLUDES . DIRECTORY_SEPARATOR . 'database' . DIRECTORY_SEPARATOR . 'better-backup-v3.php';
1251
1252 $database_file_dir = $this->fixSlashes((dirname($database_file))) . DIRECTORY_SEPARATOR;
1253 $better_database_files_dir = $database_file_dir . 'db_tables';
1254 $better_database_files_dir = str_replace('file:', 'file://', $better_database_files_dir);
1255
1256 if (!is_dir($better_database_files_dir)) @mkdir($better_database_files_dir, 0755, true);
1257 $db_exporter = new BetterDatabaseExport($better_database_files_dir, $this->output, $this->dbit, intval($this->backupstart));
1258
1259 $dbBatchingEnabled = false;
1260 if (Dashboard\bmi_get_config('OTHER:BACKUP:DB:BATCHING') == 'true') {
1261 $dbBatchingEnabled = true;
1262 } else {
1263 if ($this->dbit === 0) {
1264 $this->output->log("Database batching is disabled in options, consider to use this option if your database backup fails.", 'WARN');
1265 }
1266 }
1267
1268 if (BMI_CLI_REQUEST === true || $dbBatchingEnabled === false) {
1269
1270 $results = $db_exporter->export();
1271
1272 $this->output->log("Database backup finished", 'SUCCESS');
1273 $this->dbitJustFinished = true;
1274 $this->dbit = -1;
1275 $this->dblast = 0;
1276
1277 } else {
1278
1279 $results = $db_exporter->export($this->dbit, $this->dblast);
1280
1281 $this->dbit = intval($results['batchingStep']);
1282 $this->dblast = intval($results['finishedQuery']);
1283 $dbFinished = $results['dumpCompleted'];
1284
1285 if ($dbFinished == true) {
1286 $this->output->log("Database backup finished", 'SUCCESS');
1287 $this->dbitJustFinished = true;
1288 $this->dbit = -1;
1289 }
1290
1291 }
1292
1293 $this->res = [ 'status' => 'success' ];
1294 return true;
1295
1296 }
1297
1298 } else {
1299
1300 $this->output->log('Database will not be dumped due to user settings.', 'INFO');
1301 $this->dbitJustFinished = true;
1302 $this->dbit = -1;
1303
1304 $this->res = [ 'status' => 'success' ];
1305 return true;
1306
1307 }
1308
1309 }
1310
1311 public function actionsAfterProcess($success = false) {
1312 if ($success == true) {
1313 Logger::log("Backup file created successfully via backup-process.php");
1314 BMP::handle_after_cron();
1315 } else {
1316 Logger::log("Backup file creation failed via backup-process.php");
1317 }
1318
1319 if (has_action('bmi_premium_after_process') || (defined('BACKUP_TRIGGERED_BY_URL') && BACKUP_TRIGGERED_BY_URL === true)){
1320 do_action('bmi_premium_after_process', $success, 'backup', defined('BACKUP_TRIGGERED_BY_URL') && BACKUP_TRIGGERED_BY_URL === true);
1321 }
1322
1323 return null;
1324
1325 }
1326
1327 public function __destruct() {
1328 $this->shutdown();
1329 }
1330
1331 }
1332