PluginProbe
GiveWP – Donation Plugin and Fundraising Platform / 4.17.0
GiveWP – Donation Plugin and Fundraising Platform v4.17.0
4.17.0 4.16.9 4.16.8.1 4.16.8 4.16.7.2 4.16.7.1 4.16.7 4.16.6.1 4.16.6 4.16.5.1 4.16.5 4.16.4 4.16.3 4.16.2 4.16.1 4.16.0 4.15.5 4.15.4 4.15.3 4.15.2 4.15.1 4.15.0 2.3.0 2.3.1 2.3.2 All 256 releases
← All changes | includes/donors/class-give-donor-wall.php +325 -137 2.3.0 → 4.17.0 View file →
@@ -1,18 +1,20 @@
1 1 <?php
2 2 /**
3 - * Donors Gravatars
3 + * Donor Wall
4 4 *
5 5 * @package Give
6 - * @subpackage Classes/Give_Donors_Gravatars
7 - * @copyright Copyright (c) 2016, WordImpress
6 + * @subpackage Classes/Give_Donor_Wall
7 + * @copyright Copyright (c) 2020, GiveWP
8 8 * @license https://opensource.org/licenses/gpl-license GNU Public License
9 9 * @since 1.0
10 10 */
11 11
12 12 // Exit if accessed directly.
13 -if ( ! defined( 'ABSPATH' ) ) {
14 - exit;
13 +use Give\Donations\ValueObjects\DonationMetaKeys;
14 +
15 +if (!defined('ABSPATH')) {
16 + exit;
15 17 }
16 18
17 19
18 20 /**
@@ -22,8 +24,9 @@
22 24 *
23 25 * @since 2.2.0
24 26 */
25 27 class Give_Donor_Wall {
28 +
26 29 /**
27 30 * Instance.
28 31 *
29 32 * @since 2.2.0
@@ -29,9 +32,9 @@
29 32 * @since 2.2.0
30 33 * @access private
31 34 * @var Give_Donor_Wall
32 35 */
33 - static private $instance;
36 + private static $instance;
34 37
35 38 /**
36 39 * Singleton pattern.
37 40 *
@@ -67,53 +70,61 @@
67 70 * @return void
68 71 */
69 72 public function setup_actions() {
70 73
71 - add_shortcode( 'give_donor_wall', array( $this, 'render_shortcode' ) );
74 + add_shortcode( 'give_donor_wall', [ $this, 'render_shortcode' ] );
72 75
73 - add_action( 'wp_ajax_give_get_donor_comments', array( $this, 'ajax_handler' ) );
74 - add_action( 'wp_ajax_nopriv_give_get_donor_comments', array( $this, 'ajax_handler' ) );
76 + add_action( 'wp_ajax_give_get_donor_comments', [ $this, 'ajax_handler' ] );
77 + add_action( 'wp_ajax_nopriv_give_get_donor_comments', [ $this, 'ajax_handler' ] );
75 78
76 79 }
77 80
78 81
79 - /**
80 - * Displays donors in a grid layout.
81 - *
82 - * @since 2.2.0
83 - *
84 - * @param array $atts {
85 - * Optional. Attributes of the donor wall shortcode.
86 - *
87 - * @type int $donors_per_page Number of donors per page. Default '20'.
88 - * @type int $form_id The donation form to filter donors by. Default is all forms (no filter).
89 - * @type bool $paged Whether to paginate donors. Default 'true'.
90 - * @type string $ids A comma-separated list of donor IDs to display. Default empty.
91 - * @type string $columns Maximum columns to display. Default 'best-fit'.
92 - * Accepts 'best-fit', '1', '2', '3', '4'.
93 - * @type bool $show_avatar Whether to display the donor's gravatar image if available. Default 'true'.
94 - * @type bool $show_name Whether to display the donor's full name, first and last. Default 'true'.
95 - * @type bool $show_total Whether to display the donor's donation amount. Default 'true'.
96 - * @type bool $show_time Whether to display date of the last donation. Default 'true'.
97 - * @type bool $show_comments Whether to display the donor's comment if they left one. Default 'true'.
98 - * @type int $comment_length The number of words to display for the comments before a "Read more" field
99 - * @type int $only_comments Whether to display the donors only with comment. Default 'false'.
100 - *
101 - * @type string $readmore_text Link label for modal in which donor can read full comment.
102 - * @type string $loadmore_text Button label which will load more donor comments.
103 - * @type int $avatar_size Avatar image size in pixels without the "px". Default "60"
104 - * @type string $orderby The order in which you want the donors to appear. Accepts "donation_amount", "donation_count",
105 - * if donor donated same value for orderby attribute then they will short by created date (fallback)
106 - * @type string $order The order in which you want the donors to appear. Accepts "ASC". "DESC".
107 - *
108 - * }
109 - * @return string|bool The markup of the form grid or false.
110 - */
82 + /**
83 + * Displays donors in a grid layout.
84 + *
85 + * @since 4.16.9 Added additional sanitization to donor output.
86 + * @since 4.13.2 add strip_shortcodes to the html output
87 + * @since 4.3.1 remove redundant _give_redirect_form_id() function.
88 + * @since 3.7.0 Sanitize attributes
89 + * @since 2.27.0 Moved AJAX nonce verification to ajax_handler method.
90 + * @since 2.2.0
91 + *
92 + * @param array $atts {
93 + * Optional. Attributes of the donor wall shortcode.
94 + *
95 + * @type int $donors_per_page Number of donors per page. Default '20'.
96 + * @type int $form_id The donation form to filter donors by. Default is all forms (no filter).
97 + * @type bool $paged Whether to paginate donors. Default 'true'.
98 + * @type string $ids A comma-separated list of donor IDs to display. Default empty.
99 + * @type string $columns Maximum columns to display. Default 'best-fit'.
100 + * Accepts 'best-fit', '1', '2', '3', '4'.
101 + * @type bool $show_avatar Whether to display the donor's gravatar image if available. Default 'true'.
102 + * @type bool $show_name Whether to display the donor's full name, first and last. Default 'true'.
103 + * @type bool $show_company_name Whether to display the donor's company name. Default 'false'.
104 + * @type bool $show_total Whether to display the donor's donation amount. Default 'true'.
105 + * @type bool $show_comments Whether to display the donor's comment if they left one. Default 'true'.
106 + * @type int $comment_length The number of words to display for the comments before a "Read more" field
107 + * @type int $only_comments Whether to display the donors only with comment. Default 'false'.
108 + * @type bool $show_time Whether to display date of the last donation. Default 'true'.
109 + *
110 + * @type string $readmore_text Link label for modal in which donor can read full comment.
111 + * @type string $loadmore_text Button label which will load more donor comments.
112 + * @type int $avatar_size Avatar image size in pixels without the "px". Default "75"
113 + * @type string $orderby The order in which you want the donations to appear.
114 + * Currently we are using this attribute internally and, it will sort donations by created date.
115 + * @type string $order The order in which you want the donors to appear. Accepts "ASC". "DESC".
116 + *
117 + * }
118 + * @return string|bool The markup of the form grid or false.
119 + */
111 120 public function render_shortcode( $atts ) {
121 + $atts = give_clean($atts);
112 122
113 123 $give_settings = give_get_settings();
114 124
115 125 $atts = $this->parse_atts( $atts );
126 +
116 127 $donations = $this->get_donation_data( $atts );
117 128 $html = '';
118 129
119 130 if ( $donations ) {
@@ -120,16 +131,28 @@
120 131
121 132 ob_start();
122 133
123 134 foreach ( $donations as $donation ) {
124 - // Give/templates/shortcode-donor-wall.php.
125 - give_get_template( 'shortcode-donor-wall', array( $donation, $give_settings, $atts ) );
126 - }
135 + $donor = new Give_Donor($donation['_give_payment_donor_id']);
136 + // Give/templates/shortcode-donor-wall.php.
137 + give_get_template(
138 + 'shortcode-donor-wall',
139 + [
140 + $donation,
141 + $give_settings,
142 + $atts,
143 + $donor
144 + ]
145 + );
146 + }
127 147
128 148 $html = ob_get_clean();
129 149
130 - // Return only donor html.
131 - if (
150 + // Strip shortcodes to prevent execution of user-supplied shortcode syntax.
151 + $html = give_strip_shortcodes_deep($html);
152 +
153 + // Return only donor html.
154 + if (
132 155 isset( $atts['only_donor_html'] )
133 156 && wp_doing_ajax()
134 157 && $atts['only_donor_html']
135 158 ) {
@@ -140,10 +163,11 @@
140 163 $temp_atts = $atts;
141 164 $temp_atts['paged'] = $atts['paged'] + 1;
142 165
143 166 $more_btn_html = sprintf(
144 - '<input type="hidden" class="give-donor-wall-shortcode-attrs" data-shortcode="%1$s">',
145 - rawurlencode( http_build_query( $atts ) )
167 + '<input type="hidden" class="give-donor-wall-shortcode-attrs" data-shortcode="%s" data-nonce="%s">',
168 + rawurlencode( http_build_query( $atts ) ),
169 + wp_create_nonce( 'givewp-donor-wall-more' )
146 170 );
147 171
148 172 if ( $this->has_donations( $temp_atts ) ) {
149 173 $more_btn_html .= sprintf(
@@ -166,8 +190,9 @@
166 190
167 191 /**
168 192 * Parse shortcode attributes
169 193 *
194 + * @since 2.30.0
170 195 * @since 2.2.0
171 196 * @access public
172 197 *
173 198 * @param array $atts Shortcode attributes.
@@ -175,44 +200,54 @@
175 200 * @return array
176 201 */
177 202 public function parse_atts( $atts ) {
178 203 $atts = shortcode_atts(
179 - array(
180 - 'donors_per_page' => 12,
181 - 'form_id' => 0,
182 - 'paged' => 1,
183 - 'ids' => '',
184 - 'columns' => 'best-fit',
185 - 'show_avatar' => true,
186 - 'show_name' => true,
187 - 'show_total' => true,
188 - 'show_time' => true,
189 - 'show_comments' => true,
190 - 'comment_length' => 140,
191 - 'only_comments' => false,
192 - 'readmore_text' => esc_html__( 'Read more', 'give' ),
193 - 'loadmore_text' => esc_html__( 'Load more', 'give' ),
194 - 'avatar_size' => 60,
195 - 'orderby' => 'post_date', // Only for internal use.
196 - 'order' => 'DESC',
197 - 'hide_empty' => true, // Deprecated in 2.3.0
198 - 'only_donor_html' => false, // Only for internal use.
199 - ), $atts
204 + [
205 + 'donors_per_page' => 12,
206 + 'form_id' => 0,
207 + 'paged' => 1,
208 + 'ids' => '',
209 + 'cats' => '',
210 + 'tags' => '',
211 + 'columns' => '3',
212 + 'anonymous' => true,
213 + 'show_avatar' => true,
214 + 'show_name' => true,
215 + 'show_company_name' => false,
216 + 'show_form' => false,
217 + 'show_total' => true,
218 + 'show_comments' => true,
219 + 'show_tributes' => true,
220 + 'comment_length' => 140,
221 + 'only_comments' => false,
222 + 'readmore_text' => esc_html__( 'Read more', 'give' ),
223 + 'loadmore_text' => esc_html__( 'Load more', 'give' ),
224 + 'avatar_size' => 75,
225 + 'color' => "#219653",
226 + 'orderby' => 'post_date',
227 + 'order' => 'DESC',
228 + 'hide_empty' => true, // Deprecated in 2.3.0
229 + 'only_donor_html' => false, // Only for internal use.,
230 + 'show_time' => true,
231 + ],
232 + $atts,
233 + 'give_donor_wall'
200 234 );
201 235
202 -
203 236 // Validate boolean attributes.
204 - $boolean_attributes = array(
237 + $boolean_attributes = [
238 + 'anonymous',
205 239 'show_avatar',
206 240 'show_name',
241 + 'show_company_name',
207 242 'show_total',
208 - 'show_time',
209 243 'show_comments',
210 - 'show_comments',
244 + 'show_tributes',
211 245 'hide_empty',
212 246 'only_comments',
213 247 'only_donor_html',
214 - );
248 + 'show_time'
249 + ];
215 250
216 251 foreach ( $boolean_attributes as $att ) {
217 252 // Convert numeric to boolean.
218 253 // It will prevent condition check against boolean value.
@@ -222,8 +257,41 @@
222 257
223 258 $atts[ $att ] = filter_var( $atts[ $att ], FILTER_VALIDATE_BOOLEAN );
224 259 }
225 260
261 + // Validate numeric attributes.
262 + $numeric_attributes = [
263 + 'donors_per_page',
264 + 'paged',
265 + 'comment_length',
266 + 'avatar_size',
267 + ];
268 +
269 + foreach ( $numeric_attributes as $att ) {
270 + // It will prevent condition check against numeric value.
271 + $atts[ $att ] = absint( $atts[ $att ] );
272 + }
273 +
274 + // Validate comma separated numeric attributes and keep original data format ( comma separated string).
275 + if ( ! empty( $atts['ids'] ) ) {
276 + $atts['ids'] = implode( ',', $this->split_string($atts['ids'], 'absint') );
277 + }
278 +
279 + // Validate Form IDs
280 + if ( ! empty( $atts['form_id'] ) ) {
281 + $atts['form_id'] = implode( ',', $this->split_string($atts['form_id'], 'absint') );
282 + }
283 +
284 + // Donation form categories
285 + if ( ! empty( $atts['cats'] ) ) {
286 + $atts['cats'] = $this->split_string($atts['cats']);
287 + }
288 +
289 + // Donation form tags
290 + if ( ! empty( $atts['tags'] ) ) {
291 + $atts['tags'] = $this->split_string($atts['tags']);
292 + }
293 +
226 294 return $atts;
227 295 }
228 296
229 297 /**
@@ -231,33 +299,35 @@
231 299 *
232 300 * @since 2.2.0
233 301 * @access public
234 302 *
235 - * @param array $donor_query Dorno query.
303 + * @param array $donor_query Donor query.
236 304 *
237 305 * @return array
238 306 */
239 307 public function get_donors( $donor_query ) {
240 308 $donor_query = new Give_Donors_Query( $donor_query );
241 - $donors = $donor_query->get_donors();
242 309
243 - return $donors;
310 + return $donor_query->get_donors();
244 311 }
245 312
246 313
247 314 /**
248 - * Ajax handler
315 + * This function should return donor comment for ajax request.
249 316 *
317 + * @since 2.27.0 Check nonce for AJAX request to prevent scrapping, see https://github.com/impress-org/givewp/issues/6374.
250 318 * @since 2.2.0
251 319 * @access public
252 320 */
253 321 public function ajax_handler() {
254 - $shortcode_atts = wp_parse_args( give_clean( rawurldecode( $_POST['data'] ) ) ); // @codingStandardsIgnoreLine
322 + $shortcode_atts = array_map( 'give_clean', wp_parse_args( rawurldecode( $_POST['data'] ) ) ); // @codingStandardsIgnoreLine
255 323
256 324 // Get next page donor comments.
257 325 $shortcode_atts['paged'] = $shortcode_atts['paged'] + 1;
258 326 $shortcode_atts['only_donor_html'] = true;
259 327
328 + check_ajax_referer( 'givewp-donor-wall-more', 'nonce' );
329 +
260 330 $donors_comment_html = $this->render_shortcode( $shortcode_atts );
261 331
262 332 // Check if donor comment remaining.
263 333 $temp_atts = $shortcode_atts;
@@ -267,13 +337,13 @@
267 337 // Remove internal shortcode param.
268 338 unset( $shortcode_atts['only_donor_html'] );
269 339
270 340 wp_send_json(
271 - array(
341 + [
272 342 'shortcode' => rawurlencode( http_build_query( $shortcode_atts ) ),
273 343 'html' => $donors_comment_html,
274 344 'remaining' => $has_donors,
275 - )
345 + ]
276 346 );
277 347 }
278 348
279 349 /**
@@ -278,8 +348,9 @@
278 348
279 349 /**
280 350 * Get query params
281 351 *
352 + * @since 2.24.1
282 353 * @since 2.3.0
283 354 *
284 355 * @param array $atts
285 356 *
@@ -284,41 +355,47 @@
284 355 * @param array $atts
285 356 *
286 357 * @return array
287 358 */
288 - private function get_query_param( $atts = array() ) {
289 - $valid_order = array( 'ASC', 'DESC' );
290 - $valid_orderby = array( 'post_date' );
359 + private function get_query_param( $atts = [] ) {
360 + $valid_order = [ 'ASC', 'DESC' ];
361 + $valid_orderby = [ 'post_date', 'donation_amount' ];
291 362
292 - $query_atts = array();
363 + $query_atts = [];
293 364
294 365 $query_atts['order'] = in_array( $atts['order'], $valid_order ) ? $atts['order'] : 'DESC';
295 366 $query_atts['orderby'] = in_array( $atts['orderby'], $valid_orderby ) ? $atts['orderby'] : 'post_date';
296 - $query_atts['limit'] = $atts['donors_per_page'];
297 - $query_atts['offset'] = $atts['donors_per_page'] * ( $atts['paged'] - 1 );
298 - $query_atts['form_id'] = $atts['form_id'];
367 + $query_atts['limit'] = absint( $atts['donors_per_page'] );
368 + $query_atts['offset'] = absint( $atts['donors_per_page'] * ( $atts['paged'] - 1 ) );
369 + $query_atts['form_id'] = implode( '\',\'', array_map( 'absint', explode( ',', $atts['form_id'] ) ) );
370 + $query_atts['ids'] = implode( '\',\'', array_map( 'absint', explode( ',', $atts['ids'] ) ) );
371 + $query_atts['cats'] = $atts['cats'];
372 + $query_atts['tags'] = $atts['tags'];
299 373 $query_atts['only_comments'] = ( true === $atts['only_comments'] );
374 + $query_atts['anonymous'] = ( true === $atts['anonymous'] );
300 375
376 +
377 +
301 378 return $query_atts;
302 379 }
303 380
304 - /**
305 - * Get donation data.
306 - *
307 - * @since 2.3.0
308 - *
309 - * @param array $atts
310 - *
311 - * @return array
312 - */
313 - private function get_donation_data( $atts = array() ) {
381 + /**
382 + * Get donation data.
383 + *
384 + * @since 4.16.7.2 Restrict unserialize to prevent object instantiation.
385 + * @since 2.27.0 Change to read comment from donations meta table
386 + * @since 2.3.0
387 + *
388 + * @param array $atts
389 + *
390 + * @return array
391 + */
392 + private function get_donation_data( $atts = [] ) {
314 393 global $wpdb;
315 394
316 - $query_params = $this->get_query_param( $atts );
317 -
318 395 // Bailout if donation does not exist.
319 396 if ( ! ( $donation_ids = $this->get_donations( $atts ) ) ) {
320 - return array();
397 + return [];
321 398 }
322 399
323 400 $donation_ids = ! empty( $donation_ids )
324 401 ? '\'' . implode( '\',\'', $donation_ids ) . '\''
@@ -326,40 +403,48 @@
326 403
327 404 // Backward compatibility
328 405 $donation_id_col = Give()->payment_meta->get_meta_type() . '_id';
329 406
330 - $sql = "SELECT * FROM {$wpdb->donationmeta} as m1
407 + $sql = "SELECT m1.*, p1.post_date as donation_date FROM {$wpdb->donationmeta} as m1
331 408 INNER JOIN {$wpdb->posts} as p1 ON (m1.{$donation_id_col}=p1.ID)
332 409 WHERE m1.{$donation_id_col} IN ( {$donation_ids} )
333 - ORDER BY p1.post_date {$query_params['order']}, p1.ID {$query_params['order']}
410 + ORDER BY FIELD( p1.ID, {$donation_ids} )
334 411 ";
335 412
336 413 $results = (array) $wpdb->get_results( $sql );
337 414
338 415 if ( ! empty( $results ) ) {
339 - $temp = array();
416 + $temp = [];
340 417
341 418 /* @var stdClass $result */
342 419 foreach ( $results as $result ) {
343 - $temp[ $result->{$donation_id_col} ][ $result->meta_key ] = maybe_unserialize( $result->meta_value );
420 + $temp[ $result->{$donation_id_col} ][ $result->meta_key ] = unserialize( $result->meta_value, [ 'allowed_classes' => false ] );
421 +
422 + // Set donation date.
423 + if ( empty( $temp[ $result->{$donation_id_col} ]['donation_date'] ) ) {
424 + $temp[ $result->{$donation_id_col} ]['donation_date'] = $result->donation_date;
425 + }
344 426 }
345 427
346 - $comments = $this->get_donor_comments($temp);
347 -
348 428 if ( ! empty( $temp ) ) {
349 429 foreach ( $temp as $donation_id => $donation_data ) {
350 430 $temp[ $donation_id ]['donation_id'] = $donation_id;
351 431
352 - $temp[ $donation_id ]['name_initial'] = give_get_name_initial( array(
353 - 'firstname' => $donation_data['_give_donor_billing_first_name'],
354 - 'lastname' => $donation_data['_give_donor_billing_last_name'],
355 - ) );
432 + $temp[ $donation_id ]['name_initial'] = give_get_name_initial(
433 + [
434 + 'firstname' => $donation_data['_give_donor_billing_first_name'],
435 + 'lastname' => $donation_data['_give_donor_billing_last_name'],
436 + ]
437 + );
356 438
357 - $temp[ $donation_id ]['donor_comment'] = ! empty( $comments[$donation_id] ) ? $comments[$donation_id] : '';
439 + $temp[$donation_id]['donor_comment'] = give_get_payment_meta(
440 + $donation_id,
441 + DonationMetaKeys::COMMENT
442 + );
358 443 }
359 444 }
360 445
361 - $results = ! empty( $temp ) ? $temp : array();
446 + $results = ! empty( $temp ) ? $temp : [];
362 447 }
363 448
364 449 return $results;
365 450 }
@@ -366,8 +451,9 @@
366 451
367 452 /**
368 453 * Get donation list for specific query
369 454 *
455 + * @since 3.17.2 fix - filter by only_comments attr
370 456 * @since 2.3.0
371 457 *
372 458 * @param array $atts
373 459 *
@@ -372,9 +458,9 @@
372 458 * @param array $atts
373 459 *
374 460 * @return array
375 461 */
376 - private function get_donations( $atts = array() ) {
462 + private function get_donations( $atts = [] ) {
377 463 global $wpdb;
378 464
379 465 // Backward compatibility
380 466 $donation_id_col = Give()->payment_meta->get_meta_type() . '_id';
@@ -387,32 +473,94 @@
387 473 // exclude donation with zero amount from result.
388 474 $sql .= " INNER JOIN {$wpdb->donationmeta} as m1 ON (p1.ID = m1.{$donation_id_col})";
389 475 $where .= " AND m1.meta_key='_give_payment_total' AND m1.meta_value>0";
390 476
391 -
392 477 if ( $query_params['form_id'] ) {
393 478 $sql .= " INNER JOIN {$wpdb->donationmeta} as m2 ON (p1.ID = m2.{$donation_id_col})";
394 - $where .= " AND m2.meta_key='_give_payment_form_id' AND m2.meta_value={$query_params['form_id']}";
479 + $where .= " AND m2.meta_key='_give_payment_form_id' AND m2.meta_value IN ('{$query_params['form_id']}')";
395 480 }
396 481
482 + // Get donations only from specific donors.
483 + if ( $query_params['ids'] ) {
484 + $sql .= " INNER JOIN {$wpdb->donationmeta} as m3 ON (p1.ID = m3.{$donation_id_col})";
485 + $where .= " AND m3.meta_key='_give_payment_donor_id' AND m3.meta_value IN ('{$query_params['ids']}')";
486 + }
487 +
397 488 // exclude donations which does not has donor comment.
398 489 if ( $query_params['only_comments'] ) {
399 - $sql .= " INNER JOIN {$wpdb->give_comments} as gc1 ON (p1.ID = gc1.comment_parent)";
400 - $where .= " AND gc1.comment_type='donor_donation'";
490 + $sql .= " INNER JOIN {$wpdb->donationmeta} as m4 ON (p1.ID = m4.{$donation_id_col})";
491 + $where .= " AND m4.meta_key='_give_donation_comment'";
401 492 }
402 493
403 - // exclude anonymous donation form query.
404 - $where .= " AND p1.ID NOT IN ( SELECT DISTINCT({$donation_id_col}) FROM {$wpdb->donationmeta} WHERE meta_key='_give_anonymous_donation' AND meta_value='1')";
494 + // exclude anonymous donation form query based on query parameters.
495 + if (
496 + ! $query_params['anonymous']
497 + || $query_params['only_comments']
498 + ) {
499 + $where .= " AND p1.ID NOT IN ( SELECT DISTINCT({$donation_id_col}) FROM {$wpdb->donationmeta} WHERE meta_key='_give_anonymous_donation' AND meta_value='1')";
500 + }
405 501
406 - $order = " ORDER BY p1.{$query_params['orderby']} {$query_params['order']}, p1.ID {$query_params['order']}";
502 + // Handle Taxonomy
503 + $args = [
504 + 'post_type' => 'give_forms',
505 + 'posts_per_page' => -1,
506 + 'fields' => 'ids',
507 + 'tax_query' => [],
508 + ];
509 +
510 + // Categories
511 + if ( is_array($atts['cats'])) {
512 + $args['tax_query']['conditions'] = ['relation' => 'OR'];
513 +
514 + foreach ($atts['cats'] as $category) {
515 + $args['tax_query']['conditions'][] = [
516 + 'operator' => 'IN',
517 + 'taxonomy' => 'give_forms_category',
518 + 'field' => 'slug',
519 + 'terms' => $category,
520 + ];
521 + }
522 + }
523 +
524 + // Tags
525 + if ( is_array($atts['tags'])) {
526 + if (empty($args['tax_query'])) {
527 + $args['tax_query']['conditions'] = ['relation' => 'OR'];
528 + }
529 +
530 + foreach($atts['tags'] as $tag) {
531 + $args['tax_query']['conditions'][] = [
532 + 'operator' => 'IN',
533 + 'taxonomy' => 'give_forms_tag',
534 + 'field' => 'slug',
535 + 'terms' => $tag,
536 + ];
537 + }
538 + }
539 +
540 + if ( ! empty( $args['tax_query'] ) ) {
541 + $query = new WP_Query( $args );
542 +
543 + if ( ! empty($query->posts) ) {
544 + $form_ids = implode("','", $query->posts );
545 + $sql .= " INNER JOIN {$wpdb->donationmeta} as m4 ON (p1.ID = m4.{$donation_id_col})";
546 + $where .= " AND m4.meta_key='_give_payment_form_id' AND m4.meta_value IN ('{$form_ids}')";
547 + }
548 + }
549 +
550 + // order by query based on parameter.
551 + if ( 'donation_amount' === $query_params['orderby'] ) {
552 + $order = " ORDER BY m1.meta_value+0 {$query_params['order']}";
553 + } else {
554 + $order = " ORDER BY p1.{$query_params['orderby']} {$query_params['order']}, p1.ID {$query_params['order']}";
555 + }
556 +
407 557 $limit = " LIMIT {$query_params['limit']}";
408 558 $offset = " OFFSET {$query_params['offset']}";
409 559
410 - $sql = $sql . $where . $order . $limit . $offset;
560 + $sql .= $where . $order . $limit . $offset;
411 561
412 - $donation_ids = $wpdb->get_col( $sql );
413 -
414 - return $donation_ids;
562 + return $wpdb->get_col( $sql );
415 563 }
416 564
417 565 /**
418 566 * Get donor comments
@@ -422,14 +570,14 @@
422 570 * @param array $donations_data
423 571 *
424 572 * @return array
425 573 */
426 - private function get_donor_comments( $donations_data = array() ) {
574 + private function get_donor_comments( $donations_data = [] ) {
427 575 global $wpdb;
428 - $comments = array();
576 + $comments = [];
429 577
430 578 // Bailout.
431 - if( empty( $donations_data ) ) {
579 + if ( empty( $donations_data ) ) {
432 580 return $comments;
433 581 }
434 582
435 583 // Backward compatibility.
@@ -437,31 +585,36 @@
437 585 ! give_has_upgrade_completed( 'v230_move_donor_note' )
438 586 || ! give_has_upgrade_completed( 'v230_move_donation_note' )
439 587 ) {
440 588 foreach ( $donations_data as $id => $data ) {
441 - $comment = give_get_donor_donation_comment( $id, $data['_give_payment_donor_id'] );
442 - $comments[$id] = ! empty( $comment ) ? $comment->comment_content : '';
589 + $comment = give_get_donor_donation_comment( $id, $data['_give_payment_donor_id'] );
590 + $comments[ $id ] = ! empty( $comment ) ? $comment->comment_content : '';
443 591 }
444 592
445 593 return $comments;
446 594 }
447 595
448 - $sql = "SELECT c1.comment_parent as donation_id, c1.comment_content as comment FROM {$wpdb->give_comments} as c1";
449 - $sql .= " INNER JOIN {$wpdb->give_commentmeta} as cm1 ON (c1.comment_ID=cm1.give_comment_id)";
450 - $where = array();
596 + $sql = "SELECT c1.comment_parent as donation_id, c1.comment_content as comment FROM {$wpdb->give_comments} as c1";
597 + $sql .= " INNER JOIN {$wpdb->give_commentmeta} as cm1 ON (c1.comment_ID=cm1.give_comment_id)";
598 + $where = [];
451 599
452 600 foreach ( $donations_data as $id => $data ) {
601 + // Do not fetch comment for anonymous donation.
602 + if ( ! empty( $data['_give_anonymous_donation'] ) ) {
603 + continue;
604 + }
605 +
453 606 $where[] = "(c1.comment_parent={$id} AND cm1.meta_key='_give_donor_id' AND cm1.meta_value={$data['_give_payment_donor_id']})";
454 607 }
455 608
456 - $where = ' WHERE '. implode( ' OR ', $where );
609 + $where = ' WHERE ' . implode( ' OR ', $where );
457 610 $where .= " AND c1.comment_type='donor_donation'";
458 611
459 - $sql = $sql.$where;
612 + $sql = $sql . $where;
460 613
461 614 $comments = (array) $wpdb->get_results( $sql );
462 615
463 - if( ! empty( $comments ) ) {
616 + if ( ! empty( $comments ) ) {
464 617 $comments = array_combine(
465 618 wp_list_pluck( $comments, 'donation_id' ),
466 619 wp_list_pluck( $comments, 'comment' )
467 620 );
@@ -478,11 +631,46 @@
478 631 * @param array $atts
479 632 *
480 633 * @return bool
481 634 */
482 - private function has_donations( $atts = array() ) {
635 + private function has_donations( $atts = [] ) {
483 636 return (bool) $this->get_donations( $atts );
484 637 }
638 +
639 + /**
640 + * @since 2.20.0
641 + *
642 + * @param string $string
643 + * @param null|callable $filter
644 + * @param string $separator
645 + *
646 + * @return array
647 + */
648 + private function split_string($string, $filter = null, $separator = ',') {
649 + if ( false === strpos( $string, $separator ) ) {
650 + $string = trim( $string );
651 +
652 + if (is_callable($filter)) {
653 + $string = $filter($string);
654 + }
655 +
656 + return [$string];
657 + }
658 +
659 + return array_filter(
660 + array_map(
661 + static function( $value ) use ($filter) {
662 + $value = trim( $value );
663 +
664 + if (is_callable($filter)) {
665 + return $filter($value);
666 + }
667 + return $value;
668 + },
669 + explode( $separator, $string )
670 + )
671 + );
672 + }
485 673 }
486 674
487 675 // Initialize shortcode.
488 676 Give_Donor_Wall::get_instance();