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 ( dc9fa8...f90b76 )
by Liuta
06:40
created

Xcloner_File_System::is_regex()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
use League\Flysystem\Config;
3
use League\Flysystem\Filesystem;
4
use League\Flysystem\Util;
5
use League\Flysystem\Adapter\Local;
6
7
class Xcloner_File_System{
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...
8
	
9
	private $excluded_files 			= "";
10
	private $additional_regex_patterns	= array();
11
	private $excluded_files_by_default	= array("administrator/backups", "wp-content/backups");
12
	private $included_files_handler 	= "backup_files.csv";
13
	private $temp_dir_handler 			= ".dir";
14
	public  $filesystem;
15
	public  $tmp_filesystem;
16
	public  $storage_filesystem;
17
	private $xcloner_settings_append;
0 ignored issues
show
Unused Code introduced by
The property $xcloner_settings_append is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
18
	private $xcloner_container;
19
	private $diff_timestamp_start		= "";
20
	
21
	private $logger;
22
	private $start_adapter;
23
	private $tmp_adapter;
24
	private $storage_adapter;
25
	private $xcloner_requirements;
0 ignored issues
show
Unused Code introduced by
The property $xcloner_requirements is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
26
	private $xcloner_settings;
27
	private $start_filesystem;
28
	private $tmp_filesystem_append;
29
	private $storage_filesystem_append;
30
	
31
	private $files_counter;
32
	private $files_size;
33
	private $last_logged_file;
34
	private $folders_to_process_per_session = 25;
35
	private $backup_archive_extensions = array("tar", "tgz", "tar.gz", "gz", "csv");
36
	private $backup_name_tags = array('[time]', '[hostname]', '[domain]');
37
	
38
	public function __construct(Xcloner $xcloner_container, $hash = "")
0 ignored issues
show
Unused Code introduced by
The parameter $hash 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...
39
	{
40
		$this->xcloner_container = $xcloner_container;
41
		
42
		$this->logger 				= $xcloner_container->get_xcloner_logger()->withName("xcloner_file_system");
43
		$this->xcloner_settings 	= $xcloner_container->get_xcloner_settings();
44
45
		try{
46
			
47
			$this->start_adapter = new Local($this->xcloner_settings->get_xcloner_start_path(),LOCK_EX, 'SKIP_LINKS');
48
			$this->start_filesystem = new Filesystem($this->start_adapter, new Config([
49
					'disable_asserts' => true,
50
				]));
51
			
52
			$this->tmp_adapter = new Local($this->xcloner_settings->get_xcloner_tmp_path(),LOCK_EX, 'SKIP_LINKS');
53
			$this->tmp_filesystem = new Filesystem($this->tmp_adapter, new Config([
54
					'disable_asserts' => true,
55
				]));
56
			$adapter = new Local($this->xcloner_settings->get_xcloner_tmp_path(),LOCK_EX|FILE_APPEND, 'SKIP_LINKS');
57
			$this->tmp_filesystem_append = new Filesystem($adapter, new Config([
58
					'disable_asserts' => true,
59
				]));
60
61
			$adapter = new Local($this->xcloner_settings->get_xcloner_store_path(),LOCK_EX, 'SKIP_LINKS');
62
			$this->storage_filesystem = new Filesystem($adapter, new Config([
63
					'disable_asserts' => true,
64
				]));	
65
			
66
			$this->storage_adapter = new Local($this->xcloner_settings->get_xcloner_store_path(),FILE_APPEND, 'SKIP_LINKS');
67
			$this->storage_filesystem_append = new Filesystem($this->storage_adapter, new Config([
68
					'disable_asserts' => true,
69
				]));
70
		}catch(Exception $e){
71
			$this->logger->error("Filesystem Initialization Error: ".$e->getMessage());
72
		}
73
		
74
		
75
		if($value = get_option('xcloner_directories_to_scan_per_request'))
76
			$this->folders_to_process_per_session = $value;
77
78
	}
79
	
80
	public function set_diff_timestamp_start($timestamp = "")
81
	{
82
		if($timestamp)
83
		{
84
			$this->logger->info(sprintf("Setting Differential Timestamp To %s", date("Y-m-d", $timestamp)), array("FILESYSTEM", "DIFF"));
85
			$this->diff_timestamp_start = $timestamp;
86
		}
87
	}
88
	
89
	public function get_diff_timestamp_start()
90
	{
91
		return $this->diff_timestamp_start;
92
	}
93
94
	private function get_xcloner_container()
95
	{
96
		return $this->xcloner_container;
97
	}
98
	
99
	
100
	public function set_hash($hash)
101
	{
102
		$this->xcloner_settings->set_hash($hash);
103
	}
104
	
105
	public function get_hash($hash)
0 ignored issues
show
Unused Code introduced by
The parameter $hash 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...
106
	{
107
		$this->xcloner_settings->get_hash();
108
	}
109
	
110
	public function get_tmp_filesystem()
111
	{
112
		return $this->tmp_filesystem;
113
	}
114
	
115
	public function get_storage_filesystem($remote_storage_selection = "")
116
	{
117
		if($remote_storage_selection != "")
118
		{
119
			$remote_storage = $this->get_xcloner_container()->get_xcloner_remote_storage();
120
			$method = "get_".$remote_storage_selection."_filesystem";
121
			
122
			if(!method_exists($remote_storage, $method))
123
				return false;
124
				
125
			list($adapter, $filesystem) = $remote_storage->$method();	
0 ignored issues
show
Unused Code introduced by
The assignment to $adapter 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...
126
			
127
			return $filesystem;
128
		}
129
130
		return $this->storage_filesystem;
131
	}
132
	
133
	public function get_tmp_filesystem_adapter()
134
	{
135
		return $this->tmp_adapter;
136
	}
137
	
138
	public function get_tmp_filesystem_append()
139
	{
140
		return $this->tmp_filesystem_append;
141
	}
142
	
143
	public function get_start_adapter()
144
	{
145
		return $this->start_adapter;
146
	}
147
	
148
	public function get_start_filesystem()
149
	{
150
		return $this->start_filesystem;
151
	}
152
	
153
	public function get_logger()
154
	{
155
		return $this->logger;
156
	}
157
	
158
	public function get_start_path_file_info($file)
159
	{
160
		$info= $this->getMetadataFull('start_adapter', $file);
161
		return $this->start_filesystem->normalizeFileInfo($info);
162
	}
163
	
164
	public function get_storage_path_file_info($file)
165
	{
166
		return $this->getMetadataFull('storage_adapter', $file);
167
	}
168
	
169
	public function get_included_files_handler($metadata  = 0)
170
	{
171
		$path = $this->included_files_handler;
172
		if(!$metadata)
173
			return $path;
174
		
175
		$spl_info = $this->getMetadataFull('tmp_adapter', $path);
176
		return $spl_info;
177
		
178
	}
179
		
180
	public function get_temp_dir_handler()
181
	{
182
		return $this->temp_dir_handler;
183
	}
184
	
185
	public function get_latest_backup()
186
	{
187
		$files = $this->get_backup_archives_list();
188
		
189
		if(is_array($files))
190
			$this->sort_by($files, "timestamp","desc");
191
		
192
		$new_list = array();
193
		
194 View Code Duplication
		foreach($files as $key=>$file)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
195
			if(!isset($file['parent']))
196
				$new_list[] = ($files[$key]);
197
198
		if(isset($new_list[0]))
199
			return $new_list[0];
200
	}
201
	
202
	public function get_latest_backups()
203
	{
204
		$files = $this->get_backup_archives_list();
205
206
		if(is_array($files))
207
			$this->sort_by($files, "timestamp","desc");
208
		
209
		$new_list = array();
210
		
211 View Code Duplication
		foreach($files as $key=>$file)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
212
			if(!isset($file['parent']))
213
				$new_list[] = ($files[$key]);
214
215
		return $new_list;
216
	}
217
	
218
	public function get_storage_usage()
219
	{
220
		$files = $this->get_backup_archives_list();
221
		$total = 0;
222
		
223
		if(is_array($files))
224
			foreach($files as $file)
225
				$total += $file['size'];
226
				
227
		return $total;		
228
	}
229
	
230
	public function is_part($backup_name)
231
	{
232
		if(stristr($backup_name, "-part"))
233
			return true;
234
		
235
		return false;	
236
	}
237
	
238
	public function is_multipart($backup_name)
239
	{
240
		if(stristr($backup_name, "-multipart"))
241
			return true;
242
		
243
		return false;	
244
	}
245
	
246 View Code Duplication
	public function get_backup_size($backup_name)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
247
	{
248
		$backup_size = $this->get_storage_filesystem()->getSize($backup_name);
249
		if($this->is_multipart($backup_name))
250
		{
251
			$backup_parts = $this->get_multipart_files($backup_name);
252
			foreach($backup_parts as $part_file)
253
				$backup_size += $this->get_storage_filesystem()->getSize($part_file);
254
		}
255
		
256
		return $backup_size;
257
	}
258
	
259 View Code Duplication
	public function get_multipart_files($backup_name, $storage_selection = "")
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
260
	{
261
		$files = array();
262
		
263
		if($this->is_multipart($backup_name))
264
		{
265
			$lines = explode(PHP_EOL, $this->get_storage_filesystem($storage_selection)->read($backup_name));
266
			foreach($lines as $line)
267
			{
268
				if($line)
269
				{
270
					$data = str_getcsv($line);
271
					$files[] = $data[0];
272
				}
273
			}
274
		}
275
		
276
		return $files;
277
	}
278
	
279
	public function delete_backup_by_name($backup_name, $storage_selection = "")
280
	{
281
		if($this->is_multipart($backup_name))
282
		{
283
			$lines = explode(PHP_EOL, $this->get_storage_filesystem($storage_selection)->read($backup_name));
284
			foreach($lines as $line)
285
			{
286
				if($line)
287
				{
288
					$data = str_getcsv($line);
289
					$this->get_storage_filesystem($storage_selection)->delete($data[0]);
290
				}
291
			}
292
		}
293
		
294
		if($this->get_storage_filesystem($storage_selection)->delete($backup_name))
295
			$return = true;
296
		else
297
			$return = false;
298
			
299
		return $return;	
300
	}
301
	
302
	public function getMetadataFull($adapter = "storage_adapter" , $path)
303
    {
304
        $location = $this->$adapter->applyPathPrefix($path);
305
        $spl_info = new SplFileInfo($location);
306
        
307
        return ($spl_info);
308
    }
309
	
310
	
311
	public function get_backup_archives_list($storage_selection = "")
312
	{
313
		$list = array();
314
		
315
316
		if(method_exists($this->get_storage_filesystem($storage_selection), "listContents"))
317
			$list = $this->get_storage_filesystem($storage_selection)->listContents();
318
319
		
320
		$backup_files = array();
321
		$parents = array();
322
		
323 View Code Duplication
		foreach($list as $file_info)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
324
		{
325
			if(isset($file_info['extension']) and $file_info['extension'] == "csv")
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...
326
			{
327
				$data = array();
0 ignored issues
show
Unused Code introduced by
$data 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...
328
				
329
				$lines = explode(PHP_EOL, $this->get_storage_filesystem($storage_selection)->read($file_info['path']));
330
				foreach($lines as $line)
331
					if($line)
332
					{
333
						$data = str_getcsv($line);
334
						if(is_array($data)){
335
							$parents[$data[0]] = $file_info['basename'];
336
							$file_info['childs'][] = $data;
337
							$file_info['size'] += $data[2];
338
						}
339
					}
340
						
341
			}
342
			
343
			if($file_info['type'] == 'file' and isset($file_info['extension']) and in_array($file_info['extension'], $this->backup_archive_extensions))
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...
344
				$backup_files[$file_info['path']] = $file_info;
345
		}
346
		
347
		foreach($backup_files as $key=>$file_info)
348
		{
349
			if(!isset($backup_files[$key]['timestamp']))
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
350
			{
351
				//$backup_files[$key]['timestamp'] = $this->get_storage_filesystem($storage_selection)->getTimestamp($file_info['path']);
0 ignored issues
show
Unused Code Comprehensibility introduced by
80% 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...
352
			}
353
			
354
			if(isset($parents[$file_info['basename']]))
355
				$backup_files[$key]['parent'] = $parents[$file_info['basename']];
356
		}
357
		
358
		return $backup_files;
359
	}
360
	
361
	public function start_file_recursion($init = 0)
362
	{
363
		if($init)
364
		{
365
			$this->logger->info(sprintf(__("Starting the filesystem scanner on root folder %s"), $this->xcloner_settings->get_xcloner_start_path()));
366
			$this->do_system_init();
367
		}
368
		
369
		if($this->tmp_filesystem->has($this->get_temp_dir_handler())){
370
		//.dir exists, we presume we have files to iterate	
371
			$content = $this->tmp_filesystem->read($this->get_temp_dir_handler());
372
			$files = array_filter(explode("\n", $content));
373
			$this->tmp_filesystem->delete($this->get_temp_dir_handler());
374
			
375
			$counter = 0;
376
			foreach($files as $file)
377
			{
378
				if($counter < $this->folders_to_process_per_session){
379
					$this->build_files_list($file);
380
					$counter++;
381
				}else{
382
					$this->tmp_filesystem_append->write($this->get_temp_dir_handler(), $file."\n");
383
				}
384
			}
385
		}else{
386
			$this->build_files_list();
387
		}
388
		
389
		if($this->scan_finished())
390
		{
391
			$metadata_dumpfile = $this->get_tmp_filesystem()->getMetadata("index.html");
392
			$this->store_file($metadata_dumpfile, 'tmp_filesystem');
393
			$this->files_counter++;
394
		
395
			//adding included dump file to the included files list
396
			if($this->get_tmp_filesystem()->has($this->get_included_files_handler()))
0 ignored issues
show
Bug introduced by
It seems like $this->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...
397
			{
398
				$metadata_dumpfile = $this->get_tmp_filesystem()->getMetadata($this->get_included_files_handler());
0 ignored issues
show
Bug introduced by
It seems like $this->get_included_files_handler() targeting Xcloner_File_System::get_included_files_handler() can also be of type object<SplFileInfo>; however, League\Flysystem\Filesystem::getMetadata() 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...
399
				$this->store_file($metadata_dumpfile, 'tmp_filesystem');
400
				$this->files_counter++;
401
			}
402
		
403
			//adding a default index.html to the temp xcloner folder
404
			if(!$this->get_tmp_filesystem()->has("index.html"))
405
			{
406
				$this->get_tmp_filesystem()->write("index.html","");
407
			}
408
			
409
			//adding the default log file
410
			if($this->get_tmp_filesystem()->has($this->xcloner_settings->get_logger_filename(1)))
411
			{
412
				$metadata_dumpfile = $this->get_tmp_filesystem()->getMetadata($this->xcloner_settings->get_logger_filename(1));
413
				$this->store_file($metadata_dumpfile, 'tmp_filesystem');
414
				$this->files_counter++;
415
			}
416
		
417
			return false;
418
		}	
419
	
420
		return true;	
421
	}
422
	
423
	public function get_backup_attachments()
424
	{
425
		$return = array();
426
		
427
		$files_list_file = $this->xcloner_settings->get_xcloner_tmp_path().DS.$this->get_included_files_handler();
428
		if(file_exists($files_list_file))
429
			{
430
				$return[] = $files_list_file;
431
			}
432
			
433
		if($this->xcloner_settings->get_xcloner_option('xcloner_enable_log'))
434
		{
435
			$log_file = $this->xcloner_settings->get_xcloner_tmp_path().DS.$this->xcloner_settings->get_logger_filename(1);
436
			if(!file_exists($log_file))
437
			{
438
				$log_file = $this->xcloner_settings->get_xcloner_store_path().DS.$this->xcloner_settings->get_logger_filename();
439
			}
440
			
441
			if(file_exists($log_file))
442
			{
443
				$return[] = $log_file;
444
			}
445
		}
446
		
447
		return $return;
448
	}
449
	
450
	public function remove_tmp_filesystem()
451
	{
452
		//delete the temporary folder
453
		$this->logger->info(sprintf("Deleting the temporary storage folder %s", $this->xcloner_settings->get_xcloner_tmp_path()));
454
		
455
		$contents = $this->get_tmp_filesystem()->listContents();
456
	
457
		if(is_array($contents))
458
		foreach($contents as $file_info)
459
			$this->get_tmp_filesystem()->delete($file_info['path']);
460
			
461
		@rmdir($this->xcloner_settings->get_xcloner_tmp_path());
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
462
		
463
		return;
464
	}
465
	
466
	public function cleanup_tmp_directories()
467
	{
468
		$adapter = new Local($this->xcloner_settings->get_xcloner_tmp_path(false),LOCK_EX|FILE_APPEND, 'SKIP_LINKS');
469
		$tmp_filesystem = new Filesystem($adapter, new Config([
470
					'disable_asserts' => true,
471
				]));
472
				
473
		$contents = $tmp_filesystem->listContents();
474
		
475
		foreach($contents as $file)
476
		{
477 View Code Duplication
			if(preg_match("/.xcloner-(.*)/",$file['path']))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
478
			{
479
				$tmp_filesystem->deleteDir($file['path']);
480
				$this->logger->info(sprintf("Delete temporary directory %s", $file['path']));
481
			}
482
		}
483
		
484
		return true;
485
	}
486
	
487
	private function do_system_init()
488
	{
489
		$this->files_counter = 0;
490
		
491
		if(!$this->storage_filesystem->has("index.html"))	
492
			$this->storage_filesystem->write("index.html","");
493
		
494
		if(!$this->tmp_filesystem->has("index.html"))	
495
			$this->tmp_filesystem->write("index.html","");
496
			
497
		if($this->tmp_filesystem->has($this->get_included_files_handler()))
0 ignored issues
show
Bug introduced by
It seems like $this->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...
498
			$this->tmp_filesystem->delete($this->get_included_files_handler());
0 ignored issues
show
Bug introduced by
It seems like $this->get_included_files_handler() targeting Xcloner_File_System::get_included_files_handler() can also be of type object<SplFileInfo>; however, League\Flysystem\Filesystem::delete() 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...
499
		
500
		if($this->tmp_filesystem->has($this->get_temp_dir_handler()))	
501
			$this->tmp_filesystem->delete($this->get_temp_dir_handler());
502
	}
503
	
504
	public function get_scanned_files_num()
505
	{
506
		return $this->files_counter;
507
	}
508
	
509
	public function get_scanned_files_total_size()
510
	{
511
		return $this->files_size;
512
	}
513
	
514
	public function last_logged_file()
515
	{
516
		return $this->last_logged_file;
517
	}
518
	
519
	public static function is_regex($regex) {
520
		return preg_match("/^\^(.*)\$$/i",$regex);
521
	}
522
	
523
	public function set_excluded_files($excluded_files = array())
524
	{
525
		if(!is_array($excluded_files))
526
		{
527
			$excluded_files = array();
528
		}
529
		
530
		foreach($excluded_files as $excl)
531
		{
532
			
533
			if($this->is_regex($excl))
534
			{
535
				$this->additional_regex_patterns[] = $excl;
536
			}
537
		}
538
		
539
		$this->excluded_files = array_merge($excluded_files, $this->excluded_files_by_default);
0 ignored issues
show
Documentation Bug introduced by
It seems like array_merge($excluded_fi...luded_files_by_default) of type array is incompatible with the declared type string of property $excluded_files.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
540
		
541
		return $this->excluded_files;
542
	}
543
	
544
	public function get_excluded_files()
545
	{
546
		return $this->excluded_files_by_default;
547
	}
548
	
549
	public function list_directory($path)
550
	{
551
		return $this->start_filesystem->listContents($path);
552
	}
553
	
554
	public function build_files_list($folder = "")
555
	{
556
		$this->logger->debug(sprintf(("Building the files system list")));
557
		
558
		//if we start with the root folder(empty value), we initializa the file system
559
		if(!$folder){
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
560
			
561
		}
562
			
563
		try{
564
			
565
			$files = $this->start_filesystem->listContents($folder);
566
			foreach($files as $file)
567
			{
568
				if(!is_readable($this->xcloner_settings->get_xcloner_start_path().DS.$file['path']))
569
				{
570
					$this->logger->info(sprintf(__("Excluding %s from the filesystem list, file not readable"), $file['path']), array("FILESYSTEM SCAN","NOT READABLE"));
571
				}
572
				elseif(!$matching_pattern = $this->is_excluded($file) ){
573
					$this->logger->info(sprintf(__("Adding %s to the filesystem list"), $file['path']), array("FILESYSTEM SCAN","INCLUDE"));
574
					$file['visibility'] = $this->start_filesystem->getVisibility($file['path']);
575
					if($this->store_file($file))
576
					{
577
						$this->files_counter++;
578
					}
579
					if(isset($file['size']))
580
						$this->files_size += $file['size'];
581
					
582
				}else{
583
					$this->logger->info(sprintf(__("Excluding %s from the filesystem list, matching pattern %s"), $file['path'], $matching_pattern), array("FILESYSTEM SCAN","EXCLUDE"));
584
					}
585
			}
586
			
587
		}catch(Exception $e){
588
			
589
			$this->logger->error($e->getMessage());
590
		
591
		}
592
			
593
	}
594
	
595
	public function estimate_read_write_time()
596
	{
597
		$tmp_file = ".xcloner".substr(md5(time()), 0, 5);
598
				
599
		$start_time = microtime();
600
		
601
		$data = str_repeat(rand(0,9), 1024*1024); //write 1MB data
602
		
603
		try{
604
			$this->tmp_filesystem->write($tmp_file, $data);
605
			
606
			$end_time = microtime() - $start_time;
607
		
608
			$return['writing_time'] = $end_time;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$return was never initialized. Although not strictly required by PHP, it is generally a good practice to add $return = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
609
		
610
			$return['reading_time']	= $this->estimate_reading_time($tmp_file);
611
		
612
			$this->tmp_filesystem->delete($tmp_file);
613
		
614
		}catch(Exception $e){
615
			
616
			$this->logger->error($e->getMessage());
617
			
618
		}
619
		
620
		return $return;
0 ignored issues
show
Bug introduced by
The variable $return 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...
621
	}
622
	
623
	public function backup_storage_cleanup()
624
	{
625
		$this->logger->info(sprintf(("Cleaning the backup storage on matching rules")));
626
		
627
		$_storage_size = 0;
628
		$_backup_files_list = array();
629
		
630
		//rule date limit
631
		$current_timestamp = strtotime("-".$this->xcloner_settings->get_xcloner_option('xcloner_cleanup_retention_limit_days')." days");
632
		
633
		$files = $this->storage_filesystem->listContents();
634
		
635
		if(is_array($files))
636
			foreach($files as $file)
637
			{
638
				if(isset($file['extension']) and in_array($file['extension'], $this->backup_archive_extensions))
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...
639
				{
640
					$_storage_size += $file['size']; //bytes
641
					$_backup_files_list[] = $file;
642
				}
643
			}
644
		
645
		
646
		$this->sort_by($_backup_files_list, "timestamp","asc");
647
		
648
		$_backups_counter = sizeof($_backup_files_list);
649
				
650
		foreach($_backup_files_list as $file)
651
		{
652
			//processing rule folder capacity
653
			if($this->xcloner_settings->get_xcloner_option('xcloner_cleanup_capacity_limit') &&
654
			$_storage_size >= ($set_storage_limit = 1024*1024*$this->xcloner_settings->get_xcloner_option('xcloner_cleanup_capacity_limit')))	//bytes	
655
			{
656
				$this->storage_filesystem->delete($file['path']);
657
				$_storage_size -= $file['size'];
658
				$this->logger->info("Deleting backup ".$file['path']." matching rule", array("STORAGE SIZE LIMIT", $_storage_size." >= ".$set_storage_limit));
659
			}
660
			
661
			//processing rule days limit
662 View Code Duplication
			if($this->xcloner_settings->get_xcloner_option('xcloner_cleanup_retention_limit_days') && $current_timestamp >= $file['timestamp'])
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
663
			{
664
				$this->storage_filesystem->delete($file['path']);
665
				$this->logger->info("Deleting backup ".$file['path']." matching rule", array("RETENTION LIMIT TIMESTAMP", $file['timestamp']." =< ".$this->xcloner_settings->get_xcloner_option('xcloner_cleanup_retention_limit_days')));
666
			}
667
			
668
			//processing backup countert limit
669 View Code Duplication
			if($this->xcloner_settings->get_xcloner_option('xcloner_cleanup_retention_limit_archives') && $_backups_counter >= $this->xcloner_settings->get_xcloner_option('xcloner_cleanup_retention_limit_archives'))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
670
			{
671
				$this->storage_filesystem->delete($file['path']);
672
				$_backups_counter--;
673
				$this->logger->info("Deleting backup ".$file['path']." matching rule", array("BACKUP QUANTITY LIMIT", $_backups_counter." >= ".$this->xcloner_settings->get_xcloner_option('xcloner_cleanup_retention_limit_archives')));
674
			}
675
			
676
				
677
		}
678
		
679
	}
680
	
681
	public function estimate_reading_time($tmp_file)
682
	{
683
		$this->logger->debug(sprintf(("Estimating file system reading time")));
684
		
685
		$start_time = microtime();
686
		
687
		$this->tmp_filesystem->read($tmp_file);
688
		
689
		$end_time = microtime() - $start_time;
690
		
691
		return $end_time;
692
	
693
	}
694
	
695
	public function process_backup_name($name = "", $max_length=100)
696
	{
697
		if(!$name)
698
			$name = $this->xcloner_settings->get_default_backup_name();
699
		
700
		foreach($this->backup_name_tags as $tag)
701
		{
702
			if($tag == '[time]')
703
				$name = str_replace($tag, date("Y-m-d_H-i"),$name);
704
			elseif($tag == '[hostname]')
705
				$name = str_replace($tag, gethostname() ,$name);	
706
			elseif($tag == '[domain]')
707
			{
708
				$domain = parse_url(admin_url(), PHP_URL_HOST);
709
				$name = str_replace($tag, $domain ,$name);	
710
			}
711
		}
712
		
713
		if($max_length)
714
			$name = substr($name, 0, $max_length);
715
			
716
		return $name;	
717
	}
718
	
719
	public function sort_by( &$array, $field, $direction = 'asc')
720
	{
721
		if(strtolower($direction) == "desc" || $direction == SORT_DESC)
722
			$direction = SORT_DESC;
723
		else
724
			$direction = SORT_ASC;
725
					
726
	   $array = $this->array_orderby($array, $field, $direction);
727
	    
728
	   return true;
729
	}
730
	
731
	private function array_orderby()
732
	{
733
	    $args = func_get_args();
734
	    $data = array_shift($args);
735
	    
736
	    foreach ($args as $n => $field) {
737
	        if (is_string($field)) {
738
	            $tmp = array();
739
	            foreach ($data as $key => $row)
740
	            {
741
					if(is_array($row))
742
						$tmp[$key] = $row[$field];
743
					else
744
						$tmp[$key] = $row->$field;
745
				}
746
	            $args[$n] = $tmp;
747
	            }
748
	    }
749
	    $args[] = &$data;
750
	    
751
	    call_user_func_array('array_multisort', $args);
752
	    
753
	    return array_pop($args);
754
	}
755
	
756
	private function check_file_diff_time($file)
757
	{
758
		if($this->get_diff_timestamp_start() != "")
759
		{
760
			$fileMeta = $this->getMetadataFull("start_adapter", $file['path']);
761
			$timestamp = $fileMeta->getMTime();
762
			if($timestamp < $fileMeta->getCTime())
763
			{
764
				$timestamp = $fileMeta->getCTime();
765
			}
766
			
767
			if($timestamp <= $this->get_diff_timestamp_start())
768
			{
769
				return  " file DIFF timestamp ".$timestamp." < ". $this->diff_timestamp_start;
770
			}
771
		}
772
		
773
		return false;
774
	}
775
	
776
	public function is_excluded($file)
777
	{
778
		$this->logger->debug(sprintf(("Checking if %s is excluded"), $file['path']));
779
		
780
		if($xcloner_exclude_files_larger_than_mb = $this->xcloner_settings->get_xcloner_option('xcloner_exclude_files_larger_than_mb'))
781
		{
782
			if(isset($file['size']) && $file['size'] > $this->calc_to_bytes($xcloner_exclude_files_larger_than_mb))
783
				return "> ".$xcloner_exclude_files_larger_than_mb."MB";
784
		}
785
		
786
		if(!sizeof($this->excluded_files))
787
		{
788
			$this->set_excluded_files();
789
		}
790
						
791
		if(is_array($this->excluded_files))
792
		foreach($this->excluded_files as $excluded_file_pattern)
793
		{
794
			if($excluded_file_pattern == "/")
795
				$needle = "$";
796
			else
797
				$needle = "$".$excluded_file_pattern;
798
				
799
			if(strstr("$".$file['path'], $needle)){
800
				return $excluded_file_pattern;
801
			}
802
		}
803
		
804
		if( $regex = $this->is_excluded_regex($file))
805
			return $regex;
806
		
807
		if($file['type'] == "file")
808
		{
809
			$check_file_diff_timestamp = $this->check_file_diff_time($file);
810
			if($check_file_diff_timestamp)
0 ignored issues
show
Bug Best Practice introduced by
The expression $check_file_diff_timestamp of type string|false is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
811
			{
812
				return $check_file_diff_timestamp;
813
			}
814
		}
815
		
816
		return false;
817
	}
818
	
819
	/*REGEX examples
820
	 * 
821
	* exclude all except .php file
822
	* PATTERN: ^(.*)\.(.+)$(?<!(php))
823
	* 
824
	* exclude all except .php and .txt
825
	* PATTERN: ^(.*)\.(.+)$(?<!(php|txt))";
826
	* 
827
	* exclude all .svn and .git
828
	* PATTERN: ^(.*)\.(svn|git)(.*)$";
829
	* 
830
	* exclude root directory /test
831
	* PATTERN: "^\/test(.*)$";
832
	* 
833
	* exclude the wp-admin folder
834
	* PATTERN: ^(\/wp-admin)(.*)$";
835
	* 
836
	* exclude the wp-admin, wp-includes and wp-config.php
837
	* PATTERN: ^\/(wp-admin|wp-includes|wp-config.php)(.*)$";
838
	* 
839
	* exclude all .avi files
840
	* PATTERN: ^(.*)$(?<=(avi))";
841
	* 
842
	* exclude all .jpg and gif files
843
	* PATTERN: ^(.*)$(?<=(gif|jpg))";
844
	* 
845
	* exclude all cache folders from wp-content/
846
	* PATTERN: ^\/wp-content(.*)\/cache($|\/)(.*)";
847
	* 
848
	* exclude the backup folders
849
	* PATTERN: (^|^\/)(wp-content\/backups|administrator\/backups)(.*)$";
850
	*/
851
	private function is_excluded_regex($file)
852
	{
853
		//$this->logger->debug(sprintf(("Checking if %s is excluded"), $file['path']));
0 ignored issues
show
Unused Code Comprehensibility introduced by
80% 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...
854
		
855
		$regex_patterns = explode(PHP_EOL, $this->xcloner_settings->get_xcloner_option('xcloner_regex_exclude'));
856
		
857
		if(is_array($this->additional_regex_patterns))
858
		{
859
			$regex_patterns = array_merge($regex_patterns, $this->additional_regex_patterns);
860
		}
861
		
862
		//print_r($regex_patterns);exit;
0 ignored issues
show
Unused Code Comprehensibility introduced by
86% 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...
863
		
864
		if(is_array($regex_patterns))
865
		{
866
			//$this->excluded_files = array();
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...
867
			//$this->excluded_files[] ="(.*)\.(git)(.*)$";
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% 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...
868
			//$this->excluded_files[] ="wp-content\/backups(.*)$";
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% 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...
869
			
870
			foreach($regex_patterns as $excluded_file_pattern)
871
			{
872
				
873
				if( substr($excluded_file_pattern, strlen($excluded_file_pattern)-1, strlen($excluded_file_pattern)) == "\r")
874
					$excluded_file_pattern = substr($excluded_file_pattern, 0, strlen($excluded_file_pattern)-1);
875
					
876
				if($file['path'] == "/")
877
					$needle = "/";
878
				else
879
					$needle = "/".$file['path'];
880
				//echo $needle."---".$excluded_file_pattern."---\n";
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...
881
				
882
				if(@preg_match("/(^|^\/)".$excluded_file_pattern."/i", $needle)){
883
					return $excluded_file_pattern;
884
				}
885
			}
886
		}
887
		
888
		return false;
889
	}
890
	
891
	public function store_file($file, $storage = 'start_filesystem')
892
	{
893
		$this->logger->debug(sprintf("Storing %s in the backup list", $file['path']));
894
		
895
		if(!isset($file['size']))
896
			$file['size'] = 0;
897
		if(!isset($file['visibility']))	
898
			$file['visibility'] = "private";
899
		
900
		$csv_filename = str_replace('"','""', $file['path']);
901
		
902
		$line = '"'.($csv_filename).'","'.$file['timestamp'].'","'.$file['size'].'","'.$file['visibility'].'","'.$storage.'"'.PHP_EOL;
903
		
904
		$this->last_logged_file = $file['path'];
905
		
906
		if($file['type'] == "dir"){
907
			try{
908
				$this->tmp_filesystem_append->write($this->get_temp_dir_handler(), $file['path']."\n");
909
			}catch(Exception $e){
910
				$this->logger->error($e->getMessage());	
911
			}
912
		}
913
		
914
		if($this->get_diff_timestamp_start())
915
		{
916
			if($file['type'] != "file" && $response = $this->check_file_diff_time($file))
917
			{
918
				$this->logger->info(sprintf("Directory %s archiving skipped on differential backup %s", $file['path'], $response), array("FILESYSTEM SCAN","DIR DIFF"));
919
				return false;
920
			}
921
		}
922
		
923
		try{
924
			if(!$this->tmp_filesystem_append->has($this->get_included_files_handler()))
0 ignored issues
show
Bug introduced by
It seems like $this->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...
925
			{
926
				//adding fix for UTF-8 CSV preview
927
				$start_line = "\xEF\xBB\xBF".'"Filename","Timestamp","Size","Visibility","Storage"'.PHP_EOL;
928
				$this->tmp_filesystem_append->write($this->get_included_files_handler(), $start_line);
0 ignored issues
show
Bug introduced by
It seems like $this->get_included_files_handler() targeting Xcloner_File_System::get_included_files_handler() can also be of type object<SplFileInfo>; however, League\Flysystem\Filesystem::write() 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...
929
			}
930
			
931
			$this->tmp_filesystem_append->write($this->get_included_files_handler(), $line);
0 ignored issues
show
Bug introduced by
It seems like $this->get_included_files_handler() targeting Xcloner_File_System::get_included_files_handler() can also be of type object<SplFileInfo>; however, League\Flysystem\Filesystem::write() 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...
932
		
933
		}catch(Exception $e){
934
		
935
			$this->logger->error($e->getMessage());	
936
		}
937
		
938
		return true;
939
	}
940
	
941
	public function get_fileystem_handler()
942
	{
943
		return $this;
944
	}
945
	
946
	public function get_filesystem($system = "")
947
	{
948
		if($system == "storage_filesystem_append")
949
			return $this->storage_filesystem_append;
950
		elseif($system == "tmp_filesystem_append")
951
			return $this->tmp_filesystem_append;
952
		elseif($system == "tmp_filesystem")
953
			return $this->tmp_filesystem;
954
		elseif($system == "storage_filesystem")
955
			return $this->storage_filesystem;
956
		else
957
			return $this->start_filesystem;	
958
	}
959
	
960
	public function get_adapter($system)
961
	{
962
		if($system == "tmp_filesystem")
963
			return $this->tmp_adapter;
964
		elseif($system == "storage_filesystem")
965
			return $this->storage_adapter;
966
		else
967
			return $this->start_adapter;	
968
	}
969
	
970
	private function scan_finished()
971
	{
972
		if($this->tmp_filesystem_append->has($this->get_temp_dir_handler()) && $this->tmp_filesystem_append->getSize($this->get_temp_dir_handler()))
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->tmp_filesystem_ap...get_temp_dir_handler()) of type false|integer is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
973
			return false;
974
		
975
		if($this->tmp_filesystem->has($this->get_temp_dir_handler()))
976
			$this->tmp_filesystem->delete($this->get_temp_dir_handler());
977
		
978
		$this->logger->debug(sprintf(("File scan finished")));
979
			
980
		return true;
981
	}
982
	
983
	private function calc_to_bytes($mb_size)
984
	{
985
		return $mb_size*(1024*1024);
986
	}
987
	
988
}
989