GravityView  2.10.1
The best, easiest way to display Gravity Forms entries on your website.
future/includes/class-gv-license-handler.php
Go to the documentation of this file.
1 <?php
2 namespace GV;
3 
5 
6 /** If this file is called directly, abort. */
7 if ( ! defined( 'GRAVITYVIEW_DIR' ) ) {
8  die();
9 }
10 
11 /**
12  * The \GV\License_Handler class.
13  *
14  * Handles everything licensing. Ka-ching!
15  */
17  /**
18  * @var \GV\Addon_Settings The global addon settings binding.
19  */
20  private $settings;
21 
22  const name = 'GravityView';
23  const author = 'Katz Web Services, Inc.';
24  const url = 'https://gravityview.co';
25 
26  /**
27  * Post ID on gravityview.co
28  * @since 1.15
29  */
30  const item_id = 17;
31 
32  /**
33  * Name of the transient used to store license status for GV
34  * @since 1.17
35  */
36  const status_transient_key = 'gravityview_edd-activate_valid';
37 
38  /**
39  * @var string Key used to store active GravityView/Gravity Forms plugin data
40  * @since 1.15
41  */
42  const related_plugins_key = 'gravityview_related_plugins';
43 
44  /** @var \GV\EDD_SL_Plugin_Updater */
46 
47  /**
48  * @var \GV\License_Handler
49  */
50  private static $__instance;
51 
52  private function __construct( $settings ) {
53 
54  $this->settings = $settings;
55 
56  if ( ! $this->settings instanceof Addon_Settings ) {
57  $this->settings = gravityview()->plugin->settings;
58  }
59 
60  add_action( 'admin_init', array( $this, 'setup_edd' ), 0 );
61  add_action( 'wp_ajax_gravityview_license', array( $this, 'license_call' ) );
62  add_action( 'admin_init', array( $this, 'refresh_license_status' ) );
63  add_action( 'admin_init', array( $this, 'check_license' ) );
64  add_action( 'update_option_active_plugins', array( $this, 'flush_related_plugins_transient' ) );
65  add_action( 'update_option_active_sitewide_plugins', array( $this, 'flush_related_plugins_transient' ) );
66  }
67 
68  /**
69  * @return \GV\License_Handler The global instance.
70  */
71  public static function get( $settings = null ) {
72  if ( ! self::$__instance ) {
73  self::$__instance = new self( $settings );
74  }
75  return self::$__instance;
76  }
77 
78  /**
79  * Generate the array of settings passed to the EDD license call
80  *
81  * @since 1.7.4
82  *
83  * @param string $action The action to send to edd, such as `check_license`
84  * @param string $license The license key to have passed to EDD
85  *
86  * @return array
87  */
88  private function _get_edd_settings( $action = '', $license = '' ) {
89 
90  // retrieve our license key from the DB
91  $license_key = empty( $license ) ? trim( $this->settings->get( 'license_key' ) ) : $license;
92 
93  $settings = array(
94  'version' => Plugin::$version,
95  'license' => $license_key,
96  'item_name' => self::name,
97  'item_id' => self::item_id,
98  'author' => self::author,
99  'language' => get_locale(),
100  'url' => home_url(),
101  'beta' => $this->settings->get( 'beta' ),
102  );
103 
104  if ( ! empty( $action ) ) {
105  $settings['edd_action'] = esc_attr( $action );
106  }
107 
108  return array_map( 'urlencode', $settings );
109  }
110 
111  /**
112  * Include the EDD plugin updater class, if not exists
113  *
114  * @since 1.7.4
115  * @since 1.21.5.3 Changed visibility of method to public
116  *
117  * @return void
118  */
119  public function setup_edd() {
120  if ( ! class_exists( '\GV\EDD_SL_Plugin_Updater' ) ) {
121  require_once gravityview()->plugin->dir( 'future/lib/EDD_SL_Plugin_Updater.php' );
122  }
123 
124  // setup the updater
126  self::url,
128  $this->_get_edd_settings()
129  );
130  }
131 
132  /**
133  * Perform the call to EDD based on the AJAX call or passed data
134  *
135  * @since 1.7.4
136  *
137  * @param array $array {
138  * @type string $license The license key
139  * @type string $edd_action The EDD action to perform, like `check_license`
140  * @type string $field_id The ID of the field to check
141  * @type boolean $update Whether to update plugin settings. Prevent updating the data by setting an `update` key to false
142  * @type string $format If `object`, return the object of the license data. Else, return the JSON-encoded object
143  * }
144  * @param boolean $cap_check Require `gravityview_edit_settings` capability from current user.
145  *
146  * @return mixed|string|void
147  */
148  public function license_call( $array = array(), $cap_check = true ) {
149 
150  $is_ajax = ( defined( 'DOING_AJAX' ) && DOING_AJAX );
151  $data = empty( $array ) ? Utils::_POST( 'data', array() ) : $array;
152 
153  $data = wp_parse_args( $data, array(
154  'license' => '',
155  'edd_action' => '',
156  'field_id' => '',
157  'update' => '',
158  'format' => 'json',
159  ) );
160 
161  if ( $is_ajax && empty( $data['license'] ) ) {
162  die( -1 );
163  }
164 
165  // If the user isn't allowed to edit settings, show an error message
166  if ( $cap_check && ! \GVCommon::has_cap( 'gravityview_edit_settings' ) ) {
167  $license_data = new \stdClass();
168  $license_data->error = 'capability';
169  $license_data->message = $this->get_license_message( $license_data );
170  $json = json_encode( $license_data );
171  } else {
172  $license = esc_attr( Utils::get( $data, 'license' ) );
173  $license_data = $this->_license_get_remote_response( $data, $license );
174 
175  // Empty is returned when there's an error.
176  if ( empty( $license_data ) ) {
177  if ( $is_ajax ) {
178  exit( json_encode( array() ) );
179  } else { // Non-ajax call
180  return json_encode( array() );
181  }
182  }
183 
184  $license_data->details = $this->license_details( $license_data );
185  $license_data->message = $this->get_license_message( $license_data );
186 
187  $json = json_encode( $license_data );
188 
189  $update_license = Utils::get( $data, 'update' ) || 'gravityview_license' === Utils::_POST('action');
190 
191  $is_check_action_button = ( 'check_license' === Utils::get( $data, 'edd_action' ) && defined( 'DOING_AJAX' ) && DOING_AJAX );
192 
193  do_action('gravityview/admin_installer/delete_downloads_data', true );
194 
195  if ( $is_check_action_button ) {
196  delete_transient( self::status_transient_key );
197 
198  // Failed is the response from trying to de-activate a license and it didn't work.
199  // This likely happened because people entered in a different key and clicked "Deactivate",
200  // meaning to deactivate the original key. We don't want to save this response, since it is
201  // most likely a mistake.
202  } else if ( $license_data->license !== 'failed' && $update_license ) {
203 
204  if ( ! empty( $data['field_id'] ) ) {
205  set_transient( self::status_transient_key, $license_data, DAY_IN_SECONDS );
206  }
207 
208  $this->license_call_update_settings( $license_data, $data );
209  }
210  }
211 
212  if ( $is_ajax ) {
213  exit( $json );
214  } else { // Non-ajax call
215  return ( Utils::_GET( 'format', Utils::get( $data, 'format' ) ) === 'object' ) ? $license_data : $json;
216  }
217  }
218 
219  /**
220  * Generate the status message displayed in the license field
221  *
222  * @since 1.7.4
223  * @param $license_data
224  *
225  * @return string
226  */
227  private function get_license_message( $license_data ) {
228  if ( empty( $license_data ) ) {
229  $class = 'hide';
230  $message = '';
231  } else {
232  if( ! empty( $license_data->error ) ) {
233  $class = 'error';
234  $string_key = $license_data->error;
235  } else { $class = $license_data->license;
236  $string_key = $license_data->license;
237  }
238 
239  $message = sprintf( '<p><strong>%s: %s</strong></p>', $this->strings( 'status' ), $this->strings( $string_key, $license_data ) );
240  }
241 
242  return $this->generate_license_box( $message, $class );
243  }
244 
245  /**
246  * Allow pure HTML in settings fields
247  *
248  * @since 1.17
249  *
250  * @param array $response License response
251  *
252  * @return string `html` key of the $field
253  */
254  public function license_details( $response = array() ) {
255 
256  $response = (array) $response;
257 
258  $return = '';
259  $wrapper = '<span class="gv-license-details" aria-live="polite" aria-busy="false">%s</span>';
260 
261  if ( ! empty( $response['license_key'] ) ) {
262  $return .= '<h3>' . rtrim( esc_html__( 'License Details:', 'gravityview' ), ':' ) . '</h3>';
263 
264  if ( in_array( Utils::get( $response, 'license' ), array( 'invalid', 'deactivated' ) ) ) {
265  if ( gravityview()->plugin->is_GF_25() ) {
266  return sprintf( $wrapper, '' ); // Do not show redundant information - invalid/deactivated notice will be displayed by generate_license_box()
267  }
268 
269 
270  $return .= $this->strings( $response['license'], $response );
271  } elseif ( ! empty( $response['license_name'] ) ) {
272  $response_keys = array(
273  'license_name' => '',
274  'license_limit' => '',
275  'customer_name' => '',
276  'customer_email' => '',
277  'site_count' => '',
278  'expires' => '',
279  'upgrades' => ''
280  );
281 
282  // Make sure all the keys are set
283  $response = wp_parse_args( $response, $response_keys );
284 
285  $login_link_class = gravityview()->plugin->is_GF_25() ? 'button button-outline outline' : 'text-link';
286  $renews_on = ( 'lifetime' === $response['expires'] ) ? '' : sprintf( esc_html__( 'Renew on: %s', 'gravityview' ), date_i18n( get_option( 'date_format' ), strtotime( $response['expires'] ) - DAY_IN_SECONDS ) );
287  $login_link = sprintf( '<a href="%s" class="gv-access-account ' . $login_link_class . '" rel="external">%s</a>', esc_url( sprintf( 'https://gravityview.co/wp-login.php?username=%s', $response['customer_email'] ) ), esc_html__( 'Access your GravityView account', 'gravityview' ) );
288  $local_text = ( ! empty( $response['is_local'] ) ? '<span class="howto">' . __( 'This development site does not count toward license activation limits', 'gravityview' ) . '</span>' : '' );
289  $license_limit = empty( $response['license_limit'] ) ? __( 'Unlimited', 'gravityview' ) : (int) $response['license_limit'];
290 
291 
292  $details = array(
293  'license' => sprintf( esc_html__( 'License level: %s', 'gravityview' ), '<span class="gv-license-detail">' . esc_html( $response['license_name'] ) . '</span>' ),
294  'licensed_to' => sprintf( esc_html_x( 'Licensed to: %1$s (%2$s)', '1: Customer name; 2: Customer email', 'gravityview' ), '<span class="gv-license-detail">' . esc_html__( $response['customer_name'], 'gravityview' ), esc_html__( $response['customer_email'], 'gravityview' ) ) . '</span>' . $renews_on . $login_link,
295  'activations' => sprintf( str_replace( '%d', '%s', esc_html__( 'Activations: %d of %s sites', 'gravityview' ) ), '<span class="gv-license-detail">' . intval( $response['site_count'] ), esc_html( $license_limit ) ) . '</span>' . $local_text,
296  'upgrade' => $this->get_upgrade_html( $response['upgrades'] ),
297  );
298 
299  if ( ! empty( $response['error'] ) && 'expired' === $response['error'] ) {
300  unset( $details['upgrade'] );
301  $details['licensed_to'] .= '<div class="error inline"><p>' . $this->strings( 'expired', $response ) . '</p></div>';
302  }
303 
304  $return .= '<ul>';
305 
306  foreach ( $details as $key => $detail ) {
307  $return .= sprintf( '<li class="%s">%s</li>', 'license-detail--' . esc_attr( $key ), $detail );
308  }
309 
310  $return .= '</ul>';
311  }
312  }
313 
314  return sprintf( $wrapper, $return );
315  }
316 
317  /**
318  * Display possible upgrades for a license
319  *
320  * @since 1.17
321  *
322  * @param array $upgrades Array of upgrade paths, returned from the GV website
323  *
324  * @return string HTML list of upgrades available for the current license
325  */
326  private function get_upgrade_html( $upgrades ) {
327 
328  $output = '';
329 
330  if ( ! empty( $upgrades ) ) {
331 
332  $locale_parts = explode( '_', get_locale() );
333  $is_english = ( 'en' === $locale_parts[0] );
334 
335  $output .= '<h4>' . esc_html__( 'Upgrades available:', 'gravityview' ) . '</h4>';
336  $output .= '<ul>';
337 
338  foreach ( $upgrades as $upgrade_id => $upgrade ) {
339  $upgrade = (object) $upgrade;
340 
341  $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 ) );
342 
343  if ( $is_english && isset( $upgrade->description ) ) {
344  $message = esc_html( $upgrade->description );
345  } else {
346  switch( $upgrade->price_id ) {
347  // Interstellar
348  case 1:
349  default:
350  $message = esc_html__( 'Get access to Extensions', 'gravityview' );
351  break;
352  // Galactic
353  case 2:
354  $message = esc_html__( 'Get access to Entry Importer and other Premium plugins', 'gravityview' );
355  break;
356  }
357  }
358 
359  $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 );
360  }
361  $output .= '</ul>';
362  }
363 
364  return $output;
365  }
366 
367  /**
368  * Generate the status message box HTML based on the current status
369  *
370  * @since 1.7.4
371  * @param string $message
372  * @param string $class
373  *
374  * @return string
375  */
376  private function generate_license_box( $message, $class = '' ) {
377 
378  $message = ! empty( $message ) ? $message : '<p><strong></strong></p>';
379 
380  if ( gravityview()->plugin->is_GF_25() ) {
381  switch ( $class ) {
382  case 'valid':
383  $class .= ' success';
384  break;
385  case 'invalid':
386  $class .= ' error';
387  break;
388  default:
389  $class .= ' warning';
390  }
391 
392  $template = '<div id="gv-edd-status" aria-live="polite" aria-busy="false" class="alert %s">%s</div>';
393  } else {
394  $template = '<div id="gv-edd-status" aria-live="polite" aria-busy="false" class="gv-edd-message inline %s">%s</div>';
395  }
396 
397  $output = sprintf( $template, esc_attr( $class ), $message );
398 
399  return $output;
400  }
401 
402  /**
403  * Override the text used in the GravityView EDD license Javascript
404  *
405  * @param string $status Status to get. If empty, get all strings.
406  * @param object|array|null $license_data Object with license data, used to generate link to license renewal URL
407  * @return string Modified array of content
408  */
409  public function strings( $status = NULL, $license_data = null ) {
410 
411  $strings = array(
412  'status' => esc_html__( 'Status', 'gravityview' ),
413  'error' => esc_html__( 'There was an error processing the request.', 'gravityview' ),
414  'failed' => esc_html__( 'Could not deactivate the license. The license key you attempted to deactivate may not be active or valid.', 'gravityview' ),
415  'site_inactive' => esc_html__( 'The license key is valid, but it has not been activated for this site.', 'gravityview' ),
416  'inactive' => esc_html__( 'The license key is valid, but it has not been activated for this site.', 'gravityview' ),
417  '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>' ),
418  'deactivated' => esc_html__( 'The license has been deactivated.', 'gravityview' ),
419  'valid' => esc_html__( 'The license key is valid and active.', 'gravityview' ),
420  'disabled' => sprintf( esc_html__( 'This license key is disabled. For updates and support, %spurchase a new license%s.', 'gravityview' ), '<a href="https://gravityview.co/account/">', '</a>' ),
421  'invalid' => esc_html__( 'The license key entered is invalid.', 'gravityview' ),
422  'invalid_item_id' => esc_html__( 'This license key does not have access to this plugin.', 'gravityview' ),
423  'missing' => esc_html__( 'The license key entered is invalid.', 'gravityview' ), // Missing is "the license couldn't be found", not "you submitted an empty license"
424  'revoked' => esc_html__( 'This license key has been revoked.', 'gravityview' ),
425  '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>' ),
426  'capability' => esc_html__( 'You don\'t have the ability to edit plugin settings.', 'gravityview' ),
427  'verifying_license' => esc_html__( 'Verifying license&hellip;', 'gravityview' ),
428  'activate_license' => esc_html__( 'Activate License', 'gravityview' ),
429  'deactivate_license' => esc_html__( 'Deactivate License', 'gravityview' ),
430  'check_license' => esc_html__( 'Verify License', 'gravityview' ),
431  );
432 
433  /**
434  * @internal Do not rely on this filter.
435  * @since 2.1
436  */
437  $strings = apply_filters( 'gravityview/admin/license/strings', $strings );
438 
439  return Utils::get( $strings, $status, null );
440  }
441 
442  /**
443  * URL to direct license renewal, or if license key is not set, then just the account page
444  * @since 1.13.1
445  * @param object|null $license_data Object with license data
446  * @return string Renewal or account URL
447  */
448  private function get_license_renewal_url( $license_data ) {
449  $license_data = is_array( $license_data ) ? (object)$license_data : $license_data;
450 
451  if ( ! empty( $license_data->renewal_url ) ) {
452  $renew_license_url = $license_data->renewal_url;
453  } elseif( ! empty( $license_data->license_key ) ) {
454  $renew_license_url = sprintf( 'https://gravityview.co/checkout/?download_id=17&edd_license_key=%s', $license_data->license_key );
455  } else {
456  $renew_license_url = 'https://gravityview.co/account/';
457  }
458 
459  $renew_license_url = add_query_arg( wp_parse_args( 'utm_source=admin_notice&utm_medium=admin&utm_content=expired&utm_campaign=Activation&force_login=1' ), $renew_license_url );
460 
461  return $renew_license_url;
462  }
463 
464  /**
465  * Perform the call
466  *
467  * @return array|\WP_Error
468  */
469  private function _license_get_remote_response( $data, $license = '' ) {
470  $api_params = $this->_get_edd_settings( $data['edd_action'], $license );
471 
472  $url = add_query_arg( $api_params, self::url );
473 
474  $response = wp_remote_get( $url, array(
475  'timeout' => 15,
476  'sslverify' => false,
477  ) );
478 
479  if ( is_wp_error( $response ) ) {
480  gravityview()->log->error( 'WP_Error response from license check. API params:', array( 'data' => $api_params ) );
481  return array();
482  }
483 
484  $license_data = json_decode( wp_remote_retrieve_body( $response ) );
485 
486  // Not JSON
487  if ( empty( $license_data ) ) {
488  gravityview()->log->error( 'Empty license data response from license check', array( 'data' => compact( 'response', 'url', 'api_params', 'data' ) ) );
489 
490  delete_transient( self::status_transient_key );
491 
492  // Change status
493  return array();
494  }
495 
496  // Store the license key inside the data array
497  $license_data->license_key = $license;
498 
499  return $license_data;
500  }
501 
502  /**
503  * Update the license after fetching it
504  * @param object $license_data
505  * @return void
506  */
507  private function license_call_update_settings( $license_data, $data ) {
508  $settings = array();
509 
510  $settings['license_key'] = $license_data->license_key = trim( $data['license'] );
511  $settings['license_key_status'] = $license_data->license;
512  $settings['license_key_response'] = (array)$license_data;
513 
514  $this->settings->set( $settings );
515  }
516 
517  public function settings_edd_license_activation( $field, $echo ) {
518 
519  $script_debug = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min';
520 
521  wp_enqueue_script( 'gv-admin-edd-license', GRAVITYVIEW_URL . 'assets/js/admin-edd-license' . $script_debug . '.js', array( 'jquery' ) );
522 
523  // GF 2.5 compatibility
524  if ( gravityview()->plugin->is_GF_25() ) {
525  wp_register_style( 'gv-admin-edd-license', false );
526  wp_enqueue_style( 'gv-admin-edd-license' );
527  }
528 
529  $status = trim( $this->settings->get( 'license_key_status' ) );
530  $key = trim( $this->settings->get( 'license_key' ) );
531 
532  if ( !empty( $key ) ) {
533  $response = $this->settings->get( 'license_key_response' );
534  $response = is_array( $response ) ? (object) $response : json_decode( $response );
535  } else {
536  $response = array();
537  }
538 
539  wp_localize_script( 'gv-admin-edd-license', 'GVGlobals', array(
540  'license_box' => $this->get_license_message( $response )
541  ) );
542 
543 
544  $fields = array(
545  array(
546  'name' => 'edd-activate',
547  'value' => __( 'Activate License', 'gravityview' ),
548  'data-pending_text' => __( 'Verifying license&hellip;', 'gravityview' ),
549  'data-edd_action' => 'activate_license',
550  'class' => 'button-primary primary',
551  ),
552  array(
553  'name' => 'edd-deactivate',
554  'value' => __( 'Deactivate License', 'gravityview' ),
555  'data-pending_text' => __( 'Deactivating license&hellip;', 'gravityview' ),
556  'data-edd_action' => 'deactivate_license',
557  'class' => ( empty( $status ) ? 'button-primary primary hide' : 'button-primary primary' ),
558  ),
559  array(
560  'name' => 'edd-check',
561  'value' => __( 'Check License', 'gravityview' ),
562  'data-pending_text' => __( 'Verifying license&hellip;', 'gravityview' ),
563  'title' => 'Check the license before saving it',
564  'data-edd_action' => 'check_license',
565  'class' => 'button-secondary',
566  ),
567  );
568 
569  $class = 'button gv-edd-action';
570 
571  $class .= ( ! empty( $key ) && $status !== 'valid' ) ? '' : ' hide';
572 
573  $disabled_attribute = \GVCommon::has_cap( 'gravityview_edit_settings' ) ? false : 'disabled';
574 
575  $submit = '<div class="gv-edd-button-wrapper">';
576  foreach ( $fields as $field ) {
577  $field['type'] = 'button';
578  $field['class'] = isset( $field['class'] ) ? $field['class'] . ' '. $class : $class;
579  $field['style'] = 'margin-left: 10px;';
580  if( $disabled_attribute ) {
581  $field['disabled'] = $disabled_attribute;
582  }
583  $submit .= $this->settings->as_html( $field, $echo );
584  }
585  $submit .= '</div>';
586 
587  return $submit;
588  }
589 
590  /**
591  * When the status transient expires (or is deleted on activation), re-check the status
592  *
593  * @since 1.17
594  *
595  * @return void
596  */
597  public function refresh_license_status() {
598  if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
599  return;
600  }
601 
602  // The transient is fresh; don't fetch.
603  if ( $status = get_transient( self::status_transient_key ) ) {
604  return;
605  }
606 
607  $data = array(
608  'edd_action' => 'check_license',
609  'license' => trim( $this->settings->get( 'license_key' ) ),
610  'update' => true,
611  'format' => 'object',
612  'field_id' => 'refresh_license_status', // Required to set the `status_transient_key` transient
613  );
614 
615  $license_call = $this->license_call( $data, false );
616 
617  gravityview()->log->debug( 'Refreshed the license.', array( 'data' => $license_call ) );
618  }
619 
620  /**
621  * Check the GravityView license information
622  *
623  * @since 1.19.3
624  * @param bool $force Whether to force checking license, even if AJAX
625  *
626  * @return void
627  */
628  public function check_license() {
629  if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
630  return; // Don't fire when saving settings or AJAX
631  }
632 
633  if ( ! apply_filters( 'gv_send_site_data', true ) ) {
634  return;
635  }
636 
637  // Send checkins once per week
638  $last_checked = get_option( 'gv_last_checkin', false );
639 
640  if ( is_numeric( $last_checked ) && $last_checked > strtotime( '-1 week', current_time( 'timestamp' ) ) ) {
641  return; // checked within a week
642  }
643 
644  $status = get_transient( 'gv_license_check' );
645 
646  // Run the license check a maximum of once per day, and not on GV website
647  if ( false === $status && site_url() !== self::url ) {
648 
649  // Call the custom API.
650  $response = wp_remote_post( self::url, array(
651  'timeout' => 15,
652  'sslverify' => false,
653  'body' => array(
654  'edd_action' => 'check_license',
655  'license' => trim( $this->settings->get( 'license_key' ) ),
656  'item_name' => self::name,
657  'url' => home_url(),
658  'site_data' => $this->get_site_data(),
659  ),
660  ));
661 
662  // make sure the response came back okay
663  if ( is_wp_error( $response ) ) {
664 
665  // Connection failed, try again in three hours
666  set_transient( 'gv_license_check', 1, 3 * HOUR_IN_SECONDS );
667 
668  return;
669  }
670 
671  set_transient( 'gv_license_check', 1, DAY_IN_SECONDS );
672 
673  update_option( 'gv_last_checkin', current_time( 'timestamp' ) );
674  }
675  }
676 
677  /**
678  * Retrieves site data (plugin versions, integrations, etc) to be sent along with the license check.
679  *
680  * @since 1.9
681  *
682  * @return array
683  */
684  public function get_site_data() {
685  $data = array();
686 
687  $theme_data = wp_get_theme();
688  $theme = $theme_data->Name . ' ' . $theme_data->Version;
689 
690  $data['gv_version'] = Plugin::$version;
691  $data['php_version'] = phpversion();
692  $data['wp_version'] = get_bloginfo( 'version' );
693  $data['gf_version'] = \GFForms::$version;
694  $data['server'] = Utils::get( $_SERVER, 'SERVER_SOFTWARE' );
695  $data['multisite'] = is_multisite();
696  $data['theme'] = $theme;
697  $data['url'] = home_url();
698  $data['license_key'] = $this->settings->get( 'license_key' );
699  $data['beta'] = $this->settings->get( 'beta' );
700 
701  // View Data
702  $gravityview_posts = wp_count_posts( 'gravityview', 'readable' );
703 
704  $data['view_count'] = null;
705  $data['view_first'] = null;
706  $data['view_latest'] = null;
707 
708  if ( $gravityview_posts->publish ) {
709  $data['view_count'] = $gravityview_posts->publish;
710 
711  $first = get_posts( 'numberposts=1&post_type=gravityview&post_status=publish&order=ASC' );
712  $latest = get_posts( 'numberposts=1&post_type=gravityview&post_status=publish&order=DESC' );
713 
714  if ( $first = array_shift( $first ) ) {
715  $data['view_first'] = $first->post_date;
716  }
717  if ( $latest = array_pop( $latest ) ) {
718  $data['view_latest'] = $latest->post_date;
719  }
720  }
721 
722  // Form counts
723  if ( class_exists( 'GFFormsModel' ) ) {
724  $form_data = \GFFormsModel::get_form_count();
725  $data['forms_total'] = Utils::get( $form_data, 'total', 0 );
726  $data['forms_active'] = Utils::get( $form_data, 'active', 0 );
727  $data['forms_inactive'] = Utils::get( $form_data, 'inactive', 0 );
728  $data['forms_trash'] = Utils::get( $form_data, 'inactive', 0 );
729  }
730 
731  // Retrieve current plugin information
732  if ( ! function_exists( 'get_plugins' ) ) {
733  include ABSPATH . '/wp-admin/includes/plugin.php';
734  }
735 
736  $data['integrations'] = self::get_related_plugins_and_extensions();
737  $data['active_plugins'] = get_option( 'active_plugins', array() );
738  $data['inactive_plugins'] = array();
739  $data['locale'] = get_locale();
740 
741  // Validate request on the GV server
742  $data['hash'] = 'gv_version.url.locale:' . sha1( $data['gv_version'] . $data['url'] . $data['locale'] );
743 
744  return $data;
745  }
746 
747  /**
748  * Get active GravityView Extensions and Gravity Forms Add-ons to help debug issues.
749  *
750  * @since 1.15
751  * @return string List of active extensions related to GravityView or Gravity Forms, separated by HTML line breaks
752  */
753  static public function get_related_plugins_and_extensions( $implode = '<br />' ) {
754  if ( ! function_exists( 'wp_get_active_and_valid_plugins' ) ) {
755  return 'Running < WP 3.0';
756  }
757 
758  $extensions = get_site_transient( self::related_plugins_key );
759 
760  if ( empty( $extensions ) ) {
761 
762  $active_plugins = wp_get_active_and_valid_plugins();
763  $extensions = array();
764  foreach ( $active_plugins as $active_plugin ) {
765  // Match gravityview, gravity-forms, gravityforms, gravitate
766  if ( ! preg_match( '/(gravityview|gravity-?forms|gravitate|perk|gravity|gf)/ism', $active_plugin ) ) {
767  continue;
768  }
769 
770  $plugin_data = get_plugin_data( $active_plugin );
771 
772  $extensions[] = sprintf( '%s %s', $plugin_data['Name'], $plugin_data['Version'] );
773  }
774 
775  if ( ! empty( $extensions ) ) {
776  set_site_transient( self::related_plugins_key, $extensions, HOUR_IN_SECONDS );
777  } else {
778  return 'There was an error fetching related plugins.';
779  }
780  }
781 
782  return $implode ? implode( $implode, $extensions ) : $extensions;
783  }
784 
785  /**
786  * When a plugin is activated or deactivated, delete the cached extensions/plugins used by get_related_plugins_and_extensions()
787  *
788  * @see get_related_plugins_and_extensions()
789  * @since 1.15
790  */
792  if ( function_exists( 'delete_site_transient' ) ) {
793  delete_site_transient( self::related_plugins_key );
794  }
795  }
796 }
$url
Definition: post_image.php:25
setup_edd()
Include the EDD plugin updater class, if not exists.
If this file is called directly, abort.
get_site_data()
Retrieves site data (plugin versions, integrations, etc) to be sent along with the license check...
Allows plugins to use their own update API.
refresh_license_status()
When the status transient expires (or is deleted on activation), re-check the status.
get_license_message( $license_data)
Generate the status message displayed in the license field.
license_details( $response=array())
Allow pure HTML in settings fields.
const GRAVITYVIEW_URL
The URL to this file, with trailing slash.
Definition: gravityview.php:36
get_license_renewal_url( $license_data)
URL to direct license renewal, or if license key is not set, then just the account page...
_license_get_remote_response( $data, $license='')
Perform the call.
license_call( $array=array(), $cap_check=true)
Perform the call to EDD based on the AJAX call or passed data.
flush_related_plugins_transient()
When a plugin is activated or deactivated, delete the cached extensions/plugins used by get_related_p...
if(! isset( $gravityview)||empty( $gravityview->template)) $template
The entry loop for the list output.
$class
gravityview()
Definition: _stubs.php:26
get( $key, $default=null)
Retrieve a setting.
get_upgrade_html( $upgrades)
Display possible upgrades for a license.
check_license()
Check the GravityView license information.
static get_related_plugins_and_extensions( $implode='< br/>')
Get active GravityView Extensions and Gravity Forms Add-ons to help debug issues. ...
generate_license_box( $message, $class='')
Generate the status message box HTML based on the current status.
_get_edd_settings( $action='', $license='')
Generate the array of settings passed to the EDD license call.
const GRAVITYVIEW_FILE
Full path to the GravityView file "GRAVITYVIEW_FILE" "./gravityview.php".
Definition: gravityview.php:31
if(empty( $field_settings['email_field'])) $settings
If this file is called directly, abort.
strings( $status=NULL, $license_data=null)
Override the text used in the GravityView EDD license Javascript.
static has_cap( $caps='', $object_id=null, $user_id=null)
Alias of GravityView_Roles_Capabilities::has_cap()
license_call_update_settings( $license_data, $data)
Update the license after fetching it.
$field
Definition: gquiz_grade.php:11
$strings
Definition: notes.php:29