PluginProbe
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) / 1.8.13.1
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) v1.8.13.1
1.8.13.1 1.8.13 1.8.12.3 1.8.12.2 1.8.12.1 1.8.12 1.8.11.3 1.8.11.2 1.8.11.1 1.8.11 1.6.6 1.6.60 1.6.7 1.6.8 1.6.9 1.7.0 1.7.0.1 1.7.0.11 1.7.0.12 1.7.0.14 1.7.0.2 1.7.0.3 1.7.0.5 1.7.0.6 1.7.0.7 All 212 releases
charitable / includes / admin / settings / class-charitable-licenses-settings.php

class-charitable-licenses-settings.php in Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) 1.8.13.1, at includes/admin/settings/class-charitable-licenses-settings.php

869 lines 28.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Charitable Licenses Settings UI.
4 *
5 * @package Charitable/Classes/Charitable_Licenses_Settings
6 * @version 1.8.1.12
7 * @author David Bisset
8 * @copyright Copyright (c) 2023, WP Charitable LLC
9 * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
10 */
11
12 // Exit if accessed directly.
13 if ( ! defined( 'ABSPATH' ) ) {
14 exit;
15 }
16
17 if ( ! class_exists( 'Charitable_Licenses_Settings' ) ) :
18
19 /**
20 * Charitable_Licenses_Settings
21 *
22 * @final
23 * @since 1.0.0
24 */
25 final class Charitable_Licenses_Settings {
26
27 /**
28 * The single instance of this class.
29 *
30 * @var Charitable_Licenses_Settings|null
31 */
32 private static $instance = null;
33
34 /**
35 * Create object instance.
36 *
37 * @since 1.0.0
38 */
39 private function __construct() {
40 }
41
42 /**
43 * Returns and/or create the single instance of this class.
44 *
45 * @since 1.2.0
46 *
47 * @return Charitable_Licenses_Settings
48 */
49 public static function get_instance() {
50 if ( is_null( self::$instance ) ) {
51 self::$instance = new self();
52 }
53
54 return self::$instance;
55 }
56
57 /**
58 * Optionally add the licenses tab.
59 *
60 * @since 1.4.7
61 *
62 * @param string[] $tabs Settings tabs.
63 * @return string[]
64 */
65 public function maybe_add_licenses_tab( $tabs ) {
66
67 $products = charitable_get_helper( 'licenses' )->get_products();
68
69 if ( empty( $products ) ) {
70 return $tabs;
71 }
72
73 $show_licenses_tab = apply_filters( 'charitable_show_old_license_tab', false );
74
75 if ( $show_licenses_tab ) :
76
77 $tabs = charitable_add_settings_tab(
78 $tabs,
79 'licenses',
80 __( 'Licenses', 'charitable' ),
81 array(
82 'index' => 4,
83 )
84 );
85
86 endif;
87
88 return $tabs;
89 }
90
91 /**
92 * Add the licenses tab settings fields.
93 *
94 * @since 1.0.0
95 *
96 * @return array
97 */
98 public function add_licenses_fields() {
99 if ( ! charitable_is_settings_view( 'licenses' ) ) {
100 return array();
101 }
102
103 $fields = array(
104 'section' => array(
105 'title' => '',
106 'type' => 'hidden',
107 'priority' => 10000,
108 'value' => 'licenses',
109 'save' => false,
110 ),
111 'licenses' => array(
112 'title' => false,
113 'callback' => array( $this, 'render_licenses_table' ),
114 'priority' => 4,
115 ),
116 );
117
118 foreach ( charitable_get_helper( 'licenses' )->get_products() as $key => $product ) {
119 $fields[ $key ] = array(
120 'type' => 'text',
121 'render' => false,
122 'priority' => 6,
123 );
124 }
125
126 return $fields;
127 }
128
129 /**
130 * Add the licenses group.
131 *
132 * @since 1.0.0
133 *
134 * @param string[] $groups Settings groups.
135 * @return string[]
136 */
137 public function add_licenses_group( $groups ) {
138 $groups['licenses'] = array();
139 return $groups;
140 }
141
142 /**
143 * Render the licenses table.
144 *
145 * @since 1.0.0
146 *
147 * @return void
148 */
149 public function render_licenses_table() {
150 charitable_admin_view( 'settings/licenses' );
151 }
152
153 /**
154 * Check if a license is expiring in x seconds.
155 *
156 * @since 1.8.1.12
157 *
158 * @param int $seconds The number of seconds to check for.
159 * @return bool
160 */
161 public function is_license_expiring( $seconds = 1209600 ) {
162
163 if ( $this->is_license_expired() ) {
164 return false;
165 }
166
167 // If the 'CHARITABLE_FORCE_EXPIRING_LICENSE' is defined, then return true.
168 if ( defined( 'CHARITABLE_FORCE_EXPIRING_LICENSE' ) && CHARITABLE_FORCE_EXPIRING_LICENSE ) {
169 return true;
170 }
171
172 $expire_date = $this->get_license_expire_date( 'timestamp' );
173
174 if ( false === $expire_date ) {
175 return false;
176 }
177
178 // expire_date must be a timestamp, if not then return false.
179 if ( ! is_numeric( $expire_date ) ) {
180 return false;
181 }
182
183 $current_date = time();
184 // If the license is expiring in x seconds, return true.
185 if ( $expire_date - $current_date < $seconds ) {
186 return true;
187 }
188 return false;
189 }
190
191 /**
192 * Check if a license has expired,
193 *
194 * @since 1.8.1.12
195 *
196 * @return bool
197 */
198 public function is_license_expired() {
199
200 // If the 'CHARITABLE_FORCE_EXPIRED_LICENSE' is defined, then return true. For troubleshooting.
201 if ( defined( 'CHARITABLE_FORCE_EXPIRED_LICENSE' ) && CHARITABLE_FORCE_EXPIRED_LICENSE ) {
202 return true;
203 }
204
205 $expire_date = $this->get_license_expire_date( 'timestamp' );
206
207 if ( false === $expire_date ) {
208 return false;
209 }
210
211 // expire_date must be a timestamp, if not then return false.
212 if ( ! is_numeric( $expire_date ) ) {
213 return false;
214 }
215
216 $current_date = time();
217 // If the license is expiring in x seconds, return true.
218 if ( $expire_date - $current_date < 0 ) {
219 return true;
220 }
221 return false;
222 }
223
224 /**
225 * If a license has expired, do a license request (to make sure we have the most updated informatino, especially when it comes to license renewals).
226 *
227 * @since 1.8.3.2
228 *
229 * @return void
230 */
231 public function maybe_check_if_license_expired() {
232
233 // We need to be on the settings general page, otherwise bail.
234 if ( ! charitable_is_settings_view( 'general' ) ) {
235 return;
236 }
237
238 // Determine if the license is expired.
239 if ( ! $this->is_license_expired() ) {
240 return;
241 }
242
243 // Determine when (if ever) we last checked.
244
245 $settings = get_option( 'charitable_settings' );
246 $license_settings = $settings['licenses'];
247
248 if ( false === $license_settings || false === $license_settings['charitable-v2'] || ! isset( $license_settings['checked'] ) || time() > $license_settings['checked'] ) {
249 /*
250 * Check and see if this check recently happened.
251 * If it has within the last day (and the license is still expired) then try again for a while.
252 */
253
254 if ( ! empty( $license_settings['charitable-v2']['license'] ) ) :
255
256 $license_data = charitable_get_helper( 'licenses' )->verify_license( 'charitable', esc_html( $license_settings['charitable-v2']['license'] ), true, false );
257
258 // if the license "keys" don't match, abort.
259 if ( empty( $license_data ) || ! isset( $license_data['license'] ) || $license_data['license'] !== $license_settings['charitable-v2']['license'] ) { // phpcs:ignore
260 // do nothing.
261 } else {
262 // Check the expiration_date in the license data - if it's not the same as the current expiration date, update it.
263 if ( isset( $license_data['expiration_date'] ) && $license_data['expiration_date'] !== $license_settings['charitable-v2']['expiration_date'] ) {
264 $license_settings['charitable-v2']['expiration_date'] = $license_data['expiration_date'];
265 }
266 }
267
268 endif;
269
270 // We've done the check, so update the updated time for one day in the future.
271 $license_settings['checked'] = strtotime( '+1 day' );
272 $settings['licenses'] = $license_settings;
273
274 global $wpdb;
275 // manually update the 'charitable_settings' option.
276 $wpdb->update( // phpcs:ignore
277 $wpdb->options,
278 array(
279 'option_value' => maybe_serialize( $settings ),
280 ),
281 array(
282 'option_name' => 'charitable_settings',
283 )
284 );
285
286 // redirect to the settings page.
287 wp_safe_redirect( admin_url( 'admin.php?page=charitable-settings' ) );
288 exit;
289 }
290 }
291
292 /**
293 * If a license has expired, do a license request (to make sure we have the most updated informatino, especially when it comes to license renewals).
294 *
295 * @since 1.8.3.2
296 *
297 * @return void
298 */
299 public function maybe_check_if_license_expiring() {
300
301 // We need to be on the settings general page, otherwise bail.
302 if ( ! charitable_is_settings_view( 'general' ) ) {
303 return;
304 }
305
306 // Determine if the license is expired.
307 if ( ! $this->is_license_expiring() ) {
308 return;
309 }
310
311 // Determine when (if ever) we last checked.
312
313 $settings = get_option( 'charitable_settings' );
314 $license_settings = $settings['licenses'];
315
316 if ( false === $license_settings || false === $license_settings['charitable-v2'] || ! isset( $license_settings['checked'] ) || time() > $license_settings['checked'] ) {
317 /*
318 * Check and see if this check recently happened.
319 * If it has within the last day (and the license is still expired) then try again for a while.
320 */
321
322 if ( ! empty( $license_settings['charitable-v2']['license'] ) ) :
323
324 $license_data = charitable_get_helper( 'licenses' )->verify_license( 'charitable', esc_html( $license_settings['charitable-v2']['license'] ), true, false );
325
326 // if the license "keys" don't match, abort.
327 if ( empty( $license_data ) || ! isset( $license_data['license'] ) || $license_data['license'] !== $license_settings['charitable-v2']['license'] ) { // phpcs:ignore
328 // do nothing.
329 } else {
330 // Check the expiration_date in the license data - if it's not the same as the current expiration date, update it.
331 if ( isset( $license_data['expiration_date'] ) && $license_data['expiration_date'] !== $license_settings['charitable-v2']['expiration_date'] ) {
332 $license_settings['charitable-v2']['expiration_date'] = $license_data['expiration_date'];
333 }
334 }
335
336 endif;
337
338 // We've done the check, so update the updated time for one day in the future.
339 $license_settings['checked'] = strtotime( '+1 day' );
340 $settings['licenses'] = $license_settings;
341
342 global $wpdb;
343 // manually update the 'charitable_settings' option.
344 $wpdb->update( // phpcs:ignore
345 $wpdb->options,
346 array(
347 'option_value' => maybe_serialize( $settings ),
348 ),
349 array(
350 'option_name' => 'charitable_settings',
351 )
352 );
353
354 // redirect to the settings page.
355 wp_safe_redirect( admin_url( 'admin.php?page=charitable-settings' ) );
356 exit;
357 }
358 }
359
360 /**
361 * Get the expire data of a current license (checks for "is_pro" happen before this function).
362 *
363 * @since 1.8.1.12
364 * @version 1.8.1.14 added lifetime license check.
365 *
366 * @param mixed $timestamp Whether to return a timestamp or a formatted date.
367 *
368 * @return mixed[]
369 */
370 public function get_license_expire_date( $timestamp = false ) {
371
372 $settings = get_option( 'charitable_settings' );
373
374 if ( false === $settings ) {
375 return false;
376 }
377
378 $license_key = ! empty( $settings['licenses']['charitable-v2']['license'] ) ? esc_html( $settings['licenses']['charitable-v2']['license'] ) : false;
379 $license_expires = ! empty( $settings['licenses']['charitable-v2']['expiration_date'] ) ? esc_html( $settings['licenses']['charitable-v2']['expiration_date'] ) : false;
380
381 if ( strtolower( $license_expires ) === 'lifetime' ) {
382 // make the license expire date a long time from now.
383 if ( $timestamp ) {
384 return strtotime( '+100 years' );
385 } else {
386 return date_i18n( get_option( 'date_format' ), strtotime( '+100 years' ) );
387 }
388 }
389
390 if ( false === $license_key || false === $license_expires ) {
391 return false;
392 }
393
394 if ( $timestamp ) {
395 return strtotime( $license_expires );
396 }
397
398 return date_i18n( get_option( 'date_format' ), strtotime( $license_expires ) );
399 }
400
401 /**
402 * Add an extra button to the Licenses tab to re-check licenses.
403 *
404 * @since 1.6.0
405 *
406 * @param string $button The button HTML.
407 * @return string
408 */
409 public function add_license_recheck_button( $button ) {
410 $licenses = array_filter( charitable_get_helper( 'licenses' )->get_licenses(), 'is_array' );
411
412 if ( empty( $licenses ) ) {
413 return $button;
414 }
415
416 $slug = Charitable_Addons_Directory::get_current_plan_slug();
417
418 if ( $slug === false || ( is_string( $slug ) && strtolower( $slug ) === 'lite' ) ) {
419 // there is no valid updated license so allow this button to output.
420
421 $html = '<input style="margin-left:8px;" type="submit" class="button button-secondary" name="recheck" value="' . esc_attr__( 'Save & Re-check All Licenses', 'charitable' ) . '" /></p>';
422
423 return str_replace(
424 '</p>',
425 $html,
426 $button
427 );
428
429 }
430
431 return $button;
432 }
433
434 /**
435 * Checks for updated license and invalidates status field if not set.
436 *
437 * @since 1.0.0
438 * @version 1.7.0.4
439 * @version 1.8.6.2 - clear transient _charitable_plugin_versions
440 * @version 1.8.9.1
441 *
442 * @param mixed[] $values The parsed values combining old values & new values.
443 * @param mixed[] $new_values The newly submitted values.
444 * @return mixed[]
445 */
446 public function save_license( $values, $new_values ) {
447
448 /* If we didn't just submit licenses, stop here. */
449 if ( ! isset( $new_values['licenses_legacy'] ) ) {
450 return $values;
451 }
452
453 // phpcs:ignore WordPress.Security.NonceVerification.Missing
454 $re_check = array_key_exists( 'recheck', $_POST );
455 $licenses = $new_values['licenses_legacy'];
456
457 // Delete transients (related to plugin versions).
458 delete_transient( '_charitable_plugin_versions' );
459 delete_transient( '_charitable_plugin_versions_failed' );
460
461 // Remember that legacy licenses are passed into values differently in this hook. $values[licenses_legacy].
462 foreach ( $licenses as $product_key => $license ) {
463 $license = trim( $license );
464
465 if ( empty( $license ) ) {
466 $values['licenses_legacy'][ $product_key ] = '';
467 continue;
468 }
469
470 $license_data = charitable_get_helper( 'licenses' )->verify_license( $product_key, $license, $re_check, true ); // the true added to make sure we let the server know we are attempting to vertify a legacy license.
471
472 if ( empty( $license_data ) ) {
473 continue;
474 }
475
476 $values['licenses'][ $product_key ] = $license_data; // this is ok because this follows previous versions of where the licenses would be going.
477 }
478
479 return $values;
480 }
481
482 /**
483 * Outputs the "new" license HTML for the general settings tab.
484 *
485 * @since 1.7.0.4
486 * @version 1.8.3 added charitable_is_pro() check.
487 * @version 1.8.5 added pro_connect flag.
488 *
489 * @param string $has_valid_license Allows us to control HTML based on valid license already in the system.
490 * @return string
491 */
492 public function generate_license_check_html( $has_valid_license = 'false' ) {
493
494 $slug = (string) Charitable_Addons_Directory::get_current_plan_slug();
495 $is_legacy = Charitable_Addons_Directory::is_current_plan_legacy();
496 $pro_connect = $this->is_pro_connect();
497 $readonly = false;
498 $show_license_form = true;
499
500 // PRE-VALIDATION: Check for existing valid licenses before showing upgrade prompt
501 $licenses_helper = charitable_get_helper( 'licenses' );
502 $has_stored_valid_license = false;
503
504 // Check if there's already a valid license stored (prevents duplicate prompts)
505 if ( $licenses_helper ) {
506 // Check for v3 license (newer format)
507 if ( method_exists( $licenses_helper, 'is_v3_license_valid' ) && $licenses_helper->is_v3_license_valid() ) {
508 $has_stored_valid_license = true;
509 }
510 // Check for any valid license in the system
511 elseif ( method_exists( $licenses_helper, 'has_valid_license' ) && $licenses_helper->has_valid_license( 'charitable' ) ) {
512 $has_stored_valid_license = true;
513 }
514 }
515
516 if ( $slug === false || strtolower( $slug ) === 'lite' ) {
517 $has_valid_license = $has_stored_valid_license; // Use stored license status instead of always false
518 } elseif ( charitable_is_pro() ) {
519 $has_valid_license = true;
520 }
521
522 $output = '<div id="charitable-license-message" class="license-message license-valid-' . $has_valid_license . '">';
523 if ( $has_valid_license && ! $is_legacy ) {
524 $output .= $this->get_licensed_message();
525 $readonly = 'readonly value="xxxxxxxxxxxxxxxxxxxx"';
526 } else {
527 // Getting the current plan slug might be only applicate for newer licenses, so we need to account for "legacy" licenses to see if the install is licensed or not.
528 if ( charitable_is_pro() && $is_legacy ) {
529 $output .= $this->get_legacy_licensed_message();
530 $show_license_form = false;
531 } else {
532 // 1.8.5
533 if ( charitable_is_pro() ) {
534 $output .= $this->get_licensed_message();
535 $readonly = 'readonly value="xxxxxxxxxxxxxxxxxxxx"';
536 $has_valid_license = true;
537 } else {
538 $output .= $this->get_unlicensed_message();
539 }
540 }
541 }
542 if ( $show_license_form ) :
543 $output .= '<p>';
544 $output .= '<input type="password" autocomplete="off" name="license-key" id="charitable-settings-upgrade-license-key" ' . $readonly . ' placeholder="' . esc_attr__( 'Paste license key here', 'charitable' ) . '" value="" />';
545 if ( ! $has_valid_license ) {
546 $output .= '<button data-action="verify" type="button" class="charitable-btn charitable-btn-md charitable-btn-green charitable-btn-activate" id="charitable-settings-connect-btn" data-pro-connect="' . $pro_connect . '">' . esc_html__( 'Verify Key', 'charitable' ) . '</button>';
547 } elseif ( $has_valid_license ) {
548 $output .= '<button data-action="deactivate" type="button" class="charitable-btn charitable-btn-md charitable-btn-orange charitable-btn-deactivate" id="charitable-settings-connect-btn">' . esc_html__( 'Deactivate Key', 'charitable' ) . '</button>';
549 }
550 $output .= '</p>';
551 endif;
552
553 // Add help text to the license field.
554 $output .= '<div class="charitable-help">' . esc_html__( 'Your license key provides access to updates and addons.', 'charitable' ) . '</div>';
555
556 $output . '</div>';
557
558 return $output;
559 }
560
561 /**
562 * Checks if the pro_connect flag is set. This decides if entering a license key will trigger Charitable Connect, an improved migration path to Charitable Pro.
563 *
564 * @since 1.8.5
565 * @version 1.8.5.3
566 *
567 * @return boolean
568 */
569 public function is_pro_connect() {
570
571 if ( defined( 'CHARITABLE_FORCE_PRO_CONNECT' ) && CHARITABLE_FORCE_PRO_CONNECT ) {
572 return true;
573 }
574
575 if ( defined( 'CHARITABLE_MANUAL_LICENSE_ACTIVATION' ) && CHARITABLE_MANUAL_LICENSE_ACTIVATION ) {
576 return false;
577 }
578
579 // If the pro plugin is already installed (but not activated), then we don't need to do anything.
580 if ( file_exists( WP_PLUGIN_DIR . '/charitable-pro/charitable.php' ) ) {
581 return false;
582 }
583
584 $charitable_activated = (array) get_option( 'charitable_activated', array() );
585
586 // If pro connect has been done before, it can be done again.
587 if ( ! empty( $charitable_activated['pro_connect'] ) ) {
588 return true;
589 }
590
591 // Allows special cases to be handled by other plugins.
592 return apply_filters( 'charitable_allow_pro_connect', true );
593 }
594
595 /**
596 * Outputs a message for unlicnensed users for the general settings tab.
597 *
598 * @since 1.7.0.4
599 *
600 * @param boolean $valid Valid license.
601 * @param array $license_data Available license information.
602 * @param boolean $error Error flag.
603 * @return string
604 */
605 public function get_unlicensed_message( $valid = false, $license_data = false, $error = true ) {
606
607 $output = '<p>' . esc_html__( 'You\'re using ', 'charitable' );
608 $output .= '<strong>Charitable Lite</strong>';
609 $output .= esc_html__( ' - no license needed. Enjoy!', 'charitable' ) . ' 🙂</p>';
610 $output .=
611 '<p>' .
612 sprintf(
613 wp_kses(
614 /* translators: %s - charitable.com upgrade URL. */
615 __( 'To unlock more features consider <strong><a href="%s" target="_blank" rel="noopener noreferrer" class="charitable-upgrade-modal">upgrading to PRO</a></strong>.', 'charitable' ),
616 array(
617 'a' => array(
618 'href' => array(),
619 'class' => array(),
620 'target' => array(),
621 'rel' => array(),
622 ),
623 'strong' => array(),
624 )
625 ),
626 esc_url( charitable_pro_upgrade_url( 'settings-upgrade' ) )
627 ) .
628 '</p>';
629 $output .=
630 '<p class="discount-note">' .
631 wp_kses(
632 __( 'As a valued Charitable Lite user, you receive up to <strong>$300 off</strong>, automatically applied at checkout!', 'charitable' ),
633 array(
634 'strong' => array(),
635 'br' => array(),
636 )
637 ) .
638 '</p>';
639
640 if ( $valid && false === $error ) {
641 $output .= '<p>' . esc_html__( 'Already registered? You might have an expired or invalid license. Reach out to us for support.', 'charitable' ) . '</p>';
642 } elseif ( ! $valid && isset( $license_data['license_limit'] ) && false !== $license_data['license_limit'] ) {
643 $output .= '<p>' . esc_html__( 'There was an error attempting to validate your license key. Check and see if you have exceeded your license activations.', 'charitable' ) . '</p>';
644 } elseif ( ! $valid && isset( $license_data['comm_success'] ) && false !== $license_data['comm_success'] ) {
645 $output .= '<p>' . esc_html__( 'There was an error attempting to contact the license server. Please try again later.', 'charitable' ) . '</p>';
646 // phpcs:disable WordPress.Security.NonceVerification.Recommended
647 } elseif ( isset( $_GET['valid'] ) && 'invalid' === sanitize_text_field( wp_unslash( $_GET['valid'] ) ) && isset( $_GET['comm_success'] ) && 0 === intval( wp_unslash( $_GET['comm_success'] ) ) ) {
648 $output .= '<p style="color:red;">' . esc_html__( 'There was an error attempting to validate your license key. Please try again later.', 'charitable' ) . '</p>';
649 } elseif ( isset( $_GET['valid'] ) && 'invalid' === sanitize_text_field( wp_unslash( $_GET['valid'] ) ) && isset( $_GET['license_limit'] ) && false !== sanitize_text_field( wp_unslash( $_GET['license_limit'] ) ) ) {
650 $output .= '<p style="color:red;">' . esc_html__( 'There was an error attempting to validate your license key. Check and see if you have exceeded your license activations.', 'charitable' ) . '</p>';
651 } elseif ( isset( $_GET['valid'] ) && 'invalid' === sanitize_text_field( wp_unslash( $_GET['valid'] ) ) ) {
652 $output .= '<p style="color:red;" data-invalid="Unknown">' . esc_html__( 'There was a problem attempting to validate your license key. Please try again later.', 'charitable' ) . '</p>';
653 // phpcs:enable WordPress.Security.NonceVerification.Recommended
654 } else {
655 $output .= '<hr><p>' . esc_html__( 'Already purchased? Simply enter your license key below to enable Charitable PRO!', 'charitable' ) . '</p>';
656 }
657
658 return $output;
659 }
660
661 /**
662 * Outputs a message for licnensed users for the general settings tab.
663 *
664 * @since 1.7.0.4
665 * @version 1.8.1.15 added license expiring message, account for no license expire date (lifetime licenses).
666 *
667 * @param boolean $force_valid Force valid license (not used).
668 * @return string
669 */
670 public function get_licensed_message( $force_valid = true ) { // phpcs:ignore
671
672 $settings = get_option( 'charitable_settings' );
673 $price_id = intval( $settings['licenses']['charitable-v2']['plan_id'] );
674 $license_expires = ! empty( $settings['licenses']['charitable-v2']['expiration_date'] ) ? esc_html( $settings['licenses']['charitable-v2']['expiration_date'] ) : false;
675 $valid = $settings['licenses']['charitable-v2']['valid'];
676 $output = '';
677
678 if ( $valid ) {
679
680 $plan_name = $this->get_license_label_from_plan_id( $price_id );
681
682 $output = '<p>' . esc_html__( 'You\'re using ', 'charitable' );
683 $output .= '<strong>Charitable ' . $plan_name . '</strong>';
684 if ( $license_expires ) :
685 if ( 'lifetime' === $license_expires ) :
686 $output .= esc_html__( '. You have a lifetime license', 'charitable' );
687 else :
688 $output .= esc_html__( '. Your license expires on ', 'charitable' );
689 $output .= gmdate( 'M d, Y', strtotime( $license_expires ) );
690 endif;
691 endif;
692 $output .= esc_html__( '. Enjoy!', 'charitable' ) . ' 🙂</p>';
693
694 if ( $this->is_license_expiring() ) {
695 $output .= '<p style="color:red;">' . sprintf(
696 wp_kses(
697 /* translators: %s - charitable.com upgrade URL. */
698 __( 'Your license may be expiring soon. Please renew to continue receiving updates and support. <a target="_blank" href="%s">Learn more</a>.', 'charitable' ),
699 array(
700 'a' => array(
701 'href' => array(),
702 'class' => array(),
703 'target' => array(),
704 'rel' => array(),
705 ),
706 'br' => array(),
707 'strong' => array(),
708 )
709 ),
710 'https://wpcharitable.com/documentation/expired-expiring-license'
711 ) . '</p>';
712 } elseif ( $this->is_license_expired() ) {
713
714 $output .= '<p style="color:red;">' . sprintf(
715 wp_kses(
716 /* translators: %s - charitable.com upgrade URL. */
717 __( 'It appears your license may have expired. Please renew to continue receiving updates and support. <a target="_blank" href="%s">Learn more</a>.', 'charitable' ),
718 array(
719 'a' => array(
720 'href' => array(),
721 'class' => array(),
722 'target' => array(),
723 'rel' => array(),
724 ),
725 'br' => array(),
726 'strong' => array(),
727 )
728 ),
729 'https://wpcharitable.com/documentation/expired-expiring-license'
730 ) . '</p>';
731 }
732
733 if ( defined( 'CHARITABLE_DEBUG_LICENSE' ) && CHARITABLE_DEBUG_LICENSE ) {
734 $output .= '<fieldset style="border: 1px; margin: 10px 0; padding: 10px; border-width: 10px; background-color: #eae2d3;"><legend style="border: 1px; background: white; padding: 10px;">Charitable Debug License Data</legend>';
735 $license_data = '';
736 foreach ( $settings['licenses'] as $key => $value ) {
737 if ( is_array( $settings['licenses'][ $key ] ) ) {
738 foreach ( $settings['licenses'][ $key ] as $k => $v ) {
739 $license_data .= '<p>' . $k . ' : ' . $v . '</p>';
740 }
741 }
742 }
743
744 $output .= '<p><strong>' . esc_html__( 'License data:', 'charitable' ) . '</strong> ' . $license_data . '</p>';
745 if ( $settings ) {
746 $output .= '<p><strong>' . esc_html__( 'Settings data:', 'charitable' ) . '</strong> ' . print_r( $settings, true ) . '</p>'; // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r
747 }
748 if ( $plan_name ) {
749 $output .= '<p><strong>' . esc_html__( 'Plan name:', 'charitable' ) . '</strong> ' . print_r( $plan_name, true ) . '</p>'; // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r
750 }
751 $output .= '</fieldset>';
752 if ( charitable_is_debug() ) {
753 error_log( 'get_licensed_message - valid' ); // phpcs:ignore
754 error_log( print_r( $settings, true ) ); // phpcs:ignore
755 error_log( print_r( $plan_name, true ) ); // phpcs:ignore
756 }
757 }
758 } else {
759 $plan_name = esc_html__( 'Lite', 'charitable' );
760 if ( intval( $price_id ) > 0 ) {
761 $valid = esc_html__( 'Your license is not valid or has expired.', 'charitable' );
762 } else {
763 $valid = false;
764 }
765 $output .= $this->get_unlicensed_message( $valid );
766 if ( defined( 'CHARITABLE_DEBUG_LICENSE' ) && CHARITABLE_DEBUG_LICENSE ) {
767 if ( charitable_is_debug() ) {
768 error_log( 'get_licensed_message - not valid' ); // phpcs:ignore
769 error_log( print_r( $valid, true ) ); // phpcs:ignore
770 }
771 }
772 }
773
774 return $output;
775 }
776
777 /**
778 * Outputs a message for deactivated licenses for the general settings tab.
779 *
780 * @since 1.8.5
781 * @return string
782 */
783 public function get_deactivated_message() {
784
785 return sprintf(
786 '<p class="charitable-license-message-details">'
787 . '<strong>' . __( 'Your license key has been removed.', 'charitable' ) . '</strong>'
788 . '</p>'
789 );
790 }
791
792 /**
793 * Get license label from plan id.
794 *
795 * @since 1.8.0
796 *
797 * @param boolean $plan_id Plan ID.
798 * @return string
799 */
800 public function get_license_label_from_plan_id( $plan_id = false ) {
801
802 return charitable_get_license_label_from_plan_id( $plan_id );
803 }
804
805 /**
806 * Outputs a message for unlicnensed users for the general settings tab.
807 *
808 * @since 1.7.0.4
809 * @version 1.8.3.2 remove upsell message.
810 * @return string
811 */
812 public function get_legacy_licensed_message() {
813
814 $output =
815 '<p>' .
816 sprintf(
817 wp_kses(
818 /* translators: %s - charitable.com upgrade URL. */
819 __( 'You\'re using <strong>Charitable</strong> with one or more <a href="%s">activated legacy licenses</a>. Enjoy! 🙂', 'charitable' ),
820 array(
821 'a' => array(
822 'href' => array(),
823 'class' => array(),
824 'target' => array(),
825 'rel' => array(),
826 ),
827 'br' => array(),
828 'strong' => array(),
829 )
830 ),
831 esc_url( admin_url( 'admin.php?page=charitable-settings&tab=advanced' ) )
832 ) .
833 '</p>';
834
835 return $output;
836 }
837
838 /**
839 * Activates the pro plugin after a license is activated.
840 *
841 * @since 1.8.5.3
842 * @return void
843 */
844 public function activate_pro_plugin_after_license_activation() {
845
846 // Check query params.
847 if ( ! isset( $_GET['valid'] ) || 'valid' !== $_GET['valid'] ) { // phpcs:ignore
848 return;
849 }
850
851 if ( ! isset( $_GET['pro'] ) || 'activate' !== $_GET['pro'] ) { // phpcs:ignore
852 return;
853 }
854 // Confirm pro plugin is installed.
855 if ( ! file_exists( WP_PLUGIN_DIR . '/charitable-pro/charitable.php' ) ) {
856 return;
857 }
858
859 // Activate the pro plugin.
860 activate_plugin( 'charitable-pro/charitable.php' );
861
862 // Redirect to the settings page.
863 wp_safe_redirect( admin_url( 'admin.php?page=charitable-settings&tab=general&valid=valid' ) );
864 exit;
865 }
866 }
867
868 endif;
869