Completed
Push — master ( 6b2386...2bf093 )
by Ahmad
04:44
created

TitanFrameworkOptionEddLicense   B

Complexity

Total Complexity 53

Size/Duplication

Total Lines 452
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4
Metric Value
wmc 53
lcom 1
cbo 4
dl 0
loc 452
rs 7.4757

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
C activateLicense() 0 40 8
C display() 0 66 9
A registerCustomizerControl() 0 12 1
D check() 0 93 13
D checkUpdates() 0 109 15
B item_is() 0 32 4
A disable_wporg_request() 0 21 2

How to fix   Complexity   

Complex Class

Complex classes like TitanFrameworkOptionEddLicense often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use TitanFrameworkOptionEddLicense, and based on these observations, apply Extract Interface, too.

1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 27 and the first side effect is on line 23.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
/**
3
 * EDD License Activation.
4
 *
5
 * This class is meant to handle Easy Digital Downloads licenses.
6
 * When a license is entered, it's checked with the server through
7
 * the EDD API. If the license is valid it is activated and
8
 * the activation result is saved as a transient.
9
 *
10
 * As the licensed can be deactivated directly from the server,
11
 * a regular check needs to be done on the license in order to make sure
12
 * that the status is up to date.
13
 *
14
 * The required option parameters for the activator to work are:
15
 *
16
 * - (string) $server     URL of the shop where the license was generated
17
 * - (string) $item_name  The name of the item as set in the shop
18
 *
19
 * @author Julien Liabeuf <[email protected]>
20
 * @link   http://julienliabeuf.com
21
 */
22
23
if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly
24
}
25
if ( class_exists( 'TitanFrameworkOption' ) ) {
26
27
	class TitanFrameworkOptionEddLicense extends TitanFrameworkOption {
28
29
		public $defaultSecondarySettings = array(
30
			'placeholder' => '', // show this when blank
31
			'is_password' => false,
32
			'server'      => false,
33
		);
34
35
		/**
36
		 * Constructor
37
		 *
38
		 * @since    1.7.1
39
		 *
40
		 * @param array  $settings Option settings
41
		 * @param string $owner
42
		 */
43
		function __construct( $settings, $owner ) {
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...
44
			parent::__construct( $settings, $owner );
45
46
			add_action( 'admin_init',                                      array( $this, 'checkUpdates' ), 10, 0 );
47
			add_action( 'tf_create_option_' . $this->getOptionNamespace(), array( $this, 'activateLicense' ) );
48
		}
49
50
		/**
51
		 * Activated the given EDD license.
52
		 *
53
		 * @return	void
54
		 * @since	1.7.1
55
		 */
56
		public function activateLicense( $option ) {
57
			if ( $this->settings['id'] != $option->settings['id'] ) {
58
				return;
59
			}
60
61
			/* Get the license */
62
			$license = esc_attr( $this->getValue() );
63
64
			/* License ID */
65
			$key = substr( md5( $license ), 0, 10 );
66
67
			/* If the license is set we can handle activation. */
68
			if ( strlen( $license ) > 0 ) {
69
70
				/* First of all we check if the user requested a manual activation */
71
				if ( isset( $_GET['eddactivate'] ) && '1' == $_GET['eddactivate'] ) {
72
73
					global $pagenow;
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...
74
75
					if ( isset( $_GET ) ) {
76
						$get = (array) $_GET;
77
					}
78
79
					if ( isset( $get['eddactivate'] ) ) {
80
						unset( $get['eddactivate'] );
81
					}
82
83
					$this->check( $license, 'activate_license' );
84
85
					/* Redirect to the settings page without the eddactivate parameter (otherwise it's used in all tabs links) */
86
					wp_redirect( wp_sanitize_redirect( add_query_arg( $get, admin_url( $pagenow ) ) ) );
0 ignored issues
show
Bug introduced by
The variable $get 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...
87
				}
88
89
				/* First activation of the license. */
90
				if ( false == get_transient( "tf_edd_license_try_$key" ) ) {
91
					$this->check( $license, 'activate_license' );
92
				}
93
			}
94
95
		}
96
97
		/**
98
		 * Display for options and meta
99
		 */
100
		public function display() {
101
102
			/* Get the license */
103
			$license = esc_attr( $this->getValue() );
104
105
			/* License ID */
106
			$key = substr( md5( $license ), 0, 10 );
107
108
			$this->echoOptionHeader();
109
110
			printf( '<input class="regular-text" name="%s" placeholder="%s" id="%s" type="%s" value="%s" />',
111
				$this->getID(),
112
				$this->settings['placeholder'],
113
				$this->getID(),
114
				$this->settings['is_password'] ? 'password' : 'text',
115
			$license );
116
117
			/* If the license is set, we display its status and check it if necessary. */
118
			if ( strlen( $license ) > 0 ) {
119
120
				/* Get the license activation status */
121
				$status = get_transient( "tf_edd_license_status_$key" );
122
123
				/* If no transient is found or it is expired to check the license again. */
124
				if ( false == $status ) {
125
					$status = $this->check( $license );
126
				}
127
128
				switch ( $status ) {
129
130
					case 'valid':
131
						?><p class="description"><?php esc_html_e( 'Your license is valid and active.', TF_I18NDOMAIN ); ?></p><?php
132
					break;
133
134
					case 'invalid':
135
						?><p class="description"><?php esc_html_e( 'Your license is invalid.', TF_I18NDOMAIN ); ?></p><?php
136
					break;
137
138
					case 'inactive':
139
140
						global $pagenow;
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...
141
142
						if ( isset( $_GET ) ) {
143
							$get = (array) $_GET;
144
						}
145
146
						$get['eddactivate'] = true;
0 ignored issues
show
Bug introduced by
The variable $get 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...
147
						$url                = esc_url( add_query_arg( $get, admin_url( $pagenow ) ) );
148
						?>
149
						<a href="<?php echo $url; ?>" class="button-secondary"><?php esc_html_e( 'Activate', TF_I18NDOMAIN ); ?></a>
150
						<p class="description"><?php esc_html_e( 'Your license is valid but inactive. Click the button above to activate it.', TF_I18NDOMAIN ); ?></p><?php
151
152
					break;
153
154
					case 'no_response':
155
						?><p class="description"><?php esc_html_e( 'The remote server did not return a valid response. You can retry by hitting the &laquo;Save&raquo; button again.', TF_I18NDOMAIN ); ?></p><?php
156
					break;
157
158
				}
159
			} else {
160
				?><p class="description"><?php esc_html_e( 'Entering your license key is mandatory to get the product updates.', TF_I18NDOMAIN ); ?></p><?php
161
			}
162
163
			$this->echoOptionFooter();
164
165
		}
166
167
		/*
168
		 * Display for theme customizer
169
		 */
170
		public function registerCustomizerControl( $wp_customize, $section, $priority = 1 ) {
171
			/**
172
			 * @var WP_Customize_Manager $wp_customize
173
			 */
174
			$wp_customize->add_control( new TitanFrameworkCustomizeControl( $wp_customize, $this->getID(), array(
175
				'label' => $this->settings['name'],
176
				'section' => $section->settings['id'],
177
				'settings' => $this->getID(),
178
				'description' => $this->settings['desc'],
179
				'priority' => $priority,
180
			) ) );
181
		}
182
183
		/**
184
		 * Check license status.
185
		 *
186
		 * The function makes an API call to the remote server and
187
		 * requests the license status.
188
		 *
189
		 * This function check (only) the license status or activate it
190
		 * depending on the $action parameter. The license status is then
191
		 * stored as a transient, and if an activation was made, an activation
192
		 * transient is also set in order to avoid activating when
193
		 * checking only is required.
194
		 *
195
		 * @param  string $license License key
196
		 * @param  string $action  Action to take (check_license or activate_license)
197
		 * @return string          Current license status
198
		 */
199
		public function check( $license = '', $action = 'check_license' ) {
200
201
			if ( empty( $license ) ) {
202
				return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type documented by TitanFrameworkOptionEddLicense::check of type string.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

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

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
203
			}
204
205
			/* Sanitize the key. */
206
			$license = trim( sanitize_key( $license ) );
207
208
			/* Set the transients lifetime. */
209
			$status_lifetime     = apply_filters( 'tf_edd_license_status_lifetime', 48 * 60 * 60 );         // Default is set to two days
210
			$activation_lifetime = apply_filters( 'tf_edd_license_activation_lifetime', 365 * 24 * 60 * 60 ); // Default is set to one year
211
212
			/* Prepare the data to send with the API request. */
213
			$api_params = array(
214
				'edd_action' => $action,
215
				'license'    => $license,
216
				'url'        => home_url(),
217
			);
218
219
			/**
220
			 * Set the item ID or name. ID has the highest priority
221
			 *
222
			 * @since 1.7.4
223
			 */
224
			if ( isset( $this->settings['item_id'] ) ) {
225
				$api_params['item_id'] = urlencode( $this->settings['item_id'] );
226
			} elseif ( isset( $this->settings['item_name'] ) ) {
227
				$api_params['item_name'] = urlencode( $this->settings['item_name'] );
228
			}
229
230
			if ( ! isset( $api_params['item_id'] ) && ! isset( $api_params['item_name'] ) ) {
231
				return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type documented by TitanFrameworkOptionEddLicense::check of type string.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

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

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
232
			}
233
234
			/* Call the API. */
235
			$response = wp_remote_get( add_query_arg( $api_params, $this->settings['server'] ), array( 'timeout' => 15, 'sslverify' => false ) );
236
237
			/* Check for request error. */
238
			if ( is_wp_error( $response ) ) {
239
				return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type documented by TitanFrameworkOptionEddLicense::check of type string.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

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

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
240
			}
241
242
			/* Decode license data. */
243
			$license_data = json_decode( wp_remote_retrieve_body( $response ) );
244
245
			/* If the remote server didn't return a valid response we just return an error and don't set any transients so that activation will be tried again next time the option is saved */
246
			if ( ! is_object( $license_data ) || empty( $license_data ) || ! isset( $license_data->license ) ) {
247
				return 'no_response';
248
			}
249
250
			/* License ID */
251
			$key = substr( md5( $license ), 0, 10 );
252
253
			if ( 'activate_license' == $action ) {
254
255
				/**
256
				 * If the license is invalid we can set all transients right away.
257
				 * The user will need to modify its license anyways so there is no risk
258
				 * of preventing further activation attempts.
259
				 */
260
				if ( 'invalid' == $license_data->license ) {
261
					set_transient( "tf_edd_license_status_$key", 'invalid', $status_lifetime );
262
					set_transient( "tf_edd_license_try_$key", true, $activation_lifetime );
263
					return 'invalid';
264
				}
265
266
				/**
267
				 * Because sometimes EDD returns a "success" status even though the license hasn't been activated,
268
				 * we need to check the license status after activating it. Only then we can safely set the
269
				 * transients and avoid further activation attempts issues.
270
				 *
271
				 * @link https://github.com/gambitph/Titan-Framework/issues/203
272
				 */
273
				$status = $this->check( $license );
274
275
				if ( in_array( $status, array( 'valid', 'inactive' ) ) ) {
276
277
					/* We set the "try" transient only as the status will be set by the second instance of this method when we check the license status */
278
					set_transient( "tf_edd_license_try_$key", true, $activation_lifetime );
279
280
				}
281
			} else {
282
283
				/* Set the status transient. */
284
				set_transient( "tf_edd_license_status_$key", $license_data->license, $status_lifetime );
285
286
			}
287
288
			/* Return the license status. */
289
			return $license_data->license;
290
291
		}
292
293
		/**
294
		 * Check for plugin updates.
295
		 *
296
		 * This method is called throughout the entire WordPress admin
297
		 * and uses the EDD plugin updater class to check for new updates.
298
		 *
299
		 * @since  1.7.2
300
		 * @return boolean True if an update check was done, false otherwise
301
		 */
302
		public function checkUpdates() {
303
304
			/* Check if we have all the required parameters. */
305
			if ( ! isset( $this->settings['server'] ) || ! isset( $this->settings['name'] ) || ! isset( $this->settings['file'] ) ) {
306
				return false;
307
			}
308
309
			/* Make sure the file actually exists. */
310
			if ( ! file_exists( $this->settings['file'] ) ) {
311
				return false;
312
			}
313
314
			/* Check what type of item the file is */
315
			$item_is = $this->item_is( $this->settings['file'] );
316
317
			/* Item name */
318
			$item_name = isset( $this->settings['item_name'] ) ? sanitize_text_field( $this->settings['item_name'] ) : false;
319
			$item_id   = isset( $this->settings['item_id'] ) ? (int) $this->settings['item_id'] : false;
320
321
			/* Retrieve license key */
322
			$license_key = trim( esc_attr( $this->getValue() ) );
323
324
			/* Prepare updater arguments */
325
			$args = array(
326
				'license' => $license_key, // Item license key
327
			);
328
329
			/* Add license ID or name for identification */
330
			if ( false != $item_id ) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $item_id of type integer|false against false; this is ambiguous if the integer can be zero. Consider using a strict comparison !== instead.
Loading history...
331
				$args['item_id'] = $item_id;
332
			} elseif ( false != $item_name ) {
333
				$args['item_name'] = $item_name;
334
			}
335
336
			/* Load the plugin updater class and add required parameters. */
337
			if ( 'plugin' == $item_is ) {
338
339
				if ( ! class_exists( 'TITAN_EDD_SL_Plugin_Updater' ) ) {
340
					include( TF_PATH . 'inc/edd-licensing/EDD_SL_Plugin_Updater.php' );
341
				}
342
343
				$plugin          = get_plugin_data( $this->settings['file'] );
344
				$args['version'] = $plugin['Version'];
345
				$args['author']  = $plugin['Author'];
346
347
			} /* Load the theme updater class and add required parameters. */
348
			elseif ( in_array( $item_is, array( 'theme-parent', 'theme-child' ) ) ) {
349
350
				if ( ! class_exists( 'TITAN_EDD_Theme_Updater' ) ) {
351
					include( TF_PATH . 'inc/edd-licensing/theme-updater-class.php' );
352
				}
353
354
				add_filter( 'http_request_args', array( $this, 'disable_wporg_request' ), 5, 2 );
355
356
				$theme_dir = explode( '/', substr( str_replace( get_theme_root(), '', $this->settings['file'] ), 1 ) );
357
				$theme     = wp_get_theme( $theme_dir[0], get_theme_root() );
358
359
				/* Make sure the theme exists. */
360
				if ( ! $theme->exists() ) {
361
					return false;
362
				}
363
364
				$args['version']        = $theme->get( 'Version' );
365
				$args['author']         = $theme->get( 'Author' );
366
				$args['remote_api_url'] = esc_url( $this->settings['server'] );
367
368
				/* Set the update messages. */
369
				$strings = array(
370
					'theme-license'             => __( 'Theme License', 'edd-theme-updater' ),
371
					'enter-key'                 => __( 'Enter your theme license key.', 'edd-theme-updater' ),
372
					'license-key'               => __( 'License Key', 'edd-theme-updater' ),
373
					'license-action'            => __( 'License Action', 'edd-theme-updater' ),
374
					'deactivate-license'        => __( 'Deactivate License', 'edd-theme-updater' ),
375
					'activate-license'          => __( 'Activate License', 'edd-theme-updater' ),
376
					'status-unknown'            => __( 'License status is unknown.', 'edd-theme-updater' ),
377
					'renew'                     => __( 'Renew?', 'edd-theme-updater' ),
378
					'unlimited'                 => __( 'unlimited', 'edd-theme-updater' ),
379
					'license-key-is-active'     => __( 'License key is active.', 'edd-theme-updater' ),
380
					'expires%s'                 => __( 'Expires %s.', 'edd-theme-updater' ),
381
					'%1$s/%2$-sites'            => __( 'You have %1$s / %2$s sites activated.', 'edd-theme-updater' ),
382
					'license-key-expired-%s'    => __( 'License key expired %s.', 'edd-theme-updater' ),
383
					'license-key-expired'       => __( 'License key has expired.', 'edd-theme-updater' ),
384
					'license-keys-do-not-match' => __( 'License keys do not match.', 'edd-theme-updater' ),
385
					'license-is-inactive'       => __( 'License is inactive.', 'edd-theme-updater' ),
386
					'license-key-is-disabled'   => __( 'License key is disabled.', 'edd-theme-updater' ),
387
					'site-is-inactive'          => __( 'Site is inactive.', 'edd-theme-updater' ),
388
					'license-status-unknown'    => __( 'License status is unknown.', 'edd-theme-updater' ),
389
					'update-notice'             => __( "Updating this theme will lose any customizations you have made. 'Cancel' to stop, 'OK' to update.", 'edd-theme-updater' ),
390
					'update-available'          => __( '<strong>%1$s %2$s</strong> is available. <a href="%3$s" class="thickbox" title="%4s">Check out what\'s new</a> or <a href="%5$s"%6$s>update now</a>.', 'edd-theme-updater' ),
391
				);
392
393
			} /* What the hell is this?? */
394
			else {
395
				return false;
396
			}
397
398
			/* Update server URL */
399
			$endpoint = esc_url( $this->settings['server'] );
400
401
			/* Setup updater */
402
			if ( 'plugin' == $item_is ) {
403
				$edd_updater = new TITAN_EDD_SL_Plugin_Updater( $endpoint, $this->settings['file'], $args );
404
			} else {
405
				new TITAN_EDD_Theme_Updater( $args, $strings );
0 ignored issues
show
Bug introduced by
The variable $strings 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...
406
			}
407
408
			return true;
409
410
		}
411
412
		/**
413
		 * Check if $file is a theme or a plugin.
414
		 *
415
		 * @since  1.7.2
416
		 * @param  string $file Path to the file to check
417
		 * @return string       What type of file this is (parent theme, child theme or plugin)
418
		 */
419
		public function item_is( $file ) {
420
421
			$parentTheme = trailingslashit( get_template_directory() );
422
			$childTheme  = trailingslashit( get_stylesheet_directory() );
423
424
			/**
425
			 * Windows sometimes mixes up forward and back slashes, ensure forward slash for
426
			 * correct URL output.
427
			 *
428
			 * @see  TitanFramework::getURL()
429
			 */
430
			$parentTheme = str_replace( '\\', '/', $parentTheme );
431
			$childTheme  = str_replace( '\\', '/', $childTheme );
432
			$file        = str_replace( '\\', '/', $file );
433
434
			/* Make sure the file exists. */
435
			if ( ! file_exists( $file ) ) {
436
				return false;
437
			}
438
439
			/* The $file is in a parent theme */
440
			if ( stripos( $file, $parentTheme ) != false ) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing stripos($file, $parentTheme) of type integer to the boolean false. If you are specifically checking for non-zero, consider using something more explicit like > 0 or !== 0 instead.
Loading history...
441
				return 'theme-parent';
442
			} /* The $file is in a child theme */
443
			else if ( stripos( $file, $childTheme ) != false ) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing stripos($file, $childTheme) of type integer to the boolean false. If you are specifically checking for non-zero, consider using something more explicit like > 0 or !== 0 instead.
Loading history...
444
				return 'theme-child';
445
			} /* The $file is in a plugin */
446
			else {
447
				return 'plugin';
448
			}
449
450
		}
451
452
		/**
453
		 * Disable requests to wp.org repository for this theme.
454
		 *
455
		 * @since 1.7.2
456
		 */
457
		function disable_wporg_request( $r, $url ) {
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...
458
459
			// If it's not a theme update request, bail.
460
			if ( 0 != strpos( $url, 'https://api.wordpress.org/themes/update-check/1.1/' ) ) {
461
	 			return $r;
462
	 		}
463
464
	 		// Decode the JSON response
465
	 		$themes = json_decode( $r['body']['themes'] );
466
467
	 		// Remove the active parent and child themes from the check
468
	 		$parent = get_option( 'template' );
469
	 		$child = get_option( 'stylesheet' );
470
	 		unset( $themes->themes->$parent );
471
	 		unset( $themes->themes->$child );
472
473
	 		// Encode the updated JSON response
474
	 		$r['body']['themes'] = json_encode( $themes );
475
476
	 		return $r;
477
		}
478
	}
479
}
480