PluginProbe
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) / 1.7.0.2
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) v1.7.0.2
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 / data / class-charitable-campaign-donations-db.php

class-charitable-campaign-donations-db.php in Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) 1.7.0.2, at includes/data/class-charitable-campaign-donations-db.php

982 lines 26.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Charitable Campaign Donations DB class.
4 *
5 * @package Charitable/Classes/Charitable_Campaign_Donations_DB
6 * @author David Bisset
7 * @copyright Copyright (c) 2022, 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.57
11 */
12
13 // Exit if accessed directly.
14 if ( ! defined( 'ABSPATH' ) ) {
15 exit;
16 }
17
18 if ( ! class_exists( 'Charitable_Campaign_Donations_DB' ) ) :
19
20 /**
21 * Charitable_Campaign_Donations_DB
22 *
23 * @since 1.0.0
24 */
25 class Charitable_Campaign_Donations_DB extends Charitable_DB {
26
27 /**
28 * The version of our database table
29 *
30 * @since 1.0.0
31 *
32 * @var string
33 */
34 public $version = '1.5.4';
35
36 /**
37 * The name of the primary column
38 *
39 * @since 1.0.0
40 *
41 * @var string
42 */
43 public $primary_key = 'campaign_donation_id';
44
45 /**
46 * Stores whether the site is using commas for decimals in amounts.
47 *
48 * @since 1.3.0
49 *
50 * @var boolean
51 */
52 private $comma_decimal;
53
54 /**
55 * Set up the database table name.
56 *
57 * @since 1.0.0
58 *
59 * @global WPDB $wpdb
60 */
61 public function __construct() {
62 global $wpdb;
63
64 $this->table_name = $wpdb->prefix . 'charitable_campaign_donations';
65 }
66
67 /**
68 * Create the table.
69 *
70 * @since 1.0.0
71 *
72 * @global WPDB $wpdb
73 */
74 public function create_table() {
75 global $wpdb;
76
77 $charset_collate = $wpdb->get_charset_collate();
78
79 $sql = "CREATE TABLE {$this->table_name} (
80 campaign_donation_id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
81 donation_id bigint(20) unsigned NOT NULL,
82 donor_id bigint(20) unsigned NOT NULL,
83 campaign_id bigint(20) unsigned NOT NULL,
84 campaign_name text NOT NULL,
85 amount decimal(13, 4) NOT NULL,
86 PRIMARY KEY (campaign_donation_id),
87 KEY donation (donation_id),
88 KEY campaign (campaign_id),
89 KEY donor (donor_id)
90 ) $charset_collate;";
91
92 $this->_create_table( $sql );
93 }
94
95 /**
96 * Whitelist of columns.
97 *
98 * @since 1.0.0
99 *
100 * @return array
101 */
102 public function get_columns() {
103 return array(
104 'campaign_donation_id' => '%d',
105 'donation_id' => '%d',
106 'donor_id' => '%d',
107 'campaign_id' => '%d',
108 'campaign_name' => '%s',
109 'amount' => '%f',
110 );
111 }
112
113 /**
114 * Default column values.
115 *
116 * @since 1.0.0
117 *
118 * @return array
119 */
120 public function get_column_defaults() {
121 return array();
122 }
123
124 /**
125 * Add a new campaign donation.
126 *
127 * @since 1.0.0
128 *
129 * @param array $data Data we are inserting.
130 * @param string $type Type of record we are inserting.
131 * @return int The ID of the inserted campaign donation
132 */
133 public function insert( $data, $type = 'campaign_donation' ) {
134 if ( ! isset( $data['campaign_name'] ) ) {
135 $data['campaign_name'] = get_the_title( $data['campaign_id'] );
136 }
137
138 Charitable_Campaign::flush_donations_cache( $data['campaign_id'] );
139
140 return parent::insert( $data, $type );
141 }
142
143 /**
144 * Update campaign donation record.
145 *
146 * @since 1.0.0
147 *
148 * @param int $row_id The primary key ID for the row we are retrieving.
149 * @param array $data The updated date.
150 * @param string $where Column used in where argument.
151 * @return boolean
152 */
153 public function update( $row_id, $data = array(), $where = '' ) {
154 $this->flush_campaign_caches( $row_id, $where );
155
156 return parent::update( $row_id, $data, $where );
157 }
158
159 /**
160 * Delete a row identified by the primary key.
161 *
162 * @since 1.0.0
163 *
164 * @param int $row_id The primary key ID.
165 * @return boolean
166 */
167 public function delete( $row_id = 0 ) {
168 $this->flush_campaign_caches( $row_id );
169
170 return parent::delete( $row_id );
171 }
172
173 /**
174 * Delete all campaign donation records for a given donation.
175 *
176 * @since 1.2.0
177 *
178 * @param int $donation_id The donation ID.
179 * @return boolean
180 */
181 public static function delete_donation_records( $donation_id ) {
182 $table = charitable_get_table( 'campaign_donations' );
183
184 foreach ( $table->get_campaigns_for_donation( $donation_id ) as $campaign_id ) {
185 Charitable_Campaign::flush_donations_cache( $campaign_id );
186 }
187
188 return $table->delete_by( 'donation_id', $donation_id );
189 }
190
191 /**
192 * Get the total amount donated, ever.
193 *
194 * @since 1.0.0
195 *
196 * @global $wpdb WPDB
197 * @param string[] $statuses List of statuses.
198 * @return float
199 */
200 public function get_total( $statuses = array() ) {
201 global $wpdb;
202
203 if ( empty( $statuses ) ) {
204 $statuses = charitable_get_approval_statuses();
205 }
206
207 list( $status_clause, $parameters ) = $this->get_donation_status_clause( $statuses );
208
209 if ( ! empty( $status_clause ) ) {
210 $where_sql = 'WHERE ' . $status_clause;
211 }
212
213 $sql = "SELECT COALESCE( SUM(cd.amount), 0 )
214 FROM $this->table_name cd
215 INNER JOIN $wpdb->posts p
216 ON p.ID = cd.donation_id
217 $where_sql";
218
219 $total = $wpdb->get_var( $wpdb->prepare( $sql, $parameters ) );
220
221 if ( $this->is_comma_decimal() ) {
222 $total = Charitable_Currency::get_instance()->sanitize_database_amount( $total );
223 }
224
225 return $total;
226 }
227
228 /**
229 * Return an object containing all campaign donations associated with a particular
230 * campaign ID or a particular donation ID.
231 *
232 * @since 1.4.0
233 *
234 * @global WPDB $wpdb
235 * @param string $field The field we are retrieving donations by. Either 'campaign' or 'donation'.
236 * @param int|int[] $donation_id A single donation ID or an array of IDs.
237 * @return object
238 */
239 public function get_campaign_donations_by( $field, $donation_id ) {
240 global $wpdb;
241
242 $column = $this->get_sanitized_column( $field );
243
244 list( $in, $parameters ) = $this->get_in_clause_params( $donation_id );
245
246 $sql = "SELECT *
247 FROM $this->table_name
248 WHERE $column IN ( $in );";
249
250 $records = $wpdb->get_results( $wpdb->prepare( $sql, $parameters ), OBJECT_K );
251
252 if ( $this->is_comma_decimal() ) {
253 $records = array_map( array( $this, 'sanitize_amounts' ), $records );
254 }
255
256 return $records;
257 }
258
259 /**
260 * Return a list of all distinct IDs based on a particular field.
261 *
262 * @since 1.4.0
263 *
264 * @global WPDB $wpdb
265 * @param string $field The distinct field we are retrieving.
266 * @param int|int[] $id An ID or an array of IDs.
267 * @param string $where_field Column used for the where argument.
268 * @return object
269 */
270 public function get_distinct_ids( $field, $id, $where_field = 'campaign_id' ) {
271 global $wpdb;
272
273 $select_column = $this->get_sanitized_column( $field );
274 $where_column = $this->get_sanitized_column( $where_field );
275
276 list( $in, $parameters ) = $this->get_in_clause_params( $id );
277
278 $sql = "SELECT DISTINCT $select_column
279 FROM $this->table_name
280 WHERE $where_column IN ( $in );";
281
282 return $wpdb->get_col( $wpdb->prepare( $sql, $parameters ) );
283 }
284
285 /**
286 * Get an object of all campaign donations associated with one or more donations.
287 *
288 * @uses Charitable_Campaign_Donations_DB::get_campaign_donations_by()
289 *
290 * @since 1.0.0
291 *
292 * @param int|int[] $donation_id A single donation ID or an array of IDs.
293 * @return object
294 */
295 public function get_donation_records( $donation_id ) {
296 return $this->get_campaign_donations_by( 'donation_id', $donation_id );
297 }
298
299 /**
300 * Get the amount donated in a single donation.
301 *
302 * @since 1.3.0
303 *
304 * @global WPDB $wpdb
305 * @param int|int[] $donation_id A single donation ID or an array of IDs.
306 * @param int|int[] $campaign Optional. If set, this will only return the total donated to that campaign, or array of campaigns.
307 * @return decimal
308 */
309 public function get_donation_amount( $donation_id, $campaign = '' ) {
310 global $wpdb;
311
312 list( $in, $parameters ) = $this->get_in_clause_params( $donation_id );
313
314 $where_clause = "donation_id IN ( $in )";
315
316 if ( ! empty( $campaign ) ) {
317
318 list( $campaigns_in, $campaigns_parameters ) = $this->get_in_clause_params( $campaign );
319
320 $where_clause .= " AND campaign_id IN ( $campaigns_in )";
321 $parameters = array_merge( $parameters, $campaigns_parameters );
322
323 }
324
325 $sql = "SELECT SUM(amount)
326 FROM $this->table_name
327 WHERE $where_clause;";
328
329 $total = $wpdb->get_var( $wpdb->prepare( $sql, $parameters ) );
330
331 if ( $this->is_comma_decimal() ) {
332 $total = Charitable_Currency::get_instance()->sanitize_database_amount( $total );
333 }
334
335 return $total;
336 }
337
338 /**
339 * Get the total amount donated in a single donation.
340 *
341 * @since 1.0.0
342 *
343 * @param int $donation_id
344 * @return decimal
345 */
346 public function get_donation_total_amount( $donation_id ) {
347 return $this->get_donation_amount( $donation_id );
348 }
349
350 /**
351 * Return an array of campaigns donated to in a single donation.
352 *
353 * @since 1.2.0
354 *
355 * @global wpdb $wpdb
356 * @return object
357 */
358 public function get_campaigns_for_donation( $donation_id ) {
359 global $wpdb;
360
361 $sql = "SELECT DISTINCT campaign_id
362 FROM $this->table_name
363 WHERE donation_id = %d;";
364
365 return $wpdb->get_col( $wpdb->prepare( $sql, intval( $donation_id ) ) );
366 }
367
368 /**
369 * Get an object of all donations on a campaign.
370 *
371 * @uses Charitable_Campaign_Donations_DB::get_campaign_donations_by()
372 *
373 * @since 1.0.0
374 *
375 * @param int|int[] $campaign_id
376 * @return object
377 */
378 public function get_donations_on_campaign( $campaign_id ) {
379 return $this->get_campaign_donations_by( 'campaign_id', $campaign_id );
380 }
381
382 /**
383 * Get total amount donated to a campaign.
384 *
385 * @since 1.0.0
386 *
387 * @global wpdb $wpdb
388 * @param int|int[] $campaigns A campaign ID. Optionally, you can pass an array of campaign IDs to get the total of all put together.
389 * @param boolean $include_all Whether donations with non-approved statuses should be included.
390 * @param boolean $sanitize Whether to sanitize the amount if we're using commas for decimals.
391 * @return string
392 */
393 public function get_campaign_donated_amount( $campaigns, $include_all = false, $sanitize = true ) {
394 return $this->get_amount_report(
395 array(
396 'status' => $include_all ? array() : charitable_get_approval_statuses(),
397 'campaigns' => $campaigns,
398 ),
399 $sanitize
400 );
401
402 }
403
404 /**
405 * Get an array of all donation ids for a campaign.
406 *
407 * @uses Charitable_Campaign_Donations_DB::get_distinct_ids()
408 *
409 * @since 1.0.0
410 *
411 * @param int $campaign_id Campaign ID.
412 * @return object
413 */
414 public function get_donation_ids_for_campaign( $campaign_id ) {
415 return $this->get_distinct_ids( 'donation_id', $campaign_id, 'campaign_id' );
416 }
417
418 /**
419 * The donor IDs of all who have donated to the given campaign.
420 *
421 * @uses Charitable_Campaign_Donations_DB::get_distinct_ids()
422 *
423 * @since 1.0.0
424 *
425 * @param int $campaign_id The campaign ID to get donors for.
426 * @return object
427 */
428 public function get_campaign_donors( $campaign_id ) {
429 return $this->get_distinct_ids( 'donor_id', $campaign_id, 'campaign_id' );
430 }
431
432 /**
433 * Return the number of users who have donated to the given campaign.
434 *
435 * @since 1.0.0
436 *
437 * @global wpdb $wpdb
438 * @param int|int[] $campaign The campaign ID, or list of campaign IDs.
439 * @param boolean $include_all Whether to include all donations (true), or only include approved donations (false).
440 * @return int
441 */
442 public function count_campaign_donors( $campaign, $include_all = false ) {
443 global $wpdb;
444
445 $statuses = $include_all ? array() : charitable_get_approval_statuses();
446
447 list( $status_clause, $status_parameters ) = $this->get_donation_status_clause( $statuses );
448 list( $campaigns_in, $campaigns_parameters ) = $this->get_in_clause_params( $campaign );
449
450 $sql_where_clauses[] = "cd.campaign_id IN ( $campaigns_in )";
451 $sql_where_clauses[] = $status_clause;
452 $sql_where = 'WHERE ' . implode( ' AND ', $sql_where_clauses );
453
454 $parameters = array_merge( $campaigns_parameters, $status_parameters );
455
456 $sql = "SELECT COUNT( DISTINCT cd.donor_id )
457 FROM $this->table_name cd
458 INNER JOIN $wpdb->posts p ON p.ID = cd.donation_id
459 $sql_where;";
460
461 return $wpdb->get_var( $wpdb->prepare( $sql, $parameters ) );
462 }
463
464 /**
465 * Return all donations made by a donor.
466 *
467 * @since 1.0.0
468 *
469 * @global wpdb $wpdb
470 * @param int $donor_id The donor ID.
471 * @param boolean $distinct_donations Whether to get distinct donations.
472 * @return object[]
473 */
474 public function get_donations_by_donor( $donor_id, $distinct_donations = false ) {
475 global $wpdb;
476
477 if ( $distinct_donations ) {
478 $select_fields = 'DISTINCT( cd.donation_id ), cd.campaign_id, cd.campaign_name, cd.amount';
479 } else {
480 $select_fields = 'cd.campaign_donation_id, cd.donation_id, cd.campaign_id, cd.campaign_name, cd.amount';
481 }
482
483 $sql = "SELECT $select_fields
484 FROM $this->table_name cd
485 WHERE cd.donor_id = %d;";
486
487 $results = $wpdb->get_results( $wpdb->prepare( $sql, $donor_id ), OBJECT_K );
488
489 if ( $this->is_comma_decimal() ) {
490 $results = array_map( array( $this, 'sanitize_amounts' ), $results );
491 }
492
493 return $results;
494 }
495
496 /**
497 * Return total amount donated by a donor.
498 *
499 * @since 1.0.0
500 *
501 * @global WPDB $wpdb
502 * @param int $donor_id The donor ID.
503 * @return int
504 */
505 public function get_total_donated_by_donor( $donor_id ) {
506 global $wpdb;
507
508 $sql = "SELECT COALESCE( SUM(cd.amount), 0 )
509 FROM $this->table_name cd
510 WHERE cd.donor_id = %d;";
511
512 $total = $wpdb->get_var( $wpdb->prepare( $sql, $donor_id ) );
513
514 if ( $this->is_comma_decimal() ) {
515 $total = Charitable_Currency::get_instance()->sanitize_database_amount( $total );
516 }
517
518 return $total;
519 }
520
521 /**
522 * Count the number of donations made by the donor.
523 *
524 * @since 1.0.0
525 *
526 * @global wpdb $wpdb
527 * @param int $donor_id The donor ID.
528 * @param boolean $distinct_donations If true, will only count unique donations.
529 * @return int
530 */
531 public function count_donations_by_donor( $donor_id, $distinct_donations = false ) {
532 global $wpdb;
533
534 $count = $distinct_donations ? 'DISTINCT donation_id' : 'donation_id';
535
536 $sql = "SELECT COUNT( $count )
537 FROM $this->table_name
538 WHERE donor_id = %d;";
539
540 return $wpdb->get_var( $wpdb->prepare( $sql, $donor_id ) );
541 }
542
543 /**
544 * Count the number of campaigns that the donor has supported.
545 *
546 * @since 1.0.0
547 *
548 * @global wpdb $wpdb
549 * @param int $donor_id The donor to retrieve campaigns for.
550 * @return int
551 */
552 public function count_campaigns_supported_by_donor( $donor_id ) {
553 global $wpdb;
554
555 $sql = "SELECT COUNT( DISTINCT campaign_id )
556 FROM $this->table_name
557 WHERE donor_id = %d;";
558
559 return $wpdb->get_var( $wpdb->prepare( $sql, $donor_id ) );
560 }
561
562 /**
563 * Return a set of donations, filtered by the provided arguments.
564 *
565 * @since 1.0.0
566 *
567 * @global WPDB $wpdb
568 * @param array $args Query arguments.
569 * @return array
570 */
571 public function get_donations_report( $args ) {
572 global $wpdb;
573
574 $sql_order = $this->get_orderby_clause( $args, 'ORDER BY p.post_date ASC' );
575 list( $sql_where, $parameters ) = $this->get_report_sql_where_clause( $args );
576
577 /* This is our base SQL query */
578 $sql = "SELECT cd.donation_id, cd.campaign_id, cd.campaign_name, cd.amount, d.email, d.first_name, d.last_name, p.post_date, p.post_content, p.post_status
579 FROM $this->table_name cd
580 INNER JOIN {$wpdb->prefix}charitable_donors d
581 ON d.donor_id = cd.donor_id
582 INNER JOIN $wpdb->posts p
583 ON p.ID = cd.donation_id
584 $sql_where
585 $sql_order";
586
587 if ( ! empty( $parameters ) ) {
588 $sql = $wpdb->prepare( $sql, $parameters );
589 }
590
591 $results = $wpdb->get_results( $sql );
592
593 if ( $this->is_comma_decimal() ) {
594 $results = array_map( array( $this, 'sanitize_amounts' ), $results );
595 }
596
597 return $results;
598 }
599
600 /**
601 * Return a total amount donated
602 *
603 * @since 1.6.57
604 *
605 * @global WPDB $wpdb
606 * @param array $args Query arguments.
607 * @param boolean $sanitize Whether to sanitize the amount if we're using commas for decimals.
608 * @return int The total amount
609 */
610 public function get_amount_report( $args, $sanitize = true ) {
611 global $wpdb;
612
613 list( $sql_where, $parameters ) = $this->get_report_sql_where_clause( $args );
614
615 /* Get the total */
616 $sql = "SELECT COALESCE( SUM(amount), 0 )
617 FROM $this->table_name cd
618 INNER JOIN $wpdb->posts p
619 ON p.ID = cd.donation_id
620 $sql_where";
621
622 if ( ! empty( $parameters ) ) {
623 $sql = $wpdb->prepare( $sql, $parameters );
624 }
625
626 $total = $wpdb->get_var( $sql );
627
628 if ( $this->is_comma_decimal() && $sanitize ) {
629 $total = Charitable_Currency::get_instance()->sanitize_database_amount( $total );
630 }
631
632 return $total;
633 }
634
635 /**
636 * Return a total amount donated, grouped by campaign.
637 * Created for Charitable-Stats-Shortcode.
638 *
639 * @since 1.6.57
640 *
641 * @global WPDB $wpdb
642 *
643 * @param array $args Query arguments.
644 * @param boolean $sanitize Whether to sanitize the amount if we're using commas for decimals.
645 * @return array An array of amounts and campaign names
646 */
647 public function get_amount_by_campaign_report( $args, $sanitize = true ) {
648 global $wpdb;
649
650 list( $sql_where, $parameters ) = $this->get_report_sql_where_clause( $args );
651
652 /* Get the total */
653 $sql = "SELECT cd.campaign_name, COALESCE( SUM(amount), 0 ) as total
654 FROM $this->table_name cd
655 INNER JOIN $wpdb->posts p
656 ON p.ID = cd.donation_id
657 $sql_where
658 GROUP BY cd.campaign_id, cd.campaign_name";
659
660 if ( ! empty( $parameters ) ) {
661 $sql = $wpdb->prepare( $sql, $parameters );
662 }
663
664 $results = $wpdb->get_results( $sql, 'ARRAY_N' );
665
666 if ( $this->is_comma_decimal() && $sanitize ) {
667 $results = array_map( array( $this, 'sanitize_grouped_amounts' ), $results );
668 }
669
670 return $results;
671 }
672
673 /**
674 * Return an SQL where clause for the report
675 *
676 * @since 1.6.57
677 *
678 * @param array $args Query arguments.
679 * @return array
680 */
681 public function get_report_sql_where_clause( $args ) {
682 $parameters = array();
683 $sql_where = '';
684 $sql_where_clauses = array();
685
686 /* campaign_id should become 'campaigns'. */
687 if ( isset( $args['campaign_id'] ) ) {
688 $args['campaigns'] = $args['campaign_id'];
689 }
690
691 if ( isset( $args['campaigns'] ) ) {
692 list( $campaigns_in, $campaigns_parameters ) = $this->get_in_clause_params( $args['campaigns'] );
693
694 $sql_where_clauses[] = "cd.campaign_id IN ( $campaigns_in )";
695 $parameters = array_merge( $parameters, $campaigns_parameters );
696 }
697
698 if ( isset( $args['status'] ) ) {
699 if ( ! is_array( $args['status'] ) ) {
700 /* Ensure this is an array. */
701 $args['status'] = array( $args['status'] );
702 }
703
704 list( $status_sql, $status_parameters ) = $this->get_donation_status_clause( $args['status'] );
705 $sql_where_clauses[] = $status_sql;
706 $parameters = array_merge( $parameters, $status_parameters );
707
708 } else {
709 /* If ALL: select all valid statuses */
710 $statuses = array_keys( charitable_get_valid_donation_statuses() );
711 $in = charitable_get_query_placeholders( count( $statuses ), '%s' );
712 $sql_where_clauses[] = "p.post_status IN ( $in )";
713 $parameters = array_merge( $parameters, $statuses );
714 }
715
716 if ( ! empty( $args['start_date'] ) ) {
717 $sql_where_clauses[] = 'p.post_date >= %s';
718 $parameters[] = $args['start_date'];
719 }
720
721 if ( ! empty( $args['end_date'] ) ) {
722 $sql_where_clauses[] = 'p.post_date <= %s';
723 $parameters[] = $args['end_date'];
724 }
725
726 if ( ! empty( $sql_where_clauses ) ) {
727 $sql_where = 'WHERE ' . implode( ' AND ', $sql_where_clauses );
728 }
729
730 return array( $sql_where, $parameters );
731 }
732
733 /**
734 * Return a count and sum of donations for a given period.
735 *
736 * @since 1.2.0
737 *
738 * @global WPDB $wpdb
739 * @param string $period The period to get donations for.
740 * @param string[] $statuses List of statuses.
741 * @return array
742 */
743 public function get_donations_summary_by_period( $period = '', $statuses = array() ) {
744 global $wpdb;
745
746 if ( empty( $statuses ) ) {
747 $statuses = charitable_get_approval_statuses();
748 }
749
750 list( $status_clause, $parameters ) = $this->get_donation_status_clause( $statuses );
751
752 array_unshift( $parameters, $period );
753
754 $sql_where_clauses[] = "DATE_FORMAT( p.post_date, '%%Y-%%m-%%d' ) LIKE %s";
755 $sql_where_clauses[] = $status_clause;
756 $sql_where = 'WHERE ' . implode( ' AND ', $sql_where_clauses );
757
758 $sql = "SELECT COALESCE( SUM( cd.amount ), 0 ) as amount, COUNT( cd.donation_id ) as count
759 FROM {$wpdb->prefix}charitable_campaign_donations cd
760 INNER JOIN $wpdb->posts p ON p.ID = cd.donation_id
761 $sql_where";
762
763 $results = $wpdb->get_results( $wpdb->prepare( $sql, $parameters ) );
764
765 if ( empty( $results ) ) {
766 return (object) array(
767 'amount' => 0.0000,
768 'count' => 0,
769 );
770 }
771
772 $result = $results[0];
773
774 if ( $this->is_comma_decimal() ) {
775 $result = $this->sanitize_amounts( $result );
776 }
777
778 return $result;
779 }
780
781 /**
782 * Returns the orderby clause.
783 *
784 * @since 1.3.4
785 *
786 * @param array $args Query arguments.
787 * @param string $default Default.
788 * @return string
789 */
790 public function get_orderby_clause( $args, $default = '' ) {
791 if ( ! isset( $args['orderby'] ) && ! isset( $args['order'] ) ) {
792 return $default;
793 }
794
795 $orderby = isset( $args['orderby'] ) ? $args['orderby'] : 'ID';
796 $order = isset( $args['order'] ) && in_array( $args['order'], array( 'ASC', 'DESC' ) ) ? $args['order'] : 'ASC';
797
798 switch ( $orderby ) {
799 case 'date':
800 $ret = 'ORDER BY p.post_date ';
801 break;
802
803 default:
804 $ret = 'ORDER BY cd.campaign_donation_id ';
805 }
806
807 $ret .= $order;
808
809 return $ret;
810 }
811
812 /**
813 * Count donations by status.
814 *
815 * @since 1.0.0
816 *
817 * @param string|string[] $statuses List of statuses.
818 * @return int
819 */
820 public function count_donations_by_status( $statuses ) {
821 global $wpdb;
822
823 if ( ! is_array( $statuses ) ) {
824 $statuses = array( $statuses );
825 }
826
827 list( $status_clause, $parameters ) = $this->get_donation_status_clause( $statuses );
828 if ( ! empty( $status_clause ) ) {
829 $sql_where = 'WHERE ' . $status_clause;
830 }
831
832 $sql = "SELECT COUNT( * )
833 FROM {$wpdb->prefix}charitable_campaign_donations cd
834 INNER JOIN $wpdb->posts p ON p.ID = cd.donation_id
835 $sql_where;";
836
837 return $wpdb->get_var( $wpdb->prepare( $sql, $parameters ) );
838 }
839
840 /**
841 * Returns the donation status clause.
842 *
843 * @since 1.0.0
844 *
845 * @param string[] $statuses List of statuses.
846 * @return array
847 */
848 private function get_donation_status_clause( $statuses = array() ) {
849 if ( empty( $statuses ) ) {
850 return array( '', array() );
851 }
852
853 $statuses = array_filter( $statuses, 'charitable_is_valid_donation_status' );
854 $in = charitable_get_query_placeholders( count( $statuses ), '%s' );
855 $sql = "p.post_status IN ( $in )";
856
857 return array( $sql, $statuses );
858 }
859
860 /**
861 * Returns an array containing the placeholders and sanitized parameters for an IN clause.
862 *
863 * @since 1.4.0
864 *
865 * @param int|int[] $list List of elements.
866 * @return array
867 */
868 private function get_in_clause_params( $list ) {
869 if ( ! is_array( $list ) ) {
870 $list = array( $list );
871 }
872
873 /* Filter out any non-numeric campaign IDs, then convert to int */
874 $list = array_filter( $list, 'is_numeric' );
875 $list = array_map( 'intval', $list );
876
877 return array( charitable_get_query_placeholders( count( $list ), '%d' ), $list );
878 }
879
880 /**
881 * Checks whether we are using commas for decimals.
882 *
883 * @since 1.3.0
884 *
885 * @return boolean
886 */
887 private function is_comma_decimal() {
888 if ( ! isset( $this->comma_decimal ) ) {
889 $this->comma_decimal = Charitable_Currency::get_instance()->is_comma_decimal();
890 }
891
892 return $this->comma_decimal;
893 }
894
895 /**
896 * Sanitize amounts retrieved from the database.
897 *
898 * @since 1.3.0
899 *
900 * @param object $campaign_donation Campaign donation record.
901 * @return object
902 */
903 private function sanitize_amounts( $campaign_donation ) {
904 $campaign_donation->amount = Charitable_Currency::get_instance()->sanitize_database_amount( $campaign_donation->amount );
905 return $campaign_donation;
906 }
907
908 /**
909 * Sanitize amounts for grouped queries
910 *
911 * @since 1.6.57
912 *
913 * @param array $item[0] in array is a label, item[1] is the amount. We need to sanitize the amount.
914 * @return object
915 */
916 private function sanitize_grouped_amounts( $item ) {
917 $item[1] = Charitable_Currency::get_instance()->sanitize_database_amount( $item[1] );
918 return $item;
919 }
920
921 /**
922 * Return a sanitized column name.
923 *
924 * @since 1.4.0
925 *
926 * @param string $field Return the column name.
927 * @return string
928 */
929 private function get_sanitized_column( $field ) {
930 switch ( $field ) {
931 case 'campaign':
932 case 'campaign_id':
933 $column = 'campaign_id';
934 break;
935
936 case 'donation':
937 case 'donation_id':
938 $column = 'donation_id';
939 break;
940
941 case 'donor':
942 case 'donor_id':
943 $column = 'donor_id';
944 break;
945
946 default:
947 charitable_get_deprecated()->doing_it_wrong(
948 __METHOD__,
949 __( 'Field expected to be `campaign`, `campaign_id`, `donation`, `donation_id`, `donor` or `donor_id`.', 'charitable' ),
950 '1.4.0'
951 );
952
953 $column = false;
954 }
955
956 return $column;
957 }
958
959 /**
960 * Flush campaign caches when updating one or more rows.
961 *
962 * @since 1.5.11
963 *
964 * @param int $row_id The primary key ID for the row we are retrieving.
965 * @param string $where Column used in where argument.
966 * @return void
967 */
968 private function flush_campaign_caches( $row_id, $where = '' ) {
969 if ( empty( $where ) ) {
970 $where = $this->primary_key;
971 }
972
973 $campaign_ids = array_unique( $this->get_column_all_by( 'campaign_id', $where, $row_id ) );
974
975 foreach ( $campaign_ids as $campaign_id ) {
976 Charitable_Campaign::flush_donations_cache( $campaign_id );
977 }
978 }
979 }
980
981 endif;
982