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

Give_Stats   C

Complexity

Total Complexity 61

Size/Duplication

Total Lines 518
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 0

Test Coverage

Coverage 23.85%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 518
rs 6.018
ccs 62
cts 260
cp 0.2385
wmc 61
lcom 1
cbo 0

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 2 1
A get_predefined_dates() 0 16 1
A setup_dates() 0 13 3
F convert_date() 0 320 46
B count_where() 0 35 5
B payments_where() 0 36 5

How to fix   Complexity   

Complex Class

Complex classes like Give_Stats 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_Stats, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * Stats Base
4
 *
5
 * @package     Give
6
 * @subpackage  Classes/Stats
7
 * @copyright   Copyright (c) 2016, Give
8
 * @license     http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
 * @since       1.0
10
 */
11
12
13
/**
14
 * Give_Stats Class
15
 *
16
 * Base class for other stats classes
17
 *
18
 * Primarily for setting up dates and ranges
19
 *
20
 * @since 1.0
21
 */
22
class Give_Stats {
23
24
25
	/**
26
	 * The start date for the period we're getting stats for
27
	 *
28
	 * Can be a timestamp, formatted date, date string (such as August 3, 2013),
29
	 * or a predefined date string, such as last_week or this_month
30
	 *
31
	 * Predefined date options are: today, yesterday, this_week, last_week, this_month, last_month
32
	 * this_quarter, last_quarter, this_year, last_year
33
	 *
34
	 * @access public
35
	 * @since  1.0
36
	 */
37
	public $start_date;
38
39
40
	/**
41
	 * The end date for the period we're getting stats for
42
	 *
43
	 * Can be a timestamp, formatted date, date string (such as August 3, 2013),
44
	 * or a predefined date string, such as last_week or this_month
45
	 *
46
	 * Predefined date options are: today, yesterday, this_week, last_week, this_month, last_month
47
	 * this_quarter, last_quarter, this_year, last_year
48
	 *
49
	 * The end date is optional
50
	 *
51
	 * @access public
52
	 */
53
	public $end_date;
54
55
	/**
56
	 * Flag to determine if current query is based on timestamps
57
	 *
58
	 * @access public
59
	 */
60
	public $timestamp;
61
62
	/**
63
	 * @access public
64
	 * @return void
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
65
	 */
66 15
	public function __construct() { /* nothing here. Call get_sales() and get_earnings() directly */
67 15
	}
68
69
70
	/**
71
	 * Get the predefined date periods permitted
72
	 *
73
	 * @access public
74
	 * @since  1.8
75
	 * @return array
76
	 */
77 2
	public function get_predefined_dates() {
78
		$predefined = array(
79 2
			'today'        => __( 'Today', 'give' ),
80 2
			'yesterday'    => __( 'Yesterday', 'give' ),
81 2
			'this_week'    => __( 'This Week', 'give' ),
82 2
			'last_week'    => __( 'Last Week', 'give' ),
83 2
			'this_month'   => __( 'This Month', 'give' ),
84 2
			'last_month'   => __( 'Last Month', 'give' ),
85 2
			'this_quarter' => __( 'This Quarter', 'give' ),
86 2
			'last_quarter' => __( 'Last Quarter', 'give' ),
87 2
			'this_year'    => __( 'This Year', 'give' ),
88 2
			'last_year'    => __( 'Last Year', 'give' )
89 2
		);
90
91 2
		return apply_filters( 'give_stats_predefined_dates', $predefined );
92
	}
93
94
	/**
95
	 * Setup the dates passed to our constructor.
96
	 *
97
	 * This calls the convert_date() member function to ensure the dates are formatted correctly
98
	 *
99
	 * @access public
100
	 * @since  1.0
101
	 *
102
	 * @param string $_start_date
103
	 * @param bool $_end_date
104
	 *
105
	 * @return void
106
	 */
107 2
	public function setup_dates( $_start_date = 'this_month', $_end_date = false ) {
108
109 2
		if ( empty( $_start_date ) ) {
110
			$_start_date = 'this_month';
111
		}
112
113 2
		if ( empty( $_end_date ) ) {
114 2
			$_end_date = $_start_date;
115 2
		}
116
117 2
		$this->start_date = $this->convert_date( $_start_date );
118 2
		$this->end_date   = $this->convert_date( $_end_date, true );
119 2
	}
120
121
	/**
122
	 * Converts a date to a timestamp
123
	 *
124
	 * @access public
125
	 * @since  1.0
126
	 * @return array|WP_Error If the date is invalid, a WP_Error object will be returned
127
	 */
128 1
	public function convert_date( $date, $end_date = false ) {
129
130 1
		$this->timestamp = false;
131 1
		$second          = $end_date ? 59 : 0;
132 1
		$minute          = $end_date ? 59 : 0;
133 1
		$hour            = $end_date ? 23 : 0;
134 1
		$day             = 1;
135 1
		$month           = date( 'n', current_time( 'timestamp' ) );
136 1
		$year            = date( 'Y', current_time( 'timestamp' ) );
137
138 1
		if ( array_key_exists( $date, $this->get_predefined_dates() ) ) {
139
140
			// This is a predefined date rate, such as last_week
141
			switch ( $date ) {
142
143 1
				case 'this_month' :
144
145 1
					if ( $end_date ) {
146
147 1
						$day    = cal_days_in_month( CAL_GREGORIAN, $month, $year );
148 1
						$hour   = 23;
149 1
						$minute = 59;
150 1
						$second = 59;
151 1
					}
152
153 1
					break;
154
155
				case 'last_month' :
156
157
					if ( $month == 1 ) {
158
159
						$month = 12;
160
						$year --;
161
162
					} else {
163
164
						$month --;
165
166
					}
167
168
					if ( $end_date ) {
169
						$day = cal_days_in_month( CAL_GREGORIAN, $month, $year );
170
					}
171
172
					break;
173
174
				case 'today' :
175
176
					$day = date( 'd', current_time( 'timestamp' ) );
177
178
					if ( $end_date ) {
179
						$hour   = 23;
180
						$minute = 59;
181
						$second = 59;
182
					}
183
184
					break;
185
186
				case 'yesterday' :
187
188
					$day = date( 'd', current_time( 'timestamp' ) ) - 1;
189
190
					// Check if Today is the first day of the month (meaning subtracting one will get us 0)
191
					if ( $day < 1 ) {
192
193
						// If current month is 1
194
						if ( 1 == $month ) {
195
196
							$year -= 1; // Today is January 1, so skip back to last day of December
197
							$month = 12;
198
							$day   = cal_days_in_month( CAL_GREGORIAN, $month, $year );
199
200
						} else {
201
202
							// Go back one month and get the last day of the month
203
							$month -= 1;
204
							$day = cal_days_in_month( CAL_GREGORIAN, $month, $year );
205
206
						}
207
					}
208
209
					break;
210
211
				case 'this_week' :
212
213
					$days_to_week_start = ( date( 'w', current_time( 'timestamp' ) ) - 1 ) * 60 * 60 * 24;
214
					$today              = date( 'd', current_time( 'timestamp' ) ) * 60 * 60 * 24;
215
216
					if ( $today < $days_to_week_start ) {
217
218
						if ( $month > 1 ) {
219
							$month -= 1;
220
						} else {
221
							$month = 12;
222
						}
223
224
					}
225
226
					if ( ! $end_date ) {
227
228
						// Getting the start day
229
230
						$day = date( 'd', current_time( 'timestamp' ) - $days_to_week_start ) - 1;
231
						$day += get_option( 'start_of_week' );
232
233
					} else {
234
235
						// Getting the end day
236
237
						$day = date( 'd', current_time( 'timestamp' ) - $days_to_week_start ) - 1;
238
						$day += get_option( 'start_of_week' ) + 6;
239
240
					}
241
242
					break;
243
244
				case 'last_week' :
245
246
					$days_to_week_start = ( date( 'w', current_time( 'timestamp' ) ) - 1 ) * 60 * 60 * 24;
247
					$today              = date( 'd', current_time( 'timestamp' ) ) * 60 * 60 * 24;
248
249
					if ( $today < $days_to_week_start ) {
250
251
						if ( $month > 1 ) {
252
							$month -= 1;
253
						} else {
254
							$month = 12;
255
						}
256
257
					}
258
259
					if ( ! $end_date ) {
260
261
						// Getting the start day
262
263
						$day = date( 'd', current_time( 'timestamp' ) - $days_to_week_start ) - 8;
264
						$day += get_option( 'start_of_week' );
265
266
					} else {
267
268
						// Getting the end day
269
270
						$day = date( 'd', current_time( 'timestamp' ) - $days_to_week_start ) - 8;
271
						$day += get_option( 'start_of_week' ) + 6;
272
273
					}
274
275
					break;
276
277
				case 'this_quarter' :
278
279
					$month_now = date( 'n', current_time( 'timestamp' ) );
280
281
					if ( $month_now <= 3 ) {
282
283
						if ( ! $end_date ) {
284
							$month = 1;
285
						} else {
286
							$month  = 3;
287
							$day    = cal_days_in_month( CAL_GREGORIAN, $month, $year );
288
							$hour   = 23;
289
							$minute = 59;
290
							$second = 59;
291
						}
292
293
					} else if ( $month_now <= 6 ) {
294
295
						if ( ! $end_date ) {
296
							$month = 4;
297
						} else {
298
							$month  = 6;
299
							$day    = cal_days_in_month( CAL_GREGORIAN, $month, $year );
300
							$hour   = 23;
301
							$minute = 59;
302
							$second = 59;
303
						}
304
305
					} else if ( $month_now <= 9 ) {
306
307
						if ( ! $end_date ) {
308
							$month = 7;
309
						} else {
310
							$month  = 9;
311
							$day    = cal_days_in_month( CAL_GREGORIAN, $month, $year );
312
							$hour   = 23;
313
							$minute = 59;
314
							$second = 59;
315
						}
316
317
					} else {
318
319
						if ( ! $end_date ) {
320
							$month = 10;
321
						} else {
322
							$month  = 12;
323
							$day    = cal_days_in_month( CAL_GREGORIAN, $month, $year );
324
							$hour   = 23;
325
							$minute = 59;
326
							$second = 59;
327
						}
328
329
					}
330
331
					break;
332
333
				case 'last_quarter' :
334
335
					$month_now = date( 'n', current_time( 'timestamp' ) );
336
337
					if ( $month_now <= 3 ) {
338
339
						if ( ! $end_date ) {
340
							$month = 10;
341
						} else {
342
							$year -= 1;
343
							$month  = 12;
344
							$day    = cal_days_in_month( CAL_GREGORIAN, $month, $year );
345
							$hour   = 23;
346
							$minute = 59;
347
							$second = 59;
348
						}
349
350
					} else if ( $month_now <= 6 ) {
351
352
						if ( ! $end_date ) {
353
							$month = 1;
354
						} else {
355
							$month  = 3;
356
							$day    = cal_days_in_month( CAL_GREGORIAN, $month, $year );
357
							$hour   = 23;
358
							$minute = 59;
359
							$second = 59;
360
						}
361
362
					} else if ( $month_now <= 9 ) {
363
364
						if ( ! $end_date ) {
365
							$month = 4;
366
						} else {
367
							$month  = 6;
368
							$day    = cal_days_in_month( CAL_GREGORIAN, $month, $year );
369
							$hour   = 23;
370
							$minute = 59;
371
							$second = 59;
372
						}
373
374
					} else {
375
376
						if ( ! $end_date ) {
377
							$month = 7;
378
						} else {
379
							$month  = 9;
380
							$day    = cal_days_in_month( CAL_GREGORIAN, $month, $year );
381
							$hour   = 23;
382
							$minute = 59;
383
							$second = 59;
384
						}
385
386
					}
387
388
					break;
389
390
				case 'this_year' :
391
392
					if ( ! $end_date ) {
393
						$month = 1;
394
					} else {
395
						$month  = 12;
396
						$day    = cal_days_in_month( CAL_GREGORIAN, $month, $year );
397
						$hour   = 23;
398
						$minute = 59;
399
						$second = 59;
400
					}
401
402
					break;
403
404
				case 'last_year' :
405
406
					$year -= 1;
407
					if ( ! $end_date ) {
408
						$month = 1;
409
					} else {
410
						$month  = 12;
411
						$day    = cal_days_in_month( CAL_GREGORIAN, $month, $year );
412
						$hour   = 23;
413
						$minute = 59;
414
						$second = 59;
415
					}
416
417
					break;
418
419
			}
420
421
422 1
		} else if ( is_numeric( $date ) ) {
423
424
			// return $date unchanged since it is a timestamp
425
			$this->timestamp = true;
426
427
		} else if ( false !== strtotime( $date ) ) {
428
429
			$date  = strtotime( $date, current_time( 'timestamp' ) );
430
			$year  = date( 'Y', $date );
431
			$month = date( 'm', $date );
432
			$day   = date( 'd', $date );
433
434
		} else {
435
436
			return new WP_Error( 'invalid_date', __( 'Improper date provided.', 'give' ) );
437
438
		}
439
440 1
		if ( false === $this->timestamp ) {
441
			// Create an exact timestamp
442 1
			$date = mktime( $hour, $minute, $second, $month, $day, $year );
443 1
		}
444
445 1
		return apply_filters( 'give_stats_date', $date, $end_date, $this );
446
447
	}
448
449
	/**
450
	 * Modifies the WHERE flag for payment counts
451
	 *
452
	 * @access public
453
	 * @since  1.0
454
	 * @return string
455
	 */
456 1
	public function count_where( $where = '' ) {
457
		// Only get payments in our date range
458
459 1
		$start_where = '';
460 1
		$end_where   = '';
461
462 1
		if ( $this->start_date ) {
463
464 1
			if ( $this->timestamp ) {
465
				$format = 'Y-m-d H:i:s';
466
			} else {
467 1
				$format = 'Y-m-d 00:00:00';
468
			}
469
470 1
			$start_date  = date( $format, $this->start_date );
471 1
			$start_where = " AND p.post_date >= '{$start_date}'";
472 1
		}
473
474 1
		if ( $this->end_date ) {
475
476 1
			if ( $this->timestamp ) {
477
				$format = 'Y-m-d H:i:s';
478
			} else {
479 1
				$format = 'Y-m-d 23:59:59';
480
			}
481
482 1
			$end_date = date( $format, $this->end_date );
483
484 1
			$end_where = " AND p.post_date <= '{$end_date}'";
485 1
		}
486
487 1
		$where .= "{$start_where}{$end_where}";
488
489 1
		return $where;
490
	}
491
492
	/**
493
	 * Modifies the WHERE flag for payment queries
494
	 *
495
	 * @access public
496
	 * @since  1.0
497
	 *
498
	 * @param string $where
499
	 *
500
	 * @return string
501
	 */
502
	public function payments_where( $where = '' ) {
503
504
		global $wpdb;
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...
505
506
		$start_where = '';
507
		$end_where   = '';
508
509
		if ( ! is_wp_error( $this->start_date ) ) {
510
511
			if ( $this->timestamp ) {
512
				$format = 'Y-m-d H:i:s';
513
			} else {
514
				$format = 'Y-m-d 00:00:00';
515
			}
516
517
			$start_date  = date( $format, $this->start_date );
518
			$start_where = " AND $wpdb->posts.post_date >= '{$start_date}'";
519
		}
520
521
		if ( ! is_wp_error( $this->end_date ) ) {
522
523
			if ( $this->timestamp ) {
524
				$format = 'Y-m-d 00:00:00';
525
			} else {
526
				$format = 'Y-m-d 23:59:59';
527
			}
528
529
			$end_date = date( $format, $this->end_date );
530
531
			$end_where = " AND $wpdb->posts.post_date <= '{$end_date}'";
532
		}
533
534
		$where .= "{$start_where}{$end_where}";
535
536
		return $where;
537
	}
538
539
}
540