PluginProbe ʕ •ᴥ•ʔ
GiveWP – Donation Plugin and Fundraising Platform / 2.4.5
GiveWP – Donation Plugin and Fundraising Platform v2.4.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 2.30.0 2.31.0 2.31.1 2.32.0 2.33.0 2.33.1 2.33.2 2.33.3 2.33.4 2.33.5 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.4.5 2.4.6 2.4.7 2.5.0 2.5.1 2.5.10 2.5.11 2.5.12 2.5.13 2.5.2 2.5.3 2.5.4 2.5.5 2.5.6 2.5.7 2.5.8 2.5.9 2.6.0 2.6.1 2.6.2 2.6.3 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.8.0 2.8.1 2.9.0 2.9.1 2.9.2 2.9.3 2.9.4 2.9.5 2.9.6 2.9.7 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.1.0 3.1.1 3.1.2 3.10.0 3.11.0 3.12.0 3.12.1 3.12.2 3.12.3 3.13.0 3.14.0 3.14.1 3.14.2 3.15.0 3.15.1 3.16.0 3.16.1 3.16.2 3.16.3 3.16.4 3.16.5 3.17.0 3.17.1 3.17.2 3.18.0 3.19.0 3.19.1 3.19.2 3.19.3 3.19.4 3.2.0 3.2.1 3.2.2 3.20.0 3.21.0 3.21.1 3.22.0 3.22.1 3.22.2 3.3.0 3.3.1 3.4.0 3.4.1 3.4.2 3.5.0 3.5.1 3.6.0 3.6.1 3.6.2 3.7.0 3.8.0 3.9.0 4.0.0 4.1.0 4.1.1 4.10.0 4.10.1 4.11.0 4.12.0 4.13.0 4.13.1 4.13.2 4.14.0 4.14.1 4.14.2 4.14.3 4.14.4 4.14.5 4.14.6 4.2.0 4.2.1 4.3.0 4.3.1 4.3.2 4.4.0 4.5.0 4.6.1 4.7.0 4.7.1 4.8.0 4.8.1 4.9.0 trunk 1.9.0 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.10.0 2.10.1 2.10.2 2.10.3 2.10.4 2.11.0 2.11.1 2.11.2 2.11.3 2.12.0 2.12.1 2.12.2 2.12.3 2.13.0 2.13.1 2.13.2 2.13.3 2.13.4 2.14.0 2.15.0 2.16.0 2.16.1 2.17.0 2.17.1 2.17.3 2.18.0 2.18.1 2.19.1 2.19.2 2.19.3 2.19.4 2.19.5 2.19.6 2.19.7 2.19.8 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 2.20.0 2.20.1 2.20.2 2.21.0 2.21.1 2.21.2 2.21.3 2.21.4 2.22.0 2.22.1 2.22.2 2.22.3 2.23.0 2.23.1 2.23.2 2.24.0 2.24.1 2.24.2 2.25.0 2.25.1 2.25.2 2.25.3 2.26.0 2.27.0 2.27.1 2.27.2 2.27.3 2.28.0 2.29.0 2.29.1 2.29.2
give / includes / donors / class-give-donor-wall.php
give / includes / donors Last commit date
actions.php 7 years ago backward-compatibility.php 7 years ago class-give-donor-stats.php 7 years ago class-give-donor-wall.php 7 years ago class-give-donors-query.php 7 years ago frontend-donor-functions.php 7 years ago
class-give-donor-wall.php
512 lines
1 <?php
2 /**
3 * Donors Gravatars
4 *
5 * @package Give
6 * @subpackage Classes/Give_Donors_Gravatars
7 * @copyright Copyright (c) 2016, GiveWP
8 * @license https://opensource.org/licenses/gpl-license GNU Public License
9 * @since 1.0
10 */
11
12 // Exit if accessed directly.
13 if ( ! defined( 'ABSPATH' ) ) {
14 exit;
15 }
16
17
18 /**
19 * Give_Donor_Wall Class
20 *
21 * This class handles donors.
22 *
23 * @since 2.2.0
24 */
25 class Give_Donor_Wall {
26
27 /**
28 * Instance.
29 *
30 * @since 2.2.0
31 * @access private
32 * @var Give_Donor_Wall
33 */
34 static private $instance;
35
36 /**
37 * Singleton pattern.
38 *
39 * @since 2.2.0
40 * @access private
41 */
42 private function __construct() {
43 }
44
45
46 /**
47 * Get instance.
48 *
49 * @since 2.2.0
50 * @access public
51 * @return Give_Donor_Wall
52 */
53 public static function get_instance() {
54 if ( null === static::$instance ) {
55 self::$instance = new static();
56
57 self::$instance->setup_actions();
58 }
59
60 return self::$instance;
61 }
62
63 /**
64 * Setup the default hooks and actions
65 *
66 * @since 2.2.0
67 *
68 * @return void
69 */
70 public function setup_actions() {
71
72 add_shortcode( 'give_donor_wall', array( $this, 'render_shortcode' ) );
73
74 add_action( 'wp_ajax_give_get_donor_comments', array( $this, 'ajax_handler' ) );
75 add_action( 'wp_ajax_nopriv_give_get_donor_comments', array( $this, 'ajax_handler' ) );
76
77 }
78
79
80 /**
81 * Displays donors in a grid layout.
82 *
83 * @since 2.2.0
84 *
85 * @param array $atts {
86 * Optional. Attributes of the donor wall shortcode.
87 *
88 * @type int $donors_per_page Number of donors per page. Default '20'.
89 * @type int $form_id The donation form to filter donors by. Default is all forms (no filter).
90 * @type bool $paged Whether to paginate donors. Default 'true'.
91 * @type string $ids A comma-separated list of donor IDs to display. Default empty.
92 * @type string $columns Maximum columns to display. Default 'best-fit'.
93 * Accepts 'best-fit', '1', '2', '3', '4'.
94 * @type bool $show_avatar Whether to display the donor's gravatar image if available. Default 'true'.
95 * @type bool $show_name Whether to display the donor's full name, first and last. Default 'true'.
96 * @type bool $show_total Whether to display the donor's donation amount. Default 'true'.
97 * @type bool $show_time Whether to display date of the last donation. Default 'true'.
98 * @type bool $show_comments Whether to display the donor's comment if they left one. Default 'true'.
99 * @type int $comment_length The number of words to display for the comments before a "Read more" field
100 * @type int $only_comments Whether to display the donors only with comment. Default 'false'.
101 *
102 * @type string $readmore_text Link label for modal in which donor can read full comment.
103 * @type string $loadmore_text Button label which will load more donor comments.
104 * @type int $avatar_size Avatar image size in pixels without the "px". Default "60"
105 * @type string $orderby The order in which you want the donations to appear.
106 * Currently we are using this attribute internally and it will sort donations by created date.
107 * @type string $order The order in which you want the donors to appear. Accepts "ASC". "DESC".
108 *
109 * }
110 * @return string|bool The markup of the form grid or false.
111 */
112 public function render_shortcode( $atts ) {
113
114 $give_settings = give_get_settings();
115
116 $atts = $this->parse_atts( $atts );
117 $donations = $this->get_donation_data( $atts );
118 $html = '';
119
120 if ( $donations ) {
121
122 ob_start();
123
124 foreach ( $donations as $donation ) {
125 // Give/templates/shortcode-donor-wall.php.
126 give_get_template( 'shortcode-donor-wall', array( $donation, $give_settings, $atts ) );
127 }
128
129 $html = ob_get_clean();
130
131 // Return only donor html.
132 if (
133 isset( $atts['only_donor_html'] )
134 && wp_doing_ajax()
135 && $atts['only_donor_html']
136 ) {
137 return $html;
138 }
139 }
140
141 $temp_atts = $atts;
142 $temp_atts['paged'] = $atts['paged'] + 1;
143
144 $more_btn_html = sprintf(
145 '<input type="hidden" class="give-donor-wall-shortcode-attrs" data-shortcode="%1$s">',
146 rawurlencode( http_build_query( $atts ) )
147 );
148
149 if ( $this->has_donations( $temp_atts ) ) {
150 $more_btn_html .= sprintf(
151 '<button class="give-donor__load_more give-button-with-loader"><span class="give-loading-animation"></span>%1$s</button>',
152 $atts['loadmore_text']
153 );
154 }
155
156 $html = $html
157 ? sprintf(
158 '<div class="give-wrap give-grid-ie-utility"><div class="give-grid give-grid--%1$s">%2$s</div>%3$s</div>',
159 esc_attr( $atts['columns'] ),
160 $html,
161 $more_btn_html
162 )
163 : '';
164
165 return $html;
166 }
167
168 /**
169 * Parse shortcode attributes
170 *
171 * @since 2.2.0
172 * @access public
173 *
174 * @param array $atts Shortcode attributes.
175 *
176 * @return array
177 */
178 public function parse_atts( $atts ) {
179 $atts = shortcode_atts(
180 array(
181 'donors_per_page' => 12,
182 'form_id' => 0,
183 'paged' => 1,
184 'ids' => '',
185 'columns' => 'best-fit',
186 'anonymous' => true,
187 'show_avatar' => true,
188 'show_name' => true,
189 'show_total' => true,
190 'show_time' => true,
191 'show_comments' => true,
192 'comment_length' => 140,
193 'only_comments' => false,
194 'readmore_text' => esc_html__( 'Read more', 'give' ),
195 'loadmore_text' => esc_html__( 'Load more', 'give' ),
196 'avatar_size' => 60,
197 'orderby' => 'post_date',
198 'order' => 'DESC',
199 'hide_empty' => true, // Deprecated in 2.3.0
200 'only_donor_html' => false, // Only for internal use.
201 ), $atts
202 );
203
204
205 // Validate boolean attributes.
206 $boolean_attributes = array(
207 'anonymous',
208 'show_avatar',
209 'show_name',
210 'show_total',
211 'show_time',
212 'show_comments',
213 'show_comments',
214 'hide_empty',
215 'only_comments',
216 'only_donor_html',
217 );
218
219 foreach ( $boolean_attributes as $att ) {
220 // Convert numeric to boolean.
221 // It will prevent condition check against boolean value.
222 if ( is_numeric( $atts[ $att ] ) ) {
223 $atts[ $att ] = (bool) $atts[ $att ];
224 }
225
226 $atts[ $att ] = filter_var( $atts[ $att ], FILTER_VALIDATE_BOOLEAN );
227 }
228
229 return $atts;
230 }
231
232 /**
233 * Get donors
234 *
235 * @since 2.2.0
236 * @access public
237 *
238 * @param array $donor_query Dorno query.
239 *
240 * @return array
241 */
242 public function get_donors( $donor_query ) {
243 $donor_query = new Give_Donors_Query( $donor_query );
244 $donors = $donor_query->get_donors();
245
246 return $donors;
247 }
248
249
250 /**
251 * Ajax handler
252 *
253 * @since 2.2.0
254 * @access public
255 */
256 public function ajax_handler() {
257 $shortcode_atts = wp_parse_args( give_clean( rawurldecode( $_POST['data'] ) ) ); // @codingStandardsIgnoreLine
258
259 // Get next page donor comments.
260 $shortcode_atts['paged'] = $shortcode_atts['paged'] + 1;
261 $shortcode_atts['only_donor_html'] = true;
262
263 $donors_comment_html = $this->render_shortcode( $shortcode_atts );
264
265 // Check if donor comment remaining.
266 $temp_atts = $shortcode_atts;
267 $temp_atts['paged'] = $shortcode_atts['paged'] + 1;
268 $has_donors = $this->has_donations( $temp_atts ) ? 1 : 0;
269
270 // Remove internal shortcode param.
271 unset( $shortcode_atts['only_donor_html'] );
272
273 wp_send_json(
274 array(
275 'shortcode' => rawurlencode( http_build_query( $shortcode_atts ) ),
276 'html' => $donors_comment_html,
277 'remaining' => $has_donors,
278 )
279 );
280 }
281
282 /**
283 * Get query params
284 *
285 * @since 2.3.0
286 *
287 * @param array $atts
288 *
289 * @return array
290 */
291 private function get_query_param( $atts = array() ) {
292 $valid_order = array( 'ASC', 'DESC' );
293 $valid_orderby = array( 'post_date', 'donation_amount' );
294
295 $query_atts = array();
296
297 $query_atts['order'] = in_array( $atts['order'], $valid_order ) ? $atts['order'] : 'DESC';
298 $query_atts['orderby'] = in_array( $atts['orderby'], $valid_orderby ) ? $atts['orderby'] : 'post_date';
299 $query_atts['limit'] = $atts['donors_per_page'];
300 $query_atts['offset'] = $atts['donors_per_page'] * ( $atts['paged'] - 1 );
301 $query_atts['form_id'] = $atts['form_id'];
302 $query_atts['only_comments'] = ( true === $atts['only_comments'] );
303 $query_atts['anonymous'] = ( true === $atts['anonymous'] );
304
305 return $query_atts;
306 }
307
308 /**
309 * Get donation data.
310 *
311 * @since 2.3.0
312 *
313 * @param array $atts
314 *
315 * @return array
316 */
317 private function get_donation_data( $atts = array() ) {
318 global $wpdb;
319
320 // Bailout if donation does not exist.
321 if ( ! ( $donation_ids = $this->get_donations( $atts ) ) ) {
322 return array();
323 }
324
325 $donation_ids = ! empty( $donation_ids )
326 ? '\'' . implode( '\',\'', $donation_ids ) . '\''
327 : '';
328
329 // Backward compatibility
330 $donation_id_col = Give()->payment_meta->get_meta_type() . '_id';
331
332 $sql = "SELECT m1.*, p1.post_date as donation_date FROM {$wpdb->donationmeta} as m1
333 INNER JOIN {$wpdb->posts} as p1 ON (m1.{$donation_id_col}=p1.ID)
334 WHERE m1.{$donation_id_col} IN ( {$donation_ids} )
335 ORDER BY FIELD( p1.ID, {$donation_ids} )
336 ";
337
338 $results = (array) $wpdb->get_results( $sql );
339
340 if ( ! empty( $results ) ) {
341 $temp = array();
342
343 /* @var stdClass $result */
344 foreach ( $results as $result ) {
345 $temp[ $result->{$donation_id_col} ][ $result->meta_key ] = maybe_unserialize( $result->meta_value );
346
347 // Set donation date.
348 if( empty( $temp[ $result->{$donation_id_col} ][ 'donation_date' ] ) ){
349 $temp[ $result->{$donation_id_col} ]['donation_date'] = $result->donation_date;
350 }
351 }
352
353 $comments = $this->get_donor_comments( $temp );
354
355 if ( ! empty( $temp ) ) {
356 foreach ( $temp as $donation_id => $donation_data ) {
357 $temp[ $donation_id ]['donation_id'] = $donation_id;
358
359 $temp[ $donation_id ]['name_initial'] = give_get_name_initial( array(
360 'firstname' => $donation_data['_give_donor_billing_first_name'],
361 'lastname' => $donation_data['_give_donor_billing_last_name'],
362 ) );
363
364 $temp[ $donation_id ]['donor_comment'] = ! empty( $comments[ $donation_id ] ) ? $comments[ $donation_id ] : '';
365 }
366 }
367
368 $results = ! empty( $temp ) ? $temp : array();
369 }
370
371 return $results;
372 }
373
374 /**
375 * Get donation list for specific query
376 *
377 * @since 2.3.0
378 *
379 * @param array $atts
380 *
381 * @return array
382 */
383 private function get_donations( $atts = array() ) {
384 global $wpdb;
385
386 // Backward compatibility
387 $donation_id_col = Give()->payment_meta->get_meta_type() . '_id';
388
389 $query_params = $this->get_query_param( $atts );
390
391 $sql = "SELECT p1.ID FROM {$wpdb->posts} as p1";
392 $where = " WHERE p1.post_status IN ('publish') AND p1.post_type = 'give_payment'";
393
394 // exclude donation with zero amount from result.
395 $sql .= " INNER JOIN {$wpdb->donationmeta} as m1 ON (p1.ID = m1.{$donation_id_col})";
396 $where .= " AND m1.meta_key='_give_payment_total' AND m1.meta_value>0";
397
398
399 if ( $query_params['form_id'] ) {
400 $sql .= " INNER JOIN {$wpdb->donationmeta} as m2 ON (p1.ID = m2.{$donation_id_col})";
401 $where .= " AND m2.meta_key='_give_payment_form_id' AND m2.meta_value={$query_params['form_id']}";
402 }
403
404 // exclude donations which does not has donor comment.
405 if ( $query_params['only_comments'] ) {
406 $sql .= " INNER JOIN {$wpdb->give_comments} as gc1 ON (p1.ID = gc1.comment_parent)";
407 $where .= " AND gc1.comment_type='donor_donation'";
408 }
409
410 // exclude anonymous donation form query based on query parameters.
411 if (
412 ! $query_params['anonymous']
413 || $query_params['only_comments']
414 ) {
415 $where .= " AND p1.ID NOT IN ( SELECT DISTINCT({$donation_id_col}) FROM {$wpdb->donationmeta} WHERE meta_key='_give_anonymous_donation' AND meta_value='1')";
416 }
417
418 // order by query based on parameter.
419 if ( 'donation_amount' === $query_params['orderby'] ) {
420 $order = " ORDER BY m1.meta_value+0 {$query_params['order']}";
421 } else {
422 $order = " ORDER BY p1.{$query_params['orderby']} {$query_params['order']}, p1.ID {$query_params['order']}";
423 }
424
425 $limit = " LIMIT {$query_params['limit']}";
426 $offset = " OFFSET {$query_params['offset']}";
427
428 $sql = $sql . $where . $order . $limit . $offset;
429
430 $donation_ids = $wpdb->get_col( $sql );
431
432 return $donation_ids;
433 }
434
435 /**
436 * Get donor comments
437 *
438 * @since 2.3.0
439 *
440 * @param array $donations_data
441 *
442 * @return array
443 */
444 private function get_donor_comments( $donations_data = array() ) {
445 global $wpdb;
446 $comments = array();
447
448 // Bailout.
449 if ( empty( $donations_data ) ) {
450 return $comments;
451 }
452
453 // Backward compatibility.
454 if (
455 ! give_has_upgrade_completed( 'v230_move_donor_note' )
456 || ! give_has_upgrade_completed( 'v230_move_donation_note' )
457 ) {
458 foreach ( $donations_data as $id => $data ) {
459 $comment = give_get_donor_donation_comment( $id, $data['_give_payment_donor_id'] );
460 $comments[ $id ] = ! empty( $comment ) ? $comment->comment_content : '';
461 }
462
463 return $comments;
464 }
465
466 $sql = "SELECT c1.comment_parent as donation_id, c1.comment_content as comment FROM {$wpdb->give_comments} as c1";
467 $sql .= " INNER JOIN {$wpdb->give_commentmeta} as cm1 ON (c1.comment_ID=cm1.give_comment_id)";
468 $where = array();
469
470 foreach ( $donations_data as $id => $data ) {
471 // Do not fetch comment for anonymous donation.
472 if( ! empty( $data['_give_anonymous_donation'] ) ) {
473 continue;
474 }
475
476 $where[] = "(c1.comment_parent={$id} AND cm1.meta_key='_give_donor_id' AND cm1.meta_value={$data['_give_payment_donor_id']})";
477 }
478
479 $where = ' WHERE ' . implode( ' OR ', $where );
480 $where .= " AND c1.comment_type='donor_donation'";
481
482 $sql = $sql . $where;
483
484 $comments = (array) $wpdb->get_results( $sql );
485
486 if ( ! empty( $comments ) ) {
487 $comments = array_combine(
488 wp_list_pluck( $comments, 'donation_id' ),
489 wp_list_pluck( $comments, 'comment' )
490 );
491 }
492
493 return $comments;
494 }
495
496 /**
497 * Check if donation exist or not for specific query
498 *
499 * @since 2.3.0
500 *
501 * @param array $atts
502 *
503 * @return bool
504 */
505 private function has_donations( $atts = array() ) {
506 return (bool) $this->get_donations( $atts );
507 }
508 }
509
510 // Initialize shortcode.
511 Give_Donor_Wall::get_instance();
512