Completed
Pull Request — develop (#1505)
by Zack
21:14 queued 01:15
created

License_Handler   F

Complexity

Total Complexity 104

Size/Duplication

Total Lines 777
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 6

Test Coverage

Coverage 89.27%

Importance

Changes 0
Metric Value
dl 0
loc 777
ccs 283
cts 317
cp 0.8927
rs 1.823
c 0
b 0
f 0
wmc 104
lcom 1
cbo 6

19 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 15 2
A get() 0 6 2
A _get_edd_settings() 0 22 3
A setup_edd() 0 12 2
F license_call() 0 70 18
A get_license_message() 0 21 4
C license_details() 0 54 11
B get_upgrade_html() 0 40 7
A generate_license_box() 0 25 5
A strings() 0 32 1
A get_license_renewal_url() 0 15 4
A _license_get_remote_response() 0 32 3
A license_call_update_settings() 0 9 1
F settings_edd_license_activation() 0 72 13
A refresh_license_status() 0 22 4
B check_license() 0 48 9
B get_site_data() 0 62 6
B get_related_plugins_and_extensions() 0 31 7
A flush_related_plugins_transient() 0 5 2

How to fix   Complexity   

Complex Class

Complex classes like License_Handler 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 License_Handler, and based on these observations, apply Extract Interface, too.

1
<?php
2
namespace GV;
3
4
use GV\Shortcodes\gravityview;
5
6
/** If this file is called directly, abort. */
7
if ( ! defined( 'GRAVITYVIEW_DIR' ) ) {
8
	die();
9
}
10
11
/**
12
 * The \GV\License_Handler class.
13
 *
14
 * Handles everything licensing. Ka-ching!
15
 */
16
class License_Handler {
0 ignored issues
show
Coding Style introduced by
Since you have declared the constructor as private, maybe you should also declare the class as final.
Loading history...
17
	/**
18
	 * @var \GV\Addon_Settings The global addon settings binding.
19
	 */
20
	private $settings;
21
22
	const name = 'GravityView';
23
	const author = 'Katz Web Services, Inc.';
24
	const url = 'https://gravityview.co';
25
26
	/**
27
	 * Post ID on gravityview.co
28
	 * @since 1.15
29
	 */
30
	const item_id = 17;
31
32
	/**
33
	 * Name of the transient used to store license status for GV
34
	 * @since 1.17
35
	 */
36
	const status_transient_key = 'gravityview_edd-activate_valid';
37
38
	/**
39
	 * @var string Key used to store active GravityView/Gravity Forms plugin data
40
	 * @since 1.15
41
	 */
42
	const related_plugins_key = 'gravityview_related_plugins';
43
44
	/** @var \GV\EDD_SL_Plugin_Updater */
45
	private $EDD_SL_Plugin_Updater;
46
47
	/**
48
	 * @var \GV\License_Handler
49
	 */
50 1
	private static $__instance;
51
52 1
	private function __construct( $settings ) {
53
54 1
		$this->settings = $settings;
55
56
		if ( ! $this->settings instanceof Addon_Settings ) {
57
			$this->settings = gravityview()->plugin->settings;
58 1
		}
59 1
60 1
		add_action( 'admin_init', array( $this, 'setup_edd' ), 0 );
61 1
		add_action( 'wp_ajax_gravityview_license', array( $this, 'license_call' ) );
62 1
		add_action( 'admin_init', array( $this, 'refresh_license_status' ) );
63 1
		add_action( 'admin_init', array( $this, 'check_license' ) );
64 1
		add_action( 'update_option_active_plugins', array( $this, 'flush_related_plugins_transient' ) );
65
		add_action( 'update_option_active_sitewide_plugins', array( $this, 'flush_related_plugins_transient' ) );
66
	}
67
68
	/**
69 2
	 * @return \GV\License_Handler The global instance.
70 2
	 */
71 1
	public static function get( $settings = null ) {
72
		if ( ! self::$__instance ) {
73 2
			self::$__instance = new self( $settings );
74
		}
75
		return self::$__instance;
76
	}
77
78
	/**
79
	 * Generate the array of settings passed to the EDD license call
80
	 *
81
	 * @since 1.7.4
82
	 *
83
	 * @param string $action The action to send to edd, such as `check_license`
84
	 * @param string $license The license key to have passed to EDD
85
	 *
86 1
	 * @return array
87
	 */
88
	private function _get_edd_settings( $action = '', $license = '' ) {
89 1
90
		// retrieve our license key from the DB
91
		$license_key = empty( $license ) ? trim( $this->settings->get( 'license_key' ) ) : $license;
92 1
93 1
		$settings = array(
94 1
			'version'   => Plugin::$version,
95 1
			'license'   => $license_key,
96 1
			'item_name' => self::name,
97 1
			'item_id'   => self::item_id,
98 1
			'author'    => self::author,
99 1
			'language'  => get_locale(),
100
			'url'       => home_url(),
101
		    'beta'      => $this->settings->get( 'beta' ),
102 1
		);
103 1
104
		if ( ! empty( $action ) ) {
105
			$settings['edd_action'] = esc_attr( $action );
106 1
		}
107
108
		return array_map( 'urlencode', $settings );
109
	}
110
111
	/**
112
	 * Include the EDD plugin updater class, if not exists
113
	 *
114
	 * @since 1.7.4
115
	 * @since 1.21.5.3 Changed visibility of method to public
116
	 *
117 1
	 * @return void
118 1
	 */
119 1
	public function setup_edd() {
120
		if ( ! class_exists( '\GV\EDD_SL_Plugin_Updater' ) ) {
121
			require_once gravityview()->plugin->dir( 'future/lib/EDD_SL_Plugin_Updater.php' );
122
		}
123 1
124 1
		// setup the updater
125 1
		$this->EDD_SL_Plugin_Updater = new EDD_SL_Plugin_Updater(
126 1
			self::url,
127
			GRAVITYVIEW_FILE,
128 1
			$this->_get_edd_settings()
129
		);
130
	}
131
132
	/**
133
	 * Perform the call to EDD based on the AJAX call or passed data
134
	 *
135
	 * @since 1.7.4
136
	 *
137
	 * @param array $array {
138
	 * @type string $license The license key
139
	 * @type string $edd_action The EDD action to perform, like `check_license`
140
	 * @type string $field_id The ID of the field to check
141
	 * @type boolean $update Whether to update plugin settings. Prevent updating the data by setting an `update` key to false
142
	 * @type string $format If `object`, return the object of the license data. Else, return the JSON-encoded object
143
	 * }
144
	 * @param boolean $cap_check Require `gravityview_edit_settings` capability from current user.
145
	 *
146 1
	 * @return mixed|string|void
147
	 */
148 1
	public function license_call( $array = array(), $cap_check = true ) {
149 1
150
		$is_ajax = ( defined( 'DOING_AJAX' ) && DOING_AJAX );
151 1
		$data = empty( $array ) ? Utils::_POST( 'data', array() ) : $array;
152 1
153
		$data = wp_parse_args( $data, array(
154
			'license' => '',
155
			'edd_action' => '',
156
			'field_id' => '',
157
			'update' => '',
158
			'format' => 'json',
159 1
		) );
160
161
		if ( $is_ajax && empty( $data['license'] ) ) {
162
			die( -1 );
163
		}
164 1
165 1
		// If the user isn't allowed to edit settings, show an error message
166 1
		if ( $cap_check && ! \GVCommon::has_cap( 'gravityview_edit_settings' ) ) {
167 1
			$license_data = new \stdClass();
168 1
			$license_data->error = 'capability';
169
			$license_data->message = $this->get_license_message( $license_data );
170 1
			$json = json_encode( $license_data );
171 1
		} else {
172
			$license      = esc_attr( Utils::get( $data, 'license' ) );
173
			$license_data = $this->_license_get_remote_response( $data, $license );
174 1
175 1
			// Empty is returned when there's an error.
176
			if ( empty( $license_data ) ) {
177
				if ( $is_ajax ) {
178 1
					exit( json_encode( array() ) );
179
				} else { // Non-ajax call
180
					return json_encode( array() );
181
				}
182 1
			}
183 1
184
			$license_data->details = $this->license_details( $license_data );
185 1
			$license_data->message = $this->get_license_message( $license_data );
186
187 1
			$json = json_encode( $license_data );
188
189 1
			$update_license = Utils::get( $data, 'update' ) || 'gravityview_license' === Utils::_POST('action');
190
191 1
			$is_check_action_button = ( 'check_license' === Utils::get( $data, 'edd_action' ) && defined( 'DOING_AJAX' ) && DOING_AJAX );
192
193 1
			do_action('gravityview/admin_installer/delete_downloads_data', true );
194
195
			if ( $is_check_action_button ) {
196
				delete_transient( self::status_transient_key );
197
198
			// Failed is the response from trying to de-activate a license and it didn't work.
199
			// This likely happened because people entered in a different key and clicked "Deactivate",
200 1
			// meaning to deactivate the original key. We don't want to save this response, since it is
201
			// most likely a mistake.
202 1
			} else if ( $license_data->license !== 'failed' && $update_license ) {
203 1
204
				if ( ! empty( $data['field_id'] ) ) {
205
					set_transient( self::status_transient_key, $license_data, DAY_IN_SECONDS );
206 1
				}
207
208
				$this->license_call_update_settings( $license_data, $data );
209
			}
210 1
		}
211
212
		if ( $is_ajax ) {
213 1
			exit( $json );
214
		} else { // Non-ajax call
215
			return ( Utils::_GET( 'format', Utils::get( $data, 'format' ) ) === 'object' ) ? $license_data : $json;
216
		}
217
	}
218
219
	/**
220
	 * Generate the status message displayed in the license field
221
	 *
222
	 * @since 1.7.4
223
	 * @param $license_data
224
	 *
225 2
	 * @return string
226 2
	 */
227 2
	private function get_license_message( $license_data ) {
228
		if ( empty( $license_data ) ) {
229 1
			$message = '';
230 1
			if (gravityview()->plugin->is_GF_25()) {
231 1
				$message = $this->generate_license_box( $message, 'hide' );
232 1
			}
233 1
		} else {
234
			if( ! empty( $license_data->error ) ) {
235
				$class = 'error';
236 1
				$string_key = $license_data->error;
237
			} else { $class = $license_data->license;
238 1
				$string_key = $license_data->license;
239
			}
240
241 2
			$message = sprintf( '<p><strong>%s: %s</strong></p>', $this->strings( 'status' ), $this->strings( $string_key, $license_data ) );
242
243
			$message = $this->generate_license_box( $message, $class );
244
		}
245
246
		return $message;
247
	}
248
249
	/**
250
	 * Allow pure HTML in settings fields
251
	 *
252
	 * @since 1.17
253 2
	 *
254
	 * @param array $response License response
255 2
	 *
256
	 * @return string `html` key of the $field
257 2
	 */
258 2
	public function license_details( $response = array() ) {
259
260 2
		$response = (array) $response;
261 1
262
		$return = '';
263 1
		$wrapper = '<span class="gv-license-details" aria-live="polite" aria-busy="false">%s</span>';
264 1
265 1
		if ( ! empty( $response['license_key'] ) ) {
266
			$return .= '<h3>' . rtrim( esc_html__( 'License Details:', 'gravityview' ), ':' ) . '</h3>';
267 1
268
			if ( in_array( Utils::get( $response, 'license' ), array( 'invalid', 'deactivated' ) ) ) {
269
				if ( gravityview()->plugin->is_GF_25() ) {
270
					return sprintf( $wrapper, '' ); // Do not show redundant information - invalid/deactivated notice will be displayed by generate_license_box()
271
				}
272
273
				$return .= $this->strings( $response['license'], $response );
274
			} elseif ( ! empty( $response['license_name'] ) ) {
275
				$response_keys = array(
276
					'license_name'   => '',
277 1
					'license_limit'  => '',
278
					'customer_name'  => '',
279 1
					'customer_email' => '',
280 1
					'site_count'     => '',
281 1
					'expires'        => '',
282
					'upgrades'       => ''
283
				);
284 1
285 1
				// Make sure all the keys are set
286 1
				$response = wp_parse_args( $response, $response_keys );
287 1
288 1
				$login_link_class = gravityview()->plugin->is_GF_25() ? 'button button-outline outline' : 'text-link';
289
				$login_link    = sprintf( '<a href="%s" class="gv-access-account ' . $login_link_class . '" rel="external">%s</a>', esc_url( sprintf( 'https://gravityview.co/wp-login.php?username=%s', $response['customer_email'] ) ), esc_html__( 'Access your GravityView account', 'gravityview' ) );
290
				$local_text    = ( ! empty( $response['is_local'] ) ? '<span class="howto">' . __( 'This development site does not count toward license activation limits', 'gravityview' ) . '</span>' : '' );
291 1
				$license_limit = empty( $response['license_limit'] ) ? __( 'Unlimited', 'gravityview' ) : (int) $response['license_limit'];
292
293
				$details    = array(
294
					'license'     => sprintf( esc_html__( 'License level: %s', 'gravityview' ), '<span class="gv-license-detail">' . esc_html( $response['license_name'] ) . '</span>' ),
295
					'licensed_to' => sprintf( esc_html_x( 'Licensed to: %1$s (%2$s)', '1: Customer name; 2: Customer email', 'gravityview' ),  '<span class="gv-license-detail">' . esc_html__( $response['customer_name'], 'gravityview' ), esc_html__( $response['customer_email'], 'gravityview' ) ) . $login_link . '</span>',
296 1
					'activations' => sprintf( str_replace( '%d', '%s', esc_html__( 'Activations: %d of %s sites', 'gravityview' ) ), '<span class="gv-license-detail">' . intval( $response['site_count'] ), esc_html( $license_limit ) ) . '</span>' . $local_text,
297
					'expires'     => 'lifetime' === $response['expires'] ? '' : sprintf( esc_html__( 'Renew on: %s', 'gravityview' ), date_i18n( get_option( 'date_format' ), strtotime( $response['expires'] ) - DAY_IN_SECONDS ) ),
298
					'upgrade'     => $this->get_upgrade_html( $response['upgrades'] ),
299
				);
300 2
301
				if ( ! empty( $response['error'] ) && 'expired' === $response['error'] ) {
302
					unset( $details['upgrade'] );
303
					$details['expires'] = '<div class="error inline"><p>' . $this->strings( 'expired', $response ) . '</p></div>';
304
				}
305
306
				$return .= '<ul><li>' . implode( '</li><li>', array_filter( $details ) ) . '</li></ul>';
307
			}
308
		}
309
310
		return sprintf( $wrapper, $return );
311
	}
312 1
313
	/**
314 1
	 * Display possible upgrades for a license
315
	 *
316 1
	 * @since 1.17
317
	 *
318 1
	 * @param array $upgrades Array of upgrade paths, returned from the GV website
319 1
	 *
320
	 * @return string HTML list of upgrades available for the current license
321 1
	 */
322 1
	private function get_upgrade_html( $upgrades ) {
323
324 1
		$output = '';
325 1
326
		if ( ! empty( $upgrades ) ) {
327 1
328
			$locale_parts = explode( '_', get_locale() );
329 1
			$is_english = ( 'en' === $locale_parts[0] );
330 1
331
			$output .= '<h4>' . esc_html__( 'Upgrades available:', 'gravityview' ) . '</h4>';
332
			$output .= '<ul class="ul-disc">';
333
334
			foreach ( $upgrades as $upgrade_id => $upgrade ) {
335
				$upgrade = (object) $upgrade;
336
337
				$anchor_text = sprintf( esc_html_x( 'Upgrade to %1$s for %2$s', '1: GravityView upgrade name, 2: Cost of upgrade', 'gravityview' ), esc_attr( $upgrade->name ), esc_attr( $upgrade->price ) );
338
339
				if ( $is_english && isset( $upgrade->description ) ) {
340
					$message = esc_html( $upgrade->description );
341
				} else {
342
					switch( $upgrade->price_id ) {
343
						// Interstellar
344
						case 1:
345 1
						default:
346
							$message = esc_html__( 'Get access to Extensions', 'gravityview' );
347 1
							break;
348
						// Galactic
349
						case 2:
0 ignored issues
show
Unused Code introduced by
case 2: $message = e...avityview'); break; 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...
350 1
							$message = esc_html__( 'Get access to Entry Importer and other Premium plugins', 'gravityview' );
351
							break;
352
					}
353
				}
354
355
				$output .= sprintf( '<li><a href="%s">%s</a><span class="howto">%s</span></li>', esc_url( add_query_arg( array( 'utm_source' => 'settings', 'utm_medium' => 'admin', 'utm_content' => 'license-details', 'utm_campaign' => 'Upgrades' ), $upgrade->url ) ), $anchor_text, $message );
356
			}
357
			$output .= '</ul>';
358
		}
359
360
		return $output;
361
	}
362 1
363 1
	/**
364
	 * Generate the status message box HTML based on the current status
365 1
	 *
366
	 * @since 1.7.4
367 1
	 * @param string $message
368
	 * @param string $class
369
	 *
370
	 * @return string
371
	 */
372
	private function generate_license_box( $message, $class = '' ) {
373
374
		$message = ! empty( $message ) ? $message : '<p><strong></strong></p>';
375
376
		if ( gravityview()->plugin->is_GF_25() ) {
377 1
			switch ( $class ) {
378
				case 'valid':
379
					$class .= ' success';
380 1
					break;
381 1
				case 'invalid':
382 1
					$class .= ' error';
383 1
					break;
384 1
				default:
385 1
					$class .= ' warning';
386 1
			}
387 1
388 1
			$template = '<div id="gv-edd-status" aria-live="polite" aria-busy="false" class="alert %s">%s</div>';
389 1
		} else {
390 1
			$template = '<div id="gv-edd-status" aria-live="polite" aria-busy="false" class="gv-edd-message inline %s">%s</div>';
391 1
		}
392 1
393 1
		$output = sprintf( $template, esc_attr( $class ), $message );
394
395 1
		return $output;
396 1
	}
397 1
398 1
	/**
399
	 * Override the text used in the GravityView EDD license Javascript
400
	 *
401
	 * @param  string $status Status to get. If empty, get all strings.
402
	 * @param  object|array|null $license_data Object with license data, used to generate link to license renewal URL
403
	 * @return string Modified array of content
404
	 */
405 1
	public function strings( $status = NULL, $license_data = null ) {
406
407 1
		$strings = array(
408
			'status' => esc_html__( 'Status', 'gravityview' ),
409
			'error' => esc_html__( 'There was an error processing the request.', 'gravityview' ),
410
			'failed'  => esc_html__( 'Could not deactivate the license. The license key you attempted to deactivate may not be active or valid.', 'gravityview' ),
411
			'site_inactive' => esc_html__( 'The license key is valid, but it has not been activated for this site.', 'gravityview' ),
412
			'inactive' => esc_html__( 'The license key is valid, but it has not been activated for this site.', 'gravityview' ),
413
			'no_activations_left' => esc_html__( 'Invalid: this license has reached its activation limit.', 'gravityview' ) . ' ' . sprintf( esc_html__( 'You can manage license activations %son your GravityView account page%s.', 'gravityview' ), '<a href="https://gravityview.co/account/#licenses">', '</a>' ),
414
			'deactivated' => esc_html__( 'The license has been deactivated.', 'gravityview' ),
415
			'valid' => esc_html__( 'The license key is valid and active.', 'gravityview' ),
416 1
			'disabled' => sprintf( esc_html__( 'This license key is disabled. For updates and support, %spurchase a new license%s.', 'gravityview' ), '<a href="https://gravityview.co/account/">', '</a>' ),
417 1
			'invalid' => esc_html__( 'The license key entered is invalid.', 'gravityview' ),
418
			'invalid_item_id' => esc_html__( 'This license key does not have access to this plugin.', 'gravityview' ),
419 1
			'missing' => esc_html__( 'The license key entered is invalid.', 'gravityview' ), // Missing is "the license couldn't be found", not "you submitted an empty license"
420
			'revoked' => esc_html__( 'This license key has been revoked.', 'gravityview' ),
421 1
			'expired' => sprintf( esc_html__( 'This license key has expired. %sRenew your license on the GravityView website%s to receive updates and support.', 'gravityview' ), '<a href="'. esc_url( $this->get_license_renewal_url( $license_data ) ) .'">', '</a>' ),
422 1
			'capability' => esc_html__( 'You don\'t have the ability to edit plugin settings.', 'gravityview' ),
423
			'verifying_license' => esc_html__( 'Verifying license&hellip;', 'gravityview' ),
424 1
			'activate_license' => esc_html__( 'Activate License', 'gravityview' ),
425
			'deactivate_license' => esc_html__( 'Deactivate License', 'gravityview' ),
426
			'check_license' => esc_html__( 'Verify License', 'gravityview' ),
427 1
		);
428
429 1
		/**
430
		 * @internal Do not rely on this filter.
431
		 * @since 2.1
432
		 */
433
		$strings = apply_filters( 'gravityview/admin/license/strings', $strings );
434
435
		return Utils::get( $strings, $status, null );
436
	}
437 1
438 1
	/**
439
	 * URL to direct license renewal, or if license key is not set, then just the account page
440 1
	 * @since 1.13.1
441
	 * @param  object|null $license_data Object with license data
442 1
	 * @return string Renewal or account URL
443 1
	 */
444
	private function get_license_renewal_url( $license_data ) {
445
		$license_data = is_array( $license_data ) ? (object)$license_data : $license_data;
446
447 1
		if ( ! empty( $license_data->renewal_url ) ) {
448
			$renew_license_url = $license_data->renewal_url;
449
		} elseif( ! empty( $license_data->license_key ) ) {
450
			$renew_license_url = sprintf( 'https://gravityview.co/checkout/?download_id=17&edd_license_key=%s', $license_data->license_key );
451
		} else {
452 1
			$renew_license_url = 'https://gravityview.co/account/';
453
		}
454
455 1
		$renew_license_url = add_query_arg( wp_parse_args( 'utm_source=admin_notice&utm_medium=admin&utm_content=expired&utm_campaign=Activation&force_login=1' ), $renew_license_url );
456 1
457
		return $renew_license_url;
458 1
	}
459
460
	/**
461 1
	 * Perform the call
462
	 *
463
	 * @return array|\WP_Error
464
	 */
465 1
	private function _license_get_remote_response( $data, $license = '' ) {
466
		$api_params = $this->_get_edd_settings( $data['edd_action'], $license );
467 1
468
		$url = add_query_arg( $api_params, self::url );
469
470
		$response = wp_remote_get( $url, array(
471
			'timeout'   => 15,
472
			'sslverify' => false,
473
		) );
474
475 1
		if ( is_wp_error( $response ) ) {
476 1
			gravityview()->log->error( 'WP_Error response from license check. API params:', array( 'data' => $api_params ) );
477
			return array();
478 1
		}
479 1
480 1
		$license_data = json_decode( wp_remote_retrieve_body( $response ) );
481
482 1
		// Not JSON
483 1
		if ( empty( $license_data ) ) {
484
			gravityview()->log->error( 'Empty license data response from license check', array( 'data' => compact( 'response', 'url', 'api_params', 'data' ) ) );
485 2
486 2
			delete_transient( self::status_transient_key );
487
488 2
			// Change status
489
			return array();
490 2
		}
491 2
492
		// Store the license key inside the data array
493 2
		$license_data->license_key = $license;
494
495
		return $license_data;
496
	}
497 2
498
	/**
499
	 * Update the license after fetching it
500 2
	 * @param object $license_data
501 2
	 * @return void
502
	 */
503
	private function license_call_update_settings( $license_data, $data ) {
504
		$settings = array();
505
506 2
        $settings['license_key'] = $license_data->license_key = trim( $data['license'] );
507 2
		$settings['license_key_status'] = $license_data->license;
508 2
		$settings['license_key_response'] = (array)$license_data;
509 2
510 2
		$this->settings->set( $settings );
511
	}
512
513 2
	public function settings_edd_license_activation( $field, $echo ) {
0 ignored issues
show
Unused Code introduced by
The parameter $field 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...
514 2
515 2
		$script_debug = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min';
516 2
517 2
		wp_enqueue_script( 'gv-admin-edd-license', GRAVITYVIEW_URL . 'assets/js/admin-edd-license' . $script_debug . '.js', array( 'jquery' ) );
518
519
		// GF 2.5 compatibility
520 2
		if ( gravityview()->plugin->is_GF_25() ) {
521 2
			wp_register_style( 'gv-admin-edd-license', false );
522 2
			wp_enqueue_style( 'gv-admin-edd-license' );
523 2
		}
524 2
525 2
		$status = trim( $this->settings->get( 'license_key_status' ) );
526
		$key = trim( $this->settings->get( 'license_key' ) );
527
528
		if (  !empty( $key ) ) {
529 2
			$response = $this->settings->get( 'license_key_response' );
530
			$response = is_array( $response ) ? (object) $response : json_decode( $response );
531 2
		} else {
532
			$response = array();
533 2
		}
534
535 2
		wp_localize_script( 'gv-admin-edd-license', 'GVGlobals', array(
536 2
			'license_box' => $this->get_license_message( $response )
537 2
		) );
538 2
539 2
540 2
		$fields = array(
541 1
			array(
542
				'name'  => 'edd-activate',
543 2
				'value' => __( 'Activate License', 'gravityview' ),
544
				'data-pending_text' => __( 'Verifying license&hellip;', 'gravityview' ),
545 2
				'data-edd_action' => 'activate_license',
546
				'class' => 'button-primary primary',
547 2
			),
548
			array(
549
				'name'  => 'edd-deactivate',
550
				'value' => __( 'Deactivate License', 'gravityview' ),
551
				'data-pending_text' => __( 'Deactivating license&hellip;', 'gravityview' ),
552
				'data-edd_action' => 'deactivate_license',
553
				'class' => ( empty( $status ) ? 'button-primary primary hide' : 'button-primary primary' ),
554
			),
555
			array(
556
				'name'  => 'edd-check',
557 1
				'value' => __( 'Check License', 'gravityview' ),
558 1
				'data-pending_text' => __( 'Verifying license&hellip;', 'gravityview' ),
559
				'title' => 'Check the license before saving it',
560
				'data-edd_action' => 'check_license',
561
				'class' => 'button-secondary',
562
			),
563 1
		);
564
565
		$class = 'button gv-edd-action';
566
567
		$class .= ( ! empty( $key ) && $status !== 'valid' ) ? '' : ' hide';
568 1
569 1
		$disabled_attribute = \GVCommon::has_cap( 'gravityview_edit_settings' ) ? false : 'disabled';
570
571 1
		$submit = '<div class="gv-edd-button-wrapper">';
572 1
		foreach ( $fields as $field ) {
573
			$field['type'] = 'button';
574
			$field['class'] = isset( $field['class'] ) ? $field['class'] . ' '. $class : $class;
575 1
			$field['style'] = 'margin-left: 10px;';
576
			if( $disabled_attribute ) {
577 1
				$field['disabled'] = $disabled_attribute;
578 1
			}
579
			$submit .= $this->settings->as_html( $field, $echo );
580
		}
581
		$submit .= '</div>';
582
583
		return $submit;
584
	}
585
586
	/**
587
	 * When the status transient expires (or is deleted on activation), re-check the status
588 1
	 *
589 1
	 * @since 1.17
590
	 *
591
	 * @return void
592
	 */
593 1
	public function refresh_license_status() {
594
		if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
595
			return;
596
		}
597
598 1
		// The transient is fresh; don't fetch.
599
		if ( $status = get_transient( self::status_transient_key ) ) {
600 1
			return;
601
		}
602
603
		$data = array(
604 1
			'edd_action' => 'check_license',
605
			'license' => trim( $this->settings->get( 'license_key' ) ),
606
			'update' => true,
607 1
			'format' => 'object',
608
			'field_id' => 'refresh_license_status', // Required to set the `status_transient_key` transient
609
		);
610 1
611 1
		$license_call = $this->license_call( $data, false );
612
613
		gravityview()->log->debug( 'Refreshed the license.', array( 'data' => $license_call ) );
614 1
	}
615 1
616 1
	/**
617 1
	 * Check the GravityView license information
618 1
	 *
619
	 * @since 1.19.3
620
	 * @param bool $force Whether to force checking license, even if AJAX
0 ignored issues
show
Bug introduced by
There is no parameter named $force. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
621
	 *
622
	 * @return void
623 1
	 */
624
	public function check_license() {
625
		if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
626
			return; // Don't fire when saving settings or AJAX
627
		}
628
629
		if ( ! apply_filters( 'gv_send_site_data', true ) ) {
630
			return;
631 1
		}
632
633 1
		// Send checkins once per week
634
		$last_checked = get_option( 'gv_last_checkin', false );
635 1
636
		if ( is_numeric( $last_checked ) && $last_checked > strtotime( '-1 week', current_time( 'timestamp' ) ) ) {
637
			return; // checked within a week
638
		}
639
640
		$status = get_transient( 'gv_license_check' );
641
642
		// Run the license check a maximum of once per day, and not on GV website
643
		if ( false === $status && site_url() !== self::url ) {
644 1
645 1
			// Call the custom API.
646
			$response = wp_remote_post( self::url, array(
647 1
				'timeout'   => 15,
648 1
			    'sslverify' => false,
649
			    'body'      =>  array(
650 1
				    'edd_action' => 'check_license',
651 1
				    'license'    => trim( $this->settings->get( 'license_key' ) ),
652 1
				    'item_name'  => self::name,
653 1
				    'url'        => home_url(),
654 1
				    'site_data'  => $this->get_site_data(),
655 1
			    ),
656 1
			));
657 1
658 1
			// make sure the response came back okay
659 1
			if ( is_wp_error( $response ) ) {
660
661
				// Connection failed, try again in three hours
662 1
				set_transient( 'gv_license_check', 1, 3 * HOUR_IN_SECONDS );
663
664 1
				return;
665 1
			}
666 1
667
			set_transient( 'gv_license_check', 1, DAY_IN_SECONDS );
668 1
669 1
			update_option( 'gv_last_checkin', current_time( 'timestamp' ) );
670
		}
671 1
	}
672 1
673
	/**
674 1
	 * Retrieves site data (plugin versions, integrations, etc) to be sent along with the license check.
675 1
	 *
676
	 * @since 1.9
677 1
	 *
678 1
	 * @return array
679
	 */
680
	public function get_site_data() {
681
		$data = array();
682
683 1
		$theme_data = wp_get_theme();
684 1
		$theme      = $theme_data->Name . ' ' . $theme_data->Version;
685 1
686 1
		$data['gv_version']  = Plugin::$version;
687 1
		$data['php_version']  = phpversion();
688 1
		$data['wp_version']   = get_bloginfo( 'version' );
689
		$data['gf_version']  = \GFForms::$version;
690
		$data['server']       = Utils::get( $_SERVER, 'SERVER_SOFTWARE' );
691
		$data['multisite']    = is_multisite();
692 1
		$data['theme']        = $theme;
693
		$data['url']          = home_url();
694
		$data['license_key']  = $this->settings->get( 'license_key' );
695
		$data['beta']         = $this->settings->get( 'beta' );
696 1
697 1
		// View Data
698 1
		$gravityview_posts = wp_count_posts( 'gravityview', 'readable' );
699 1
700
		$data['view_count'] = null;
701
		$data['view_first'] = null;
702 1
		$data['view_latest'] = null;
703
704 1
		if ( $gravityview_posts->publish ) {
705
			$data['view_count'] = $gravityview_posts->publish;
706
707
			$first = get_posts( 'numberposts=1&post_type=gravityview&post_status=publish&order=ASC' );
708
			$latest = get_posts( 'numberposts=1&post_type=gravityview&post_status=publish&order=DESC' );
709
710
			if ( $first = array_shift( $first ) ) {
711
				$data['view_first'] = $first->post_date;
712
			}
713 1
			if ( $latest = array_pop( $latest ) ) {
714 1
				$data['view_latest'] = $latest->post_date;
715
			}
716
		}
717
718 1
		// Form counts
719
		if ( class_exists( 'GFFormsModel' ) ) {
720 1
			$form_data = \GFFormsModel::get_form_count();
721
			$data['forms_total'] = Utils::get( $form_data, 'total', 0 );
722 1
			$data['forms_active'] = Utils::get( $form_data, 'active', 0 );
723 1
			$data['forms_inactive'] = Utils::get( $form_data, 'inactive', 0 );
724 1
			$data['forms_trash'] = Utils::get( $form_data, 'inactive', 0 );
725
		}
726
727
		// Retrieve current plugin information
728
		if ( ! function_exists( 'get_plugins' ) ) {
729
			include ABSPATH . '/wp-admin/includes/plugin.php';
730
		}
731
732
		$data['integrations']     = self::get_related_plugins_and_extensions();
733
		$data['active_plugins']   = get_option( 'active_plugins', array() );
734
		$data['inactive_plugins'] = array();
735 1
		$data['locale']           = get_locale();
736
737
		// Validate request on the GV server
738 1
		$data['hash']             = 'gv_version.url.locale:' . sha1( $data['gv_version'] . $data['url'] . $data['locale'] );
739
740
		return $data;
741
	}
742
743
	/**
744
	 * Get active GravityView Extensions and Gravity Forms Add-ons to help debug issues.
745
	 *
746
	 * @since 1.15
747
	 * @return string List of active extensions related to GravityView or Gravity Forms, separated by HTML line breaks
748
	 */
749
	static public function get_related_plugins_and_extensions( $implode = '<br />' ) {
750
		if ( ! function_exists( 'wp_get_active_and_valid_plugins' ) ) {
751 1
			return 'Running < WP 3.0';
752 1
		}
753 1
754
		$extensions = get_site_transient( self::related_plugins_key );
755 1
756
		if ( empty( $extensions ) ) {
757
758
			$active_plugins = wp_get_active_and_valid_plugins();
759
			$extensions = array();
760
			foreach ( $active_plugins as $active_plugin ) {
761
				// Match gravityview, gravity-forms, gravityforms, gravitate
762
				if ( ! preg_match( '/(gravityview|gravity-?forms|gravitate|perk|gravity|gf)/ism', $active_plugin ) ) {
763
					continue;
764
				}
765
766
				$plugin_data = get_plugin_data( $active_plugin );
767
768
				$extensions[] = sprintf( '%s %s', $plugin_data['Name'], $plugin_data['Version'] );
769
			}
770
771
			if ( ! empty( $extensions ) ) {
772
				set_site_transient( self::related_plugins_key, $extensions, HOUR_IN_SECONDS );
773
			} else {
774
				return 'There was an error fetching related plugins.';
775
			}
776
		}
777
778
		return $implode ? implode( $implode, $extensions ) : $extensions;
779
	}
780
781
	/**
782
	 * When a plugin is activated or deactivated, delete the cached extensions/plugins used by get_related_plugins_and_extensions()
783
	 *
784
	 * @see get_related_plugins_and_extensions()
785
	 * @since 1.15
786
	 */
787
	public function flush_related_plugins_transient() {
788
		if ( function_exists( 'delete_site_transient' ) ) {
789
			delete_site_transient( self::related_plugins_key );
790
		}
791
	}
792
}
793