PluginProbe ʕ •ᴥ•ʔ
GiveWP – Donation Plugin and Fundraising Platform / 2.3.2
GiveWP – Donation Plugin and Fundraising Platform v2.3.2
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
489 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 * Instance.
28 *
29 * @since 2.2.0
30 * @access private
31 * @var Give_Donor_Wall
32 */
33 static private $instance;
34
35 /**
36 * Singleton pattern.
37 *
38 * @since 2.2.0
39 * @access private
40 */
41 private function __construct() {
42 }
43
44
45 /**
46 * Get instance.
47 *
48 * @since 2.2.0
49 * @access public
50 * @return Give_Donor_Wall
51 */
52 public static function get_instance() {
53 if ( null === static::$instance ) {
54 self::$instance = new static();
55
56 self::$instance->setup_actions();
57 }
58
59 return self::$instance;
60 }
61
62 /**
63 * Setup the default hooks and actions
64 *
65 * @since 2.2.0
66 *
67 * @return void
68 */
69 public function setup_actions() {
70
71 add_shortcode( 'give_donor_wall', array( $this, 'render_shortcode' ) );
72
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' ) );
75
76 }
77
78
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 donations to appear.
105 * Currently we are using this attribute internally and it will sort donations by created date.
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 */
111 public function render_shortcode( $atts ) {
112
113 $give_settings = give_get_settings();
114
115 $atts = $this->parse_atts( $atts );
116 $donations = $this->get_donation_data( $atts );
117 $html = '';
118
119 if ( $donations ) {
120
121 ob_start();
122
123 foreach ( $donations as $donation ) {
124 // Give/templates/shortcode-donor-wall.php.
125 give_get_template( 'shortcode-donor-wall', array( $donation, $give_settings, $atts ) );
126 }
127
128 $html = ob_get_clean();
129
130 // Return only donor html.
131 if (
132 isset( $atts['only_donor_html'] )
133 && wp_doing_ajax()
134 && $atts['only_donor_html']
135 ) {
136 return $html;
137 }
138 }
139
140 $temp_atts = $atts;
141 $temp_atts['paged'] = $atts['paged'] + 1;
142
143 $more_btn_html = sprintf(
144 '<input type="hidden" class="give-donor-wall-shortcode-attrs" data-shortcode="%1$s">',
145 rawurlencode( http_build_query( $atts ) )
146 );
147
148 if ( $this->has_donations( $temp_atts ) ) {
149 $more_btn_html .= sprintf(
150 '<button class="give-donor__load_more give-button-with-loader"><span class="give-loading-animation"></span>%1$s</button>',
151 $atts['loadmore_text']
152 );
153 }
154
155 $html = $html
156 ? sprintf(
157 '<div class="give-wrap give-grid-ie-utility"><div class="give-grid give-grid--%1$s">%2$s</div>%3$s</div>',
158 esc_attr( $atts['columns'] ),
159 $html,
160 $more_btn_html
161 )
162 : '';
163
164 return $html;
165 }
166
167 /**
168 * Parse shortcode attributes
169 *
170 * @since 2.2.0
171 * @access public
172 *
173 * @param array $atts Shortcode attributes.
174 *
175 * @return array
176 */
177 public function parse_atts( $atts ) {
178 $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
200 );
201
202
203 // Validate boolean attributes.
204 $boolean_attributes = array(
205 'show_avatar',
206 'show_name',
207 'show_total',
208 'show_time',
209 'show_comments',
210 'show_comments',
211 'hide_empty',
212 'only_comments',
213 'only_donor_html',
214 );
215
216 foreach ( $boolean_attributes as $att ) {
217 // Convert numeric to boolean.
218 // It will prevent condition check against boolean value.
219 if ( is_numeric( $atts[ $att ] ) ) {
220 $atts[ $att ] = (bool) $atts[ $att ];
221 }
222
223 $atts[ $att ] = filter_var( $atts[ $att ], FILTER_VALIDATE_BOOLEAN );
224 }
225
226 return $atts;
227 }
228
229 /**
230 * Get donors
231 *
232 * @since 2.2.0
233 * @access public
234 *
235 * @param array $donor_query Dorno query.
236 *
237 * @return array
238 */
239 public function get_donors( $donor_query ) {
240 $donor_query = new Give_Donors_Query( $donor_query );
241 $donors = $donor_query->get_donors();
242
243 return $donors;
244 }
245
246
247 /**
248 * Ajax handler
249 *
250 * @since 2.2.0
251 * @access public
252 */
253 public function ajax_handler() {
254 $shortcode_atts = wp_parse_args( give_clean( rawurldecode( $_POST['data'] ) ) ); // @codingStandardsIgnoreLine
255
256 // Get next page donor comments.
257 $shortcode_atts['paged'] = $shortcode_atts['paged'] + 1;
258 $shortcode_atts['only_donor_html'] = true;
259
260 $donors_comment_html = $this->render_shortcode( $shortcode_atts );
261
262 // Check if donor comment remaining.
263 $temp_atts = $shortcode_atts;
264 $temp_atts['paged'] = $shortcode_atts['paged'] + 1;
265 $has_donors = $this->has_donations( $temp_atts ) ? 1 : 0;
266
267 // Remove internal shortcode param.
268 unset( $shortcode_atts['only_donor_html'] );
269
270 wp_send_json(
271 array(
272 'shortcode' => rawurlencode( http_build_query( $shortcode_atts ) ),
273 'html' => $donors_comment_html,
274 'remaining' => $has_donors,
275 )
276 );
277 }
278
279 /**
280 * Get query params
281 *
282 * @since 2.3.0
283 *
284 * @param array $atts
285 *
286 * @return array
287 */
288 private function get_query_param( $atts = array() ) {
289 $valid_order = array( 'ASC', 'DESC' );
290 $valid_orderby = array( 'post_date' );
291
292 $query_atts = array();
293
294 $query_atts['order'] = in_array( $atts['order'], $valid_order ) ? $atts['order'] : 'DESC';
295 $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'];
299 $query_atts['only_comments'] = ( true === $atts['only_comments'] );
300
301 return $query_atts;
302 }
303
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() ) {
314 global $wpdb;
315
316 $query_params = $this->get_query_param( $atts );
317
318 // Bailout if donation does not exist.
319 if ( ! ( $donation_ids = $this->get_donations( $atts ) ) ) {
320 return array();
321 }
322
323 $donation_ids = ! empty( $donation_ids )
324 ? '\'' . implode( '\',\'', $donation_ids ) . '\''
325 : '';
326
327 // Backward compatibility
328 $donation_id_col = Give()->payment_meta->get_meta_type() . '_id';
329
330 $sql = "SELECT * FROM {$wpdb->donationmeta} as m1
331 INNER JOIN {$wpdb->posts} as p1 ON (m1.{$donation_id_col}=p1.ID)
332 WHERE m1.{$donation_id_col} IN ( {$donation_ids} )
333 ORDER BY p1.post_date {$query_params['order']}, p1.ID {$query_params['order']}
334 ";
335
336 $results = (array) $wpdb->get_results( $sql );
337
338 if ( ! empty( $results ) ) {
339 $temp = array();
340
341 /* @var stdClass $result */
342 foreach ( $results as $result ) {
343 $temp[ $result->{$donation_id_col} ][ $result->meta_key ] = maybe_unserialize( $result->meta_value );
344 }
345
346 $comments = $this->get_donor_comments($temp);
347
348 if ( ! empty( $temp ) ) {
349 foreach ( $temp as $donation_id => $donation_data ) {
350 $temp[ $donation_id ]['donation_id'] = $donation_id;
351
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 ) );
356
357 $temp[ $donation_id ]['donor_comment'] = ! empty( $comments[$donation_id] ) ? $comments[$donation_id] : '';
358 }
359 }
360
361 $results = ! empty( $temp ) ? $temp : array();
362 }
363
364 return $results;
365 }
366
367 /**
368 * Get donation list for specific query
369 *
370 * @since 2.3.0
371 *
372 * @param array $atts
373 *
374 * @return array
375 */
376 private function get_donations( $atts = array() ) {
377 global $wpdb;
378
379 // Backward compatibility
380 $donation_id_col = Give()->payment_meta->get_meta_type() . '_id';
381
382 $query_params = $this->get_query_param( $atts );
383
384 $sql = "SELECT p1.ID FROM {$wpdb->posts} as p1";
385 $where = " WHERE p1.post_status IN ('publish') AND p1.post_type = 'give_payment'";
386
387 // exclude donation with zero amount from result.
388 $sql .= " INNER JOIN {$wpdb->donationmeta} as m1 ON (p1.ID = m1.{$donation_id_col})";
389 $where .= " AND m1.meta_key='_give_payment_total' AND m1.meta_value>0";
390
391
392 if ( $query_params['form_id'] ) {
393 $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']}";
395 }
396
397 // exclude donations which does not has donor comment.
398 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'";
401 }
402
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')";
405
406 $order = " ORDER BY p1.{$query_params['orderby']} {$query_params['order']}, p1.ID {$query_params['order']}";
407 $limit = " LIMIT {$query_params['limit']}";
408 $offset = " OFFSET {$query_params['offset']}";
409
410 $sql = $sql . $where . $order . $limit . $offset;
411
412 $donation_ids = $wpdb->get_col( $sql );
413
414 return $donation_ids;
415 }
416
417 /**
418 * Get donor comments
419 *
420 * @since 2.3.0
421 *
422 * @param array $donations_data
423 *
424 * @return array
425 */
426 private function get_donor_comments( $donations_data = array() ) {
427 global $wpdb;
428 $comments = array();
429
430 // Bailout.
431 if( empty( $donations_data ) ) {
432 return $comments;
433 }
434
435 // Backward compatibility.
436 if (
437 ! give_has_upgrade_completed( 'v230_move_donor_note' )
438 || ! give_has_upgrade_completed( 'v230_move_donation_note' )
439 ) {
440 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 : '';
443 }
444
445 return $comments;
446 }
447
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();
451
452 foreach ( $donations_data as $id => $data ) {
453 $where[] = "(c1.comment_parent={$id} AND cm1.meta_key='_give_donor_id' AND cm1.meta_value={$data['_give_payment_donor_id']})";
454 }
455
456 $where = ' WHERE '. implode( ' OR ', $where );
457 $where .= " AND c1.comment_type='donor_donation'";
458
459 $sql = $sql.$where;
460
461 $comments = (array) $wpdb->get_results( $sql );
462
463 if( ! empty( $comments ) ) {
464 $comments = array_combine(
465 wp_list_pluck( $comments, 'donation_id' ),
466 wp_list_pluck( $comments, 'comment' )
467 );
468 }
469
470 return $comments;
471 }
472
473 /**
474 * Check if donation exist or not for specific query
475 *
476 * @since 2.3.0
477 *
478 * @param array $atts
479 *
480 * @return bool
481 */
482 private function has_donations( $atts = array() ) {
483 return (bool) $this->get_donations( $atts );
484 }
485 }
486
487 // Initialize shortcode.
488 Give_Donor_Wall::get_instance();
489