PluginProbe
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) / 1.8.12
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) v1.8.12
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 1.7.0.9 1.8.0 All 210 releases
charitable / includes / charitable-core-functions.php

charitable-core-functions.php in Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) 1.8.12, at includes/charitable-core-functions.php

1,077 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 Core Functions.
4 *
5 * General core functions.
6 *
7 * @package Charitable/Functions/Core
8 * @author David Bisset
9 * @copyright Copyright (c) 2023, WP Charitable LLC
10 * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
11 * @since 1.0.0
12 * @version 1.6.37
13 */
14
15 // Exit if accessed directly.
16 if ( ! defined( 'ABSPATH' ) ) {
17 exit;
18 }
19
20 /**
21 * This returns the original Charitable object.
22 *
23 * Use this whenever you want to get an instance of the class. There is no
24 * reason to instantiate a new object, though you can do so if you're stubborn :)
25 *
26 * @since 1.0.0
27 *
28 * @return Charitable
29 */
30 function charitable() {
31 return Charitable::get_instance();
32 }
33
34 /**
35 * This returns the value for a particular Charitable setting.
36 *
37 * @since 1.0.0
38 *
39 * @param mixed $key Accepts an array of strings or a single string.
40 * @param mixed $default The value to return if key is not set.
41 * @param array $settings Optional. Used when $key is an array.
42 * @param mixed $original_key Optional. Original array of keys.
43 * @return mixed
44 */
45 function charitable_get_option( $key, $default = false, $settings = array(), $original_key = array() ) {
46 if ( empty( $settings ) ) {
47 $settings = get_option( 'charitable_settings' );
48 }
49
50 if ( ! is_array( $key ) ) {
51 $key = array( $key );
52 }
53
54 $current_key = current( $key );
55
56 if ( empty( $original_key ) ) {
57 $original_key = $key;
58 }
59
60 /* Key does not exist */
61 if ( ! isset( $settings[ $current_key ] ) ) {
62 return $default;
63 }
64
65 array_shift( $key );
66
67 if ( ! empty( $key ) ) {
68 return charitable_get_option( $key, $default, $settings[ $current_key ], $original_key );
69 }
70
71 /**
72 * Filter the option value.
73 *
74 * @since 1.6.37
75 *
76 * @param mixed $value The option value.
77 * @param mixed $key The key, or list of keys.
78 * @param mixed $default The default value.
79 */
80 return apply_filters( 'charitable_option_' . $current_key, $settings[ $current_key ], $original_key, $default );
81 }
82
83 /**
84 * Returns a helper class.
85 *
86 * @since 1.0.0
87 *
88 * @param string $class_key The class to get an object for.
89 * @return mixed|false
90 */
91 function charitable_get_helper( $class_key ) {
92 return charitable()->registry()->get( $class_key );
93 }
94
95 /**
96 * Returns the Charitable_Notices class instance.
97 *
98 * @since 1.0.0
99 *
100 * @return Charitable_Notices
101 */
102 function charitable_get_notices() {
103 return charitable()->registry()->get( 'notices' );
104 }
105
106 /**
107 * Returns the Charitable_Donation_Processor class instance.
108 *
109 * @since 1.0.0
110 *
111 * @return Charitable_Donation_Processor
112 */
113 function charitable_get_donation_processor() {
114 $registry = charitable()->registry();
115
116 if ( ! $registry->has( 'donation_processor' ) ) {
117 $registry->register_object( Charitable_Donation_Processor::get_instance() );
118 }
119
120 return $registry->get( 'donation_processor' );
121 }
122
123 /**
124 * Return Charitable_Locations helper class.
125 *
126 * @since 1.0.0
127 *
128 * @return Charitable_Locations
129 */
130 function charitable_get_location_helper() {
131 return charitable()->registry()->get( 'locations' );
132 }
133
134 /**
135 * Returns the current user's session object.
136 *
137 * @since 1.0.0
138 *
139 * @return Charitable_Session
140 */
141 function charitable_get_session() {
142 return charitable()->registry()->get( 'session' );
143 }
144
145 /**
146 * Returns the current request helper object.
147 *
148 * @since 1.0.0
149 *
150 * @return Charitable_Request
151 */
152 function charitable_get_request() {
153 $registry = charitable()->registry();
154
155 if ( ! $registry->has( 'request' ) ) {
156 $registry->register_object( Charitable_Request::get_instance() );
157 }
158
159 return $registry->get( 'request' );
160 }
161
162 /**
163 * Returns the Charitable_User_Dashboard object.
164 *
165 * @since 1.0.0
166 *
167 * @return Charitable_User_Dashboard
168 */
169 function charitable_get_user_dashboard() {
170 return charitable()->registry()->get( 'user_dashboard' );
171 }
172
173 /**
174 * Return the database table helper object.
175 *
176 * @since 1.0.0
177 *
178 * @param string $table The table key.
179 * @return mixed|null A child class of Charitable_DB if table exists. null otherwise.
180 */
181 function charitable_get_table( $table ) {
182 $charitable = function_exists( 'charitable' ) ? charitable() : null;
183
184 if ( empty( $charitable ) || ! is_object( $charitable ) || ! method_exists( $charitable, 'get_db_table' ) ) {
185 return null;
186 }
187
188 return $charitable->get_db_table( $table );
189 }
190
191 /**
192 * Returns the current donation form.
193 *
194 * @since 1.0.0
195 *
196 * @return Charitable_Donation_Form_Interface|false
197 */
198 function charitable_get_current_donation_form() {
199 $campaign = charitable_get_current_campaign();
200 return false === $campaign ? false : $campaign->get_donation_form();
201 }
202
203 /**
204 * Returns the provided array as a HTML element attribute.
205 *
206 * @since 1.0.0
207 *
208 * @param array $args Arguments to be added.
209 * @return string
210 */
211 function charitable_get_action_args( $args ) {
212 return sprintf( "data-charitable-args='%s'", wp_json_encode( $args ) );
213 }
214
215 /**
216 * Returns the Charitable_Deprecated class, loading the file if required.
217 *
218 * @since 1.4.0
219 *
220 * @return Charitable_Deprecated
221 */
222 function charitable_get_deprecated() {
223 $registry = charitable()->registry();
224
225 if ( ! $registry->has( 'deprecated' ) ) {
226 $registry->register_object( Charitable_Deprecated::get_instance() );
227 }
228
229 return $registry->get( 'deprecated' );
230 }
231
232 /**
233 * Returns if the check (license check or otherwise) determines if the install is "pro".
234 *
235 * @since 1.7.0
236 *
237 * @return boolean
238 */
239 function charitable_is_pro() {
240
241 if ( charitable_get_helper( 'licenses' )->is_pro() ) {
242 return true;
243 }
244
245 return false;
246 }
247
248 /**
249 * Returns if Charitable is currently using built-in Stripe Connect
250 *
251 * @since 1.7.0
252 *
253 * @return boolean
254 */
255 function charitable_using_stripe_connect() {
256
257 // the option gets written when the stripe connect in the core plugin (starting in v1.7.0) is connected in gateway settings in the admin.
258 // the option is removed when, after the stripe connect is connected, the user clicks on the "disconnect" link is clicked in the settings.
259
260 $charitable_stripe_connect = get_option( 'charitable_using_stripe_connect' );
261
262 if ( $charitable_stripe_connect ) {
263 return true;
264 }
265
266 return false;
267 }
268
269 /**
270 * Returns if Charitable is currently using built-in Square "Connect". Similar to charitable_using_stripe_connect().
271 * But the difference is that it can check for a specific mode.
272 *
273 * @since 1.8.7
274 *
275 * @param string $mode_to_check The mode to check for. Should be 'test' or 'live'. If it's sandbox, rename it to 'test'.
276 * @return boolean
277 */
278 function charitable_using_square_connect( $mode_to_check = '' ) {
279 if ( '' === $mode_to_check ) {
280 return null;
281 }
282
283 if ( charitable_is_debug( 'square' ) ) {
284 // phpcs:disable
285 error_log( 'USING AND BEING FORCED charitable_using_square_connect: ' . $mode_to_check );
286 // phpcs:enable
287 }
288
289 return true;
290 }
291
292 /**
293 * A top level fundtion to get Access Token for Square.
294 *
295 * @since 1.8.7
296 *
297 * @param string $mode The mode to get the access token for.
298 * @return string
299 */
300 function charitable_square_get_access_token( $mode = '' ) {
301 // If there is no $mode being "forced", we get the mode from the settings.
302 if ( empty( $mode ) ) {
303 $mode = charitable_get_option( 'test_mode' ) ? 'test' : 'live';
304 }
305 if ( 1 == $mode ) { // phpcs:ignore
306 $mode = 'test';
307 }
308 // Now that we have a mode, let's see if we are using Square connect or legacy settings.
309 if ( charitable_using_square_connect( $mode ) ) {
310 $square_settings = charitable_get_option( 'gateways_square' );
311 $access_token = ! empty( $square_settings[ $mode ]['access_token'] ) ? $square_settings[ $mode ]['access_token'] : '';
312 // This is an encrypted token.
313 $access_token = charitable_crypto_decrypt( $access_token );
314 } else {
315 $access_token = charitable_get_option( array( 'gateways_square', $mode, 'access_token' ) );
316 }
317 return esc_html( $access_token );
318 }
319
320 /**
321 * Get the refresh token for Square.
322 *
323 * @since 1.8.7
324 *
325 * @param string $mode The mode to get the refresh token for.
326 * @return string
327 */
328 function charitable_square_get_refresh_token( $mode = '' ) {
329 // If there is no $mode being "forced", we get the mode from the settings.
330 if ( empty( $mode ) ) {
331 $mode = charitable_get_option( 'test_mode' ) ? 'test' : 'live';
332 }
333 if ( 1 == $mode ) { // phpcs:ignore
334 $mode = 'test';
335 }
336 // Now that we have a mode, let's see if we are using Square connect or legacy settings.
337 if ( charitable_using_square_connect( $mode ) ) {
338 $square_settings = charitable_get_option( 'gateways_square' );
339 $access_token = ! empty( $square_settings[ $mode ]['refresh_token'] ) ? $square_settings[ $mode ]['refresh_token'] : '';
340 // This is an encrypted token.
341 $access_token = charitable_crypto_decrypt( $access_token );
342 } else {
343 $access_token = charitable_get_option( array( 'gateways_square', $mode, 'refresh_token' ) );
344 }
345 return esc_html( $access_token );
346 }
347
348 /**
349 * Check if Square is connected.
350 *
351 * @since 1.8.7
352 *
353 * @param string $mode The mode to check for.
354 */
355 function charitable_square_is_connected( $mode = '' ) {
356 if ( empty( $mode ) ) {
357 $mode = charitable_get_option( 'test_mode' ) ? 'test' : 'live';
358 }
359
360 return charitable_square_get_access_token( $mode ) ? true : false;
361 }
362
363 /**
364 * A top level function to get Application ID for Square.
365 *
366 * @since 1.8.7
367 *
368 * @return mixed
369 */
370 function charitable_square_get_application_id( $mode = 'test' ) {
371
372 if ( empty( $mode ) ) {
373 $mode = charitable_get_option( 'test_mode' ) ? 'test' : 'live';
374 }
375
376 if ( 'sandbox' === $mode ) {
377 $mode = 'test';
378 }
379
380 // Are we overridng with legacy settings?
381 if ( charitable_square_legacy_mode() ) {
382 $application_id = charitable_get_option( 'gateways_square', $mode . '_application_id' );
383 return $application_id['application_id'];
384 }
385
386 // Get from settings or use default.
387 $settings = charitable_get_option( 'gateways_square' );
388 $application_id = ! empty( $settings[ $mode ]['application_id'] ) ? esc_html( $settings[ $mode ]['application_id'] ) : '';
389
390 if ( empty( $application_id ) ) {
391 // Default to sandbox application ID.
392 $application_id = 'sandbox-sq0idb-xxxxxxxxxxxxxxxxxxxxxxxx';
393 }
394
395 return $application_id;
396 }
397
398 /**
399 * Returns if should load the core stripe functionality.
400 *
401 * @since 1.7.0
402 *
403 * @return boolean
404 */
405 function charitable_load_core_stripe() {
406
407 if ( false !== ( defined( 'USE_NEW_STRIPE' ) && USE_NEW_STRIPE ) ) { // phpcs:ignore
408 return true;
409 }
410
411 // check for stripe addon.
412
413 if ( in_array( 'charitable-stripe/charitable-stripe.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) { // phpcs:ignore
414 return false;
415 }
416
417 if ( class_exists( 'Charitable_Stripe' ) ) {
418 return false;
419 }
420
421 return true;
422 }
423
424 /**
425 * Returns if charitable debug should be on for an admin screen, even if the constant isn't defined/false.
426 *
427 * @since 1.7.0.2
428 *
429 * @return boolean
430 */
431 function charitable_is_admin_debug() {
432
433 if ( isset( $_GET['charitable_debug'] ) && 'true' == $_GET['charitable_debug'] ) { // phpcs:ignore
434 return true;
435 }
436
437 return false;
438 }
439
440 /**
441 * Returns if charitable is in break-cache mode, which is a mode that attempts to break cache for certain styles and scripts.
442 *
443 * @since 1.8.4.2
444 *
445 * @return boolean
446 */
447 function charitable_is_break_cache() {
448 return ( charitable_is_debug() || ( defined( 'CHARITABLE_BREAK_CACHE_STYLES' ) && CHARITABLE_BREAK_CACHE_STYLES ) ) ? true : false;
449 }
450
451 /**
452 * Returns if charitable is in debug mode, mostly by checking the constant.
453 * Supports 'vendor', 'settings', 'stripe', and 'square' modes and whatever is passed in.
454 *
455 * @since 1.8.0
456 * @version 1.8.6.1 Revisited to allow for more granular debug modes.
457 * @version 1.8.7.1 Revisited so if modes are passed in and the constant is not defined, it will return false.
458 *
459 * @param string $mode Optional. 'vendor' to check for vendor debug mode.
460 *
461 * @return boolean
462 */
463 function charitable_is_debug( $mode = '' ) {
464
465 if ( ! empty( $mode ) ) {
466 $constant = 'CHARITABLE_DEBUG_' . strtoupper( $mode );
467 if ( defined( $constant ) ) {
468 return constant( $constant ) ? true : false;
469 }
470 return false;
471 }
472
473 return ( defined( 'CHARITABLE_DEBUG' ) && CHARITABLE_DEBUG ) ? true : false; // phpcs:ignore
474 }
475
476
477 /**
478 * Returns if charitable is in script debug mode, mostly by checking the constant.
479 *
480 * @since 1.8.0
481 *
482 * @return boolean
483 */
484 function charitable_is_script_debug() {
485
486 return ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? true : false; // phpcs:ignore
487 }
488
489 /**
490 * Checks for the existence of the legacy dashboard constant.
491 *
492 * @since 1.8.1
493 *
494 * @return boolean
495 */
496 function charitable_use_legacy_dashboard() {
497
498 return ( defined( 'CHARITABLE_LEGACY_DASHBOARD' ) && CHARITABLE_LEGACY_DASHBOARD ) ? true : false;
499 }
500
501
502 /**
503 * Format, sanitize, and return/echo HTML element ID, classes, attributes,
504 * and data attributes.
505 *
506 * @since 1.3.7
507 *
508 * @param string $id HTML id attribute value.
509 * @param array $class A list of classnames for the class attribute.
510 * @param array $datas Data attributes.
511 * @param array $atts Any additional HTML attributes and their values.
512 * @param bool $echo Whether to echo the output or just return it. Defaults to return.
513 *
514 * @return string|void
515 */
516 function charitable_html_attributes( $id = '', $class = array(), $datas = array(), $atts = array(), $echo = false ) {
517
518 $id = trim( $id );
519 $parts = array();
520
521 if ( ! empty( $id ) ) {
522 $id = sanitize_html_class( $id );
523
524 if ( ! empty( $id ) ) {
525 $parts[] = 'id="' . $id . '"';
526 }
527 }
528
529 if ( ! empty( $class ) ) {
530 $class = charitable_sanitize_classes( $class, true );
531
532 if ( ! empty( $class ) ) {
533 $parts[] = 'class="' . $class . '"';
534 }
535 }
536
537 if ( ! empty( $datas ) ) {
538 foreach ( $datas as $data => $val ) {
539 $parts[] = 'data-' . sanitize_html_class( $data ) . '="' . esc_attr( $val ) . '"';
540 }
541 }
542
543 if ( ! empty( $atts ) ) {
544 foreach ( $atts as $att => $val ) {
545 if ( '0' === (string) $val || ! empty( $val ) ) {
546 if ( $att[0] === '[' ) {
547 // Handle special case for bound attributes in AMP.
548 $escaped_att = '[' . sanitize_html_class( trim( $att, '[]' ) ) . ']';
549 } else {
550 $escaped_att = sanitize_html_class( $att );
551 }
552 $parts[] = $escaped_att . '="' . esc_attr( $val ) . '"';
553 }
554 }
555 }
556
557 $output = implode( ' ', $parts );
558
559 if ( $echo ) {
560 echo trim( $output ); // phpcs:ignore
561 } else {
562 return trim( $output );
563 }
564 }
565
566
567 /**
568 * Sanitize string of CSS classes.
569 *
570 * @since 1.8.0
571 *
572 * @param array|string $classes CSS classes.
573 * @param bool $convert True will convert strings to array and vice versa.
574 *
575 * @return string|array
576 */
577 function charitable_sanitize_classes( $classes, $convert = false ) {
578
579 $array = is_array( $classes );
580 $css = array();
581
582 if ( ! empty( $classes ) ) {
583 if ( ! $array ) {
584 $classes = explode( ' ', trim( $classes ) );
585 }
586 foreach ( array_unique( $classes ) as $class ) {
587 if ( ! empty( $class ) ) {
588 $css[] = sanitize_html_class( $class );
589 }
590 }
591 }
592
593 if ( $array ) {
594 return $convert ? implode( ' ', $css ) : $css;
595 }
596
597 return $convert ? $css : implode( ' ', $css );
598 }
599
600 /**
601 * Add UTM tags to a link that allows detecting traffic sources for our or partners' websites.
602 *
603 * @since 1.7.5
604 *
605 * @param string $link Link to which you need to add UTM tags.
606 * @param string $medium The page or location description. Check your current page and try to find
607 * and use an already existing medium for links otherwise, use a page name.
608 * @param string $content The feature's name, the button's content, the link's text, or something
609 * else that describes the element that contains the link.
610 * @param string $term Additional information for the content that makes the link more unique.
611 *
612 * @return string
613 */
614 function charitable_utm_link( $link, $medium, $content = '', $term = '' ) {
615
616 return add_query_arg(
617 array_filter(
618 array(
619 'utm_campaign' => charitable_is_pro() ? 'plugin' : 'liteplugin',
620 'utm_source' => strpos( $link, 'https://wpcharitable.com' ) === 0 ? 'WordPress' : 'charitableplugin',
621 'utm_medium' => rawurlencode( $medium ),
622 'utm_content' => rawurlencode( $content ),
623 'utm_term' => rawurlencode( $term ),
624 )
625 ),
626 $link
627 );
628 }
629
630 /**
631 * Get an upgrade link.
632 *
633 * @since 1.8.0
634 *
635 * @param string $medium The page or location description.
636 * @param string $content Content.
637 *
638 * @return string
639 */
640 function charitable_admin_upgrade_link( $medium, $content = 'Upgrade+to+Pro' ) {
641
642 return charitable_utm_link( 'https://wpcharitable.com/lite-vs-pro/', $medium, $content, false );
643 }
644
645 /**
646 * Get an upgrade modal text.
647 *
648 * @since 1.8.0
649 *
650 * @param string $help_id Referrer code to pass to the help link.
651 *
652 * @return string
653 */
654 function charitable_help_link( $help_id = false ) {
655
656 if ( ! is_admin() ) {
657 return;
658 }
659
660 if ( false === $help_id ) {
661 $screen = get_current_screen();
662 if ( $screen && ! empty( $screen->base ) ) {
663
664 switch ( esc_attr( $screen->base ) ) {
665 case 'edit':
666 $help_id = 'general';
667 break;
668
669 default:
670 $help_id = 'general';
671 break;
672 }
673 }
674 }
675
676 return 'https://www.wpcharitable.com/documentation/?utm_campaign=liteplugin&utm_source=WordPress&utm_medium=help&utm_content=help-' . $help_id;
677 }
678
679 /**
680 * Get an upgrade modal text.
681 *
682 * @since 1.8.0
683 *
684 * @param string $type Either "pro" or "elite". Default is "pro".
685 *
686 * @return string
687 */
688 function charitable_get_upgrade_modal_text( $type = 'pro' ) {
689
690 switch ( $type ) {
691 case 'basic':
692 $level = 'Charitable Basic';
693 break;
694 case 'plus':
695 $level = 'Charitable Basic';
696 break;
697 case 'agency':
698 $level = 'Charitable Basic';
699 break;
700 case 'pro':
701 default:
702 $level = 'Charitable Pro';
703 }
704
705 if ( charitable_is_pro() ) {
706 return '<p>' .
707 sprintf(
708 wp_kses( /* translators: %s - WPCharitable.com contact page URL. */
709 __( 'Thank you for considering upgrading. If you have any questions, please <a href="%s" target="_blank" rel="noopener noreferrer">let us know</a>.', 'charitable' ),
710 array(
711 'a' => array(
712 'href' => array(),
713 'target' => array(),
714 'rel' => array(),
715 ),
716 )
717 ),
718 esc_url(
719 charitable_utm_link(
720 'https://wpcharitable.com/contact/',
721 'Upgrade Follow Up Modal',
722 'Contact Support'
723 )
724 )
725 ) .
726 '</p>' .
727 '<p>' .
728 wp_kses(
729 __( 'After upgrading, your license key will remain the same.<br>You may need to do a quick refresh to unlock your new addons. In your WordPress admin, go to <strong>Charitable &raquo; Settings</strong>. If you don\'t see your updated plan, click <em>refresh</em>.', 'charitable' ),
730 array(
731 'strong' => array(),
732 'br' => array(),
733 'em' => array(),
734 )
735 ) .
736 '</p>' .
737 '<p>' .
738 sprintf(
739 wp_kses( /* translators: %s - WPCharitable.com upgrade license docs page URL. */
740 __( 'Check out <a href="%s" target="_blank" rel="noopener noreferrer">our documentation</a> for step-by-step instructions.', 'charitable' ),
741 array(
742 'a' => array(
743 'href' => array(),
744 'target' => array(),
745 'rel' => array(),
746 ),
747 )
748 ),
749 'https://wpcharitable.com/docs/upgrade-charitable-license/'
750 ) .
751 '</p>';
752 }
753
754 return '<p>' .
755 sprintf(
756 wp_kses( /* translators: %s - WPCharitable.com contact page URL. */
757 __( 'If you have any questions or issues just <a href="%s" target="_blank" rel="noopener noreferrer">let us know</a>.', 'charitable' ),
758 array(
759 'a' => array(
760 'href' => array(),
761 'target' => array(),
762 'rel' => array(),
763 ),
764 )
765 ),
766 esc_url(
767 charitable_utm_link(
768 'https://wpcharitable.com/contact/',
769 'Upgrade Intention Alert',
770 'Upgrade Intention Alert'
771 )
772 )
773 ) .
774 '</p>' .
775 '<p>' .
776 sprintf(
777 wp_kses( /* translators: %s - license level, Charitable Pro or Charitable Elite. */
778 __( 'After purchasing a license, just <strong>enter your license key on the Charitable Settings page</strong>. This will let your site automatically upgrade to %s! (Don\'t worry, all your campaigns, donations and settings will be preserved.)', 'charitable' ),
779 array(
780 'strong' => array(),
781 'br' => array(),
782 )
783 ),
784 $level
785 ) .
786 '</p>' .
787 '<p>' .
788 sprintf(
789 wp_kses( /* translators: %s - WPCharitable.com upgrade from Lite to paid docs page URL. */
790 __( 'Check out <a href="%s" target="_blank" rel="noopener noreferrer">our documentation</a> for step-by-step instructions.', 'charitable' ),
791 array(
792 'a' => array(
793 'href' => array(),
794 'target' => array(),
795 'rel' => array(),
796 ),
797 )
798 ),
799 esc_url(
800 charitable_utm_link(
801 'https://wpcharitable.com/lite-vs-pro/',
802 'Upgrade Intention Alert',
803 'Upgrade Documentation'
804 )
805 )
806 ) .
807 '</p>';
808 }
809
810 /**
811 * Perform json_decode and unslash.
812 *
813 * IMPORTANT: This function decodes the result of charitable_encode() properly only if
814 * wp_insert_post() or wp_update_post() were used after the data is encoded.
815 * Both wp_insert_post() and wp_update_post() remove excessive slashes added by charitable_encode().
816 *
817 * Using charitable_decode() on charitable_encode() result directly
818 * (without using wp_insert_post() or wp_update_post() first) always returns null or false.
819 *
820 * @since 1.0.0
821 *
822 * @param string $data Data to decode.
823 *
824 * @return array|false|null
825 */
826 function charitable_decode( $data ) {
827
828 if ( ! $data || empty( $data ) ) {
829 return false;
830 }
831
832 return wp_unslash( json_decode( $data, true ) );
833 }
834
835 /**
836 * Perform json_encode and wp_slash.
837 *
838 * IMPORTANT: This function adds excessive slashes to prevent data damage
839 * by wp_insert_post() or wp_update_post() that use wp_unslash() on all the incoming data.
840 *
841 * Decoding the result of this function by charitable_decode() directly
842 * (without using wp_insert_post() or wp_update_post() first) always returns null or false.
843 *
844 * @since 1.3.1.3
845 *
846 * @param mixed $data Data to encode.
847 *
848 * @return string|false
849 */
850 function charitable_encode( $data = false ) {
851
852 if ( empty( $data ) ) {
853 return false;
854 }
855
856 return wp_slash( wp_json_encode( $data ) );
857 }
858
859 /**
860 * Decode json-encoded string if it is in json format.
861 *
862 * @since 1.7.5
863 *
864 * @param string $the_string A string.
865 * @param bool $associative Decode to the associative array if true. Decode to object if false.
866 *
867 * @return array|string
868 */
869 function charitable_json_decode( $the_string, $associative = false ) {
870
871 $the_string = html_entity_decode( $the_string );
872
873 if ( function_exists( 'charitable_is_json' ) && ! charitable_is_json( $the_string ) ) {
874 return $the_string;
875 }
876
877 return json_decode( $the_string, $associative );
878 }
879
880 /**
881 * Check permissions for currently logged in user, taken from Charitable.
882 * Both short (e.g. 'view_own_forms') or long (e.g. 'charitable_view_own_forms') capability name can be used.
883 * Only Charitable capabilities get processed.
884 *
885 * @since 1.7.0.3
886 *
887 * @param array|string $caps Capability name(s).
888 * @param int $id ID of the specific object to check against if capability is a "meta" cap. "Meta"
889 * capabilities, e.g. 'edit_post', 'edit_user', etc., are capabilities used by
890 * map_meta_cap() to map to other "primitive" capabilities, e.g. 'edit_posts',
891 * edit_others_posts', etc. Accessed via func_get_args() and passed to
892 * WP_User::has_cap(), then map_meta_cap().
893 *
894 * @return bool
895 */
896 function charitable_current_user_can( $caps = array(), $id = 0 ) {
897
898 $user_can = current_user_can( $caps, $id );
899
900 return apply_filters( 'charitable_current_user_can', $user_can, $caps, $id );
901 }
902
903 /**
904 * Get a suffix for assets, if SCRIPT_DEBUG or CHARITABLE_DEBUG are 'true' then it's blank, otherwise it's minimial (`.min`)'.
905 *
906 * @since 1.8.0
907 *
908 * @return string
909 */
910 function charitable_get_min_suffix() {
911
912 return ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) || ( charitable_is_debug() ) || ( ! charitable_is_script_minification_enabled() ) ? '' : '.min';
913 }
914
915 /**
916 * Get a version for style unqueues. If SCRIPT_DEBUG or CHARITABLE_DEBUG are 'true' then force a flush cache with time() otherwise it's the Chartiable version.
917 *
918 * @since 1.8.0
919 *
920 * @return string
921 */
922 function charitable_get_style_version() {
923 return ( charitable_is_break_cache() || ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) || ( charitable_is_debug() ) ) ? time() : charitable()->get_version();
924 }
925
926 /**
927 * User can override the minification setting via advanced settings.
928 *
929 * @since 1.8.1.9
930 *
931 * @return string
932 */
933 function charitable_is_script_minification_enabled() {
934
935 return 'scripts-enabled' === charitable_get_option( 'script_minification', 'scripts-enabled' );
936 }
937
938 /**
939 * Returns an array of screen IDs where the Charitable scripts should be loaded.
940 * Used to be get_charitable_screens() in class-charitable-admin.php.
941 *
942 * @uses charitable_admin_screens
943 *
944 * @since 1.0.0
945 *
946 * @return array
947 */
948 function charitable_get_charitable_screens() {
949 /**
950 * Filter admin screens where Charitable styles & scripts should be loaded.
951 *
952 * @since 1.8.0
953 * @version 1.8.1 Added `charitable_page_charitable-dashboard` and 'charitable_page_charitable-reports' to the list of screens.
954 * @version 1.8.1.6 Added 'charitable_page_charitable-tools' and 'charitable_page_charitable-growth-tool' to the list of screens.
955 * @version 1.8.1.15 Added to core functions, added 'charitable_page_charitable-setup-checklist' to the list of screens.
956 * @version 1.8.5 Added 'charitable_page_charitable-donors' to the list of screens.
957 *
958 * @param string[] $screens List of screen ids.
959 */
960 return apply_filters(
961 'charitable_admin_screens',
962 array(
963 'campaign',
964 'donation',
965 'charitable_page_charitable-reports',
966 'charitable_page_charitable-dashboard',
967 'charitable_page_charitable-settings',
968 'charitable_page_charitable-tools',
969 'charitable_page_charitable-growth-tools',
970 'edit-campaign',
971 'edit-donation',
972 'toplevel_page_charitable',
973 'charitable_page_charitable-addons',
974 'charitable_page_charitable-setup-checklist',
975 'charitable_page_charitable-donors',
976 'charitable_page_charitable-about',
977 'charitable_page_charitable-seo',
978 'charitable_page_charitable-smtp',
979 'charitable_page_charitable-privacy-compliance',
980 'charitable_page_charitable-backups',
981 'charitable_page_charitable-automation',
982 )
983 );
984 }
985
986 /**
987 * Determines if it's ok to show plugin notifications when the dashboard page is visited.
988 * Shouldn't do it every time, so we limit it.
989 *
990 * Returns true to show the notifications, false to not auto show them.
991 *
992 * @since 1.8.3
993 *
994 * @return bool
995 */
996 function charitable_get_autoshow_plugin_notifications() {
997
998 if ( false === ( $autoshow_plugin = get_transient( 'charitable_autoshow_plugin_notifications' ) ) ) {
999 // It wasn't there, so regenerate the data and save the transient.
1000 set_transient( 'charitable_autoshow_plugin_notifications', true, 60 * 60 ); // one hour.
1001 return true;
1002 } else {
1003 return false;
1004 }
1005 }
1006
1007 /**
1008 * Check if Square legacy mode is enabled.
1009 *
1010 * @since 1.8.7
1011 *
1012 * @return boolean
1013 */
1014 function charitable_square_legacy_mode() {
1015
1016 $settings = charitable_get_option( 'gateways_square' );
1017
1018 // Debug: Log the settings and plugin status.
1019 if ( charitable_is_debug( 'square' ) ) {
1020 // phpcs:disable
1021 error_log( '[Square Legacy Mode] Settings: ' . print_r( $settings, true ) );
1022 error_log( '[Square Legacy Mode] Plugin active: ' . ( is_plugin_active( 'charitable-square/charitable-square.php' ) ? 'true' : 'false' ) );
1023 error_log( '[Square Legacy Mode] square_legacy_settings: ' . ( isset( $settings['square_legacy_settings'] ) ? $settings['square_legacy_settings'] : 'not set' ) );
1024 // phpcs:enable
1025 }
1026
1027 // Check if the legacy Square plugin is installed and activated.
1028 if ( ! is_plugin_active( 'charitable-square/charitable-square.php' ) ) {
1029 if ( charitable_is_debug( 'square' ) ) {
1030 // phpcs:disable
1031 error_log( '[Square Legacy Mode] Returning false - plugin not active' );
1032 // phpcs:enable
1033 }
1034 return false;
1035 }
1036
1037 // Check if Square Legacy gateway is active.
1038 $active_gateways = charitable_get_helper( 'gateways' )->get_active_gateways();
1039 $square_legacy_active = isset( $active_gateways['square'] );
1040
1041 if ( charitable_is_debug( 'square' ) ) {
1042 // phpcs:disable
1043 error_log( '[Square Legacy Mode] Square Legacy gateway active: ' . ( $square_legacy_active ? 'true' : 'false' ) );
1044 // phpcs:enable
1045 }
1046
1047 // Return true if either the settings option is set OR the gateway is active.
1048 if ( ( isset( $settings['square_legacy_settings'] ) && $settings['square_legacy_settings'] ) || $square_legacy_active ) {
1049 if ( charitable_is_debug( 'square' ) ) {
1050 // phpcs:disable
1051 error_log( '[Square Legacy Mode] Returning true - settings or gateway active' );
1052 // phpcs:enable
1053 }
1054 return true;
1055 }
1056
1057 if ( charitable_is_debug( 'square' ) ) {
1058 // phpcs:disable
1059 error_log( '[Square Legacy Mode] Returning false' );
1060 // phpcs:enable
1061 }
1062 return false;
1063 }
1064
1065 /**
1066 * Check if charitable-square plugin is active.
1067 *
1068 * @since 1.8.7
1069 *
1070 * @return boolean
1071 */
1072 function charitable_is_square_addon_active() {
1073 return is_plugin_active( 'charitable-square/charitable-square.php' );
1074 }
1075
1076 require_once dirname( __FILE__ ) . '/logger/charitable-log-functions.php';
1077