PluginProbe
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) / 1.8.12.3
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) v1.8.12.3
1.8.13.1 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 All 212 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.12.3, at includes/abstracts/abstract-class-charitable-query.php

1,115 lines 25.5 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 * The returned value is interpolated directly into the SQL statement
431 * assembled by Charitable_Query::run_query(). A sort direction cannot be
432 * passed to $wpdb->prepare() as a placeholder, so it is validated against
433 * a strict whitelist here instead. Any value other than ASC or DESC --
434 * including anything supplied through a shortcode attribute or the
435 * `charitable_query_order` filter -- falls back to DESC.
436 *
437 * @since 1.0.0
438 * @version 1.8.12.2
439 *
440 * @return string
441 */
442 public function order() {
443 /**
444 * Filter the `ORDER` statement.
445 *
446 * Note that the filtered value is validated against ASC/DESC before it
447 * is used in the query, so returning any other value has no effect.
448 *
449 * @since 1.0.0
450 *
451 * @param string $sql The `ORDER` statement. DESC by default.
452 * @param Charitable_Query $query The `Charitable_Query` instance.
453 */
454 $order = apply_filters( 'charitable_query_order', $this->get( 'order', 'DESC' ), $this );
455
456 return charitable_validate_sort_direction( $order );
457 }
458
459 /**
460 * Return the LIMIT part of the query.
461 *
462 * @since 1.0.0
463 *
464 * @return string
465 */
466 public function limit() {
467 if ( $this->show_all() ) {
468 return '';
469 }
470
471 /**
472 * Filter the `LIMIT` statement.
473 *
474 * @since 1.0.0
475 *
476 * @param string $sql The `LIMIT` statement.
477 * @param Charitable_Query $query The `Charitable_Query` instance.
478 */
479 return apply_filters( 'charitable_query_limit', sprintf( 'LIMIT %d', $this->get( 'number', 20 ) ), $this );
480 }
481
482 /**
483 * Return the OFFSET part of the query.
484 *
485 * @since 1.0.0
486 *
487 * @return string
488 */
489 public function offset() {
490 if ( $this->show_all() ) {
491 return '';
492 }
493
494 $offset = $this->get( 'number' ) * ( $this->get( 'paged', 1 ) - 1 );
495
496 /**
497 * Filter the `OFFSET` statement.
498 *
499 * @since 1.0.0
500 *
501 * @param string $sql The `OFFSET` statement.
502 * @param Charitable_Query $query The `Charitable_Query` instance.
503 */
504 return apply_filters( 'charitable_query_offset', sprintf( 'OFFSET %d', $offset ), $this );
505 }
506
507 /**
508 * Select donor-specific fields.
509 *
510 * @since 1.0.0
511 *
512 * @param string $select_statement The default select statement.
513 * @return string
514 */
515 public function donor_fields( $select_statement ) {
516 return $select_statement . ', d.donor_id, d.user_id, d.first_name, d.last_name, d.email, d.date_joined';
517 }
518
519 /**
520 * Retrieve the donation ID and campaigns.
521 *
522 * @since 1.0.0
523 *
524 * @param string $select_statement The default select statement.
525 * @return string
526 */
527 public function donation_fields( $select_statement ) {
528 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";
529 }
530
531 /**
532 * Select donation-specific fields.
533 *
534 * @since 1.0.0
535 *
536 * @param string $select_statement The default select statement.
537 * @return string
538 */
539 public function donation_calc_fields( $select_statement ) {
540 return $select_statement . ', COUNT(cd.campaign_donation_id) AS donations, SUM(cd.amount) AS amount';
541 }
542
543 /**
544 * Select total amount field.
545 *
546 * @since 1.2.0
547 *
548 * @param string $select_statement The default select statement.
549 * @return string
550 */
551 public function donation_amount_sum_field( $select_statement ) {
552 return $select_statement . ', SUM(cd.amount) AS amount';
553 }
554
555 /**
556 * Return the SQL to be used for meta queries.
557 *
558 * @since 1.6.5
559 *
560 * @global WPDB $wpdb
561 *
562 * @return false|array {
563 * Array containing JOIN and WHERE SQL clauses to append to the main query.
564 *
565 * @type string $join SQL fragment to append to the main JOIN clause.
566 * @type string $where SQL fragment to append to the main WHERE clause.
567 * }
568 */
569 public function get_meta_sql() {
570 if ( ! isset( $this->meta_sql ) ) {
571 global $wpdb;
572
573 $meta_args = $this->get( 'meta_query' );
574
575 if ( empty( $meta_args ) ) {
576 return false;
577 }
578
579 $meta_query = new WP_Meta_Query( $meta_args );
580
581 $this->meta_sql = $meta_query->get_sql( 'post', $wpdb->posts, 'ID' );
582 }
583
584 return $this->meta_sql;
585 }
586
587 /**
588 * A helper function used to populate the query parameters ith an item and a return a string
589 * of placeholders that can be used in a MySQL `IN` statement.
590 *
591 * @since 1.5.0
592 *
593 * @param mixed $item The item.
594 * @param callable $filter_callback A callback to use to filter out invalid items.
595 * @param string $placeholder_type The type of placeholder to use. May be %s, %d or %f.
596 * @return string A string containing the correct number of placeholders.
597 */
598 public function get_where_in_placeholders( $item, $filter_callback, $placeholder_type ) {
599 if ( ! is_array( $item ) ) {
600 $item = array( $item );
601 }
602
603 $item = array_filter( $item, $filter_callback );
604
605 $this->add_parameters( $item );
606
607 return $this->get_placeholders( count( $item ), $placeholder_type );
608 }
609
610 /**
611 * Filter query by donation_plan ID.
612 *
613 * @since 1.6.8
614 *
615 * @global WPBD $wpdb
616 * @param string $where_statement The default where statement.
617 * @return string
618 */
619 public function where_donation_plan_is_in( $where_statement ) {
620 global $wpdb;
621
622 $donation_plan = $this->get( 'donation_plan', false );
623
624 if ( ! $donation_plan ) {
625 return $where_statement;
626 }
627
628 $placeholders = $this->get_where_in_placeholders( $donation_plan, 'charitable_validate_absint', '%d' );
629
630 return $where_statement . " AND {$wpdb->posts}.post_parent IN ({$placeholders})";
631 }
632
633 /**
634 * Filter query by campaign receiving the donation.
635 *
636 * @since 1.0.0
637 *
638 * @param string $where_statement The default where statement.
639 * @return string
640 */
641 public function where_campaign_is_in( $where_statement ) {
642 $campaign = $this->get( 'campaign', 0 );
643
644 if ( ! $campaign ) {
645 return $where_statement;
646 }
647
648 $placeholders = $this->get_where_in_placeholders( $this->get( 'campaign', 0 ), 'charitable_validate_absint', '%d' );
649
650 return $where_statement . " AND cd.campaign_id IN ({$placeholders})";
651 }
652
653 /**
654 * Filter query by status of the post.
655 *
656 * @global WPBD $wpdb
657 *
658 * @since 1.0.0
659 *
660 * @param string $where_statement The default where statement.
661 * @return string
662 */
663 public function where_status_is_in( $where_statement ) {
664 global $wpdb;
665
666 $status = $this->get( 'status', false );
667
668 if ( ! $status ) {
669 return $where_statement;
670 }
671
672 $placeholders = $this->get_where_in_placeholders( $status, 'charitable_is_valid_donation_status', '%s' );
673
674 return $where_statement . " AND {$wpdb->posts}.post_status IN ({$placeholders})";
675 }
676
677 /**
678 * Filter query by donor ID.
679 *
680 * @global WPBD $wpdb
681 * @since 1.0.0
682 * @version 1.7.0.9
683 *
684 * @param string $where_statement The default where statement.
685 * @return string
686 */
687 public function where_donor_id_is_in( $where_statement ) {
688
689 $donor_email_passed = isset( $_GET['donor_email'] ) ? sanitize_email( $_GET['donor_email'] ) : false; // phpcs:ignore
690 $donor_email = $this->get( 'email', $donor_email_passed );
691
692 if ( $donor_email ) { // stop searching by ID, we will search by email that was supplied.
693 return $where_statement;
694 }
695
696 $donor_id = $this->get( 'donor_id', false );
697
698 if ( ! $donor_id ) {
699 return $where_statement;
700 }
701
702 $placeholders = $this->get_where_in_placeholders( $donor_id, 'charitable_validate_absint', '%d' );
703
704 return $where_statement . " AND cd.donor_id IN ({$placeholders})";
705 }
706
707 /**
708 * Filter query by donor email.
709 *
710 * @global WPBD $wpdb
711 * @since 1.7.0.9
712 *
713 * @param string $where_statement The default where statement.
714 * @return string
715 */
716 public function where_donor_email_is_in( $where_statement ) {
717 return $where_statement;
718 }
719
720 /**
721 * Filter query by user ID.
722 *
723 * @since 1.5.0
724 *
725 * @global WPBD $wpdb
726 * @param string $where_statement The default where statement.
727 * @return string
728 */
729 public function where_user_id_is_in( $where_statement ) {
730 global $wpdb;
731
732 $user_id = $this->get( 'user_id', false );
733
734 if ( ! $user_id ) {
735 return $where_statement;
736 }
737
738 $placeholders = $this->get_where_in_placeholders( $user_id, 'charitable_validate_absint', '%d' );
739
740 return $where_statement . " AND {$wpdb->posts}.post_author IN ({$placeholders})";
741 }
742
743 /**
744 * Filter query by donation ID(s).
745 *
746 * @since 1.7.0.9
747 * @version 1.8.8.5
748 *
749 * @global WPBD $wpdb
750 * @param string $where_statement The default where statement.
751 * @return string
752 */
753 public function where_donation_id_is_in( $where_statement ) {
754 global $wpdb;
755
756 $donation_ids_passed = isset( $_GET['donation_ids'] ) ? sanitize_text_field( $_GET['donation_ids'] ) : false; // phpcs:ignore
757
758 if ( $donation_ids_passed === false ) {
759 return $where_statement;
760 }
761
762 // this could be a comma delimited list.
763 $donation_ids = explode( ',', $donation_ids_passed );
764
765 if ( empty( $donation_ids ) ) {
766 return $where_statement;
767 }
768
769 // Validate and sanitize each donation ID to ensure they are positive integers
770 $valid_donation_ids = array();
771 foreach ( $donation_ids as $donation_id ) {
772 $donation_id = trim( $donation_id );
773 if ( is_numeric( $donation_id ) && intval( $donation_id ) > 0 ) {
774 $valid_donation_ids[] = intval( $donation_id );
775 }
776 }
777
778 if ( empty( $valid_donation_ids ) ) {
779 return $where_statement;
780 }
781
782 // Use proper parameterized query with placeholders
783 $placeholders = $this->get_where_in_placeholders( $valid_donation_ids, 'charitable_validate_absint', '%d' );
784
785 return $where_statement . " AND {$wpdb->posts}.ID IN ({$placeholders})";
786 }
787
788 /**
789 * Filter a query by date.
790 *
791 * @uses WP_Date_Query
792 *
793 * @since 1.5.0
794 *
795 * @param string $where_statement The where query.
796 * @return string
797 */
798 public function where_date( $where_statement ) {
799 $date_args = $this->get( 'date_query' );
800
801 if ( empty( $date_args ) ) {
802 return $where_statement;
803 }
804
805 $date_query = new WP_Date_Query( $date_args );
806
807 return $where_statement . $date_query->get_sql();
808 }
809
810 /**
811 * Filter a query by meta data.
812 *
813 * @uses WP_Meta_Query
814 *
815 * @since 1.6.5
816 *
817 * @param string $where_statement The where query.
818 * @return string
819 */
820 public function where_meta( $where_statement ) {
821 $meta_sql = $this->get_meta_sql();
822
823 if ( ! $meta_sql || empty( $meta_sql['where'] ) ) {
824 return $where_statement;
825 }
826
827 return $where_statement . $meta_sql['where'];
828 }
829
830 /**
831 * A method used to join the campaign donations table on the campaigns query.
832 *
833 * @global WPBD $wpdb
834 *
835 * @since 1.0.0
836 *
837 * @param string $join_statement The default join statement.
838 * @return string
839 */
840 public function join_campaign_donations_table_on_campaign( $join_statement ) {
841 global $wpdb;
842 return $join_statement . " INNER JOIN {$wpdb->prefix}charitable_campaign_donations cd ON cd.campaign_id = $wpdb->posts.ID ";
843 }
844
845 /**
846 * Add one or more joins to the post meta table.
847 *
848 * @uses WP_Meta_Query
849 *
850 * @since 1.6.5
851 *
852 * @param string $join_statement The where query.
853 * @return string
854 */
855 public function join_meta( $join_statement ) {
856 $meta_sql = $this->get_meta_sql();
857
858 if ( ! $meta_sql || empty( $meta_sql['join'] ) ) {
859 return $join_statement;
860 }
861
862 return $join_statement . $meta_sql['join'];
863 }
864
865 /**
866 * A method used to join the campaign donations table on the campaigns query.
867 *
868 * @global WPBD $wpdb
869 *
870 * @since 1.0.0
871 *
872 * @param string $join_statement The default join statement.
873 * @return string
874 */
875 public function join_campaign_donations_table_on_donation( $join_statement ) {
876 global $wpdb;
877 return $join_statement . " INNER JOIN {$wpdb->prefix}charitable_campaign_donations cd ON cd.donation_id = $wpdb->posts.ID ";
878 }
879
880 /**
881 * A method used to join the campaign donations table on the campaigns query.
882 *
883 * @global WPBD $wpdb
884 *
885 * @since 1.7.0.9
886 *
887 * @param string $join_statement The default join statement.
888 * @return string
889 */
890 public function join_campaign_donors_table_on_donation( $join_statement ) {
891 global $wpdb;
892 return $join_statement . " INNER JOIN {$wpdb->prefix}charitable_donors cdn ON cdn.donor_id = cd.donor_id ";
893 }
894
895 /**
896 * A method used to join the donors table on the query.
897 *
898 * @global WPBD $wpdb
899 * @since 1.5.0
900 *
901 * @param string $join_statement The default join statement.
902 * @return string
903 */
904 public function join_post_meta_table_on_donation( $join_statement ) {
905 global $wpdb;
906 return $join_statement . " INNER JOIN $wpdb->postmeta pm ON pm.post_id = $wpdb->posts.ID ";
907 }
908
909 /**
910 * A method used to join the donors table on the query.
911 *
912 * @global WPBD $wpdb
913 * @since 1.0.0
914 *
915 * @param string $join_statement The default join statement.
916 * @return string
917 */
918 public function join_donors_table( $join_statement ) {
919 global $wpdb;
920 return $join_statement . " INNER JOIN {$wpdb->prefix}charitable_donors d ON d.donor_id = cd.donor_id ";
921 }
922
923 /**
924 * Group results by the ID.
925 *
926 * @global WPBD $wpdb
927 * @since 1.0.0
928 *
929 * @return string
930 */
931 public function groupby_ID() {
932 global $wpdb;
933 return "GROUP BY {$wpdb->posts}.ID";
934 }
935
936 /**
937 * Group a query by the donor ID.
938 *
939 * @since 1.0.0
940 *
941 * @return string
942 */
943 public function groupby_donor_id() {
944 return 'GROUP BY cd.donor_id';
945 }
946
947 /**
948 * Group a query by the donation ID.
949 *
950 * @since 1.4.0
951 *
952 * @return string
953 */
954 public function groupby_donation_id() {
955 return 'GROUP BY cd.donation_id';
956 }
957
958 /**
959 * Order by the date of the post.
960 *
961 * @global WPBD $wpdb
962 * @since 1.0.0
963 *
964 * @return string
965 */
966 public function orderby_date() {
967 global $wpdb;
968 return "ORDER BY {$wpdb->posts}.post_date";
969 }
970
971 /**
972 * Order by the results count of the ID column.
973 *
974 * This is useful when used in combination with a group statement.
975 *
976 * @since 1.0.0
977 *
978 * @return string
979 */
980 public function orderby_count() {
981 return 'ORDER BY COUNT(*)';
982 }
983
984 /**
985 * A method used to change the ordering of the campaigns query, to order by the amount donated.
986 *
987 * @since 1.0.0
988 *
989 * @return string
990 */
991 public function orderby_donation_amount() {
992 return 'ORDER BY COALESCE(SUM(cd.amount), 0)';
993 }
994
995 /**
996 * Return number of results.
997 *
998 * @since 1.0.0
999 *
1000 * @return int
1001 */
1002 public function count() {
1003 return 'count' == $this->get( 'output' ) ? $this->found_items : count( $this->results );
1004 }
1005
1006 /**
1007 * Return total result count.
1008 *
1009 * @since 1.5.0
1010 *
1011 * @return int
1012 */
1013 public function found_items() {
1014 return $this->found_items;
1015 }
1016
1017 /**
1018 * Rewind to first result.
1019 *
1020 * @since 1.0.0
1021 *
1022 * @return void
1023 */
1024 #[\ReturnTypeWillChange]
1025 public function rewind() {
1026 $this->position = 0;
1027 }
1028
1029 /**
1030 * Return current element.
1031 *
1032 * @since 1.0.0
1033 *
1034 * @return object
1035 */
1036 #[\ReturnTypeWillChange]
1037 public function current() {
1038 return isset( $this->results[ $this->position ] ) ? $this->results[ $this->position ] : false;
1039 }
1040
1041 /**
1042 * Return current key.
1043 *
1044 * @since 1.0.0
1045 *
1046 * @return int
1047 */
1048 #[\ReturnTypeWillChange]
1049 public function key() {
1050 return $this->position;
1051 }
1052
1053 /**
1054 * Advance to next item.
1055 *
1056 * @since 1.0.0
1057 *
1058 * @return void
1059 */
1060 #[\ReturnTypeWillChange]
1061 public function next() {
1062 ++$this->position;
1063 }
1064
1065 /**
1066 * Ensure that current position is valid.
1067 *
1068 * @since 1.0.0
1069 *
1070 * @return boolean
1071 */
1072 #[\ReturnTypeWillChange]
1073 public function valid() {
1074 return isset( $this->results[ $this->position ] );
1075 }
1076
1077 /**
1078 * Add parameters to pass to the prepared query.
1079 *
1080 * @since 1.0.0
1081 *
1082 * @param mixed $parameters Parameters to be set for the query.
1083 * @return void
1084 */
1085 public function add_parameters( $parameters ) {
1086 $this->parameters = array_merge( $this->parameters, $parameters );
1087 }
1088
1089 /**
1090 * Whether to show all results.
1091 *
1092 * @since 1.1.0
1093 *
1094 * @return boolean
1095 */
1096 public function show_all() {
1097 return -1 == $this->get( 'number' );
1098 }
1099
1100 /**
1101 * Return the correct number of placeholders given a symbol and count.
1102 *
1103 * @since 1.0.0
1104 *
1105 * @param int $count Number of placeholders.
1106 * @param string $placeholder Placeholder symbol.
1107 * @return string
1108 */
1109 protected function get_placeholders( $count = 1, $placeholder = '%s' ) {
1110 return charitable_get_query_placeholders( $count, $placeholder );
1111 }
1112 }
1113
1114 endif;
1115