PluginProbe ʕ •ᴥ•ʔ
GiveWP – Donation Plugin and Fundraising Platform / 2.4.5
GiveWP – Donation Plugin and Fundraising Platform v2.4.5
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-donors-query.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-donors-query.php
665 lines
1 <?php
2 /**
3 * Donors Query
4 *
5 * @package Give
6 * @subpackage Classes/Stats
7 * @copyright Copyright (c) 2017, GiveWP
8 * @license https://opensource.org/licenses/gpl-license GNU Public License
9 * @since 1.8.14
10 */
11
12 // Exit if accessed directly.
13 if ( ! defined( 'ABSPATH' ) ) {
14 exit;
15 }
16
17 /**
18 * Give_Donors_Query Class
19 *
20 * This class is for retrieving donors data.
21 *
22 * Donors can be retrieved for date ranges and pre-defined periods.
23 *
24 * @since 1.8.14
25 */
26 class Give_Donors_Query {
27
28 /**
29 * The args to pass to the give_get_donors() query
30 *
31 * @since 1.8.14
32 * @access public
33 *
34 * @var array
35 */
36 public $args = array();
37
38 /**
39 * The donors found based on the criteria set
40 *
41 * @since 1.8.14
42 * @access public
43 *
44 * @var array
45 */
46 public $donors = array();
47
48 /**
49 * The donors found based on the criteria set
50 *
51 * @since 1.8.14
52 * @access public
53 *
54 * @var string
55 */
56 public $table_name = '';
57
58 /**
59 * The donors found based on the criteria set
60 *
61 * @since 1.8.14
62 * @access public
63 *
64 * @var string
65 */
66 public $meta_table_name = '';
67
68 /**
69 * The donors found based on the criteria set
70 *
71 * @since 1.8.14
72 * @access public
73 *
74 * @var string
75 */
76 public $meta_type = '';
77
78 /**
79 * Preserve args
80 *
81 * @since 2.4.0
82 * @access public
83 *
84 * @var array
85 */
86 public $_args = array();
87
88 /**
89 * Default query arguments.
90 *
91 * Not all of these are valid arguments that can be passed to WP_Query. The ones that are not, are modified before
92 * the query is run to convert them to the proper syntax.
93 *
94 * @since 1.8.14
95 * @access public
96 *
97 * @param $args array The array of arguments that can be passed in and used for setting up this payment query.
98 */
99 public function __construct( $args = array() ) {
100 $defaults = array(
101 'number' => 20,
102 'offset' => 0,
103 'paged' => 1,
104 'orderby' => 'id',
105 'order' => 'DESC',
106 'user' => null,
107 'email' => null,
108 'donor' => null,
109 'meta_query' => array(),
110 'date_query' => array(),
111 's' => null,
112 'fields' => 'all', // Supports donors (all fields) or valid column as string or array list.
113 'count' => false,
114 'give_forms' => array(),
115 'start_date' => false,
116 'end_date' => false,
117
118 /**
119 * donation_amount will contain value like:
120 * array(
121 * 'compare' => *compare symbol* (by default set to > )
122 * 'amount' => *numeric_value*
123 * )
124 *
125 * You can also pass number value to this param then compare symbol will auto set to >
126 */
127 'donation_amount' => array(),
128 );
129
130 $this->args = $this->_args = wp_parse_args( $args, $defaults );
131 $this->table_name = Give()->donors->table_name;
132 $this->meta_table_name = Give()->donor_meta->table_name;
133 $this->meta_type = Give()->donor_meta->meta_type;
134
135 $this->date_filter_pre();
136 }
137
138 /**
139 * Modify the query/query arguments before we retrieve donors.
140 *
141 * @since 1.8.14
142 * @access public
143 *
144 * @return void
145 */
146 public function init() {
147 }
148
149
150 /**
151 * Retrieve donors.
152 *
153 * The query can be modified in two ways; either the action before the
154 * query is run, or the filter on the arguments (existing mainly for backwards
155 * compatibility).
156 *
157 * @since 1.8.14
158 * @access public
159 *
160 * @global wpdb $wpdb
161 *
162 * @return array
163 */
164 public function get_donors() {
165 global $wpdb;
166
167 /**
168 * Fires before retrieving donors.
169 *
170 * @since 1.8.14
171 *
172 * @param Give_Donors_Query $this Donors query object.
173 */
174 do_action( 'give_pre_get_donors', $this );
175
176 $cache_key = Give_Cache::get_key( 'give_donor', $this->get_sql(), false );
177
178 // Get donors from cache.
179 $this->donors = Give_Cache::get_db_query( $cache_key );
180
181 if ( is_null( $this->donors ) ) {
182 if ( empty( $this->args['count'] ) ) {
183 $this->donors = $wpdb->get_results( $this->get_sql() );
184 } else {
185 $this->donors = $wpdb->get_var( $this->get_sql() );
186 }
187
188 Give_Cache::set_db_query( $cache_key, $this->donors );
189 }
190
191
192 /**
193 * Fires after retrieving donors.
194 *
195 * @since 1.8.14
196 *
197 * @param Give_Donors_Query $this Donors query object.
198 */
199 do_action( 'give_post_get_donors', $this );
200
201 return $this->donors;
202 }
203
204 /**
205 * Get sql query from queried array.
206 *
207 * @since 2.0
208 * @access public
209 *
210 * @global wpdb $wpdb
211 * @return string
212 */
213 public function get_sql() {
214 global $wpdb;
215
216 if ( $this->args['number'] < 1 ) {
217 $this->args['number'] = 99999999999;
218 }
219
220 $where = $this->get_where_query();
221
222
223 // Set offset.
224 if ( empty( $this->args['offset'] ) && ( 0 < $this->args['paged'] ) ) {
225 $this->args['offset'] = $this->args['number'] * ( $this->args['paged'] - 1 );
226 }
227
228 // Set fields.
229 $fields = "{$this->table_name}.*";
230 if ( ! empty( $this->args['fields'] ) && 'all' !== $this->args['fields'] ) {
231 if ( is_string( $this->args['fields'] ) ) {
232 $fields = "{$this->table_name}.{$this->args['fields']}";
233 } elseif ( is_array( $this->args['fields'] ) ) {
234 $fields = "{$this->table_name}." . implode( " , {$this->table_name}.", $this->args['fields'] );
235 }
236 }
237
238 // Set count.
239 if ( ! empty( $this->args['count'] ) ) {
240 $fields = "COUNT({$this->table_name}.id)";
241 }
242
243 $orderby = $this->get_order_query();
244
245 $sql = $wpdb->prepare( "SELECT {$fields} FROM {$this->table_name} LIMIT %d,%d;", absint( $this->args['offset'] ), absint( $this->args['number'] ) );
246
247 // $where, $orderby and order already prepared query they can generate notice if you re prepare them in above.
248 // WordPress consider LIKE condition as placeholder if start with s,f, or d.
249 $sql = str_replace( 'LIMIT', "{$where} {$orderby} LIMIT", $sql );
250
251 return $sql;
252 }
253
254 /**
255 * Set query where clause.
256 *
257 * @since 1.8.14
258 * @access private
259 *
260 * @global wpdb $wpdb
261 * @return string
262 */
263 private function get_where_query() {
264
265 // Get sql query for meta.
266 if ( ! empty( $this->args['meta_query'] ) ) {
267 $meta_query_object = new WP_Meta_Query( $this->args['meta_query'] );
268 $meta_query = $meta_query_object->get_sql( $this->meta_type, $this->table_name, 'id' );
269
270 $where[] = implode( '', $meta_query );
271 }
272
273 $where[] = 'WHERE 1=1';
274 $where[] = $this->get_where_search();
275 $where[] = $this->get_where_email();
276 $where[] = $this->get_where_donor();
277 $where[] = $this->get_where_user();
278 $where[] = $this->get_where_date();
279 $where[] = $this->get_where_donation_amount();
280 $where[] = $this->get_where_donation_count();
281 $where[] = $this->get_where_give_forms();
282
283 $where = array_filter( $where );
284
285 return trim( implode( ' ', array_map( 'trim', $where ) ) );
286
287 }
288
289 /**
290 * Set email where clause.
291 *
292 * @since 1.8.14
293 * @access private
294 *
295 * @global wpdb $wpdb
296 * @return string
297 */
298 private function get_where_email() {
299 global $wpdb;
300
301 $where = '';
302
303 if ( ! empty( $this->args['email'] ) ) {
304
305 if ( is_array( $this->args['email'] ) ) {
306
307 $emails_count = count( $this->args['email'] );
308 $emails_placeholder = array_fill( 0, $emails_count, '%s' );
309 $emails = implode( ', ', $emails_placeholder );
310
311 $where .= $wpdb->prepare( "AND {$this->table_name}.email IN( $emails )", $this->args['email'] );
312 } else {
313 $where .= $wpdb->prepare( "AND {$this->table_name}.email = %s", $this->args['email'] );
314 }
315 }
316
317 return $where;
318 }
319
320 /**
321 * Set donor where clause.
322 *
323 * @since 1.8.14
324 * @access private
325 *
326 * @global wpdb $wpdb
327 * @return string
328 */
329 private function get_where_donor() {
330 $where = '';
331
332 // Specific donors.
333 if ( ! empty( $this->args['donor'] ) ) {
334 if ( ! is_array( $this->args['donor'] ) ) {
335 $this->args['donor'] = explode( ',', $this->args['donor'] );
336 }
337 $donor_ids = implode( ',', array_map( 'intval', $this->args['donor'] ) );
338
339 $where .= "AND {$this->table_name}.id IN( {$donor_ids} )";
340 }
341
342 return $where;
343 }
344
345 /**
346 * Set date where clause.
347 *
348 * @since 1.8.14
349 * @access private
350 *
351 * @global wpdb $wpdb
352 * @return string
353 */
354 private function get_where_date() {
355 $where = '';
356
357 // Donors created for a specific date or in a date range
358 if ( ! empty( $this->args['date_query'] ) ) {
359 $date_query_object = new WP_Date_Query( is_array( $this->args['date_query'] ) ? $this->args['date_query'] : wp_parse_args( $this->args['date_query'] ), "{$this->table_name}.date_created" );
360
361 $where .= str_replace( array(
362 "\n",
363 '( (',
364 '))',
365 ), array(
366 '',
367 '( (',
368 ') )',
369 ), $date_query_object->get_sql() );
370 }
371
372 return $where;
373 }
374
375 /**
376 * Set search where clause.
377 *
378 * @since 1.8.14
379 * @access private
380 *
381 * @global wpdb $wpdb
382 * @return string
383 */
384 private function get_where_search() {
385 $where = '';
386
387 // Bailout.
388 if( empty( $this->args['s'] ) ) {
389 return $where;
390 }
391
392 // Donors created for a specific date or in a date range
393 if ( false !== strpos( $this->args['s'], ':' ) ) {
394 $search_parts = explode( ':', $this->args['s'] );
395 if ( ! empty( $search_parts[0] ) ) {
396 switch ( $search_parts[0] ) {
397 // Backward compatibility.
398 case 'name':
399 $where = "AND {$this->table_name}.name LIKE '%{$search_parts[1]}%'";
400 break;
401 case 'note':
402 $where = "AND {$this->table_name}.notes LIKE '%{$search_parts[1]}%'";
403 break;
404 }
405 }
406
407 } else if ( is_numeric( $this->args['s'] ) ) {
408 $where = "AND {$this->table_name}.id ='{$this->args['s']}'";
409
410 } else {
411 $search_field = is_email( $this->args['s'] ) ? 'email' : 'name';
412 $where = "AND {$this->table_name}.$search_field LIKE '%{$this->args['s']}%'";
413 }
414
415 return $where;
416 }
417
418 /**
419 * Set user where clause.
420 *
421 * @since 1.8.14
422 * @access private
423 *
424 * @global wpdb $wpdb
425 * @return string
426 */
427 private function get_where_user() {
428 $where = '';
429
430 // Donors create for specific wp user.
431 if ( ! empty( $this->args['user'] ) ) {
432 if ( ! is_array( $this->args['user'] ) ) {
433 $this->args['user'] = explode( ',', $this->args['user'] );
434 }
435 $user_ids = implode( ',', array_map( 'intval', $this->args['user'] ) );
436
437 $where .= "AND {$this->table_name}.user_id IN( {$user_ids} )";
438 }
439
440 return $where;
441 }
442
443 /**
444 * Set orderby query
445 *
446 * @since 1.8.14
447 * @access private
448 *
449 * @return string
450 */
451 private function get_order_query() {
452 $table_columns = Give()->donors->get_columns();
453
454 $query = array();
455 $ordersby = $this->args['orderby'];
456
457 if( ! is_array( $ordersby ) ) {
458 $ordersby = array(
459 $this->args['orderby'] => $this->args['order']
460 );
461 }
462
463 // Remove non existing column.
464 // Filter orderby values.
465 foreach ( $ordersby as $orderby => $order ) {
466 if( ! array_key_exists( $orderby, $table_columns ) ) {
467 unset( $ordersby[$orderby] );
468 }
469
470 $ordersby[ esc_sql( $orderby ) ] = esc_sql( $order );
471 }
472
473 if( empty( $ordersby ) ) {
474 $ordersby = array(
475 'id' => $this->args['order']
476 );
477 }
478
479 // Create query.
480 foreach ( $ordersby as $orderby => $order ) {
481 switch ( $table_columns[ $orderby ] ) {
482 case '%d':
483 case '%f':
484 $query[] = "{$this->table_name}.{$orderby}+0 {$order}";
485 break;
486
487 default:
488 $query[] = "{$this->table_name}.{$orderby} {$order}";
489 }
490 }
491
492 return ! empty( $query ) ? 'ORDER BY ' . implode( ', ', $query ) : '';
493 }
494
495 /**
496 * Set donation count value where clause.
497 * @todo: add phpunit test
498 *
499 * @since 2.2.0
500 * @access private
501 *
502 * @global wpdb $wpdb
503 * @return string
504 */
505 private function get_where_donation_count() {
506 $where = '';
507
508 if ( ! empty( $this->args['donation_count'] ) ) {
509 $compare = '>';
510 $amount = $this->args['donation_count'];
511 if ( is_array( $this->args['donation_count'] ) ) {
512 $compare = $this->args['donation_count'] ['compare'];
513 $amount = $this->args['donation_count']['amount'];
514 }
515
516 $where .= "AND {$this->table_name}.purchase_count{$compare}{$amount}";
517 }
518
519 return $where;
520 }
521
522 /**
523 * Set purchase value where clause.
524 * @todo: add phpunit test
525 *
526 * @since 2.1.0
527 * @access private
528 *
529 * @global wpdb $wpdb
530 * @return string
531 */
532 private function get_where_donation_amount() {
533 $where = '';
534
535 if ( ! empty( $this->args['donation_amount'] ) ) {
536 $compare = '>';
537 $amount = $this->args['donation_amount'];
538 if ( is_array( $this->args['donation_amount'] ) ) {
539 $compare = $this->args['donation_amount'] ['compare'];
540 $amount = $this->args['donation_amount']['amount'];
541 }
542
543 $where .= "AND {$this->table_name}.purchase_value{$compare}{$amount}";
544 }
545
546 return $where;
547 }
548
549 /**
550 * Set give_forms where clause.
551 *
552 * @todo : add phpunit test
553 *
554 * @since 2.1.0
555 * @access private
556 *
557 * @global wpdb $wpdb
558 * @return string
559 */
560 private function get_where_give_forms() {
561 global $wpdb;
562 $where = '';
563
564 if ( ! empty( $this->args['give_forms'] ) ) {
565 if ( ! is_array( $this->args['give_forms'] ) ) {
566 $this->args['give_forms'] = explode( ',', $this->args['give_forms'] );
567 }
568
569 $form_ids = implode( ',', array_map( 'intval', $this->args['give_forms'] ) );
570 $donation_id_col = Give()->payment_meta->get_meta_type() . '_id';
571
572 $query = $wpdb->prepare(
573 "
574 SELECT DISTINCT meta_value as donor_id
575 FROM {$wpdb->donationmeta}
576 WHERE meta_key=%s
577 AND {$donation_id_col} IN(
578 SELECT {$donation_id_col}
579 FROM {$wpdb->paymentmeta}
580 WHERE meta_key=%s
581 AND meta_value IN (%s)
582 )
583 ",
584 '_give_payment_donor_id',
585 '_give_payment_form_id',
586 $form_ids
587 );
588
589 $donor_ids = $wpdb->get_results( $query, ARRAY_A );
590
591 if ( ! empty( $donor_ids ) ) {
592 $donor_ids = wp_list_pluck( $donor_ids, 'donor_id' );
593 $donor_ids = implode( ',', array_map( 'intval', $donor_ids ) );
594 $where .= "AND {$this->table_name}.id IN ({$donor_ids})";
595 } else {
596 $where .= "AND {$this->table_name}.id IN ('0')";
597 }
598 }
599
600 return $where;
601 }
602
603 /**
604 * If querying a specific date, add the proper filters.
605 * Note: This function currently only accept dates with admin defined core date format
606 *
607 * @since 2.4.0
608 * @access public
609 *
610 * @return void
611 */
612 public function date_filter_pre() {
613 if (
614 ! empty( $this->args['date_query'] )
615 || empty( $this->args['start_date'] )
616 || empty( $this->args['end_date'] )
617 ) {
618 return;
619 }
620
621 $date_query = array();
622
623 if ( ! empty ( $this->args['start_date'] ) ) {
624 $date_query['after'] = date(
625 'Y-m-d H:i:s',
626 is_numeric( $this->args['start_date'] )
627 ? $this->args['start_date']
628 : strtotime( $this->args['start_date'] )
629 );
630 }
631
632 if ( ! empty ( $this->args['end_date'] ) ) {
633 $date_query['before'] = date(
634 'Y-m-d H:i:s',
635 is_numeric( $this->args['end_date'] )
636 ? $this->args['end_date']
637 : strtotime( $this->args['end_date'] )
638 );
639 }
640
641 // Include Start Date and End Date while querying.
642 $date_query['inclusive'] = true;
643
644 $this->__set( 'date_query', $date_query );
645 }
646
647 /**
648 * Set a query variable.
649 *
650 * @since 2.4.0
651 * @access public
652 *
653 * @param $query_var
654 * @param $value
655 */
656 public function __set( $query_var, $value ) {
657 if ( in_array( $query_var, array( 'meta_query', 'tax_query' ) ) ) {
658 $this->args[ $query_var ][] = $value;
659 } else {
660 $this->args[ $query_var ] = $value;
661 }
662 }
663
664 }
665