Completed
Push — master ( 1e5684...c05137 )
by Zack
27:45 queued 24:32
created

get_related_plugins_and_extensions()   C

Complexity

Conditions 7
Paths 6

Size

Total Lines 33
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

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