Completed
Push — develop ( b30a9b...fddcc1 )
by Zack
07:54
created

GV_License_Handler::_get_edd_settings()   B

Complexity

Conditions 3
Paths 4

Size

Total Lines 24
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
cc 3
eloc 15
nc 4
nop 2
dl 0
loc 24
ccs 0
cts 18
cp 0
crap 12
rs 8.9713
c 0
b 0
f 0
1
<?php
2
3
class GV_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...
4
5
	/**
6
	 * @var GravityView_Settings
7
	 */
8
	private $Addon;
9
10
	const name = 'GravityView';
11
12
	const author = 'Katz Web Services, Inc.';
13
	
14
	const url = 'https://gravityview.co';
15
	
16
	const version = GravityView_Plugin::version;
17
18
	/**
19
	 * Post ID on gravityview.co
20
	 * @since 1.15
21
	 */
22
	const item_id = 17;
23
24
	/**
25
	 * Name of the transient used to store license status for GV
26
	 * @since 1.17
27
	 */
28
	const status_transient_key = 'gravityview_edd-activate_valid';
29
30
	/**
31
	 * @var string Key used to store active GravityView/Gravity Forms plugin data
32
	 * @since 1.15
33
	 */
34
	const related_plugins_key = 'gravityview_related_plugins';
35
36
	/** @var EDD_SL_Plugin_Updater */
37
	private $EDD_SL_Plugin_Updater;
38
39
	/**
40
	 * @var GV_License_Handler
41
	 */
42
	public static $instance;
43
44
	/**
45
	 * @param GravityView_Settings $GFAddOn
46
	 *
47
	 * @return GV_License_Handler
48
	 */
49
	public static function get_instance( GravityView_Settings $GFAddOn ) {
50
		if( empty( self::$instance ) ) {
51
			self::$instance = new self( $GFAddOn );
52
		}
53
		return self::$instance;
54
	}
55
	
56
	private function __construct( GravityView_Settings $GFAddOn ) {
57
58
		$this->Addon = $GFAddOn;
59
60
		$this->setup_edd();
61
		
62
		$this->add_hooks();
63
	}
64
65
	private function add_hooks() {
66
		add_action( 'wp_ajax_gravityview_license', array( $this, 'license_call' ) );
67
		add_action( 'admin_init', array( $this, 'refresh_license_status' ) );
68
		add_action( 'admin_init', array( $this, 'check_license' ) );
69
		add_action( 'update_option_active_plugins', array( $this, 'flush_related_plugins_transient' ) );
70
		add_action( 'update_option_active_sitewide_plugins', array( $this, 'flush_related_plugins_transient' ) );
71
	}
72
73
	/**
74
	 * When a plugin is activated or deactivated, delete the cached extensions/plugins used by get_related_plugins_and_extensions()
75
	 *
76
	 * @see get_related_plugins_and_extensions()
77
	 * @since 1.15
78
	 */
79
	public function flush_related_plugins_transient() {
80
		if ( function_exists( 'delete_site_transient' ) ) {
81
			delete_site_transient( self::related_plugins_key );
82
		}
83
	}
84
85
	/**
86
	 * Check the GravityView license information
87
	 *
88
	 * @since 1.19.3
89
	 *
90
	 * @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...
91
	 *
92
	 * @return void
93
	 */
94
	public function check_license() {
95
96
		if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
97
			return; // Don't fire when saving settings or AJAX
98
		}
99
100
		if ( ! apply_filters( 'gv_send_site_data', true ) ) {
101
			return;
102
		}
103
104
		// Send checkins once per week
105
		$last_checked = get_option( 'gv_last_checkin', false );
106
107
		if ( is_numeric( $last_checked ) && $last_checked > strtotime( '-1 week', current_time( 'timestamp' ) ) ) {
108
			return; // checked within a week
109
		}
110
111
		$status = get_transient( 'gv_license_check' );
112
113
		// Run the license check a maximum of once per day, and not on GV website
114
		if ( false === $status && site_url() !== self::url ) {
115
116
			// Call the custom API.
117
			$response = wp_remote_post( self::url, array(
118
				'timeout'   => 15,
119
			    'sslverify' => false,
120
			    'body'      =>  array(
0 ignored issues
show
introduced by
Expected 1 space after "=>"; 2 found
Loading history...
121
				    'edd_action' => 'check_license',
122
				    'license'    => trim( $this->Addon->get_app_setting( 'license_key' ) ),
123
				    'item_name'  => self::name,
124
				    'url'        => home_url(),
125
				    'site_data'  => $this->get_site_data(),
126
			    ),
127
			));
128
129
			// make sure the response came back okay
130
			if ( is_wp_error( $response ) ) {
131
132
				// Connection failed, try again in three hours
133
				set_transient( 'gv_license_check', 1, 3 * HOUR_IN_SECONDS );
134
135
				return;
136
			}
137
138
			set_transient( 'gv_license_check', 1, DAY_IN_SECONDS );
139
140
			update_option( 'gv_last_checkin', current_time( 'timestamp' ) );
141
		}
142
	}
143
144
	/**
145
	 * When the status transient expires (or is deleted on activation), re-check the status
146
	 *
147
	 * @since 1.17
148
	 *
149
	 * @return void
150
	 */
151
	public function refresh_license_status() {
152
153
		if ( defined('DOING_AJAX') && DOING_AJAX ) {
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
154
			return;
155
		}
156
157
		// The transient is fresh; don't fetch.
158
		if( $status = get_transient( self::status_transient_key ) ) {
159
			return;
160
		}
161
162
		$data = array(
163
			'edd_action' => 'check_license',
164
			'license' => trim( $this->Addon->get_app_setting( 'license_key' ) ),
165
			'update' => true,
166
			'format' => 'object',
167
			'all_caps' => true,
168
			'field_id' => 'refresh_license_status', // Required to set the `status_transient_key` transient
169
		);
170
171
		$license_call = GravityView_Settings::get_instance()->get_license_handler()->license_call( $data );
172
173
		do_action( 'gravityview_log_debug', __METHOD__ . ': Refreshed the license.', $license_call );
174
	}
175
176
	/**
177
	 * Retrieves site data (plugin versions, integrations, etc) to be sent along with the license check.
178
	 *
179
	 * @since 1.9
180
	 * @access public
181
	 *
182
	 * @return array
183
	 */
184
	public function get_site_data() {
185
186
		$data = array();
187
188
		$theme_data = wp_get_theme();
189
		$theme      = $theme_data->Name . ' ' . $theme_data->Version;
190
191
		$data['gv_version']  = GravityView_Plugin::version;
192
		$data['php_version']  = phpversion();
193
		$data['wp_version']   = get_bloginfo( 'version' );
194
		$data['gf_version']  = GFForms::$version;
195
		$data['server']       = isset( $_SERVER['SERVER_SOFTWARE'] ) ? $_SERVER['SERVER_SOFTWARE'] : '';
0 ignored issues
show
introduced by
Detected usage of a non-sanitized input variable: $_SERVER
Loading history...
196
		$data['multisite']    = is_multisite();
197
		$data['theme']        = $theme;
198
		$data['url']          = home_url();
199
		$data['license_key']  = GravityView_Settings::get_instance()->get_app_setting( 'license_key' );
200
201
		// View Data
202
		$gravityview_posts = get_posts('numberposts=-1&post_type=gravityview&post_status=publish&order=ASC');
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
introduced by
Disabling pagination is prohibited in VIP context, do not set numberposts to -1 ever.
Loading history...
203
204
		if ( ! empty( $gravityview_posts ) ) {
205
			$first = array_shift( $gravityview_posts );
206
			$latest = array_pop( $gravityview_posts );
207
			$data['view_count'] = count( $gravityview_posts );
208
			$data['view_first'] = $first->post_date;
209
			$data['view_latest'] = $latest->post_date;
210
		}
211
212
		// Form counts
213
		if ( class_exists( 'GFFormsModel' ) ) {
214
			$form_data = GFFormsModel::get_form_count();
215
			$data['forms_total'] = rgar( $form_data, 'total', 0 );
216
			$data['forms_active'] = rgar( $form_data, 'active', 0 );
217
			$data['forms_inactive'] = rgar( $form_data, 'inactive', 0 );
218
			$data['forms_trash'] = rgar( $form_data, 'inactive', 0 );
219
		}
220
221
		// Retrieve current plugin information
222
		if( ! function_exists( 'get_plugins' ) ) {
223
			include ABSPATH . '/wp-admin/includes/plugin.php';
224
		}
225
226
		$data['integrations']     = self::get_related_plugins_and_extensions();
227
		$data['active_plugins']   = get_option( 'active_plugins', array() );
228
		$data['inactive_plugins'] = array();
229
		$data['locale']           = get_locale();
230
231
		// Validate request on the GV server
232
		$data['hash']             = 'gv_version.url.locale:' . sha1( $data['gv_version'] . $data['url'] . $data['locale'] );
233
234
		return $data;
235
	}
236
237
	/**
238
	 * Get active GravityView Extensions and Gravity Forms Add-ons to help debug issues.
239
	 *
240
	 * @since 1.15
241
	 * @return string List of active extensions related to GravityView or Gravity Forms, separated by HTML line breaks
242
	 */
243
	static public function get_related_plugins_and_extensions( $implode = '<br />' ) {
0 ignored issues
show
Coding Style introduced by
As per PSR2, the static declaration should come after the visibility declaration.
Loading history...
244
245
		if ( ! function_exists( 'wp_get_active_and_valid_plugins' ) ) {
246
			return 'Running < WP 3.0';
247
		}
248
249
		$extensions = get_site_transient( self::related_plugins_key );
250
251
		if ( empty( $extensions ) ) {
252
253
			$active_plugins = wp_get_active_and_valid_plugins();
254
			$extensions = array();
255
			foreach ( $active_plugins as $active_plugin ) {
256
257
				// Match gravityview, gravity-forms, gravityforms, gravitate
258
				if ( ! preg_match( '/(gravityview|gravity-?forms|gravitate)/ism', $active_plugin ) ) {
259
					continue;
260
				}
261
262
				$plugin_data = get_plugin_data( $active_plugin );
263
264
				$extensions[] = sprintf( '%s %s', $plugin_data['Name'], $plugin_data['Version'] );
265
			}
266
267
			if( ! empty( $extensions ) ) {
268
				set_site_transient( self::related_plugins_key, $extensions, HOUR_IN_SECONDS );
269
			} else {
270
				return 'There was an error fetching related plugins.';
271
			}
272
		}
273
274
		return $implode ? implode( $implode, $extensions ) : $extensions;
275
	}
276
277
	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...
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...
278
279
		$script_debug = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min';
280
281
		wp_enqueue_script( 'gv-admin-edd-license', GRAVITYVIEW_URL . 'assets/js/admin-edd-license' . $script_debug . '.js', array( 'jquery' ) );
282
283
		$status = trim( $this->Addon->get_app_setting( 'license_key_status' ) );
284
		$key = trim( $this->Addon->get_app_setting( 'license_key' ) );
285
286
		if( !empty( $key ) ) {
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
287
			$response = $this->Addon->get_app_setting( 'license_key_response' );
288
			$response = is_array( $response ) ? (object) $response : json_decode( $response );
289
		} else {
290
			$response = array();
291
		}
292
293
		wp_localize_script( 'gv-admin-edd-license', 'GVGlobals', array(
294
			'license_box' => $this->get_license_message( $response )
295
		));
296
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
297
298
		$fields = array(
299
			array(
300
				'name'  => 'edd-activate',
301
				'value' => __('Activate License', 'gravityview'),
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
302
				'data-pending_text' => __('Verifying license&hellip;', 'gravityview'),
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
303
				'data-edd_action' => 'activate_license',
304
				'class' => 'button-primary',
305
			),
306
			array(
307
				'name'  => 'edd-deactivate',
308
				'value' => __('Deactivate License', 'gravityview'),
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
309
				'data-pending_text' => __('Deactivating license&hellip;', 'gravityview'),
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
310
				'data-edd_action' => 'deactivate_license',
311
				'class' => ( empty( $status ) ? 'button-primary hide' : 'button-primary' ),
312
			),
313
			array(
314
				'name'  => 'edd-check',
315
				'value' => __('Check License', 'gravityview'),
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
316
				'data-pending_text' => __('Verifying license&hellip;', 'gravityview'),
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
317
				'title' => 'Check the license before saving it',
318
				'data-edd_action' => 'check_license',
319
				'class' => 'button-secondary',
320
			),
321
		);
322
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
323
324
		$class = 'button gv-edd-action';
325
326
		$class .= ( !empty( $key ) && $status !== 'valid' ) ? '' : ' hide';
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
327
328
		$disabled_attribute = GVCommon::has_cap( 'gravityview_edit_settings' ) ? false : 'disabled';
329
330
		$submit = '<div class="gv-edd-button-wrapper">';
331
		foreach ( $fields as $field ) {
332
			$field['type'] = 'button';
333
			$field['class'] = isset( $field['class'] ) ? $field['class'] . ' '. $class : $class;
334
			$field['style'] = 'margin-left: 10px;';
335
			if( $disabled_attribute ) {
336
				$field['disabled'] = $disabled_attribute;
337
			}
338
			$submit .= $this->Addon->settings_submit( $field, $echo );
339
		}
340
		$submit .= '</div>';
341
342
		return $submit;
343
	}
344
345
	/**
346
	 * Include the EDD plugin updater class, if not exists
347
	 * @since 1.7.4
348
	 * @return void
349
	 */
350
	private function setup_edd() {
351
352
		if( !class_exists('EDD_SL_Plugin_Updater') ) {
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
353
			require_once( GRAVITYVIEW_DIR . 'includes/lib/EDD_SL_Plugin_Updater.php');
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
354
		}
355
356
		// setup the updater
357
		$this->EDD_SL_Plugin_Updater = new EDD_SL_Plugin_Updater(
358
			self::url,
359
			GRAVITYVIEW_FILE,
360
			$this->_get_edd_settings()
361
		);
362
363
	}
364
365
	/**
366
	 * Generate the array of settings passed to the EDD license call
367
	 *
368
	 * @since 1.7.4
369
	 *
370
	 * @param string $action The action to send to edd, such as `check_license`
371
	 * @param string $license The license key to have passed to EDD
372
	 *
373
	 * @return array
374
	 */
375
	function _get_edd_settings( $action = '', $license = '' ) {
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...
376
377
		// retrieve our license key from the DB
378
		$license_key = empty( $license ) ? trim( $this->Addon->get_app_setting( 'license_key' ) ) : $license;
379
380
		$settings = array(
381
			'version'   => self::version,
382
			'license'   => $license_key,
383
			'item_name' => self::name,
384
			'item_id'   => self::item_id,
385
			'author'    => self::author,
386
			'language'  => get_locale(),
387
			'url'       => home_url(),
388
		    'beta'      => $this->Addon->get_app_setting( 'beta' ),
389
		);
390
391
		if( !empty( $action ) ) {
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
392
			$settings['edd_action'] = esc_attr( $action );
393
		}
394
395
		$settings = array_map( 'urlencode', $settings );
396
397
		return $settings;
398
	}
399
400
	/**
401
	 * Perform the call
402
	 * @return array|WP_Error
403
	 */
404
	private function _license_get_remote_response( $data, $license = '' ) {
405
406
		$api_params = $this->_get_edd_settings( $data['edd_action'], $license );
407
408
		$url = add_query_arg( $api_params, self::url );
409
410
		$response = wp_remote_get( $url, array(
0 ignored issues
show
introduced by
wp_remote_get is highly discouraged, please use vip_safe_wp_remote_get() instead.
Loading history...
411
			'timeout'   => 15,
412
			'sslverify' => false,
413
		));
414
415
		if ( is_wp_error( $response ) ) {
416
			return array();
417
		}
418
419
		$license_data = json_decode( wp_remote_retrieve_body( $response ) );
420
421
		// Not JSON
422
		if ( empty( $license_data ) ) {
423
424
			delete_transient( self::status_transient_key );
425
426
			// Change status
427
			return array();
428
		}
429
430
		// Store the license key inside the data array
431
		$license_data->license_key = $license;
432
433
		return $license_data;
434
	}
435
436
	/**
437
	 * Generate the status message displayed in the license field
438
	 *
439
	 * @since 1.7.4
440
	 * @param $license_data
441
	 *
442
	 * @return string
443
	 */
444
	function get_license_message( $license_data ) {
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...
445
446
		if( empty( $license_data ) ) {
447
			$message = '';
448
		} else {
449
450
			if( ! empty( $license_data->error ) ) {
451
				$class = 'error';
452
				$string_key = $license_data->error;
453
			} else {
454
				$class = $license_data->license;
455
				$string_key = $license_data->license;
456
			}
457
458
			$message = sprintf( '<p><strong>%s: %s</strong></p>', $this->strings('status'), $this->strings( $string_key, $license_data ) );
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
459
460
			$message = $this->generate_license_box( $message, $class );
461
		}
462
463
		return $message;
464
	}
465
466
	/**
467
	 * Generate the status message box HTML based on the current status
468
	 *
469
	 * @since 1.7.4
470
	 * @param $message
471
	 * @param string $class
472
	 *
473
	 * @return string
474
	 */
475
	private function generate_license_box( $message, $class = '' ) {
476
477
		$template = '<div id="gv-edd-status" aria-live="polite" aria-busy="false" class="gv-edd-message inline %s">%s</div>';
478
479
		$output = sprintf( $template, esc_attr( $class ), $message );
480
481
		return $output;
482
	}
483
484
	/**
485
	 * Allow pure HTML in settings fields
486
	 *
487
	 * @since 1.17
488
	 *
489
	 * @param array $response License response
490
	 *
491
	 * @return string `html` key of the $field
492
	 */
493
	public function license_details( $response = array() ) {
494
495
		$response = (array) $response;
496
497
		$return = '';
498
		$wrapper = '<span class="gv-license-details" aria-live="polite" aria-busy="false">%s</span>';
499
500
		if( ! empty( $response['license_key'] ) ) {
501
502
			$return .= '<h3>' . esc_html__( 'License Details:', 'gravityview' ) . '</h3>';
503
504
			if ( in_array( rgar( $response, 'license' ), array( 'invalid', 'deactivated' ) ) ) {
505
				$return .= $this->strings( $response['license'], $response );
506
			} elseif ( ! empty( $response['license_name'] ) ) {
507
508
				$response_keys = array(
509
					'license_name'   => '',
510
					'license_limit'  => '',
511
					'customer_name'  => '',
512
					'customer_email' => '',
513
					'site_count'     => '',
514
					'expires'        => '',
515
					'upgrades'       => ''
0 ignored issues
show
introduced by
Each line in an array declaration must end in a comma
Loading history...
516
				);
517
518
				// Make sure all the keys are set
519
				$response = wp_parse_args( $response, $response_keys );
520
521
				$login_link = sprintf( '<a href="%s" class="howto" 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' ) );
522
				$local_text = ( ! empty( $response['is_local'] ) ? '<span class="howto">' . __( 'This development site does not count toward license activation limits', 'gravityview' ) . '</span>' : '' );
523
				$details    = array(
524
					'license'     => sprintf( esc_html__( 'License level: %s', 'gravityview' ), esc_html( $response['license_name'] ), esc_html( $response['license_limit'] ) ),
525
					'licensed_to' => sprintf( esc_html_x( 'Licensed to: %1$s (%2$s)', '1: Customer name; 2: Customer email', 'gravityview' ), esc_html__( $response['customer_name'], 'gravityview' ), esc_html__( $response['customer_email'], 'gravityview' ) ) . $login_link,
526
					'activations' => sprintf( esc_html__( 'Activations: %d of %s sites', 'gravityview' ), intval( $response['site_count'] ), esc_html( $response['license_limit'] ) ) . $local_text,
527
					'expires'     => 'lifetime' === $response['expires'] ? '' : sprintf( esc_html__( 'Renew on: %s', 'gravityview' ), date_i18n( get_option( 'date_format' ), strtotime( $response['expires'] ) - DAY_IN_SECONDS ) ),
528
					'upgrade'     => $this->get_upgrade_html( $response['upgrades'] ),
529
				);
530
531
				if ( ! empty( $response['error'] ) && 'expired' === $response['error'] ) {
532
					unset( $details['upgrade'] );
533
					$details['expires'] = '<div class="error inline"><p>' . $this->strings( 'expired', $response ) . '</p></div>';
534
				}
535
536
				$return .= '<ul><li>' . implode( '</li><li>', array_filter( $details ) ) . '</li></ul>';
537
			}
538
		}
539
540
		return sprintf( $wrapper, $return );
541
	}
542
543
	/**
544
	 * Display possible upgrades for a license
545
	 *
546
	 * @since 1.17
547
	 *
548
	 * @param array $upgrades Array of upgrade paths, returned from the GV website
549
	 *
550
	 * @return string HTML list of upgrades available for the current license
551
	 */
552
	function get_upgrade_html( $upgrades ) {
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...
553
554
		$output = '';
555
556
		if( ! empty( $upgrades ) ) {
557
558
			$locale_parts = explode( '_', get_locale() );
559
560
			$is_english = ( 'en' === $locale_parts[0] );
561
562
			$output .= '<h4>' . esc_html__( 'Upgrades available:', 'gravityview' ) . '</h4>';
563
564
			$output .= '<ul class="ul-disc">';
565
566
			foreach ( $upgrades as $upgrade_id => $upgrade ) {
567
568
				$upgrade = (object) $upgrade;
569
570
				$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 ) );
571
572
				if( $is_english && isset( $upgrade->description ) ) {
573
					$message = esc_html( $upgrade->description );
574
				} else {
575
					switch( $upgrade->price_id ) {
576
						// Interstellar
577
						case 1:
578
						default:
579
							$message = esc_html__( 'Get access to Extensions', 'gravityview' );
580
							break;
581
						// Galactic
582
						case 2:
0 ignored issues
show
Unused Code introduced by
// Galactic case 2: ...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...
583
							$message = esc_html__( 'Get access to Entry Importer and other Premium plugins', 'gravityview' );
584
							break;
585
					}
586
				}
587
588
				$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 );
589
			}
590
			$output .= '</ul>';
591
		}
592
593
		return $output;
594
	}
595
596
	/**
597
	 * Perform the call to EDD based on the AJAX call or passed data
598
	 *
599
	 * @since 1.7.4
600
	 *
601
	 * @param array $array {
602
	 * @type string $license The license key
603
	 * @type string $edd_action The EDD action to perform, like `check_license`
604
	 * @type string $field_id The ID of the field to check
605
	 * @type boolean $update Whether to update plugin settings. Prevent updating the data by setting an `update` key to false
606
	 * @type string $format If `object`, return the object of the license data. Else, return the JSON-encoded object
607
	 * }
608
	 *
609
	 * @return mixed|string|void
610
	 */
611
	public function license_call( $array = array() ) {
612
613
		$is_ajax = ( defined('DOING_AJAX') && DOING_AJAX );
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
614
		$data = empty( $array ) ? $_POST['data'] : $array;
0 ignored issues
show
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_POST
Loading history...
615
		$has_cap = GVCommon::has_cap( 'gravityview_edit_settings' );
616
617
		if ( $is_ajax && empty( $data['license'] ) ) {
618
			die( - 1 );
0 ignored issues
show
Coding Style Compatibility introduced by
The method license_call() contains an exit expression.

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

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

Loading history...
619
		}
620
621
		// If the user isn't allowed to edit settings, show an error message
622
		if( ! $has_cap && empty( $data['all_caps'] ) ) {
623
			$license_data = new stdClass();
624
			$license_data->error = 'capability';
625
			$license_data->message = $this->get_license_message( $license_data );
626
			$json = json_encode( $license_data );
627
		} else {
628
629
			$license      = esc_attr( rgget( 'license', $data ) );
630
			$license_data = $this->_license_get_remote_response( $data, $license );
631
632
			// Empty is returned when there's an error.
633
			if ( empty( $license_data ) ) {
634
				if ( $is_ajax ) {
635
					exit( json_encode( array() ) );
0 ignored issues
show
Coding Style Compatibility introduced by
The method license_call() contains an exit expression.

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

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

Loading history...
636
				} else { // Non-ajax call
637
					return json_encode( array() );
638
				}
639
			}
640
641
			$license_data->details = $this->license_details( $license_data );
642
			$license_data->message = $this->get_license_message( $license_data );
643
644
			$json = json_encode( $license_data );
645
646
			$update_license = ( ! isset( $data['update'] ) || ! empty( $data['update'] ) );
647
648
			$is_check_action_button = ( 'check_license' === $data['edd_action'] && defined( 'DOING_AJAX' ) && DOING_AJAX );
649
650
			// Failed is the response from trying to de-activate a license and it didn't work.
651
			// This likely happened because people entered in a different key and clicked "Deactivate",
652
			// meaning to deactivate the original key. We don't want to save this response, since it is
653
			// most likely a mistake.
654
			if ( $license_data->license !== 'failed' && ! $is_check_action_button && $update_license ) {
0 ignored issues
show
introduced by
Found "!== '". Use Yoda Condition checks, you must
Loading history...
655
656
				if ( ! empty( $data['field_id'] ) ) {
657
					set_transient( self::status_transient_key, $license_data, DAY_IN_SECONDS );
658
				}
659
660
				$this->license_call_update_settings( $license_data, $data );
661
			}
662
		} // End $has_cap
663
664
		if ( $is_ajax ) {
665
			exit( $json );
0 ignored issues
show
Coding Style Compatibility introduced by
The method license_call() contains an exit expression.

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

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

Loading history...
666
		} else { // Non-ajax call
667
			return ( rgget('format', $data ) === 'object' ) ? $license_data : $json;
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
668
		}
669
	}
670
671
	/**
672
	 * Update the license after fetching it
673
	 * @param object $license_data
674
	 * @return void
675
	 */
676
	private function license_call_update_settings( $license_data, $data ) {
677
678
		// Update option with passed data license
679
		$settings = $this->Addon->get_app_settings();
680
681
        $settings['license_key'] = $license_data->license_key = trim( $data['license'] );
682
		$settings['license_key_status'] = $license_data->license;
683
		$settings['license_key_response'] = (array)$license_data;
0 ignored issues
show
introduced by
No space after closing casting parenthesis is prohibited
Loading history...
684
685
		$this->Addon->update_app_settings( $settings );
686
	}
687
688
	/**
689
	 * URL to direct license renewal, or if license key is not set, then just the account page
690
	 * @since 1.13.1
691
	 * @param  object|null $license_data Object with license data
692
	 * @return string Renewal or account URL
693
	 */
694
	private function get_license_renewal_url( $license_data ) {
695
		$license_data = is_array( $license_data ) ? (object)$license_data : $license_data;
0 ignored issues
show
introduced by
No space after closing casting parenthesis is prohibited
Loading history...
696
		$renew_license_url = ( ! empty( $license_data ) && !empty( $license_data->license_key ) ) ? sprintf( 'https://gravityview.co/checkout/?download_id=17&edd_license_key=%s&utm_source=admin_notice&utm_medium=admin&utm_content=expired&utm_campaign=Activation&force_login=1', $license_data->license_key ) : 'https://gravityview.co/account/';
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
697
		return $renew_license_url;
698
	}
699
700
	/**
701
	 * Override the text used in the GravityView EDD license Javascript
702
	 *
703
	 * @param  array|null $status Status to get. If empty, get all strings.
704
	 * @param  object|null $license_data Object with license data
705
	 * @return array          Modified array of content
706
	 */
707
	public function strings( $status = NULL, $license_data = null ) {
0 ignored issues
show
Coding Style introduced by
TRUE, FALSE and NULL must be lowercase; expected null, but found NULL.
Loading history...
708
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
709
710
		$strings = array(
711
			'status' => esc_html__('Status', 'gravityview'),
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
712
			'error' => esc_html__('There was an error processing the request.', 'gravityview'),
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
713
			'failed'  => esc_html__('Could not deactivate the license. The license key you attempted to deactivate may not be active or valid.', 'gravityview'),
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
714
			'site_inactive' => esc_html__('The license key is valid, but it has not been activated for this site.', 'gravityview'),
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
715
			'inactive' => esc_html__('The license key is valid, but it has not been activated for this site.', 'gravityview'),
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
716
			'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>' ),
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
717
			'deactivated' => esc_html__('The license has been deactivated.', 'gravityview'),
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
718
			'valid' => esc_html__('The license key is valid and active.', 'gravityview'),
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
719
			'invalid' => esc_html__('The license key entered is invalid.', 'gravityview'),
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
720
			'missing' => esc_html__('Invalid license key.', 'gravityview'),
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
721
			'revoked' => esc_html__('This license key has been revoked.', 'gravityview'),
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
722
			'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>' ),
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
723
			'capability' => esc_html__( 'You don\'t have the ability to edit plugin settings.', 'gravityview' ),
724
725
			'verifying_license' => esc_html__('Verifying license&hellip;', 'gravityview'),
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
726
			'activate_license' => esc_html__('Activate License', 'gravityview'),
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
727
			'deactivate_license' => esc_html__('Deactivate License', 'gravityview'),
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
728
			'check_license' => esc_html__('Verify License', 'gravityview'),
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
729
		);
730
731
		if( empty( $status ) ) {
732
			return $strings;
733
		}
734
735
		if( isset( $strings[ $status ] ) ) {
736
			return $strings[ $status ];
737
		}
738
739
		return NULL;
0 ignored issues
show
Coding Style introduced by
TRUE, FALSE and NULL must be lowercase; expected null, but found NULL.
Loading history...
740
	}
741
742
}