Completed
Push — master ( 647547...13dcfc )
by Devin
17:56
created

Give_Payments_Query   C

Complexity

Total Complexity 57

Size/Duplication

Total Lines 501
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 52.81%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 501
ccs 122
cts 231
cp 0.5281
rs 6.433
wmc 57
lcom 1
cbo 2

17 Methods

Rating   Name   Duplication   Size   Complexity  
B __construct() 0 27 1
A __set() 0 7 2
A __unset() 0 3 1
A init() 0 16 1
A date_filter_pre() 0 9 3
A date_filter_post() 0 7 3
A status() 0 8 2
A page() 0 8 2
A per_page() 0 14 3
A month() 0 8 2
A orderby() 0 11 2
A user() 0 16 3
A mode() 0 12 3
A children() 0 6 2
B give_forms() 0 47 5
B get_payments() 0 32 4
D search() 0 107 18

How to fix   Complexity   

Complex Class

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
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 26 and the first side effect is on line 14.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
/**
3
 * Payments Query
4
 *
5
 * @package     Give
6
 * @subpackage  Classes/Stats
7
 * @copyright   Copyright (c) 2016, WordImpress
8
 * @license     http://opensource.org/licenses/gpl-2.0.php 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
	 * The args to pass to the give_get_payments() query
30
	 *
31
	 * @var array
32
	 * @access public
33
	 * @since  1.0
34
	 */
35
	public $args = array();
36
37
	/**
38
	 * The payments found based on the criteria set
39
	 *
40
	 * @var array
41
	 * @access public
42
	 * @since  1.0
43
	 */
44
	public $payments = array();
45
46
	/**
47
	 * Default query arguments.
48
	 *
49
	 * Not all of these are valid arguments that can be passed to WP_Query. The ones that are not, are modified before
50
	 * the query is run to convert them to the proper syntax.
51
	 *
52
	 * @access public
53
	 * @since  1.0
54
	 *
55
	 * @param $args array The array of arguments that can be passed in and used for setting up this payment query.
56
	 */
57 52
	public function __construct( $args = array() ) {
58
		$defaults = array(
59 52
			'output'          => 'payments', // Use 'posts' to get standard post objects
60 52
			'post_type'       => array( 'give_payment' ),
61 52
			'start_date'      => false,
62 52
			'end_date'        => false,
63 52
			'number'          => 20,
64 52
			'page'            => null,
65 52
			'orderby'         => 'ID',
66 52
			'order'           => 'DESC',
67 52
			'user'            => null,
68 52
			'status'          => give_get_payment_status_keys(),
69 52
			'meta_key'        => null,
70 52
			'year'            => null,
71 52
			'month'           => null,
72 52
			'day'             => null,
73 52
			's'               => null,
74 52
			'search_in_notes' => false,
75 52
			'children'        => false,
76 52
			'fields'          => null,
77
			'give_forms'      => null
78 52
		);
79
80 52
		$this->args = wp_parse_args( $args, $defaults );
81
82 52
		$this->init();
83 52
	}
84
85
	/**
86
	 * Set a query variable.
87
	 *
88
	 * @access public
89
	 * @since  1.0
90
	 */
91 52
	public function __set( $query_var, $value ) {
92 52
		if ( in_array( $query_var, array( 'meta_query', 'tax_query' ) ) ) {
93 32
			$this->args[ $query_var ][] = $value;
94 32
		} else {
95 52
			$this->args[ $query_var ] = $value;
96
		}
97 52
	}
98
99
	/**
100
	 * Unset a query variable.
101
	 *
102
	 * @access public
103
	 * @since  1.0
104
	 */
105 52
	public function __unset( $query_var ) {
106 52
		unset( $this->args[ $query_var ] );
107 52
	}
108
109
	/**
110
	 * Modify the query/query arguments before we retrieve payments.
111
	 *
112
	 * @access public
113
	 * @since  1.0
114
	 * @return void
115
	 */
116 52
	public function init() {
117
118 52
		add_action( 'give_pre_get_payments', array( $this, 'date_filter_pre' ) );
119 52
		add_action( 'give_post_get_payments', array( $this, 'date_filter_post' ) );
120
121 52
		add_action( 'give_pre_get_payments', array( $this, 'orderby' ) );
122 52
		add_action( 'give_pre_get_payments', array( $this, 'status' ) );
123 52
		add_action( 'give_pre_get_payments', array( $this, 'month' ) );
124 52
		add_action( 'give_pre_get_payments', array( $this, 'per_page' ) );
125 52
		add_action( 'give_pre_get_payments', array( $this, 'page' ) );
126 52
		add_action( 'give_pre_get_payments', array( $this, 'user' ) );
127 52
		add_action( 'give_pre_get_payments', array( $this, 'search' ) );
128 52
		add_action( 'give_pre_get_payments', array( $this, 'mode' ) );
129 52
		add_action( 'give_pre_get_payments', array( $this, 'children' ) );
130 52
		add_action( 'give_pre_get_payments', array( $this, 'give_forms' ) );
131 52
	}
132
133
	/**
134
	 * Retrieve payments.
135
	 *
136
	 * The query can be modified in two ways; either the action before the
137
	 * query is run, or the filter on the arguments (existing mainly for backwards
138
	 * compatibility).
139
	 *
140
	 * @access public
141
	 * @since  1.0
142
	 * @return object
143
	 */
144 52
	public function get_payments() {
145
146 52
		do_action( 'give_pre_get_payments', $this );
147
148 52
		$query = new WP_Query( $this->args );
149
150
		$custom_output = array(
151 52
			'payments',
152 52
			'give_payments',
153 52
		);
154
155 52
		if ( ! in_array( $this->args['output'], $custom_output ) ) {
156 52
			return $query->posts;
157
		}
158
159
		if ( $query->have_posts() ) {
160
			while ( $query->have_posts() ) {
161
				$query->the_post();
162
163
				$payment_id = get_post()->ID;
164
				$payment    = new Give_Payment( $payment_id );
165
166
				$this->payments[] = apply_filters( 'give_payment', $payment, $payment_id, $this );
167
			}
168
169
			wp_reset_postdata();
170
		}
171
172
		do_action( 'give_post_get_payments', $this );
173
174
		return $this->payments;
175
	}
176
177
	/**
178
	 * If querying a specific date, add the proper filters.
179
	 *
180
	 * @access public
181
	 * @since  1.0
182
	 * @return void
183
	 */
184 52
	public function date_filter_pre() {
185 52
		if ( ! ( $this->args['start_date'] || $this->args['end_date'] ) ) {
186 52
			return;
187
		}
188
189
		$this->setup_dates( $this->args['start_date'], $this->args['end_date'] );
190
191
		add_filter( 'posts_where', array( $this, 'payments_where' ) );
192
	}
193
194
	/**
195
	 * If querying a specific date, remove filters after the query has been run
196
	 * to avoid affecting future queries.
197
	 *
198
	 * @access public
199
	 * @since  1.0
200
	 * @return void
201
	 */
202
	public function date_filter_post() {
203
		if ( ! ( $this->args['start_date'] || $this->args['end_date'] ) ) {
204
			return;
205
		}
206
207
		remove_filter( 'posts_where', array( $this, 'payments_where' ) );
208
	}
209
210
	/**
211
	 * Post Status
212
	 *
213
	 * @access public
214
	 * @since  1.0
215
	 * @return void
216
	 */
217 52
	public function status() {
218 52
		if ( ! isset ( $this->args['status'] ) ) {
219 42
			return;
220
		}
221
222 52
		$this->__set( 'post_status', $this->args['status'] );
223 52
		$this->__unset( 'status' );
224 52
	}
225
226
	/**
227
	 * Current Page
228
	 *
229
	 * @access public
230
	 * @since  1.0
231
	 * @return void
232
	 */
233 52
	public function page() {
234 52
		if ( ! isset ( $this->args['page'] ) ) {
235 52
			return;
236
		}
237
238 11
		$this->__set( 'paged', $this->args['page'] );
239 11
		$this->__unset( 'page' );
240 11
	}
241
242
	/**
243
	 * Posts Per Page
244
	 *
245
	 * @access public
246
	 * @since  1.0
247
	 * @return void
248
	 */
249 52
	public function per_page() {
250
251 52
		if ( ! isset( $this->args['number'] ) ) {
252 42
			return;
253
		}
254
255 52
		if ( $this->args['number'] == - 1 ) {
256 42
			$this->__set( 'nopaging', true );
257 42
		} else {
258 52
			$this->__set( 'posts_per_page', $this->args['number'] );
259
		}
260
261 52
		$this->__unset( 'number' );
262 52
	}
263
264
	/**
265
	 * Current Month
266
	 *
267
	 * @access public
268
	 * @since  1.0
269
	 * @return void
270
	 */
271 52
	public function month() {
272 52
		if ( ! isset ( $this->args['month'] ) ) {
273 52
			return;
274
		}
275
276
		$this->__set( 'monthnum', $this->args['month'] );
277
		$this->__unset( 'month' );
278
	}
279
280
	/**
281
	 * Order by
282
	 *
283
	 * @access public
284
	 * @since  1.0
285
	 * @return void
286
	 */
287 52
	public function orderby() {
288 52
		switch ( $this->args['orderby'] ) {
289 52
			case 'amount' :
290
				$this->__set( 'orderby', 'meta_value_num' );
291
				$this->__set( 'meta_key', '_give_payment_total' );
292
				break;
293 52
			default :
294 52
				$this->__set( 'orderby', $this->args['orderby'] );
295 52
				break;
296 52
		}
297 52
	}
298
299
	/**
300
	 * Specific User
301
	 *
302
	 * @access public
303
	 * @since  1.0
304
	 * @return void
305
	 */
306 52
	public function user() {
307 52
		if ( is_null( $this->args['user'] ) ) {
308 52
			return;
309
		}
310
311
		if ( is_numeric( $this->args['user'] ) ) {
312
			$user_key = '_give_payment_user_id';
313
		} else {
314
			$user_key = '_give_payment_user_email';
315
		}
316
317
		$this->__set( 'meta_query', array(
318
			'key'   => $user_key,
319
			'value' => $this->args['user']
320
		) );
321
	}
322
323
	/**
324
	 * Search
325
	 *
326
	 * @access public
327
	 * @since  1.0
328
	 * @return void
329
	 */
330 52
	public function search() {
331
332 52
		if ( ! isset( $this->args['s'] ) ) {
333 52
			return;
334
		}
335
336 32
		$search = trim( $this->args['s'] );
337
338 32
		if ( empty( $search ) ) {
339
			return;
340
		}
341
342 32
		$is_email = is_email( $search ) || strpos( $search, '@' ) !== false;
343 32
		$is_user  = strpos( $search, strtolower( 'user:' ) ) !== false;
344
345 32
		if ( ! empty( $this->args['search_in_notes'] ) ) {
346
347
			$notes = give_get_payment_notes( 0, $search );
348
349
			if ( ! empty( $notes ) ) {
350
351
				$payment_ids = wp_list_pluck( (array) $notes, 'comment_post_ID' );
352
353
				$this->__set( 'post__in', $payment_ids );
354
			}
355
356
			$this->__unset( 's' );
357
358 32
		} elseif ( $is_email || strlen( $search ) == 32 ) {
359
360 32
			$key         = $is_email ? '_give_payment_user_email' : '_give_payment_purchase_key';
361
			$search_meta = array(
362 32
				'key'     => $key,
363 32
				'value'   => $search,
364
				'compare' => 'LIKE'
365 32
			);
366
367 32
			$this->__set( 'meta_query', $search_meta );
368 32
			$this->__unset( 's' );
369
370 32
		} elseif ( $is_user ) {
371
372
			$search_meta = array(
373
				'key'   => '_give_payment_user_id',
374
				'value' => trim( str_replace( 'user:', '', strtolower( $search ) ) )
375
			);
376
377
			$this->__set( 'meta_query', $search_meta );
378
379
			if ( give_get_option( 'enable_sequential' ) ) {
380
381
				$search_meta = array(
382
					'key'     => '_give_payment_number',
383
					'value'   => $search,
384
					'compare' => 'LIKE'
385
				);
386
387
				$this->__set( 'meta_query', $search_meta );
388
389
				$this->args['meta_query']['relation'] = 'OR';
390
391
			}
392
393
			$this->__unset( 's' );
394
395
		} elseif (
396
			give_get_option( 'enable_sequential' ) &&
397
			(
398
				false !== strpos( $search, give_get_option( 'sequential_prefix' ) ) ||
399
				false !== strpos( $search, give_get_option( 'sequential_postfix' ) )
400
			)
401
		) {
402
403
			$search_meta = array(
404
				'key'     => '_give_payment_number',
405
				'value'   => $search,
406
				'compare' => 'LIKE'
407
			);
408
409
			$this->__set( 'meta_query', $search_meta );
410
			$this->__unset( 's' );
411
412
		} elseif ( is_numeric( $search ) ) {
413
414
			$post = get_post( $search );
415
416
			if ( is_object( $post ) && $post->post_type == 'give_payment' ) {
417
418
				$arr   = array();
419
				$arr[] = $search;
420
				$this->__set( 'post__in', $arr );
421
				$this->__unset( 's' );
422
			}
423
424
		} elseif ( '#' == substr( $search, 0, 1 ) ) {
425
426
			$search = str_replace( '#:', '', $search );
427
			$search = str_replace( '#', '', $search );
428
			$this->__set( 'give_forms', $search );
429
			$this->__unset( 's' );
430
431
		} else {
432
			$this->__set( 's', $search );
433
434
		}
435
436 32
	}
437
438
	/**
439
	 * Payment Mode
440
	 *
441
	 * @access public
442
	 * @since  1.0
443
	 * @return void
444
	 */
445 52
	public function mode() {
446 52
		if ( empty( $this->args['mode'] ) || $this->args['mode'] == 'all' ) {
447 52
			$this->__unset( 'mode' );
448
449 52
			return;
450
		}
451
452
		$this->__set( 'meta_query', array(
453
			'key'   => '_give_payment_mode',
454
			'value' => $this->args['mode']
455
		) );
456
	}
457
458
	/**
459
	 * Children
460
	 *
461
	 * @access public
462
	 * @since  1.0
463
	 * @return void
464
	 */
465 52
	public function children() {
466 52
		if ( empty( $this->args['children'] ) ) {
467 52
			$this->__set( 'post_parent', 0 );
468 52
		}
469 52
		$this->__unset( 'children' );
470 52
	}
471
472
	/**
473
	 * Specific Give Form
474
	 *
475
	 * @access public
476
	 * @since  1.0
477
	 * @return void
478
	 */
479 52
	public function give_forms() {
480
481 52
		if ( empty( $this->args['give_forms'] ) ) {
482 52
			return;
483
		}
484
485
		global $give_logs;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
486
487
		$args = array(
488
			'post_parent'            => $this->args['give_forms'],
489
			'log_type'               => 'sale',
490
			'post_status'            => array( 'publish' ),
491
			'nopaging'               => true,
492
			'no_found_rows'          => true,
493
			'update_post_term_cache' => false,
494
			'update_post_meta_cache' => false,
495
			'cache_results'          => false,
496
			'fields'                 => 'ids'
497
		);
498
499
		if ( is_array( $this->args['give_forms'] ) ) {
500
			unset( $args['post_parent'] );
501
			$args['post_parent__in'] = $this->args['give_forms'];
502
		}
503
504
		$sales = $give_logs->get_connected_logs( $args );
505
506
		if ( ! empty( $sales ) ) {
507
508
			$payments = array();
509
510
			foreach ( $sales as $sale ) {
511
				$payments[] = get_post_meta( $sale, '_give_log_payment_id', true );
512
			}
513
514
			$this->__set( 'post__in', $payments );
515
516
		} else {
517
518
			// Set post_parent to something crazy so it doesn't find anything
519
			$this->__set( 'post_parent', 999999999999999 );
520
521
		}
522
523
		$this->__unset( 'give_forms' );
524
525
	}
526
}
527