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.
Completed
Push — master ( e65d67...dc9fa8 )
by Liuta
03:08
created

Xcloner_Archive::__construct()   C

Complexity

Conditions 7
Paths 32

Size

Total Lines 25
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 15
nc 32
nop 2
dl 0
loc 25
rs 6.7272
c 0
b 0
f 0
1
<?php
2
use splitbrain\PHPArchive\Tar;
3
use splitbrain\PHPArchive\Archive;
4
use splitbrain\PHPArchive\FileInfo;
5
6
class Xcloner_Archive extends Tar
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
7
{
8
	/*
9
	 * bytes
10
	 */ 
11
	private $file_size_per_request_limit	= 52428800 ; //50MB = 52428800; 1MB = 1048576
0 ignored issues
show
Unused Code Comprehensibility introduced by
36% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
12
	private $files_to_process_per_request 	= 250; //block of 512 bytes
13
	private $compression_level 				= 0; //0-9 , 0 uncompressed
0 ignored issues
show
Unused Code Comprehensibility introduced by
45% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
14
	private $xcloner_split_backup_limit		= 2048; //2048MB
15
	private $processed_size_bytes			= 0 ;
16
	
17
	private $archive_name;
18
	private $backup_archive;
19
	private $filesystem;
20
	private $logger;
21
	private $xcloner_settings;
22
	
23
	public function __construct(Xcloner $xcloner_container, $archive_name = "")
24
	{
25
		$this->filesystem 		= $xcloner_container->get_xcloner_filesystem();
26
		$this->logger 			= $xcloner_container->get_xcloner_logger()->withName("xcloner_archive");
27
		$this->xcloner_settings = $xcloner_container->get_xcloner_settings();
28
		
29
		if($value = $this->xcloner_settings->get_xcloner_option('xcloner_size_limit_per_request'))
30
			$this->file_size_per_request_limit = $value*1024*1024; //MB
0 ignored issues
show
Documentation Bug introduced by
It seems like $value * 1024 * 1024 can also be of type double. However, the property $file_size_per_request_limit is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
31
			
32
		if($value = $this->xcloner_settings->get_xcloner_option('xcloner_files_to_process_per_request'))
33
			$this->files_to_process_per_request = $value;
34
		
35
		if($value = get_option('xcloner_backup_compression_level'))
36
			$this->compression_level = $value;
37
		
38
		if($value = get_option('xcloner_split_backup_limit'))
39
			$this->xcloner_split_backup_limit = $value;
40
		
41
		$this->xcloner_split_backup_limit = $this->xcloner_split_backup_limit * 1024*1024; //transform to bytes
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->xcloner_split_backup_limit * 1024 * 1024 can also be of type double. However, the property $xcloner_split_backup_limit is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
42
			
43
		if(isset($archive_name) && $archive_name)
44
		{
45
			$this->set_archive_name($archive_name);
46
		}
47
	}
48
	
49
	/*
50
	 * 
51
	 * Rename backup archive
52
	 * 
53
	 */ 
54
	public function rename_archive($old_name, $new_name)
55
	{
56
		$this->logger->info(sprintf("Renaming backup archive %s to %s", $old_name, $new_name));
57
		$storage_filesystem = $this->filesystem->get_storage_filesystem();
58
		$storage_filesystem->rename($old_name, $new_name);
59
	}
60
	
61
	/*
62
	 * 
63
	 * Set the backup archive name
64
	 * 
65
	 */ 
66
	public function set_archive_name($name = "", $part = 0)
67
	{
68
		
69
		$this->archive_name = $this->filesystem->process_backup_name($name);
70
		
71
		if($diff_timestamp_start = $this->filesystem->get_diff_timestamp_start())
72
		{
73
			//$this->archive_name = $this->archive_name."-diff-".date("Y-m-d_H-i",$diff_timestamp_start);
0 ignored issues
show
Unused Code Comprehensibility introduced by
58% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
74
			$new_name = $this->archive_name;
75
			
76
			if(!stristr($new_name, "-diff"))
77
				$new_name = $this->archive_name . "-diff".date("Y-m-d_H-i",$diff_timestamp_start);
78
			
79
			$this->archive_name = $new_name;
80
			
81
		}
82
		
83
		if(isset($part) and $part)
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
84
		{
85
			$new_name =  preg_replace('/-part(\d*)/', "-part".$part, $this->archive_name);
86
			if(!stristr($new_name, "-part"))
87
				$new_name = $this->archive_name . "-part".$part;
88
			
89
			$this->archive_name = $new_name;	
90
		}
91
		
92
		return $this;
93
	}
94
	
95
	/*
96
	 * 
97
	 * Returns the backup archive name
98
	 * 
99
	 */
100
	public function get_archive_name()
101
	{
102
		return $this->archive_name;
103
	}
104
	
105
	/*
106
	 * 
107
	 * Returns the multipart naming for the backup archive
108
	 * 
109
	 */ 
110
	public function get_archive_name_multipart()
111
	{
112
		$new_name =  preg_replace('/-part(\d*)/', "", $this->archive_name);
113
		return $new_name."-multipart".$this->xcloner_settings->get_backup_extension_name(".csv");
114
	}
115
	
116
	/*
117
	 * 
118
	 * Returns the full backup name including extension
119
	 * 
120
	 */ 
121
	public function get_archive_name_with_extension()
122
	{
123
		return $this->archive_name.$this->xcloner_settings->get_backup_extension_name();
124
	}
125
	
126
	/*
127
	 * 
128
	 * Send notification error by E-Mail
129
	 * 
130
	 */
131
	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.

This check looks from 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.

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

Loading history...
132
	{
133
		
134
		$body  = $error_message; 
135
		
136
		$this->logger->info(sprintf("Sending backup error notification to %s", $to));
137
		
138
		$admin_email = get_option("admin_email");
139
		
140
		$headers = array('Content-Type: text/html; charset=UTF-8');
141
		
142
		if($admin_email and $from )
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
143
			$headers[] = 'From: '.$from.' <'.$admin_email.'>';
144
145
		$return = wp_mail( $to, $subject, $body, $headers );
146
		
147
		return $return;
148
	}
149
	
150
	/*
151
	 * 
152
	 * Send backup archive notfication by E-Mail
153
	 * 
154
	 */ 
155
	public function send_notification($to, $from, $subject, $backup_name, $params, $error_message="", $additional = array())
156
	{
157
		if(!$from)
158
		{
159
			$from = "XCloner Backup";
160
		}
161
			
162
		if(($error_message))
163
		{
164
			return $this->send_notification_error($to, $from, $subject, $backup_name, $params, $error_message);
165
		}
166
		
167
		$params = (array)$params;
168
		
169
		if(!$subject)
170
		{
171
			$subject = sprintf(__("New backup generated %s") ,$backup_name);
172
		}
173
			
174
		$body = sprintf(__("Generated Backup Size: %s"), size_format($this->filesystem->get_backup_size($backup_name)));
175
		$body .= "<br /><br />";
176
		
177
		if(isset($additional['lines_total']))
178
		{
179
			$body .= sprintf(__("Total files added: %s"), $additional['lines_total']);
180
			$body .= "<br /><br />";
181
		}
182
		
183
		$backup_parts = $this->filesystem->get_multipart_files($backup_name);
184
		
185
		if(!$backups_counter = sizeof($backup_parts))
186
			$backups_counter = 1;
187
		
188
		$body .= sprintf(__("Backup Parts: %s"), $backups_counter);
189
		$body .= "<br />";
190
		
191
		if(sizeof($backup_parts))
192
		{
193
			$body .= implode("<br />",$backup_parts);
194
			$body .= "<br />";
195
		}
196
		
197
		$body.= "<br />";
198
		
199
		if(isset($params['backup_params']->backup_comments))
200
		{
201
			$body .= __("Backup Comments: ").$params['backup_params']->backup_comments;
202
			$body .= "<br /><br />";
203
		}
204
		
205
		if($this->xcloner_settings->get_xcloner_option('xcloner_enable_log'))
206
			$body .= __("Latest 50 Log Lines: ")."<br />".implode("<br />\n", $this->logger->getLastDebugLines(50));
207
		
208
		$attachments = $this->filesystem->get_backup_attachments();
209
		
210
		$attachments_archive = $this->xcloner_settings->get_xcloner_tmp_path().DS."info.tgz";
211
		
212
		$tar = new Tar();
213
		$tar->create($attachments_archive);
214
			
215
		foreach($attachments as $key => $file)
216
		{
217
			$tar->addFile($file, basename($file));
218
		}
219
		$tar->close();
220
		
221
		$this->logger->info(sprintf("Sending backup notification to %s", $to));
222
		
223
		$admin_email = get_option("admin_email");
224
		
225
		$headers = array('Content-Type: text/html; charset=UTF-8', 'From: '.$from.' <'.$admin_email.'>');
226
		
227
		$return = wp_mail( $to, $subject, $body, $headers, array($attachments_archive) );
228
	
229
		return $return;
230
	}
231
	
232
	/*
233
	 * 
234
	 * Incremental Backup method
235
	 * 
236
	 */ 
237
	public function start_incremental_backup($backup_params, $extra_params, $init)
238
	{
239
		$return = array();
240
		
241
		if(!isset($extra_params['backup_part']))
242
			$extra_params['backup_part'] = 0;
243
		
244
		$return['extra']['backup_part'] = $extra_params['backup_part'];
245
					
246
		if(isset( $extra_params['backup_archive_name']))
247
			$this->set_archive_name($extra_params['backup_archive_name'], $return['extra']['backup_part']);
248
		else
249
			$this->set_archive_name($backup_params['backup_name']);
250
			
251
		if(!$this->get_archive_name())
252
			$this->set_archive_name();
253
		
254
		$this->backup_archive = new Tar();
255
		$this->backup_archive->setCompression($this->compression_level);
256
		
257
		$archive_info = $this->filesystem->get_storage_path_file_info($this->get_archive_name_with_extension());
258
		
259
		if($init)
260
		{
261
			$this->logger->info(sprintf(__("Initializing the backup archive %s"), $this->get_archive_name()));
262
		
263
			$this->backup_archive->create($archive_info->getPath().DS.$archive_info->getFilename());
264
			
265
			$return['extra']['backup_init'] = 1;
266
			
267
		}else{
268
			$this->logger->info(sprintf(__("Opening for append the backup archive %s"), $this->get_archive_name()));
269
			
270
			$this->backup_archive->openForAppend($archive_info->getPath().DS.$archive_info->getFilename());
0 ignored issues
show
Bug introduced by
The method openForAppend() does not seem to exist on object<splitbrain\PHPArchive\Tar>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
271
			
272
			$return['extra']['backup_init'] = 0;
273
			
274
		}
275
		
276
		$return['extra']['backup_archive_name'] = $this->get_archive_name();
277
		$return['extra']['backup_archive_name_full'] = $this->get_archive_name_with_extension();
278
		
279
		if(!isset($extra_params['start_at_line']))
280
			$extra_params['start_at_line'] = 0;
281
		
282
		if(!isset($extra_params['start_at_byte']))
283
			$extra_params['start_at_byte'] = 0;
284
		
285
		if(!$this->filesystem->get_tmp_filesystem()->has($this->filesystem->get_included_files_handler()))
0 ignored issues
show
Bug introduced by
It seems like $this->filesystem->get_included_files_handler() targeting Xcloner_File_System::get_included_files_handler() can also be of type object<SplFileInfo>; however, League\Flysystem\Filesystem::has() does only seem to accept string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
286
		{
287
			$this->logger->error(sprintf("Missing the includes file handler %s, aborting...", $this->filesystem->get_included_files_handler()));
288
			
289
			$return['finished'] = 1;
290
			return $return;
291
		}
292
			
293
		$included_files_handler = $this->filesystem->get_included_files_handler(1);	
294
		
295
		$file = new SplFileObject($included_files_handler);
296
		
297
		$file->seek(PHP_INT_MAX);
298
299
		$return['extra']['lines_total'] = ($file->key()-1);
300
		
301
		//we skip the first CSV line with headers 
302
		if(!$extra_params['start_at_line'])
303
		{
304
			$file->seek(1);
305
		}else{
306
			$file->seek($extra_params['start_at_line']+1);
307
		}
308
		
309
		$this->processed_size_bytes = 0;
310
		
311
		$counter = 0;
312
		
313
		$start_byte = $extra_params['start_at_byte'];
314
		
315
		$byte_limit = 0;
0 ignored issues
show
Unused Code introduced by
$byte_limit is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
316
		
317
		while(!$file->eof() and $counter<=$this->files_to_process_per_request)
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
318
		{
319
			$current_line_str = $file->current();
320
			
321
			$line = str_getcsv($current_line_str);
322
323
			$relative_path = stripslashes($line[0]);
324
			
325
			$start_filesystem = "start_filesystem";
326
			
327
			if(isset($line[4])){
328
				$start_filesystem = $line[4];
329
			}
330
			
331
			//$adapter = $this->filesystem->get_adapter($start_filesystem);
0 ignored issues
show
Unused Code Comprehensibility introduced by
62% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
332
			
333
			if(!$relative_path || !$this->filesystem->get_filesystem($start_filesystem)->has($relative_path))
334
			{
335
				if($relative_path != "")
336
				{
337
					$this->logger->error(sprintf("Could not add file %b to backup archive, file not found", $relative_path));
338
				}
339
				
340
				$extra_params['start_at_line']++;
341
				$file->next();
342
				continue;
343
			}
344
			
345
			$file_info = $this->filesystem->get_filesystem($start_filesystem)->getMetadata($relative_path);
346
			
347
			if(!isset($file_info['size']))
348
				$file_info['size'] = 0;
349
			
350
			if($start_filesystem == "tmp_filesystem")
351
			{	
352
				$file_info['archive_prefix_path'] = $this->xcloner_settings->get_xcloner_tmp_path_suffix();
353
			}
354
			
355
			$byte_limit = (int)$this->file_size_per_request_limit/512;
356
			
357
			$append = 0;
358
			
359
			if($file_info['size'] > $byte_limit*512 or $start_byte)
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
360
				$append = 1;
361
						
362
			if(!isset($return['extra']['backup_size']))
363
				$return['extra']['backup_size'] =0;
364
			
365
			$return['extra']['backup_size'] = $archive_info->getSize();
366
			
367
			$estimated_new_size = $return['extra']['backup_size'] + $file_info['size'];
368
			
369
			//we create a new backup part if we reach the Split Achive Limit
370
			if($this->xcloner_split_backup_limit and ($estimated_new_size > $this->xcloner_split_backup_limit) and (!$start_byte))
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
371
			{
372
				$this->logger->info(sprintf("Backup size limit %s bytes reached, file add estimate %s, attempt to create a new archive ",$this->xcloner_split_backup_limit, $estimated_new_size));
373
				list($archive_info, $return['extra']['backup_part']) = $this->create_new_backup_part($return['extra']['backup_part']);
0 ignored issues
show
Unused Code introduced by
The assignment to $archive_info is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
374
				
375
				if($file_info['size'] > $this->xcloner_split_backup_limit)
376
				{
377
					$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",$file_info['path'], $file_info['size'], $this->xcloner_split_backup_limit));
378
					$extra_params['start_at_line']++;
379
				}
380
				
381
				$return['extra']['start_at_line'] = $extra_params['start_at_line'];
382
				$return['extra']['start_at_byte'] = 0;
383
				
384
				$return['finished'] = 0;
385
				
386
				return $return;
387
			}
388
			
389
			list($bytes_wrote, $last_position) = $this->add_file_to_archive( $file_info, $start_byte, $byte_limit, $append, $start_filesystem);
390
			$this->processed_size_bytes += $bytes_wrote;
391
			
392
			//echo" - processed ".$this->processed_size_bytes." bytes ".$this->file_size_per_request_limit." last_position:".$last_position." \n";
0 ignored issues
show
Unused Code Comprehensibility introduced by
58% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
393
			$return['extra']['processed_file'] = $file_info['path'];
394
			$return['extra']['processed_file_size'] = $file_info['size'];
395
			$return['extra']['backup_size'] = $archive_info->getSize();
396
			
397
			if($last_position>0){	
398
				$start_byte = $last_position;
399
			}
400
			else{	
401
				$extra_params['start_at_line']++;
402
				$file->next();
403
				$start_byte = 0;
404
				$counter++;
405
			}
406
			
407
			if($this->processed_size_bytes >= $this->file_size_per_request_limit)
408
			{
409
				clearstatcache();
410
				$return['extra']['backup_size'] = $archive_info->getSize();
411
				
412
				$return['finished'] = 0;
413
				$return['extra']['start_at_line'] = $extra_params['start_at_line'];
414
				$return['extra']['start_at_byte'] = $last_position;
415
				$this->logger->info(sprintf("Reached the maximum %s request data limit, returning response", $this->file_size_per_request_limit));
416
				return $return;
417
			}
418
		}
419
		
420
		if(!$file->eof())
421
		{
422
			clearstatcache();
423
			$return['extra']['backup_size'] = $archive_info->getSize();
424
				
425
			$return['finished'] = 0;
426
			$return['extra']['start_at_line'] = $extra_params['start_at_line'];
427
			$return['extra']['start_at_byte'] = $last_position;
0 ignored issues
show
Bug introduced by
The variable $last_position does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
428
			$this->logger->info(sprintf("We have reached the maximum files to process per request limit of %s, returning response", $this->files_to_process_per_request));
429
430
			return $return;
431
		}
432
		
433
		//close the backup archive by adding 2*512 blocks of zero bytes
434
		$this->logger->info(sprintf("Closing the backup archive %s with 2*512 zero bytes blocks.", $this->get_archive_name_with_extension()));
435
		$this->backup_archive->close();
436
				
437
		if($return['extra']['backup_part'])
438
			$this->write_multipart_file($this->get_archive_name_with_extension());
439
		
440
		$return['extra']['start_at_line'] = $extra_params['start_at_line']-1;
441
		
442
		if(isset($file_info))
443
		{
444
			$return['extra']['processed_file'] = $file_info['path'];
445
			$return['extra']['processed_file_size'] = $file_info['size'];
446
		}
447
		
448
		clearstatcache();
449
		$return['extra']['backup_size'] = $archive_info->getSize();
450
		
451
		$return['finished'] = 1;
452
		return $return;
453
	}
454
	
455
	/*
456
	 * 
457
	 * Write multipart file components
458
	 * 
459
	 */ 
460
	private function write_multipart_file($path)
0 ignored issues
show
Unused Code introduced by
The parameter $path is not used and could be removed.

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

Loading history...
461
	{
462
		$path = $this->get_archive_name_with_extension();
463
		
464
		$file = $this->filesystem->get_filesystem("storage_filesystem_append")->getMetadata($path);
465
		//print_r($file_info);
466
		$line = '"'.$file['path'].'","'.$file['timestamp'].'","'.$file['size'].'"'.PHP_EOL;
467
468
		
469
		$this->filesystem->get_filesystem("storage_filesystem_append")
470
						->write($this->get_archive_name_multipart(), $line);
471
	}
472
	
473
	/*
474
	 * 
475
	 * Create a new backup part
476
	 * 
477
	 */ 
478
	private function create_new_backup_part($part = 0)
479
	{
480
		//close the backup archive by adding 2*512 blocks of zero bytes
481
		$this->logger->info(sprintf("Closing the backup archive %s with 2*512 zero bytes blocks.", $this->get_archive_name_with_extension()));
482
		$this->backup_archive->close();		
483
		
484
		if(!$part)
485
		{
486
			$old_name = $this->get_archive_name_with_extension();
487
			$this->set_archive_name($this->get_archive_name(), ++$part);
488
			$this->rename_archive($old_name, $this->get_archive_name_with_extension());
489
			
490
			if($this->filesystem->get_storage_filesystem()->has($this->get_archive_name_multipart()))
491
				$this->filesystem->get_storage_filesystem()->delete($this->get_archive_name_multipart());
492
				
493
			$this->write_multipart_file($this->get_archive_name_with_extension());
494
			
495
		}else
496
		{
497
			$this->logger->info(sprintf("Creating new multipart info file %s",$this->get_archive_name_with_extension()));
498
			$this->write_multipart_file($this->get_archive_name_with_extension());
499
		}
500
				
501
		$this->set_archive_name($this->get_archive_name(), ++$part);		
502
		
503
		$this->logger->info(sprintf("Creating new backup archive part %s", $this->get_archive_name_with_extension()));
504
505
		$this->backup_archive = new Tar();
506
		$this->backup_archive->setCompression($this->compression_level);
507
		$archive_info = $this->filesystem->get_storage_path_file_info($this->get_archive_name_with_extension());
508
		$this->backup_archive->create($archive_info->getPath().DS.$archive_info->getFilename());
509
		
510
		return array($archive_info, $part);
511
		
512
	}
513
	
514
	/*
515
	 * 
516
	 * Add file to archive
517
	 * 
518
	 */ 
519
	public function add_file_to_archive($file_info, $start_at_byte, $byte_limit = 0, $append, $filesystem)
520
	{
521
		
522
		$start_adapter = $this->filesystem->get_adapter($filesystem);
523
		$start_filesystem = $this->filesystem->get_adapter($filesystem);
524
		
525
		if(!$file_info['path'])
526
			return;
527
		
528
		if(isset($file_info['archive_prefix_path']))	
529
			$file_info['target_path'] = $file_info['archive_prefix_path']."/".$file_info['path'];
530
		else
531
			$file_info['target_path'] = $file_info['path'];
532
			
533
		$last_position = $start_at_byte;
534
		
535
		//$start_adapter = $this->filesystem->get_start_adapter();
0 ignored issues
show
Unused Code Comprehensibility introduced by
59% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
536
537
		if(!$append){
538
			$bytes_wrote = $file_info['size'];
539
			$this->logger->info(sprintf("Adding %s bytes of file %s to archive %s ", $bytes_wrote, $file_info['target_path'], $this->get_archive_name_with_extension()));
540
			$this->backup_archive->addFile($start_adapter->applyPathPrefix($file_info['path']), $file_info['target_path']);
541
		}
542
		else{	
543
			$tmp_file = md5($file_info['path']);
544
			
545
			//we isolate file to tmp if we are at byte 0, the starting point of file reading
546
			if(!$start_at_byte)
547
			{
548
				$this->logger->info(sprintf("Copying %s file to tmp filesystem file %s to prevent reading changes", $file_info['path'], $tmp_file));
549
				$file_stream = $start_filesystem->readStream($file_info['path']);
550
				
551
				if(is_resource($file_stream['stream']))
552
					$this->filesystem->get_tmp_filesystem()->writeStream($tmp_file, $file_stream['stream']);
553
			}
554
			
555
			if($this->filesystem->get_tmp_filesystem()->has($tmp_file))
556
			{
557
				$is_tmp = 1;
558
				$last_position = $this->backup_archive->appendFileData($this->filesystem->get_tmp_filesystem_adapter()->applyPathPrefix($tmp_file), $file_info['target_path'], $start_at_byte, $byte_limit);
0 ignored issues
show
Bug introduced by
The method appendFileData() does not seem to exist on object<splitbrain\PHPArchive\Tar>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
559
			}
560
			else{
561
				$is_tmp = 0;
562
				$last_position = $this->backup_archive->appendFileData($start_adapter->applyPathPrefix($file_info['path']), $file_info['target_path'], $start_at_byte, $byte_limit);
0 ignored issues
show
Bug introduced by
The method appendFileData() does not seem to exist on object<splitbrain\PHPArchive\Tar>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
563
			}
564
				
565
			
566
			if($last_position == -1)
567
			{
568
				$bytes_wrote = $file_info['size'] - $start_at_byte;
569
			}
570
			else
571
			{
572
				$bytes_wrote = $last_position - $start_at_byte;
573
			}
574
			
575
			
576
			if($is_tmp)
577
			{
578
				$this->logger->info(sprintf("Appended %s bytes, starting position %s, of tmp file %s (%s) to archive %s ", $bytes_wrote, $start_at_byte, $tmp_file, $file_info['target_path'], $this->get_archive_name()));
579
			}
580
			else{
581
				$this->logger->info(sprintf("Appended %s bytes, starting position %s, of original file %s to archive %s ", $bytes_wrote, $start_at_byte, $file_info['target_path'], $tmp_file, $this->get_archive_name()));
582
			}
583
			
584
			//we delete here the isolated tmp file
585
			if($last_position == -1)
586
			{
587
				if($this->filesystem->get_tmp_filesystem_adapter()->has($tmp_file))
588
				{
589
					$this->logger->info(sprintf("Deleting %s from the tmp filesystem", $tmp_file));
590
					$this->filesystem->get_tmp_filesystem_adapter()->delete($tmp_file);
591
				}
592
			}
593
			
594
		}
595
		
596
		return array($bytes_wrote, $last_position);
597
	}
598
	    
599
    /**
600
     * Open a TAR archive and put the file cursor at the end for data appending
601
     *
602
     * If $file is empty, the tar file will be created in memory
603
     *
604
     * @param string $file
605
     * @throws ArchiveIOException
606
     */
607
    /*
0 ignored issues
show
Unused Code Comprehensibility introduced by
48% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
608
    public function openForAppend($file = '')
609
    {
610
        $this->file   = $file;
611
        $this->memory = '';
612
        $this->fh     = 0;
613
614
        if ($this->file) {
615
            // determine compression
616
            if ($this->comptype == Archive::COMPRESS_AUTO) {
617
                $this->setCompression($this->complevel, $this->filetype($file));
618
            }
619
620
            if ($this->comptype === Archive::COMPRESS_GZIP) {
621
                $this->fh = @gzopen($this->file, 'ab'.$this->complevel);
622
            } elseif ($this->comptype === Archive::COMPRESS_BZIP) {
623
                $this->fh = @bzopen($this->file, 'a');
624
            } else {
625
                $this->fh = @fopen($this->file, 'ab');
626
            }
627
628
            if (!$this->fh) {
629
                throw new ArchiveIOException('Could not open file for writing: '.$this->file);
630
            }
631
        }
632
        $this->backup_archive->writeaccess = true;
633
        $this->backup_archive->closed      = false;
634
    }
635
    */
636
    
637
     /**
638
     * Append data to a file to the current TAR archive using an existing file in the filesystem
639
     *
640
     * @param string          	$file     path to the original file
641
     * @param int          		$start    starting reading position in file
642
     * @param int          		$end      end position in reading multiple with 512
643
     * @param string|FileInfo $fileinfo either the name to us in archive (string) or a FileInfo oject with all meta data, empty to take from original
644
     * @throws ArchiveIOException
645
     */
646
    /*
0 ignored issues
show
Unused Code Comprehensibility introduced by
46% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
647
     * public function appendFileData($file, $fileinfo = '', $start = 0, $limit = 0)
648
    {
649
		$end = $start+($limit*512);
650
		
651
		//check to see if we are at the begining of writing the file
652
		if(!$start)
653
		{
654
	        if (is_string($fileinfo)) {
655
				$fileinfo = FileInfo::fromPath($file, $fileinfo);
656
	        }
657
		}
658
		
659
        if ($this->closed) {
660
            throw new ArchiveIOException('Archive has been closed, files can no longer be added');
661
        }
662
663
        $fp = fopen($file, 'rb');
664
        
665
        fseek($fp, $start);
666
        
667
        if (!$fp) {
668
            throw new ArchiveIOException('Could not open file for reading: '.$file);
669
        }
670
671
        // create file header
672
		if(!$start)
673
			$this->backup_archive->writeFileHeader($fileinfo);
674
		
675
		$bytes = 0;
676
        // write data
677
        while ($end >=ftell($fp) and !feof($fp) ) {
678
            $data = fread($fp, 512);
679
            if ($data === false) {
680
                break;
681
            }
682
            if ($data === '') {
683
                break;
684
            }
685
            $packed = pack("a512", $data);
686
            $bytes += $this->backup_archive->writebytes($packed);
687
        }
688
        
689
        
690
        
691
        //if we are not at the end of file, we return the current position for incremental writing
692
        if(!feof($fp))
693
			$last_position = ftell($fp);
694
		else
695
			$last_position = -1;
696
	
697
        fclose($fp);
698
        
699
        return $last_position;
700
    }*/
701
    
702
    /**
703
     * Adds a file to a TAR archive by appending it's data
704
     *
705
     * @param string $archive			name of the archive file
706
     * @param string $file				name of the file to read data from				
707
     * @param string $start				start position from where to start reading data
708
     * @throws ArchiveIOException
709
     */
710
	/*public function addFileToArchive($archive, $file, $start = 0)
0 ignored issues
show
Unused Code Comprehensibility introduced by
60% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
711
	{
712
		$this->openForAppend($archive);
713
		return $start = $this->appendFileData($file, $start, $this->file_size_per_request_limit);
714
	}
715
	*/
716
717
}
718