Issues (4296)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

includes/payments/class-payments-query.php (22 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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