PluginProbe
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) / 1.8.12.3
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) v1.8.12.3
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.12.3, at includes/admin/settings/class-charitable-licenses-settings.php

868 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
460 // Remember that legacy licenses are passed into values differently in this hook. $values[licenses_legacy].
461 foreach ( $licenses as $product_key => $license ) {
462 $license = trim( $license );
463
464 if ( empty( $license ) ) {
465 $values['licenses_legacy'][ $product_key ] = '';
466 continue;
467 }
468
469 $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.
470
471 if ( empty( $license_data ) ) {
472 continue;
473 }
474
475 $values['licenses'][ $product_key ] = $license_data; // this is ok because this follows previous versions of where the licenses would be going.
476 }
477
478 return $values;
479 }
480
481 /**
482 * Outputs the "new" license HTML for the general settings tab.
483 *
484 * @since 1.7.0.4
485 * @version 1.8.3 added charitable_is_pro() check.
486 * @version 1.8.5 added pro_connect flag.
487 *
488 * @param string $has_valid_license Allows us to control HTML based on valid license already in the system.
489 * @return string
490 */
491 public function generate_license_check_html( $has_valid_license = 'false' ) {
492
493 $slug = (string) Charitable_Addons_Directory::get_current_plan_slug();
494 $is_legacy = Charitable_Addons_Directory::is_current_plan_legacy();
495 $pro_connect = $this->is_pro_connect();
496 $readonly = false;
497 $show_license_form = true;
498
499 // PRE-VALIDATION: Check for existing valid licenses before showing upgrade prompt
500 $licenses_helper = charitable_get_helper( 'licenses' );
501 $has_stored_valid_license = false;
502
503 // Check if there's already a valid license stored (prevents duplicate prompts)
504 if ( $licenses_helper ) {
505 // Check for v3 license (newer format)
506 if ( method_exists( $licenses_helper, 'is_v3_license_valid' ) && $licenses_helper->is_v3_license_valid() ) {
507 $has_stored_valid_license = true;
508 }
509 // Check for any valid license in the system
510 elseif ( method_exists( $licenses_helper, 'has_valid_license' ) && $licenses_helper->has_valid_license( 'charitable' ) ) {
511 $has_stored_valid_license = true;
512 }
513 }
514
515 if ( $slug === false || strtolower( $slug ) === 'lite' ) {
516 $has_valid_license = $has_stored_valid_license; // Use stored license status instead of always false
517 } elseif ( charitable_is_pro() ) {
518 $has_valid_license = true;
519 }
520
521 $output = '<div id="charitable-license-message" class="license-message license-valid-' . $has_valid_license . '">';
522 if ( $has_valid_license && ! $is_legacy ) {
523 $output .= $this->get_licensed_message();
524 $readonly = 'readonly value="xxxxxxxxxxxxxxxxxxxx"';
525 } else {
526 // 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.
527 if ( charitable_is_pro() && $is_legacy ) {
528 $output .= $this->get_legacy_licensed_message();
529 $show_license_form = false;
530 } else {
531 // 1.8.5
532 if ( charitable_is_pro() ) {
533 $output .= $this->get_licensed_message();
534 $readonly = 'readonly value="xxxxxxxxxxxxxxxxxxxx"';
535 $has_valid_license = true;
536 } else {
537 $output .= $this->get_unlicensed_message();
538 }
539 }
540 }
541 if ( $show_license_form ) :
542 $output .= '<p>';
543 $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="" />';
544 if ( ! $has_valid_license ) {
545 $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>';
546 } elseif ( $has_valid_license ) {
547 $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>';
548 }
549 $output .= '</p>';
550 endif;
551
552 // Add help text to the license field.
553 $output .= '<div class="charitable-help">' . esc_html__( 'Your license key provides access to updates and addons.', 'charitable' ) . '</div>';
554
555 $output . '</div>';
556
557 return $output;
558 }
559
560 /**
561 * 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.
562 *
563 * @since 1.8.5
564 * @version 1.8.5.3
565 *
566 * @return boolean
567 */
568 public function is_pro_connect() {
569
570 if ( defined( 'CHARITABLE_FORCE_PRO_CONNECT' ) && CHARITABLE_FORCE_PRO_CONNECT ) {
571 return true;
572 }
573
574 if ( defined( 'CHARITABLE_MANUAL_LICENSE_ACTIVATION' ) && CHARITABLE_MANUAL_LICENSE_ACTIVATION ) {
575 return false;
576 }
577
578 // If the pro plugin is already installed (but not activated), then we don't need to do anything.
579 if ( file_exists( WP_PLUGIN_DIR . '/charitable-pro/charitable.php' ) ) {
580 return false;
581 }
582
583 $charitable_activated = (array) get_option( 'charitable_activated', array() );
584
585 // If pro connect has been done before, it can be done again.
586 if ( ! empty( $charitable_activated['pro_connect'] ) ) {
587 return true;
588 }
589
590 // Allows special cases to be handled by other plugins.
591 return apply_filters( 'charitable_allow_pro_connect', true );
592 }
593
594 /**
595 * Outputs a message for unlicnensed users for the general settings tab.
596 *
597 * @since 1.7.0.4
598 *
599 * @param boolean $valid Valid license.
600 * @param array $license_data Available license information.
601 * @param boolean $error Error flag.
602 * @return string
603 */
604 public function get_unlicensed_message( $valid = false, $license_data = false, $error = true ) {
605
606 $output = '<p>' . esc_html__( 'You\'re using ', 'charitable' );
607 $output .= '<strong>Charitable Lite</strong>';
608 $output .= esc_html__( ' - no license needed. Enjoy!', 'charitable' ) . ' 🙂</p>';
609 $output .=
610 '<p>' .
611 sprintf(
612 wp_kses(
613 /* translators: %s - charitable.com upgrade URL. */
614 __( 'To unlock more features consider <strong><a href="%s" target="_blank" rel="noopener noreferrer" class="charitable-upgrade-modal">upgrading to PRO</a></strong>.', 'charitable' ),
615 array(
616 'a' => array(
617 'href' => array(),
618 'class' => array(),
619 'target' => array(),
620 'rel' => array(),
621 ),
622 'strong' => array(),
623 )
624 ),
625 esc_url( charitable_pro_upgrade_url( 'settings-upgrade' ) )
626 ) .
627 '</p>';
628 $output .=
629 '<p class="discount-note">' .
630 wp_kses(
631 __( 'As a valued Charitable Lite user, you receive up to <strong>$300 off</strong>, automatically applied at checkout!', 'charitable' ),
632 array(
633 'strong' => array(),
634 'br' => array(),
635 )
636 ) .
637 '</p>';
638
639 if ( $valid && false === $error ) {
640 $output .= '<p>' . esc_html__( 'Already registered? You might have an expired or invalid license. Reach out to us for support.', 'charitable' ) . '</p>';
641 } elseif ( ! $valid && isset( $license_data['license_limit'] ) && false !== $license_data['license_limit'] ) {
642 $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>';
643 } elseif ( ! $valid && isset( $license_data['comm_success'] ) && false !== $license_data['comm_success'] ) {
644 $output .= '<p>' . esc_html__( 'There was an error attempting to contact the license server. Please try again later.', 'charitable' ) . '</p>';
645 // phpcs:disable WordPress.Security.NonceVerification.Recommended
646 } elseif ( isset( $_GET['valid'] ) && 'invalid' === sanitize_text_field( wp_unslash( $_GET['valid'] ) ) && isset( $_GET['comm_success'] ) && 0 === intval( wp_unslash( $_GET['comm_success'] ) ) ) {
647 $output .= '<p style="color:red;">' . esc_html__( 'There was an error attempting to validate your license key. Please try again later.', 'charitable' ) . '</p>';
648 } 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'] ) ) ) {
649 $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>';
650 } elseif ( isset( $_GET['valid'] ) && 'invalid' === sanitize_text_field( wp_unslash( $_GET['valid'] ) ) ) {
651 $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>';
652 // phpcs:enable WordPress.Security.NonceVerification.Recommended
653 } else {
654 $output .= '<hr><p>' . esc_html__( 'Already purchased? Simply enter your license key below to enable Charitable PRO!', 'charitable' ) . '</p>';
655 }
656
657 return $output;
658 }
659
660 /**
661 * Outputs a message for licnensed users for the general settings tab.
662 *
663 * @since 1.7.0.4
664 * @version 1.8.1.15 added license expiring message, account for no license expire date (lifetime licenses).
665 *
666 * @param boolean $force_valid Force valid license (not used).
667 * @return string
668 */
669 public function get_licensed_message( $force_valid = true ) { // phpcs:ignore
670
671 $settings = get_option( 'charitable_settings' );
672 $price_id = intval( $settings['licenses']['charitable-v2']['plan_id'] );
673 $license_expires = ! empty( $settings['licenses']['charitable-v2']['expiration_date'] ) ? esc_html( $settings['licenses']['charitable-v2']['expiration_date'] ) : false;
674 $valid = $settings['licenses']['charitable-v2']['valid'];
675 $output = '';
676
677 if ( $valid ) {
678
679 $plan_name = $this->get_license_label_from_plan_id( $price_id );
680
681 $output = '<p>' . esc_html__( 'You\'re using ', 'charitable' );
682 $output .= '<strong>Charitable ' . $plan_name . '</strong>';
683 if ( $license_expires ) :
684 if ( 'lifetime' === $license_expires ) :
685 $output .= esc_html__( '. You have a lifetime license', 'charitable' );
686 else :
687 $output .= esc_html__( '. Your license expires on ', 'charitable' );
688 $output .= gmdate( 'M d, Y', strtotime( $license_expires ) );
689 endif;
690 endif;
691 $output .= esc_html__( '. Enjoy!', 'charitable' ) . ' 🙂</p>';
692
693 if ( $this->is_license_expiring() ) {
694 $output .= '<p style="color:red;">' . sprintf(
695 wp_kses(
696 /* translators: %s - charitable.com upgrade URL. */
697 __( 'Your license may be expiring soon. Please renew to continue receiving updates and support. <a target="_blank" href="%s">Learn more</a>.', 'charitable' ),
698 array(
699 'a' => array(
700 'href' => array(),
701 'class' => array(),
702 'target' => array(),
703 'rel' => array(),
704 ),
705 'br' => array(),
706 'strong' => array(),
707 )
708 ),
709 'https://wpcharitable.com/documentation/expired-expiring-license'
710 ) . '</p>';
711 } elseif ( $this->is_license_expired() ) {
712
713 $output .= '<p style="color:red;">' . sprintf(
714 wp_kses(
715 /* translators: %s - charitable.com upgrade URL. */
716 __( 'It appears your license may have expired. Please renew to continue receiving updates and support. <a target="_blank" href="%s">Learn more</a>.', 'charitable' ),
717 array(
718 'a' => array(
719 'href' => array(),
720 'class' => array(),
721 'target' => array(),
722 'rel' => array(),
723 ),
724 'br' => array(),
725 'strong' => array(),
726 )
727 ),
728 'https://wpcharitable.com/documentation/expired-expiring-license'
729 ) . '</p>';
730 }
731
732 if ( defined( 'CHARITABLE_DEBUG_LICENSE' ) && CHARITABLE_DEBUG_LICENSE ) {
733 $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>';
734 $license_data = '';
735 foreach ( $settings['licenses'] as $key => $value ) {
736 if ( is_array( $settings['licenses'][ $key ] ) ) {
737 foreach ( $settings['licenses'][ $key ] as $k => $v ) {
738 $license_data .= '<p>' . $k . ' : ' . $v . '</p>';
739 }
740 }
741 }
742
743 $output .= '<p><strong>' . esc_html__( 'License data:', 'charitable' ) . '</strong> ' . $license_data . '</p>';
744 if ( $settings ) {
745 $output .= '<p><strong>' . esc_html__( 'Settings data:', 'charitable' ) . '</strong> ' . print_r( $settings, true ) . '</p>'; // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r
746 }
747 if ( $plan_name ) {
748 $output .= '<p><strong>' . esc_html__( 'Plan name:', 'charitable' ) . '</strong> ' . print_r( $plan_name, true ) . '</p>'; // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r
749 }
750 $output .= '</fieldset>';
751 if ( charitable_is_debug() ) {
752 error_log( 'get_licensed_message - valid' ); // phpcs:ignore
753 error_log( print_r( $settings, true ) ); // phpcs:ignore
754 error_log( print_r( $plan_name, true ) ); // phpcs:ignore
755 }
756 }
757 } else {
758 $plan_name = esc_html__( 'Lite', 'charitable' );
759 if ( intval( $price_id ) > 0 ) {
760 $valid = esc_html__( 'Your license is not valid or has expired.', 'charitable' );
761 } else {
762 $valid = false;
763 }
764 $output .= $this->get_unlicensed_message( $valid );
765 if ( defined( 'CHARITABLE_DEBUG_LICENSE' ) && CHARITABLE_DEBUG_LICENSE ) {
766 if ( charitable_is_debug() ) {
767 error_log( 'get_licensed_message - not valid' ); // phpcs:ignore
768 error_log( print_r( $valid, true ) ); // phpcs:ignore
769 }
770 }
771 }
772
773 return $output;
774 }
775
776 /**
777 * Outputs a message for deactivated licenses for the general settings tab.
778 *
779 * @since 1.8.5
780 * @return string
781 */
782 public function get_deactivated_message() {
783
784 return sprintf(
785 '<p class="charitable-license-message-details">'
786 . '<strong>' . __( 'Your license key has been removed.', 'charitable' ) . '</strong>'
787 . '</p>'
788 );
789 }
790
791 /**
792 * Get license label from plan id.
793 *
794 * @since 1.8.0
795 *
796 * @param boolean $plan_id Plan ID.
797 * @return string
798 */
799 public function get_license_label_from_plan_id( $plan_id = false ) {
800
801 return charitable_get_license_label_from_plan_id( $plan_id );
802 }
803
804 /**
805 * Outputs a message for unlicnensed users for the general settings tab.
806 *
807 * @since 1.7.0.4
808 * @version 1.8.3.2 remove upsell message.
809 * @return string
810 */
811 public function get_legacy_licensed_message() {
812
813 $output =
814 '<p>' .
815 sprintf(
816 wp_kses(
817 /* translators: %s - charitable.com upgrade URL. */
818 __( 'You\'re using <strong>Charitable</strong> with one or more <a href="%s">activated legacy licenses</a>. Enjoy! 🙂', 'charitable' ),
819 array(
820 'a' => array(
821 'href' => array(),
822 'class' => array(),
823 'target' => array(),
824 'rel' => array(),
825 ),
826 'br' => array(),
827 'strong' => array(),
828 )
829 ),
830 esc_url( admin_url( 'admin.php?page=charitable-settings&tab=advanced' ) )
831 ) .
832 '</p>';
833
834 return $output;
835 }
836
837 /**
838 * Activates the pro plugin after a license is activated.
839 *
840 * @since 1.8.5.3
841 * @return void
842 */
843 public function activate_pro_plugin_after_license_activation() {
844
845 // Check query params.
846 if ( ! isset( $_GET['valid'] ) || 'valid' !== $_GET['valid'] ) { // phpcs:ignore
847 return;
848 }
849
850 if ( ! isset( $_GET['pro'] ) || 'activate' !== $_GET['pro'] ) { // phpcs:ignore
851 return;
852 }
853 // Confirm pro plugin is installed.
854 if ( ! file_exists( WP_PLUGIN_DIR . '/charitable-pro/charitable.php' ) ) {
855 return;
856 }
857
858 // Activate the pro plugin.
859 activate_plugin( 'charitable-pro/charitable.php' );
860
861 // Redirect to the settings page.
862 wp_safe_redirect( admin_url( 'admin.php?page=charitable-settings&tab=general&valid=valid' ) );
863 exit;
864 }
865 }
866
867 endif;
868