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/shortcodes/class-charitable-stat-shortcode.php +133 -10 1.6.8 → 1.8.13 View file →
@@ -2,10 +2,10 @@
2 2 /**
3 3 * Responsible for parsing and displaying the output of the [charitable_stat] shortcode.
4 4 *
5 5 * @package Charitable_Stat/Classes/Charitable_Stat_Shortcode
6 - * @author Eric Daams
7 - * @copyright Copyright (c) 2019, Studio 164a
6 + * @author David Bisset
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.6.0
10 10 * @version 1.6.0
11 11 */
@@ -84,10 +84,11 @@
84 84 if ( ! $this->args['goal'] ) {
85 85 return charitable_format_money( $total );
86 86 }
87 87
88 + $goal = charitable_sanitize_amount( $this->args['goal'], false );
88 89 $total = charitable_sanitize_amount( $total, true );
89 - $percent = ( $total / $this->args['goal'] ) * 100;
90 + $percent = ( $total / $goal ) * 100;
90 91
91 92 return '<div class="campaign-progress-bar" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="' . $percent . '"><span class="bar" style="width:' . $percent . '%;"></span></div>';
92 93
93 94 case 'total':
@@ -101,9 +102,11 @@
101 102
102 103 /**
103 104 * Parse shortcode attributes.
104 105 *
105 - * @since 1.6.0
106 + * @since 1.6.0
107 + * @version 1.8.3.5 added 'campaign_categories' to the shortcode attributes.
108 + * @version 1.9.0 added 'include_children' to the shortcode attributes.
106 109 *
107 110 * @param array $atts User-defined attributes.
108 111 * @return array
109 112 */
@@ -108,16 +111,44 @@
108 111 * @return array
109 112 */
110 113 private function parse_args( $atts ) {
111 114 $defaults = array(
112 - 'display' => 'total',
113 - 'campaigns' => '',
114 - 'goal' => false,
115 + 'display' => 'total',
116 + 'campaigns' => '',
117 + 'goal' => false,
118 + 'campaign_categories' => '',
119 + 'include_children' => false,
115 120 );
116 121
117 - $args = shortcode_atts( $defaults, $atts, 'charitable_stat' );
122 + $args = shortcode_atts( $defaults, $atts, 'charitable_stat' );
123 +
124 + if ( '' !== $args['campaign_categories'] ) {
125 + $campaign_categories = str_replace( ', ', ',', $args['campaign_categories'] );
126 + $campaign_categories = explode( ',', $args['campaign_categories'] );
127 + $cat_args = [
128 + 'post_type' => 'campaign',
129 + 'posts_per_page' => -1,
130 + 'fields' => 'ids',
131 + 'tax_query' => [ // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query
132 + [
133 + 'taxonomy' => 'campaign_category',
134 + 'field' => 'slug',
135 + 'terms' => $campaign_categories,
136 + ],
137 + ],
138 + ];
139 + $cat_query = new WP_Query( $cat_args );
140 + if ( ! empty( $cat_query->posts ) ) {
141 + $campaigns = $cat_query->posts;
142 + $args['campaigns'] = implode( ',', $campaigns );
143 + }
144 + }
145 +
118 146 $args['campaigns'] = strlen( $args['campaigns'] ) ? explode( ',', $args['campaigns'] ) : array();
119 147
148 + // Convert include_children to boolean.
149 + $args['include_children'] = filter_var( $args['include_children'], FILTER_VALIDATE_BOOLEAN );
150 +
120 151 return $args;
121 152 }
122 153
123 154 /**
@@ -134,17 +165,109 @@
134 165 /**
135 166 * Return the arguments used for generating the report.
136 167 *
137 168 * @since 1.6.0
169 + * @version 1.9.0 added support for including child campaigns.
138 170 *
139 171 * @return array
140 172 */
141 173 private function get_report_args() {
142 174 $args = array();
143 - $args['report_type'] = in_array( $this->type, array( 'progress', 'total' ) ) ? 'amount' : $this->type;
144 - $args['campaigns'] = $this->args['campaigns'];
175 + $args['report_type'] = in_array( $this->type, array( 'progress', 'total' ), true ) ? 'amount' : $this->type;
145 176
177 + // Expand campaigns to include child campaigns if requested.
178 + if ( $this->args['include_children'] && ! empty( $this->args['campaigns'] ) ) {
179 + $args['campaigns'] = $this->expand_campaigns_with_children( $this->args['campaigns'] );
180 + } else {
181 + $args['campaigns'] = $this->args['campaigns'];
182 + }
183 +
146 184 return $args;
185 + }
186 +
187 + /**
188 + * Expand campaign IDs to include all child campaigns recursively.
189 + *
190 + * @since 1.9.0
191 + *
192 + * @param array $campaign_ids Array of campaign IDs.
193 + * @return array Expanded array of campaign IDs including children.
194 + */
195 + private function expand_campaigns_with_children( $campaign_ids ) {
196 + $all_campaign_ids = array();
197 +
198 + foreach ( $campaign_ids as $campaign_id ) {
199 + $campaign_id = intval( $campaign_id );
200 + if ( ! $campaign_id ) {
201 + continue;
202 + }
203 +
204 + // Add the parent campaign.
205 + $all_campaign_ids[] = $campaign_id;
206 +
207 + // Get child campaigns recursively.
208 + $child_campaigns = $this->get_all_child_campaigns( $campaign_id );
209 + if ( ! empty( $child_campaigns ) ) {
210 + $all_campaign_ids = array_merge( $all_campaign_ids, $child_campaigns );
211 + }
212 + }
213 +
214 + return array_unique( array_filter( $all_campaign_ids ) );
215 + }
216 +
217 + /**
218 + * Get all child campaigns for a campaign ID, recursively.
219 + *
220 + * @since 1.9.0
221 + *
222 + * @param int $campaign_id The parent campaign ID.
223 + * @return array Array of child campaign IDs.
224 + */
225 + private function get_all_child_campaigns( $campaign_id ) {
226 + $child_campaign_ids = array();
227 +
228 + // Check if Charitable Ambassadors is active and use its method if available.
229 + if ( class_exists( 'Charitable_Ambassadors_Campaign' ) ) {
230 + $ambassadors_campaign = new Charitable_Ambassadors_Campaign( $campaign_id );
231 + $child_campaigns = $ambassadors_campaign->get_child_campaigns();
232 +
233 + if ( ! empty( $child_campaigns ) ) {
234 + $child_campaign_ids = array_merge( $child_campaign_ids, $child_campaigns );
235 +
236 + // Recursively get grandchildren.
237 + foreach ( $child_campaigns as $child_id ) {
238 + $grandchildren = $this->get_all_child_campaigns( $child_id );
239 + if ( ! empty( $grandchildren ) ) {
240 + $child_campaign_ids = array_merge( $child_campaign_ids, $grandchildren );
241 + }
242 + }
243 + }
244 + } else {
245 + // Fallback to standard WordPress parent-child relationship.
246 + $direct_children = get_posts(
247 + array(
248 + 'post_type' => Charitable::CAMPAIGN_POST_TYPE,
249 + 'posts_per_page' => -1,
250 + 'post_parent' => $campaign_id,
251 + 'fields' => 'ids',
252 + 'post_status' => 'any',
253 + )
254 + );
255 +
256 + if ( ! empty( $direct_children ) ) {
257 + $child_campaign_ids = array_merge( $child_campaign_ids, $direct_children );
258 +
259 + // Recursively get grandchildren.
260 + foreach ( $direct_children as $child_id ) {
261 + $grandchildren = $this->get_all_child_campaigns( $child_id );
262 + if ( ! empty( $grandchildren ) ) {
263 + $child_campaign_ids = array_merge( $child_campaign_ids, $grandchildren );
264 + }
265 + }
266 + }
267 + }
268 +
269 + return $child_campaign_ids;
147 270 }
148 271 }
149 272
150 273 endif;