PluginProbe ʕ •ᴥ•ʔ
GiveWP – Donation Plugin and Fundraising Platform / 3.22.2
GiveWP – Donation Plugin and Fundraising Platform v3.22.2
4.16.3 4.16.2 4.16.1 4.16.0 4.15.5 4.15.4 4.15.3 4.15.2 4.15.1 4.15.0 2.3.0 2.3.1 2.3.2 2.30.0 2.31.0 2.31.1 2.32.0 2.33.0 2.33.1 2.33.2 2.33.3 2.33.4 2.33.5 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.4.5 2.4.6 2.4.7 2.5.0 2.5.1 2.5.10 2.5.11 2.5.12 2.5.13 2.5.2 2.5.3 2.5.4 2.5.5 2.5.6 2.5.7 2.5.8 2.5.9 2.6.0 2.6.1 2.6.2 2.6.3 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.8.0 2.8.1 2.9.0 2.9.1 2.9.2 2.9.3 2.9.4 2.9.5 2.9.6 2.9.7 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.1.0 3.1.1 3.1.2 3.10.0 3.11.0 3.12.0 3.12.1 3.12.2 3.12.3 3.13.0 3.14.0 3.14.1 3.14.2 3.15.0 3.15.1 3.16.0 3.16.1 3.16.2 3.16.3 3.16.4 3.16.5 3.17.0 3.17.1 3.17.2 3.18.0 3.19.0 3.19.1 3.19.2 3.19.3 3.19.4 3.2.0 3.2.1 3.2.2 3.20.0 3.21.0 3.21.1 3.22.0 3.22.1 3.22.2 3.3.0 3.3.1 3.4.0 3.4.1 3.4.2 3.5.0 3.5.1 3.6.0 3.6.1 3.6.2 3.7.0 3.8.0 3.9.0 4.0.0 4.1.0 4.1.1 4.10.0 4.10.1 4.11.0 4.12.0 4.13.0 4.13.1 4.13.2 4.14.0 4.14.1 4.14.2 4.14.3 4.14.4 4.14.5 4.14.6 4.2.0 4.2.1 4.3.0 4.3.1 4.3.2 4.4.0 4.5.0 4.6.1 4.7.0 4.7.1 4.8.0 4.8.1 4.9.0 trunk 1.9.0 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.10.0 2.10.1 2.10.2 2.10.3 2.10.4 2.11.0 2.11.1 2.11.2 2.11.3 2.12.0 2.12.1 2.12.2 2.12.3 2.13.0 2.13.1 2.13.2 2.13.3 2.13.4 2.14.0 2.15.0 2.16.0 2.16.1 2.17.0 2.17.1 2.17.3 2.18.0 2.18.1 2.19.1 2.19.2 2.19.3 2.19.4 2.19.5 2.19.6 2.19.7 2.19.8 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 2.20.0 2.20.1 2.20.2 2.21.0 2.21.1 2.21.2 2.21.3 2.21.4 2.22.0 2.22.1 2.22.2 2.22.3 2.23.0 2.23.1 2.23.2 2.24.0 2.24.1 2.24.2 2.25.0 2.25.1 2.25.2 2.25.3 2.26.0 2.27.0 2.27.1 2.27.2 2.27.3 2.28.0 2.29.0 2.29.1 2.29.2
give / includes / class-give-license-handler.php
give / includes Last commit date
admin 1 year ago api 3 years ago database 2 years ago deprecated 3 years ago donors 1 year ago emails 3 years ago forms 1 year ago frontend 6 years ago gateways 1 year ago libraries 2 years ago payments 1 year ago actions.php 5 years ago ajax-functions.php 2 years ago class-give-async-process.php 1 year ago class-give-background-updater.php 2 years ago class-give-cache-setting.php 2 years ago class-give-cache.php 3 years ago class-give-cli-commands.php 3 years ago class-give-comment.php 6 years ago class-give-cron.php 6 years ago class-give-donate-form.php 1 year ago class-give-donor.php 2 years ago class-give-email-access.php 5 years ago class-give-license-handler.php 1 year ago class-give-logging.php 5 years ago class-give-readme-parser.php 4 years ago class-give-roles.php 6 years ago class-give-scripts.php 2 years ago class-give-session.php 5 years ago class-give-stats.php 6 years ago class-give-template-loader.php 6 years ago class-give-tooltips.php 6 years ago class-give-translation.php 4 years ago class-notices.php 2 years ago country-functions.php 1 year ago currencies-list.php 3 years ago currency-functions.php 3 years ago error-tracking.php 6 years ago filters.php 3 years ago formatting.php 1 year ago install.php 2 years ago login-register.php 2 years ago misc-functions.php 1 year ago plugin-compatibility.php 6 years ago post-types.php 1 year ago price-functions.php 6 years ago process-donation.php 1 year ago setting-functions.php 6 years ago shortcodes.php 1 year ago template-functions.php 4 years ago user-functions.php 3 years ago
class-give-license-handler.php
1170 lines
1 <?php
2 /**
3 * Give License handler
4 *
5 * @package Give
6 * @subpackage Admin/License
7 * @copyright Copyright (c) 2016, GiveWP
8 * @license https://opensource.org/licenses/gpl-license GNU Public License
9 * @since 1.0
10 */
11
12 // Exit if accessed directly.
13 use Give\Log\Log;
14 use Give\Vendors\StellarWP\AdminNotices\AdminNotices;
15
16 if ( ! defined('ABSPATH') ) {
17 exit;
18 }
19
20 if ( ! class_exists('Give_License') ) :
21
22 /**
23 * Give_License Class
24 *
25 * This class simplifies the process of adding license information
26 * to new Give add-ons.
27 *
28 * @since 1.0
29 */
30 class Give_License
31 {
32
33 /**
34 * File
35 *
36 * @access private
37 * @since 1.0
38 *
39 * @var string
40 */
41 private $file;
42
43 /**
44 * License
45 *
46 * @access private
47 * @since 1.0
48 *
49 * @var string
50 */
51 private $license;
52
53 /**
54 * The license bundled with the premium add-on.
55 *
56 * @since 3.21.0
57 *
58 * @var string|null
59 */
60 private $bundled_license;
61
62 /**
63 * Item name
64 *
65 * @access private
66 * @since 1.0
67 *
68 * @var string
69 */
70 private $item_name;
71
72 /**
73 * Item ID
74 *
75 * @access private
76 * @since 2.2.4
77 *
78 * @var int
79 */
80 private $item_id;
81
82 /**
83 * License Information object.
84 *
85 * @access private
86 * @since 1.7
87 *
88 * @var object
89 */
90 private $license_data;
91
92 /**
93 * Item shortname
94 *
95 * @access private
96 * @since 1.0
97 *
98 * @var string
99 */
100 private $item_shortname;
101
102 /**
103 * Version
104 *
105 * @access private
106 * @since 1.0
107 *
108 * @var string
109 */
110 private $version;
111
112 /**
113 * Author
114 *
115 * @access private
116 * @since 1.0
117 *
118 * @var string
119 */
120 private $author;
121
122 /**
123 * Plugin basename (as provided by plugin_basename() function)
124 *
125 * @var string
126 */
127 private $plugin_basename;
128
129 /**
130 * Plugin directory name
131 *
132 * @access private
133 * @since 2.5.0
134 *
135 * @var string
136 */
137 private $plugin_dirname;
138
139 /**
140 * Website URL
141 *
142 * @access private
143 * @since 1.0
144 *
145 * @var string
146 */
147 private static $site_url = 'https://givewp.com/';
148
149 /**
150 * API URL
151 *
152 * @access private
153 * @since 1.0
154 *
155 * @var string
156 */
157 private static $api_url = 'https://givewp.com/edd-sl-api/';
158
159 /**
160 * array of licensed addons
161 *
162 * @since 3.21.0 store the Give_License instances, not just the plugin basenames
163 * @since 2.1.4
164 * @access private
165 *
166 * @var Give_License[]
167 */
168 private static $licensed_addons = [];
169
170 /**
171 * Account URL
172 *
173 * @access private
174 * @since 1.7
175 *
176 * @var null|string
177 */
178 private static $account_url = 'http://docs.givewp.com/settings-account';
179
180 /**
181 * Downloads URL
182 *
183 * @access private
184 * @since 2.5.0
185 *
186 * @var null|string
187 */
188 private static $downloads_url = 'http://docs.givewp.com/settings-downloads';
189
190 /**
191 * Checkout URL
192 *
193 * @access private
194 * @since 1.7
195 *
196 * @var null|string
197 */
198 private static $checkout_url = 'https://givewp.com/checkout/';
199
200 /**
201 * Class Constructor
202 *
203 * Set up the Give License Class.
204 *
205 * @access public
206 *
207 * @since 3.17.2 removed unused auto_updater_obj property assignment
208 * @since 1.0
209 *
210 * @param string $_file
211 * @param string $_item_name
212 * @param string $_version
213 * @param string $_author
214 * @param string $_optname
215 * @param string $_api_url
216 * @param string $_checkout_url
217 * @param string $_account_url
218 * @param int $_item_id
219 *
220 * @since 3.21.0 adds plugin_basename property
221 */
222 public function __construct(
223 $_file,
224 $_item_name,
225 $_version,
226 $_author,
227 $_optname = null,
228 $_api_url = null,
229 $_checkout_url = null,
230 $_account_url = null,
231 $_item_id = null
232 ) {
233
234 // Only load in wp-admin.
235 if ( ! is_admin() ) {
236 return;
237 }
238
239 if ( is_numeric( $_item_id ) ) {
240 $this->item_id = absint( $_item_id );
241 }
242
243 $this->file = $_file;
244 $this->item_name = $_item_name;
245 $this->plugin_basename = plugin_basename($this->file);
246 $this->plugin_dirname = dirname( plugin_basename( $this->file ) );
247 $this->item_shortname = self::get_short_name( $this->item_name );
248 $this->license_data = self::get_license_by_plugin_dirname( $this->plugin_dirname );
249 $this->version = $_version;
250 $this->license = ! empty( $this->license_data['license_key'] ) ? $this->license_data['license_key'] : '';
251 $this->bundled_license = self::get_bundled_license($this->file);
252 $this->author = $_author;
253 self::$api_url = is_null( $_api_url ) ? self::$api_url : $_api_url;
254 self::$checkout_url = is_null( $_checkout_url ) ? self::$checkout_url : $_checkout_url;
255 self::$account_url = is_null( $_account_url ) ? self::$account_url : $_account_url;
256
257 // Add plugin to registered licenses list.
258 array_push(self::$licensed_addons, $this);
259 }
260
261 /**
262 * Get plugin shortname
263 *
264 * @param $plugin_name
265 *
266 * @return string
267 * @since 2.1.0
268 * @access public
269 */
270 public static function get_short_name( $plugin_name ) {
271 $plugin_name = trim( str_replace( 'Give - ', '', $plugin_name ) );
272 $plugin_name = 'give_' . preg_replace( '/[^a-zA-Z0-9_\s]/', '', str_replace( ' ', '_', strtolower( $plugin_name ) ) );
273
274 return $plugin_name;
275 }
276
277 /**
278 * Checks to see if the license was bundled with the add-on and if so, returns it. This is meant to be a
279 * convenience, so any errors are ignored and the user can still manually enter their license key.
280 *
281 * @since 3.21.0
282 */
283 public static function get_bundled_license(string $plugin_file): ?string
284 {
285 $license = null;
286 $file_path = plugin_dir_path($plugin_file) . 'PLUGIN_LICENSE.php';
287 if (is_readable($file_path)) {
288 $license = include $file_path;
289 }
290
291 return $license ?: null;
292 }
293
294 /**
295 * This sorts through all the registered add-ons and checks to see if any of them have bundled licenses, but
296 * aren't set up with a license key. If so, it will attempt to activate the license key for them.
297 *
298 * It's likely that many add-ons will have the same license key which is a plan, so the license key will only be
299 * activated once for all add-ons using it.
300 *
301 * If any sort of error occurs, an admin notice will be shown to the user providing the error and instructions
302 * to manually activate the license key.
303 *
304 * Note: much of this code is taken directly from give_get_license_info_handler()
305 *
306 * @since 3.21.0
307 */
308 public static function activate_bundled_licenses(): void
309 {
310 $unactivated_bundled_licenses = [];
311 foreach (self::$licensed_addons as $addon) {
312 if ($addon->bundled_license && empty($addon->license)) {
313 // Store a unique associative array where the key is the license key and the value is an array of
314 // addons using that license
315 if ( ! isset($unactivated_bundled_licenses[$addon->bundled_license])) {
316 $unactivated_bundled_licenses[$addon->bundled_license] = [];
317 }
318
319 $unactivated_bundled_licenses[$addon->bundled_license][] = $addon;
320 }
321 }
322
323 if (empty($unactivated_bundled_licenses)) {
324 return;
325 }
326
327 $show_failed_activation_notice = static function ($license_key, $reason) {
328 AdminNotices::show(
329 "license-bundle-activation-error-$license_key",
330 "An error occurred while attempting to activate license $license_key: $reason. Please activate the license manually."
331 )->asError()->isDismissible();
332 };
333
334 foreach ($unactivated_bundled_licenses as $license => $addons) {
335 $check_license_res = self::request_license_api(
336 [
337 'edd_action' => 'check_license',
338 'license' => $license,
339 ],
340 true
341 );
342 $is_plan_license = ! empty($check_license_res['is_all_access_pass']);
343
344 if (is_wp_error($check_license_res)) {
345 $show_failed_activation_notice($license, $check_license_res->get_error_message());
346 continue;
347 }
348
349 if ( ! $check_license_res['success']) {
350 $show_failed_activation_notice($license, $check_license_res['error']);
351 continue;
352 }
353
354 if ( ! $is_plan_license) {
355 if (count($addons) > 1) {
356 $show_failed_activation_notice(
357 $license,
358 'A single add-on license cannot be used for multiple add-ons'
359 );
360 continue;
361 }
362
363 if ($check_license_res['plugin_slug'] !== $addons[0]->plugin_dirname) {
364 $show_failed_activation_notice(
365 $license,
366 'The license is not valid for this add-on'
367 );
368 continue;
369 }
370 }
371
372 $activate_license_res = self::request_license_api(
373 [
374 'edd_action' => 'activate_license',
375 'item_name' => $check_license_res['item_name'],
376 'license' => $license,
377 ],
378 true
379 );
380
381 if (is_wp_error($activate_license_res)) {
382 $show_failed_activation_notice($license, $activate_license_res->get_error_message());
383 continue;
384 }
385
386 $check_license_res['license'] = $activate_license_res['license'];
387 $check_license_res['site_count'] = $activate_license_res['site_count'];
388 $check_license_res['activations_left'] = $activate_license_res['activations_left'];
389 $licenses = get_option('give_licenses', []);
390
391 if ($is_plan_license) {
392 $addonSlugs = self::getAddonSlugsFromAllAccessPassLicense($check_license_res);
393 foreach ($licenses as $license_key => $data) {
394 if (in_array($data['plugin_slug'], $addonSlugs, true) || ! empty($data['is_all_access_pass'])) {
395 unset($licenses[$license_key]);
396 }
397 }
398 }
399
400 $licenses[$check_license_res['license_key']] = $check_license_res;
401 update_option('give_licenses', $licenses);
402 }
403
404 // Have WordPress check for updates
405 give_refresh_licenses();
406 }
407
408 /**
409 * Activate License
410 *
411 * Activate the license key.
412 *
413 * @access public
414 * @return void
415 * @since 1.0
416 */
417 public function activate_license() {
418 }
419
420 /**
421 * Deactivate License
422 *
423 * Deactivate the license key.
424 *
425 * @access public
426 * @return void
427 * @since 1.0
428 */
429 public function deactivate_license() {
430 }
431
432
433 /**
434 * Get license information.
435 *
436 * @param string $edd_action
437 * @param bool $response_in_array
438 *
439 * @return mixed
440 * @deprecated 2.5.0 Use self::request_license_api instead.
441 *
442 * @since 1.8.9
443 * @access public
444 */
445 public function get_license_info($edd_action = '', $response_in_array = false)
446 {
447 if ( empty($edd_action) ) {
448 return false;
449 }
450
451 give_doing_it_wrong(__FUNCTION__, 'Use self::request_license_api instead from GiveWP 2.5.0');
452
453 // Data to send to the API.
454 $api_params = [
455 'edd_action' => $edd_action, // never change from "edd_" to "give_"!
456 'license' => $this->license,
457 'item_name' => urlencode($this->item_name),
458 ];
459
460 return self::request_license_api($api_params, $response_in_array);
461 }
462
463 /**
464 * Return licensed addons info
465 *
466 * Note: note only for internal logic
467 *
468 * @since 3.21.1 use array_map to safely access the private property
469 * @since 3.21.0 plucks the basename for backwards compatibility
470 * @since 2.1.4
471 * @return string[]
472 */
473 static function get_licensed_addons(): array
474 {
475 return array_map( static function ( Give_License $license ) {
476 return $license->plugin_basename;
477 }, self::$licensed_addons );
478 }
479
480 /**
481 * Check if license key attached to subscription
482 *
483 * @since 2.5.0
484 *
485 * @param string $license_key
486 *
487 * @return array
488 */
489 static function is_subscription($license_key = '')
490 {
491 // Check if current license is part of subscription or not.
492 $subscriptions = get_option('give_subscriptions');
493 $subscription = [];
494
495 if ( $subscriptions ) {
496 foreach ($subscriptions as $subs) {
497 if ( in_array($license_key, $subs['licenses']) ) {
498 $subscription = $subs;
499 break;
500 }
501 }
502 }
503
504 return $subscription;
505 }
506
507 /**
508 * Get license information.
509 *
510 * @since 1.8.9
511 * @since 2.18.0 log failed license api request information
512 *
513 * @param bool $response_in_array
514 *
515 * @param array $api_params
516 *
517 * @return array|WP_Error
518 */
519 public static function request_license_api($api_params = [], $response_in_array = false)
520 {
521 // Bailout.
522 if ( empty($api_params['edd_action']) ) {
523 return new WP_Error('give-invalid-edd-action', __('Valid edd_action not defined', 'give'));
524 }
525
526 // Data to send to the API.
527 $default_api_params = [
528 // 'edd_action' => $edd_action, never change from "edd_" to "give_"!
529 // 'license' => $this->license,
530 // 'item_name' => urlencode( $this->item_name ),
531 'url' => home_url(),
532 ];
533
534 $api_params = wp_parse_args($api_params, $default_api_params);
535
536 // Call the API.
537 $response = wp_remote_post(
538 self::get_api_url(),
539 apply_filters(
540 'give_request_license_api_args',
541 [
542 'timeout' => 15,
543 'sslverify' => false,
544 'body' => $api_params,
545 ]
546 )
547 );
548
549 $statusCode = wp_remote_retrieve_response_code($response);
550 $body = json_decode(wp_remote_retrieve_body($response), $response_in_array);
551
552 if ( 200 !== $statusCode ) {
553 Log::http(
554 'License Api request failed',
555 [
556 'category' => 'License',
557 'api url' => self::get_api_url(),
558 'request' => $api_params,
559 'status code' => $statusCode,
560 'response' => $response
561 ]
562 );
563 }
564
565 // Make sure there are no errors.
566 if ( is_wp_error($response) ) {
567 return $response;
568 }
569
570 return $body;
571 }
572
573 /**
574 * Get license by plugin dirname
575 *
576 * @param string $plugin_dirname
577 *
578 * @return array
579 *
580 * @since 2.5.0
581 * @access public
582 */
583 public static function get_license_by_plugin_dirname( $plugin_dirname ) {
584 $license = [];
585 $give_licenses = get_option( 'give_licenses', [] );
586
587 if ( ! empty( $give_licenses ) ) {
588 foreach ( $give_licenses as $give_license ) {
589
590 // Logic to match all access pass license to add-on.
591 $compares = $give_license['is_all_access_pass']
592 ? $give_license['download']
593
594 // Prevent PHP notice if somehow automatic update does not run properly.
595 // Because plugin_slug will only define in updated license rest api response.
596 : [ [ 'plugin_slug' => ! empty( $give_license['plugin_slug'] ) ? $give_license['plugin_slug'] : '' ] ];
597
598 foreach ( $compares as $compare ) {
599 if ( ! empty( $compare['plugin_slug'] ) && $plugin_dirname === $compare['plugin_slug'] ) {
600 $license = $give_license;
601 break;
602 }
603 }
604 }
605 }
606
607 return $license;
608 }
609
610
611 /**
612 * Get checkout url
613 *
614 * @return string|null
615 * @since 2.5.0
616 */
617 public static function get_checkout_url() {
618 return self::$checkout_url;
619 }
620
621 /**
622 * Get account url
623 *
624 * @return string|null
625 * @since 2.5.0
626 */
627 public static function get_account_url() {
628 return self::$account_url;
629 }
630
631 /**
632 * Get downloads url
633 *
634 * @return string|null
635 * @since 2.5.0
636 */
637 public static function get_downloads_url() {
638 return self::$downloads_url;
639 }
640
641 /**
642 * Get account url
643 *
644 * @since 3.20.0 allows to override the API URL via constant
645 * @since 2.5.0
646 */
647 public static function get_website_url(): ?string
648 {
649 if (defined('GIVE_SITE_URL')) {
650 return GIVE_SITE_URL;
651 }
652
653 return self::$site_url;
654 }
655
656
657 /**
658 * Get plugin information by id.
659 * Note: only for internal use
660 *
661 * @param string $plugin_slug
662 *
663 * @return array
664 * @since 2.5.0
665 */
666 public static function get_plugin_by_slug( $plugin_slug ) {
667 $give_plugins = give_get_plugins();
668 $matching_list = wp_list_pluck( $give_plugins, 'Dir', 'Path' );
669 $is_match_found = array_search( $plugin_slug, $matching_list, true );
670
671 return $is_match_found ? $give_plugins[ $is_match_found ] : [];
672 }
673
674 /**
675 * Get plugin information by id.
676 * Note: only for internal use
677 *
678 * @param string $plugin_slug
679 *
680 * @return string
681 * @since 2.5.0
682 */
683 public static function build_plugin_name_from_slug( $plugin_slug ) {
684 $plugin_name = str_replace( [ '-', 'give ' ], [ ' ', 'Give - ' ], $plugin_slug );
685
686 return ucwords( $plugin_name );
687 }
688
689 /**
690 * Render license section
691 *
692 * @return string
693 * @since 2.5.0
694 */
695 public static function render_licenses_list() {
696 $give_plugins = give_get_plugins( [ 'only_premium_add_ons' => true ] );
697 $give_licenses = get_option( 'give_licenses', [] );
698 $licenses_without_addon = $give_licenses;
699
700 // Get all access pass licenses
701 $all_access_pass_licenses = [];
702 $all_access_pass_addon_list = [];
703 foreach ( $give_licenses as $key => $give_license ) {
704 if ( $give_license['is_all_access_pass'] ) {
705 $all_access_pass_licenses[ $key ] = $give_license;
706
707 unset( $licenses_without_addon[ $key ] );
708
709 foreach ( $give_license['download'] as $download ) {
710 $all_access_pass_addon_list[] = $download['plugin_slug'];
711 }
712 }
713 }
714
715 $html = [
716 'unlicensed' => '',
717 'licensed' => '',
718 'licenses_without_addon' => '',
719 'all_access_licensed' => '',
720 ];
721
722 if ( ! empty( $give_plugins ) ) {
723 foreach ( $give_plugins as $give_plugin ) {
724 if ( in_array( $give_plugin['Dir'], $all_access_pass_addon_list ) ) {
725 continue;
726 }
727
728 $addon_license = self::get_license_by_plugin_dirname( $give_plugin['Dir'] );
729 $html_arr_key = 'unlicensed';
730
731 if ( $addon_license ) {
732 $html_arr_key = 'licensed';
733 unset( $licenses_without_addon[ $addon_license['license_key'] ] );
734 }
735
736 $html[ "{$html_arr_key}" ] .= self::html_by_plugin( $give_plugin );
737 }
738 }
739
740 if ( ! empty( $all_access_pass_licenses ) ) {
741 foreach ( $all_access_pass_licenses as $key => $all_access_pass_license ) {
742 $html['all_access_licensed'] .= self::html_by_license( $all_access_pass_license );
743 }
744 }
745
746 if ( ! empty( $licenses_without_addon ) ) {
747 foreach ( $licenses_without_addon as $key => $license ) {
748 if ( in_array( $license['plugin_slug'], $all_access_pass_addon_list ) ) {
749 continue;
750 }
751 $html['licenses_without_addon'] .= self::html_by_license( $license );
752 }
753 }
754
755 ksort( $html );
756
757 // After sorting order will be all_access_licensed -> licensed -> unlicensed
758
759 return implode( '', $html );
760 }
761
762 /**
763 * Get add-on item html
764 * Note: only for internal use
765 *
766 * @param $plugin
767 *
768 * @return string
769 * @since 2.5.0
770 */
771 public static function html_by_plugin( $plugin ) {
772 // Bailout.
773 if ( empty( $plugin ) ) {
774 return '';
775 }
776
777 ob_start();
778 $license = self::get_license_by_plugin_dirname( $plugin['Dir'] );
779
780 $default_plugin = [
781 'ChangeLogSlug' => $plugin['Dir'],
782 'DownloadURL' => '',
783 ];
784
785 if ( false !== strpos( $default_plugin['ChangeLogSlug'], '-gateway' ) ) {
786 // We found that each gateway addon does not have `-gateway` in changelog file slug
787 $default_plugin['ChangeLogSlug'] = str_replace( '-gateway', '', $default_plugin['ChangeLogSlug'] );
788 }
789
790 if ( $license ) {
791 $license['renew_url'] = self::$checkout_url . "?edd_license_key={$license['license_key']}";
792 $default_plugin['ChangeLogSlug'] = $license['readme'];
793 $default_plugin['DownloadURL'] = $license['download'];
794 }
795
796 $plugin['License'] = $license = wp_parse_args(
797 $license,
798 [
799 'item_name' => str_replace( 'give-', '', $plugin['Dir'] ),
800 'purchase_link' => $plugin['PluginURI'],
801 ]
802 );
803
804 $plugin = wp_parse_args( $plugin, $default_plugin );
805 ?>
806 <div class="give-addon-wrap">
807 <div class="give-addon-inner">
808 <?php echo self::html_license_row( $license, $plugin ); ?>
809 <?php echo self::html_plugin_row( $plugin ); ?>
810 </div>
811 </div>
812 <?php
813
814 return ob_get_clean();
815 }
816
817 /**
818 * Get add-on item html
819 * Note: only for internal use
820 *
821 * @param array $license
822 *
823 * @return string
824 * @since 2.5.0
825 */
826 private static function html_by_license( $license ) {
827 ob_start();
828
829 $license['renew_url'] = self::$checkout_url . "?edd_license_key={$license['license_key']}";
830 ?>
831 <div class="give-addon-wrap">
832 <div class="give-addon-inner">
833 <?php
834 echo self::html_license_row( $license );
835
836 $addons = $license['download'];
837
838 if ( empty( $license['is_all_access_pass'] ) ) {
839 $addons = [ $license ];
840 }
841
842 foreach ( $addons as $addon ) {
843 $default_plugin = [
844 // In single license key we will get item_name instead of name.
845 'Name' => ! empty( $addon['item_name'] ) ? $addon['item_name'] : $addon['name'],
846
847 'ChangeLogSlug' => $addon['readme'],
848 'Version' => $addon['current_version'],
849 'Status' => 'not installed',
850
851 // In single license key we will get download instead of file.
852 'DownloadURL' => ! empty( $addon['download'] ) ? $addon['download'] : $addon['file'],
853
854 ];
855
856 $plugin = wp_parse_args(
857 self::get_plugin_by_slug( $addon['plugin_slug'] ),
858 $default_plugin
859 );
860
861 $plugin['Name'] = false !== strpos( $plugin['Name'], 'Give' )
862 ? $plugin['Name']
863 : self::build_plugin_name_from_slug( $addon['plugin_slug'] );
864
865 $plugin['License'] = $license;
866
867 echo self::html_plugin_row( $plugin );
868 }
869 ?>
870 </div>
871 </div>
872 <?php
873
874 return ob_get_clean();
875 }
876
877
878 /**
879 * license row html
880 *
881 * @param array $license
882 * @param array $plugin
883 *
884 * @return string
885 * @since 2.5.0
886 */
887 private static function html_license_row( $license, $plugin = [] ) {
888 ob_start();
889
890 $is_license = $license && ! empty( $license['license_key'] );
891 $license_key = $is_license ? $license['license_key'] : '';
892 $license_is_inactive = $license_key && ! in_array( $license['license'], [ 'valid', 'expired' ] );
893 $expires_timestamp = $is_license ? strtotime( $license['expires'] ) : '';
894 $is_license_expired = $is_license && ( 'expired' === $license['license'] || $expires_timestamp < time() );
895 $addon_dir = ! empty( $plugin['Dir'] ) ? $plugin['Dir'] : ( ! empty( $license['plugin_slug'] ) ? $license['plugin_slug'] : '' );
896 ?>
897 <div class="give-license-row give-clearfix">
898 <div class="give-license-notice-container"></div>
899 <div class="give-license-top give-clearfix">
900
901 <div class="give-license-top-column give-license-key-field-wrap">
902
903 <div class="give-license__key<?php echo $license_key ? ' give-has-license-key' : ''; ?>">
904 <?php $value = $license_key ? give_hide_char( $license['license_key'], 5 ) : ''; ?>
905 <label for="give-license-addon-key-field" class="give-license-top-header"><?php _e( 'License Key', 'give' ); ?></label>
906 <input id="give-license-addon-key-field" type="text" autocomplete="off" value="<?php echo $value; ?>"<?php echo $value ? ' readonly' : ''; ?>>
907 <?php if ( ! $license_key ) : ?>
908 <button class="give-button__license-activate button-primary" data-addon="<?php echo $addon_dir; ?>">
909 <?php _e( 'Activate', 'give' ); ?>
910 </button>
911 <?php elseif ( $license_is_inactive ) : ?>
912 <button class="give-button__license-reactivate button-primary" data-addon="<?php echo $addon_dir; ?>" data-license="<?php echo $license['license_key']; ?>">
913 <?php _e( 'Reactivate', 'give' ); ?>
914 </button>
915 <?php else : ?>
916
917 <?php
918 echo sprintf(
919 '<button class="give-license__deactivate button button-secondary" data-license-key="%2$s" data-item-name="%3$s" data-plugin-dirname="%5$s" data-nonce="%4$s">%1$s</button>',
920 __( 'Deactivate', 'give' ),
921 $license['license_key'],
922 $license['item_name'],
923 wp_create_nonce( "give-deactivate-license-{$license['item_name']}" ),
924 ! empty( $license['plugin_slug'] ) ? $license['plugin_slug'] : ''
925 );
926 ?>
927
928 <?php endif; ?>
929
930 <div class="give-license__status">
931 <?php
932 echo $license_key && ! $license_is_inactive
933 ? sprintf(
934 '<span class="dashicons dashicons-%2$s"></span>&nbsp;%1$s',
935 $is_license_expired
936 ? __( 'License is expired. Please activate your license key.', 'give' )
937 : __( 'License is active and you are receiving updates and support.', 'give' ),
938 $is_license_expired
939 ? 'no'
940 : 'yes'
941 )
942 : sprintf(
943 '<span class="dashicons dashicons-no"></span> %1$s %2$s',
944 __( 'License is inactive.', 'give' ),
945 $license_is_inactive
946 ? sprintf(
947 __( 'Please <a href="%1$s" target="_blank">Visit your dashboard</a> to check this license details and activate this license to receive updates and support.', 'give' ),
948 self::get_account_url()
949 )
950 : __( 'Please activate your license key.', 'give' )
951 );
952 ?>
953 </div>
954 </div>
955 </div>
956
957 <div class="give-license-top-column give-license-info-field-wrap">
958 <h3 class="give-license-top-header"><?php _e( 'License Information', 'give' ); ?></h3>
959 <?php
960 // @todo: handle all license status;
961 if ( $license_key ) :
962 ?>
963
964 <?php if ( $license_key ) : ?>
965 <?php
966 echo sprintf(
967 '<p class="give-license-renewal-date"><span class="dashicons dashicons-calendar-alt"></span> <strong>%1$s</strong> %2$s</p>',
968 $is_license_expired ? __( 'Expired:', 'give' ) : __( 'Renews:', 'give' ),
969 date( give_date_format(), $expires_timestamp )
970 );
971 ?>
972 <?php endif; ?>
973
974 <?php
975 if ( $is_license_expired ) {
976 // @todo: need to test renew license link
977 echo sprintf(
978 '<a href="%1$s" target="_blank">%2$s</a>',
979 $license['renew_url'],
980 __( 'Renew to manage sites', 'give' )
981 );
982 } elseif ( $license_key ) {
983 if ( ! $license['activations_left'] ) {
984 echo sprintf(
985 '<span class="give-license-activations-left">%1$s</span>',
986 __( 'No activations remaining', 'give' )
987 );
988 } else {
989 echo sprintf(
990 '<span class="give-license-activations-left"><span class="give-license-activations-remaining-icon wp-ui-highlight">%1$s</span> %2$s</span>',
991 $license['activations_left'],
992 _n( 'Activation Remaining', 'Activations Remaining', $license['activations_left'], 'give' )
993 );
994 }
995 }
996 ?>
997 <?php else : ?>
998
999 <p class="give-field-description"><?php _e( 'This is an unlicensed add-on and is not receiving updates or support. Please activate your license key to fix the issue.', 'give' ); ?></p>
1000
1001 <?php endif; ?>
1002 </div>
1003
1004 <div class="give-license-top-column">
1005 <h3 class="give-license-top-header"><?php _e( 'License Actions', 'give' ); ?></h3>
1006
1007 <?php
1008 // Purchase license link.
1009 if ( ! $license_key ) :
1010 ?>
1011 <?php
1012 echo sprintf(
1013 '<a class="give-button button-secondary" href="%1$s" target="_blank">%2$s</a>',
1014 $license['purchase_link'],
1015 __( 'Purchase License', 'give' )
1016 );
1017 ?>
1018 <?php endif; ?>
1019
1020 <?php
1021 // Manage license link on GiveWP.com
1022 if ( ! $is_license_expired && $license_key ) {
1023 echo sprintf(
1024 '<a href="%1$spurchase-history/?license_id=%2$s&action=manage_licenses&payment_id=%3$s" target="_blank" class="give-license-action-link">%4$s</a>',
1025 trailingslashit( self::get_website_url() ),
1026 $license['license_id'],
1027 $license['payment_id'],
1028 __( 'Manage License', 'give' )
1029 );
1030 echo sprintf(
1031 '<a href="%1$spriority-support/" target="_blank" class="give-license-action-link">%2$s</a>',
1032 trailingslashit( self::get_website_url() ),
1033 __( 'Access Support', 'give' )
1034 );
1035 }
1036 ?>
1037
1038 </div>
1039 </div>
1040 </div>
1041 <?php
1042 return ob_get_clean();
1043 }
1044
1045
1046 /**
1047 * Plugin row html
1048 *
1049 * @param array $plugin
1050 *
1051 * @return string
1052 * @since 2.5.0
1053 */
1054 public static function html_plugin_row( $plugin ) {
1055 // Bailout.
1056 if ( ! $plugin ) {
1057 return '';
1058 }
1059
1060 $is_license = $plugin['License'] && ! empty( $plugin['License']['license_key'] );
1061 $expires_timestamp = $is_license ? strtotime( $plugin['License']['expires'] ) : '';
1062 $is_license_expired = $is_license && ( 'expired' === $plugin['License']['license'] || $expires_timestamp < time() );
1063 ob_start();
1064 ?>
1065 <div class="give-addon-info-wrap give-clearfix">
1066
1067 <div class="give-addon-info-left">
1068 <span class="give-addon-name">
1069 <?php echo $plugin['Name']; ?>
1070 </span>
1071 <span class="give-addon-version">
1072 <?php echo sprintf( '%1$s %2$s', __( 'Version', 'give' ), $plugin['Version'] ); ?>
1073 </span>
1074 </div>
1075
1076 <div class="give-addon-info-right">
1077 <?php
1078 echo sprintf(
1079 '<a href="%1$s" class="give-ajax-modal give-addon-view-changelog" title="%3$s">%2$s</a>',
1080 give_modal_ajax_url(
1081 [
1082 'url' => filter_var( $plugin['ChangeLogSlug'], FILTER_VALIDATE_URL )
1083 ? urldecode_deep( $plugin['ChangeLogSlug'] )
1084 : urlencode_deep( give_get_addon_readme_url( $plugin['ChangeLogSlug'] ) ),
1085 'show_changelog' => 1,
1086 ]
1087 ),
1088 __( 'View Changelog', 'give' ),
1089 __( 'Changelog of', 'give' ) . " {$plugin['Name']}"
1090 );
1091 ?>
1092
1093 <?php
1094 // Activation status.
1095 if ( in_array( $plugin['Status'], [ 'active', 'inactive' ] ) ) {
1096 echo sprintf(
1097 '<span class="give-addon-activation-status give-addon-activation-status__%1$s">%1$s</span>',
1098 'active' === $plugin['Status'] ? __( 'activated', 'give' ) : __( 'installed', 'give' )
1099 );
1100 }
1101
1102 printf(
1103 '<%3$s class="give-button button button-secondary button-small" href="%1$s"%4$s><span class="dashicons dashicons-download"></span>%2$s</%3$s>',
1104 $plugin['DownloadURL'],
1105 __( 'Download', 'give' ),
1106 $is_license_expired || ! $plugin['DownloadURL'] ? 'button' : 'a',
1107 $is_license_expired || ! $plugin['DownloadURL'] ? ' disabled' : ''
1108 );
1109 ?>
1110 </div>
1111 </div>
1112 <?php
1113
1114 return ob_get_clean();
1115 }
1116
1117
1118 /**
1119 * Get refresh license status
1120 *
1121 * @return mixed|void
1122 * @since 2.5.0
1123 */
1124 public static function refresh_license_status() {
1125 return get_option(
1126 'give_licenses_refreshed_last_checked',
1127 [
1128 'compare' => date( 'Ymd' ),
1129 'time' => time(),
1130 'count' => 0,
1131 ]
1132 );
1133 }
1134
1135 /**
1136 * Get all download slugs from all access pass key.
1137 * Note: only for internal use and will be refactored in the future.
1138 *
1139 * @param array $license All access pass license data
1140 *
1141 * @return string[]
1142 * @since 2.6.3
1143 */
1144 public static function getAddonSlugsFromAllAccessPassLicense( $license ) {
1145 $result = [];
1146
1147 foreach ( $license['download'] as $download ) {
1148 $result[] = $download['plugin_slug'];
1149 }
1150
1151 return $result;
1152 }
1153
1154 /**
1155 * Returns the API URL for license requests, checking for a constant first.
1156 *
1157 * @since 3.20.0
1158 */
1159 public static function get_api_url(): string
1160 {
1161 if (defined('GIVE_LICENSE_API_URL')) {
1162 return GIVE_LICENSE_API_URL;
1163 }
1164
1165 return self::$api_url;
1166 }
1167 }
1168
1169 endif; // end class_exists check.
1170