PluginProbe
Content Control – The Ultimate Content Restriction Plugin! Restrict Content, Create Conditional Blocks & More / trunk
Content Control – The Ultimate Content Restriction Plugin! Restrict Content, Create Conditional Blocks & More vtrunk
trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.1.10 1.1.2 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 1.1.8 2.0.0 2.0.1 2.0.10 2.0.11 2.0.12 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 All 47 releases
content-control / classes / Plugin / License.php

License.php in Content Control – The Ultimate Content Restriction Plugin! Restrict Content, Create Conditional Blocks & More trunk, at classes/Plugin/License.php

556 lines 13.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Upgrade management.
4 *
5 * @copyright (c) 2023, Code Atlantic LLC.
6 *
7 * @package ContentControl
8 */
9
10 namespace ContentControl\Plugin;
11
12 defined( 'ABSPATH' ) || exit;
13
14 /**
15 * Temporary license provider for active Pro releases older than 1.3.0.
16 *
17 * Note for WordPress.org Plugin Review Team: Core registers this deprecated
18 * bridge only when it detects an active Content Control Pro version below
19 * 1.3.0. It preserves licensing and update access while that already-installed
20 * add-on is upgraded. Core alone and Pro 1.3.0 or later never instantiate it,
21 * and this class cannot install plugins.
22 *
23 * @see \ContentControl\Plugin\Core::is_legacy_pro_active()
24 *
25 * @package ContentControl
26 * @deprecated 2.7.0 Content Control Pro 1.3.0+ owns licensing.
27 */
28 class License {
29
30 /**
31 * Legacy EDD API URL used only for active Pro releases older than 1.3.0.
32 *
33 * @var string
34 * @deprecated 2.7.0 Content Control Pro 1.3.0+ owns licensing.
35 */
36 const API_URL = 'https://contentcontrolplugin.com/edd-sl-api/';
37
38 /**
39 * Item ID.
40 *
41 * @var int
42 */
43 const ID = 45;
44
45 /**
46 * Option key.
47 *
48 * @var string
49 */
50 const OPTION_KEY = 'content_control_license';
51
52 /**
53 * License data
54 *
55 * @var array<string,mixed>|null
56 */
57 private $license_data;
58
59 /**
60 * Initialize license management.
61 *
62 * @deprecated 2.7.0 Content Control Pro 1.3.0+ owns licensing.
63 */
64 public function __construct() {
65 $this->register_hooks();
66 }
67
68 /**
69 * Register hooks.
70 *
71 * @return void
72 * @deprecated 2.7.0 Content Control Pro 1.3.0+ owns licensing.
73 */
74 public function register_hooks() {
75 add_action( 'init', [ $this, 'autoregister' ] );
76 add_action( 'content_control_license_status_check', [ $this, 'refresh_license_status' ] );
77 add_action( 'admin_init', [ $this, 'schedule_crons' ] );
78 }
79
80 /**
81 * Autoregister license.
82 *
83 * @return void
84 * @deprecated 2.7.0 Content Control Pro 1.3.0+ owns licensing.
85 */
86 public function autoregister() {
87 $key = defined( '\CONTENT_CONTROL_LICENSE_KEY' ) && '' !== \CONTENT_CONTROL_LICENSE_KEY ? \CONTENT_CONTROL_LICENSE_KEY : false;
88
89 if ( $key && '' === $this->get_license_key() ) {
90 try {
91 $this->activate_license( \CONTENT_CONTROL_LICENSE_KEY );
92 // phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedCatch
93 } catch ( \Exception $e ) {
94 // Do nothing.
95 }
96 }
97 }
98
99 /**
100 * Schedule cron jobs.
101 *
102 * @return void
103 * @deprecated 2.7.0 Content Control Pro 1.3.0+ owns licensing.
104 */
105 public function schedule_crons() {
106 if ( ! wp_next_scheduled( 'content_control_license_status_check' ) ) {
107 wp_schedule_event( time(), 'daily', 'content_control_license_status_check' );
108 }
109 }
110
111 /**
112 * Get license data.
113 *
114 * @return array{key:string|null,status:array<string,mixed>|null}
115 * @deprecated 2.7.0 Content Control Pro 1.3.0+ owns licensing.
116 */
117 public function get_license_data() {
118 if ( ! isset( $this->license_data ) ) {
119 $this->license_data = \get_option( self::OPTION_KEY, [
120 'key' => '',
121 'status' => [
122 'success' => false, // bool.
123 'license' => 'invalid', // valid or invalid.
124 'item_id' => self::ID, // int or false.
125 'item_name' => '', // string.
126 'license_limit' => 1, // int. 0 = unlimited.
127 'site_count' => 0,
128 'expires' => '', // date or 'lifetime'.
129 'activations_left' => 0, // int or 'unlimited'.
130 'checksum' => '', // string.
131 'payment_id' => 0, // int.
132 'customer_name' => '', // string.
133 'customer_email' => '', // string.
134 'price_id' => 0, // string or int.
135 'error' => null, // string. expired, missing, invalid, item_name_mismatch, no_activations_left etc.
136 ],
137 ] );
138 }
139
140 return $this->license_data;
141 }
142
143 /**
144 * Get license key.
145 *
146 * @return string
147 * @deprecated 2.7.0 Content Control Pro 1.3.0+ owns licensing.
148 */
149 public function get_license_key() {
150 $license_data = $this->get_license_data();
151 return ! empty( $license_data['key'] ) ? $license_data['key'] : '';
152 }
153
154 /**
155 * Get license status.
156 *
157 * @param bool $refresh Whether to refresh license status.
158 *
159 * @return array<string,mixed> Array of license status data.
160 * @deprecated 2.7.0 Content Control Pro 1.3.0+ owns licensing.
161 */
162 public function get_license_status( $refresh = false ) {
163 if ( $refresh ) {
164 $this->refresh_license_status();
165 }
166
167 $license_data = $this->get_license_data();
168
169 $license_status = isset( $license_data['status'] ) ? $license_data['status'] : [];
170
171 return $license_status;
172 }
173
174 /**
175 * Get license level.
176 *
177 * Only used in pro version.
178 *
179 * @return int Integer representing license level.
180 * @deprecated 2.7.0 Content Control Pro 1.3.0+ owns licensing.
181 */
182 public function get_license_level() {
183 $license_status = $this->get_license_status();
184
185 if ( empty( $license_status ) ) {
186 return -1;
187 }
188
189 $price_id = isset( $license_status['price_id'] ) ? $license_status['price_id'] : null;
190
191 switch ( $price_id ) {
192 default:
193 return -1;
194
195 case false:
196 case 0:
197 return 0;
198
199 case 1:
200 case 2:
201 case 3:
202 case 4:
203 return absint( $price_id );
204 }
205 }
206
207 /**
208 * Update license data.
209 *
210 * @param array{key:string|null,status:array<string,mixed>|null} $license_data License data.
211 *
212 * @return bool
213 * @deprecated 2.7.0 Content Control Pro 1.3.0+ owns licensing.
214 */
215 public function udpate_license_data( $license_data ) {
216 if ( \update_option( self::OPTION_KEY, $license_data ) ) {
217 $this->license_data = $license_data;
218 return true;
219 }
220
221 return false;
222 }
223
224 /**
225 * Update license key.
226 *
227 * @param string $key License key.
228 *
229 * @return void
230 * @deprecated 2.7.0 Content Control Pro 1.3.0+ owns licensing.
231 */
232 public function update_license_key( $key ) {
233 $license_data = $this->get_license_data();
234
235 $old_key = isset( $license_data['key'] ) ? $license_data['key'] : '';
236
237 $license_data['key'] = trim( $key );
238
239 $this->udpate_license_data( $license_data );
240
241 /**
242 * Fires when license key is changed.
243 *
244 * @param string $key License key.
245 * @param string $old_key Old license key.
246 */
247 \do_action( 'content_control_license_key_changed', $key, $old_key );
248 }
249
250 /**
251 * Update license status.
252 *
253 * @param array<string,mixed> $license_status License status data.
254 *
255 * @return void
256 * @deprecated 2.7.0 Content Control Pro 1.3.0+ owns licensing.
257 */
258 public function update_license_status( $license_status ) {
259 $license_data = $this->get_license_data();
260
261 $previous_status = isset( $license_data['status'] ) ? $license_data['status'] : [];
262
263 if ( ! empty( $license_status['error'] ) ) {
264 $license_status['error_message'] = $this->get_license_error_message( $license_status );
265 }
266
267 $license_data['status'] = $license_status;
268
269 $this->udpate_license_data( $license_data );
270
271 /**
272 * Fires when license status is updated.
273 *
274 * @param array $license_status License status data.
275 * @param array $previous_status Previous license status data.
276 */
277 \do_action( 'content_control_license_status_updated', $license_status, $previous_status );
278 }
279
280 /**
281 * Get license expiration from license status data.
282 *
283 * @param bool $as_datetime Whether to return as DateTime object.
284 *
285 * @return \DateTime|false|null
286 * @deprecated 2.7.0 Content Control Pro 1.3.0+ owns licensing.
287 */
288 public function get_license_expiration( $as_datetime = false ) {
289 $status = $this->get_license_status();
290
291 $expiration = isset( $status['expires'] ) ? $status['expires'] : null;
292
293 return $as_datetime ?
294 \DateTime::createFromFormat( 'Y-m-d H:i:s', $expiration ) :
295 $expiration;
296 }
297
298 /**
299 * Fetch license status from remote server.
300 * This is a blocking request.
301 *
302 * @return void
303 * @deprecated 2.7.0 Content Control Pro 1.3.0+ owns licensing.
304 */
305 public function refresh_license_status() {
306 $key = $this->get_license_key();
307
308 if ( empty( $key ) ) {
309 return;
310 }
311
312 try {
313 $status = $this->check_license();
314 } catch ( \Exception $e ) {
315 $status = [];
316 }
317
318 $this->update_license_status( $status );
319 }
320
321 /**
322 * Get license status from remote server.
323 *
324 * @return array<string,mixed> License status data.
325 *
326 * @throws \Exception If there is an error.
327 * @deprecated 2.7.0 Content Control Pro 1.3.0+ owns licensing.
328 */
329 private function check_license() {
330 $api_params = [
331 'edd_action' => 'check_license',
332 'license' => $this->get_license_key(),
333 'item_id' => self::ID,
334 'item_name' => rawurlencode( 'Content Control Pro' ),
335 'url' => home_url(),
336 'environment' => function_exists( 'wp_get_environment_type' ) ? wp_get_environment_type() : 'production',
337 ];
338
339 // Call the custom API.
340 $response = wp_remote_post(
341 self::API_URL,
342 [
343 'timeout' => 15,
344 'body' => $api_params,
345 ]
346 );
347
348 if ( is_wp_error( $response ) ) {
349 throw new \Exception( esc_html( $response->get_error_message() ) );
350 }
351
352 $license_status = json_decode( wp_remote_retrieve_body( $response ), true );
353
354 if ( empty( $license_status ) ) {
355 return [];
356 }
357
358 return $license_status;
359 }
360
361 /**
362 * Activate license.
363 *
364 * @param string $key License key.
365 *
366 * @return array<string,mixed> License status data.
367 *
368 * @throws \Exception If there is an error.
369 * @deprecated 2.7.0 Content Control Pro 1.3.0+ owns licensing.
370 */
371 public function activate_license( $key = null ) {
372 if ( ! empty( $key ) ) {
373 $this->update_license_key( $key );
374 } else {
375 $key = $this->get_license_key();
376 }
377
378 $api_params = [
379 'edd_action' => 'activate_license',
380 'license' => $key,
381 'item_id' => self::ID,
382 'url' => home_url(),
383 'environment' => function_exists( 'wp_get_environment_type' ) ? wp_get_environment_type() : 'production',
384 ];
385
386 // Call the custom API.
387 $response = wp_remote_post(
388 self::API_URL,
389 [
390 'timeout' => 15,
391 'body' => $api_params,
392 ]
393 );
394
395 // Make sure the response came back okay.
396 if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) {
397 if ( is_wp_error( $response ) ) {
398 $message = $response->get_error_message();
399 } else {
400 $message = __( 'An error occurred, please try again.', 'content-control' );
401 }
402
403 throw new \Exception( esc_html( $message ) );
404 }
405
406 $license_status = json_decode( wp_remote_retrieve_body( $response ), true );
407
408 $this->update_license_status( $license_status );
409
410 if ( $this->is_license_active() ) {
411 if ( ! \get_option( 'content_control_pro_activation_date', false ) ) {
412 \update_option( 'content_control_pro_activation_date', time() );
413 }
414 }
415
416 return $this->get_license_status();
417 }
418
419 /**
420 * Deactivate license.
421 *
422 * @return array<string,mixed> License status data.
423 *
424 * @throws \Exception If there is an error.
425 * @deprecated 2.7.0 Content Control Pro 1.3.0+ owns licensing.
426 */
427 public function deactivate_license() {
428 $api_params = [
429 'edd_action' => 'deactivate_license',
430 'license' => $this->get_license_key(),
431 'item_id' => self::ID,
432 'item_name' => rawurlencode( 'Content Control' ),
433 'url' => home_url(),
434 'environment' => function_exists( 'wp_get_environment_type' ) ? wp_get_environment_type() : 'production',
435 ];
436
437 // Call the custom API.
438 $response = wp_remote_post(
439 self::API_URL,
440 [
441 'timeout' => 15,
442 'body' => $api_params,
443 ]
444 );
445
446 // Make sure the response came back okay.
447 if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) {
448 if ( is_wp_error( $response ) ) {
449 $message = $response->get_error_message();
450 } else {
451 $message = __( 'An error occurred, please try again.', 'content-control' );
452 }
453
454 throw new \Exception( esc_html( $message ) );
455 }
456
457 $license_status = json_decode( wp_remote_retrieve_body( $response ), true );
458
459 $this->update_license_status( $license_status );
460
461 return $license_status;
462 }
463
464 /**
465 * Convert license error to human readable message.
466 *
467 * @param array<string,mixed> $license_status License status data.
468 *
469 * @return string
470 * @deprecated 2.7.0 Content Control Pro 1.3.0+ owns licensing.
471 */
472 public function get_license_error_message( $license_status ) {
473 switch ( $license_status['error'] ) {
474 case 'expired':
475 $message = sprintf(
476 /* translators: the license key expiration date */
477 __( 'Your license key expired on %s.', 'content-control' ),
478 date_i18n( \get_option( 'date_format' ), strtotime( $license_status['expires'], time() ) )
479 );
480 break;
481
482 case 'disabled':
483 case 'revoked':
484 $message = __( 'Your license key has been disabled.', 'content-control' );
485 break;
486
487 case 'missing':
488 $message = __( 'Invalid license.', 'content-control' );
489 break;
490
491 case 'invalid':
492 case 'site_inactive':
493 $message = __( 'Your license is not active for this URL.', 'content-control' );
494 break;
495
496 case 'item_name_mismatch':
497 $message = sprintf(
498 /* translators: the plugin name */
499 __( 'This appears to be an invalid license key for %s.', 'content-control' ),
500 __( 'Content Control', 'content-control' )
501 );
502 break;
503
504 case 'no_activations_left':
505 $message = __( 'Your license key has reached its activation limit.', 'content-control' );
506 break;
507
508 default:
509 $message = __( 'An error occurred, please try again.', 'content-control' );
510 break;
511 }
512
513 return $message;
514 }
515
516 /**
517 * Remove license.
518 *
519 * @return void
520 * @deprecated 2.7.0 Content Control Pro 1.3.0+ owns licensing.
521 */
522 public function remove_license() {
523 if ( '' === $this->get_license_key() ) {
524 \delete_option( self::OPTION_KEY );
525 $this->license_data = null;
526 return;
527 }
528
529 try {
530 $deactivated = $this->deactivate_license();
531 } catch ( \Exception $e ) {
532 $deactivated = [];
533 }
534
535 if ( ! empty( $deactivated['license'] ) && 'active' !== $deactivated['license'] ) {
536 \delete_option( self::OPTION_KEY );
537 }
538 }
539
540 /**
541 * Check if license is active.
542 *
543 * @return bool
544 * @deprecated 2.7.0 Content Control Pro 1.3.0+ owns licensing.
545 */
546 public function is_license_active() {
547 $license_status = $this->get_license_status();
548
549 if ( empty( $license_status ) ) {
550 return false;
551 }
552
553 return 'valid' === $license_status['license'];
554 }
555 }
556