PluginProbe
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) / 1.8.0
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) v1.8.0
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.0, at includes/charitable-core-functions.php

753 lines 18.4 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 return charitable()->get_db_table( $table );
183 }
184
185 /**
186 * Returns the current donation form.
187 *
188 * @since 1.0.0
189 *
190 * @return Charitable_Donation_Form_Interface|false
191 */
192 function charitable_get_current_donation_form() {
193 $campaign = charitable_get_current_campaign();
194 return false === $campaign ? false : $campaign->get_donation_form();
195 }
196
197 /**
198 * Returns the provided array as a HTML element attribute.
199 *
200 * @since 1.0.0
201 *
202 * @param array $args Arguments to be added.
203 * @return string
204 */
205 function charitable_get_action_args( $args ) {
206 return sprintf( "data-charitable-args='%s'", json_encode( $args ) );
207 }
208
209 /**
210 * Returns the Charitable_Deprecated class, loading the file if required.
211 *
212 * @since 1.4.0
213 *
214 * @return Charitable_Deprecated
215 */
216 function charitable_get_deprecated() {
217 $registry = charitable()->registry();
218
219 if ( ! $registry->has( 'deprecated' ) ) {
220 $registry->register_object( Charitable_Deprecated::get_instance() );
221 }
222
223 return $registry->get( 'deprecated' );
224 }
225
226 /**
227 * Returns if the check (license check or otherwise) determines if the install is "pro".
228 *
229 * @since 1.7.0
230 *
231 * @return boolean
232 */
233 function charitable_is_pro() {
234
235 if ( charitable_get_helper( 'licenses' )->is_pro() ) {
236 return true;
237 }
238
239 return false;
240 }
241
242 /**
243 * Returns if Charitable is currently using built-in Stripe Connect
244 *
245 * @since 1.7.0
246 *
247 * @return boolean
248 */
249 function charitable_using_stripe_connect() {
250
251 // 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.
252 // the option is removed when, after the stripe connect is connected, the user clicks on the "disconnect" link is clicked in the settings.
253
254 $charitable_stripe_connect = get_option( 'charitable_using_stripe_connect' );
255
256 if ( $charitable_stripe_connect ) {
257 return true;
258 }
259
260 return false;
261 }
262
263 /**
264 * Returns if should load the core stripe functionality.
265 *
266 * @since 1.7.0
267 *
268 * @return boolean
269 */
270 function charitable_load_core_stripe() {
271
272 if ( false !== ( defined( 'USE_NEW_STRIPE' ) && USE_NEW_STRIPE ) ) {
273 return true;
274 }
275
276 // check for stripe addon.
277
278 if ( in_array( 'charitable-stripe/charitable-stripe.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) {
279 return false;
280 }
281
282 if ( class_exists( 'Charitable_Stripe' ) ) {
283 return false;
284 }
285
286 return true;
287 }
288
289 /**
290 * Returns if charitable debug should be on for an admin screen, even if the constant isn't defined/false.
291 *
292 * @since 1.7.0.2
293 *
294 * @return boolean
295 */
296 function charitable_is_admin_debug() {
297
298 if ( isset( $_GET['charitable_debug'] ) && 'true' == $_GET['charitable_debug'] ) {
299 return true;
300 }
301
302 return false;
303 }
304
305 /**
306 * Returns if charitable is in debug mode, mostly by checking the constant.
307 *
308 * @since 1.8.0
309 *
310 * @return boolean
311 */
312 function charitable_is_debug() {
313
314 return ( defined( 'CHARITABLE_DEBUG' ) && CHARITABLE_DEBUG ) ? true : false;
315 }
316
317 /**
318 * Returns if charitable is in script debug mode, mostly by checking the constant.
319 *
320 * @since 1.8.0
321 *
322 * @return boolean
323 */
324 function charitable_is_script_debug() {
325
326 return ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? true : false;
327 }
328
329 /**
330 * Format, sanitize, and return/echo HTML element ID, classes, attributes,
331 * and data attributes.
332 *
333 * @since 1.3.7
334 *
335 * @param string $id HTML id attribute value.
336 * @param array $class A list of classnames for the class attribute.
337 * @param array $datas Data attributes.
338 * @param array $atts Any additional HTML attributes and their values.
339 * @param bool $echo Whether to echo the output or just return it. Defaults to return.
340 *
341 * @return string|void
342 */
343 function charitable_html_attributes( $id = '', $class = array(), $datas = array(), $atts = array(), $echo = false ) {
344
345 $id = trim( $id );
346 $parts = array();
347
348 if ( ! empty( $id ) ) {
349 $id = sanitize_html_class( $id );
350
351 if ( ! empty( $id ) ) {
352 $parts[] = 'id="' . $id . '"';
353 }
354 }
355
356 if ( ! empty( $class ) ) {
357 $class = charitable_sanitize_classes( $class, true );
358
359 if ( ! empty( $class ) ) {
360 $parts[] = 'class="' . $class . '"';
361 }
362 }
363
364 if ( ! empty( $datas ) ) {
365 foreach ( $datas as $data => $val ) {
366 $parts[] = 'data-' . sanitize_html_class( $data ) . '="' . esc_attr( $val ) . '"';
367 }
368 }
369
370 if ( ! empty( $atts ) ) {
371 foreach ( $atts as $att => $val ) {
372 if ( '0' === (string) $val || ! empty( $val ) ) {
373 if ( $att[0] === '[' ) {
374 // Handle special case for bound attributes in AMP.
375 $escaped_att = '[' . sanitize_html_class( trim( $att, '[]' ) ) . ']';
376 } else {
377 $escaped_att = sanitize_html_class( $att );
378 }
379 $parts[] = $escaped_att . '="' . esc_attr( $val ) . '"';
380 }
381 }
382 }
383
384 $output = implode( ' ', $parts );
385
386 if ( $echo ) {
387 echo trim( $output ); // phpcs:ignore
388 } else {
389 return trim( $output );
390 }
391 }
392
393
394 /**
395 * Sanitize string of CSS classes.
396 *
397 * @since 1.8.0
398 *
399 * @param array|string $classes CSS classes.
400 * @param bool $convert True will convert strings to array and vice versa.
401 *
402 * @return string|array
403 */
404 function charitable_sanitize_classes( $classes, $convert = false ) {
405
406 $array = is_array( $classes );
407 $css = array();
408
409 if ( ! empty( $classes ) ) {
410 if ( ! $array ) {
411 $classes = explode( ' ', trim( $classes ) );
412 }
413 foreach ( array_unique( $classes ) as $class ) {
414 if ( ! empty( $class ) ) {
415 $css[] = sanitize_html_class( $class );
416 }
417 }
418 }
419
420 if ( $array ) {
421 return $convert ? implode( ' ', $css ) : $css;
422 }
423
424 return $convert ? $css : implode( ' ', $css );
425 }
426
427 /**
428 * Add UTM tags to a link that allows detecting traffic sources for our or partners' websites.
429 *
430 * @since 1.7.5
431 *
432 * @param string $link Link to which you need to add UTM tags.
433 * @param string $medium The page or location description. Check your current page and try to find
434 * and use an already existing medium for links otherwise, use a page name.
435 * @param string $content The feature's name, the button's content, the link's text, or something
436 * else that describes the element that contains the link.
437 * @param string $term Additional information for the content that makes the link more unique.
438 *
439 * @return string
440 */
441 function charitable_utm_link( $link, $medium, $content = '', $term = '' ) {
442
443 return add_query_arg(
444 array_filter(
445 array(
446 'utm_campaign' => charitable_is_pro() ? 'plugin' : 'liteplugin',
447 'utm_source' => strpos( $link, 'https://wpcharitable.com' ) === 0 ? 'WordPress' : 'charitableplugin',
448 'utm_medium' => rawurlencode( $medium ),
449 'utm_content' => rawurlencode( $content ),
450 'utm_term' => rawurlencode( $term ),
451 )
452 ),
453 $link
454 );
455 }
456
457 /**
458 * Get an upgrade link.
459 *
460 * @since 1.8.0
461 *
462 * @param string $medium The page or location description.
463 * @param string $content Content.
464 *
465 * @return string
466 */
467 function charitable_admin_upgrade_link( $medium, $content = 'Upgrade+to+Pro' ) {
468
469 return charitable_utm_link( 'https://wpcharitable.com/lite-vs-pro/', $medium, $content, false );
470 }
471
472 /**
473 * Get an upgrade modal text.
474 *
475 * @since 1.8.0
476 *
477 * @param string $help_id Referrer code to pass to the help link.
478 *
479 * @return string
480 */
481 function charitable_help_link( $help_id = false ) {
482
483 if ( ! is_admin() ) {
484 return;
485 }
486
487 if ( false === $help_id ) {
488 $screen = get_current_screen();
489 if ( $screen && ! empty( $screen->base ) ) {
490
491 switch ( esc_attr( $screen->base ) ) {
492 case 'edit':
493 $help_id = 'general';
494 break;
495
496 default:
497 $help_id = 'general';
498 break;
499 }
500 }
501 }
502
503 return 'https://www.wpcharitable.com/documentation/?referrer=' . $help_id;
504 }
505
506 /**
507 * Get an upgrade modal text.
508 *
509 * @since 1.4.4
510 *
511 * @param string $type Either "pro" or "elite". Default is "pro".
512 *
513 * @return string
514 */
515 function charitable_get_upgrade_modal_text( $type = 'pro' ) {
516
517 switch ( $type ) {
518 case 'basic':
519 $level = 'Charitable Basic';
520 break;
521 case 'plus':
522 $level = 'Charitable Basic';
523 break;
524 case 'agency':
525 $level = 'Charitable Basic';
526 break;
527 case 'pro':
528 default:
529 $level = 'Charitable Pro';
530 }
531
532 if ( charitable_is_pro() ) {
533 return '<p>' .
534 sprintf(
535 wp_kses( /* translators: %s - WPCharitable.com contact page URL. */
536 __( 'Thank you for considering upgrading. If you have any questions, please <a href="%s" target="_blank" rel="noopener noreferrer">let us know</a>.', 'charitable' ),
537 array(
538 'a' => array(
539 'href' => array(),
540 'target' => array(),
541 'rel' => array(),
542 ),
543 )
544 ),
545 esc_url(
546 charitable_utm_link(
547 'https://wpcharitable.com/contact/',
548 'Upgrade Follow Up Modal',
549 'Contact Support'
550 )
551 )
552 ) .
553 '</p>' .
554 '<p>' .
555 wp_kses(
556 __( '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' ),
557 array(
558 'strong' => array(),
559 'br' => array(),
560 'em' => array(),
561 )
562 ) .
563 '</p>' .
564 '<p>' .
565 sprintf(
566 wp_kses( /* translators: %s - WPCharitable.com upgrade license docs page URL. */
567 __( 'Check out <a href="%s" target="_blank" rel="noopener noreferrer">our documentation</a> for step-by-step instructions.', 'charitable' ),
568 array(
569 'a' => array(
570 'href' => array(),
571 'target' => array(),
572 'rel' => array(),
573 ),
574 )
575 ),
576 'https://wpcharitable.com/docs/upgrade-charitable-license/'
577 ) .
578 '</p>';
579 }
580
581 return '<p>' .
582 sprintf(
583 wp_kses( /* translators: %s - WPCharitable.com contact page URL. */
584 __( 'If you have any questions or issues just <a href="%s" target="_blank" rel="noopener noreferrer">let us know</a>.', 'charitable' ),
585 array(
586 'a' => array(
587 'href' => array(),
588 'target' => array(),
589 'rel' => array(),
590 ),
591 )
592 ),
593 esc_url(
594 charitable_utm_link(
595 'https://wpcharitable.com/contact/',
596 'Upgrade Intention Alert',
597 'Upgrade Intention Alert'
598 )
599 )
600 ) .
601 '</p>' .
602 '<p>' .
603 sprintf(
604 wp_kses( /* translators: %s - license level, Charitable Pro or Charitable Elite. */
605 __( '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' ),
606 array(
607 'strong' => array(),
608 'br' => array(),
609 )
610 ),
611 $level
612 ) .
613 '</p>' .
614 '<p>' .
615 sprintf(
616 wp_kses( /* translators: %s - WPCharitable.com upgrade from Lite to paid docs page URL. */
617 __( 'Check out <a href="%s" target="_blank" rel="noopener noreferrer">our documentation</a> for step-by-step instructions.', 'charitable' ),
618 array(
619 'a' => array(
620 'href' => array(),
621 'target' => array(),
622 'rel' => array(),
623 ),
624 )
625 ),
626 esc_url(
627 charitable_utm_link(
628 'https://wpcharitable.com/lite-vs-pro/',
629 'Upgrade Intention Alert',
630 'Upgrade Documentation'
631 )
632 )
633 ) .
634 '</p>';
635 }
636
637 /**
638 * Perform json_decode and unslash.
639 *
640 * IMPORTANT: This function decodes the result of charitable_encode() properly only if
641 * wp_insert_post() or wp_update_post() were used after the data is encoded.
642 * Both wp_insert_post() and wp_update_post() remove excessive slashes added by charitable_encode().
643 *
644 * Using charitable_decode() on charitable_encode() result directly
645 * (without using wp_insert_post() or wp_update_post() first) always returns null or false.
646 *
647 * @since 1.0.0
648 *
649 * @param string $data Data to decode.
650 *
651 * @return array|false|null
652 */
653 function charitable_decode( $data ) {
654
655 if ( ! $data || empty( $data ) ) {
656 return false;
657 }
658
659 return wp_unslash( json_decode( $data, true ) );
660 }
661
662 /**
663 * Perform json_encode and wp_slash.
664 *
665 * IMPORTANT: This function adds excessive slashes to prevent data damage
666 * by wp_insert_post() or wp_update_post() that use wp_unslash() on all the incoming data.
667 *
668 * Decoding the result of this function by charitable_decode() directly
669 * (without using wp_insert_post() or wp_update_post() first) always returns null or false.
670 *
671 * @since 1.3.1.3
672 *
673 * @param mixed $data Data to encode.
674 *
675 * @return string|false
676 */
677 function charitable_encode( $data = false ) {
678
679 if ( empty( $data ) ) {
680 return false;
681 }
682
683 return wp_slash( wp_json_encode( $data ) );
684 }
685
686 /**
687 * Decode json-encoded string if it is in json format.
688 *
689 * @since 1.7.5
690 *
691 * @param string $the_string A string.
692 * @param bool $associative Decode to the associative array if true. Decode to object if false.
693 *
694 * @return array|string
695 */
696 function charitable_json_decode( $the_string, $associative = false ) {
697
698 $the_string = html_entity_decode( $the_string );
699
700 if ( function_exists( 'charitable_is_json' ) && ! charitable_is_json( $the_string ) ) {
701 return $the_string;
702 }
703
704 return json_decode( $the_string, $associative );
705 }
706
707 /**
708 * Check permissions for currently logged in user, taken from Charitable.
709 * Both short (e.g. 'view_own_forms') or long (e.g. 'charitable_view_own_forms') capability name can be used.
710 * Only Charitable capabilities get processed.
711 *
712 * @since 1.7.0.3
713 *
714 * @param array|string $caps Capability name(s).
715 * @param int $id ID of the specific object to check against if capability is a "meta" cap. "Meta"
716 * capabilities, e.g. 'edit_post', 'edit_user', etc., are capabilities used by
717 * map_meta_cap() to map to other "primitive" capabilities, e.g. 'edit_posts',
718 * edit_others_posts', etc. Accessed via func_get_args() and passed to
719 * WP_User::has_cap(), then map_meta_cap().
720 *
721 * @return bool
722 */
723 function charitable_current_user_can( $caps = array(), $id = 0 ) {
724
725 $user_can = current_user_can( $caps, $id );
726
727 return apply_filters( 'charitable_current_user_can', $user_can, $caps, $id );
728 }
729
730 /**
731 * Get a suffix for assets, if SCRIPT_DEBUG or CHARITABLE_DEBUG are 'true' then it's blank, otherwise it's minimial (`.min`)'.
732 *
733 * @since 1.8.0
734 *
735 * @return string
736 */
737 function charitable_get_min_suffix() {
738
739 return ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) || ( defined( 'CHARITABLE_DEBUG' ) && CHARITABLE_DEBUG ) ? '' : '.min';
740 }
741
742 /**
743 * Get a verion for style unqueues. If SCRIPT_DEBUG or CHARITABLE_DEBUG are 'true' then force a flush cache with time() otherwise it's the Chartiable version.
744 *
745 * @since 1.8.0
746 *
747 * @return string
748 */
749 function charitable_get_style_version() {
750
751 return ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) || ( defined( 'CHARITABLE_DEBUG' ) && CHARITABLE_DEBUG ) ? time() : charitable()->get_version();
752 }
753