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/campaigns/class-charitable-campaign.php +378 -16 1.7.0 → 1.8.13 View file →
@@ -3,9 +3,9 @@
3 3 * Campaign model.
4 4 *
5 5 * @package Charitable/Classes/Charitable_Campaign
6 6 * @author David Bisset
7 - * @copyright Copyright (c) 2022, WP Charitable LLC
7 + * @copyright Copyright (c) 2023, WP Charitable LLC
8 8 * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9 9 * @since 1.0.0
10 10 * @version 1.6.54
11 11 */
@@ -70,8 +70,15 @@
70 70 */
71 71 private $goal;
72 72
73 73 /**
74 + * The fundraising goal for the campaign.
75 + *
76 + * @var string|false
77 + */
78 + private $min_donation_amount;
79 +
80 + /**
74 81 * The donations made to this campaign.
75 82 *
76 83 * @var WP_Query|false
77 84 */
@@ -111,12 +118,65 @@
111 118 if ( ! $post instanceof WP_Post ) {
112 119 $post = get_post( $post );
113 120 }
114 121
122 + add_filter( 'charitable_campaign_description_template_content', array( $this, 'description_content' ), 10, 2 );
123 +
115 124 $this->post = $post;
116 125 }
117 126
118 127 /**
128 + * Return description content.
129 + *
130 + * @since 1.7.0.4
131 + *
132 + * @param string $content The content.
133 + * @param object $campaign The campaign object.
134 + * @return mixed
135 + */
136 + public function description_content( $content = false, $campaign = false ) {
137 +
138 + // search for YouTube and Vimeo video urls by default and attempt to convert them to oembed.
139 +
140 + preg_match_all( '#(?<=v=|v\/|vi=|vi\/|youtu.be\/)[a-zA-Z0-9_-]{11}#', $content, $matches );
141 +
142 + if ( $matches ) :
143 + foreach ( $matches as $video_id ) {
144 + if ( ! empty( $video_id ) ) :
145 + $video_embed_args = apply_filters( 'charitable_campaign_description_template_video', array(), 'youtube', $video_id, $content );
146 + $embed = wp_oembed_get( 'https://youtube.com/watch?v=' . $video_id[0], $video_embed_args );
147 +
148 + $content = str_replace( trim( 'https://youtube.com/watch?v=' . $video_id[0] ), $embed, $content );
149 + $content = str_replace( trim( 'http://youtube.com/watch?v=' . $video_id[0] ), $embed, $content );
150 + $content = str_replace( trim( 'https://www.youtube.com/watch?v=' . $video_id[0] ), $embed, $content );
151 + $content = str_replace( trim( 'http://www.youtube.com/watch?v=' . $video_id[0] ), $embed, $content );
152 + endif;
153 + }
154 + endif;
155 +
156 + preg_match( '/https?:\/\/(?:www\.)?vimeo\.com\/\d{8}/', $content, $matches );
157 +
158 + if ( $matches ) :
159 + foreach ( $matches as $video_url ) {
160 + if ( ! empty( $video_id ) ) :
161 + $video_embed_args = apply_filters( 'charitable_campaign_description_template_video', array(), 'vimeo', $video_id, $content, $campaign );
162 + $embed = wp_oembed_get( $video_url, $video_embed_args );
163 +
164 + $content = str_replace( trim( $video_url ), $embed, $content );
165 + endif;
166 + }
167 + endif;
168 +
169 + // allow developers and plugins to hook into content.
170 + $content = apply_filters( 'charitable_campaign_description_content', $content, $campaign );
171 +
172 + // apply WP's the_content filter, which other plugins can hook into.
173 + $content = apply_filters( 'the_content', $content ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- 'the_content' is a WordPress core filter hook.
174 +
175 + return $content;
176 + }
177 +
178 + /**
119 179 * Magic getter.
120 180 *
121 181 * @since 1.0.0
122 182 *
@@ -123,9 +183,9 @@
123 183 * @param string $key The key of the field to get.
124 184 * @return mixed
125 185 */
126 186 public function __get( $key ) {
127 - if ( property_exists( $this->post, $key ) ) {
187 + if ( null !== $this->post && property_exists( $this->post, $key ) ) {
128 188 return $this->post->$key;
129 189 }
130 190
131 191 return $this->get( $key );
@@ -185,8 +245,13 @@
185 245 * @return mixed This will return an array if single is false. If it's true, the value of the
186 246 * meta_value field will be returned.
187 247 */
188 248 public function get_meta( $meta_name, $single = true ) {
249 +
250 + if ( empty( $this->post->ID ) ) {
251 + return;
252 + }
253 +
189 254 /**
190 255 * Filter the meta value of a particular campaign field.
191 256 *
192 257 * @since 1.0.0
@@ -214,8 +279,20 @@
214 279 return $this->fields;
215 280 }
216 281
217 282 /**
283 + * Returns the id of the campaign (post).
284 + *
285 + * @since 1.7.0.9
286 + * @version 1.8.0
287 + *
288 + * @return integer
289 + */
290 + public function get_campaign_id() {
291 + return ( isset( $this->post->ID ) ) ? intval( $this->post->ID ) : false;
292 + }
293 +
294 + /**
218 295 * Returns whether the campaign is endless (i.e. no end date has been set).
219 296 *
220 297 * @since 1.0.0
221 298 *
@@ -253,8 +330,25 @@
253 330 return apply_filters( 'charitable_campaign_suggested_donations', $value, $this );
254 331 }
255 332
256 333 /**
334 + * Return the suggested amounts, or an empty array if there are none.
335 + *
336 + * @since 1.0.0
337 + *
338 + * @return array
339 + */
340 + public function get_suggested_donations_default() {
341 + $value = get_post_meta( $this->post->ID, '_campaign_suggested_donations_default', true );
342 +
343 + if ( is_array( $value ) && isset( $value[0] ) ) {
344 + $value = $value[0];
345 + }
346 +
347 + return apply_filters( 'charitable_campaign_suggested_donations_default', $value, $this );
348 + }
349 +
350 + /**
257 351 * Returns the end date in your preferred format.
258 352 *
259 353 * If a format is not provided, the user-defined date_format in WordPress settings is used.
260 354 *
@@ -286,8 +380,9 @@
286 380 /**
287 381 * Returns the timetamp of the end date.
288 382 *
289 383 * @since 1.0.0
384 + * @since 1.8.1.10
290 385 *
291 386 * @return int|false Int if campaign has an end date. False if campaign has no end date.
292 387 */
293 388 public function get_end_time() {
@@ -302,8 +397,13 @@
302 397 $date_time = explode( ' ', $end_date );
303 398 $date = explode( '-', $date_time[0] );
304 399 $time = explode( ':', $date_time[1] );
305 400
401 + // Check for undefined array keys. If any of these are not defined, return false.
402 + if ( ! isset( $date[0] ) || ! isset( $date[1] ) || ! isset( $date[2] ) || ! isset( $time[0] ) || ! isset( $time[1] ) || ! isset( $time[2] ) ) {
403 + return false;
404 + }
405 +
306 406 $this->end_time = mktime( $time[0], $time[1], $time[2], $date[1], $date[2], $date[0] );
307 407 }
308 408
309 409 return $this->end_time;
@@ -360,9 +460,10 @@
360 460 /* Condition 2: There is less than an hour left. */
361 461
362 462 $minutes_remaining = ceil( $seconds_left / 60 );
363 463 $time_left = apply_filters(
364 - 'charitabile_campaign_minutes_left',
464 + 'charitabile_campaign_minutes_left', // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- This is a legacy hook used by other Charitable code. Changing it would break existing functionality.
465 + // translators: %s is the number of minutes left.
365 466 sprintf( _n( '%s Minute Left', '%s Minutes Left', $minutes_remaining, 'charitable' ), '<span class="amount time-left minutes-left">' . $minutes_remaining . '</span>' ),
366 467 $this
367 468 );
368 469
@@ -371,9 +472,10 @@
371 472 /* Condition 3: There is less than a day left. */
372 473
373 474 $hours_remaining = floor( $seconds_left / 3600 );
374 475 $time_left = apply_filters(
375 - 'charitabile_campaign_hours_left',
476 + 'charitabile_campaign_hours_left', // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- This is a legacy hook used by other Charitable code. Changing it would break existing functionality.
477 + // translators: %s is the number of hours left.
376 478 sprintf( _n( '%s Hour Left', '%s Hours Left', $hours_remaining, 'charitable' ), '<span class="amount time-left hours-left">' . $hours_remaining . '</span>' ),
377 479 $this
378 480 );
379 481
@@ -382,14 +484,15 @@
382 484 /* Condition 4: There is more than a day left. */
383 485
384 486 $days_remaining = floor( $seconds_left / 86400 );
385 487 $time_left = apply_filters(
386 - 'charitabile_campaign_days_left',
488 + 'charitabile_campaign_days_left', // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- This is a legacy hook used by other Charitable code. Changing it would break existing functionality.
489 + // translators: %s is the number of days left.
387 490 sprintf( _n( '%s Day Left', '%s Days Left', $days_remaining, 'charitable' ), '<span class="amount time-left days-left">' . $days_remaining . '</span>' ),
388 491 $this
389 492 );
390 493
391 - }//end if
494 + } //end if
392 495
393 496 return apply_filters( 'charitable_campaign_time_left', $time_left, $this );
394 497 }
395 498
@@ -437,12 +540,15 @@
437 540 return '';
438 541 }
439 542
440 543 if ( ! $this->has_goal() ) {
544 + // translators: %s is the time since the campaign ended.
441 545 $message = __( 'This campaign ended %s ago', 'charitable' );
442 546 } elseif ( $this->has_achieved_goal() ) {
547 + // translators: %s is the time since the campaign ended.
443 548 $message = __( 'This campaign successfully reached its funding goal and ended %s ago', 'charitable' );
444 549 } else {
550 + // translators: %s is the time since the campaign ended.
445 551 $message = __( 'This campaign failed to reach its funding goal %s ago', 'charitable' );
446 552 }
447 553
448 554 return apply_filters( 'charitable_campaign_finished_notice', sprintf( $message, '<span class="time-ago">' . human_time_diff( $this->get_end_time() ) . '</span>' ), $this );
@@ -478,8 +584,24 @@
478 584 return $this->goal;
479 585 }
480 586
481 587 /**
588 + * Returns the minimum donation amount of the campaign.
589 + *
590 + * @since 1.0.0
591 + *
592 + * @return string|false Amount if goal is set. False otherwise.
593 + */
594 + public function get_min_donation_amount() {
595 + if ( ! isset( $this->min_donation_amount ) ) {
596 + $this->min_donation_amount = $this->get_meta( '_campaign_min_donation_amount' ) ? $this->get_meta( '_campaign_min_donation_amount' ) : false;
597 + }
598 +
599 + return $this->min_donation_amount;
600 + }
601 +
602 +
603 + /**
482 604 * Returns whether a goal has been set (anything greater than $0 is a goal).
483 605 *
484 606 * @since 1.0.0
485 607 *
@@ -566,10 +688,11 @@
566 688 *
567 689 * @return string
568 690 */
569 691 public function get_status() {
570 - $status = $this->post->post_status;
571 692
693 + $status = $post_status = isset( $this->post ) && ! empty( $this->post->post_status ) ? $this->post->post_status : false; // phpcs:ignore
694 +
572 695 if ( 'publish' == $status ) {
573 696 $status = $this->has_ended() ? 'finished' : 'active';
574 697 }
575 698
@@ -581,9 +704,9 @@
581 704 * @param string $status The campaign status.
582 705 * @param string $post_status The post_status of the campaign.
583 706 * @param Charitable_Campaign $campaign This instance of `Charitable_Campaign`.
584 707 */
585 - return apply_filters( 'charitable_campaign_status', $status, $this->post->post_status, $this );
708 + return apply_filters( 'charitable_campaign_status', $status, $post_status, $this );
586 709 }
587 710
588 711 /**
589 712 * Return a status key for the campaign.
@@ -639,8 +762,11 @@
639 762 * Return the campaign status tag.
640 763 *
641 764 * @since 1.0.0
642 765 *
766 + * @param boolean $show_achievement Whether to show the achievement status tag.
767 + * @param boolean $show_active_tag Whether to show the active status tag.
768 + *
643 769 * @return string
644 770 */
645 771 public function get_status_tag( $show_achievement = null, $show_active_tag = null ) {
646 772 $key = $this->get_status_key();
@@ -821,8 +947,9 @@
821 947 $goal = $this->get_meta( '_campaign_goal' );
822 948
823 949 if ( $goal ) {
824 950 $ret = sprintf(
951 + // translators: %1$s is the amount donated, %2$s is the goal amount.
825 952 _x( '%1$s donated of %2$s goal', 'amount donated of goal', 'charitable' ),
826 953 '<span class="amount">' . $currency_helper->get_monetary_amount( $amount ) . '</span>',
827 954 '<span class="goal-amount">' . $currency_helper->get_monetary_amount( $goal ) . '</span>'
828 955 );
@@ -827,8 +954,9 @@
827 954 '<span class="goal-amount">' . $currency_helper->get_monetary_amount( $goal ) . '</span>'
828 955 );
829 956 } else {
830 957 $ret = sprintf(
958 + // translators: %s is the amount donated.
831 959 _x( '%s donated', 'amount donated', 'charitable' ),
832 960 '<span class="amount">' . $currency_helper->get_monetary_amount( $amount ) . '</span>'
833 961 );
834 962 }
@@ -848,8 +976,39 @@
848 976 return apply_filters( 'charitable_donation_summary', $ret, $this, $amount, $goal );
849 977 }
850 978
851 979 /**
980 + * Return a string especially for the campaign builder describing the campaign's donation summary.
981 + *
982 + * @since 1.8.0
983 + *
984 + * @return string
985 + */
986 + public function get_builder_donation_summary() {
987 + $currency_helper = charitable_get_currency_helper();
988 + $amount = $this->get_donated_amount();
989 + $goal = $this->get_meta( '_campaign_goal' );
990 +
991 + $ret = sprintf(
992 + // translators: %s is the amount donated.
993 + _x( '%s donated', 'amount donated', 'charitable' ),
994 + '<span class="amount">' . $currency_helper->get_monetary_amount( $amount ) . '</span>'
995 + );
996 +
997 + /**
998 + * Filter the returned string if you want to display the donation summary in a different way.
999 + *
1000 + * @since 1.8.0
1001 + *
1002 + * @param string $ret The summary.
1003 + * @param Charitable_Campaign $this This campaign object.
1004 + * @param float $amount The amount donated.
1005 + * @param int $goal The campaign goal.
1006 + */
1007 + return apply_filters( 'charitable_builder_donation_summary', $ret, $this, $amount, $goal );
1008 + }
1009 +
1010 + /**
852 1011 * Return the percentage donated. Use this if you want a formatted string.
853 1012 *
854 1013 * @since 1.0.0
855 1014 *
@@ -869,10 +1028,43 @@
869 1028
870 1029 /**
871 1030 * Returns the percentage donated as a number.
872 1031 *
873 - * @since 1.0.0
1032 + * Ported from Charitable Pro, 1.8.13, THEN deliberately changed —
1033 + * Lite deviates from Pro here on purpose. Pro's own version (and my
1034 + * first port of it) unconditionally strips the thousands separator
1035 + * and swaps the decimal separator, which is correct for a
1036 + * DISPLAY-locale-formatted goal like "1,000.00" but wrong for the
1037 + * CANONICAL dot-decimal form sanitize_campaign_goal() actually
1038 + * stores: that method runs every saved goal through
1039 + * Charitable_Currency::sanitize_monetary_amount(), which returns
1040 + * floatval() — always dot-decimal, regardless of site locale. On a
1041 + * comma-decimal / dot-thousands site (Settings > General; both
1042 + * separators are user-settable), the unconditional strip reads an
1043 + * already-canonical "1000.5" as "10005" — a campaign that raised 300
1044 + * of a 1000.5 goal reported 3% instead of 30%.
874 1045 *
1046 + * is_numeric() distinguishes the two shapes: a canonical dot-decimal
1047 + * value passes it and is used via a plain floatval(), untouched; a
1048 + * display-formatted value ("1,000.00", "1.000,50") does not, and
1049 + * still gets the separator treatment below. This is what makes both
1050 + * the locale-formatted-input case (list-campaigns/get-campaign's own
1051 + * "1,000.00" trap) and the canonical-storage case correct at once.
1052 + *
1053 + * Callers reach well beyond the abilities surface: the front-end
1054 + * progress bar (templates/campaign/progress-bar.php, both the bar
1055 + * width and the aria-valuenow a screen reader announces), the
1056 + * dashboard and reports classes, and get_percent_donated() below all
1057 + * go through this method. Pro carries the same bug on the same
1058 + * front-end path; Charitable_Campaign_Abilities::percent_raised()
1059 + * being correct would not have been enough to fix what a donor's
1060 + * screen reader announces. The verbatim-fidelity rule for this port
1061 + * covers the abilities registrars; it does not require shipping a
1062 + * known locale regression on a shared front-end template.
1063 + *
1064 + * @since 1.0.0
1065 + * @version 1.8.13
1066 + *
875 1067 * @return int
876 1068 */
877 1069 public function get_percent_donated_raw() {
878 1070 if ( ! $this->has_goal() ) {
@@ -878,9 +1070,30 @@
878 1070 if ( ! $this->has_goal() ) {
879 1071 return false;
880 1072 }
881 1073
882 - return ( $this->get_donated_amount( true ) / $this->get_goal() ) * 100;
1074 + $donated = floatval( $this->get_donated_amount( true ) );
1075 +
1076 + $goal_meta = $this->get_meta( '_campaign_goal' );
1077 + $currency = Charitable_Currency::get_instance();
1078 + $decimal_separator = $currency->get_decimal_separator();
1079 + $thousands_separator = $currency->get_thousands_separator();
1080 +
1081 + /*
1082 + * Already-canonical dot-decimal values (the shape every saved
1083 + * goal is actually stored in) pass through untouched; anything
1084 + * else is a display-formatted string and gets the thousands
1085 + * strip + decimal-separator swap.
1086 + */
1087 + $goal = is_numeric( $goal_meta )
1088 + ? floatval( $goal_meta )
1089 + : floatval( str_replace( $decimal_separator, '.', str_replace( $thousands_separator, '', $goal_meta ) ) );
1090 +
1091 + if ( $goal <= 0 ) {
1092 + return 0;
1093 + }
1094 +
1095 + return ( $donated / $goal ) * 100;
883 1096 }
884 1097
885 1098 /**
886 1099 * Return the number of people who have donated to the campaign.
@@ -905,8 +1118,36 @@
905 1118 );
906 1119 }
907 1120
908 1121 /**
1122 + * Return the number of donations (transactions) for the campaign.
1123 + *
1124 + * Ported from Charitable Pro unchanged. Backs the
1125 + * charitable/get-campaign-performance ability's donation_count field —
1126 + * a campaign with two donations from the same donor has a donor_count
1127 + * of 1 but a get_donation_count() of 2.
1128 + *
1129 + * @since 1.8.13
1130 + *
1131 + * @return int
1132 + */
1133 + public function get_donation_count() {
1134 + /**
1135 + * Filter the number of donations (transactions) for the campaign.
1136 + *
1137 + * @since 1.8.13
1138 + *
1139 + * @param int $count Number of donations.
1140 + * @param Charitable_Campaign $this This campaign object.
1141 + */
1142 + return apply_filters(
1143 + 'charitable_campaign_donation_count',
1144 + (int) charitable_get_table( 'campaign_donations' )->count_campaign_donations( $this->ID ),
1145 + $this
1146 + );
1147 + }
1148 +
1149 + /**
909 1150 * Returns the donation form object.
910 1151 *
911 1152 * @since 1.0.0
912 1153 *
@@ -1138,8 +1379,24 @@
1138 1379 return charitable_get_currency_helper()->sanitize_monetary_amount( $value );
1139 1380 }
1140 1381
1141 1382 /**
1383 + * Sanitize the campaign minimum amount.
1384 + *
1385 + * @since 1.7.0.3
1386 + *
1387 + * @param string $value Current value of min amount.
1388 + * @return string|int
1389 + */
1390 + public static function sanitize_min_donation_amount( $value ) {
1391 + if ( empty( $value ) || ! $value ) {
1392 + return 0;
1393 + }
1394 +
1395 + return charitable_get_currency_helper()->sanitize_monetary_amount( $value );
1396 + }
1397 +
1398 + /**
1142 1399 * Sanitize the campaign end date.
1143 1400 *
1144 1401 * We use WP_Locale to parse the month that the user has set.
1145 1402 *
@@ -1174,9 +1431,24 @@
1174 1431 *
1175 1432 * @param array $value Current suggested donations value.
1176 1433 * @return array
1177 1434 */
1178 - public static function sanitize_campaign_suggested_donations( $value ) {
1435 + public static function sanitize_campaign_suggested_donations_default( $value ) {
1436 +
1437 + return $value; // this is likely an array.
1438 + }
1439 +
1440 + /**
1441 + * Sanitize the campaign suggested donations.
1442 + *
1443 + * @since 1.0.0
1444 + *
1445 + * @param array $value Current suggested donations value.
1446 + * @param bool $submitted Whether the value was submitted.
1447 + * @param int $campaign_id The campaign ID.
1448 + * @return array
1449 + */
1450 + public static function sanitize_campaign_suggested_donations( $value, $submitted = false, $campaign_id = false ) { // phpcs:ignore
1179 1451 if ( ! is_array( $value ) ) {
1180 1452 return array();
1181 1453 }
1182 1454
@@ -1188,8 +1460,18 @@
1188 1460
1189 1461 foreach ( $value as $key => $suggestion ) {
1190 1462 $value[ $key ]['amount'] = charitable_sanitize_amount( (string) $suggestion['amount'] );
1191 1463
1464 + /*
1465 + * A description is OPTIONAL. filter_suggested_donation() above keeps any entry that has
1466 + * a non-empty 'amount', so array( 'amount' => 25 ) is a perfectly valid suggestion with
1467 + * no 'description' key at all - which is the normal shape when a campaign offers bare
1468 + * amounts. Reading it unguarded emitted an "Undefined array key" warning on every such
1469 + * sanitize pass. Defaulted rather than skipped so the key is always present in the
1470 + * returned array, which is what callers and the stored meta already assume.
1471 + */
1472 + $description = isset( $suggestion['description'] ) ? $suggestion['description'] : '';
1473 +
1192 1474 /**
1193 1475 * Sanitize the description field.
1194 1476 *
1195 1477 * @since 1.6.51
@@ -1198,11 +1480,11 @@
1198 1480 * Returning false will allow HTML to be used, though it will
1199 1481 * still be filtered using wp_kses_post.
1200 1482 */
1201 1483 if ( apply_filters( 'charitable_sanitize_suggested_amount_description', true ) ) {
1202 - $value[ $key ]['description'] = sanitize_text_field( $suggestion['description'] );
1484 + $value[ $key ]['description'] = sanitize_text_field( $description );
1203 1485 } else {
1204 - $value[ $key ]['description'] = wp_kses_post( $suggestion['description'] );
1486 + $value[ $key ]['description'] = wp_kses_post( $description );
1205 1487 }
1206 1488 }
1207 1489
1208 1490 return $value;
@@ -1238,21 +1520,96 @@
1238 1520
1239 1521 /**
1240 1522 * Sanitize the campaign description.
1241 1523 *
1242 - * @since 1.0.0
1524 + * @since 1.0.0
1525 + * @updated 1.7.0.4
1243 1526 *
1244 1527 * @param string $value Current description value.
1245 1528 * @return string
1246 1529 */
1247 1530 public static function sanitize_campaign_description( $value ) {
1248 - return sanitize_text_field( $value );
1531 +
1532 + /**
1533 + * Allowed HTML in description.
1534 + */
1535 + $wp_kses_allowed_html = array(
1536 + 'a' => array(
1537 + 'href' => array(),
1538 + 'target' => array(),
1539 + 'class' => array(),
1540 + 'title' => array(),
1541 + ),
1542 + 'br' => array(),
1543 + 'img' => array(
1544 + 'src' => array(),
1545 + 'class' => array(),
1546 + 'alt' => array(),
1547 + ),
1548 + 'h1' => array(
1549 + 'class' => array(),
1550 + ),
1551 + 'h2' => array(
1552 + 'class' => array(),
1553 + ),
1554 + 'h3' => array(
1555 + 'class' => array(),
1556 + ),
1557 + 'h4' => array(
1558 + 'class' => array(),
1559 + ),
1560 + 'h5' => array(
1561 + 'class' => array(),
1562 + ),
1563 + 'h6' => array(
1564 + 'class' => array(),
1565 + ),
1566 + 'div' => array(
1567 + 'class' => array(),
1568 + ),
1569 + 'p' => array(
1570 + 'style' => array(),
1571 + 'class' => array(),
1572 + ),
1573 + 'ul' => array(
1574 + 'class' => array(),
1575 + ),
1576 + 'li' => array(
1577 + 'id' => array(),
1578 + 'class' => array(),
1579 + ),
1580 + 'em' => array(),
1581 + 'span' => array(
1582 + 'class' => array(),
1583 + ),
1584 + 'strong' => array(),
1585 + );
1586 +
1587 + if ( apply_filters( 'charitable_sanitize_campaign_description', false ) ) {
1588 + return sanitize_text_field( $value );
1589 + } else {
1590 + return wp_kses( apply_filters( 'charitable_campaign_description', $value ), apply_filters( 'charitable_sanitize_campaign_description_allowed_html', $wp_kses_allowed_html ) );
1591 + }
1249 1592 }
1250 1593
1251 1594 /**
1595 + * Sanitize the campaign donation button text..
1596 + *
1597 + * @since 1.7.0.9
1598 + *
1599 + * @param string $value Current text value.
1600 + * @return string
1601 + */
1602 + public static function sanitize_campaign_donate_button_text( $value = false ) {
1603 +
1604 + return wp_strip_all_tags( $value );
1605 + }
1606 +
1607 + /**
1252 1608 * Sanitize the value provided for custom donations.
1253 1609 *
1254 - * @since 1.3.6
1610 + * @since 1.3.6
1611 + * @version 1.8.0
1255 1612 *
1256 1613 * @param mixed $value Current custom donations value.
1257 1614 * @param array $submitted All posted values.
1258 1615 * @return boolean
@@ -1275,8 +1632,13 @@
1275 1632 * @param array $submitted The submitted values.
1276 1633 */
1277 1634 if ( apply_filters( 'charitable_campaign_permitted_without_custom_or_suggested', false, $submitted ) ) {
1278 1635 return $checked;
1636 + }
1637 +
1638 + // see if literally "0" was passed.
1639 + if ( is_string( $value ) && '0' === $value ) {
1640 + return 0;
1279 1641 }
1280 1642
1281 1643 /* If suggested donations are not set, custom donations needs to be enabled. */
1282 1644 if ( ! isset( $submitted['_campaign_suggested_donations'] ) ) {