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_Api::get_scheduler_list()   C

Complexity

Conditions 9
Paths 73

Size

Total Lines 67
Code Lines 38

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
eloc 38
nc 73
nop 0
dl 0
loc 67
rs 6.3448
c 0
b 0
f 0

How to fix   Long Method   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
3
use League\Flysystem\Config;
4
use League\Flysystem\Filesystem;
5
use League\Flysystem\Util;
6
use League\Flysystem\Adapter\Local;
7
8
use splitbrain\PHPArchive\Tar;
9
use splitbrain\PHPArchive\Zip;
10
use splitbrain\PHPArchive\Archive;
11
use splitbrain\PHPArchive\FileInfo;
12
13
14
class Xcloner_Api{
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...
15
16
	private $xcloner_database;
17
	private $xcloner_settings;
18
	private $xcloner_file_system;
19
	private $xcloner_requirements;
20
	private $xcloner_sanitization;
21
	private $archive_system;
22
	private $form_params;
23
	private $logger;
24
	private $xcloner_container;
25
	
26
	public function __construct(Xcloner $xcloner_container)
0 ignored issues
show
Coding Style introduced by
__construct uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

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

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
27
	{
28
		global $wpdb;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
29
		
30
		if(WP_DEBUG)
31
		{
32
			error_reporting(0);
33
		}
34
		
35
		if( ob_get_length() )
36
			ob_end_clean();
37
		ob_start();
38
		
39
		$wpdb->show_errors			= false;
40
			
41
		$this->xcloner_container	= $xcloner_container;
42
				
43
		$this->xcloner_settings 	= $xcloner_container->get_xcloner_settings();
44
		$this->logger				= $xcloner_container->get_xcloner_logger()->withName("xcloner_api");
45
		$this->xcloner_file_system 	= $xcloner_container->get_xcloner_filesystem();
46
		$this->xcloner_sanitization = $xcloner_container->get_xcloner_sanitization();
47
		$this->xcloner_requirements = $xcloner_container->get_xcloner_requirements();
48
		$this->archive_system 		=  $xcloner_container->get_archive_system();
49
		$this->xcloner_database 	=  $xcloner_container->get_xcloner_database();
50
		$this->xcloner_scheduler 	=  $xcloner_container->get_xcloner_scheduler();
0 ignored issues
show
Bug introduced by
The property xcloner_scheduler does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
51
		
52
		if(isset($_POST['API_ID'])){
53
			$this->logger->info("Processing ajax request ID ".substr($this->xcloner_sanitization->sanitize_input_as_string($_POST['API_ID']), 0 , 15));
54
		}
55
		
56
	}
57
	
58
	public function get_xcloner_container()
59
	{
60
		return $this->xcloner_container;
61
	}
62
	
63
	private function check_access()
64
	{
65
		if (function_exists('current_user_can') && !current_user_can('manage_options')) {
66
			die("Not allowed access here!");
0 ignored issues
show
Coding Style Compatibility introduced by
The method check_access() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
67
		}
68
	}
69
	
70
	public function init_db()
71
	{
72
		return;
73
		
74
		
75
		$data['dbHostname'] = $this->xcloner_settings->get_db_hostname();
0 ignored issues
show
Unused Code introduced by
$data['dbHostname'] = $t...ngs->get_db_hostname(); does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
76
		$data['dbUsername'] = $this->xcloner_settings->get_db_username();
77
		$data['dbPassword'] = $this->xcloner_settings->get_db_password();
78
		$data['dbDatabase'] = $this->xcloner_settings->get_db_database();
79
		
80
		
81
		$data['recordsPerSession'] 		= $this->xcloner_settings->get_xcloner_option('xcloner_database_records_per_request');
82
		$data['TEMP_DBPROCESS_FILE'] 	= $this->xcloner_settings->get_xcloner_tmp_path().DS.".database";
83
		$data['TEMP_DUMP_FILE'] 		= $this->xcloner_settings->get_xcloner_tmp_path().DS."database-sql.sql";
84
		
85
		try
86
		{
87
			$this->xcloner_database->init($data);
88
89
		}catch(Exception $e){
90
			
91
			$this->send_response($e->getMessage());
92
			$this->logger->error($e->getMessage());
93
			
94
		}
95
		
96
		return $this->xcloner_database;
97
		
98
	
99
	}
100
	
101
	/*
102
	 * 
103
	 * Save Schedule API
104
	 */
105
	public function save_schedule()
0 ignored issues
show
Coding Style introduced by
save_schedule uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

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

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
106
	{
107
		global $wpdb; 
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
108
		
109
		$this->check_access();
110
		
111
		$scheduler = $this->xcloner_scheduler;
112
		$params = array();
113
		$schedule = array();
114
		$response = array();
115
		
116
		if(isset($_POST['data']))
117
			$params = json_decode(stripslashes($_POST['data']));
118
		
119
		$this->process_params($params);
120
		
121
		if(isset($_POST['id']))
122
		{
123
			
124
			$this->form_params['backup_params']['backup_name'] = $this->xcloner_sanitization->sanitize_input_as_string($_POST['backup_name']);
125
			$this->form_params['backup_params']['email_notification'] = $this->xcloner_sanitization->sanitize_input_as_string($_POST['email_notification']);
126
			if($_POST['diff_start_date']){
127
				$this->form_params['backup_params']['diff_start_date'] = strtotime($this->xcloner_sanitization->sanitize_input_as_string($_POST['diff_start_date']));
128
			}else{
129
				$this->form_params['backup_params']['diff_start_date'] = "";
130
				}
131
			$this->form_params['backup_params']['schedule_name'] = $this->xcloner_sanitization->sanitize_input_as_string($_POST['schedule_name']);
132
			$this->form_params['backup_params']['start_at'] = strtotime($_POST['schedule_start_date']);
133
			$this->form_params['backup_params']['schedule_frequency'] = $this->xcloner_sanitization->sanitize_input_as_string($_POST['schedule_frequency']);
134
			$this->form_params['backup_params']['schedule_storage'] = $this->xcloner_sanitization->sanitize_input_as_string($_POST['schedule_storage']);
135
			$this->form_params['database'] = (stripslashes($this->xcloner_sanitization->sanitize_input_as_raw($_POST['table_params'])));
136
			$this->form_params['excluded_files'] = (stripslashes($this->xcloner_sanitization->sanitize_input_as_raw($_POST['excluded_files'])));
137
			
138
			//$this->form_params['backup_params']['backup_type'] = $this->xcloner_sanitization->sanitize_input_as_string($_POST['backup_type']);
0 ignored issues
show
Unused Code Comprehensibility introduced by
75% 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...
139
			
140
			$tables = explode(PHP_EOL, $this->form_params['database']);
141
			$return = array();
142
			
143
			foreach($tables as $table)
144
			{
145
					$table = str_replace("\r","", $table);
146
					$data = explode(".", $table);
147
					if(isset($data[1]))
148
						$return[$data[0]][] = $data[1];
149
			}
150
			
151
			$this->form_params['database'] = ($return);
152
			
153
			$excluded_files = explode(PHP_EOL, $this->form_params['excluded_files']);
154
			$return = array();
155
			
156
			foreach($excluded_files as $file)
157
			{
158
				$file = str_replace("\r","", $file);
159
				if($file)
160
					$return[] = $file;
161
			}
162
			
163
			$this->form_params['excluded_files'] = ($return);
164
			
165
			$schedule['start_at'] = $this->form_params['backup_params']['start_at'];
166
			
167
			if(!isset($_POST['status']))
168
				$schedule['status'] = 0;
169
			else	
170
				$schedule['status'] = $this->xcloner_sanitization->sanitize_input_as_int($_POST['status']);
171
		}else{
172
		
173
			$schedule['status'] = 1;
174
			$schedule['start_at'] = strtotime($this->form_params['backup_params']['schedule_start_date'] .
175
								" ".$this->form_params['backup_params']['schedule_start_time']);
176
			
177
			if($schedule['start_at'] <= time())
178
			{
179
				$schedule['start_at'] = "";
180
			}
181
		}
182
		
183
		if(!$schedule['start_at'])						
184
		{
185
			$schedule['start_at'] = date('Y-m-d H:i:s', time());
186
		}else{
187
			$schedule['start_at'] = date('Y-m-d H:i:s', $schedule['start_at'] - (get_option( 'gmt_offset' ) * HOUR_IN_SECONDS) );	
188
		}
189
		
190
		$schedule['name'] = $this->form_params['backup_params']['schedule_name'];
191
		$schedule['recurrence'] = $this->form_params['backup_params']['schedule_frequency'];
192
		$schedule['remote_storage'] = $this->form_params['backup_params']['schedule_storage'];
193
		//$schedule['backup_type'] = $this->form_params['backup_params']['backup_type'];
0 ignored issues
show
Unused Code Comprehensibility introduced by
77% 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...
194
		$schedule['params'] = json_encode($this->form_params);
195
196
		if(!isset($_POST['id']))
197
		{
198
			$wpdb->insert( 
199
				$wpdb->prefix.'xcloner_scheduler', 
200
				$schedule, 
201
				array( 
202
					'%s', 
203
					'%s' 
204
				) 
205
			);
206
		}else		{
207
			$wpdb->update( 
208
				$wpdb->prefix.'xcloner_scheduler', 
209
				$schedule, 
210
				array( 'id' => $_POST['id'] ), 
211
				array( 
212
					'%s', 
213
					'%s' 
214
				) 
215
			);
216
		}
217
		if(isset($_POST['id']))
218
		{
219
			$scheduler->update_cron_hook($_POST['id']);
220
		}
221
			
222
		if( $wpdb->last_error ) {
223
            $response['error'] = 1;
224
            $response['error_message'] = $wpdb->last_error/*."--".$wpdb->last_query*/;
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% 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...
225
            
226
        }
227
        
228
        $scheduler->update_wp_cron_hooks();
229
		$response['finished'] = 1;
230
		
231
		$this->send_response($response);
232
	}
233
	
234
	/*
235
	 * 
236
	 * Backup Files API
237
	 * 
238
	 */ 
239
	public function backup_files()
0 ignored issues
show
Coding Style introduced by
backup_files uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

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

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
240
	{
241
		$this->check_access();
242
		
243
		$params = json_decode(stripslashes($_POST['data']));
244
		
245
		$init 	= (int)$_POST['init'];
246
		
247
		if($params === NULL)
248
			 die( '{"status":false,"msg":"The post_data parameter must be valid JSON"}' );
0 ignored issues
show
Coding Style Compatibility introduced by
The method backup_files() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
249
			 
250
		$this->process_params($params);
251
		
252
		$return['finished'] = 1;
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...
253
254
		//$return = $this->archive_system->start_incremental_backup($this->form_params['backup_params'], $this->form_params['extra'], $init);
0 ignored issues
show
Unused Code Comprehensibility introduced by
69% 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...
255
		try{
256
			$return = $this->archive_system->start_incremental_backup($this->form_params['backup_params'], $this->form_params['extra'], $init);
257
		}catch(Exception $e)
258
		{
259
			$return = array();
260
			$return['error'] = true;
261
			$return['status'] = 500;
262
			$return['error_message'] = $e->getMessage();
263
			return $this->send_response($return, $hash = 1);
264
		}
265
		
266
		if($return['finished'])
267
		{
268
			$return['extra']['backup_parent'] = $this->archive_system->get_archive_name_with_extension();
269 View Code Duplication
			if($this->xcloner_file_system->is_part($this->archive_system->get_archive_name_with_extension()))
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...
270
				$return['extra']['backup_parent'] = $this->archive_system->get_archive_name_multipart();
271
		}
272
		
273
		$data = $return;
274
		
275
		//check if backup is finished
276
		if($return['finished'] )
277
		{
278
			if(isset($this->form_params['backup_params']['email_notification']) and $to=$this->form_params['backup_params']['email_notification'])
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...
279
			{
280
				try{
281
					$from = "";
282
					$subject = "";
283
					$additional['lines_total'] = $return['extra']['lines_total'];
0 ignored issues
show
Coding Style Comprehensibility introduced by
$additional was never initialized. Although not strictly required by PHP, it is generally a good practice to add $additional = 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...
284
					$this->archive_system->send_notification($to, $from, $subject, $return['extra']['backup_parent'], $this->form_params,"", $additional);
285
				}catch(Exception $e)
286
				{
287
					$this->logger->error($e->getMessage());
288
				}
289
			}
290
			$this->xcloner_file_system->remove_tmp_filesystem();
291
		}
292
		
293
		return $this->send_response($data, $hash = 1);
294
	}
295
	
296
	/*
297
	 * 
298
	 * Backup Database API
299
	 * 
300
	 */ 
301
	public function backup_database()
0 ignored issues
show
Coding Style introduced by
backup_database uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

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

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
302
	{
303
		$this->check_access();
304
		
305
		$params = json_decode(stripslashes($_POST['data']));
306
		
307
		$init 	= (int)$_POST['init'];
308
		
309
		if($params === NULL)
310
			 die( '{"status":false,"msg":"The post_data parameter must be valid JSON"}' );
0 ignored issues
show
Coding Style Compatibility introduced by
The method backup_database() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
311
		
312
		$this->process_params($params);
313
			
314
		//$xcloner_database = $this->init_db();	
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...
315
		$return = $this->xcloner_database->start_database_recursion($this->form_params['database'], $this->form_params['extra'], $init);
316
		
317 View Code Duplication
		if(isset($return['error']) and $return['error'])
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...
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
			$data['finished'] = 1;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$data was never initialized. Although not strictly required by PHP, it is generally a good practice to add $data = 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...
319
		else	
320
			$data['finished'] = $return['finished'];
0 ignored issues
show
Coding Style Comprehensibility introduced by
$data was never initialized. Although not strictly required by PHP, it is generally a good practice to add $data = 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...
321
			
322
		$data['extra'] = $return;
323
		
324
		return $this->send_response($data, $hash = 1);
325
	}
326
	
327
	/*
328
	 * 
329
	 * Scan Filesystem API
330
	 * 
331
	 */ 
332
	public function scan_filesystem()
0 ignored issues
show
Coding Style introduced by
scan_filesystem uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

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

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
333
	{
334
		$this->check_access();
335
		
336
		$params = json_decode(stripslashes($_POST['data']));
337
		$init 	= (int)$_POST['init'];
338
		
339
		if($params === NULL)
340
			 die( '{"status":false,"msg":"The post_data parameter must be valid JSON"}' );
0 ignored issues
show
Coding Style Compatibility introduced by
The method scan_filesystem() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
341
			 
342
		$hash = $this->process_params($params);
0 ignored issues
show
Unused Code introduced by
$hash 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...
343
		
344
		$this->xcloner_file_system->set_excluded_files($this->form_params['excluded_files']);
0 ignored issues
show
Bug introduced by
It seems like $this->form_params['excluded_files'] can also be of type string; however, Xcloner_File_System::set_excluded_files() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
345
		
346
		$return = $this->xcloner_file_system->start_file_recursion($init);
347
		
348
		$data["finished"] = !$return;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$data was never initialized. Although not strictly required by PHP, it is generally a good practice to add $data = 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...
349
		$data["total_files_num"] = $this->xcloner_file_system->get_scanned_files_num();
350
		$data["last_logged_file"] = $this->xcloner_file_system->last_logged_file();
351
		$data["total_files_size"] = sprintf("%.2f",$this->xcloner_file_system->get_scanned_files_total_size()/(1024*1024));
352
		
353
		return $this->send_response($data, $hash = 1);
354
	}
355
	
356
	/*
357
	 * 
358
	 * Process params sent by the user
359
	 * 
360
	 */ 
361
	private function process_params($params)
362
	{
363
		if(isset($params->hash))
364
			$this->xcloner_settings->set_hash($params->hash);
365
			
366
		$this->form_params['extra'] = array();
367
		$this->form_params['backup_params'] = array();
368
		
369
		$this->form_params['database'] = array();
370
		
371 View Code Duplication
		if(isset($params->backup_params))
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...
372
		{
373
			foreach($params->backup_params as $param)
374
			{
375
				$this->form_params['backup_params'][$param->name] = $this->xcloner_sanitization->sanitize_input_as_string($param->value);
376
				$this->logger->debug("Adding form parameter ".$param->name.".".$param->value."\n", array('POST', 'fields filter'));
377
			}
378
		}
379
		
380
		$this->form_params['database'] = array();
381
		
382 View Code Duplication
		if(isset($params->table_params))
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...
383
		{
384
			foreach($params->table_params as $param)
385
			{
386
				$this->form_params['database'][$param->parent][] = $this->xcloner_sanitization->sanitize_input_as_raw($param->id);
387
				$this->logger->debug("Adding database filter ".$param->parent.".".$param->id."\n", array('POST', 'database filter'));
388
			}
389
		}
390
		
391
		$this->form_params['excluded_files'] =  array();
392
		if(isset($params->files_params))
393
		{
394
			foreach($params->files_params as $param)
395
			{
396
				$this->form_params['excluded_files'][] = $this->xcloner_sanitization->sanitize_input_as_relative_path($param->id);
397
			}
398
			
399
			$unique_exclude_files = array();
400
			
401
			foreach($params->files_params as $key=>$param)
402
			{
403
				if(!in_array($param->parent, $this->form_params['excluded_files'])){
404
				//$this->form_params['excluded_files'][] = $this->xcloner_sanitization->sanitize_input_as_relative_path($param->id);
0 ignored issues
show
Unused Code Comprehensibility introduced by
69% 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...
405
					$unique_exclude_files[] = $param->id;
406
					$this->logger->debug("Adding file filter ".$param->id."\n", array('POST', 'exclude files filter'));
407
				}
408
			}
409
			$this->form_params['excluded_files'] = (array)$unique_exclude_files;
410
			
411
		}
412
		
413
		//$this->form_params['excluded_files'] =  array_merge($this->form_params['excluded_files'], $this->exclude_files_by_default);
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...
414
		
415
		if(isset($params->extra))
416
		{
417
			foreach($params->extra as $key=>$value)
418
				$this->form_params['extra'][$key] = $this->xcloner_sanitization->sanitize_input_as_raw($value);
419
		}
420
		
421
		if(isset($this->form_params['backup_params']['diff_start_date']) and $this->form_params['backup_params']['diff_start_date'])
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...
422
		{
423
			$this->form_params['backup_params']['diff_start_date'] = strtotime($this->form_params['backup_params']['diff_start_date']);
424
			$this->xcloner_file_system->set_diff_timestamp_start($this->form_params['backup_params']['diff_start_date']);
425
		}
426
		
427
		return $this->xcloner_settings->get_hash();
428
	}
429
	
430
	/*
431
	 * 
432
	 * Get file list for tree view API
433
	 * 
434
	 */ 
435
	public function get_file_system_action()
0 ignored issues
show
Coding Style introduced by
get_file_system_action uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

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

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
436
	{
437
		$this->check_access();
438
		
439
		$folder = $this->xcloner_sanitization->sanitize_input_as_relative_path($_POST['id']);
440
		
441
		$data = array();
442
		
443
		if($folder == "#"){
444
			
445
			$folder = "/";
446
			$data[] = array(
447
						'id' => $folder,
448
						'parent' => '#',
449
						'text' => $this->xcloner_settings->get_xcloner_start_path(),
450
						//'children' => true,
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% 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...
451
						'state' =>  array('selected' => false, 'opened' => true),
452
						'icon' => plugin_dir_url(dirname(__FILE__))."/admin/assets/file-icon-root.png"
453
						);
454
		}
455
			
456
			try{
457
				$files = $this->xcloner_file_system->list_directory($folder);
458
			}catch(Exception $e){
459
				
460
				print $e->getMessage();
461
				$this->logger->error($e->getMessage());
462
463
				return;
464
			}
465
			
466
			$type = array();
467
			foreach ($files as $key => $row)
468
			{
469
				$type[$key] = $row['type'];
470
			}
471
			array_multisort($type, SORT_ASC, $files);
472
			
473
			foreach($files as $file)
474
			{
475
				$children = false;
476
				$text = $file['basename'];
477
				
478
				if($file['type'] == "dir")
479
					$children = true;
480
				else
481
					 $text .= " (". $this->xcloner_requirements->file_format_size($file['size']).")";
482
				
483
				if($this->xcloner_file_system->is_excluded($file))
484
					$selected = true;
485
				else
486
					$selected = false;
487
					
488
				$data[] = array(
489
							'id' => $file['path'],
490
							'parent' => $folder,
491
							'text' => $text,
492
							//'title' => "test",
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...
493
							'children' => $children,
494
							'state' =>  array('selected' => $selected, 'opened' => false, "checkbox_disabled" => $selected),
495
							'icon' => plugin_dir_url(dirname(__FILE__))."/admin/assets/file-icon-".strtolower(substr($file['type'], 0, 1)).".png"
496
							);
497
			}
498
		
499
		
500
		return $this->send_response($data, 0);
501
	}
502
	
503
	/*
504
	 * 
505
	 * Get databases/tables list for frontend tree display API
506
	 * 
507
	 */ 
508
	public function get_database_tables_action()
0 ignored issues
show
Coding Style introduced by
get_database_tables_action uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

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

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
509
	{
510
		$this->check_access();
511
		
512
		$database = $this->xcloner_sanitization->sanitize_input_as_raw($_POST['id']);
513
		
514
		$data = array();
515
		
516
		$xcloner_backup_only_wp_tables = $this->xcloner_settings->get_xcloner_option('xcloner_backup_only_wp_tables');
517
	
518
		if($database == "#")
519
		{
520
			try{
521
				$return = $this->xcloner_database->get_all_databases();
522
			}catch(Exception $e){
523
				$this->logger->error($e->getMessage());
524
			}
525
			
526
			foreach($return as $database)
527
			{
528
				if($xcloner_backup_only_wp_tables and $database['name'] != $this->xcloner_settings->get_db_database())
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...
529
					continue;
530
					
531
				$state = array();
532
				
533
				if($database['name'] == $this->xcloner_settings->get_db_database())
534
				{
535
					$state['selected'] = true;
536
					if($database['num_tables'] < 25)
537
						$state['opened'] = false;
538
				}
539
					
540
				$data[] = array(
541
						'id' => $database['name'],
542
						'parent' => '#',
543
						'text' => $database['name']." (".(int)$database['num_tables'].")",
544
						'children' => true,
545
						'state' => $state,
546
						'icon' => plugin_dir_url(dirname(__FILE__))."/admin/assets/database-icon.png"
547
						);
548
			}
549
			
550
		}
551
		
552
		else{
553
			
554
			try{
555
				$return = $this->xcloner_database->list_tables($database, "", 1);
556
			}catch(Exception $e){
557
				$this->logger->error($e->getMessage());
558
			}
559
			
560
			foreach($return as $table)
561
			{
562
				$state = array();
563
				
564
				if($xcloner_backup_only_wp_tables and !stristr($table['name'], $this->xcloner_settings->get_table_prefix()))
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...
565
					continue;
566
				
567
				if(isset($database['name']) and $database['name'] == $this->xcloner_settings->get_db_database())
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...
568
					$state = array('selected' => true);
569
					
570
				$data[] = array(
571
						'id' => $table['name'],
572
						'parent' => $database,
573
						'text' => $table['name']." (".(int)$table['records'].")",
574
						'children' => false,
575
						'state' => $state,
576
						'icon' => plugin_dir_url(dirname(__FILE__))."/admin/assets/table-icon.png"
577
						);
578
			}
579
		}
580
		
581
		return $this->send_response($data, 0);
582
	}
583
	
584
	/*
585
	 * 
586
	 * Get schedule by id API
587
	 * 
588
	 */ 
589
	public function get_schedule_by_id()
0 ignored issues
show
Coding Style introduced by
get_schedule_by_id uses the super-global variable $_GET which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

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

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
590
	{
591
		$this->check_access();
592
		
593
		$schedule_id = $this->xcloner_sanitization->sanitize_input_as_int($_GET['id']);
594
		$scheduler = $this->xcloner_scheduler;
595
		$data  = $scheduler->get_schedule_by_id($schedule_id);
596
		
597
		$data['start_at'] = date("Y-m-d H:i", strtotime($data['start_at']) + (get_option( 'gmt_offset' ) * HOUR_IN_SECONDS));
598
		if(isset($data['backup_params']->diff_start_date) && $data['backup_params']->diff_start_date != "")
599
		{
600
			$data['backup_params']->diff_start_date = date("Y-m-d", ($data['backup_params']->diff_start_date) );
601
		}
602
		
603
		return $this->send_response($data);
604
	}
605
	
606
	/*
607
	 * 
608
	 * Get Schedule list API
609
	 * 
610
	 */ 
611
	public function get_scheduler_list()
612
	{
613
		$this->check_access();
614
		
615
		$scheduler = $this->xcloner_scheduler;
616
		$data  = $scheduler->get_scheduler_list();
617
		$return['data'] = array();
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...
618
		
619
		foreach($data as $res)
620
		{
621
			$action = "<a href=\"#".$res->id."\" class=\"edit\" title='Edit'> <i class=\"material-icons \">edit</i></a> 
622
					<a href=\"#".$res->id."\" class=\"delete\" title='Delete'><i class=\"material-icons  \">delete</i></a>";
623
			if($res->status)
624
				$status = '<i class="material-icons active status">timer</i>';
625
			else
626
				$status = '<i class="material-icons status inactive">timer_off</i>';
627
				
628
			$next_run_time = wp_next_scheduled('xcloner_scheduler_'.$res->id, array($res->id));
629
				
630
			$next_run = date(get_option('date_format')." ".get_option('time_format'), $next_run_time);	
631
			
632
			$remote_storage = $res->remote_storage;
633
			
634
			if(!$next_run_time >= time())
635
				$next_run = " ";
636
			
637
			if(trim($next_run))
638
			{
639
				$date_text = date(get_option('date_format')." ".get_option('time_format'), $next_run_time + (get_option( 'gmt_offset' ) * HOUR_IN_SECONDS));
640
				
641
				if($next_run_time >= time())
642
					$next_run = "in ".human_time_diff($next_run_time, time());
643
				else
644
					$next_run = __("executed", 'xcloner-backup-and-restore');
645
				
646
				$next_run = "<a href='#' title='".$date_text."'>".$next_run."</a>";
647
				//$next_run .=" ($date_text)";	
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% 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...
648
			}
649
			
650
			$backup_text = "";
651
			$backup_size = "";
652
			$backup_time = "";
653
			
654
			if($res->last_backup)
655
			{
656
				if( $this->xcloner_file_system->get_storage_filesystem()->has($res->last_backup))
657
				{
658
					$metadata = $this->xcloner_file_system->get_storage_filesystem()->getMetadata($res->last_backup);
659
					$backup_size  = size_format($this->xcloner_file_system->get_backup_size($res->last_backup));
660
					$backup_time  = date(get_option('date_format')." ".get_option('time_format'), $metadata['timestamp']+(get_option( 'gmt_offset' ) * HOUR_IN_SECONDS));
661
				}
662
			
663
				$backup_text = "<span title='".$backup_time."' class='shorten_string'>".$res->last_backup." (".$backup_size.")</span>";
664
			}
665
			
666
			$schedules = wp_get_schedules();
667
668
			if(isset($schedules[$res->recurrence]))
669
			{
670
				$res->recurrence = $schedules[$res->recurrence]['display'];
671
			}
672
				
673
			$return['data'][] = array($res->id, $res->name, $res->recurrence,/*$res->start_at,*/ $next_run, $remote_storage, $backup_text, $status, $action);
674
		}
675
676
		return $this->send_response($return, 0);
677
	}
678
	
679
	/*
680
	 * 
681
	 * Delete Schedule by ID API
682
	 * 
683
	 */
684
	public function delete_schedule_by_id()
0 ignored issues
show
Coding Style introduced by
delete_schedule_by_id uses the super-global variable $_GET which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

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

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
685
	{
686
		$this->check_access();
687
		
688
		$schedule_id = $this->xcloner_sanitization->sanitize_input_as_int($_GET['id']);
689
		$scheduler = $this->xcloner_scheduler;
690
		$data['finished']  = $scheduler->delete_schedule_by_id($schedule_id);
0 ignored issues
show
Coding Style Comprehensibility introduced by
$data was never initialized. Although not strictly required by PHP, it is generally a good practice to add $data = 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...
691
		
692
		return $this->send_response($data);
693
	}
694
	
695
	/*
696
	 * 
697
	 * Delete backup by name from the storage path
698
	 * 
699
	 */ 
700
	public function delete_backup_by_name()
0 ignored issues
show
Coding Style introduced by
delete_backup_by_name uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

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

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
701
	{
702
		$this->check_access();
703
		
704
		$backup_name = $this->xcloner_sanitization->sanitize_input_as_string($_POST['name']);
705
		$storage_selection = $this->xcloner_sanitization->sanitize_input_as_string($_POST['storage_selection']);
706
		
707
		$data['finished']  = $this->xcloner_file_system->delete_backup_by_name($backup_name, $storage_selection);
0 ignored issues
show
Coding Style Comprehensibility introduced by
$data was never initialized. Although not strictly required by PHP, it is generally a good practice to add $data = 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...
708
		
709
		return $this->send_response($data);
710
	}
711
	
712
	public function list_backup_files()
0 ignored issues
show
Coding Style introduced by
list_backup_files uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

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

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
713
	{
714
		$this->check_access();
715
		
716
		$backup_parts = array();
717
		
718
		$source_backup_file = $this->xcloner_sanitization->sanitize_input_as_string($_POST['file']);
719
		$start = $this->xcloner_sanitization->sanitize_input_as_int($_POST['start']);
720
		$return['part'] = $this->xcloner_sanitization->sanitize_input_as_int($_POST['part']);
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...
721
		
722
		$backup_file = $source_backup_file;
723
		
724 View Code Duplication
		if($this->xcloner_file_system->is_multipart($backup_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...
725
		{
726
			$backup_parts = $this->xcloner_file_system->get_multipart_files($backup_file);
727
			$backup_file = $backup_parts[$return['part']];
728
		}
729
		
730
		try{
731
			$tar = new Tar();
732
			$tar->open($this->xcloner_settings->get_xcloner_store_path().DS.$backup_file, $start);
0 ignored issues
show
Unused Code introduced by
The call to Tar::open() has too many arguments starting with $start.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
733
		
734
			$data = $tar->contents(get_option('xcloner_files_to_process_per_request'));
0 ignored issues
show
Unused Code introduced by
The call to Tar::contents() has too many arguments starting with get_option('xcloner_file...o_process_per_request').

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
735
		}catch(Exception $e)
736
		{
737
			$return['error'] = true;
738
			$return['message'] = $e->getMessage();
739
			$this->send_response($return, 0);
740
		}
741
		
742
		$return['files'] 		= array();
743
		$return['finished'] 	= 1;
744
		$return['total_size'] 	= filesize($this->xcloner_settings->get_xcloner_store_path().DS.$backup_file);
745
		$i = 0;
746
		
747
		if(isset($data['extracted_files']) and is_array($data['extracted_files']))
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...
748
		{
749
			foreach($data['extracted_files'] as $file)
750
			{
751
				$return['files'][$i]['path'] = $file->getPath();
752
				$return['files'][$i]['size'] = $file->getSize();
753
				$return['files'][$i]['mtime'] = date(get_option('date_format')." ".get_option('time_format'), $file->getMtime());
754
				
755
				$i++;
756
			}
757
		}
758
		
759 View Code Duplication
		if(isset($data['start']))
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...
760
		{
761
			$return['start'] = $data['start'];
762
			$return['finished'] = 0;	
763
		}else{
764
			if($this->xcloner_file_system->is_multipart($source_backup_file))
765
			{
766
				$return['start'] = 0;
767
				
768
				++$return['part'];
769
			
770
				if($return['part'] < sizeof($backup_parts))	
771
					$return['finished'] = 0;
772
				
773
			}
774
		}	
775
		
776
		$this->send_response($return, 0);
777
	}
778
	
779 View Code Duplication
	public function copy_backup_remote_to_local()
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...
Coding Style introduced by
copy_backup_remote_to_local uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

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

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
780
	{
781
	
782
		$this->check_access();
783
		
784
		$backup_file = $this->xcloner_sanitization->sanitize_input_as_string($_POST['file']);
785
		$storage_type = $this->xcloner_sanitization->sanitize_input_as_string($_POST['storage_type']);
786
		
787
		$xcloner_remote_storage = $this->get_xcloner_container()->get_xcloner_remote_storage();
788
		
789
		$return = array();
790
		
791
		try
792
		{
793
			if(method_exists($xcloner_remote_storage, "copy_backup_remote_to_local"))
794
			{
795
				$return = call_user_func_array(array($xcloner_remote_storage, "copy_backup_remote_to_local"), array($backup_file, $storage_type));
796
			}
797
		}catch(Exception $e){
798
		
799
			$return['error'] = 1;
800
			$return['message'] = $e->getMessage();
801
		}
802
		
803
		if(!$return)
804
		{
805
			$return['error'] = 1;
806
			$return['message'] = "Upload failed, please check the error log for more information!";
807
		}
808
			
809
		
810
		$this->send_response($return, 0);
811
		
812
	}
813
	
814
	/*
815
	 * 
816
	 * Upload backup to remote API
817
	 * 
818
	 */ 
819 View Code Duplication
	public function upload_backup_to_remote()
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...
Coding Style introduced by
upload_backup_to_remote uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

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

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
820
	{
821
		$this->check_access();
822
		
823
		$backup_file = $this->xcloner_sanitization->sanitize_input_as_string($_POST['file']);
824
		$storage_type = $this->xcloner_sanitization->sanitize_input_as_string($_POST['storage_type']);
825
		
826
		$xcloner_remote_storage = $this->get_xcloner_container()->get_xcloner_remote_storage();
827
		
828
		$return = array();
829
		
830
		try
831
		{
832
			if(method_exists($xcloner_remote_storage, "upload_backup_to_storage"))
833
			{
834
				$return = call_user_func_array(array($xcloner_remote_storage, "upload_backup_to_storage"), array($backup_file, $storage_type));
835
			}
836
		}catch(Exception $e){
837
		
838
			$return['error'] = 1;
839
			$return['message'] = $e->getMessage();
840
		}
841
		
842
		if(!$return)
843
		{
844
			$return['error'] = 1;
845
			$return['message'] = "Upload failed, please check the error log for more information!";
846
		}
847
			
848
		
849
		$this->send_response($return, 0);
850
		
851
	}
852
	
853
	/*
854
	 * 
855
	 * Remote Storage Status Save
856
	 * 
857
	 */ 
858
	public function remote_storage_save_status()
0 ignored issues
show
Coding Style introduced by
remote_storage_save_status uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

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

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
859
	{
860
		$this->check_access();
861
		
862
		$xcloner_remote_storage = $this->get_xcloner_container()->get_xcloner_remote_storage();
863
		
864
		$return['finished'] = $xcloner_remote_storage->change_storage_status($_POST['id'], $_POST['value']);
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...
865
		
866
		$this->send_response($return, 0);
867
	}
868
	
869
	
870
	public function download_restore_script()
871
	{
872
		$this->check_access();
873
		
874
		@ob_end_clean();
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...
875
		
876
		$adapter = new Local(dirname(__DIR__) ,LOCK_EX, 'SKIP_LINKS');
877
		$xcloner_plugin_filesystem = new Filesystem($adapter, new Config([
878
				'disable_asserts' => true,
879
			]));
880
		
881
		/* Generate PHAR FILE
0 ignored issues
show
Unused Code Comprehensibility introduced by
47% 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...
882
		$file = 'restore/vendor.built';	
883
884
		if(file_exists($file))
885
			unlink($file);
886
		$phar2 = new Phar($file, 0, 'vendor.phar');
887
		
888
		// add all files in the project, only include php files
889
		$phar2->buildFromIterator(
890
		    new RecursiveIteratorIterator(
891
		     new RecursiveDirectoryIterator(__DIR__.'/vendor/')),
892
		    __DIR__);
893
		
894
		$phar2->setStub($phar2->createDefaultStub('vendor/autoload.php', 'vendor/autoload.php')); 
895
		 * */
896
			
897
		$tmp_file = $this->xcloner_settings->get_xcloner_tmp_path().DS."xcloner-restore.tgz";
898
		
899
		$tar = new Tar();
900
		$tar->create($tmp_file);
901
		
902
		$tar->addFile(dirname(__DIR__)."/restore/vendor.build.txt", "vendor.phar");
903
		//$tar->addFile(dirname(__DIR__)."/restore/vendor.tgz", "vendor.tgz");
0 ignored issues
show
Unused Code Comprehensibility introduced by
74% 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...
904
		
905
		$files = $xcloner_plugin_filesystem->listContents("vendor/", true);
906
		foreach($files as $file)
907
		{
908
			$tar->addFile(dirname(__DIR__).DS.$file['path'], $file['path']);
909
		}
910
		
911
		$content = file_get_contents(dirname(__DIR__)."/restore/xcloner_restore.php");
912
		$content = str_replace("define('AUTH_KEY', '');", "define('AUTH_KEY', '".md5(AUTH_KEY)."');", $content);
913
		
914
		$tar->addData("xcloner_restore.php", $content);
915
		
916
		$tar->close();
917
		
918
		if (file_exists($tmp_file)) {
919
		    header('Content-Description: File Transfer');
920
		    header('Content-Type: application/octet-stream');
921
		    header('Content-Disposition: attachment; filename="'.basename($tmp_file).'"');
922
		    header('Expires: 0');
923
		    header('Cache-Control: must-revalidate');
924
		    header('Pragma: public');
925
		    header('Content-Length: ' . filesize($tmp_file));
926
		    readfile($tmp_file);
927
		    
928
		}
929
		
930
		@unlink($tmp_file);
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...
931
		exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The method download_restore_script() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
932
	}
933
	
934
	/*
935
	 * 
936
	 * Download backup by Name from the Storage Path
937
	 * 
938
	 */ 
939
	public function download_backup_by_name()
0 ignored issues
show
Coding Style introduced by
download_backup_by_name uses the super-global variable $_GET which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

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

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
940
	{
941
		$this->check_access();
942
		
943
		@ob_end_clean();
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...
944
		
945
		$backup_name = $this->xcloner_sanitization->sanitize_input_as_string($_GET['name']);
946
		
947
		
948
		$metadata  = $this->xcloner_file_system->get_storage_filesystem()->getMetadata($backup_name);
949
		$read_stream  = $this->xcloner_file_system->get_storage_filesystem()->readStream($backup_name);
950
		
951
		
952
		header('Pragma: public');
953
	    header('Expires: 0');
954
	    header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
955
	    header('Cache-Control: private', false);
956
	    header('Content-Transfer-Encoding: binary');
957
	    header('Content-Disposition: attachment; filename="'.$metadata['path'].'";');
958
	    header('Content-Type: application/octet-stream');
959
	    header('Content-Length: ' . $metadata['size']);
960
	    
961
	    @ob_end_clean();
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...
962
	    
963
	    $chunkSize = 1024 * 1024;
964
	    while (!feof($read_stream))
965
	    {
966
	        $buffer = fread($read_stream, $chunkSize);
967
	        echo $buffer;
968
	    }
969
	    fclose($read_stream);
970
	    exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The method download_backup_by_name() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
971
    
972
	}
973
	
974
	
975
	public function restore_upload_backup()
0 ignored issues
show
Coding Style introduced by
restore_upload_backup uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

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

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
976
	{
977
		$this->check_access();
978
		
979
		$return['part'] = 0;
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...
980
		$return['total_parts'] = 0;
981
		$return['uploaded_size'] = 0;
982
		$is_multipart = 0;
983
		
984
		$file = $this->xcloner_sanitization->sanitize_input_as_string($_POST['file']);
985
		$hash = $this->xcloner_sanitization->sanitize_input_as_string($_POST['hash']);
986
		
987
		if(isset($_POST['part']))
988
			$return['part'] = $this->xcloner_sanitization->sanitize_input_as_int($_POST['part']);
989
		
990
		if(isset($_POST['uploaded_size']))
991
			$return['uploaded_size'] = $this->xcloner_sanitization->sanitize_input_as_int($_POST['uploaded_size']);
992
		
993
		$start = $this->xcloner_sanitization->sanitize_input_as_string($_POST['start']);
994
		$target_url = $this->xcloner_sanitization->sanitize_input_as_string($_POST['target_url']);
995
		
996
		$return['total_size'] = $this->xcloner_file_system->get_backup_size($file);
997
		
998
		if($this->xcloner_file_system->is_multipart($file))
999
		{
1000
			$backup_parts = $this->xcloner_file_system->get_multipart_files($file);
1001
			
1002
			$return['total_parts'] = sizeof($backup_parts)+1;
1003
			
1004 View Code Duplication
			if($return['part'] and isset($backup_parts[$return['part']-1]))
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...
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...
1005
			{
1006
				$file = $backup_parts[$return['part']-1];
1007
			}
1008
			
1009
			$is_multipart = 1;	
1010
		}
1011
		
1012
		try{
1013
		
1014
			$xcloner_file_transfer = $this->get_xcloner_container()->get_xcloner_file_transfer();
1015
			$xcloner_file_transfer->set_target($target_url);
1016
			$return['start'] = $xcloner_file_transfer->transfer_file($file, $start, $hash);
1017
		
1018
		}catch(Exception $e){
1019
		
1020
			$return = array();
1021
			$return['error'] = true;
1022
			$return['status'] = 500;
1023
			$return['message'] = "CURL communication error with the restore host. ".$e->getMessage();
1024
			$this->send_response( $return, 0);
1025
		
1026
		}
1027
		
1028
		$return['status'] = 200;
1029
		
1030
		//we have finished the upload
1031
		if(!$return['start'] and $is_multipart)
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...
1032
		{
1033
			$return['part']++;
1034
			$return['uploaded_size'] += $this->xcloner_file_system->get_storage_filesystem()->getSize($file);
1035
		}
1036
		
1037
		$this->send_response( $return, 0);
1038
	}
1039
	
1040
	public function restore_backup()
1041
	{
1042
		$this->check_access();
1043
		
1044
		define("XCLONER_PLUGIN_ACCESS", 1);
1045
		include_once(dirname(__DIR__) .DS."restore".DS."xcloner_restore.php");
1046
		return;
1047
	}
1048
	
1049
	/*
1050
	 * 
1051
	 * Send the json response back
1052
	 * 
1053
	 */
1054
	private function send_response($data, $attach_hash = 1)
1055
	{
1056
		
1057
		if($attach_hash and null !== $this->xcloner_settings->get_hash())
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...
1058
		{
1059
			$data['hash'] = $this->xcloner_settings->get_hash();
1060
		}
1061
			
1062
		if( ob_get_length() )
1063
			ob_clean();
1064
		wp_send_json($data);
1065
		
1066
		die();
0 ignored issues
show
Coding Style Compatibility introduced by
The method send_response() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
1067
	}
1068
}
1069