Completed
Push — develop ( 185933...c129cb )
by Zack
03:25
created

GV_License_Handler::setup_edd()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 7
nc 2
nop 0
dl 0
loc 14
rs 9.4285
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
	private $EDD_SL_Plugin_Updater;
37
38
	/**
39
	 * @var GV_License_Handler
40
	 */
41
	public static $instance;
42
43
	/**
44
	 * @param GravityView_Settings $GFAddOn
45
	 *
46
	 * @return GV_License_Handler
47
	 */
48
	public static function get_instance( GravityView_Settings $GFAddOn ) {
49
		if( empty( self::$instance ) ) {
50
			self::$instance = new self( $GFAddOn );
51
		}
52
		return self::$instance;
53
	}
54
	
55
	private function __construct( GravityView_Settings $GFAddOn ) {
56
57
		$this->Addon = $GFAddOn;
58
59
		$this->setup_edd();
60
		
61
		$this->add_hooks();
62
	}
63
64
	private function add_hooks() {
65
		add_action( 'wp_ajax_gravityview_license', array( $this, 'license_call' ) );
66
		add_action( 'admin_init', array( $this, 'refresh_license_status' ) );
67
		add_action( 'admin_init', array( $this, 'check_license' ) );
68
		add_action( 'update_option_active_plugins', array( $this, 'flush_related_plugins_transient' ) );
69
		add_action( 'update_option_active_sitewide_plugins', array( $this, 'flush_related_plugins_transient' ) );
70
	}
71
72
	/**
73
	 * When a plugin is activated or deactivated, delete the cached extensions/plugins used by get_related_plugins_and_extensions()
74
	 *
75
	 * @see get_related_plugins_and_extensions()
76
	 * @since 1.15
77
	 */
78
	public function flush_related_plugins_transient() {
79
		if ( function_exists( 'delete_site_transient' ) ) {
80
			delete_site_transient( self::related_plugins_key );
81
		}
82
	}
83
84
	/**
85
	 * Check the GravityView license information
86
	 *
87
	 * @since 1.19.3
88
	 *
89
	 * @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...
90
	 *
91
	 * @return void
92
	 */
93
	public function check_license() {
94
95
		if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
96
			return; // Don't fire when saving settings or AJAX
97
		}
98
99
		if ( ! apply_filters( 'gv_send_site_data', true ) ) {
100
			return;
101
		}
102
103
		// Send checkins once per week
104
		$last_checked = get_option( 'gv_last_checkin', false );
105
106
		if ( is_numeric( $last_checked ) && $last_checked > strtotime( '-1 week', current_time( 'timestamp' ) ) ) {
107
			return; // checked within a week
108
		}
109
110
		$status = get_transient( 'gv_license_check' );
111
112
		// Run the license check a maximum of once per day, and not on GV website
113
		if ( false === $status && site_url() !== self::url ) {
114
115
			// Call the custom API.
116
			$response = wp_remote_post( self::url, array(
117
				'timeout'   => 15,
118
			    'sslverify' => false,
119
			    'body'      =>  array(
0 ignored issues
show
introduced by
Expected 1 space after "=>"; 2 found
Loading history...
120
				    'edd_action' => 'check_license',
121
				    'license'    => trim( $this->Addon->get_app_setting( 'license_key' ) ),
122
				    'item_name'  => self::name,
123
				    'url'        => home_url(),
124
				    'site_data'  => $this->get_site_data(),
125
			    ),
126
			));
127
128
			// make sure the response came back okay
129
			if ( is_wp_error( $response ) ) {
130
131
				// Connection failed, try again in three hours
132
				set_transient( 'gv_license_check', 1, 3 * HOUR_IN_SECONDS );
133
134
				return;
135
			}
136
137
			set_transient( 'gv_license_check', 1, DAY_IN_SECONDS );
138
139
			update_option( 'gv_last_checkin', current_time( 'timestamp' ) );
140
		}
141
	}
142
143
	/**
144
	 * When the status transient expires (or is deleted on activation), re-check the status
145
	 *
146
	 * @since 1.17
147
	 *
148
	 * @return void
149
	 */
150
	public function refresh_license_status() {
151
152
		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...
153
			return;
154
		}
155
156
		// The transient is fresh; don't fetch.
157
		if( $status = get_transient( self::status_transient_key ) ) {
158
			return;
159
		}
160
161
		$data = array(
162
			'edd_action' => 'check_license',
163
			'license' => trim( $this->Addon->get_app_setting( 'license_key' ) ),
164
			'update' => true,
165
			'format' => 'object',
166
			'all_caps' => true,
167
			'field_id' => 'refresh_license_status', // Required to set the `status_transient_key` transient
168
		);
169
170
		$license_call = GravityView_Settings::get_instance()->get_license_handler()->license_call( $data );
171
172
		do_action( 'gravityview_log_debug', __METHOD__ . ': Refreshed the license.', $license_call );
173
	}
174
175
	/**
176
	 * Retrieves site data (plugin versions, integrations, etc) to be sent along with the license check.
177
	 *
178
	 * @since 1.9
179
	 * @access public
180
	 *
181
	 * @return array
182
	 */
183
	public function get_site_data() {
184
185
		$data = array();
186
187
		$theme_data = wp_get_theme();
188
		$theme      = $theme_data->Name . ' ' . $theme_data->Version;
189
190
		$data['gv_version']  = GravityView_Plugin::version;
191
		$data['php_version']  = phpversion();
192
		$data['wp_version']   = get_bloginfo( 'version' );
193
		$data['gf_version']  = GFForms::$version;
194
		$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...
195
		$data['multisite']    = is_multisite();
196
		$data['theme']        = $theme;
197
		$data['url']          = home_url();
198
199
		// View Data
200
		$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...
201
202
		if ( ! empty( $gravityview_posts ) ) {
203
			$first = array_shift( $gravityview_posts );
204
			$latest = array_pop( $gravityview_posts );
205
			$data['view_count'] = count( $gravityview_posts );
206
			$data['view_first'] = $first->post_date;
207
			$data['view_latest'] = $latest->post_date;
208
		}
209
210
		// Form counts
211
		if ( class_exists( 'GFFormsModel' ) ) {
212
			$form_data = GFFormsModel::get_form_count();
213
			$data['forms_total'] = rgar( $form_data, 'total', 0 );
214
			$data['forms_active'] = rgar( $form_data, 'active', 0 );
215
			$data['forms_inactive'] = rgar( $form_data, 'inactive', 0 );
216
			$data['forms_trash'] = rgar( $form_data, 'inactive', 0 );
217
		}
218
219
		// Retrieve current plugin information
220
		if( ! function_exists( 'get_plugins' ) ) {
221
			include ABSPATH . '/wp-admin/includes/plugin.php';
222
		}
223
224
		$data['integrations']     = self::get_related_plugins_and_extensions();
225
		$data['active_plugins']   = get_option( 'active_plugins', array() );
226
		$data['inactive_plugins'] = array();
227
		$data['locale']           = get_locale();
228
229
		// Validate request on the GV server
230
		$data['hash']             = 'gv_version.url.locale:' . sha1( $data['gv_version'] . $data['url'] . $data['locale'] );
231
232
		return $data;
233
	}
234
235
	/**
236
	 * Get active GravityView Extensions and Gravity Forms Add-ons to help debug issues.
237
	 *
238
	 * @since 1.15
239
	 * @return string List of active extensions related to GravityView or Gravity Forms, separated by HTML line breaks
240
	 */
241
	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...
242
243
		if ( ! function_exists( 'wp_get_active_and_valid_plugins' ) ) {
244
			return 'Running < WP 3.0';
245
		}
246
247
		$extensions = get_site_transient( self::related_plugins_key );
248
249
		if ( empty( $extensions ) ) {
250
251
			$active_plugins = wp_get_active_and_valid_plugins();
252
			$extensions = array();
253
			foreach ( $active_plugins as $active_plugin ) {
254
255
				// Match gravityview, gravity-forms, gravityforms, gravitate
256
				if ( ! preg_match( '/(gravityview|gravity-?forms|gravitate)/ism', $active_plugin ) ) {
257
					continue;
258
				}
259
260
				$plugin_data = get_plugin_data( $active_plugin );
261
262
				$extensions[] = sprintf( '%s %s', $plugin_data['Name'], $plugin_data['Version'] );
263
			}
264
265
			if( ! empty( $extensions ) ) {
266
				set_site_transient( self::related_plugins_key, $extensions, HOUR_IN_SECONDS );
267
			} else {
268
				return 'There was an error fetching related plugins.';
269
			}
270
		}
271
272
		return $implode ? implode( $implode, $extensions ) : $extensions;
273
	}
274
275
	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...
276
277
		$script_debug = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min';
278
279
		wp_enqueue_script( 'gv-admin-edd-license', GRAVITYVIEW_URL . 'assets/js/admin-edd-license' . $script_debug . '.js', array( 'jquery' ) );
280
281
		$status = trim( $this->Addon->get_app_setting( 'license_key_status' ) );
282
		$key = trim( $this->Addon->get_app_setting( 'license_key' ) );
283
284
		if( !empty( $key ) ) {
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
285
			$response = $this->Addon->get_app_setting( 'license_key_response' );
286
			$response = is_array( $response ) ? (object) $response : json_decode( $response );
287
		} else {
288
			$response = array();
289
		}
290
291
		wp_localize_script( 'gv-admin-edd-license', 'GVGlobals', array(
292
			'license_box' => $this->get_license_message( $response )
293
		));
294
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
295
296
		$fields = array(
297
			array(
298
				'name'  => 'edd-activate',
299
				'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...
300
				'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...
301
				'data-edd_action' => 'activate_license',
302
				'class' => 'button-primary',
303
			),
304
			array(
305
				'name'  => 'edd-deactivate',
306
				'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...
307
				'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...
308
				'data-edd_action' => 'deactivate_license',
309
				'class' => ( empty( $status ) ? 'button-primary hide' : 'button-primary' ),
310
			),
311
			array(
312
				'name'  => 'edd-check',
313
				'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...
314
				'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...
315
				'title' => 'Check the license before saving it',
316
				'data-edd_action' => 'check_license',
317
				'class' => 'button-secondary',
318
			),
319
		);
320
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
321
322
		$class = 'button gv-edd-action';
323
324
		$class .= ( !empty( $key ) && $status !== 'valid' ) ? '' : ' hide';
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
325
326
		$disabled_attribute = GVCommon::has_cap( 'gravityview_edit_settings' ) ? false : 'disabled';
327
328
		$submit = '<div class="gv-edd-button-wrapper">';
329
		foreach ( $fields as $field ) {
330
			$field['type'] = 'button';
331
			$field['class'] = isset( $field['class'] ) ? $field['class'] . ' '. $class : $class;
332
			$field['style'] = 'margin-left: 10px;';
333
			if( $disabled_attribute ) {
334
				$field['disabled'] = $disabled_attribute;
335
			}
336
			$submit .= $this->Addon->settings_submit( $field, $echo );
337
		}
338
		$submit .= '</div>';
339
340
		return $submit;
341
	}
342
343
	/**
344
	 * Include the EDD plugin updater class, if not exists
345
	 * @since 1.7.4
346
	 * @return void
347
	 */
348
	private function setup_edd() {
349
350
		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...
351
			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...
352
		}
353
354
		// setup the updater
355
		$this->EDD_SL_Plugin_Updater = new EDD_SL_Plugin_Updater(
356
			self::url,
357
			GRAVITYVIEW_FILE,
358
			$this->_get_edd_settings()
359
		);
360
361
	}
362
363
	/**
364
	 * Generate the array of settings passed to the EDD license call
365
	 *
366
	 * @since 1.7.4
367
	 *
368
	 * @param string $action The action to send to edd, such as `check_license`
369
	 * @param string $license The license key to have passed to EDD
370
	 *
371
	 * @return array
372
	 */
373
	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...
374
375
		// retrieve our license key from the DB
376
		$license_key = empty( $license ) ? trim( $this->Addon->get_app_setting( 'license_key' ) ) : $license;
377
378
		$settings = array(
379
			'version'   => self::version,
380
			'license'   => $license_key,
381
			'item_name' => self::name,
382
			'item_id'   => self::item_id,
383
			'author'    => self::author,
384
			'language'  => get_locale(),
385
			'url'       => home_url(),
386
		);
387
388
		if( !empty( $action ) ) {
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
389
			$settings['edd_action'] = esc_attr( $action );
390
		}
391
392
		$settings = array_map( 'urlencode', $settings );
393
394
		return $settings;
395
	}
396
397
	/**
398
	 * Perform the call
399
	 * @return array|WP_Error
400
	 */
401
	private function _license_get_remote_response( $data, $license = '' ) {
402
403
		$api_params = $this->_get_edd_settings( $data['edd_action'], $license );
404
405
		$url = add_query_arg( $api_params, self::url );
406
407
		$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...
408
			'timeout'   => 15,
409
			'sslverify' => false,
410
		));
411
412
		if ( is_wp_error( $response ) ) {
413
			return array();
414
		}
415
416
		$license_data = json_decode( wp_remote_retrieve_body( $response ) );
417
418
		// Not JSON
419
		if ( empty( $license_data ) ) {
420
421
			delete_transient( self::status_transient_key );
422
423
			// Change status
424
			return array();
425
		}
426
427
		// Store the license key inside the data array
428
		$license_data->license_key = $license;
429
430
		return $license_data;
431
	}
432
433
	/**
434
	 * Generate the status message displayed in the license field
435
	 *
436
	 * @since 1.7.4
437
	 * @param $license_data
438
	 *
439
	 * @return string
440
	 */
441
	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...
442
443
		if( empty( $license_data ) ) {
444
			$message = '';
445
		} else {
446
447
			if( ! empty( $license_data->error ) ) {
448
				$class = 'error';
449
				$string_key = $license_data->error;
450
			} else {
451
				$class = $license_data->license;
452
				$string_key = $license_data->license;
453
			}
454
455
			$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...
456
457
			$message = $this->generate_license_box( $message, $class );
458
		}
459
460
		return $message;
461
	}
462
463
	/**
464
	 * Generate the status message box HTML based on the current status
465
	 *
466
	 * @since 1.7.4
467
	 * @param $message
468
	 * @param string $class
469
	 *
470
	 * @return string
471
	 */
472
	private function generate_license_box( $message, $class = '' ) {
473
474
		$template = '<div id="gv-edd-status" aria-live="polite" aria-busy="false" class="gv-edd-message inline %s">%s</div>';
475
476
		$output = sprintf( $template, esc_attr( $class ), $message );
477
478
		return $output;
479
	}
480
481
	/**
482
	 * Allow pure HTML in settings fields
483
	 *
484
	 * @since 1.17
485
	 *
486
	 * @param array $response License response
487
	 *
488
	 * @return string `html` key of the $field
489
	 */
490
	public function license_details( $response = array() ) {
491
492
		$response = (array) $response;
493
494
		$return = '';
495
		$wrapper = '<span class="gv-license-details" aria-live="polite" aria-busy="false">%s</span>';
496
497
		if( ! empty( $response['license_key'] ) ) {
498
499
			$return .= '<h3>' . esc_html__( 'License Details:', 'gravityview' ) . '</h3>';
500
501
			if ( in_array( rgar( $response, 'license' ), array( 'invalid', 'deactivated' ) ) ) {
502
				$return .= $this->strings( $response['license'], $response );
503
			} elseif ( ! empty( $response['license_name'] ) ) {
504
505
				$response_keys = array(
506
					'license_name'   => '',
507
					'license_limit'  => '',
508
					'customer_name'  => '',
509
					'customer_email' => '',
510
					'site_count'     => '',
511
					'expires'        => '',
512
					'upgrades'       => ''
0 ignored issues
show
introduced by
Each line in an array declaration must end in a comma
Loading history...
513
				);
514
515
				// Make sure all the keys are set
516
				$response = wp_parse_args( $response, $response_keys );
517
518
				$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' ) );
519
				$local_text = ( ! empty( $response['is_local'] ) ? '<span class="howto">' . __( 'This development site does not count toward license activation limits', 'gravityview' ) . '</span>' : '' );
520
				$details    = array(
521
					'license'     => sprintf( esc_html__( 'License level: %s', 'gravityview' ), esc_html( $response['license_name'] ), esc_html( $response['license_limit'] ) ),
522
					'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,
523
					'activations' => sprintf( esc_html__( 'Activations: %d of %s sites', 'gravityview' ), intval( $response['site_count'] ), esc_html( $response['license_limit'] ) ) . $local_text,
524
					'expires'     => 'lifetime' === $response['expires'] ? '' : sprintf( esc_html__( 'Renew on: %s', 'gravityview' ), date_i18n( get_option( 'date_format' ), strtotime( $response['expires'] ) - DAY_IN_SECONDS ) ),
525
					'upgrade'     => $this->get_upgrade_html( $response['upgrades'] ),
526
				);
527
528
				if ( ! empty( $response['error'] ) && 'expired' === $response['error'] ) {
529
					unset( $details['upgrade'] );
530
					$details['expires'] = '<div class="error inline"><p>' . $this->strings( 'expired', $response ) . '</p></div>';
531
				}
532
533
				$return .= '<ul><li>' . implode( '</li><li>', array_filter( $details ) ) . '</li></ul>';
534
			}
535
		}
536
537
		return sprintf( $wrapper, $return );
538
	}
539
540
	/**
541
	 * Display possible upgrades for a license
542
	 *
543
	 * @since 1.17
544
	 *
545
	 * @param array $upgrades Array of upgrade paths, returned from the GV website
546
	 *
547
	 * @return string HTML list of upgrades available for the current license
548
	 */
549
	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...
550
551
		$output = '';
552
553
		if( ! empty( $upgrades ) ) {
554
555
			$locale_parts = explode( '_', get_locale() );
556
557
			$is_english = ( 'en' === $locale_parts[0] );
558
559
			$output .= '<h4>' . esc_html__( 'Upgrades available:', 'gravityview' ) . '</h4>';
560
561
			$output .= '<ul class="ul-disc">';
562
563
			foreach ( $upgrades as $upgrade_id => $upgrade ) {
564
565
				$upgrade = (object) $upgrade;
566
567
				$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 ) );
568
569
				if( $is_english && isset( $upgrade->description ) ) {
570
					$message = esc_html( $upgrade->description );
571
				} else {
572
					switch( $upgrade->price_id ) {
573
						// Interstellar
574
						case 1:
575
						default:
576
							$message = esc_html__( 'Get access to Extensions', 'gravityview' );
577
							break;
578
						// Galactic
579
						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...
580
							$message = esc_html__( 'Get access to Entry Importer and other Premium plugins', 'gravityview' );
581
							break;
582
					}
583
				}
584
585
				$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 );
586
			}
587
			$output .= '</ul>';
588
		}
589
590
		return $output;
591
	}
592
593
	/**
594
	 * Perform the call to EDD based on the AJAX call or passed data
595
	 *
596
	 * @since 1.7.4
597
	 *
598
	 * @param array $array {
599
	 * @type string $license The license key
600
	 * @type string $edd_action The EDD action to perform, like `check_license`
601
	 * @type string $field_id The ID of the field to check
602
	 * @type boolean $update Whether to update plugin settings. Prevent updating the data by setting an `update` key to false
603
	 * @type string $format If `object`, return the object of the license data. Else, return the JSON-encoded object
604
	 * }
605
	 *
606
	 * @return mixed|string|void
607
	 */
608
	public function license_call( $array = array() ) {
609
610
		$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...
611
		$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...
612
		$has_cap = GVCommon::has_cap( 'gravityview_edit_settings' );
613
614
		if ( $is_ajax && empty( $data['license'] ) ) {
615
			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...
616
		}
617
618
		// If the user isn't allowed to edit settings, show an error message
619
		if( ! $has_cap && empty( $data['all_caps'] ) ) {
620
			$license_data = new stdClass();
621
			$license_data->error = 'capability';
622
			$license_data->message = $this->get_license_message( $license_data );
623
			$json = json_encode( $license_data );
624
		} else {
625
626
			$license      = esc_attr( rgget( 'license', $data ) );
627
			$license_data = $this->_license_get_remote_response( $data, $license );
628
629
			// Empty is returned when there's an error.
630
			if ( empty( $license_data ) ) {
631
				if ( $is_ajax ) {
632
					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...
633
				} else { // Non-ajax call
634
					return json_encode( array() );
635
				}
636
			}
637
638
			$license_data->details = $this->license_details( $license_data );
639
			$license_data->message = $this->get_license_message( $license_data );
640
641
			$json = json_encode( $license_data );
642
643
			$update_license = ( ! isset( $data['update'] ) || ! empty( $data['update'] ) );
644
645
			$is_check_action_button = ( 'check_license' === $data['edd_action'] && defined( 'DOING_AJAX' ) && DOING_AJAX );
646
647
			// Failed is the response from trying to de-activate a license and it didn't work.
648
			// This likely happened because people entered in a different key and clicked "Deactivate",
649
			// meaning to deactivate the original key. We don't want to save this response, since it is
650
			// most likely a mistake.
651
			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...
652
653
				if ( ! empty( $data['field_id'] ) ) {
654
					set_transient( self::status_transient_key, $license_data, DAY_IN_SECONDS );
655
				}
656
657
				$this->license_call_update_settings( $license_data, $data );
658
			}
659
		} // End $has_cap
660
661
		if ( $is_ajax ) {
662
			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...
663
		} else { // Non-ajax call
664
			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...
665
		}
666
	}
667
668
	/**
669
	 * Update the license after fetching it
670
	 * @param object $license_data
671
	 * @return void
672
	 */
673
	private function license_call_update_settings( $license_data, $data ) {
674
675
		// Update option with passed data license
676
		$settings = $this->Addon->get_app_settings();
677
678
        $settings['license_key'] = $license_data->license_key = trim( $data['license'] );
679
		$settings['license_key_status'] = $license_data->license;
680
		$settings['license_key_response'] = (array)$license_data;
0 ignored issues
show
introduced by
No space after closing casting parenthesis is prohibited
Loading history...
681
682
		$this->Addon->update_app_settings( $settings );
683
	}
684
685
	/**
686
	 * URL to direct license renewal, or if license key is not set, then just the account page
687
	 * @since 1.13.1
688
	 * @param  object|null $license_data Object with license data
689
	 * @return string Renewal or account URL
690
	 */
691
	private function get_license_renewal_url( $license_data ) {
692
		$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...
693
		$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...
694
		return $renew_license_url;
695
	}
696
697
	/**
698
	 * Override the text used in the GravityView EDD license Javascript
699
	 *
700
	 * @param  array|null $status Status to get. If empty, get all strings.
701
	 * @param  object|null $license_data Object with license data
702
	 * @return array          Modified array of content
703
	 */
704
	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...
705
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
706
707
		$strings = array(
708
			'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...
709
			'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...
710
			'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...
711
			'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...
712
			'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...
713
			'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...
714
			'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...
715
			'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...
716
			'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...
717
			'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...
718
			'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...
719
			'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...
720
			'capability' => esc_html__( 'You don\'t have the ability to edit plugin settings.', 'gravityview' ),
721
722
			'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...
723
			'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...
724
			'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...
725
			'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...
726
		);
727
728
		if( empty( $status ) ) {
729
			return $strings;
730
		}
731
732
		if( isset( $strings[ $status ] ) ) {
733
			return $strings[ $status ];
734
		}
735
736
		return NULL;
0 ignored issues
show
Coding Style introduced by
TRUE, FALSE and NULL must be lowercase; expected null, but found NULL.
Loading history...
737
	}
738
739
}