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