Test Failed
Pull Request — master (#2482)
by Devin
05:37
created

Give_Payments_Query::page()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2.0625

Importance

Changes 0
Metric Value
cc 2
eloc 5
nc 2
nop 0
dl 0
loc 8
ccs 3
cts 4
cp 0.75
crap 2.0625
rs 9.4285
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, WordImpress
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 52
58
	/**
59 52
	 * Default query arguments.
60 52
	 *
61 52
	 * Not all of these are valid arguments that can be passed to WP_Query. The ones that are not, are modified before the query is run to convert them to the proper syntax.
62 52
	 *
63 52
	 * @since  1.0
64 52
	 * @access public
65 52
	 *
66 52
	 * @param  $args array The array of arguments that can be passed in and used for setting up this payment query.
67 52
	 */
68 52
	public function __construct( $args = array() ) {
69 52
		$defaults = array(
70 52
			'output'          => 'payments',
71 52
			'post_type'       => array( 'give_payment' ),
72 52
			'start_date'      => false,
73 52
			'end_date'        => false,
74 52
			'number'          => 20,
75 52
			'page'            => null,
76 52
			'orderby'         => 'ID',
77
			'order'           => 'DESC',
78 52
			'user'            => null,
79
			'donor'           => null,
80 52
			'status'          => give_get_payment_status_keys(),
81
			'meta_key'        => null,
0 ignored issues
show
introduced by
Detected usage of meta_key, possible slow query.
Loading history...
82 52
			'year'            => null,
83 52
			'month'           => null,
84
			'day'             => null,
85
			's'               => null,
86
			'search_in_notes' => false,
87
			'children'        => false,
88
			'fields'          => null,
89
			'gateway'         => null,
90
			'give_forms'      => null,
91 52
		);
92 52
93 32
		$this->args = $this->_args = wp_parse_args( $args, $defaults );
94 32
95 52
		$this->init();
96
	}
97 52
98
	/**
99
	 * Set a query variable.
100
	 *
101
	 * @since  1.0
102
	 * @access public
103
	 *
104
	 * @param $query_var
105 52
	 * @param $value
106 52
	 */
107 52
	public function __set( $query_var, $value ) {
108
		if ( in_array( $query_var, array( 'meta_query', 'tax_query' ) ) ) {
109
			$this->args[ $query_var ][] = $value;
110
		} else {
111
			$this->args[ $query_var ] = $value;
112
		}
113
	}
114
115
	/**
116 52
	 * Unset a query variable.
117
	 *
118 52
	 * @since  1.0
119 52
	 * @access public
120
	 *
121 52
	 * @param $query_var
122 52
	 */
123 52
	public function __unset( $query_var ) {
124 52
		unset( $this->args[ $query_var ] );
125 52
	}
126 52
127 52
	/**
128 52
	 * Modify the query/query arguments before we retrieve payments.
129 52
	 *
130 52
	 * @since  1.0
131 52
	 * @access public
132
	 *
133
	 * @return void
134
	 */
135
	public function init() {
136
	}
137
138
139
	/**
140
	 * Set query filter.
141
	 *
142
	 * @since  1.8.9
143
	 * @access private
144 52
	 */
145
	private function set_filters() {
146 52
		// Reset param to apply filters.
147
		// While set filters $args will get override and multiple get_payments call will not work.
148 52
		$this->args = $this->_args;
149
150
		$this->date_filter_pre();
151 52
		$this->orderby();
152 52
		$this->status();
153 52
		$this->month();
154
		$this->per_page();
155 52
		$this->page();
156 52
		$this->user();
157
		$this->donor();
158
		$this->search();
159
		$this->mode();
160
		$this->children();
161
		$this->give_forms();
162
		$this->gateway_filter();
163
164
		add_filter( 'posts_orderby', array( $this, 'custom_orderby' ), 10, 2 );
165
	}
166
167
	/**
168
	 * Unset query filter.
169
	 *
170
	 * @since  1.8.9
171
	 * @access private
172
	 */
173
	private function unset_filters() {
174
		$this->date_filter_post();
175
		remove_filter( 'posts_orderby', array( $this, 'custom_orderby' ) );
176
	}
177
178
179
	/**
180
	 * Retrieve payments.
181
	 *
182
	 * The query can be modified in two ways; either the action before the
183
	 * query is run, or the filter on the arguments (existing mainly for backwards
184 52
	 * compatibility).
185 52
	 *
186 52
	 * @since  1.0
187
	 * @access public
188
	 *
189
	 * @return array
190
	 */
191
	public function get_payments() {
192
		// Modify the query/query arguments before we retrieve payments.
193
		$this->set_filters();
194
195
		/**
196
		 * Fires before retrieving payments.
197
		 *
198
		 * @since 1.0
199
		 *
200
		 * @param Give_Payments_Query $this Payments query object.
201
		 */
202
		do_action( 'give_pre_get_payments', $this );
203
204
		$query          = new WP_Query( $this->args );
205
		$this->payments = array();
206
207
		$custom_output = array(
208
			'payments',
209
			'give_payments',
210
		);
211
212
		if ( ! in_array( $this->args['output'], $custom_output ) ) {
213
			return $query->posts;
214
		}
215
216
		if ( $query->have_posts() ) {
217 52
			while ( $query->have_posts() ) {
218 52
				$query->the_post();
219 42
220
				$payment_id = get_post()->ID;
221
				$payment    = new Give_Payment( $payment_id );
222 52
223 52
				$this->payments[] = apply_filters( 'give_payment', $payment, $payment_id, $this );
224 52
			}
225
226
			wp_reset_postdata();
227
		}
228
229
		// Remove query filters after we retrieve payments.
230
		$this->unset_filters();
231
232
		/**
233 52
		 * Fires after retrieving payments.
234 52
		 *
235 52
		 * @since 1.0
236
		 *
237
		 * @param Give_Payments_Query $this Payments query object.
238 11
		 */
239 11
		do_action( 'give_post_get_payments', $this );
240 11
241
		return $this->payments;
242
	}
243
244
	/**
245
	 * If querying a specific date, add the proper filters.
246
	 *
247
	 * @since  1.0
248
	 * @access public
249 52
	 *
250
	 * @return void
251 52
	 */
252 42
	public function date_filter_pre() {
253
		if ( ! ( $this->args['start_date'] || $this->args['end_date'] ) ) {
254
			return;
255 52
		}
256 42
257 42
		$this->setup_dates( $this->args['start_date'], $this->args['end_date'] );
258 52
259
		add_filter( 'posts_where', array( $this, 'payments_where' ) );
260
	}
261 52
262 52
	/**
263
	 * If querying a specific date, remove filters after the query has been run
264
	 * to avoid affecting future queries.
265
	 *
266
	 * @since  1.0
267
	 * @access public
268
	 *
269
	 * @return void
270
	 */
271 52
	public function date_filter_post() {
272 52
		if ( ! ( $this->args['start_date'] || $this->args['end_date'] ) ) {
273 52
			return;
274
		}
275
276
		remove_filter( 'posts_where', array( $this, 'payments_where' ) );
277
	}
278
279
	/**
280
	 * Post Status
281
	 *
282
	 * @since  1.0
283
	 * @access public
284
	 *
285
	 * @return void
286
	 */
287 52
	public function status() {
288 52
		if ( ! isset( $this->args['status'] ) ) {
289 52
			return;
290
		}
291
292
		$this->__set( 'post_status', $this->args['status'] );
293 52
		$this->__unset( 'status' );
294 52
	}
295 52
296 52
	/**
297 52
	 * Current Page
298
	 *
299
	 * @since  1.0
300
	 * @access public
301
	 *
302
	 * @return void
303
	 */
304
	public function page() {
305
		if ( ! isset( $this->args['page'] ) ) {
306 52
			return;
307 52
		}
308 52
309
		$this->__set( 'paged', $this->args['page'] );
310
		$this->__unset( 'page' );
311
	}
312
313
	/**
314
	 * Posts Per Page
315
	 *
316
	 * @since  1.0
317
	 * @access public
318
	 *
319
	 * @return void
320
	 */
321
	public function per_page() {
322
323
		if ( ! isset( $this->args['number'] ) ) {
324
			return;
325
		}
326
327
		if ( $this->args['number'] == - 1 ) {
328
			$this->__set( 'nopaging', true );
329
		} else {
330 52
			$this->__set( 'posts_per_page', $this->args['number'] );
331
		}
332 52
333 52
		$this->__unset( 'number' );
334
	}
335
336 32
	/**
337
	 * Current Month
338 32
	 *
339
	 * @since  1.0
340
	 * @access public
341
	 *
342 32
	 * @return void
343 32
	 */
344
	public function month() {
345 32
		if ( ! isset( $this->args['month'] ) ) {
346
			return;
347
		}
348
349
		$this->__set( 'monthnum', $this->args['month'] );
350
		$this->__unset( 'month' );
351
	}
352
353
	/**
354
	 * Order by
355
	 *
356
	 * @since  1.0
357
	 * @access public
358 32
	 *
359
	 * @return void
360 32
	 */
361
	public function orderby() {
362 32
		switch ( $this->args['orderby'] ) {
363 32
			case 'amount':
364
				$this->__set( 'orderby', 'meta_value_num' );
365 32
				$this->__set( 'meta_key', '_give_payment_total' );
366
				break;
367 32
368 32
			case 'status':
369
				$this->__set( 'orderby', 'post_status' );
370 32
				break;
371
372
			case 'donation_form':
373
				$this->__set( 'orderby', 'meta_value' );
374
				$this->__set( 'meta_key', '_give_payment_form_title' );
375
				break;
376
377
			default:
378
				$this->__set( 'orderby', $this->args['orderby'] );
379
				break;
380
		}
381
	}
382
383
	/**
384
	 * Custom orderby.
385
	 * Note: currently custom sorting is only used for donation listing page.
386
	 *
387
	 * @since  1.8
388
	 * @access public
389
	 *
390
	 * @param string $order
391
	 * @param WP_Query $query
392
	 *
393
	 * @return mixed
394
	 */
395
	public function custom_orderby( $order, $query ) {
396
397
		if ( ! empty( $query->query['post_type'] ) ) {
398
			$post_types = is_array( $query->query['post_type'] ) ? $query->query['post_type'] : array( $query->query['post_type'] );
399
400
			if ( ! in_array( 'give_payment', $post_types ) || is_array( $query->query['orderby'] ) ) {
401
				return $order;
402
			}
403
404
			global $wpdb;
405
			switch ( $query->query['orderby'] ) {
406
				case 'post_status':
407
					$order = $wpdb->posts . '.post_status ' . strtoupper( $query->query['order'] );
408
					break;
409
			}
410
		}
411
412
		return $order;
413
	}
414
415
	/**
416
	 * Specific User
417
	 *
418
	 * @since  1.0
419
	 * @access public
420
	 *
421
	 * @return void
422
	 */
423
	public function user() {
424
		if ( is_null( $this->args['user'] ) ) {
425
			return;
426
		}
427
428
		if ( is_numeric( $this->args['user'] ) ) {
429
			$user_key = '_give_payment_user_id';
430
		} else {
431
			$user_key = '_give_payment_user_email';
432
		}
433
434
		$this->__set(
435
			'meta_query', array(
436 32
				'key'   => $user_key,
437
				'value' => $this->args['user'],
438
			)
439
		);
440
	}
441
442
	/**
443
	 * Specific donor id
444
	 *
445 52
	 * @access  public
446 52
	 * @since   1.8.9
447 52
	 * @return  void
448
	 */
449 52
	public function donor() {
450
		if ( is_null( $this->args['donor'] ) || ! is_numeric( $this->args['donor'] ) ) {
451
			return;
452
		}
453
454
		$this->__set(
455
			'meta_query', array(
456
				'key'   => '_give_payment_customer_id',
457
				'value' => (int) $this->args['donor'],
458
			)
459
		);
460
	}
461
462
	/**
463
	 * Search
464
	 *
465 52
	 * @since  1.0
466 52
	 * @access public
467 52
	 *
468 52
	 * @return void
469 52
	 */
470 52
	public function search() {
471
472
		if ( ! isset( $this->args['s'] ) ) {
473
			return;
474
		}
475
476
		$search = trim( $this->args['s'] );
477
478
		if ( empty( $search ) ) {
479 52
			return;
480
		}
481 52
482 52
		$is_email = is_email( $search ) || strpos( $search, '@' ) !== false;
483
		$is_user  = strpos( $search, strtolower( 'user:' ) ) !== false;
484
485
		if ( ! empty( $this->args['search_in_notes'] ) ) {
486
487
			$notes = give_get_payment_notes( 0, $search );
488
489
			if ( ! empty( $notes ) ) {
490
491
				$payment_ids = wp_list_pluck( (array) $notes, 'comment_post_ID' );
492
493
				$this->__set( 'post__in', $payment_ids );
494
			}
495
496
			$this->__unset( 's' );
497
498
		} elseif ( $is_email || strlen( $search ) == 32 ) {
499
500
			$key         = $is_email ? '_give_payment_user_email' : '_give_payment_purchase_key';
501
			$search_meta = array(
502
				'key'     => $key,
503
				'value'   => $search,
504
				'compare' => 'LIKE',
505
			);
506
507
			$this->__set( 'meta_query', $search_meta );
508
			$this->__unset( 's' );
509
510
		} elseif ( $is_user ) {
511
512
			$search_meta = array(
513
				'key'   => '_give_payment_user_id',
514
				'value' => trim( str_replace( 'user:', '', strtolower( $search ) ) ),
515
			);
516
517
			$this->__set( 'meta_query', $search_meta );
518
519
			if ( give_get_option( 'enable_sequential' ) ) {
520
521
				$search_meta = array(
522
					'key'     => '_give_payment_number',
523
					'value'   => $search,
524
					'compare' => 'LIKE',
525
				);
526
527
				$this->__set( 'meta_query', $search_meta );
528
529
				$this->args['meta_query']['relation'] = 'OR';
530
531
			}
532
533
			$this->__unset( 's' );
534
535
		} elseif (
536
			give_get_option( 'enable_sequential' ) &&
537
			(
538
				false !== strpos( $search, give_get_option( 'sequential_prefix' ) ) ||
539
				false !== strpos( $search, give_get_option( 'sequential_postfix' ) )
540
			)
541
		) {
542
543
			$search_meta = array(
544
				'key'     => '_give_payment_number',
545
				'value'   => $search,
546
				'compare' => 'LIKE',
547
			);
548
549
			$this->__set( 'meta_query', $search_meta );
550
			$this->__unset( 's' );
551
552
		} elseif ( is_numeric( $search ) ) {
553
554
			$post = get_post( $search );
555
556
			if ( is_object( $post ) && $post->post_type == 'give_payment' ) {
0 ignored issues
show
introduced by
Found "== '". Use Yoda Condition checks, you must
Loading history...
557
558
				$arr   = array();
559
				$arr[] = $search;
560
				$this->__set( 'post__in', $arr );
561
				$this->__unset( 's' );
562
			}
563
		} elseif ( '#' == substr( $search, 0, 1 ) ) {
564
565
			$search = str_replace( '#:', '', $search );
566
			$search = str_replace( '#', '', $search );
567
			$this->__set( 'give_forms', $search );
568
			$this->__unset( 's' );
569
570
		} else {
571
			$this->__set( 's', $search );
572
573
		}
574
575
	}
576
577
	/**
578
	 * Payment Mode
579
	 *
580
	 * @since  1.0
581
	 * @access public
582
	 *
583
	 * @return void
584
	 */
585
	public function mode() {
586
		if ( empty( $this->args['mode'] ) || $this->args['mode'] == 'all' ) {
0 ignored issues
show
introduced by
Found "== '". Use Yoda Condition checks, you must
Loading history...
587
			$this->__unset( 'mode' );
588
589
			return;
590
		}
591
592
		$this->__set(
593
			'meta_query', array(
594
				'key'   => '_give_payment_mode',
595
				'value' => $this->args['mode'],
596
			)
597
		);
598
	}
599
600
	/**
601
	 * Children
602
	 *
603
	 * @since  1.0
604
	 * @access public
605
	 *
606
	 * @return void
607
	 */
608
	public function children() {
609
		if ( empty( $this->args['children'] ) ) {
610
			$this->__set( 'post_parent', 0 );
611
		}
612
		$this->__unset( 'children' );
613
	}
614
615
	/**
616
	 * Specific Give Form
617
	 *
618
	 * @since  1.0
619
	 * @access public
620
	 *
621
	 * @return void
622
	 */
623 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...
624
625
		if ( empty( $this->args['give_forms'] ) ) {
626
			return;
627
		}
628
629
		$compare = '=';
630
631
		if ( is_array( $this->args['give_forms'] ) ) {
632
			$compare = 'IN';
633
		}
634
635
		$this->__set(
636
			'meta_query', array(
637
				array(
638
					'key'     => '_give_payment_form_id',
639
					'value'   => $this->args['give_forms'],
640
					'compare' => $compare,
641
				),
642
			)
643
		);
644
645
		$this->__unset( 'give_forms' );
646
647
	}
648
649
	/**
650
	 * Specific Gateway
651
	 *
652
	 * @since  1.8.17
653
	 * @access public
654
	 *
655
	 * @return void
656
	 */
657 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...
658
659
		if ( empty( $this->args['gateway'] ) ) {
660
			return;
661
		}
662
663
		$compare = '=';
664
665
		if ( is_array( $this->args['gateway'] ) ) {
666
			$compare = 'IN';
667
		}
668
669
		$this->__set(
670
			'meta_query', array(
671
				array(
672
					'key'     => '_give_payment_gateway',
673
					'value'   => $this->args['gateway'],
674
					'compare' => $compare,
675
				),
676
			)
677
		);
678
679
		$this->__unset( 'gateway' );
680
681
	}
682
683
}
684