GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Passed
Branch dev (231e41)
by Liuta
03:38
created

Xcloner_Archive::start_incremental_backup()   F

Complexity

Conditions 29
Paths > 20000

Size

Total Lines 231

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 29
nc 60608
nop 3
dl 0
loc 231
rs 0
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * XCloner - Backup and Restore backup plugin for Wordpress
4
 *
5
 * class-xcloner-archive.php
6
 * @author Liuta Ovidiu <[email protected]>
7
 *
8
 *        This program is free software; you can redistribute it and/or modify
9
 *        it under the terms of the GNU General Public License as published by
10
 *        the Free Software Foundation; either version 2 of the License, or
11
 *        (at your option) any later version.
12
 *
13
 *        This program is distributed in the hope that it will be useful,
14
 *        but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 *        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 *        GNU General Public License for more details.
17
 *
18
 *        You should have received a copy of the GNU General Public License
19
 *        along with this program; if not, write to the Free Software
20
 *        Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21
 *        MA 02110-1301, USA.
22
 *
23
 * @link https://github.com/ovidiul/XCloner-Wordpress
24
 *
25
 * @modified 7/31/18 3:10 PM
26
 *
27
 */
28
29
use splitbrain\PHPArchive\Tar;
30
use splitbrain\PHPArchive\Archive;
31
use splitbrain\PHPArchive\FileInfo;
32
33
/**
34
 * Class responsible for adding files to Tar
35
 * Class Xcloner_Archive
36
 */
37
class Xcloner_Archive extends Tar
38
{
39
	/**
40
	 * Process file size per API request
41
	 * @var float|int
42
	 */
43
	private $file_size_per_request_limit = 52428800; //50MB = 52428800; 1MB = 1048576
44
	/**
45
	 * Files count to process per API request
46
	 * @var int
47
	 */
48
	private $files_to_process_per_request = 250; //block of 512 bytes
49
	/**
50
	 * Compression level, 0-uncompressed, 9-maximum compression
51
	 * @var int
52
	 */
53
	private $compression_level = 0; //0-9 , 0 uncompressed
54
	/**
55
	 * Split backup size limit
56
	 * Create a new backup archive file once the set size is reached
57
	 * @var float|int
58
	 */
59
	private $xcloner_split_backup_limit = 2048; //2048MB
60
	/**
61
	 * Number of processed bytes
62
	 * @var int
63
	 */
64
	private $processed_size_bytes = 0;
65
66
	/**
67
	 * Archive name
68
	 * @var string
69
	 */
70
	private $archive_name;
71
	/**
72
	 * @var Tar
73
	 */
74
	private $backup_archive;
75
	/**
76
	 * @var Xcloner_File_System
77
	 */
78
	private $filesystem;
79
	/**
80
	 * @var Xcloner_Logger
81
	 */
82
	private $logger;
83
	/**
84
	 * @var Xcloner_Settings
85
	 */
86
	private $xcloner_settings;
87
88
	/**
89
	 * [__construct description]
90
	 * @param Xcloner $xcloner_container XCloner Container
91
	 * @param string $archive_name Achive Name
92
	 */
93
	public function __construct(Xcloner $xcloner_container, $archive_name = "")
94
	{
95
		$this->filesystem = $xcloner_container->get_xcloner_filesystem();
96
		$this->logger = $xcloner_container->get_xcloner_logger()->withName("xcloner_archive");
97
		$this->xcloner_settings = $xcloner_container->get_xcloner_settings();
98
99
		if ($value = $this->xcloner_settings->get_xcloner_option('xcloner_size_limit_per_request')) {
100
			$this->file_size_per_request_limit = $value * 1024 * 1024;
101
		} //MB
102
103
		if ($value = $this->xcloner_settings->get_xcloner_option('xcloner_files_to_process_per_request')) {
104
			$this->files_to_process_per_request = $value;
105
		}
106
107
		if ($value = get_option('xcloner_backup_compression_level')) {
0 ignored issues
show
Bug introduced by
The function get_option was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

107
		if ($value = /** @scrutinizer ignore-call */ get_option('xcloner_backup_compression_level')) {
Loading history...
108
			$this->compression_level = $value;
109
		}
110
111
		if ($value = get_option('xcloner_split_backup_limit')) {
112
			$this->xcloner_split_backup_limit = $value;
113
		}
114
115
		$this->xcloner_split_backup_limit = $this->xcloner_split_backup_limit * 1024 * 1024; //transform to bytes
116
117
		if (isset($archive_name) && $archive_name) {
118
			$this->set_archive_name($archive_name);
119
		}
120
	}
121
122
	/*
123
     * Rename backup archive
124
     *
125
     * @param string $old_name
126
     * @param string $new_name
127
     *
128
     */
129
	public function rename_archive($old_name, $new_name)
130
	{
131
		$this->logger->info(sprintf("Renaming backup archive %s to %s", $old_name, $new_name));
132
		$storage_filesystem = $this->filesystem->get_storage_filesystem();
133
		$storage_filesystem->rename($old_name, $new_name);
134
	}
135
136
	/*
137
     *
138
     * Set the backup archive name
139
     *
140
     */
141
	public function set_archive_name($name = "", $part = 0)
142
	{
143
144
		$this->archive_name = $this->filesystem->process_backup_name($name);
145
146
		if ($diff_timestamp_start = $this->filesystem->get_diff_timestamp_start()) {
147
			//$this->archive_name = $this->archive_name."-diff-".date("Y-m-d_H-i",$diff_timestamp_start);
148
			$new_name = $this->archive_name;
149
150
			if (!stristr($new_name, "-diff")) {
151
				$new_name = $this->archive_name . "-diff" . date("Y-m-d_H-i", $diff_timestamp_start);
0 ignored issues
show
Bug introduced by
$diff_timestamp_start of type string is incompatible with the type integer expected by parameter $timestamp of date(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

151
				$new_name = $this->archive_name . "-diff" . date("Y-m-d_H-i", /** @scrutinizer ignore-type */ $diff_timestamp_start);
Loading history...
152
			}
153
154
			$this->archive_name = $new_name;
155
156
		}
157
158
		if (isset($part) and $part) {
159
			$new_name = preg_replace('/-part(\d*)/', "-part" . $part, $this->archive_name);
160
			if (!stristr($new_name, "-part")) {
161
				$new_name = $this->archive_name . "-part" . $part;
162
			}
163
164
			$this->archive_name = $new_name;
165
		}
166
167
		return $this;
168
	}
169
170
	/*
171
     *
172
     * Returns the backup archive name
173
     *
174
     * @return string archive name
175
     */
176
	public function get_archive_name()
177
	{
178
		return $this->archive_name;
179
	}
180
181
	/*
182
     *
183
     * Returns the multipart naming for the backup archive
184
     *
185
     * @return string multi-part backup name
186
     */
187
	public function get_archive_name_multipart()
188
	{
189
		$new_name = preg_replace('/-part(\d*)/', "", $this->archive_name);
190
		return $new_name . "-multipart" . $this->xcloner_settings->get_backup_extension_name(".csv");
191
	}
192
193
	/*
194
     *
195
     * Returns the full backup name including extension
196
     *
197
     */
198
	public function get_archive_name_with_extension()
199
	{
200
		return $this->archive_name . $this->xcloner_settings->get_backup_extension_name();
201
	}
202
203
	/*
204
     *
205
     * Send notification error by E-Mail
206
     *
207
     * @param $to
208
     * @param $from
209
     * @param $subject
210
     * @param $backup_name
211
     * @param $params
212
     * @param $error_message
213
     *
214
     * @return bool
215
     */
216
217
    /**
218
     * @param string $error_message
219
     */
220
	public function send_notification_error($to, $from, $subject, $backup_name, $params, $error_message)
0 ignored issues
show
Unused Code introduced by
The parameter $backup_name is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

220
	public function send_notification_error($to, $from, $subject, /** @scrutinizer ignore-unused */ $backup_name, $params, $error_message)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $params is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

220
	public function send_notification_error($to, $from, $subject, $backup_name, /** @scrutinizer ignore-unused */ $params, $error_message)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
221
	{
222
223
		$body = "";
224
		$body .= sprintf(__("Backup Site Url: %s"), get_site_url());
0 ignored issues
show
Bug introduced by
The function get_site_url was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

224
		$body .= sprintf(__("Backup Site Url: %s"), /** @scrutinizer ignore-call */ get_site_url());
Loading history...
Bug introduced by
The function __ was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

224
		$body .= sprintf(/** @scrutinizer ignore-call */ __("Backup Site Url: %s"), get_site_url());
Loading history...
225
		$body .= "<br /><>";
226
227
		$body .= sprintf(__("Error Message: %s"), $error_message);
228
229
		$this->logger->info(sprintf("Sending backup error notification to %s", $to));
230
231
		$admin_email = get_option("admin_email");
0 ignored issues
show
Bug introduced by
The function get_option was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

231
		$admin_email = /** @scrutinizer ignore-call */ get_option("admin_email");
Loading history...
232
233
		$headers = array('Content-Type: text/html; charset=UTF-8');
234
235
		if ($admin_email and $from) {
236
			$headers[] = 'From: ' . $from . ' <' . $admin_email . '>';
237
		}
238
239
		$return = wp_mail($to, $subject, $body, $headers);
0 ignored issues
show
Bug introduced by
The function wp_mail was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

239
		$return = /** @scrutinizer ignore-call */ wp_mail($to, $subject, $body, $headers);
Loading history...
240
241
		return $return;
242
	}
243
244
	/*
245
     *
246
     * Send backup archive notfication by E-Mail
247
     *
248
     * @param $to
249
     * @param $from
250
     * @param $subject
251
     * @param $backup_name
252
     * @param $params
253
     * @param string $error_message
254
     * @param array $additional
255
     *
256
     * @return bool
257
     */
258
    public function send_notification(
259
        $to,
260
        $from,
261
        $subject,
262
        $backup_name,
263
        $params,
264
        $error_message = "",
265
        $additional = array()
266
    ) {
267
        if (!$from) {
268
            $from = "XCloner Backup";
269
        }
270
271
        if (($error_message)) {
272
            return $this->send_notification_error($to, $from, $subject, $backup_name, $params, $error_message);
273
        }
274
275
        $params = (array)$params;
276
277
        if (!$subject) {
278
            $subject = sprintf(__("New backup generated %s"), $backup_name);
0 ignored issues
show
Bug introduced by
The function __ was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

278
            $subject = sprintf(/** @scrutinizer ignore-call */ __("New backup generated %s"), $backup_name);
Loading history...
279
        }
280
281
        $body = sprintf(__("Generated Backup Size: %s"), size_format($this->filesystem->get_backup_size($backup_name)));
0 ignored issues
show
Bug introduced by
The function size_format was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

281
        $body = sprintf(__("Generated Backup Size: %s"), /** @scrutinizer ignore-call */ size_format($this->filesystem->get_backup_size($backup_name)));
Loading history...
282
        $body .= "<br /><br />";
283
284
        if (isset($additional['lines_total'])) {
285
            $body .= sprintf(__("Total files added: %s"), $additional['lines_total']);
286
            $body .= "<br /><br />";
287
        }
288
289
        $backup_parts = $this->filesystem->get_multipart_files($backup_name);
290
291
        if (!$backups_counter = sizeof($backup_parts)) {
292
            $backups_counter = 1;
293
        }
294
295
        $body .= sprintf(__("Backup Parts: %s"), $backups_counter);
296
        $body .= "<br />";
297
298
        if (sizeof($backup_parts)) {
299
            $body .= implode("<br />", $backup_parts);
300
            $body .= "<br />";
301
        }
302
303
        $body .= "<br />";
304
305
        $body .= sprintf(__("Backup Site Url: %s"), get_site_url());
0 ignored issues
show
Bug introduced by
The function get_site_url was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

305
        $body .= sprintf(__("Backup Site Url: %s"), /** @scrutinizer ignore-call */ get_site_url());
Loading history...
306
        $body .= "<br />";
307
308
        if (isset($params['backup_params']->backup_comments)) {
309
            $body .= __("Backup Comments: ").$params['backup_params']->backup_comments;
310
            $body .= "<br /><br />";
311
        }
312
313
        if ($this->xcloner_settings->get_xcloner_option('xcloner_enable_log')) {
314
            $body .= __("Latest 50 Log Lines: ")."<br />".implode("<br />\n",
315
                                                                        $this->logger->getLastDebugLines(50));
0 ignored issues
show
Bug introduced by
It seems like $this->logger->getLastDebugLines(50) can also be of type false; however, parameter $pieces of implode() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

315
                                                                        /** @scrutinizer ignore-type */ $this->logger->getLastDebugLines(50));
Loading history...
316
        }
317
318
        $attachments = $this->filesystem->get_backup_attachments();
319
320
        $attachments_archive = $this->xcloner_settings->get_xcloner_tmp_path().DS."info.tgz";
321
322
        $tar = new Tar();
323
        $tar->create($attachments_archive);
324
325
        foreach ($attachments as $key => $file) {
326
            $tar->addFile($file, basename($file));
327
        }
328
        $tar->close();
329
330
        $this->logger->info(sprintf("Sending backup notification to %s", $to));
331
332
        $admin_email = get_option("admin_email");
0 ignored issues
show
Bug introduced by
The function get_option was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

332
        $admin_email = /** @scrutinizer ignore-call */ get_option("admin_email");
Loading history...
333
334
        $headers = array('Content-Type: text/html; charset=UTF-8', 'From: '.$from.' <'.$admin_email.'>');
335
336
        $return = wp_mail($to, $subject, $body, $headers, array($attachments_archive));
0 ignored issues
show
Bug introduced by
The function wp_mail was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

336
        $return = /** @scrutinizer ignore-call */ wp_mail($to, $subject, $body, $headers, array($attachments_archive));
Loading history...
337
338
        return $return;
339
    }
340
341
    /*
342
     *
343
     * Incremental Backup method
344
     *
345
     */
346
    public function start_incremental_backup($backup_params, $extra_params, $init)
347
    {
348
        $return = array();
349
350
        if (!isset($extra_params['backup_part'])) {
351
            $extra_params['backup_part'] = 0;
352
        }
353
354
        $return['extra']['backup_part'] = $extra_params['backup_part'];
355
356
        if (isset($extra_params['backup_archive_name'])) {
357
            $this->set_archive_name($extra_params['backup_archive_name'], $return['extra']['backup_part']);
358
        } else {
359
            $this->set_archive_name($backup_params['backup_name']);
360
        }
361
362
        if (!$this->get_archive_name()) {
363
            $this->set_archive_name();
364
        }
365
366
        $this->backup_archive = new Tar();
367
        $this->backup_archive->setCompression($this->compression_level);
368
369
        $archive_info = $this->filesystem->get_storage_path_file_info($this->get_archive_name_with_extension());
370
371
        if ($init) {
372
            $this->logger->info(sprintf(__("Initializing the backup archive %s"), $this->get_archive_name()));
0 ignored issues
show
Bug introduced by
The function __ was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

372
            $this->logger->info(sprintf(/** @scrutinizer ignore-call */ __("Initializing the backup archive %s"), $this->get_archive_name()));
Loading history...
373
374
            $this->backup_archive->create($archive_info->getPath().DS.$archive_info->getFilename());
375
376
            $return['extra']['backup_init'] = 1;
377
378
        } else {
379
            $this->logger->info(sprintf(__("Opening for append the backup archive %s"), $this->get_archive_name()));
380
381
            $this->backup_archive->openForAppend($archive_info->getPath().DS.$archive_info->getFilename());
382
383
            $return['extra']['backup_init'] = 0;
384
385
        }
386
387
        $return['extra']['backup_archive_name'] = $this->get_archive_name();
388
        $return['extra']['backup_archive_name_full'] = $this->get_archive_name_with_extension();
389
390
        if (!isset($extra_params['start_at_line'])) {
391
            $extra_params['start_at_line'] = 0;
392
        }
393
394
        if (!isset($extra_params['start_at_byte'])) {
395
            $extra_params['start_at_byte'] = 0;
396
        }
397
398
        if (!$this->filesystem->get_tmp_filesystem()->has($this->filesystem->get_included_files_handler())) {
399
            $this->logger->error(sprintf("Missing the includes file handler %s, aborting...",
400
                $this->filesystem->get_included_files_handler()));
401
402
            $return['finished'] = 1;
403
            return $return;
404
        }
405
406
        $included_files_handler = $this->filesystem->get_included_files_handler(1);
407
408
        $file = new SplFileObject($included_files_handler);
409
410
        $file->seek(PHP_INT_MAX);
411
412
        $return['extra']['lines_total'] = ($file->key() - 1);
413
414
        //we skip the first CSV line with headers
415
        if (!$extra_params['start_at_line']) {
416
            $file->seek(1);
417
        } else {
418
            $file->seek($extra_params['start_at_line'] + 1);
419
        }
420
421
        $this->processed_size_bytes = 0;
422
423
        $counter = 0;
424
425
        $start_byte = $extra_params['start_at_byte'];
426
427
        $byte_limit = 0;
0 ignored issues
show
Unused Code introduced by
The assignment to $byte_limit is dead and can be removed.
Loading history...
428
429
        while (!$file->eof() and $counter <= $this->files_to_process_per_request) {
430
            $current_line_str = $file->current();
431
432
            $line = str_getcsv($current_line_str);
0 ignored issues
show
Bug introduced by
It seems like $current_line_str can also be of type array; however, parameter $input of str_getcsv() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

432
            $line = str_getcsv(/** @scrutinizer ignore-type */ $current_line_str);
Loading history...
433
434
            $relative_path = stripslashes($line[0]);
435
436
            $start_filesystem = "start_filesystem";
437
438
            if (isset($line[4])) {
439
                $start_filesystem = $line[4];
440
            }
441
442
            //$adapter = $this->filesystem->get_adapter($start_filesystem);
443
444
            if (!$relative_path || !$this->filesystem->get_filesystem($start_filesystem)->has($relative_path)) {
445
                if ($relative_path != "") {
446
                    $this->logger->error(sprintf("Could not add file %b to backup archive, file not found",
447
                        $relative_path));
448
                }
449
450
                $extra_params['start_at_line']++;
451
                $file->next();
452
                continue;
453
            }
454
455
            $file_info = $this->filesystem->get_filesystem($start_filesystem)->getMetadata($relative_path);
456
457
            if (!isset($file_info['size'])) {
458
                $file_info['size'] = 0;
459
            }
460
461
            if ($start_filesystem == "tmp_filesystem") {
462
                $file_info['archive_prefix_path'] = $this->xcloner_settings->get_xcloner_tmp_path_suffix();
463
            }
464
465
            $byte_limit = (int)$this->file_size_per_request_limit / 512;
466
467
            $append = 0;
468
469
            if ($file_info['size'] > $byte_limit * 512 or $start_byte) {
470
                $append = 1;
471
            }
472
473
            if (!isset($return['extra']['backup_size'])) {
474
                $return['extra']['backup_size'] = 0;
475
            }
476
477
            $return['extra']['backup_size'] = $archive_info->getSize();
478
479
            $estimated_new_size = $return['extra']['backup_size'] + $file_info['size'];
480
481
            //we create a new backup part if we reach the Split Achive Limit
482
            if ($this->xcloner_split_backup_limit and ($estimated_new_size > $this->xcloner_split_backup_limit) and (!$start_byte)) {
483
                $this->logger->info(sprintf("Backup size limit %s bytes reached, file add estimate %s, attempt to create a new archive ",
484
                    $this->xcloner_split_backup_limit, $estimated_new_size));
485
                list($archive_info, $return['extra']['backup_part']) = $this->create_new_backup_part($return['extra']['backup_part']);
486
487
                if ($file_info['size'] > $this->xcloner_split_backup_limit) {
488
                    $this->logger->info(sprintf("Excluding %s file as it's size(%s) is bigger than the backup split limit of %s and it won't fit a single backup file",
489
                        $file_info['path'], $file_info['size'], $this->xcloner_split_backup_limit));
490
                    $extra_params['start_at_line']++;
491
                }
492
493
                $return['extra']['start_at_line'] = $extra_params['start_at_line'];
494
                $return['extra']['start_at_byte'] = 0;
495
496
                $return['finished'] = 0;
497
498
                return $return;
499
            }
500
501
            list($bytes_wrote, $last_position) = $this->add_file_to_archive($file_info, $start_byte, $byte_limit,
502
                $append, $start_filesystem);
503
            $this->processed_size_bytes += $bytes_wrote;
504
505
            //echo" - processed ".$this->processed_size_bytes." bytes ".$this->file_size_per_request_limit." last_position:".$last_position." \n";
506
            $return['extra']['processed_file'] = $file_info['path'];
507
            $return['extra']['processed_file_size'] = $file_info['size'];
508
            $return['extra']['backup_size'] = $archive_info->getSize();
509
510
            if ($last_position > 0) {
511
                $start_byte = $last_position;
512
            } else {
513
                $extra_params['start_at_line']++;
514
                $file->next();
515
                $start_byte = 0;
516
                $counter++;
517
            }
518
519
            if ($this->processed_size_bytes >= $this->file_size_per_request_limit) {
520
                clearstatcache();
521
                $return['extra']['backup_size'] = $archive_info->getSize();
522
523
                $return['finished'] = 0;
524
                $return['extra']['start_at_line'] = $extra_params['start_at_line'];
525
                $return['extra']['start_at_byte'] = $last_position;
526
                $this->logger->info(sprintf("Reached the maximum %s request data limit, returning response",
527
                    $this->file_size_per_request_limit));
528
                return $return;
529
            }
530
        }
531
532
        if (!$file->eof()) {
533
            clearstatcache();
534
            $return['extra']['backup_size'] = $archive_info->getSize();
535
536
            $return['finished'] = 0;
537
            $return['extra']['start_at_line'] = $extra_params['start_at_line'];
538
            $return['extra']['start_at_byte'] = $last_position;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $last_position does not seem to be defined for all execution paths leading up to this point.
Loading history...
539
            $this->logger->info(sprintf("We have reached the maximum files to process per request limit of %s, returning response",
540
                $this->files_to_process_per_request));
541
542
            return $return;
543
        }
544
545
        //close the backup archive by adding 2*512 blocks of zero bytes
546
        $this->logger->info(sprintf("Closing the backup archive %s with 2*512 zero bytes blocks.",
547
            $this->get_archive_name_with_extension()));
548
        $this->backup_archive->close();
549
550
        /**
551
         * XCloner HOOK backup_archive_finished.
552
         *
553
         * This will get triggered when a backup archive is finished writing.
554
         */
555
        //do_action('backup_archive_finished', $this->backup_archive, $this);
556
557
        //updating archive_info
558
        $archive_info = $this->filesystem->get_storage_path_file_info($this->get_archive_name_with_extension());
559
560
        if ($return['extra']['backup_part']) {
561
            $this->write_multipart_file($this->get_archive_name_with_extension());
562
        }
563
564
        $return['extra']['start_at_line'] = $extra_params['start_at_line'] - 1;
565
566
        if (isset($file_info)) {
567
            $return['extra']['processed_file'] = $file_info['path'];
568
            $return['extra']['processed_file_size'] = $file_info['size'];
569
        }
570
571
        clearstatcache();
572
        $return['extra']['backup_size'] = $archive_info->getSize();
573
574
        $return['finished'] = 1;
575
        return $return;
576
    }
577
578
    /*
579
     *
580
     * Write multipart file components
581
     *
582
     */
583
    private function write_multipart_file($path = "")
584
    {
585
        if (!$path) {
586
            $path = $this->get_archive_name_with_extension();
587
        }
588
589
        $file = $this->filesystem->get_filesystem("storage_filesystem_append")->getMetadata($path);
590
        //print_r($file_info);
591
        $line = '"'.$file['path'].'","'.$file['timestamp'].'","'.$file['size'].'"'.PHP_EOL;
592
593
594
        $this->filesystem->get_filesystem("storage_filesystem_append")
595
            ->write($this->get_archive_name_multipart(), $line);
596
    }
597
598
    /*
599
     *
600
     * Create a new backup part
601
     *
602
     */
603
    private function create_new_backup_part($part = 0)
604
    {
605
        //close the backup archive by adding 2*512 blocks of zero bytes
606
        $this->logger->info(sprintf("Closing the backup archive %s with 2*512 zero bytes blocks.",
607
            $this->get_archive_name_with_extension()));
608
        $this->backup_archive->close();
609
610
        if (!$part) {
611
            $old_name = $this->get_archive_name_with_extension();
612
            $this->set_archive_name($this->get_archive_name(), ++$part);
613
            $this->rename_archive($old_name, $this->get_archive_name_with_extension());
614
615
            if ($this->filesystem->get_storage_filesystem()->has($this->get_archive_name_multipart())) {
616
                $this->filesystem->get_storage_filesystem()->delete($this->get_archive_name_multipart());
617
            }
618
619
            $this->write_multipart_file($this->get_archive_name_with_extension());
620
621
        } else {
622
            $this->logger->info(sprintf("Creating new multipart info file %s",
623
                $this->get_archive_name_with_extension()));
624
            $this->write_multipart_file($this->get_archive_name_with_extension());
625
        }
626
627
        $this->set_archive_name($this->get_archive_name(), ++$part);
628
629
        $this->logger->info(sprintf("Creating new backup archive part %s", $this->get_archive_name_with_extension()));
630
631
        $this->backup_archive = new Tar();
632
        $this->backup_archive->setCompression($this->compression_level);
633
        $archive_info = $this->filesystem->get_storage_path_file_info($this->get_archive_name_with_extension());
634
        $this->backup_archive->create($archive_info->getPath().DS.$archive_info->getFilename());
635
636
        return array($archive_info, $part);
637
638
    }
639
640
    /*
641
     *
642
     * Add file to archive
643
     *
644
     */
645
646
    /**
647
     * @param integer $append
648
     */
649
    public function add_file_to_archive($file_info, $start_at_byte, $byte_limit = 0, $append, $filesystem)
650
    {
651
652
        $start_adapter = $this->filesystem->get_adapter($filesystem);
653
        $start_filesystem = $this->filesystem->get_adapter($filesystem);
654
655
        if (!$file_info['path']) {
656
            return;
657
        }
658
659
        if (isset($file_info['archive_prefix_path'])) {
660
            $file_info['target_path'] = $file_info['archive_prefix_path']."/".$file_info['path'];
661
        } else {
662
            $file_info['target_path'] = $file_info['path'];
663
        }
664
665
        $last_position = $start_at_byte;
666
667
        //$start_adapter = $this->filesystem->get_start_adapter();
668
669
        if (!$append) {
670
            $bytes_wrote = $file_info['size'];
671
            $this->logger->info(sprintf("Adding %s bytes of file %s to archive %s ", $bytes_wrote,
672
                $file_info['target_path'], $this->get_archive_name_with_extension()));
673
            $this->backup_archive->addFile($start_adapter->applyPathPrefix($file_info['path']),
674
                $file_info['target_path']);
675
        } else {
676
            $tmp_file = md5($file_info['path']);
677
678
            //we isolate file to tmp if we are at byte 0, the starting point of file reading
679
            if (!$start_at_byte) {
680
                $this->logger->info(sprintf("Copying %s file to tmp filesystem file %s to prevent reading changes",
681
                    $file_info['path'], $tmp_file));
682
                $file_stream = $start_filesystem->readStream($file_info['path']);
683
684
                if (is_resource($file_stream['stream'])) {
685
                    $this->filesystem->get_tmp_filesystem()->writeStream($tmp_file, $file_stream['stream']);
686
                }
687
            }
688
689
            if ($this->filesystem->get_tmp_filesystem()->has($tmp_file)) {
690
                $is_tmp = 1;
691
                $last_position = $this->backup_archive->appendFileData($this->filesystem->get_tmp_filesystem_adapter()
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $last_position is correct as $this->backup_archive->a...t_at_byte, $byte_limit) targeting splitbrain\PHPArchive\Tar::appendFileData() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
692
                                                        ->applyPathPrefix($tmp_file),
693
                    $file_info['target_path'], $start_at_byte, $byte_limit);
694
            } else {
695
                $is_tmp = 0;
696
                $last_position = $this->backup_archive->appendFileData($start_adapter->applyPathPrefix($file_info['path']),
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $last_position is correct as $this->backup_archive->a...t_at_byte, $byte_limit) targeting splitbrain\PHPArchive\Tar::appendFileData() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
697
                    $file_info['target_path'], $start_at_byte, $byte_limit);
698
            }
699
700
701
            if ($last_position == -1) {
702
                $bytes_wrote = $file_info['size'] - $start_at_byte;
703
            } else {
704
                $bytes_wrote = $last_position - $start_at_byte;
705
            }
706
707
708
            if ($is_tmp) {
709
                $this->logger->info(sprintf("Appended %s bytes, starting position %s, of tmp file %s (%s) to archive %s ",
710
                    $bytes_wrote, $start_at_byte, $tmp_file, $file_info['target_path'], $this->get_archive_name()));
711
            } else {
712
                $this->logger->info(sprintf("Appended %s bytes, starting position %s, of original file %s to archive %s ",
713
                    $bytes_wrote, $start_at_byte, $file_info['target_path'], $tmp_file, $this->get_archive_name()));
714
            }
715
716
            //we delete here the isolated tmp file
717
            if ($last_position == -1) {
718
                if ($this->filesystem->get_tmp_filesystem_adapter()->has($tmp_file)) {
719
                    $this->logger->info(sprintf("Deleting %s from the tmp filesystem", $tmp_file));
720
                    $this->filesystem->get_tmp_filesystem_adapter()->delete($tmp_file);
721
                }
722
            }
723
724
        }
725
726
        return array($bytes_wrote, $last_position);
727
    }
728
729
    /**
730
     * Open a TAR archive and put the file cursor at the end for data appending
731
     *
732
     * If $file is empty, the tar file will be created in memory
733
     *
734
     * @param string $file
735
     * @throws ArchiveIOException
736
     */
737
    /*
738
    public function openForAppend($file = '')
739
    {
740
        $this->file   = $file;
741
        $this->memory = '';
742
        $this->fh     = 0;
743
744
        if ($this->file) {
745
            // determine compression
746
            if ($this->comptype == Archive::COMPRESS_AUTO) {
747
                $this->setCompression($this->complevel, $this->filetype($file));
748
            }
749
750
            if ($this->comptype === Archive::COMPRESS_GZIP) {
751
                $this->fh = @gzopen($this->file, 'ab'.$this->complevel);
752
            } elseif ($this->comptype === Archive::COMPRESS_BZIP) {
753
                $this->fh = @bzopen($this->file, 'a');
754
            } else {
755
                $this->fh = @fopen($this->file, 'ab');
756
            }
757
758
            if (!$this->fh) {
759
                throw new ArchiveIOException('Could not open file for writing: '.$this->file);
760
            }
761
        }
762
        $this->backup_archive->writeaccess = true;
763
        $this->backup_archive->closed      = false;
764
    }
765
    */
766
767
	/**
768
	 * Append data to a file to the current TAR archive using an existing file in the filesystem
769
	 *
770
	 * @param string $file path to the original file
771
	 * @param int $start starting reading position in file
772
	 * @param int $end end position in reading multiple with 512
773
	 * @param string|FileInfo $fileinfo either the name to us in archive (string) or a FileInfo oject with
774
	 * all meta data, empty to take from original
775
	 * @throws ArchiveIOException
776
	 */
777
	/*
778
     * public function appendFileData($file, $fileinfo = '', $start = 0, $limit = 0)
779
    {
780
		$end = $start+($limit*512);
781
782
		//check to see if we are at the begining of writing the file
783
		if(!$start)
784
		{
785
	        if (is_string($fileinfo)) {
786
				$fileinfo = FileInfo::fromPath($file, $fileinfo);
787
	        }
788
		}
789
790
        if ($this->closed) {
791
            throw new ArchiveIOException('Archive has been closed, files can no longer be added');
792
        }
793
794
        $fp = fopen($file, 'rb');
795
796
        fseek($fp, $start);
797
798
        if (!$fp) {
799
            throw new ArchiveIOException('Could not open file for reading: '.$file);
800
        }
801
802
        // create file header
803
		if(!$start)
804
			$this->backup_archive->writeFileHeader($fileinfo);
805
806
		$bytes = 0;
807
        // write data
808
        while ($end >=ftell($fp) and !feof($fp) ) {
809
            $data = fread($fp, 512);
810
            if ($data === false) {
811
                break;
812
            }
813
            if ($data === '') {
814
                break;
815
            }
816
            $packed = pack("a512", $data);
817
            $bytes += $this->backup_archive->writebytes($packed);
818
        }
819
820
821
822
        //if we are not at the end of file, we return the current position for incremental writing
823
        if(!feof($fp))
824
			$last_position = ftell($fp);
825
		else
826
			$last_position = -1;
827
828
        fclose($fp);
829
830
        return $last_position;
831
    }*/
832
833
	/**
834
	 * Adds a file to a TAR archive by appending it's data
835
	 *
836
	 * @param string $archive name of the archive file
837
	 * @param string $file name of the file to read data from
838
	 * @param string $start start position from where to start reading data
839
	 * @throws ArchiveIOException
840
	 */
841
	/*public function addFileToArchive($archive, $file, $start = 0)
842
    {
843
        $this->openForAppend($archive);
844
        return $start = $this->appendFileData($file, $start, $this->file_size_per_request_limit);
845
    }
846
    */
847
848
}
849