Test Failed
Push — issues/2531 ( 7bbe65...07c620 )
by Ravinder
04:34
created

Give_Payments_Query   D

Complexity

Total Complexity 99

Size/Duplication

Total Lines 830
Duplicated Lines 7.11 %

Coupling/Cohesion

Components 1
Dependencies 5

Importance

Changes 0
Metric Value
dl 59
loc 830
rs 4.2105
c 0
b 0
f 0
wmc 99
lcom 1
cbo 5

23 Methods

Rating   Name   Duplication   Size   Complexity  
B __construct() 0 34 1
A __set() 0 7 2
A __unset() 0 3 1
A init() 0 2 1
B set_filters() 0 30 1
A unset_filters() 0 12 1
B get_payments() 0 45 5
C get_payment_by_group() 0 51 8
D date_filter_pre() 0 25 9
A status() 0 8 2
A page() 0 8 2
A per_page() 0 14 3
A month() 0 8 2
A orderby() 0 21 4
B custom_orderby() 0 19 6
A user() 0 18 3
A donor() 0 12 3
D search() 0 106 18
A mode() 0 14 3
A children() 0 6 2
B give_forms() 25 25 3
B gateway_filter() 25 25 3
F get_sql() 9 84 16

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Give_Payments_Query often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Give_Payments_Query, and based on these observations, apply Extract Interface, too.

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
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,
80
			'donor'           => null,
81
			'status'          => give_get_payment_status_keys(),
82
			'meta_key'        => null,
0 ignored issues
show
introduced by
Detected usage of meta_key, possible slow query.
Loading history...
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
		$this->args = $this->_args = wp_parse_args( $args, $defaults );
100
101
		$this->init();
102
	}
103
104
	/**
105
	 * Set a query variable.
106
	 *
107
	 * @since  1.0
108
	 * @access public
109
	 *
110
	 * @param $query_var
111
	 * @param $value
112
	 */
113
	public function __set( $query_var, $value ) {
114
		if ( in_array( $query_var, array( 'meta_query', 'tax_query' ) ) ) {
115
			$this->args[ $query_var ][] = $value;
116
		} else {
117
			$this->args[ $query_var ] = $value;
118
		}
119
	}
120
121
	/**
122
	 * Unset a query variable.
123
	 *
124
	 * @since  1.0
125
	 * @access public
126
	 *
127
	 * @param $query_var
128
	 */
129
	public function __unset( $query_var ) {
130
		unset( $this->args[ $query_var ] );
131
	}
132
133
	/**
134
	 * Modify the query/query arguments before we retrieve payments.
135
	 *
136
	 * @since  1.0
137
	 * @access public
138
	 *
139
	 * @return void
140
	 */
141
	public function init() {
142
	}
143
144
145
	/**
146
	 * Set query filter.
147
	 *
148
	 * @since  1.8.9
149
	 * @access private
150
	 */
151
	private function set_filters() {
152
		// Reset param to apply filters.
153
		// While set filters $args will get override and multiple get_payments call will not work.
154
		$this->args = $this->_args;
155
156
		$this->date_filter_pre();
157
		$this->orderby();
158
		$this->status();
159
		$this->month();
160
		$this->per_page();
161
		$this->page();
162
		$this->user();
163
		$this->donor();
164
		$this->search();
165
		$this->mode();
166
		$this->children();
167
		$this->give_forms();
168
		$this->gateway_filter();
169
170
		add_filter( 'posts_orderby', array( $this, 'custom_orderby' ), 10, 2 );
171
172
		/**
173
		 * Fires after setup filters.
174
		 *
175
		 * @since 1.0
176
		 *
177
		 * @param Give_Payments_Query $this Payments query object.
178
		 */
179
		do_action( 'give_pre_get_payments', $this );
180
	}
181
182
	/**
183
	 * Unset query filter.
184
	 *
185
	 * @since  1.8.9
186
	 * @access private
187
	 */
188
	private function unset_filters() {
189
		remove_filter( 'posts_orderby', array( $this, 'custom_orderby' ) );
190
191
		/**
192
		 * Fires after retrieving payments.
193
		 *
194
		 * @since 1.0
195
		 *
196
		 * @param Give_Payments_Query $this Payments query object.
197
		 */
198
		do_action( 'give_post_get_payments', $this );
199
	}
200
201
202
	/**
203
	 * Retrieve payments.
204
	 *
205
	 * The query can be modified in two ways; either the action before the
206
	 * query is run, or the filter on the arguments (existing mainly for backwards
207
	 * compatibility).
208
	 *
209
	 * @since  1.0
210
	 * @access public
211
	 *
212
	 * @return array
213
	 */
214
	public function get_payments() {
215
		$cache_key      = Give_Cache::get_key( 'give_payment_query', $this->args, false );
216
		$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...
217
218
		// Return cached result.
219
		if ( ! is_null( $this->payments ) ) {
220
			return $this->payments;
221
		}
222
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
223
224
		// Modify the query/query arguments before we retrieve payments.
225
		$this->set_filters();
226
227
		$query          = new WP_Query( $this->args );
228
		$this->payments = array();
229
230
		$custom_output = array(
231
			'payments',
232
			'give_payments',
233
		);
234
235
		if ( ! in_array( $this->args['output'], $custom_output ) ) {
236
			return $query->posts;
237
		}
238
239
		if ( $query->have_posts() ) {
240
			while ( $query->have_posts() ) {
241
				$query->the_post();
242
243
				$payment_id = get_post()->ID;
244
				$payment    = new Give_Payment( $payment_id );
245
246
				$this->payments[] = apply_filters( 'give_payment', $payment, $payment_id, $this );
247
			}
248
249
			wp_reset_postdata();
250
		}
251
252
		Give_Cache::set_db_query( $cache_key, $this->payments );
253
254
		// Remove query filters after we retrieve payments.
255
		$this->unset_filters();
256
257
		return $this->payments;
258
	}
259
	
260
	/**
261
	 * Get payments by group
262
	 *
263
	 * @since  1.8.17
264
	 * @access public
265
	 *
266
	 * @return array
267
	 */
268
	public function get_payment_by_group() {
269
		global $wpdb;
270
271
		$allowed_groups = array( 'post_status' );
272
		$result         = array();
273
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
274
275
		if ( in_array( $this->args['group_by'], $allowed_groups ) ) {
276
			// Set only count in result.
277
			if ( $this->args['count'] ) {
278
279
				$this->set_filters();
280
281
				$new_results = $wpdb->get_results( $this->get_sql(), ARRAY_N );
0 ignored issues
show
introduced by
Usage of a direct database call is discouraged.
Loading history...
introduced by
Usage of a direct database call without caching is prohibited. Use wp_cache_get / wp_cache_set.
Loading history...
282
283
				$this->unset_filters();
284
285
				foreach ( $new_results as $results ) {
286
					$result[ $results[0] ] = $results[1];
287
				}
288
289
				switch ( $this->args['group_by'] ) {
290
					case 'post_status':
291
292
						/* @var Give_Payment $donation */
293
						foreach ( give_get_payment_status_keys() as $status ) {
294
							if ( ! isset( $result[ $status ] ) ) {
295
								$result[ $status ] = 0;
296
							}
297
						}
298
299
						break;
300
				}
301
			} else {
302
				$donations = $this->get_payments();
303
304
				/* @var $donation Give_Payment */
305
				foreach ( $donations as $donation ) {
306
					$result[ $donation->{$this->args['group_by']} ][] = $donation;
307
				}
308
			}
309
		}
310
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
311
312
		/**
313
		 * Filter the result
314
		 *
315
		 * @since 1.8.17
316
		 */
317
		return apply_filters( 'give_get_payment_by_group', $result, $this );
318
	}
319
320
	/**
321
	 * If querying a specific date, add the proper filters.
322
	 *
323
	 * @since  1.0
324
	 * @access public
325
	 *
326
	 * @return void
327
	 */
328
	public function date_filter_pre() {
329
		if ( ! ( $this->args['start_date'] || $this->args['end_date'] ) ) {
330
			return;
331
		}
332
333
		$this->setup_dates( $this->args['start_date'], $this->args['end_date'] );
334
		$is_start_date = property_exists( __CLASS__, 'start_date' );
335
		$is_end_date   = property_exists( __CLASS__, 'end_date' );
336
337
		if ( $is_start_date || $is_end_date ) {
338
			$date_query = array();
339
340
			if ( $is_start_date && ! is_wp_error( $this->start_date ) ) {
341
				$date_query['after'] = date( 'Y-m-d H:i:s', $this->start_date );
342
			}
343
344
			if ( $is_end_date && ! is_wp_error( $this->end_date ) ) {
345
				$date_query['before'] = date( 'Y-m-d H:i:s', $this->end_date );
346
			}
347
348
			$this->__set( 'date_query', $date_query );
349
350
		}
351
352
	}
353
354
	/**
355
	 * Post Status
356
	 *
357
	 * @since  1.0
358
	 * @access public
359
	 *
360
	 * @return void
361
	 */
362
	public function status() {
363
		if ( ! isset( $this->args['status'] ) ) {
364
			return;
365
		}
366
367
		$this->__set( 'post_status', $this->args['status'] );
368
		$this->__unset( 'status' );
369
	}
370
371
	/**
372
	 * Current Page
373
	 *
374
	 * @since  1.0
375
	 * @access public
376
	 *
377
	 * @return void
378
	 */
379
	public function page() {
380
		if ( ! isset( $this->args['page'] ) ) {
381
			return;
382
		}
383
384
		$this->__set( 'paged', $this->args['page'] );
385
		$this->__unset( 'page' );
386
	}
387
388
	/**
389
	 * Posts Per Page
390
	 *
391
	 * @since  1.0
392
	 * @access public
393
	 *
394
	 * @return void
395
	 */
396
	public function per_page() {
397
398
		if ( ! isset( $this->args['number'] ) ) {
399
			return;
400
		}
401
402
		if ( $this->args['number'] == - 1 ) {
403
			$this->__set( 'nopaging', true );
404
		} else {
405
			$this->__set( 'posts_per_page', $this->args['number'] );
406
		}
407
408
		$this->__unset( 'number' );
409
	}
410
411
	/**
412
	 * Current Month
413
	 *
414
	 * @since  1.0
415
	 * @access public
416
	 *
417
	 * @return void
418
	 */
419
	public function month() {
420
		if ( ! isset( $this->args['month'] ) ) {
421
			return;
422
		}
423
424
		$this->__set( 'monthnum', $this->args['month'] );
425
		$this->__unset( 'month' );
426
	}
427
428
	/**
429
	 * Order by
430
	 *
431
	 * @since  1.0
432
	 * @access public
433
	 *
434
	 * @return void
435
	 */
436
	public function orderby() {
437
		switch ( $this->args['orderby'] ) {
438
			case 'amount':
439
				$this->__set( 'orderby', 'meta_value_num' );
440
				$this->__set( 'meta_key', '_give_payment_total' );
441
				break;
442
443
			case 'status':
444
				$this->__set( 'orderby', 'post_status' );
445
				break;
446
447
			case 'donation_form':
448
				$this->__set( 'orderby', 'meta_value' );
449
				$this->__set( 'meta_key', '_give_payment_form_title' );
450
				break;
451
452
			default:
453
				$this->__set( 'orderby', $this->args['orderby'] );
454
				break;
455
		}
456
	}
457
458
	/**
459
	 * Custom orderby.
460
	 * Note: currently custom sorting is only used for donation listing page.
461
	 *
462
	 * @since  1.8
463
	 * @access public
464
	 *
465
	 * @param string   $order
466
	 * @param WP_Query $query
467
	 *
468
	 * @return mixed
469
	 */
470
	public function custom_orderby( $order, $query ) {
471
472
		if ( ! empty( $query->query['post_type'] ) ) {
473
			$post_types = is_array( $query->query['post_type'] ) ? $query->query['post_type'] : array( $query->query['post_type'] );
474
475
			if ( ! in_array( 'give_payment', $post_types ) || is_array( $query->query['orderby'] ) ) {
476
				return $order;
477
			}
478
479
			global $wpdb;
480
			switch ( $query->query['orderby'] ) {
481
				case 'post_status':
482
					$order = $wpdb->posts . '.post_status ' . strtoupper( $query->query['order'] );
483
					break;
484
			}
485
		}
486
487
		return $order;
488
	}
489
490
	/**
491
	 * Specific User
492
	 *
493
	 * @since  1.0
494
	 * @access public
495
	 *
496
	 * @return void
497
	 */
498
	public function user() {
499
		if ( is_null( $this->args['user'] ) ) {
500
			return;
501
		}
502
503
		if ( is_numeric( $this->args['user'] ) ) {
504
			$user_key = '_give_payment_donor_id';
505
		} else {
506
			$user_key = '_give_payment_donor_email';
507
		}
508
509
		$this->__set(
510
			'meta_query', array(
511
				'key'   => $user_key,
512
				'value' => $this->args['user'],
513
			)
514
		);
515
	}
516
517
	/**
518
	 * Specific donor id
519
	 *
520
	 * @access  public
521
	 * @since   1.8.9
522
	 * @return  void
523
	 */
524
	public function donor() {
525
		if ( is_null( $this->args['donor'] ) || ! is_numeric( $this->args['donor'] ) ) {
526
			return;
527
		}
528
529
		$donor_meta_type = Give()->donor_meta->meta_type;
530
531
		$this->__set( 'meta_query', array(
532
			'key'   => "_give_payment_{$donor_meta_type}_id",
533
			'value' => (int) $this->args['donor'],
534
		) );
535
	}
536
537
	/**
538
	 * Search
539
	 *
540
	 * @since  1.0
541
	 * @access public
542
	 *
543
	 * @return void
544
	 */
545
	public function search() {
546
547
		if ( ! isset( $this->args['s'] ) ) {
548
			return;
549
		}
550
551
		$search = trim( $this->args['s'] );
552
553
		if ( empty( $search ) ) {
554
			return;
555
		}
556
557
		$is_email = is_email( $search ) || strpos( $search, '@' ) !== false;
558
		$is_user  = strpos( $search, strtolower( 'user:' ) ) !== false;
559
560
		if ( ! empty( $this->args['search_in_notes'] ) ) {
561
562
			$notes = give_get_payment_notes( 0, $search );
563
564
			if ( ! empty( $notes ) ) {
565
566
				$payment_ids = wp_list_pluck( (array) $notes, 'comment_post_ID' );
567
568
				$this->__set( 'post__in', $payment_ids );
569
			}
570
571
			$this->__unset( 's' );
572
573
		} elseif ( $is_email || strlen( $search ) == 32 ) {
574
575
			$key         = $is_email ? '_give_payment_donor_email' : '_give_payment_purchase_key';
576
			$search_meta = array(
577
				'key'     => $key,
578
				'value'   => $search,
579
				'compare' => 'LIKE',
580
			);
581
582
			$this->__set( 'meta_query', $search_meta );
583
			$this->__unset( 's' );
584
585
		} elseif ( $is_user ) {
586
587
			$search_meta = array(
588
				'key'   => '_give_payment_donor_id',
589
				'value' => trim( str_replace( 'user:', '', strtolower( $search ) ) ),
590
			);
591
592
			$this->__set( 'meta_query', $search_meta );
593
594
			if ( give_get_option( 'enable_sequential' ) ) {
595
596
				$search_meta = array(
597
					'key'     => '_give_payment_number',
598
					'value'   => $search,
599
					'compare' => 'LIKE',
600
				);
601
602
				$this->__set( 'meta_query', $search_meta );
603
604
				$this->args['meta_query']['relation'] = 'OR';
605
606
			}
607
608
			$this->__unset( 's' );
609
610
		} elseif (
611
			give_get_option( 'enable_sequential' ) &&
612
			(
613
				false !== strpos( $search, give_get_option( 'sequential_prefix' ) ) ||
614
				false !== strpos( $search, give_get_option( 'sequential_postfix' ) )
615
			)
616
		) {
617
618
			$search_meta = array(
619
				'key'     => '_give_payment_number',
620
				'value'   => $search,
621
				'compare' => 'LIKE',
622
			);
623
624
			$this->__set( 'meta_query', $search_meta );
625
			$this->__unset( 's' );
626
627
		} elseif ( is_numeric( $search ) ) {
628
629
			$post = get_post( $search );
630
631
			if ( is_object( $post ) && $post->post_type == 'give_payment' ) {
0 ignored issues
show
introduced by
Found "== '". Use Yoda Condition checks, you must
Loading history...
632
633
				$arr   = array();
634
				$arr[] = $search;
635
				$this->__set( 'post__in', $arr );
636
				$this->__unset( 's' );
637
			}
638
		} elseif ( '#' == substr( $search, 0, 1 ) ) {
639
640
			$search = str_replace( '#:', '', $search );
641
			$search = str_replace( '#', '', $search );
642
			$this->__set( 'give_forms', $search );
643
			$this->__unset( 's' );
644
645
		} else {
646
			$this->__set( 's', $search );
647
648
		}
649
650
	}
651
652
	/**
653
	 * Payment Mode
654
	 *
655
	 * @since  1.0
656
	 * @access public
657
	 *
658
	 * @return void
659
	 */
660
	public function mode() {
661
		if ( empty( $this->args['mode'] ) || $this->args['mode'] == 'all' ) {
0 ignored issues
show
introduced by
Found "== '". Use Yoda Condition checks, you must
Loading history...
662
			$this->__unset( 'mode' );
663
664
			return;
665
		}
666
667
		$this->__set(
668
			'meta_query', array(
669
				'key'   => '_give_payment_mode',
670
				'value' => $this->args['mode'],
671
			)
672
		);
673
	}
674
675
	/**
676
	 * Children
677
	 *
678
	 * @since  1.0
679
	 * @access public
680
	 *
681
	 * @return void
682
	 */
683
	public function children() {
684
		if ( empty( $this->args['children'] ) ) {
685
			$this->__set( 'post_parent', 0 );
686
		}
687
		$this->__unset( 'children' );
688
	}
689
690
	/**
691
	 * Specific Give Form
692
	 *
693
	 * @since  1.0
694
	 * @access public
695
	 *
696
	 * @return void
697
	 */
698 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...
699
700
		if ( empty( $this->args['give_forms'] ) ) {
701
			return;
702
		}
703
704
		$compare = '=';
705
706
		if ( is_array( $this->args['give_forms'] ) ) {
707
			$compare = 'IN';
708
		}
709
710
		$this->__set(
711
			'meta_query', array(
712
				array(
713
					'key'     => '_give_payment_form_id',
714
					'value'   => $this->args['give_forms'],
715
					'compare' => $compare,
716
				),
717
			)
718
		);
719
720
		$this->__unset( 'give_forms' );
721
722
	}
723
724
	/**
725
	 * Specific Gateway
726
	 *
727
	 * @since  1.8.17
728
	 * @access public
729
	 *
730
	 * @return void
731
	 */
732 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...
733
734
		if ( empty( $this->args['gateway'] ) ) {
735
			return;
736
		}
737
738
		$compare = '=';
739
740
		if ( is_array( $this->args['gateway'] ) ) {
741
			$compare = 'IN';
742
		}
743
744
		$this->__set(
745
			'meta_query', array(
746
				array(
747
					'key'     => '_give_payment_gateway',
748
					'value'   => $this->args['gateway'],
749
					'compare' => $compare,
750
				),
751
			)
752
		);
753
754
		$this->__unset( 'gateway' );
755
756
	}
757
758
759
	/**
760
	 * Get sql query
761
	 *
762
	 * Note: Internal purpose only. We are developing on this fn.
763
	 *
764
	 * @since  1.8.18
765
	 * @access public
766
	 * @global $wpdb
767
	 *
768
	 * @return string
769
	 */
770
	private function get_sql() {
771
		global $wpdb;
772
773
		$where = "WHERE {$wpdb->posts}.post_type = 'give_payment'";
774
		$where .= " AND {$wpdb->posts}.post_status IN ('" . implode( "','", $this->args['post_status'] ) . "')";
775
776
		if( is_numeric( $this->args['post_parent'] ) ) {
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...
777
			$where .= " AND {$wpdb->posts}.post_parent={$this->args['post_parent']}";
778
		}
779
780
		// Set orderby.
781
		$orderby  = "ORDER BY {$wpdb->posts}.{$this->args['orderby']}";
782
		$group_by = '';
783
784
		// Set group by.
785 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...
786
			$group_by = "GROUP BY {$wpdb->posts}.{$this->args['group_by']}";
787
		}
788
789
		// Set offset.
790
		if (
791
			empty( $this->args['nopaging'] ) &&
792
			empty( $this->args['offset'] ) &&
793
			( ! empty( $this->args['page'] ) && 0 < $this->args['page'] )
794
		) {
795
			$this->args['offset'] = $this->args['posts_per_page'] * ( $this->args['page'] - 1 );
796
		}
797
798
		// Set fields.
799
		$fields = "{$wpdb->posts}.*";
800
		if ( ! empty( $this->args['fields'] ) && 'all' !== $this->args['fields'] ) {
801
			if ( is_string( $this->args['fields'] ) ) {
802
				$fields = "{$wpdb->posts}.{$this->args['fields']}";
803 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...
804
				$fields = "{$wpdb->posts}." . implode( " , {$wpdb->posts}.", $this->args['fields'] );
805
			}
806
		}
807
808
		// Set count.
809
		if ( ! empty( $this->args['count'] ) ) {
810
			$fields = "COUNT({$wpdb->posts}.ID)";
811
812 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...
813
				$fields = "{$wpdb->posts}.{$this->args['group_by']}, {$fields}";
814
			}
815
		}
816
817
		// Date query.
818
		if ( ! empty( $this->args['date_query'] ) ) {
819
			$date_query_obj = new WP_Date_Query( $this->args['date_query'] );
820
			$where          .= str_replace(
821
				array(
822
					"\n",
823
					'(   (',
824
					'))',
825
				),
826
				array(
827
					'',
828
					'( (',
829
					') )',
830
				),
831
				$date_query_obj->get_sql()
832
			);
833
		}
834
835
		// Meta query.
836
		if ( ! empty( $this->args['meta_query'] ) ) {
837
			$meta_query_obj = new WP_Meta_Query( $this->args['meta_query'] );
838
			$where          = implode( ' ', $meta_query_obj->get_sql( 'post', $wpdb->posts, 'ID' ) ) . " {$where}";
839
		}
840
841
		// Set sql query.
842
		$sql = $wpdb->prepare(
843
			"SELECT {$fields} FROM {$wpdb->posts} LIMIT %d,%d;",
844
			absint( $this->args['offset'] ),
845
			( empty( $this->args['nopaging'] ) ? absint( $this->args['posts_per_page'] ) : 999999999999999 )
846
		);
847
848
		// $where, $orderby and order already prepared query they can generate notice if you re prepare them in above.
849
		// WordPress consider LIKE condition as placeholder if start with s,f, or d.
850
		$sql = str_replace( 'LIMIT', "{$where} {$group_by} {$orderby} {$this->args['order']} LIMIT", $sql );
851
852
		return $sql;
853
	}
854
855
}
856