PluginProbe
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) / 1.8.13
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) v1.8.13
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 1.7.0.9 All 211 releases
← All changes | includes/charitable-core-functions.php +821 -10 1.7.0.2 → 1.8.13 View file →
@@ -5,12 +5,12 @@
5 5 * General core functions.
6 6 *
7 7 * @package Charitable/Functions/Core
8 8 * @author David Bisset
9 - * @copyright Copyright (c) 2022, WP Charitable LLC
9 + * @copyright Copyright (c) 2023, WP Charitable LLC
10 10 * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
11 11 * @since 1.0.0
12 - * @version 1.6.37
12 + * @version 1.8.12.4
13 13 */
14 14
15 15 // Exit if accessed directly.
16 16 if ( ! defined( 'ABSPATH' ) ) {
@@ -178,9 +178,15 @@
178 178 * @param string $table The table key.
179 179 * @return mixed|null A child class of Charitable_DB if table exists. null otherwise.
180 180 */
181 181 function charitable_get_table( $table ) {
182 - return charitable()->get_db_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 );
183 189 }
184 190
185 191 /**
186 192 * Returns the current donation form.
@@ -202,9 +208,9 @@
202 208 * @param array $args Arguments to be added.
203 209 * @return string
204 210 */
205 211 function charitable_get_action_args( $args ) {
206 - return sprintf( "data-charitable-args='%s'", json_encode( $args ) );
212 + return sprintf( "data-charitable-args='%s'", wp_json_encode( $args ) );
207 213 }
208 214
209 215 /**
210 216 * Returns the Charitable_Deprecated class, loading the file if required.
@@ -236,9 +242,8 @@
236 242 return true;
237 243 }
238 244
239 245 return false;
240 -
241 246 }
242 247
243 248 /**
244 249 * Returns if Charitable is currently using built-in Stripe Connect
@@ -258,12 +263,140 @@
258 263 return true;
259 264 }
260 265
261 266 return false;
267 +}
262 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;
263 290 }
264 291
265 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 +/**
266 399 * Returns if should load the core stripe functionality.
267 400 *
268 401 * @since 1.7.0
269 402 *
@@ -270,15 +403,15 @@
270 403 * @return boolean
271 404 */
272 405 function charitable_load_core_stripe() {
273 406
274 - if ( false !== ( defined( 'USE_NEW_STRIPE' ) && USE_NEW_STRIPE ) ) {
407 + if ( false !== ( defined( 'USE_NEW_STRIPE' ) && USE_NEW_STRIPE ) ) { // phpcs:ignore
275 408 return true;
276 409 }
277 410
278 - // check for stripe addon
411 + // check for stripe addon.
279 412
280 - if ( in_array('charitable-stripe/charitable-stripe.php', apply_filters( 'active_plugins', get_option('active_plugins' ) ) ) ) {
413 + if ( in_array( 'charitable-stripe/charitable-stripe.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) { // phpcs:ignore
281 414 return false;
282 415 }
283 416
284 417 if ( class_exists( 'Charitable_Stripe' ) ) {
@@ -296,11 +429,689 @@
296 429 * @return boolean
297 430 */
298 431 function charitable_is_admin_debug() {
299 432
300 - if ( isset( $_GET['charitable_debug'] ) && 'true' == $_GET['charitable_debug'] ) {
433 + if ( isset( $_GET['charitable_debug'] ) && 'true' == $_GET['charitable_debug'] ) { // phpcs:ignore
301 434 return true;
302 435 }
303 436
304 437 return false;
438 +}
305 439
306 -}
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 +/**
1077 + * Whether the current visitor may upload through a picture field.
1078 + *
1079 + * Anonymous file writes are off unless a site explicitly opts in. This lives in one place
1080 + * so the AJAX handler and the picture field template cannot drift apart: a form that draws
1081 + * a working uploader must be a form whose uploads the endpoint will actually accept.
1082 + *
1083 + * @since 1.8.12.4
1084 + *
1085 + * @param string $field_id The picture field's key, where known.
1086 + * @param int $post_id The parent post the field uploads against, where known.
1087 + * @return boolean
1088 + */
1089 +function charitable_picture_uploads_enabled( $field_id = '', $post_id = 0 ) {
1090 + if ( is_user_logged_in() ) {
1091 + return true;
1092 + }
1093 +
1094 + /*
1095 + * Ambassadors has exposed charitable_ambassadors_allow_anonymous_photo_uploads since its
1096 + * 3.2.0 for its own gallery uploader. Its campaign and fundraiser picture fields upload
1097 + * through Charitable's endpoint, which that addon does not own and cannot gate, so seed
1098 + * the default from its filter: a site that deliberately opted in to anonymous photo
1099 + * uploads keeps working, and the gallery and picture fields agree in every configuration.
1100 + * Note this widens that opt-in to every picture field on the site, which is the intended
1101 + * reading of an explicit site-owner opt-in.
1102 + */
1103 + $allow = (bool) apply_filters( 'charitable_ambassadors_allow_anonymous_photo_uploads', false );
1104 +
1105 + /**
1106 + * Whether a logged-out visitor may upload through a picture field.
1107 + *
1108 + * @since 1.8.12.4
1109 + *
1110 + * @param boolean $allow Whether to allow the upload. Off by default.
1111 + * @param string $field_id The picture field's key, where known.
1112 + * @param int $post_id The parent post the field uploads against, where known.
1113 + */
1114 + return (bool) apply_filters( 'charitable_allow_anonymous_picture_uploads', $allow, $field_id, $post_id );
1115 +}
1116 +
1117 +require_once dirname( __FILE__ ) . '/logger/charitable-log-functions.php';