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 ( e0dd2d...2542bf )
by Liuta
02:23
created

Xcloner::define_plugin_settings()   C

Complexity

Conditions 7
Paths 6

Size

Total Lines 35
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 15
nc 6
nop 0
dl 0
loc 35
rs 6.7272
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * The file that defines the core plugin class
5
 *
6
 * A class definition that includes attributes and functions used across both the
7
 * public-facing side of the site and the admin area.
8
 *
9
 * @link       http://www.thinkovi.com
10
 * @since      1.0.0
11
 *
12
 * @package    Xcloner
13
 * @subpackage Xcloner/includes
14
 */
15
16
/**
17
 * The core plugin class.
18
 *
19
 * This is used to define internationalization, admin-specific hooks, and
20
 * public-facing site hooks.
21
 *
22
 * Also maintains the unique identifier of this plugin as well as the current
23
 * version of the plugin.
24
 *
25
 * @since      1.0.0
26
 * @package    Xcloner
27
 * @subpackage Xcloner/includes
28
 * @author     Liuta Ovidiu <[email protected]>
29
 */
30
class Xcloner {
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...
31
32
	/**
33
	 * The loader that's responsible for maintaining and registering all hooks that power
34
	 * the plugin.
35
	 *
36
	 * @since    1.0.0
37
	 * @access   protected
38
	 * @var      Xcloner_Loader    $loader    Maintains and registers all hooks for the plugin.
39
	 */
40
	protected $loader;
41
	
42
	/**
43
	 * The unique identifier of this plugin.
44
	 *
45
	 * @since    1.0.0
46
	 * @access   protected
47
	 * @var      string    $plugin_name    The string used to uniquely identify this plugin.
48
	 */
49
	protected $plugin_name;
50
	
51
	protected $plugin_admin;
52
53
	/**
54
	 * The current version of the plugin.
55
	 *
56
	 * @since    1.0.0
57
	 * @access   protected
58
	 * @var      string    $version    The current version of the plugin.
59
	 */
60
	protected $version;
61
		
62
	private $xcloner_settings;	
63
	private $xcloner_logger;
64
	private $xcloner_sanitization;
65
	private $xcloner_requirements;
66
	private $xcloner_filesystem;
67
	private $archive_system;
68
	private $xcloner_database;
69
	private $xcloner_scheduler;
70
	private $xcloner_remote_storage;
71
	private $xcloner_file_transfer;
72
	/**
73
	 * Define the core functionality of the plugin.
74
	 *
75
	 * Set the plugin name and the plugin version that can be used throughout the plugin.
76
	 * Load the dependencies, define the locale, and set the hooks for the admin area and
77
	 * the public-facing side of the site.
78
	 *
79
	 * @since    1.0.0
80
	 */
81
	public function init() 
82
	{
83
		register_shutdown_function(array($this, 'exception_handler'));
84
		
85
		$this->plugin_name = 'xcloner';
86
		$this->version = '4.0.4';
87
		
88
		$this->load_dependencies();
89
		$this->set_locale();
90
		$this->define_admin_hooks();
91
		$this->define_public_hooks();
92
		
93
		$this->define_admin_menu();
94
		$this->define_plugin_settings();
95
		
96
		$this->define_ajax_hooks();
97
		$this->define_cron_hooks();
98
		
99
	}
100
	
101
	public function get_xcloner_settings()
102
	{
103
		return $this->xcloner_settings;
104
	}
105
	
106
	public function get_xcloner_filesystem()
107
	{
108
		return $this->xcloner_filesystem;
109
	}
110
	
111
	public function get_xcloner_logger()
112
	{
113
		return $this->xcloner_logger;
114
	}
115
	
116
	public function get_xcloner_sanitization()
117
	{
118
		return $this->xcloner_sanitization;
119
	}
120
	
121
	public function get_xcloner_requirements()
122
	{
123
		return $this->xcloner_requirements;
124
	}
125
	
126
	public function get_archive_system()
127
	{
128
		return $this->archive_system;
129
	}
130
	
131
	public function get_xcloner_database()
132
	{
133
		return $this->xcloner_database;
134
	}
135
	
136
	public function get_xcloner_scheduler()
137
	{
138
		return $this->xcloner_scheduler;
139
	}
140
	
141
	public function get_xcloner_remote_storage()
142
	{
143
		return $this->xcloner_remote_storage;
144
	}
145
	
146
	public function get_xcloner_file_transfer()
147
	{
148
		return $this->xcloner_file_transfer;
149
	}
150
	
151
	public function check_dependencies(){
152
		
153
		$backup_storage_path = realpath(__DIR__.DS."..".DS."..".DS."..").DS."backups".DS;
154
		
155
		define("XCLONER_STORAGE_PATH", realpath($backup_storage_path));
156
157 View Code Duplication
		if(!is_dir($backup_storage_path))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
158
		{
159
			if(!@mkdir($backup_storage_path))
160
			{
161
				$status = "error";
162
				$message = sprintf(__("Unable to create the Backup Storage Location Folder %s . Please fix this before starting the backup process."), $backup_storage_path);
163
				$this->trigger_message($message, $status, $backup_storage_path);
164
				return;
165
			}
166
		}	
167 View Code Duplication
		if(!is_writable($backup_storage_path))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
168
		{
169
			$status = "error";
170
			$message = sprintf(__("Unable to write to the Backup Storage Location Folder %s . Please fix this before starting the backup process."), $backup_storage_path);
171
			$this->trigger_message($message, $status, $backup_storage_path);
172
			
173
			return;
174
		}
175
		
176
	}
177
	
178
	public function trigger_message($message, $status = "error", $message_param1 = "", $message_param2 = "", $message_param3 = "")
179
	{
180
			$message = sprintf(__($message), $message_param1, $message_param2, $message_param3);
181
			add_action( 'xcloner_admin_notices', array($this,"trigger_message_notice"), 10, 2);
182
			do_action( 'xcloner_admin_notices', $message, $status);
183
	}
184
	
185
	public function trigger_message_notice($message, $status = "success")
186
	{
187
		?>
188
		<div class="notice notice-<?php echo $status?> is-dismissible">
189
	        <p><?php _e( $message, 'xcloner-backup-and-restore' ); ?></p>
190
	    </div>
191
		<?php
192
	}
193
194
	/**
195
	 * Load the required dependencies for this plugin.
196
	 *
197
	 * Include the following files that make up the plugin:
198
	 *
199
	 * - Xcloner_Loader. Orchestrates the hooks of the plugin.
200
	 * - Xcloner_i18n. Defines internationalization functionality.
201
	 * - Xcloner_Admin. Defines all hooks for the admin area.
202
	 * - Xcloner_Public. Defines all hooks for the public side of the site.
203
	 *
204
	 * Create an instance of the loader which will be used to register the hooks
205
	 * with WordPress.
206
	 *
207
	 * @since    1.0.0
208
	 * @access   private
209
	 */
210
	private function load_dependencies() {
211
212
		/**
213
		 * The class responsible for orchestrating the actions and filters of the
214
		 * core plugin.
215
		 */
216
		require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-xcloner-loader.php';
217
218
		/**
219
		 * The class responsible for defining internationalization functionality
220
		 * of the plugin.
221
		 */
222
		require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-xcloner-i18n.php';
223
224
		/**
225
		 * The class responsible for defining all actions that occur in the admin area.
226
		 */
227
		require_once plugin_dir_path( dirname( __FILE__ ) ) . 'admin/class-xcloner-admin.php';
228
		
229
		/**
230
		 * The class responsible for debugging XCloner.
231
		 */
232
		require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-xcloner-logger.php';
233
		
234
		/**
235
		 * The class responsible for defining the admin settings area.
236
		 */
237
		require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-xcloner-settings.php';
238
		
239
		/**
240
		 * The class responsible for defining the Remote Storage settings area.
241
		 */
242
		require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-xcloner-remote-storage.php';
243
		
244
		/**
245
		 * The class responsible for implementing the database backup methods.
246
		 */
247
		require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-xcloner-database.php';
248
		
249
		/**
250
		 * The class responsible for sanitization of users input.
251
		 */
252
		require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-xcloner-sanitization.php';
253
		
254
		/**
255
		 * The class responsible for XCloner system requirements validation.
256
		 */
257
		require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-xcloner-requirements.php';
258
		
259
		/**
260
		 * The class responsible for XCloner backup archive creation.
261
		 */
262
		require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-xcloner-archive.php';
263
		
264
		/**
265
		 * The class responsible for XCloner API requests.
266
		 */
267
		require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-xcloner-api.php';
268
		
269
		/**
270
		 * The class responsible for the XCloner File System methods.
271
		 */
272
		require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-xcloner-file-system.php';
273
		
274
		/**
275
		 * The class responsible for the XCloner File Transfer methods.
276
		 */
277
		require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-xcloner-file-transfer.php';
278
		
279
		/**
280
		 * The class responsible for the XCloner Scheduler methods.
281
		 */
282
		require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-xcloner-scheduler.php';
283
284
		/**
285
		 * The class responsible for defining all actions that occur in the public-facing
286
		 * side of the site.
287
		 */
288
		require_once plugin_dir_path( dirname( __FILE__ ) ) . 'public/class-xcloner-public.php';
289
		
290
		$this->loader = new Xcloner_Loader($this);
291
292
	}
293
294
	/**
295
	 * Define the locale for this plugin for internationalization.
296
	 *
297
	 * Uses the Xcloner_i18n class in order to set the domain and to register the hook
298
	 * with WordPress.
299
	 *
300
	 * @since    1.0.0
301
	 * @access   private
302
	 */
303
	private function set_locale() {
304
305
		$plugin_i18n = new Xcloner_i18n();
306
307
		$this->loader->add_action( 'plugins_loaded', $plugin_i18n, 'load_plugin_textdomain' );
308
		
309
		//wp_localize_script( 'ajax-script', 'my_ajax_object',
0 ignored issues
show
Unused Code Comprehensibility introduced by
63% 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...
310
        //   array( 'ajax_url' => admin_url( 'admin-ajax.php' ) ) );
0 ignored issues
show
Unused Code Comprehensibility introduced by
53% 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...
311
312
	}
313
314
	/**
315
	 * Register all of the hooks related to the admin area functionality
316
	 * of the plugin.
317
	 *
318
	 * @since    1.0.0
319
	 * @access   private
320
	 */
321
	private function define_admin_hooks() {
322
	
323
		$plugin_admin = new Xcloner_Admin( $this );
324
		$this->plugin_admin = $plugin_admin;
325
326
		$this->loader->add_action( 'admin_enqueue_scripts', $plugin_admin, 'enqueue_styles' );
327
		$this->loader->add_action( 'admin_enqueue_scripts', $plugin_admin, 'enqueue_scripts' );
328
		
329
	}
330
	
331
	/**
332
	 * Register the Admin Sidebar menu
333
	 * 
334
	 * @access 	private
335
	 */
336
	private function define_admin_menu(){
337
		
338
		add_action('admin_menu', array($this->loader, 'xcloner_backup_add_admin_menu'));
339
		
340
	}
341
	
342
	private function define_plugin_settings(){
0 ignored issues
show
Coding Style introduced by
define_plugin_settings 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...
343
		/**
344
		* register wporg_settings_init to the admin_init action hook
345
		*/
346
347
		$this->xcloner_settings = new XCloner_Settings($this);
348
				
349
		if(defined('DOING_CRON') || isset($_POST['hash'])){
350
			
351
			if(defined('DOING_CRON') || $_POST['hash'] == "generate_hash"){
352
				$this->xcloner_settings->generate_new_hash();
353
			}else{
354
				$this->xcloner_settings->set_hash($_POST['hash']);
355
			}
356
		}
357
		
358
		if(defined('DOING_CRON') || !isset($_POST['hash']))
359
		{
360
			add_action( 'shutdown', function(){
361
				$this->xcloner_file_system = new Xcloner_File_System($this);
0 ignored issues
show
Bug introduced by
The property xcloner_file_system does not seem to exist. Did you mean xcloner_filesystem?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
362
				$this->xcloner_file_system->remove_tmp_filesystem();
0 ignored issues
show
Bug introduced by
The property xcloner_file_system does not seem to exist. Did you mean xcloner_filesystem?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
363
			});
364
		}
365
		
366
		$this->xcloner_sanitization 	= new Xcloner_Sanitization();
367
		$this->xcloner_requirements 	= new Xcloner_Requirements($this);
368
		
369
		add_action('admin_init', array($this->xcloner_settings, 'settings_init'));
370
		
371
		//adding links to the Manage Plugins Wordpress page for XCloner
372
		add_filter('plugin_action_links', array($this, 'add_plugin_action_links'), 10, 2);
373
		
374
		
375
		
376
	}
377
	
378
	/*
379
	 * type = core|plugin|theme|translation
380
	 */
381
	public function pre_auto_update($type, $item, $context)
0 ignored issues
show
Unused Code introduced by
The parameter $item is not used and could be removed.

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

Loading history...
Unused Code introduced by
The parameter $context is not used and could be removed.

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

Loading history...
382
	{
383
		if(!$type)
384
		{
385
			return false;
386
		}	
387
		
388
		$this->get_xcloner_logger()->info(sprintf("Doing automatic backup before %s upgrade, pre_auto_update hook.", $type));
389
		
390
		$content_dir = str_replace(ABSPATH, "", WP_CONTENT_DIR); 
391
		$plugins_dir 	= str_replace(ABSPATH, "", WP_PLUGIN_DIR);
392
		$langs_dir 		= $content_dir . DS . "languages";
393
		$themes_dir 		= $content_dir . DS . "themes";
394
						
395
		switch ( $type ) {
396
			case 'core':
397
				$exclude_files = array(
398
									"^(?!(wp-admin|wp-includes|(?!.*\/.*.php)))(.*)$",
399
								);
400
				break;
401 View Code Duplication
			case 'plugin':
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...
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
402
			
403
				$dir_array = explode(DS, $plugins_dir);
404
				
405
				foreach($dir_array as $dir)
406
				{
407
					$data .= "\/".$dir;
0 ignored issues
show
Bug introduced by
The variable $data does not seem to be defined for all execution paths leading up to this point.

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

Let’s take a look at an example:

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

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

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

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

Available Fixes

  1. Check for existence of the variable explicitly:

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

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

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
408
					$regex .= $data."$|";
0 ignored issues
show
Bug introduced by
The variable $regex does not seem to be defined for all execution paths leading up to this point.

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

Let’s take a look at an example:

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

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

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

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

Available Fixes

  1. Check for existence of the variable explicitly:

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

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

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
409
				}
410
				
411
				$regex .= "\/".implode("\/", $dir_array);
412
				
413
				$exclude_files = array(
414
									"^(?!(".$regex."))(.*)$",
415
								);
416
				break;
417 View Code Duplication
			case 'theme':
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...
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
418
419
				$dir_array = explode(DS, $themes_dir);
420
				
421
				foreach($dir_array as $dir)
422
				{
423
					$data .= "\/".$dir;
424
					$regex .= $data."$|";
425
				}
426
				
427
				$regex .= "\/".implode("\/", $dir_array);
428
				
429
				$exclude_files = array(
430
									"^(?!(".$regex."))(.*)$",
431
								);				
432
				break;
433 View Code Duplication
			case 'translation':
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...
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
434
435
				$dir_array = explode(DS, $langs_dir);
436
				
437
				foreach($dir_array as $dir)
438
				{
439
					$data .= "\/".$dir;
440
					$regex .= $data."$|";
441
				}
442
				
443
				$regex .= "\/".implode("\/", $dir_array);
444
				
445
				$exclude_files = array(
446
									"^(?!(".$regex."))(.*)$",
447
								);				
448
				break;
449
		}
450
		
451
		$schedule = array();
452
		
453
		$schedule['id'] = 0;
454
		$schedule['name'] = "pre_auto_update";
455
		$schedule['recurrence'] = "single";
456
		$schedule['excluded_files'] = json_encode($exclude_files);
0 ignored issues
show
Bug introduced by
The variable $exclude_files does not seem to be defined for all execution paths leading up to this point.

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

Let’s take a look at an example:

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

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

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

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

Available Fixes

  1. Check for existence of the variable explicitly:

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

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

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
457
		$schedule['table_params'] = json_encode(array("#" => array($this->get_xcloner_settings()->get_db_database())));
458
		
459
		$schedule['backup_params'] = new stdClass();
460
		$schedule['backup_params']->email_notification = get_option('admin_email');
461
		$schedule['backup_params']->backup_name = "backup_pre_auto_update_".$type."_[domain]-[time]-sql";
462
		
463
		try{
464
			$this->xcloner_scheduler->xcloner_scheduler_callback(0, $schedule);
0 ignored issues
show
Documentation introduced by
$schedule is of type array<string,integer|str...s":"object<stdClass>"}>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
465
		}catch(Exception $e){
466
			$this->get_xcloner_logger()->error($e->getMessage());
467
		}
468
	
469
	}
470
471
	/**
472
	 * Register all of the hooks related to the public-facing functionality
473
	 * of the plugin.
474
	 *
475
	 * @since    1.0.0
476
	 * @access   private
477
	 */
478
	private function define_public_hooks() {
479
480
		$plugin_public = new Xcloner_Public( $this );
481
482
		$this->loader->add_action( 'wp_enqueue_scripts', $plugin_public, 'enqueue_styles' );
483
		$this->loader->add_action( 'wp_enqueue_scripts', $plugin_public, 'enqueue_scripts' );
484
485
	}
486
	
487
	public function exception_handler() {
488
		
489
		$logger = new XCloner_Logger($this, "php_system");
490
		$error = error_get_last();
491
		
492
		if($error['type'] and $logger)
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...
493
		{
494
			$logger->info($this->friendly_error_type ($error['type']).": ".var_export($error, true));
495
		}
496
	
497
	}
498
	
499 View Code Duplication
	function friendly_error_type($type) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
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...
500
	    static $levels=null;
501
	    if ($levels===null) {
502
	        $levels=[];
503
	        foreach (get_defined_constants() as $key=>$value) {
504
	            if (strpos($key,'E_')!==0) {continue;}
505
					$levels[$value]= $key; //substr($key,2);
0 ignored issues
show
Unused Code Comprehensibility introduced by
86% of this comment could be valid code. Did you maybe forget this after debugging?

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

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

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

Loading history...
506
	        }
507
	    }
508
	    return (isset($levels[$type]) ? $levels[$type] : "Error #{$type}");
509
	}
510
		
511
	private function define_ajax_hooks()
512
	{
513
		//adding the pre-update hook
514
		
515
		if(is_admin() || defined('DOING_CRON'))
516
		{
517
			$this->xcloner_logger 			= new XCloner_Logger($this, "xcloner_api");
518
			$this->xcloner_filesystem 		= new Xcloner_File_System($this);
519
			
520
			//$this->xcloner_filesystem->set_diff_timestamp_start (strtotime("-15 days"));
0 ignored issues
show
Unused Code Comprehensibility introduced by
70% 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...
521
			
522
			$this->archive_system 			= new Xcloner_Archive($this);
523
			$this->xcloner_database 		= new Xcloner_Database($this);
524
			$this->xcloner_scheduler 		= new Xcloner_Scheduler($this);
525
			$this->xcloner_remote_storage 	= new Xcloner_Remote_Storage($this);
526
			$this->xcloner_file_transfer 	= new Xcloner_File_Transfer($this);
527
			
528
			$xcloner_api 					= new Xcloner_Api($this);
529
530
			add_action( 'wp_ajax_get_database_tables_action', 	array($xcloner_api,'get_database_tables_action')  );
531
			add_action( 'wp_ajax_get_file_system_action', 		array($xcloner_api,'get_file_system_action')  );
532
			add_action( 'wp_ajax_scan_filesystem', 				array($xcloner_api,'scan_filesystem')  );
533
			add_action( 'wp_ajax_backup_database', 				array($xcloner_api,'backup_database')  );
534
			add_action( 'wp_ajax_backup_files'	, 				array($xcloner_api,'backup_files')  );
535
			add_action( 'wp_ajax_save_schedule'	, 				array($xcloner_api,'save_schedule')  );
536
			add_action( 'wp_ajax_get_schedule_by_id',	 		array($xcloner_api,'get_schedule_by_id')  );
537
			add_action( 'wp_ajax_get_scheduler_list',	 		array($xcloner_api,'get_scheduler_list')  );
538
			add_action( 'wp_ajax_delete_schedule_by_id'	, 		array($xcloner_api,'delete_schedule_by_id')  );
539
			add_action( 'wp_ajax_delete_backup_by_name'	, 		array($xcloner_api,'delete_backup_by_name')  );
540
			add_action( 'wp_ajax_download_backup_by_name', 		array($xcloner_api,'download_backup_by_name')  );
541
			add_action( 'wp_ajax_remote_storage_save_status', 	array($xcloner_api,'remote_storage_save_status')  );
542
			add_action( 'wp_ajax_upload_backup_to_remote', 		array($xcloner_api,'upload_backup_to_remote')  );
543
			add_action( 'wp_ajax_list_backup_files'	,			array($xcloner_api,'list_backup_files')  );
544
			add_action( 'wp_ajax_restore_upload_backup'	, 		array($xcloner_api,'restore_upload_backup')  );
545
			add_action( 'wp_ajax_download_restore_script', 		array($xcloner_api,'download_restore_script')  );
546
			add_action( 'wp_ajax_copy_backup_remote_to_local', 	array($xcloner_api,'copy_backup_remote_to_local')  );
547
			add_action( 'wp_ajax_restore_backup', 				array($xcloner_api,'restore_backup')  );
548
			add_action( 'admin_notices', 						array($this, 'xcloner_error_admin_notices' ));
549
            
550
        }
551
        
552
        //Do a pre-update backup of targeted files
553
        if($this->get_xcloner_settings()->get_xcloner_option('xcloner_enable_pre_update_backup'))
554
        {
555
			add_action("pre_auto_update", array($this, "pre_auto_update"), 1, 3);
556
		}
557
	}
558
	
559
	function add_plugin_action_links($links, $file) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
560
        if ($file == plugin_basename(dirname(dirname(__FILE__)) . '/xcloner.php'))
561
		{	
562
			$links[] = '<a href="admin.php?page=xcloner_settings_page">'.__('Settings', 'xcloner-backup-and-restore').'</a>';
563
			$links[] = '<a href="admin.php?page=xcloner_generate_backups_page">'.__('Generate Backup', 'xcloner-backup-and-restore').'</a>';
564
		}
565
        
566
        return $links;
567
    }
568
	
569
	public function xcloner_error_admin_notices() {
570
			settings_errors( 'xcloner_error_message' );
571
		}
572
	
573
	public function define_cron_hooks()
574
	{
575
		//registering new schedule intervals
576
		add_filter( 'cron_schedules', array($this, 'add_new_intervals'));
577
			
578
		
579
		$xcloner_scheduler = $this->get_xcloner_scheduler();
580
		$xcloner_scheduler->update_wp_cron_hooks();
581
		
582
	}
583
	
584
	function add_new_intervals($schedules) 
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
585
	{
586
		//weekly scheduler interval
587
		$schedules['weekly'] = array(
588
			'interval' => 604800,
589
			'display' => __('Once Weekly', 'xcloner-backup-and-restore')
590
		);
591
		
592
		//monthly scheduler interval
593
		$schedules['monthly'] = array(
594
			'interval' => 2635200,
595
			'display' => __('Once Monthly', 'xcloner-backup-and-restore')
596
		);
597
		
598
		//monthly scheduler interval
599
		$schedules['twicedaily'] = array(
600
			'interval' => 43200,
601
			'display' => __('Twice Daily', 'xcloner-backup-and-restore')
602
		);
603
	
604
		return $schedules;
605
	}
606
607
	
608
	/**
609
	 * Run the loader to execute all of the hooks with WordPress.
610
	 *
611
	 * @since    1.0.0
612
	 */
613
	public function run() {
614
		$this->loader->run();
615
	}
616
617
	/**
618
	 * The name of the plugin used to uniquely identify it within the context of
619
	 * WordPress and to define internationalization functionality.
620
	 *
621
	 * @since     1.0.0
622
	 * @return    string    The name of the plugin.
623
	 */
624
	public function get_plugin_name() {
625
		return $this->plugin_name;
626
	}
627
628
	/**
629
	 * The reference to the class that orchestrates the hooks with the plugin.
630
	 *
631
	 * @since     1.0.0
632
	 * @return    Xcloner_Loader    Orchestrates the hooks of the plugin.
633
	 */
634
	public function get_loader() {
635
		return $this->loader;
636
	}
637
638
	/**
639
	 * Retrieve the version number of the plugin.
640
	 *
641
	 * @since     1.0.0
642
	 * @return    string    The version number of the plugin.
643
	 */
644
	public function get_version() {
645
		return $this->version;
646
	}
647
	
648
	function xcloner_display()
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
Coding Style introduced by
xcloner_display 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...
649
	{	
650
		// check user capabilities
651
	    if (!current_user_can('manage_options')) {
652
	        return;
653
	    }
654
	
655
		$page = sanitize_key($_GET['page']);
656
657
		if($page)
658
		{
659
			$this->display($page);
660
		}
661
		
662
	}
663
	
664
	public function display($page)
665
	{
666
		$plugin_admin = new Xcloner_Admin($this);
667
		$this->plugin_admin = $plugin_admin;
668
		
669
		call_user_func_array(array($this->plugin_admin, $page), array());
670
	}
671
}
672