Passed
Push — master ( aaa057...742219 )
by Brian
04:58
created

get_collection_params()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 28
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 23
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 28
rs 9.552
1
<?php
2
/**
3
 * Helper for the date based controllers.
4
 *
5
 * @package GetPaid
6
 * @subpackage REST API
7
 * @since   2.0.0
8
 */
9
10
defined( 'ABSPATH' ) || exit;
11
12
/**
13
 * GetPaid REST date based controller class.
14
 *
15
 * @package Invoicing
16
 */
17
class GetPaid_REST_Date_Based_Controller extends GetPaid_REST_Controller {
18
19
	/**
20
	 * Group response items by day or month.
21
	 *
22
	 * @var string
23
	 */
24
	public $groupby = 'day';
25
26
	/**
27
	 * Returns an array with arguments to request the previous report.
28
	 *
29
	 * @var array
30
	 */
31
	public $previous_range = array();
32
33
	/**
34
	 * The period interval.
35
	 *
36
	 * @var int
37
	 */
38
	public $interval;
39
40
	/**
41
	 * Retrieves the before and after dates.
42
	 *
43
	 * @param WP_REST_Request $request Request object.
44
	 * @return array The appropriate date range.
45
	 */
46
	public function get_date_range( $request ) {
47
48
		// If not supported, assume all time.
49
		if ( ! in_array( $request['period'], array( 'custom', 'today', 'yesterday', 'week', 'last_week', '7_days', '30_days', '60_days', '90_days', '180_days', 'month', 'last_month', 'quarter', 'last_quarter', 'year', 'last_year' ) ) ) {
50
			$request['period'] = '7_days';
51
		}
52
53
		$date_range = call_user_func( array( $this, 'get_' . $request['period'] . '_date_range' ), $request );
54
		$this->prepare_interval( $date_range );
55
56
		return $date_range;
57
58
	}
59
60
	/**
61
	 * Groups by month or days.
62
	 *
63
	 * @param array $range Date range.
64
	 * @return array The appropriate date range.
65
	 */
66
	public function prepare_interval( $range ) {
67
68
		$before = strtotime( $range['before'] ) - DAY_IN_SECONDS;
69
		$after  = strtotime( $range['after'] ) + DAY_IN_SECONDS;
70
		if ( 'day' === $this->groupby ) {
71
			$difference     = max( DAY_IN_SECONDS, ( DAY_IN_SECONDS + $before - $after ) ); // Prevent division by 0;
72
			$this->interval = absint( ceil( max( 1, $difference / DAY_IN_SECONDS ) ) );
73
			return;
74
		}
75
76
		$this->interval = 0;
77
		$min_date       = strtotime( date( 'Y-m-01', $after ) );
78
79
		while ( $min_date <= $before ) {
80
			$this->interval ++;
81
			$min_date = strtotime( '+1 MONTH', $min_date );
82
		}
83
84
		$this->interval = max( 1, $this->interval );
85
86
	}
87
88
	/**
89
	 * Retrieves a custom date range.
90
	 *
91
	 * @param WP_REST_Request $request Request object.
92
	 * @return array The appropriate date range.
93
	 */
94
	public function get_custom_date_range( $request ) {
95
96
		$after  = max( strtotime( '-20 years' ), strtotime( sanitize_text_field( $request['after'] ) ) );
97
		$before = strtotime( '+1 day', current_time( 'timestamp' ) );
98
99
		if ( ! empty( $request['before'] ) ) {
100
			$before  = min( $before, strtotime( sanitize_text_field( $request['before'] ) ) );
101
		}
102
103
		// 3 months max for day view
104
		if ( floor( ( $before - $after ) / MONTH_IN_SECONDS ) > 3 ) {
105
			$this->groupby = 'month';
106
		}
107
108
		// Set the previous date range.
109
		$difference           = $before - $after;
110
		$this->previous_range = array(
111
			'period' => 'custom',
112
			'before' => date( 'Y-m-d', $before - $difference ),
113
			'after'  => date( 'Y-m-d', $after - $difference ),
114
		);
115
116
		// Generate the report.
117
		return array(
118
			'before' => date( 'Y-m-d', $before ),
119
			'after' => date( 'Y-m-d', $after ),
120
		);
121
122
	}
123
124
	/**
125
	 * Retrieves todays date range.
126
	 *
127
	 * @return array The appropriate date range.
128
	 */
129
	public function get_today_date_range() {
130
131
		// Set the previous date range.
132
		$this->previous_range = array(
133
			'period' => 'yesterday',
134
		);
135
136
		// Generate the report.
137
		return array(
138
			'before' => date( 'Y-m-d', strtotime( '+1 day', current_time( 'timestamp' ) ) ),
139
			'after'  => date( 'Y-m-d', strtotime( '-1 day', current_time( 'timestamp' ) ) ),
140
		);
141
142
	}
143
144
	/**
145
	 * Retrieves yesterdays date range.
146
	 *
147
	 * @return array The appropriate date range.
148
	 */
149
	public function get_yesterday_date_range() {
150
151
		// Set the previous date range.
152
		$this->previous_range = array(
153
			'period' => 'custom',
154
			'before' => date( 'Y-m-d', strtotime( '-1 day', current_time( 'timestamp' ) ) ),
155
			'after'  => date( 'Y-m-d', strtotime( '-3 days', current_time( 'timestamp' ) ) ),
156
		);
157
158
		// Generate the report.
159
		return array(
160
			'before' => date( 'Y-m-d', current_time( 'timestamp' ) ),
161
			'after'  => date( 'Y-m-d', strtotime( '-2 days', current_time( 'timestamp' ) ) ),
162
		);
163
164
	}
165
166
	/**
167
	 * Retrieves this week's date range.
168
	 *
169
	 * @return array The appropriate date range.
170
	 */
171
	public function get_week_date_range() {
172
173
		// Set the previous date range.
174
		$this->previous_range = array(
175
			'period' => 'last_week',
176
		);
177
178
		// Generate the report.
179
		return array(
180
			'before' => date( 'Y-m-d', strtotime( 'sunday last week', current_time( 'timestamp' )  ) + 8 * DAY_IN_SECONDS ),
181
			'after'  => date( 'Y-m-d', strtotime( 'sunday last week', current_time( 'timestamp' )  ) ),
182
		);
183
184
	}
185
186
	/**
187
	 * Retrieves last week's date range.
188
	 *
189
	 * @return array The appropriate date range.
190
	 */
191
	public function get_last_week_date_range() {
192
193
		// Set the previous date range.
194
		$this->previous_range = array(
195
			'period' => 'custom',
196
			'before' => date( 'Y-m-d', strtotime( 'monday last week', current_time( 'timestamp' )  ) ),
197
			'after'  => date( 'Y-m-d', strtotime( 'monday last week', current_time( 'timestamp' )  ) - 8 * DAY_IN_SECONDS ),
198
		);
199
200
		// Generate the report.
201
		return array(
202
			'before' => date( 'Y-m-d', strtotime( 'monday this week', current_time( 'timestamp' )  ) ),
203
			'after'  => date( 'Y-m-d', strtotime( 'monday last week', current_time( 'timestamp' )  ) - DAY_IN_SECONDS ),
204
		);
205
206
	}
207
208
	/**
209
	 * Retrieves last 7 days date range.
210
	 *
211
	 * @return array The appropriate date range.
212
	 */
213
	public function get_7_days_date_range() {
214
215
		// Set the previous date range.
216
		$this->previous_range = array(
217
			'period' => 'custom',
218
			'before' => date( 'Y-m-d', strtotime( '-7 days', current_time( 'timestamp' ) ) ),
219
			'after'  => date( 'Y-m-d', strtotime( '-15 days', current_time( 'timestamp' ) ) ),
220
		);
221
222
		// Generate the report.
223
		return array(
224
			'before' => date( 'Y-m-d', current_time( 'timestamp' ) ),
225
			'after'  => date( 'Y-m-d', strtotime( '-8 days', current_time( 'timestamp' ) ) ),
226
		);
227
228
	}
229
230
	/**
231
	 * Retrieves last 30 days date range.
232
	 *
233
	 * @return array The appropriate date range.
234
	 */
235
	public function get_30_days_date_range() {
236
237
		// Set the previous date range.
238
		$this->previous_range = array(
239
			'period' => 'custom',
240
			'before' => date( 'Y-m-d', strtotime( '-30 days', current_time( 'timestamp' ) ) ),
241
			'after'  => date( 'Y-m-d', strtotime( '-61 days', current_time( 'timestamp' ) ) ),
242
		);
243
244
		// Generate the report.
245
		return array(
246
			'before' => date( 'Y-m-d', current_time( 'timestamp' ) ),
247
			'after'  => date( 'Y-m-d', strtotime( '-31 days', current_time( 'timestamp' ) ) ),
248
		);
249
250
	}
251
252
	/**
253
	 * Retrieves last 90 days date range.
254
	 *
255
	 * @return array The appropriate date range.
256
	 */
257
	public function get_90_days_date_range() {
258
259
		$this->groupby = 'month';
260
261
		// Set the previous date range.
262
		$this->previous_range = array(
263
			'period' => 'custom',
264
			'before' => date( 'Y-m-d', strtotime( '-90 days', current_time( 'timestamp' ) ) ),
265
			'after'  => date( 'Y-m-d', strtotime( '-181 days', current_time( 'timestamp' ) ) ),
266
		);
267
268
		// Generate the report.
269
		return array(
270
			'before' => date( 'Y-m-d', current_time( 'timestamp' ) ),
271
			'after'  => date( 'Y-m-d', strtotime( '-91 days', current_time( 'timestamp' ) ) ),
272
		);
273
274
	}
275
276
	/**
277
	 * Retrieves last 180 days date range.
278
	 *
279
	 * @return array The appropriate date range.
280
	 */
281
	public function get_180_days_date_range() {
282
283
		$this->groupby = 'month';
284
285
		// Set the previous date range.
286
		$this->previous_range = array(
287
			'period' => 'custom',
288
			'before' => date( 'Y-m-d', strtotime( '-180 days', current_time( 'timestamp' ) ) ),
289
			'after'  => date( 'Y-m-d', strtotime( '-361 days', current_time( 'timestamp' ) ) ),
290
		);
291
292
		// Generate the report.
293
		return array(
294
			'before' => date( 'Y-m-d', current_time( 'timestamp' ) ),
295
			'after'  => date( 'Y-m-d', strtotime( '-181 days', current_time( 'timestamp' ) ) ),
296
		);
297
298
	}
299
300
	/**
301
	 * Retrieves last 60 days date range.
302
	 *
303
	 * @return array The appropriate date range.
304
	 */
305
	public function get_60_days_date_range() {
306
307
		// Set the previous date range.
308
		$this->previous_range = array(
309
			'period' => 'custom',
310
			'before' => date( 'Y-m-d', strtotime( '-60 days', current_time( 'timestamp' ) ) ),
311
			'after'  => date( 'Y-m-d', strtotime( '-121 days', current_time( 'timestamp' ) ) ),
312
		);
313
314
		// Generate the report.
315
		return array(
316
			'before' => date( 'Y-m-d', current_time( 'timestamp' ) ),
317
			'after'  => date( 'Y-m-d', strtotime( '-61 days', current_time( 'timestamp' ) ) ),
318
		);
319
320
	}
321
322
	/**
323
	 * Retrieves this month date range.
324
	 *
325
	 * @return array The appropriate date range.
326
	 */
327
	public function get_month_date_range() {
328
329
		// Set the previous date range.
330
		$this->previous_range = array(
331
			'period' => 'last_month',
332
		);
333
334
		// Generate the report.
335
		return array(
336
			'before' => date( 'Y-m-01', strtotime( 'next month', current_time( 'timestamp' ) ) ),
337
			'after'  => date( 'Y-m-t', strtotime( 'last month', current_time( 'timestamp' ) ) ),
338
		);
339
340
	}
341
342
	/**
343
	 * Retrieves last month's date range.
344
	 *
345
	 * @return array The appropriate date range.
346
	 */
347
	public function get_last_month_date_range() {
348
349
		// Set the previous date range.
350
		$this->previous_range = array(
351
			'period' => 'custom',
352
			'before' => date( 'Y-m-1', strtotime( 'last month', current_time( 'timestamp' ) ) ),
353
			'after'  => date( 'Y-m-t', strtotime( "-3 months", current_time( 'timestamp' ) ) ),
354
		);
355
356
		// Generate the report.
357
		return array(
358
			'before' => date( 'Y-m-1', current_time( 'timestamp' ) ),
359
			'after'  => date( 'Y-m-t', strtotime( "-2 months", current_time( 'timestamp' ) ) ),
360
		);
361
362
	}
363
364
	/**
365
	 * Retrieves this quarter date range.
366
	 *
367
	 * @return array The available quarters.
368
	 */
369
	public function get_quarters() {
370
371
		$last_year = (int) date('Y') - 1;
372
		$next_year = (int) date('Y') + 1;
373
		$year      = (int) date('Y');
374
		return array(
375
376
			array(
377
				'after'  => "$last_year-06-30",
378
				'before' => "$last_year-10-01",
379
			),
380
381
			array(
382
				'before' => "$year-01-01",
383
				'after'  => "$last_year-09-30",
384
			),
385
386
			array(
387
				'before' => "$year-04-01",
388
				'after'  => "$last_year-12-31",
389
			),
390
391
			array(
392
				'before' => "$year-07-01",
393
				'after'  => "$year-03-31",
394
			),
395
396
			array(
397
				'after'  => "$year-06-30",
398
				'before' => "$year-10-01",
399
			),
400
401
			array(
402
				'before' => "$next_year-01-01",
403
				'after'  => "$year-09-30",
404
			)
405
406
		);
407
408
	}
409
410
	/**
411
	 * Retrieves the current quater.
412
	 *
413
	 * @return int The current quarter.
414
	 */
415
	public function get_quarter() {
416
417
		$month    = (int) date( 'n', current_time( 'timestamp' ) );
418
		$quarters = array( 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4 );
419
		return $quarters[ $month - 1 ];
420
421
	}
422
423
	/**
424
	 * Retrieves this quarter date range.
425
	 *
426
	 * @return array The appropriate date range.
427
	 */
428
	public function get_quarter_date_range() {
429
430
		// Set the previous date range.
431
		$this->previous_range = array(
432
			'period' => 'last_quarter',
433
		);
434
435
		// Generate the report.
436
		$quarters = $this->get_quarters();
437
		return $quarters[ $this->get_quarter() + 1 ];
438
439
	}
440
441
	/**
442
	 * Retrieves last quarter's date range.
443
	 *
444
	 * @return array The appropriate date range.
445
	 */
446
	public function get_last_quarter_date_range() {
447
448
		$quarters = $this->get_quarters();
449
		$quarter  = $this->get_quarter();
450
451
		// Set the previous date range.
452
		$this->previous_range = array_merge(
453
			$quarters[ $quarter - 1 ],
454
			array( 'period' => 'custom' )
455
		);
456
457
		// Generate the report.
458
		return $quarters[ $quarter ];
459
460
	}
461
462
	/**
463
	 * Retrieves this year date range.
464
	 *
465
	 * @return array The appropriate date range.
466
	 */
467
	public function get_year_date_range() {
468
469
		$this->groupby = 'month';
470
471
		// Set the previous date range.
472
		$this->previous_range = array(
473
			'period' => 'last_year',
474
		);
475
476
		// Generate the report.
477
		return array(
478
			'before' => date( 'Y-m-d', strtotime( 'next year January 1st', current_time( 'timestamp' ) ) ),
479
			'after'  => date( 'Y-m-d', strtotime( 'last year December 31st', current_time( 'timestamp' ) ) ),
480
		);
481
482
	}
483
484
	/**
485
	 * Retrieves last year date range.
486
	 *
487
	 * @return array The appropriate date range.
488
	 */
489
	public function get_last_year_date_range() {
490
491
		$this->groupby = 'month';
492
493
		// Set the previous date range.
494
		$year          = (int) date('Y') - 3;
495
		$this->previous_range = array(
496
			'period' => 'custom',
497
			'before' => date( 'Y-m-d', strtotime( 'first day of january last year', current_time( 'timestamp' ) ) ),
498
			'after'  => "$year-12-31",
499
		);
500
501
		// Generate the report.
502
		$year          = (int) date('Y') - 2;
503
		return array(
504
			'after'  => "$year-12-31",
505
			'before' => date( 'Y-m-d', strtotime( 'first day of january this year', current_time( 'timestamp' ) ) ),
506
		);
507
508
	}
509
510
	/**
511
	 * Prepare a the request date for SQL usage.
512
	 *
513
	 * @param WP_REST_Request $request Request object.
514
	 * @param string $date_field The date field.
515
	 * @return string The appropriate SQL.
516
	 */
517
	public function get_date_range_sql( $request, $date_field ) {
518
		global $wpdb;
519
520
		$sql = '1=1';
521
		$range = $this->get_date_range( $request );
522
523
		if ( ! empty( $range['after'] ) ) {
524
			$sql .= ' AND ' .  $wpdb->prepare(
525
				"$date_field > %s",
526
				$range['after']
527
			);
528
		}
529
530
		if ( ! empty( $range['before'] ) ) {
531
			$sql .= ' AND ' .  $wpdb->prepare(
532
				"$date_field < %s",
533
				$range['before']
534
			);
535
		}
536
537
		return $sql;
538
539
	}
540
541
	/**
542
	 * Prepares a group by query.
543
	 *
544
	 * @param string $date_field The date field.
545
	 * @return string The appropriate SQL.
546
	 */
547
	public function get_group_by_sql( $date_field ) {
548
549
		if ( 'day' === $this->groupby ) {
550
			return "YEAR($date_field), MONTH($date_field), DAY($date_field)";
551
		}
552
553
		return "YEAR($date_field), MONTH($date_field)";
554
	}
555
556
	/**
557
	 * Get the query params for collections.
558
	 *
559
	 * @return array
560
	 */
561
	public function get_collection_params() {
562
		return array(
563
			'context' => $this->get_context_param( array( 'default' => 'view' ) ),
564
			'period' => array(
565
				'description'       => __( 'Limit to results of a specific period.', 'invoicing' ),
566
				'type'              => 'string',
567
				'enum'              => array( 'custom', 'today', 'yesterday', 'week', 'last_week', '7_days', '30_days', '60_days' , '90_days', '180_days', 'month', 'last_month', 'quarter', 'last_quarter', 'year', 'last_year', 'quarter', 'last_quarter' ),
568
				'validate_callback' => 'rest_validate_request_arg',
569
				'sanitize_callback' => 'sanitize_text_field',
570
				'default'           => '7_days',
571
			),
572
			'after' => array(
573
				/* translators: %s: date format */
574
				'description'       => sprintf( __( 'Limit to results after a specific date, the date needs to be in the %s format.', 'invoicing' ), 'YYYY-MM-DD' ),
575
				'type'              => 'string',
576
				'format'            => 'date',
577
				'validate_callback' => 'rest_validate_request_arg',
578
				'sanitize_callback' => 'sanitize_text_field',
579
				'default'           => date( 'Y-m-d', strtotime( '-8 days', current_time( 'timestamp' ) ) ),
580
			),
581
			'before' => array(
582
				/* translators: %s: date format */
583
				'description'       => sprintf( __( 'Limit to results before a specific date, the date needs to be in the %s format.', 'invoicing' ), 'YYYY-MM-DD' ),
584
				'type'              => 'string',
585
				'format'            => 'date',
586
				'validate_callback' => 'rest_validate_request_arg',
587
				'sanitize_callback' => 'sanitize_text_field',
588
				'default'           => date( 'Y-m-d', current_time( 'timestamp' ) ),
589
			),
590
		);
591
	}
592
}
593