Test Failed
Push — issues/2397 ( d6aef6...240f10 )
by Ravinder
03:57
created

Give_Payments_Query::search()   D

Complexity

Conditions 18
Paths 24

Size

Total Lines 106
Code Lines 59

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 18
eloc 59
nc 24
nop 0
dl 0
loc 106
rs 4.7996
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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