PluginProbe ʕ •ᴥ•ʔ
GiveWP – Donation Plugin and Fundraising Platform / 4.7.0
GiveWP – Donation Plugin and Fundraising Platform v4.7.0
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 11 months 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 11 months ago actions.php 1 year 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 1 year ago class-give-cache.php 3 years ago class-give-cli-commands.php 1 year 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 1 year 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 1 year 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 1 year ago user-functions.php 3 years ago
class-give-license-handler.php
1171 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 <code>$license_key</code>. $reason. Please activate the license manually."
331 )->autoParagraph()->asError()->dismissible();
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 $reason = $check_license_res['error'] ?? 'The licensing server was unreachable';
351 $show_failed_activation_notice( $license, $reason );
352 continue;
353 }
354
355 if ( ! $is_plan_license) {
356 if (count($addons) > 1) {
357 $show_failed_activation_notice(
358 $license,
359 'A single add-on license cannot be used for multiple add-ons'
360 );
361 continue;
362 }
363
364 if ($check_license_res['plugin_slug'] !== $addons[0]->plugin_dirname) {
365 $show_failed_activation_notice(
366 $license,
367 'The license is not valid for this add-on'
368 );
369 continue;
370 }
371 }
372
373 $activate_license_res = self::request_license_api(
374 [
375 'edd_action' => 'activate_license',
376 'item_name' => $check_license_res['item_name'],
377 'license' => $license,
378 ],
379 true
380 );
381
382 if (is_wp_error($activate_license_res)) {
383 $show_failed_activation_notice($license, $activate_license_res->get_error_message());
384 continue;
385 }
386
387 $check_license_res['license'] = $activate_license_res['license'];
388 $check_license_res['site_count'] = $activate_license_res['site_count'];
389 $check_license_res['activations_left'] = $activate_license_res['activations_left'];
390 $licenses = get_option('give_licenses', []);
391
392 if ($is_plan_license) {
393 $addonSlugs = self::getAddonSlugsFromAllAccessPassLicense($check_license_res);
394 foreach ($licenses as $license_key => $data) {
395 if (in_array($data['plugin_slug'], $addonSlugs, true) || ! empty($data['is_all_access_pass'])) {
396 unset($licenses[$license_key]);
397 }
398 }
399 }
400
401 $licenses[$check_license_res['license_key']] = $check_license_res;
402 update_option('give_licenses', $licenses);
403 }
404
405 // Have WordPress check for updates
406 give_refresh_licenses();
407 }
408
409 /**
410 * Activate License
411 *
412 * Activate the license key.
413 *
414 * @access public
415 * @return void
416 * @since 1.0
417 */
418 public function activate_license() {
419 }
420
421 /**
422 * Deactivate License
423 *
424 * Deactivate the license key.
425 *
426 * @access public
427 * @return void
428 * @since 1.0
429 */
430 public function deactivate_license() {
431 }
432
433
434 /**
435 * Get license information.
436 *
437 * @param string $edd_action
438 * @param bool $response_in_array
439 *
440 * @return mixed
441 * @deprecated 2.5.0 Use self::request_license_api instead.
442 *
443 * @since 1.8.9
444 * @access public
445 */
446 public function get_license_info($edd_action = '', $response_in_array = false)
447 {
448 if ( empty($edd_action) ) {
449 return false;
450 }
451
452 give_doing_it_wrong(__FUNCTION__, 'Use self::request_license_api instead from GiveWP 2.5.0');
453
454 // Data to send to the API.
455 $api_params = [
456 'edd_action' => $edd_action, // never change from "edd_" to "give_"!
457 'license' => $this->license,
458 'item_name' => urlencode($this->item_name),
459 ];
460
461 return self::request_license_api($api_params, $response_in_array);
462 }
463
464 /**
465 * Return licensed addons info
466 *
467 * Note: note only for internal logic
468 *
469 * @since 3.21.1 use array_map to safely access the private property
470 * @since 3.21.0 plucks the basename for backwards compatibility
471 * @since 2.1.4
472 * @return string[]
473 */
474 static function get_licensed_addons(): array
475 {
476 return array_map( static function ( Give_License $license ) {
477 return $license->plugin_basename;
478 }, self::$licensed_addons );
479 }
480
481 /**
482 * Check if license key attached to subscription
483 *
484 * @since 2.5.0
485 *
486 * @param string $license_key
487 *
488 * @return array
489 */
490 static function is_subscription($license_key = '')
491 {
492 // Check if current license is part of subscription or not.
493 $subscriptions = get_option('give_subscriptions');
494 $subscription = [];
495
496 if ( $subscriptions ) {
497 foreach ($subscriptions as $subs) {
498 if ( in_array($license_key, $subs['licenses']) ) {
499 $subscription = $subs;
500 break;
501 }
502 }
503 }
504
505 return $subscription;
506 }
507
508 /**
509 * Get license information.
510 *
511 * @since 1.8.9
512 * @since 2.18.0 log failed license api request information
513 *
514 * @param bool $response_in_array
515 *
516 * @param array $api_params
517 *
518 * @return array|WP_Error
519 */
520 public static function request_license_api($api_params = [], $response_in_array = false)
521 {
522 // Bailout.
523 if ( empty($api_params['edd_action']) ) {
524 return new WP_Error('give-invalid-edd-action', __('Valid edd_action not defined', 'give'));
525 }
526
527 // Data to send to the API.
528 $default_api_params = [
529 // 'edd_action' => $edd_action, never change from "edd_" to "give_"!
530 // 'license' => $this->license,
531 // 'item_name' => urlencode( $this->item_name ),
532 'url' => home_url(),
533 ];
534
535 $api_params = wp_parse_args($api_params, $default_api_params);
536
537 // Call the API.
538 $response = wp_remote_post(
539 self::get_api_url(),
540 apply_filters(
541 'give_request_license_api_args',
542 [
543 'timeout' => 15,
544 'sslverify' => false,
545 'body' => $api_params,
546 ]
547 )
548 );
549
550 $statusCode = wp_remote_retrieve_response_code($response);
551 $body = json_decode(wp_remote_retrieve_body($response), $response_in_array);
552
553 if ( 200 !== $statusCode ) {
554 Log::http(
555 'License Api request failed',
556 [
557 'category' => 'License',
558 'api url' => self::get_api_url(),
559 'request' => $api_params,
560 'status code' => $statusCode,
561 'response' => $response
562 ]
563 );
564 }
565
566 // Make sure there are no errors.
567 if ( is_wp_error($response) ) {
568 return $response;
569 }
570
571 return $body;
572 }
573
574 /**
575 * Get license by plugin dirname
576 *
577 * @param string $plugin_dirname
578 *
579 * @return array
580 *
581 * @since 2.5.0
582 * @access public
583 */
584 public static function get_license_by_plugin_dirname( $plugin_dirname ) {
585 $license = [];
586 $give_licenses = get_option( 'give_licenses', [] );
587
588 if ( ! empty( $give_licenses ) ) {
589 foreach ( $give_licenses as $give_license ) {
590
591 // Logic to match all access pass license to add-on.
592 $compares = $give_license['is_all_access_pass']
593 ? $give_license['download']
594
595 // Prevent PHP notice if somehow automatic update does not run properly.
596 // Because plugin_slug will only define in updated license rest api response.
597 : [ [ 'plugin_slug' => ! empty( $give_license['plugin_slug'] ) ? $give_license['plugin_slug'] : '' ] ];
598
599 foreach ( $compares as $compare ) {
600 if ( ! empty( $compare['plugin_slug'] ) && $plugin_dirname === $compare['plugin_slug'] ) {
601 $license = $give_license;
602 break;
603 }
604 }
605 }
606 }
607
608 return $license;
609 }
610
611
612 /**
613 * Get checkout url
614 *
615 * @return string|null
616 * @since 2.5.0
617 */
618 public static function get_checkout_url() {
619 return self::$checkout_url;
620 }
621
622 /**
623 * Get account url
624 *
625 * @return string|null
626 * @since 2.5.0
627 */
628 public static function get_account_url() {
629 return self::$account_url;
630 }
631
632 /**
633 * Get downloads url
634 *
635 * @return string|null
636 * @since 2.5.0
637 */
638 public static function get_downloads_url() {
639 return self::$downloads_url;
640 }
641
642 /**
643 * Get account url
644 *
645 * @since 3.20.0 allows to override the API URL via constant
646 * @since 2.5.0
647 */
648 public static function get_website_url(): ?string
649 {
650 if (defined('GIVE_SITE_URL')) {
651 return GIVE_SITE_URL;
652 }
653
654 return self::$site_url;
655 }
656
657
658 /**
659 * Get plugin information by id.
660 * Note: only for internal use
661 *
662 * @param string $plugin_slug
663 *
664 * @return array
665 * @since 2.5.0
666 */
667 public static function get_plugin_by_slug( $plugin_slug ) {
668 $give_plugins = give_get_plugins();
669 $matching_list = wp_list_pluck( $give_plugins, 'Dir', 'Path' );
670 $is_match_found = array_search( $plugin_slug, $matching_list, true );
671
672 return $is_match_found ? $give_plugins[ $is_match_found ] : [];
673 }
674
675 /**
676 * Get plugin information by id.
677 * Note: only for internal use
678 *
679 * @param string $plugin_slug
680 *
681 * @return string
682 * @since 2.5.0
683 */
684 public static function build_plugin_name_from_slug( $plugin_slug ) {
685 $plugin_name = str_replace( [ '-', 'give ' ], [ ' ', 'Give - ' ], $plugin_slug );
686
687 return ucwords( $plugin_name );
688 }
689
690 /**
691 * Render license section
692 *
693 * @return string
694 * @since 2.5.0
695 */
696 public static function render_licenses_list() {
697 $give_plugins = give_get_plugins( [ 'only_premium_add_ons' => true ] );
698 $give_licenses = get_option( 'give_licenses', [] );
699 $licenses_without_addon = $give_licenses;
700
701 // Get all access pass licenses
702 $all_access_pass_licenses = [];
703 $all_access_pass_addon_list = [];
704 foreach ( $give_licenses as $key => $give_license ) {
705 if ( $give_license['is_all_access_pass'] ) {
706 $all_access_pass_licenses[ $key ] = $give_license;
707
708 unset( $licenses_without_addon[ $key ] );
709
710 foreach ( $give_license['download'] as $download ) {
711 $all_access_pass_addon_list[] = $download['plugin_slug'];
712 }
713 }
714 }
715
716 $html = [
717 'unlicensed' => '',
718 'licensed' => '',
719 'licenses_without_addon' => '',
720 'all_access_licensed' => '',
721 ];
722
723 if ( ! empty( $give_plugins ) ) {
724 foreach ( $give_plugins as $give_plugin ) {
725 if ( in_array( $give_plugin['Dir'], $all_access_pass_addon_list ) ) {
726 continue;
727 }
728
729 $addon_license = self::get_license_by_plugin_dirname( $give_plugin['Dir'] );
730 $html_arr_key = 'unlicensed';
731
732 if ( $addon_license ) {
733 $html_arr_key = 'licensed';
734 unset( $licenses_without_addon[ $addon_license['license_key'] ] );
735 }
736
737 $html[ "{$html_arr_key}" ] .= self::html_by_plugin( $give_plugin );
738 }
739 }
740
741 if ( ! empty( $all_access_pass_licenses ) ) {
742 foreach ( $all_access_pass_licenses as $key => $all_access_pass_license ) {
743 $html['all_access_licensed'] .= self::html_by_license( $all_access_pass_license );
744 }
745 }
746
747 if ( ! empty( $licenses_without_addon ) ) {
748 foreach ( $licenses_without_addon as $key => $license ) {
749 if ( in_array( $license['plugin_slug'], $all_access_pass_addon_list ) ) {
750 continue;
751 }
752 $html['licenses_without_addon'] .= self::html_by_license( $license );
753 }
754 }
755
756 ksort( $html );
757
758 // After sorting order will be all_access_licensed -> licensed -> unlicensed
759
760 return implode( '', $html );
761 }
762
763 /**
764 * Get add-on item html
765 * Note: only for internal use
766 *
767 * @param $plugin
768 *
769 * @return string
770 * @since 2.5.0
771 */
772 public static function html_by_plugin( $plugin ) {
773 // Bailout.
774 if ( empty( $plugin ) ) {
775 return '';
776 }
777
778 ob_start();
779 $license = self::get_license_by_plugin_dirname( $plugin['Dir'] );
780
781 $default_plugin = [
782 'ChangeLogSlug' => $plugin['Dir'],
783 'DownloadURL' => '',
784 ];
785
786 if ( false !== strpos( $default_plugin['ChangeLogSlug'], '-gateway' ) ) {
787 // We found that each gateway addon does not have `-gateway` in changelog file slug
788 $default_plugin['ChangeLogSlug'] = str_replace( '-gateway', '', $default_plugin['ChangeLogSlug'] );
789 }
790
791 if ( $license ) {
792 $license['renew_url'] = self::$checkout_url . "?edd_license_key={$license['license_key']}";
793 $default_plugin['ChangeLogSlug'] = $license['readme'];
794 $default_plugin['DownloadURL'] = $license['download'];
795 }
796
797 $plugin['License'] = $license = wp_parse_args(
798 $license,
799 [
800 'item_name' => str_replace( 'give-', '', $plugin['Dir'] ),
801 'purchase_link' => $plugin['PluginURI'],
802 ]
803 );
804
805 $plugin = wp_parse_args( $plugin, $default_plugin );
806 ?>
807 <div class="give-addon-wrap">
808 <div class="give-addon-inner">
809 <?php echo self::html_license_row( $license, $plugin ); ?>
810 <?php echo self::html_plugin_row( $plugin ); ?>
811 </div>
812 </div>
813 <?php
814
815 return ob_get_clean();
816 }
817
818 /**
819 * Get add-on item html
820 * Note: only for internal use
821 *
822 * @param array $license
823 *
824 * @return string
825 * @since 2.5.0
826 */
827 private static function html_by_license( $license ) {
828 ob_start();
829
830 $license['renew_url'] = self::$checkout_url . "?edd_license_key={$license['license_key']}";
831 ?>
832 <div class="give-addon-wrap">
833 <div class="give-addon-inner">
834 <?php
835 echo self::html_license_row( $license );
836
837 $addons = $license['download'];
838
839 if ( empty( $license['is_all_access_pass'] ) ) {
840 $addons = [ $license ];
841 }
842
843 foreach ( $addons as $addon ) {
844 $default_plugin = [
845 // In single license key we will get item_name instead of name.
846 'Name' => ! empty( $addon['item_name'] ) ? $addon['item_name'] : $addon['name'],
847
848 'ChangeLogSlug' => $addon['readme'],
849 'Version' => $addon['current_version'],
850 'Status' => 'not installed',
851
852 // In single license key we will get download instead of file.
853 'DownloadURL' => ! empty( $addon['download'] ) ? $addon['download'] : $addon['file'],
854
855 ];
856
857 $plugin = wp_parse_args(
858 self::get_plugin_by_slug( $addon['plugin_slug'] ),
859 $default_plugin
860 );
861
862 $plugin['Name'] = false !== strpos( $plugin['Name'], 'Give' )
863 ? $plugin['Name']
864 : self::build_plugin_name_from_slug( $addon['plugin_slug'] );
865
866 $plugin['License'] = $license;
867
868 echo self::html_plugin_row( $plugin );
869 }
870 ?>
871 </div>
872 </div>
873 <?php
874
875 return ob_get_clean();
876 }
877
878
879 /**
880 * license row html
881 *
882 * @param array $license
883 * @param array $plugin
884 *
885 * @return string
886 * @since 2.5.0
887 */
888 private static function html_license_row( $license, $plugin = [] ) {
889 ob_start();
890
891 $is_license = $license && ! empty( $license['license_key'] );
892 $license_key = $is_license ? $license['license_key'] : '';
893 $license_is_inactive = $license_key && ! in_array( $license['license'], [ 'valid', 'expired' ] );
894 $expires_timestamp = $is_license ? strtotime( $license['expires'] ) : '';
895 $is_license_expired = $is_license && ( 'expired' === $license['license'] || $expires_timestamp < time() );
896 $addon_dir = ! empty( $plugin['Dir'] ) ? $plugin['Dir'] : ( ! empty( $license['plugin_slug'] ) ? $license['plugin_slug'] : '' );
897 ?>
898 <div class="give-license-row give-clearfix">
899 <div class="give-license-notice-container"></div>
900 <div class="give-license-top give-clearfix">
901
902 <div class="give-license-top-column give-license-key-field-wrap">
903
904 <div class="give-license__key<?php echo $license_key ? ' give-has-license-key' : ''; ?>">
905 <?php $value = $license_key ? give_hide_char( $license['license_key'], 5 ) : ''; ?>
906 <label for="give-license-addon-key-field" class="give-license-top-header"><?php _e( 'License Key', 'give' ); ?></label>
907 <input id="give-license-addon-key-field" type="text" autocomplete="off" value="<?php echo $value; ?>"<?php echo $value ? ' readonly' : ''; ?>>
908 <?php if ( ! $license_key ) : ?>
909 <button class="give-button__license-activate button-primary" data-addon="<?php echo $addon_dir; ?>">
910 <?php _e( 'Activate', 'give' ); ?>
911 </button>
912 <?php elseif ( $license_is_inactive ) : ?>
913 <button class="give-button__license-reactivate button-primary" data-addon="<?php echo $addon_dir; ?>" data-license="<?php echo $license['license_key']; ?>">
914 <?php _e( 'Reactivate', 'give' ); ?>
915 </button>
916 <?php else : ?>
917
918 <?php
919 echo sprintf(
920 '<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>',
921 __( 'Deactivate', 'give' ),
922 $license['license_key'],
923 $license['item_name'],
924 wp_create_nonce( "give-deactivate-license-{$license['item_name']}" ),
925 ! empty( $license['plugin_slug'] ) ? $license['plugin_slug'] : ''
926 );
927 ?>
928
929 <?php endif; ?>
930
931 <div class="give-license__status">
932 <?php
933 echo $license_key && ! $license_is_inactive
934 ? sprintf(
935 '<span class="dashicons dashicons-%2$s"></span>&nbsp;%1$s',
936 $is_license_expired
937 ? __( 'License is expired. Please activate your license key.', 'give' )
938 : __( 'License is active and you are receiving updates and support.', 'give' ),
939 $is_license_expired
940 ? 'no'
941 : 'yes'
942 )
943 : sprintf(
944 '<span class="dashicons dashicons-no"></span> %1$s %2$s',
945 __( 'License is inactive.', 'give' ),
946 $license_is_inactive
947 ? sprintf(
948 __( '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' ),
949 self::get_account_url()
950 )
951 : __( 'Please activate your license key.', 'give' )
952 );
953 ?>
954 </div>
955 </div>
956 </div>
957
958 <div class="give-license-top-column give-license-info-field-wrap">
959 <h3 class="give-license-top-header"><?php _e( 'License Information', 'give' ); ?></h3>
960 <?php
961 // @todo: handle all license status;
962 if ( $license_key ) :
963 ?>
964
965 <?php if ( $license_key ) : ?>
966 <?php
967 echo sprintf(
968 '<p class="give-license-renewal-date"><span class="dashicons dashicons-calendar-alt"></span> <strong>%1$s</strong> %2$s</p>',
969 $is_license_expired ? __( 'Expired:', 'give' ) : __( 'Renews:', 'give' ),
970 date( give_date_format(), $expires_timestamp )
971 );
972 ?>
973 <?php endif; ?>
974
975 <?php
976 if ( $is_license_expired ) {
977 // @todo: need to test renew license link
978 echo sprintf(
979 '<a href="%1$s" target="_blank">%2$s</a>',
980 $license['renew_url'],
981 __( 'Renew to manage sites', 'give' )
982 );
983 } elseif ( $license_key ) {
984 if ( ! $license['activations_left'] ) {
985 echo sprintf(
986 '<span class="give-license-activations-left">%1$s</span>',
987 __( 'No activations remaining', 'give' )
988 );
989 } else {
990 echo sprintf(
991 '<span class="give-license-activations-left"><span class="give-license-activations-remaining-icon wp-ui-highlight">%1$s</span> %2$s</span>',
992 $license['activations_left'],
993 _n( 'Activation Remaining', 'Activations Remaining', $license['activations_left'], 'give' )
994 );
995 }
996 }
997 ?>
998 <?php else : ?>
999
1000 <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>
1001
1002 <?php endif; ?>
1003 </div>
1004
1005 <div class="give-license-top-column">
1006 <h3 class="give-license-top-header"><?php _e( 'License Actions', 'give' ); ?></h3>
1007
1008 <?php
1009 // Purchase license link.
1010 if ( ! $license_key ) :
1011 ?>
1012 <?php
1013 echo sprintf(
1014 '<a class="give-button button-secondary" href="%1$s" target="_blank">%2$s</a>',
1015 $license['purchase_link'],
1016 __( 'Purchase License', 'give' )
1017 );
1018 ?>
1019 <?php endif; ?>
1020
1021 <?php
1022 // Manage license link on GiveWP.com
1023 if ( ! $is_license_expired && $license_key ) {
1024 echo sprintf(
1025 '<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>',
1026 trailingslashit( self::get_website_url() ),
1027 $license['license_id'],
1028 $license['payment_id'],
1029 __( 'Manage License', 'give' )
1030 );
1031 echo sprintf(
1032 '<a href="%1$spriority-support/" target="_blank" class="give-license-action-link">%2$s</a>',
1033 trailingslashit( self::get_website_url() ),
1034 __( 'Access Support', 'give' )
1035 );
1036 }
1037 ?>
1038
1039 </div>
1040 </div>
1041 </div>
1042 <?php
1043 return ob_get_clean();
1044 }
1045
1046
1047 /**
1048 * Plugin row html
1049 *
1050 * @param array $plugin
1051 *
1052 * @return string
1053 * @since 2.5.0
1054 */
1055 public static function html_plugin_row( $plugin ) {
1056 // Bailout.
1057 if ( ! $plugin ) {
1058 return '';
1059 }
1060
1061 $is_license = $plugin['License'] && ! empty( $plugin['License']['license_key'] );
1062 $expires_timestamp = $is_license ? strtotime( $plugin['License']['expires'] ) : '';
1063 $is_license_expired = $is_license && ( 'expired' === $plugin['License']['license'] || $expires_timestamp < time() );
1064 ob_start();
1065 ?>
1066 <div class="give-addon-info-wrap give-clearfix">
1067
1068 <div class="give-addon-info-left">
1069 <span class="give-addon-name">
1070 <?php echo $plugin['Name']; ?>
1071 </span>
1072 <span class="give-addon-version">
1073 <?php echo sprintf( '%1$s %2$s', __( 'Version', 'give' ), $plugin['Version'] ); ?>
1074 </span>
1075 </div>
1076
1077 <div class="give-addon-info-right">
1078 <?php
1079 echo sprintf(
1080 '<a href="%1$s" class="give-ajax-modal give-addon-view-changelog" title="%3$s">%2$s</a>',
1081 give_modal_ajax_url(
1082 [
1083 'url' => filter_var( $plugin['ChangeLogSlug'], FILTER_VALIDATE_URL )
1084 ? urldecode_deep( $plugin['ChangeLogSlug'] )
1085 : urlencode_deep( give_get_addon_readme_url( $plugin['ChangeLogSlug'] ) ),
1086 'show_changelog' => 1,
1087 ]
1088 ),
1089 __( 'View Changelog', 'give' ),
1090 __( 'Changelog of', 'give' ) . " {$plugin['Name']}"
1091 );
1092 ?>
1093
1094 <?php
1095 // Activation status.
1096 if ( in_array( $plugin['Status'], [ 'active', 'inactive' ] ) ) {
1097 echo sprintf(
1098 '<span class="give-addon-activation-status give-addon-activation-status__%1$s">%1$s</span>',
1099 'active' === $plugin['Status'] ? __( 'activated', 'give' ) : __( 'installed', 'give' )
1100 );
1101 }
1102
1103 printf(
1104 '<%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>',
1105 $plugin['DownloadURL'],
1106 __( 'Download', 'give' ),
1107 $is_license_expired || ! $plugin['DownloadURL'] ? 'button' : 'a',
1108 $is_license_expired || ! $plugin['DownloadURL'] ? ' disabled' : ''
1109 );
1110 ?>
1111 </div>
1112 </div>
1113 <?php
1114
1115 return ob_get_clean();
1116 }
1117
1118
1119 /**
1120 * Get refresh license status
1121 *
1122 * @return mixed|void
1123 * @since 2.5.0
1124 */
1125 public static function refresh_license_status() {
1126 return get_option(
1127 'give_licenses_refreshed_last_checked',
1128 [
1129 'compare' => date( 'Ymd' ),
1130 'time' => time(),
1131 'count' => 0,
1132 ]
1133 );
1134 }
1135
1136 /**
1137 * Get all download slugs from all access pass key.
1138 * Note: only for internal use and will be refactored in the future.
1139 *
1140 * @param array $license All access pass license data
1141 *
1142 * @return string[]
1143 * @since 2.6.3
1144 */
1145 public static function getAddonSlugsFromAllAccessPassLicense( $license ) {
1146 $result = [];
1147
1148 foreach ( $license['download'] as $download ) {
1149 $result[] = $download['plugin_slug'];
1150 }
1151
1152 return $result;
1153 }
1154
1155 /**
1156 * Returns the API URL for license requests, checking for a constant first.
1157 *
1158 * @since 3.20.0
1159 */
1160 public static function get_api_url(): string
1161 {
1162 if (defined('GIVE_LICENSE_API_URL')) {
1163 return GIVE_LICENSE_API_URL;
1164 }
1165
1166 return self::$api_url;
1167 }
1168 }
1169
1170 endif; // end class_exists check.
1171