Test Failed
Push — issues/2397 ( 9e50a0...769ef8 )
by Ravinder
04:13
created

Give_Payments_Query::init()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 2
rs 10
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
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 the query is run to convert them to the proper syntax.
62
	 *
63
	 * @since  1.0
64
	 * @access public
65
	 *
66
	 * @param  $args array The array of arguments that can be passed in and used for setting up this payment query.
67
	 */
68
	public function __construct( $args = array() ) {
69
		$defaults = array(
70
			'output'          => 'payments',
71
			'post_type'       => array( 'give_payment' ),
72
			'start_date'      => false,
73
			'end_date'        => false,
74
			'number'          => 20,
75
			'page'            => null,
76
			'orderby'         => 'ID',
77
			'order'           => 'DESC',
78
			'user'            => null,
79
			'donor'           => null,
80
			'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
			'year'            => null,
83
			'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
		);
92
93
		$this->args = $this->_args = wp_parse_args( $args, $defaults );
94
95
		$this->init();
96
	}
97
98
	/**
99
	 * Set a query variable.
100
	 *
101
	 * @since  1.0
102
	 * @access public
103
	 *
104
	 * @param $query_var
105
	 * @param $value
106
	 */
107
	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
	 * Unset a query variable.
117
	 *
118
	 * @since  1.0
119
	 * @access public
120
	 *
121
	 * @param $query_var
122
	 */
123
	public function __unset( $query_var ) {
124
		unset( $this->args[ $query_var ] );
125
	}
126
127
	/**
128
	 * Modify the query/query arguments before we retrieve payments.
129
	 *
130
	 * @since  1.0
131
	 * @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
	 */
145
	private function set_filters() {
146
		// Reset param to apply filters.
147
		// While set filters $args will get override and multiple get_payments call will not work.
148
		$this->args = $this->_args;
149
150
		$this->date_filter_pre();
151
		$this->orderby();
152
		$this->status();
153
		$this->month();
154
		$this->per_page();
155
		$this->page();
156
		$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
	 * compatibility).
185
	 *
186
	 * @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
			while ( $query->have_posts() ) {
218
				$query->the_post();
219
220
				$payment_id = get_post()->ID;
221
				$payment    = new Give_Payment( $payment_id );
222
223
				$this->payments[] = apply_filters( 'give_payment', $payment, $payment_id, $this );
224
			}
225
226
			wp_reset_postdata();
227
		}
228
229
		// Remove query filters after we retrieve payments.
230
		$this->unset_filters();
231
232
		/**
233
		 * Fires after retrieving payments.
234
		 *
235
		 * @since 1.0
236
		 *
237
		 * @param Give_Payments_Query $this Payments query object.
238
		 */
239
		do_action( 'give_post_get_payments', $this );
240
241
		return $this->payments;
242
	}
243
244
245
	/**
246
	 * Get payments by group
247
	 *
248
	 * @since  2.0
249
	 * @access public
250
	 *
251
	 * @param string $group_by Valid donation property
252
	 * @param bool   $count
253
	 *
254
	 * @return array
255
	 */
256
	public function get_payment_by_group( $group_by, $count = false ) {
257
		$donations      = $this->get_payments();
258
		$allowed_groups = array( 'post_status' );
259
		$result         = array();
260
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
261
262
		if ( in_array( $group_by, $allowed_groups ) ) {
263
			/* @var $donation Give_Payment */
264
			foreach ( $donations as $donation ) {
265
				$result[ $donation->{$group_by} ][] = $donation;
266
			}
267
268
			// Set only count in result.
269
			if ( $count ) {
270
				$new_result = array();
271
272
				foreach ( $result as $index => $items ) {
273
					$new_result[ $index ] = count( $items );
274
				}
275
276
				$result = $new_result;
277
278
				switch ( $group_by ) {
279
					case 'post_status':
280
						$statuses = get_post_stati();
281
282
						if ( isset( $statuses['private'] ) && empty( $args['s'] ) ) {
283
							unset( $statuses['private'] );
284
						}
285
286
						/* @var Give_Payment $donation */
287
						foreach ( $statuses as $status => $status_label ) {
288
							if ( ! isset( $result[ $status ] ) ) {
289
								$result[ $status ] = 0;
290
							}
291
						}
292
293
						break;
294
				}
295
			}
296
		}
297
		
298
		/**
299
		 * Filter the result
300
		 *
301
		 * @since 1.8.17
302
		 */
303
		return apply_filters( 'give_get_payment_by_group', $result, $donations, $this );
304
	}
305
306
	/**
307
	 * If querying a specific date, add the proper filters.
308
	 *
309
	 * @since  1.0
310
	 * @access public
311
	 *
312
	 * @return void
313
	 */
314
	public function date_filter_pre() {
315
		if ( ! ( $this->args['start_date'] || $this->args['end_date'] ) ) {
316
			return;
317
		}
318
319
		$this->setup_dates( $this->args['start_date'], $this->args['end_date'] );
320
321
		add_filter( 'posts_where', array( $this, 'payments_where' ) );
322
	}
323
324
	/**
325
	 * If querying a specific date, remove filters after the query has been run
326
	 * to avoid affecting future queries.
327
	 *
328
	 * @since  1.0
329
	 * @access public
330
	 *
331
	 * @return void
332
	 */
333
	public function date_filter_post() {
334
		if ( ! ( $this->args['start_date'] || $this->args['end_date'] ) ) {
335
			return;
336
		}
337
338
		remove_filter( 'posts_where', array( $this, 'payments_where' ) );
339
	}
340
341
	/**
342
	 * Post Status
343
	 *
344
	 * @since  1.0
345
	 * @access public
346
	 *
347
	 * @return void
348
	 */
349
	public function status() {
350
		if ( ! isset( $this->args['status'] ) ) {
351
			return;
352
		}
353
354
		$this->__set( 'post_status', $this->args['status'] );
355
		$this->__unset( 'status' );
356
	}
357
358
	/**
359
	 * Current Page
360
	 *
361
	 * @since  1.0
362
	 * @access public
363
	 *
364
	 * @return void
365
	 */
366
	public function page() {
367
		if ( ! isset( $this->args['page'] ) ) {
368
			return;
369
		}
370
371
		$this->__set( 'paged', $this->args['page'] );
372
		$this->__unset( 'page' );
373
	}
374
375
	/**
376
	 * Posts Per Page
377
	 *
378
	 * @since  1.0
379
	 * @access public
380
	 *
381
	 * @return void
382
	 */
383
	public function per_page() {
384
385
		if ( ! isset( $this->args['number'] ) ) {
386
			return;
387
		}
388
389
		if ( $this->args['number'] == - 1 ) {
390
			$this->__set( 'nopaging', true );
391
		} else {
392
			$this->__set( 'posts_per_page', $this->args['number'] );
393
		}
394
395
		$this->__unset( 'number' );
396
	}
397
398
	/**
399
	 * Current Month
400
	 *
401
	 * @since  1.0
402
	 * @access public
403
	 *
404
	 * @return void
405
	 */
406
	public function month() {
407
		if ( ! isset( $this->args['month'] ) ) {
408
			return;
409
		}
410
411
		$this->__set( 'monthnum', $this->args['month'] );
412
		$this->__unset( 'month' );
413
	}
414
415
	/**
416
	 * Order by
417
	 *
418
	 * @since  1.0
419
	 * @access public
420
	 *
421
	 * @return void
422
	 */
423
	public function orderby() {
424
		switch ( $this->args['orderby'] ) {
425
			case 'amount':
426
				$this->__set( 'orderby', 'meta_value_num' );
427
				$this->__set( 'meta_key', '_give_payment_total' );
428
				break;
429
430
			case 'status':
431
				$this->__set( 'orderby', 'post_status' );
432
				break;
433
434
			case 'donation_form':
435
				$this->__set( 'orderby', 'meta_value' );
436
				$this->__set( 'meta_key', '_give_payment_form_title' );
437
				break;
438
439
			default:
440
				$this->__set( 'orderby', $this->args['orderby'] );
441
				break;
442
		}
443
	}
444
445
	/**
446
	 * Custom orderby.
447
	 * Note: currently custom sorting is only used for donation listing page.
448
	 *
449
	 * @since  1.8
450
	 * @access public
451
	 *
452
	 * @param string   $order
453
	 * @param WP_Query $query
454
	 *
455
	 * @return mixed
456
	 */
457
	public function custom_orderby( $order, $query ) {
458
		global $wpdb;
459
460
		$post_types = is_array( $query->query['post_type'] ) ? $query->query['post_type'] : array( $query->query['post_type'] );
461
		if ( ! in_array( 'give_payment', $post_types ) || is_array( $query->query['orderby'] ) ) {
462
			return $order;
463
		}
464
465
		switch ( $query->query['orderby'] ) {
466
			case 'post_status':
467
				$order = $wpdb->posts . '.post_status ' . strtoupper( $query->query['order'] );
468
				break;
469
		}
470
471
		return $order;
472
	}
473
474
	/**
475
	 * Specific User
476
	 *
477
	 * @since  1.0
478
	 * @access public
479
	 *
480
	 * @return void
481
	 */
482
	public function user() {
483
		if ( is_null( $this->args['user'] ) ) {
484
			return;
485
		}
486
487
		if ( is_numeric( $this->args['user'] ) ) {
488
			$user_key = '_give_payment_user_id';
489
		} else {
490
			$user_key = '_give_payment_user_email';
491
		}
492
493
		$this->__set(
494
			'meta_query', array(
495
				'key'   => $user_key,
496
				'value' => $this->args['user'],
497
			)
498
		);
499
	}
500
501
	/**
502
	 * Specific donor id
503
	 *
504
	 * @access  public
505
	 * @since   1.8.9
506
	 * @return  void
507
	 */
508
	public function donor() {
509
		if ( is_null( $this->args['donor'] ) || ! is_numeric( $this->args['donor'] ) ) {
510
			return;
511
		}
512
513
		$this->__set(
514
			'meta_query', array(
515
				'key'   => '_give_payment_customer_id',
516
				'value' => (int) $this->args['donor'],
517
			)
518
		);
519
	}
520
521
	/**
522
	 * Search
523
	 *
524
	 * @since  1.0
525
	 * @access public
526
	 *
527
	 * @return void
528
	 */
529
	public function search() {
530
531
		if ( ! isset( $this->args['s'] ) ) {
532
			return;
533
		}
534
535
		$search = trim( $this->args['s'] );
536
537
		if ( empty( $search ) ) {
538
			return;
539
		}
540
541
		$is_email = is_email( $search ) || strpos( $search, '@' ) !== false;
542
		$is_user  = strpos( $search, strtolower( 'user:' ) ) !== false;
543
544
		if ( ! empty( $this->args['search_in_notes'] ) ) {
545
546
			$notes = give_get_payment_notes( 0, $search );
547
548
			if ( ! empty( $notes ) ) {
549
550
				$payment_ids = wp_list_pluck( (array) $notes, 'comment_post_ID' );
551
552
				$this->__set( 'post__in', $payment_ids );
553
			}
554
555
			$this->__unset( 's' );
556
557
		} elseif ( $is_email || strlen( $search ) == 32 ) {
558
559
			$key         = $is_email ? '_give_payment_user_email' : '_give_payment_purchase_key';
560
			$search_meta = array(
561
				'key'     => $key,
562
				'value'   => $search,
563
				'compare' => 'LIKE',
564
			);
565
566
			$this->__set( 'meta_query', $search_meta );
567
			$this->__unset( 's' );
568
569
		} elseif ( $is_user ) {
570
571
			$search_meta = array(
572
				'key'   => '_give_payment_user_id',
573
				'value' => trim( str_replace( 'user:', '', strtolower( $search ) ) ),
574
			);
575
576
			$this->__set( 'meta_query', $search_meta );
577
578
			if ( give_get_option( 'enable_sequential' ) ) {
579
580
				$search_meta = array(
581
					'key'     => '_give_payment_number',
582
					'value'   => $search,
583
					'compare' => 'LIKE',
584
				);
585
586
				$this->__set( 'meta_query', $search_meta );
587
588
				$this->args['meta_query']['relation'] = 'OR';
589
590
			}
591
592
			$this->__unset( 's' );
593
594
		} elseif (
595
			give_get_option( 'enable_sequential' ) &&
596
			(
597
				false !== strpos( $search, give_get_option( 'sequential_prefix' ) ) ||
598
				false !== strpos( $search, give_get_option( 'sequential_postfix' ) )
599
			)
600
		) {
601
602
			$search_meta = array(
603
				'key'     => '_give_payment_number',
604
				'value'   => $search,
605
				'compare' => 'LIKE',
606
			);
607
608
			$this->__set( 'meta_query', $search_meta );
609
			$this->__unset( 's' );
610
611
		} elseif ( is_numeric( $search ) ) {
612
613
			$post = get_post( $search );
614
615
			if ( is_object( $post ) && $post->post_type == 'give_payment' ) {
0 ignored issues
show
introduced by
Found "== '". Use Yoda Condition checks, you must
Loading history...
616
617
				$arr   = array();
618
				$arr[] = $search;
619
				$this->__set( 'post__in', $arr );
620
				$this->__unset( 's' );
621
			}
622
		} elseif ( '#' == substr( $search, 0, 1 ) ) {
623
624
			$search = str_replace( '#:', '', $search );
625
			$search = str_replace( '#', '', $search );
626
			$this->__set( 'give_forms', $search );
627
			$this->__unset( 's' );
628
629
		} else {
630
			$this->__set( 's', $search );
631
632
		}
633
634
	}
635
636
	/**
637
	 * Payment Mode
638
	 *
639
	 * @since  1.0
640
	 * @access public
641
	 *
642
	 * @return void
643
	 */
644
	public function mode() {
645
		if ( empty( $this->args['mode'] ) || $this->args['mode'] == 'all' ) {
0 ignored issues
show
introduced by
Found "== '". Use Yoda Condition checks, you must
Loading history...
646
			$this->__unset( 'mode' );
647
648
			return;
649
		}
650
651
		$this->__set(
652
			'meta_query', array(
653
				'key'   => '_give_payment_mode',
654
				'value' => $this->args['mode'],
655
			)
656
		);
657
	}
658
659
	/**
660
	 * Children
661
	 *
662
	 * @since  1.0
663
	 * @access public
664
	 *
665
	 * @return void
666
	 */
667
	public function children() {
668
		if ( empty( $this->args['children'] ) ) {
669
			$this->__set( 'post_parent', 0 );
670
		}
671
		$this->__unset( 'children' );
672
	}
673
674
	/**
675
	 * Specific Give Form
676
	 *
677
	 * @since  1.0
678
	 * @access public
679
	 *
680
	 * @return void
681
	 */
682 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...
683
684
		if ( empty( $this->args['give_forms'] ) ) {
685
			return;
686
		}
687
688
		$compare = '=';
689
690
		if ( is_array( $this->args['give_forms'] ) ) {
691
			$compare = 'IN';
692
		}
693
694
		$this->__set(
695
			'meta_query', array(
696
				array(
697
					'key'     => '_give_payment_form_id',
698
					'value'   => $this->args['give_forms'],
699
					'compare' => $compare,
700
				),
701
			)
702
		);
703
704
		$this->__unset( 'give_forms' );
705
706
	}
707
708
	/**
709
	 * Specific Gateway
710
	 *
711
	 * @since  1.8.17
712
	 * @access public
713
	 *
714
	 * @return void
715
	 */
716 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...
717
718
		if ( empty( $this->args['gateway'] ) ) {
719
			return;
720
		}
721
722
		$compare = '=';
723
724
		if ( is_array( $this->args['gateway'] ) ) {
725
			$compare = 'IN';
726
		}
727
728
		$this->__set(
729
			'meta_query', array(
730
				array(
731
					'key'     => '_give_payment_gateway',
732
					'value'   => $this->args['gateway'],
733
					'compare' => $compare,
734
				),
735
			)
736
		);
737
738
		$this->__unset( 'gateway' );
739
740
	}
741
742
}
743