Test Failed
Push — master ( 315839...9b266f )
by Devin
05:39
created

Give_Payments_Query::custom_orderby()   B

Complexity

Conditions 7
Paths 6

Size

Total Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
nc 6
nop 2
dl 0
loc 19
rs 8.8333
c 0
b 0
f 0
1
<?php
2
/**
3
 * Payments Query
4
 *
5
 * @package     Give
6
 * @subpackage  Classes/Stats
7
 * @copyright   Copyright (c) 2016, GiveWP
8
 * @license     https://opensource.org/licenses/gpl-license GNU Public License
9
 * @since       1.0
10
 */
11
12
// Exit if accessed directly.
13
if ( ! defined( 'ABSPATH' ) ) {
14
	exit;
15
}
16
17
/**
18
 * Give_Payments_Query Class
19
 *
20
 * This class is for retrieving payments data.
21
 *
22
 * Payments can be retrieved for date ranges and pre-defined periods.
23
 *
24
 * @since 1.0
25
 */
26
class Give_Payments_Query extends Give_Stats {
27
28
	/**
29
	 * Preserve args
30
	 *
31
	 * @since  1.8.17
32
	 * @access public
33
	 *
34
	 * @var    array
35
	 */
36
	public $_args = array();
37
38
	/**
39
	 * The args to pass to the give_get_payments() query
40
	 *
41
	 * @since  1.0
42
	 * @access public
43
	 *
44
	 * @var    array
45
	 */
46
	public $args = array();
47
48
	/**
49
	 * The payments found based on the criteria set
50
	 *
51
	 * @since  1.0
52
	 * @access public
53
	 *
54
	 * @var    array
55
	 */
56
	public $payments = array();
57
58
	/**
59
	 * Default query arguments.
60
	 *
61
	 * Not all of these are valid arguments that can be passed to WP_Query. The ones that are not, are modified before
62
	 * the query is run to convert them to the proper syntax.
63
	 *
64
	 * @since  1.0
65
	 * @access public
66
	 *
67
	 * @param  $args array The array of arguments that can be passed in and used for setting up this payment query.
68
	 */
69
	public function __construct( $args = array() ) {
70
		$defaults = array(
71
			'output'          => 'payments',
72
			'post_type'       => array( 'give_payment' ),
73
			'start_date'      => false,
74
			'end_date'        => false,
75
			'number'          => 20,
76
			'page'            => null,
77
			'orderby'         => 'ID',
78
			'order'           => 'DESC',
79
			'user'            => null, // deprecated, use donor
80
			'donor'           => null,
81
			'status'          => give_get_payment_status_keys(),
82
			'meta_key'        => null,
83
			'year'            => null,
84
			'month'           => null,
85
			'day'             => null,
86
			's'               => null,
87
			'search_in_notes' => false,
88
			'children'        => false,
89
			'fields'          => null,
90
			'gateway'         => null,
91
			'give_forms'      => null,
92
			'offset'          => null,
93
94
			// Currently these params only works with get_payment_by_group
95
			'group_by'        => '',
96
			'count'           => false,
97
		);
98
99
		// We do not want WordPress to handle meta cache because WordPress stores in under `post_meta` key and cache object while we want it under `donation_meta`.
100
		// Similar for term cache
101
		$args['update_post_meta_cache'] = false;
102
103
		$this->args = $this->_args = wp_parse_args( $args, $defaults );
104
105
		$this->init();
106
	}
107
108
	/**
109
	 * Set a query variable.
110
	 *
111
	 * @since  1.0
112
	 * @access public
113
	 *
114
	 * @param $query_var
115
	 * @param $value
116
	 */
117 View Code Duplication
	public function __set( $query_var, $value ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
118
		if ( in_array( $query_var, array( 'meta_query', 'tax_query' ) ) ) {
119
			$this->args[ $query_var ][] = $value;
120
		} else {
121
			$this->args[ $query_var ] = $value;
122
		}
123
	}
124
125
	/**
126
	 * Unset a query variable.
127
	 *
128
	 * @since  1.0
129
	 * @access public
130
	 *
131
	 * @param $query_var
132
	 */
133
	public function __unset( $query_var ) {
134
		unset( $this->args[ $query_var ] );
135
	}
136
137
	/**
138
	 * Modify the query/query arguments before we retrieve payments.
139
	 *
140
	 * @since  1.0
141
	 * @access public
142
	 *
143
	 * @return void
144
	 */
145
	public function init() {
146
	}
147
148
149
	/**
150
	 * Set query filter.
151
	 *
152
	 * @since  1.8.9
153
	 * @access private
154
	 */
155
	private function set_filters() {
156
		// Reset param to apply filters.
157
		// While set filters $args will get override and multiple get_payments call will not work.
158
		$this->args = $this->_args;
159
160
		$this->date_filter_pre();
161
		$this->orderby();
162
		$this->status();
163
		$this->month();
164
		$this->per_page();
165
		$this->page();
166
		$this->user();
167
		$this->donor();
168
		$this->search();
169
		$this->mode();
170
		$this->children();
171
		$this->give_forms();
172
		$this->gateway_filter();
173
174
		add_filter( 'posts_orderby', array( $this, 'custom_orderby' ), 10, 2 );
175
176
		/**
177
		 * Fires after setup filters.
178
		 *
179
		 * @since 1.0
180
		 *
181
		 * @param Give_Payments_Query $this Payments query object.
182
		 */
183
		do_action( 'give_pre_get_payments', $this );
184
	}
185
186
	/**
187
	 * Unset query filter.
188
	 *
189
	 * @since  1.8.9
190
	 * @access private
191
	 */
192
	private function unset_filters() {
193
		remove_filter( 'posts_orderby', array( $this, 'custom_orderby' ) );
194
195
		/**
196
		 * Fires after retrieving payments.
197
		 *
198
		 * @since 1.0
199
		 *
200
		 * @param Give_Payments_Query $this Payments query object.
201
		 */
202
		do_action( 'give_post_get_payments', $this );
203
	}
204
205
206
	/**
207
	 * Retrieve payments.
208
	 *
209
	 * The query can be modified in two ways; either the action before the
210
	 * query is run, or the filter on the arguments (existing mainly for backwards
211
	 * compatibility).
212
	 *
213
	 * @since  1.0
214
	 * @access public
215
	 *
216
	 * @return array
217
	 */
218
	public function get_payments() {
219
		global $post;
220
221
		$results        = array();
222
		$this->payments = array();
223
		$cache_key      = Give_Cache::get_key( 'give_payment_query', $this->args, false );
224
		$this->payments = Give_Cache::get_db_query( $cache_key );
0 ignored issues
show
Documentation Bug introduced by
It seems like \Give_Cache::get_db_query($cache_key) of type * is incompatible with the declared type array of property $payments.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
225
226
		// Return cached result.
227
		if ( ! is_null( $this->payments ) ) {
228
			return $this->payments;
229
		}
230
231
232
		// Modify the query/query arguments before we retrieve payments.
233
		$this->set_filters();
234
235
		/* @var WP_Query $query */
236
		$query = new WP_Query( $this->args );
237
238
		$custom_output = array(
239
			'payments',
240
			'give_payments',
241
		);
242
243
		if ( $query->have_posts() ) {
244
245
			// Update meta cache only if query is not for all donations.
246
			// @see https://github.com/impress-org/give/issues/4104
247
			if (
248
				( isset( $this->args['nopaging'] ) && true !== (bool) $this->args['nopaging'] )
249
				|| ( isset( $this->args['posts_per_page'] ) && 0 < $this->args['posts_per_page'] )
250
			) {
251
				self::update_meta_cache( wp_list_pluck( $query->posts, 'ID' ) );
252
			}
253
254 View Code Duplication
			if ( ! in_array( $this->args['output'], $custom_output ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
255
				$results = $query->posts;
256
257
			} else{
258
				$previous_post = $post;
259
260
				while ( $query->have_posts() ) {
261
					$query->the_post();
262
263
					$payment_id = get_post()->ID;
264
					$payment    = new Give_Payment( $payment_id );
265
266
					$this->payments[] = apply_filters( 'give_payment', $payment, $payment_id, $this );
267
				}
268
269
				wp_reset_postdata();
270
271
				// Prevent nest loop from producing unexpected results.
272
				if ( $previous_post instanceof WP_Post ) {
0 ignored issues
show
Bug introduced by
The class WP_Post does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
273
					$post = $previous_post;
274
					setup_postdata( $post );
275
				}
276
277
				$results = $this->payments;
278
			}
279
		}
280
281
		Give_Cache::set_db_query( $cache_key, $results );
282
283
		// Remove query filters after we retrieve payments.
284
		$this->unset_filters();
285
286
		return $results;
287
	}
288
289
	/**
290
	 * Get payments by group
291
	 *
292
	 * @since  1.8.17
293
	 * @access public
294
	 *
295
	 * @return array
296
	 */
297
	public function get_payment_by_group() {
298
		global $wpdb;
299
300
		$allowed_groups = array( 'post_status' );
301
		$result         = array();
302
303
304
		if ( in_array( $this->args['group_by'], $allowed_groups ) ) {
305
			// Set only count in result.
306
			if ( $this->args['count'] ) {
307
308
				$this->set_filters();
309
310
				$new_results = $wpdb->get_results( $this->get_sql(), ARRAY_N );
311
312
				$this->unset_filters();
313
314
				foreach ( $new_results as $results ) {
315
					$result[ $results[0] ] = $results[1];
316
				}
317
318
				switch ( $this->args['group_by'] ) {
319
					case 'post_status':
320
321
						/* @var Give_Payment $donation */
322
						foreach ( give_get_payment_status_keys() as $status ) {
323
							if ( ! isset( $result[ $status ] ) ) {
324
								$result[ $status ] = 0;
325
							}
326
						}
327
328
						break;
329
				}
330
			} else {
331
				$donations = $this->get_payments();
332
333
				/* @var $donation Give_Payment */
334
				foreach ( $donations as $donation ) {
335
					$result[ $donation->{$this->args['group_by']} ][] = $donation;
336
				}
337
			}
338
		}
339
340
341
		/**
342
		 * Filter the result
343
		 *
344
		 * @since 1.8.17
345
		 */
346
		return apply_filters( 'give_get_payment_by_group', $result, $this );
347
	}
348
349
	/**
350
	 * If querying a specific date, add the proper filters.
351
	 *
352
	 * @since  1.0
353
	 * @access public
354
	 *
355
	 * @return void
356
	 */
357
	public function date_filter_pre() {
358
		if ( ! ( $this->args['start_date'] || $this->args['end_date'] ) ) {
359
			return;
360
		}
361
362
		$this->setup_dates( $this->args['start_date'], $this->args['end_date'] );
363
364
		$is_start_date = property_exists( __CLASS__, 'start_date' );
365
		$is_end_date   = property_exists( __CLASS__, 'end_date' );
366
367
		if ( $is_start_date || $is_end_date ) {
368
			$date_query = array();
369
370
			if ( $is_start_date && ! is_wp_error( $this->start_date ) ) {
371
				$date_query['after'] = date( 'Y-m-d H:i:s', $this->start_date );
372
			}
373
374
			if ( $is_end_date && ! is_wp_error( $this->end_date ) ) {
375
				$date_query['before'] = date( 'Y-m-d H:i:s', $this->end_date );
376
			}
377
378
			// Include Start Date and End Date while querying.
379
			$date_query['inclusive'] = true;
380
381
			$this->__set( 'date_query', $date_query );
382
383
		}
384
	}
385
386
	/**
387
	 * Post Status
388
	 *
389
	 * @since  1.0
390
	 * @access public
391
	 *
392
	 * @return void
393
	 */
394
	public function status() {
395
		if ( ! isset( $this->args['status'] ) ) {
396
			return;
397
		}
398
399
		$this->__set( 'post_status', $this->args['status'] );
400
		$this->__unset( 'status' );
401
	}
402
403
	/**
404
	 * Current Page
405
	 *
406
	 * @since  1.0
407
	 * @access public
408
	 *
409
	 * @return void
410
	 */
411
	public function page() {
412
		if ( ! isset( $this->args['page'] ) ) {
413
			return;
414
		}
415
416
		$this->__set( 'paged', $this->args['page'] );
417
		$this->__unset( 'page' );
418
	}
419
420
	/**
421
	 * Posts Per Page
422
	 *
423
	 * @since  1.0
424
	 * @access public
425
	 *
426
	 * @return void
427
	 */
428
	public function per_page() {
429
430
		if ( ! isset( $this->args['number'] ) ) {
431
			return;
432
		}
433
434
		if ( $this->args['number'] == - 1 ) {
435
			$this->__set( 'nopaging', true );
436
		} else {
437
			$this->__set( 'posts_per_page', $this->args['number'] );
438
		}
439
440
		$this->__unset( 'number' );
441
	}
442
443
	/**
444
	 * Current Month
445
	 *
446
	 * @since  1.0
447
	 * @access public
448
	 *
449
	 * @return void
450
	 */
451
	public function month() {
452
		if ( ! isset( $this->args['month'] ) ) {
453
			return;
454
		}
455
456
		$this->__set( 'monthnum', $this->args['month'] );
457
		$this->__unset( 'month' );
458
	}
459
460
	/**
461
	 * Order by
462
	 *
463
	 * @since  1.0
464
	 * @access public
465
	 *
466
	 * @return void
467
	 */
468
	public function orderby() {
469
		switch ( $this->args['orderby'] ) {
470
			case 'amount':
471
				$this->__set( 'orderby', 'meta_value_num' );
472
				$this->__set( 'meta_key', '_give_payment_total' );
473
				break;
474
475
			case 'status':
476
				$this->__set( 'orderby', 'post_status' );
477
				break;
478
479
			case 'donation_form':
480
				$this->__set( 'orderby', 'meta_value' );
481
				$this->__set( 'meta_key', '_give_payment_form_title' );
482
				break;
483
484
			default:
485
				$this->__set( 'orderby', $this->args['orderby'] );
486
				break;
487
		}
488
	}
489
490
	/**
491
	 * Custom orderby.
492
	 * Note: currently custom sorting is only used for donation listing page.
493
	 *
494
	 * @since  1.8
495
	 * @access public
496
	 *
497
	 * @param string   $order
498
	 * @param WP_Query $query
499
	 *
500
	 * @return mixed
501
	 */
502
	public function custom_orderby( $order, $query ) {
503
504
		if ( ! empty( $query->query['post_type'] ) ) {
505
			$post_types = is_array( $query->query['post_type'] ) ? $query->query['post_type'] : array( $query->query['post_type'] );
506
507
			if ( ! in_array( 'give_payment', $post_types ) || ! isset( $query->query['orderby'] ) || is_array( $query->query['orderby'] ) ) {
508
				return $order;
509
			}
510
511
			global $wpdb;
512
			switch ( $query->query['orderby'] ) {
513
				case 'post_status':
514
					$order = $wpdb->posts . '.post_status ' . strtoupper( $query->query['order'] );
515
					break;
516
			}
517
		}
518
519
		return $order;
520
	}
521
522
	/**
523
	 * Specific User
524
	 *
525
	 * @since  1.0
526
	 * @access public
527
	 *
528
	 * @return void
529
	 */
530
	public function user() {
531
		if ( is_null( $this->args['user'] ) ) {
532
			return;
533
		}
534
535
536
		$args = array();
537
538
		if ( is_numeric( $this->args['user'] ) ) {
539
			// Backward compatibility: user donor param to get payment attached to donor instead of user
540
			$donor_id = Give()->donors->get_column_by( 'id', is_numeric( $this->args['user'] ) ? 'user_id' : 'email', $this->args['user'] );
541
542
			$args = array(
543
				'key'   => '_give_payment_donor_id',
544
				'value' => absint( $donor_id ),
545
			);
546
		} elseif ( is_email( $this->args['user'] ) ) {
547
			$args = array(
548
				'key'   => '_give_payment_donor_email',
549
				'value' => $this->args['user'],
550
			);
551
		}
552
553
		$this->__set( 'meta_query', $args );
554
	}
555
556
	/**
557
	 * Specific donor id
558
	 *
559
	 * @access  public
560
	 * @since   1.8.9
561
	 * @return  void
562
	 */
563
	public function donor() {
564
		if ( is_null( $this->args['donor'] ) || ! is_numeric( $this->args['donor'] ) ) {
565
			return;
566
		}
567
568
		$donor_meta_type = Give()->donor_meta->meta_type;
569
570
		$this->__set( 'meta_query', array(
571
			'key'   => "_give_payment_{$donor_meta_type}_id",
572
			'value' => (int) $this->args['donor'],
573
		) );
574
	}
575
576
	/**
577
	 * Search
578
	 *
579
	 * @since  1.0
580
	 * @access public
581
	 *
582
	 * @return void
583
	 */
584
	public function search() {
585
586
		if ( ! isset( $this->args['s'] ) ) {
587
			return;
588
		}
589
590
		$search = trim( $this->args['s'] );
591
592
		if ( empty( $search ) ) {
593
			return;
594
		}
595
596
		$is_email = is_email( $search ) || strpos( $search, '@' ) !== false;
597
		$is_user  = strpos( $search, strtolower( 'user:' ) ) !== false;
598
599
		if ( ! empty( $this->args['search_in_notes'] ) ) {
600
601
			$notes = give_get_payment_notes( 0, $search );
602
603
			if ( ! empty( $notes ) ) {
604
605
				$payment_ids = wp_list_pluck( (array) $notes, 'comment_post_ID' );
606
607
				$this->__set( 'post__in', $payment_ids );
608
			}
609
610
			$this->__unset( 's' );
611
612
		} elseif ( $is_email || strlen( $search ) == 32 ) {
613
614
			$key         = $is_email ? '_give_payment_donor_email' : '_give_payment_purchase_key';
615
			$search_meta = array(
616
				'key'     => $key,
617
				'value'   => $search,
618
				'compare' => 'LIKE',
619
			);
620
621
			$this->__set( 'meta_query', $search_meta );
622
			$this->__unset( 's' );
623
624
		} elseif ( $is_user ) {
625
626
			$search_meta = array(
627
				'key'   => '_give_payment_donor_id',
628
				'value' => trim( str_replace( 'user:', '', strtolower( $search ) ) ),
629
			);
630
631
			$this->__set( 'meta_query', $search_meta );
632
633
			$this->__unset( 's' );
634
635
		} elseif ( is_numeric( $search ) ) {
636
637
			$post = get_post( $search );
638
639
			if ( is_object( $post ) && $post->post_type == 'give_payment' ) {
640
641
				$arr   = array();
642
				$arr[] = $search;
643
				$this->__set( 'post__in', $arr );
644
				$this->__unset( 's' );
645
			}
646
		} elseif ( '#' == substr( $search, 0, 1 ) ) {
647
648
			$search = str_replace( '#:', '', $search );
649
			$search = str_replace( '#', '', $search );
650
			$this->__set( 'give_forms', $search );
651
			$this->__unset( 's' );
652
653
		} else if ( ! empty( $search ) ) {
654
			$search_parts = preg_split( '/\s+/', $search );
655
656
			if ( is_array( $search_parts ) && 2 === count( $search_parts ) ) {
657
				$search_meta = array(
658
					'relation' => 'AND',
659
					array(
660
						'key'     => '_give_donor_billing_first_name',
661
						'value'   => $search_parts[0],
662
						'compare' => '=',
663
					),
664
					array(
665
						'key'     => '_give_donor_billing_last_name',
666
						'value'   => $search_parts[1],
667
						'compare' => '=',
668
					),
669
				);
670
			} else {
671
				$search_meta = array(
672
					'relation' => 'OR',
673
					array(
674
						'key'     => '_give_donor_billing_first_name',
675
						'value'   => $search,
676
						'compare' => 'LIKE',
677
					),
678
					array(
679
						'key'     => '_give_donor_billing_last_name',
680
						'value'   => $search,
681
						'compare' => 'LIKE',
682
					),
683
				);
684
			}
685
686
			$this->__set( 'meta_query', $search_meta );
687
688
			$this->__unset( 's' );
689
690
		} else {
691
			$this->__set( 's', $search );
692
693
		}
694
695
	}
696
697
	/**
698
	 * Payment Mode
699
	 *
700
	 * @since  1.0
701
	 * @access public
702
	 *
703
	 * @return void
704
	 */
705
	public function mode() {
706
		if ( empty( $this->args['mode'] ) || $this->args['mode'] == 'all' ) {
707
			$this->__unset( 'mode' );
708
709
			return;
710
		}
711
712
		$this->__set(
713
			'meta_query', array(
714
				'key'   => '_give_payment_mode',
715
				'value' => $this->args['mode'],
716
			)
717
		);
718
	}
719
720
	/**
721
	 * Children
722
	 *
723
	 * @since  1.0
724
	 * @access public
725
	 *
726
	 * @return void
727
	 */
728
	public function children() {
729
		if ( empty( $this->args['children'] ) ) {
730
			$this->__set( 'post_parent', 0 );
731
		}
732
		$this->__unset( 'children' );
733
	}
734
735
	/**
736
	 * Specific Give Form
737
	 *
738
	 * @since  1.0
739
	 * @access public
740
	 *
741
	 * @return void
742
	 */
743 View Code Duplication
	public function give_forms() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
744
745
		if ( empty( $this->args['give_forms'] ) ) {
746
			return;
747
		}
748
749
		$compare = '=';
750
751
		if ( is_array( $this->args['give_forms'] ) ) {
752
			$compare = 'IN';
753
		}
754
755
		$this->__set(
756
			'meta_query',
757
			array(
758
				'key'     => '_give_payment_form_id',
759
				'value'   => $this->args['give_forms'],
760
				'compare' => $compare,
761
			)
762
		);
763
764
		$this->__unset( 'give_forms' );
765
766
	}
767
768
	/**
769
	 * Specific Gateway
770
	 *
771
	 * @since  1.8.17
772
	 * @access public
773
	 *
774
	 * @return void
775
	 */
776 View Code Duplication
	public function gateway_filter() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
777
778
		if ( empty( $this->args['gateway'] ) ) {
779
			return;
780
		}
781
782
		$compare = '=';
783
784
		if ( is_array( $this->args['gateway'] ) ) {
785
			$compare = 'IN';
786
		}
787
788
		$this->__set(
789
			'meta_query', array(
790
				array(
791
					'key'     => '_give_payment_gateway',
792
					'value'   => $this->args['gateway'],
793
					'compare' => $compare,
794
				),
795
			)
796
		);
797
798
		$this->__unset( 'gateway' );
799
800
	}
801
802
803
	/**
804
	 * Get sql query
805
	 *
806
	 * Note: Internal purpose only. We are developing on this fn.
807
	 *
808
	 * @since  1.8.18
809
	 * @access public
810
	 * @global $wpdb
811
	 *
812
	 * @return string
813
	 */
814
	private function get_sql() {
815
		global $wpdb;
816
817
		$where = "WHERE {$wpdb->posts}.post_type = 'give_payment'";
818
		$where .= " AND {$wpdb->posts}.post_status IN ('" . implode( "','", $this->args['post_status'] ) . "')";
819
820
		if ( is_numeric( $this->args['post_parent'] ) ) {
821
			$where .= " AND {$wpdb->posts}.post_parent={$this->args['post_parent']}";
822
		}
823
824
		// Set orderby.
825
		$orderby  = "ORDER BY {$wpdb->posts}.{$this->args['orderby']}";
826
		$group_by = '';
827
828
		// Set group by.
829 View Code Duplication
		if ( ! empty( $this->args['group_by'] ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
830
			$group_by = "GROUP BY {$wpdb->posts}.{$this->args['group_by']}";
831
		}
832
833
		// Set offset.
834
		if (
835
			empty( $this->args['nopaging'] ) &&
836
			empty( $this->args['offset'] ) &&
837
			( ! empty( $this->args['page'] ) && 0 < $this->args['page'] )
838
		) {
839
			$this->args['offset'] = $this->args['posts_per_page'] * ( $this->args['page'] - 1 );
840
		}
841
842
		// Set fields.
843
		$fields = "{$wpdb->posts}.*";
844
		if ( ! empty( $this->args['fields'] ) && 'all' !== $this->args['fields'] ) {
845
			if ( is_string( $this->args['fields'] ) ) {
846
				$fields = "{$wpdb->posts}.{$this->args['fields']}";
847 View Code Duplication
			} elseif ( is_array( $this->args['fields'] ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
848
				$fields = "{$wpdb->posts}." . implode( " , {$wpdb->posts}.", $this->args['fields'] );
849
			}
850
		}
851
852
		// Set count.
853
		if ( ! empty( $this->args['count'] ) ) {
854
			$fields = "COUNT({$wpdb->posts}.ID)";
855
856 View Code Duplication
			if ( ! empty( $this->args['group_by'] ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
857
				$fields = "{$wpdb->posts}.{$this->args['group_by']}, {$fields}";
858
			}
859
		}
860
861
		// Date query.
862
		if ( ! empty( $this->args['date_query'] ) ) {
863
			$date_query_obj = new WP_Date_Query( $this->args['date_query'] );
864
			$where          .= str_replace(
865
				array(
866
					"\n",
867
					'(   (',
868
					'))',
869
				),
870
				array(
871
					'',
872
					'( (',
873
					') )',
874
				),
875
				$date_query_obj->get_sql()
876
			);
877
		}
878
879
		// Meta query.
880
		if ( ! empty( $this->args['meta_query'] ) ) {
881
			$meta_query_obj = new WP_Meta_Query( $this->args['meta_query'] );
882
			$where          = implode( ' ', $meta_query_obj->get_sql( 'post', $wpdb->posts, 'ID' ) ) . " {$where}";
883
			$where          = Give()->payment_meta->__rename_meta_table_name( $where, 'posts_where' );
884
		}
885
886
		// Set sql query.
887
		$sql = $wpdb->prepare(
888
			"SELECT {$fields} FROM {$wpdb->posts} LIMIT %d,%d;",
889
			absint( $this->args['offset'] ),
890
			( empty( $this->args['nopaging'] ) ? absint( $this->args['posts_per_page'] ) : 99999999999 )
891
		);
892
893
		// $where, $orderby and order already prepared query they can generate notice if you re prepare them in above.
894
		// WordPress consider LIKE condition as placeholder if start with s,f, or d.
895
		$sql = str_replace( 'LIMIT', "{$where} {$group_by} {$orderby} {$this->args['order']} LIMIT", $sql );
896
897
		return $sql;
898
	}
899
900
	/**
901
	 * Update donations meta cache
902
	 *
903
	 * @since  2.5.0
904
	 * @access private
905
	 *
906
	 * @param $donation_ids
907
	 */
908
	public static function update_meta_cache( $donation_ids ) {
909
		// Exit.
910
		if ( empty( $donation_ids ) ) {
911
			return;
912
		}
913
914
		update_meta_cache( Give()->payment_meta->get_meta_type(), $donation_ids );
915
	}
916
}
917