PluginProbe
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) / 1.8.11.3
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) v1.8.11.3
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
charitable / includes / abstracts / abstract-class-charitable-query.php

abstract-class-charitable-query.php in Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) 1.8.11.3, at includes/abstracts/abstract-class-charitable-query.php

1,102 lines 24.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * An abstract base class defining common methods used by Charitable queries.
4 *
5 * @package Charitable/Classes/Charitable_Query
6 * @author David Bisset
7 * @copyright Copyright (c) 2023, WP Charitable LLC
8 * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9 * @since 1.0.0
10 * @version 1.6.8
11 */
12
13 // Exit if accessed directly.
14 if ( ! defined( 'ABSPATH' ) ) {
15 exit;
16 }
17
18 if ( ! class_exists( 'Charitable_Query' ) ) :
19
20 /**
21 * Charitable_Query
22 *
23 * @since 1.0.0
24 */
25 abstract class Charitable_Query implements Iterator {
26
27 /**
28 * User-defined arguments.
29 *
30 * @var array
31 */
32 protected $args;
33
34 /**
35 * Internal iterator position.
36 *
37 * @var int
38 */
39 protected $position = 0;
40
41 /**
42 * The raw query results.
43 *
44 * @var array
45 */
46 protected $query;
47
48 /**
49 * Number of items found.
50 *
51 * @var int|null
52 */
53 protected $found_items;
54
55 /**
56 * Result set.
57 *
58 * @var array
59 */
60 protected $results;
61
62 /**
63 * Parameters to pass to the query.
64 *
65 * @var mixed[]
66 */
67 protected $parameters = array();
68
69 /**
70 * Meta SQL query.
71 *
72 * @since 1.6.5
73 *
74 * @var array|false
75 */
76 protected $meta_sql;
77
78 /**
79 * Return the query argument value for the given key.
80 *
81 * @since 1.0.0
82 *
83 * @param string $key The key of the argument.
84 * @param mixed $fallback Default value to fall back to.
85 * @return mixed|false Returns fallback if the argument is not found.
86 */
87 public function get( $key, $fallback = false ) {
88 return isset( $this->args[ $key ] ) ? $this->args[ $key ] : $fallback;
89 }
90
91 /**
92 * Set the query argument for the given key.
93 *
94 * @since 1.0.0
95 *
96 * @param string $key Key of argument to set.
97 * @param mixed $value Value to be set.
98 * @return void
99 */
100 public function set( $key, $value ) {
101 $this->args[ $key ] = apply_filters( 'charitable_query_sanitize_argument_' . $key, $value, $this );
102 }
103
104 /**
105 * Remove the given query argument.
106 *
107 * @since 1.0.0
108 *
109 * @param string $key Key of argument to remove.
110 * @return void
111 */
112 public function remove( $key ) {
113 unset( $this->args[ $key ] );
114 }
115
116 /**
117 * Return the results of the query.
118 *
119 * @global WPDB $wpdb
120 *
121 * @since 1.6.8
122 *
123 * @return object[]
124 */
125 public function get_query() {
126 if ( ! isset( $this->query ) ) {
127 /**
128 * Fires right before the query is executed.
129 *
130 * @since 1.0.0
131 *
132 * @param Charitable_Query The `Charitable_Query` instance.
133 */
134 do_action( 'charitable_pre_query', $this );
135
136 $this->query = $this->run_query( $this->get( 'output' ) );
137 $this->found_items = $this->get_found_items();
138
139 /**
140 * Fires right after the query is executed.
141 *
142 * @since 1.0.0
143 *
144 * @param Charitable_Query The `Charitable_Query` instance.
145 */
146 do_action( 'charitable_post_query', $this );
147
148 }//end if
149
150 return $this->query;
151 }
152
153 /**
154 * Return the results.
155 *
156 * @since 1.6.8
157 *
158 * @return object[]
159 */
160 public function get_results() {
161 return $this->results;
162 }
163
164 /**
165 * Return the results of the query.
166 *
167 * @global WPDB $wpdb
168 *
169 * @since 1.0.0
170 *
171 * @return object[]
172 */
173 public function query() {
174 return $this->get_query();
175 }
176
177 /**
178 * Run query, returning the results.
179 *
180 * @global WPDB $wpdb
181 *
182 * @since 1.5.0
183 *
184 * @param string $output The output type.
185 * @return array
186 */
187 public function run_query( $output ) {
188 if ( method_exists( $this, 'run_query_' . $output ) ) {
189 return call_user_func( array( $this, 'run_query_' . $output ) );
190 }
191
192 global $wpdb;
193
194 $sql = "SELECT {$this->fields()} {$this->from()} {$this->join()} {$this->where()} {$this->groupby()} {$this->orderby()} {$this->order()} {$this->limit()} {$this->offset()};";
195
196 return $wpdb->get_results( $this->get_prepared_sql( $sql ) ); // phpcs:ignore
197 }
198
199 /**
200 * Run count query, returning the results.
201 *
202 * @global WPDB $wpdb
203 *
204 * @since 1.5.0
205 *
206 * @return array
207 */
208 public function run_query_count() {
209 global $wpdb;
210
211 $sql = "SELECT {$this->select_count()} {$this->from()} {$this->join()} {$this->where()};";
212
213 return array( $wpdb->get_var( $this->get_prepared_sql( $sql ) ) ); // phpcs:ignore
214 }
215
216 /**
217 * Prepare a query with any passed parameters.
218 *
219 * @global WPDB $wpdb
220 *
221 * @since 1.5.0
222 *
223 * @param string $sql The SQL query with placeholders.
224 * @return string
225 */
226 public function get_prepared_sql( $sql ) {
227 global $wpdb;
228
229 if ( empty( $this->parameters ) ) {
230 return $sql;
231 }
232
233 return $wpdb->prepare( $sql, $this->parameters ); // phpcs:ignore
234 }
235
236 /**
237 * After a query has been executed, check how many found rows there are.
238 *
239 * @global WPDB $wpdb
240 *
241 * @since 1.5.0
242 *
243 * @return int
244 */
245 public function get_found_items() {
246 global $wpdb;
247
248 if ( empty( $this->query ) ) {
249 return 0;
250 }
251
252 if ( 'count' == $this->get( 'output' ) ) {
253 return current( $this->query );
254 }
255
256 if ( $this->show_all() ) {
257 return count( $this->query );
258 }
259
260 /**
261 * Filters the query used to retrieve the query result count.
262 *
263 * @since 1.5.0
264 *
265 * @param string $found_customers_query SQL query. Default 'SELECT FOUND_ROWS()'.
266 * @param Charitable_Query $query The `Charitable_Query` instance.
267 */
268 $found_items_query = apply_filters( 'charitable_found_items_query', 'SELECT FOUND_ROWS()', $this );
269
270 return (int) $wpdb->get_var( $found_items_query ); // phpcs:ignore
271 }
272
273 /**
274 * Return the count query right after the SELECT part of the query.
275 *
276 * This is used instead of Charitable_Query::fields and is only appropriate
277 * when all you want to do with a query is get the number of something.
278 *
279 * @global WPBD $wpdb
280 *
281 * @since 1.5.0
282 *
283 * @return string
284 */
285 public function select_count() {
286 global $wpdb;
287
288 /**
289 * Filter the `SELECT COUNT` statement.
290 *
291 * @since 1.5.0
292 *
293 * @param string $sql The `SELECT COUNT` statement.
294 * @param Charitable_Query $query The `Charitable_Query` instance.
295 */
296 return apply_filters( 'charitable_select_count_fields', "COUNT(DISTINCT {$wpdb->posts}.ID)", $this );
297 }
298
299 /**
300 * Return the fields right after the SELECT part of the query.
301 *
302 * @global WPBD $wpdb
303 *
304 * @since 1.0.0
305 *
306 * @return string
307 */
308 public function fields() {
309 global $wpdb;
310
311 $found_rows = $this->show_all() ? '' : 'SQL_CALC_FOUND_ROWS';
312
313 /**
314 * Filter the `SELECT` statement.
315 *
316 * @since 1.0.0
317 *
318 * @param string $sql The `SELECT` statement.
319 * @param Charitable_Query $query The `Charitable_Query` instance.
320 */
321 return apply_filters( 'charitable_query_fields', "$found_rows {$wpdb->posts}.ID", $this );
322 }
323
324 /**
325 * Return the FROM part of the query.
326 *
327 * @global WPBD $wpdb
328 *
329 * @since 1.0.0
330 *
331 * @return string
332 */
333 public function from() {
334 global $wpdb;
335
336 /**
337 * Filter the `FROM` statement.
338 *
339 * @since 1.0.0
340 *
341 * @param string $sql The `FROM` statement.
342 * @param Charitable_Query $query The `Charitable_Query` instance.
343 */
344 return apply_filters( 'charitable_query_from', "FROM $wpdb->posts", $this );
345 }
346
347 /**
348 * Return the JOIN part of the query.
349 *
350 * @since 1.0.0
351 *
352 * @return string
353 */
354 public function join() {
355 /**
356 * Filter the `JOIN` statement.
357 *
358 * @since 1.0.0
359 *
360 * @param string $sql The `JOIN` statement. Empty by default.
361 * @param Charitable_Query $query The `Charitable_Query` instance.
362 */
363 return apply_filters( 'charitable_query_join', '', $this );
364 }
365
366 /**
367 * Return the WHERE part of the query.
368 *
369 * @since 1.0.0
370 *
371 * @return string
372 */
373 public function where() {
374 /**
375 * Filter the `WHERE` statement.
376 *
377 * @since 1.0.0
378 *
379 * @param string $sql The `WHERE` statement.
380 * @param Charitable_Query $query This query object.
381 */
382 return apply_filters( 'charitable_query_where', 'WHERE 1=1 ', $this );
383 }
384
385 /**
386 * Return the GROUPBY part of the query.
387 *
388 * @since 1.0.0
389 *
390 * @return string
391 */
392 public function groupby() {
393 /**
394 * Filter the `GROUP BY` statement.
395 *
396 * @since 1.0.0
397 *
398 * @param string $sql The `GROUP BY` statement. Empty by default.
399 * @param Charitable_Query $query This query object.
400 */
401 return apply_filters( 'charitable_query_groupby', '', $this );
402 }
403
404 /**
405 * Return the ORDER BY part of the query.
406 *
407 * @global WPBD $wpdb
408 *
409 * @since 1.0.0
410 *
411 * @return string
412 */
413 public function orderby() {
414 global $wpdb;
415
416 /**
417 * Filter the `ORDER BY` statement.
418 *
419 * @since 1.0.0
420 *
421 * @param string $sql The `ORDER BY` statement.
422 * @param Charitable_Query $query The `Charitable_Query` instance.
423 */
424 return apply_filters( 'charitable_query_orderby', "ORDER BY {$wpdb->posts}.ID", $this );
425 }
426
427 /**
428 * Return the ORDER part of the query.
429 *
430 * @since 1.0.0
431 *
432 * @return string
433 */
434 public function order() {
435 /**
436 * Filter the `ORDER` statement.
437 *
438 * @since 1.0.0
439 *
440 * @param string $sql The `ORDER` statement. DESC by default.
441 * @param Charitable_Query $query The `Charitable_Query` instance.
442 */
443 return apply_filters( 'charitable_query_order', $this->get( 'order', 'DESC' ), $this );
444 }
445
446 /**
447 * Return the LIMIT part of the query.
448 *
449 * @since 1.0.0
450 *
451 * @return string
452 */
453 public function limit() {
454 if ( $this->show_all() ) {
455 return '';
456 }
457
458 /**
459 * Filter the `LIMIT` statement.
460 *
461 * @since 1.0.0
462 *
463 * @param string $sql The `LIMIT` statement.
464 * @param Charitable_Query $query The `Charitable_Query` instance.
465 */
466 return apply_filters( 'charitable_query_limit', sprintf( 'LIMIT %d', $this->get( 'number', 20 ) ), $this );
467 }
468
469 /**
470 * Return the OFFSET part of the query.
471 *
472 * @since 1.0.0
473 *
474 * @return string
475 */
476 public function offset() {
477 if ( $this->show_all() ) {
478 return '';
479 }
480
481 $offset = $this->get( 'number' ) * ( $this->get( 'paged', 1 ) - 1 );
482
483 /**
484 * Filter the `OFFSET` statement.
485 *
486 * @since 1.0.0
487 *
488 * @param string $sql The `OFFSET` statement.
489 * @param Charitable_Query $query The `Charitable_Query` instance.
490 */
491 return apply_filters( 'charitable_query_offset', sprintf( 'OFFSET %d', $offset ), $this );
492 }
493
494 /**
495 * Select donor-specific fields.
496 *
497 * @since 1.0.0
498 *
499 * @param string $select_statement The default select statement.
500 * @return string
501 */
502 public function donor_fields( $select_statement ) {
503 return $select_statement . ', d.donor_id, d.user_id, d.first_name, d.last_name, d.email, d.date_joined';
504 }
505
506 /**
507 * Retrieve the donation ID and campaigns.
508 *
509 * @since 1.0.0
510 *
511 * @param string $select_statement The default select statement.
512 * @return string
513 */
514 public function donation_fields( $select_statement ) {
515 return $select_statement . ", cd.donation_id, GROUP_CONCAT(cd.campaign_name SEPARATOR ', ') AS campaigns, GROUP_CONCAT(cd.campaign_id SEPARATOR ',') AS campaign_ids, cd.donor_id";
516 }
517
518 /**
519 * Select donation-specific fields.
520 *
521 * @since 1.0.0
522 *
523 * @param string $select_statement The default select statement.
524 * @return string
525 */
526 public function donation_calc_fields( $select_statement ) {
527 return $select_statement . ', COUNT(cd.campaign_donation_id) AS donations, SUM(cd.amount) AS amount';
528 }
529
530 /**
531 * Select total amount field.
532 *
533 * @since 1.2.0
534 *
535 * @param string $select_statement The default select statement.
536 * @return string
537 */
538 public function donation_amount_sum_field( $select_statement ) {
539 return $select_statement . ', SUM(cd.amount) AS amount';
540 }
541
542 /**
543 * Return the SQL to be used for meta queries.
544 *
545 * @since 1.6.5
546 *
547 * @global WPDB $wpdb
548 *
549 * @return false|array {
550 * Array containing JOIN and WHERE SQL clauses to append to the main query.
551 *
552 * @type string $join SQL fragment to append to the main JOIN clause.
553 * @type string $where SQL fragment to append to the main WHERE clause.
554 * }
555 */
556 public function get_meta_sql() {
557 if ( ! isset( $this->meta_sql ) ) {
558 global $wpdb;
559
560 $meta_args = $this->get( 'meta_query' );
561
562 if ( empty( $meta_args ) ) {
563 return false;
564 }
565
566 $meta_query = new WP_Meta_Query( $meta_args );
567
568 $this->meta_sql = $meta_query->get_sql( 'post', $wpdb->posts, 'ID' );
569 }
570
571 return $this->meta_sql;
572 }
573
574 /**
575 * A helper function used to populate the query parameters ith an item and a return a string
576 * of placeholders that can be used in a MySQL `IN` statement.
577 *
578 * @since 1.5.0
579 *
580 * @param mixed $item The item.
581 * @param callable $filter_callback A callback to use to filter out invalid items.
582 * @param string $placeholder_type The type of placeholder to use. May be %s, %d or %f.
583 * @return string A string containing the correct number of placeholders.
584 */
585 public function get_where_in_placeholders( $item, $filter_callback, $placeholder_type ) {
586 if ( ! is_array( $item ) ) {
587 $item = array( $item );
588 }
589
590 $item = array_filter( $item, $filter_callback );
591
592 $this->add_parameters( $item );
593
594 return $this->get_placeholders( count( $item ), $placeholder_type );
595 }
596
597 /**
598 * Filter query by donation_plan ID.
599 *
600 * @since 1.6.8
601 *
602 * @global WPBD $wpdb
603 * @param string $where_statement The default where statement.
604 * @return string
605 */
606 public function where_donation_plan_is_in( $where_statement ) {
607 global $wpdb;
608
609 $donation_plan = $this->get( 'donation_plan', false );
610
611 if ( ! $donation_plan ) {
612 return $where_statement;
613 }
614
615 $placeholders = $this->get_where_in_placeholders( $donation_plan, 'charitable_validate_absint', '%d' );
616
617 return $where_statement . " AND {$wpdb->posts}.post_parent IN ({$placeholders})";
618 }
619
620 /**
621 * Filter query by campaign receiving the donation.
622 *
623 * @since 1.0.0
624 *
625 * @param string $where_statement The default where statement.
626 * @return string
627 */
628 public function where_campaign_is_in( $where_statement ) {
629 $campaign = $this->get( 'campaign', 0 );
630
631 if ( ! $campaign ) {
632 return $where_statement;
633 }
634
635 $placeholders = $this->get_where_in_placeholders( $this->get( 'campaign', 0 ), 'charitable_validate_absint', '%d' );
636
637 return $where_statement . " AND cd.campaign_id IN ({$placeholders})";
638 }
639
640 /**
641 * Filter query by status of the post.
642 *
643 * @global WPBD $wpdb
644 *
645 * @since 1.0.0
646 *
647 * @param string $where_statement The default where statement.
648 * @return string
649 */
650 public function where_status_is_in( $where_statement ) {
651 global $wpdb;
652
653 $status = $this->get( 'status', false );
654
655 if ( ! $status ) {
656 return $where_statement;
657 }
658
659 $placeholders = $this->get_where_in_placeholders( $status, 'charitable_is_valid_donation_status', '%s' );
660
661 return $where_statement . " AND {$wpdb->posts}.post_status IN ({$placeholders})";
662 }
663
664 /**
665 * Filter query by donor ID.
666 *
667 * @global WPBD $wpdb
668 * @since 1.0.0
669 * @version 1.7.0.9
670 *
671 * @param string $where_statement The default where statement.
672 * @return string
673 */
674 public function where_donor_id_is_in( $where_statement ) {
675
676 $donor_email_passed = isset( $_GET['donor_email'] ) ? sanitize_email( $_GET['donor_email'] ) : false; // phpcs:ignore
677 $donor_email = $this->get( 'email', $donor_email_passed );
678
679 if ( $donor_email ) { // stop searching by ID, we will search by email that was supplied.
680 return $where_statement;
681 }
682
683 $donor_id = $this->get( 'donor_id', false );
684
685 if ( ! $donor_id ) {
686 return $where_statement;
687 }
688
689 $placeholders = $this->get_where_in_placeholders( $donor_id, 'charitable_validate_absint', '%d' );
690
691 return $where_statement . " AND cd.donor_id IN ({$placeholders})";
692 }
693
694 /**
695 * Filter query by donor email.
696 *
697 * @global WPBD $wpdb
698 * @since 1.7.0.9
699 *
700 * @param string $where_statement The default where statement.
701 * @return string
702 */
703 public function where_donor_email_is_in( $where_statement ) {
704 return $where_statement;
705 }
706
707 /**
708 * Filter query by user ID.
709 *
710 * @since 1.5.0
711 *
712 * @global WPBD $wpdb
713 * @param string $where_statement The default where statement.
714 * @return string
715 */
716 public function where_user_id_is_in( $where_statement ) {
717 global $wpdb;
718
719 $user_id = $this->get( 'user_id', false );
720
721 if ( ! $user_id ) {
722 return $where_statement;
723 }
724
725 $placeholders = $this->get_where_in_placeholders( $user_id, 'charitable_validate_absint', '%d' );
726
727 return $where_statement . " AND {$wpdb->posts}.post_author IN ({$placeholders})";
728 }
729
730 /**
731 * Filter query by donation ID(s).
732 *
733 * @since 1.7.0.9
734 * @version 1.8.8.5
735 *
736 * @global WPBD $wpdb
737 * @param string $where_statement The default where statement.
738 * @return string
739 */
740 public function where_donation_id_is_in( $where_statement ) {
741 global $wpdb;
742
743 $donation_ids_passed = isset( $_GET['donation_ids'] ) ? sanitize_text_field( $_GET['donation_ids'] ) : false; // phpcs:ignore
744
745 if ( $donation_ids_passed === false ) {
746 return $where_statement;
747 }
748
749 // this could be a comma delimited list.
750 $donation_ids = explode( ',', $donation_ids_passed );
751
752 if ( empty( $donation_ids ) ) {
753 return $where_statement;
754 }
755
756 // Validate and sanitize each donation ID to ensure they are positive integers
757 $valid_donation_ids = array();
758 foreach ( $donation_ids as $donation_id ) {
759 $donation_id = trim( $donation_id );
760 if ( is_numeric( $donation_id ) && intval( $donation_id ) > 0 ) {
761 $valid_donation_ids[] = intval( $donation_id );
762 }
763 }
764
765 if ( empty( $valid_donation_ids ) ) {
766 return $where_statement;
767 }
768
769 // Use proper parameterized query with placeholders
770 $placeholders = $this->get_where_in_placeholders( $valid_donation_ids, 'charitable_validate_absint', '%d' );
771
772 return $where_statement . " AND {$wpdb->posts}.ID IN ({$placeholders})";
773 }
774
775 /**
776 * Filter a query by date.
777 *
778 * @uses WP_Date_Query
779 *
780 * @since 1.5.0
781 *
782 * @param string $where_statement The where query.
783 * @return string
784 */
785 public function where_date( $where_statement ) {
786 $date_args = $this->get( 'date_query' );
787
788 if ( empty( $date_args ) ) {
789 return $where_statement;
790 }
791
792 $date_query = new WP_Date_Query( $date_args );
793
794 return $where_statement . $date_query->get_sql();
795 }
796
797 /**
798 * Filter a query by meta data.
799 *
800 * @uses WP_Meta_Query
801 *
802 * @since 1.6.5
803 *
804 * @param string $where_statement The where query.
805 * @return string
806 */
807 public function where_meta( $where_statement ) {
808 $meta_sql = $this->get_meta_sql();
809
810 if ( ! $meta_sql || empty( $meta_sql['where'] ) ) {
811 return $where_statement;
812 }
813
814 return $where_statement . $meta_sql['where'];
815 }
816
817 /**
818 * A method used to join the campaign donations table on the campaigns query.
819 *
820 * @global WPBD $wpdb
821 *
822 * @since 1.0.0
823 *
824 * @param string $join_statement The default join statement.
825 * @return string
826 */
827 public function join_campaign_donations_table_on_campaign( $join_statement ) {
828 global $wpdb;
829 return $join_statement . " INNER JOIN {$wpdb->prefix}charitable_campaign_donations cd ON cd.campaign_id = $wpdb->posts.ID ";
830 }
831
832 /**
833 * Add one or more joins to the post meta table.
834 *
835 * @uses WP_Meta_Query
836 *
837 * @since 1.6.5
838 *
839 * @param string $join_statement The where query.
840 * @return string
841 */
842 public function join_meta( $join_statement ) {
843 $meta_sql = $this->get_meta_sql();
844
845 if ( ! $meta_sql || empty( $meta_sql['join'] ) ) {
846 return $join_statement;
847 }
848
849 return $join_statement . $meta_sql['join'];
850 }
851
852 /**
853 * A method used to join the campaign donations table on the campaigns query.
854 *
855 * @global WPBD $wpdb
856 *
857 * @since 1.0.0
858 *
859 * @param string $join_statement The default join statement.
860 * @return string
861 */
862 public function join_campaign_donations_table_on_donation( $join_statement ) {
863 global $wpdb;
864 return $join_statement . " INNER JOIN {$wpdb->prefix}charitable_campaign_donations cd ON cd.donation_id = $wpdb->posts.ID ";
865 }
866
867 /**
868 * A method used to join the campaign donations table on the campaigns query.
869 *
870 * @global WPBD $wpdb
871 *
872 * @since 1.7.0.9
873 *
874 * @param string $join_statement The default join statement.
875 * @return string
876 */
877 public function join_campaign_donors_table_on_donation( $join_statement ) {
878 global $wpdb;
879 return $join_statement . " INNER JOIN {$wpdb->prefix}charitable_donors cdn ON cdn.donor_id = cd.donor_id ";
880 }
881
882 /**
883 * A method used to join the donors table on the query.
884 *
885 * @global WPBD $wpdb
886 * @since 1.5.0
887 *
888 * @param string $join_statement The default join statement.
889 * @return string
890 */
891 public function join_post_meta_table_on_donation( $join_statement ) {
892 global $wpdb;
893 return $join_statement . " INNER JOIN $wpdb->postmeta pm ON pm.post_id = $wpdb->posts.ID ";
894 }
895
896 /**
897 * A method used to join the donors table on the query.
898 *
899 * @global WPBD $wpdb
900 * @since 1.0.0
901 *
902 * @param string $join_statement The default join statement.
903 * @return string
904 */
905 public function join_donors_table( $join_statement ) {
906 global $wpdb;
907 return $join_statement . " INNER JOIN {$wpdb->prefix}charitable_donors d ON d.donor_id = cd.donor_id ";
908 }
909
910 /**
911 * Group results by the ID.
912 *
913 * @global WPBD $wpdb
914 * @since 1.0.0
915 *
916 * @return string
917 */
918 public function groupby_ID() {
919 global $wpdb;
920 return "GROUP BY {$wpdb->posts}.ID";
921 }
922
923 /**
924 * Group a query by the donor ID.
925 *
926 * @since 1.0.0
927 *
928 * @return string
929 */
930 public function groupby_donor_id() {
931 return 'GROUP BY cd.donor_id';
932 }
933
934 /**
935 * Group a query by the donation ID.
936 *
937 * @since 1.4.0
938 *
939 * @return string
940 */
941 public function groupby_donation_id() {
942 return 'GROUP BY cd.donation_id';
943 }
944
945 /**
946 * Order by the date of the post.
947 *
948 * @global WPBD $wpdb
949 * @since 1.0.0
950 *
951 * @return string
952 */
953 public function orderby_date() {
954 global $wpdb;
955 return "ORDER BY {$wpdb->posts}.post_date";
956 }
957
958 /**
959 * Order by the results count of the ID column.
960 *
961 * This is useful when used in combination with a group statement.
962 *
963 * @since 1.0.0
964 *
965 * @return string
966 */
967 public function orderby_count() {
968 return 'ORDER BY COUNT(*)';
969 }
970
971 /**
972 * A method used to change the ordering of the campaigns query, to order by the amount donated.
973 *
974 * @since 1.0.0
975 *
976 * @return string
977 */
978 public function orderby_donation_amount() {
979 return 'ORDER BY COALESCE(SUM(cd.amount), 0)';
980 }
981
982 /**
983 * Return number of results.
984 *
985 * @since 1.0.0
986 *
987 * @return int
988 */
989 public function count() {
990 return 'count' == $this->get( 'output' ) ? $this->found_items : count( $this->results );
991 }
992
993 /**
994 * Return total result count.
995 *
996 * @since 1.5.0
997 *
998 * @return int
999 */
1000 public function found_items() {
1001 return $this->found_items;
1002 }
1003
1004 /**
1005 * Rewind to first result.
1006 *
1007 * @since 1.0.0
1008 *
1009 * @return void
1010 */
1011 #[\ReturnTypeWillChange]
1012 public function rewind() {
1013 $this->position = 0;
1014 }
1015
1016 /**
1017 * Return current element.
1018 *
1019 * @since 1.0.0
1020 *
1021 * @return object
1022 */
1023 #[\ReturnTypeWillChange]
1024 public function current() {
1025 return isset( $this->results[ $this->position ] ) ? $this->results[ $this->position ] : false;
1026 }
1027
1028 /**
1029 * Return current key.
1030 *
1031 * @since 1.0.0
1032 *
1033 * @return int
1034 */
1035 #[\ReturnTypeWillChange]
1036 public function key() {
1037 return $this->position;
1038 }
1039
1040 /**
1041 * Advance to next item.
1042 *
1043 * @since 1.0.0
1044 *
1045 * @return void
1046 */
1047 #[\ReturnTypeWillChange]
1048 public function next() {
1049 ++$this->position;
1050 }
1051
1052 /**
1053 * Ensure that current position is valid.
1054 *
1055 * @since 1.0.0
1056 *
1057 * @return boolean
1058 */
1059 #[\ReturnTypeWillChange]
1060 public function valid() {
1061 return isset( $this->results[ $this->position ] );
1062 }
1063
1064 /**
1065 * Add parameters to pass to the prepared query.
1066 *
1067 * @since 1.0.0
1068 *
1069 * @param mixed $parameters Parameters to be set for the query.
1070 * @return void
1071 */
1072 public function add_parameters( $parameters ) {
1073 $this->parameters = array_merge( $this->parameters, $parameters );
1074 }
1075
1076 /**
1077 * Whether to show all results.
1078 *
1079 * @since 1.1.0
1080 *
1081 * @return boolean
1082 */
1083 public function show_all() {
1084 return -1 == $this->get( 'number' );
1085 }
1086
1087 /**
1088 * Return the correct number of placeholders given a symbol and count.
1089 *
1090 * @since 1.0.0
1091 *
1092 * @param int $count Number of placeholders.
1093 * @param string $placeholder Placeholder symbol.
1094 * @return string
1095 */
1096 protected function get_placeholders( $count = 1, $placeholder = '%s' ) {
1097 return charitable_get_query_placeholders( $count, $placeholder );
1098 }
1099 }
1100
1101 endif;
1102