Passed
Push — master ( 329df8...6d2ec0 )
by Sebastiaan
02:47
created

BaseEvent::skip()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 6
c 0
b 0
f 0
ccs 3
cts 3
cp 1
rs 9.4285
cc 1
eloc 3
nc 1
nop 1
crap 1
1
<?php
2
3
namespace Basebuilder\Scheduling\Event;
4
5
use Basebuilder\Scheduling\Event;
6
use Carbon\Carbon;
7
use Cron\CronExpression;
8
use Webmozart\Assert\Assert;
9
10
abstract class BaseEvent implements Event
11
{
12
    /**
13
     * The cron expression representing the event's frequency.
14
     * @var string
15
     */
16
    protected $expression = '* * * * * *';
17
18
    /**
19
     * The timezone the date should be evaluated on.
20
     * @var \DateTimeZone|string
21
     */
22
    protected $timezone;
23
24
    /**
25
     * The array of filter callbacks. These must return true
26
     * @var callable[]
27
     */
28
    protected $filters = [];
29
30
    /**
31
     * The array of callbacks to be run before the event is started.
32
     * @var callable[]
33
     */
34
    protected $beforeCallbacks = [];
35
36
    /**
37
     * The array of callbacks to be run after the event is finished.
38
     * @var callable[]
39
     */
40
    protected $afterCallbacks = [];
41
42
    /**
43
     * The array of reject callbacks.
44
     * @var callable[]
45
     */
46
    protected $rejects = [];
47
48
    /**
49
     * @var string
50
     */
51
    protected $description;
52
53
    /**
54
     * @param string $description
55
     * @return $this
56
     */
57
    public function describe($description)
58
    {
59
        $this->description = $description;
60
        return $this;
61
    }
62
63
    /**
64
     * Schedule the event to run between start and end time.
65
     *
66
     * @param  string  $startTime
67
     * @param  string  $endTime
68
     * @return $this
69
     */
70
    public function between($startTime, $endTime)
71
    {
72
        return $this->when($this->inTimeInterval($startTime, $endTime));
73
    }
74
75
    /**
76
     * Schedule the event to not run between start and end time.
77
     *
78
     * @param  string  $startTime
79
     * @param  string  $endTime
80
     * @return $this
81
     */
82
    public function notBetween($startTime, $endTime)
83
    {
84
        return $this->skip($this->inTimeInterval($startTime, $endTime));
85
    }
86
87
    /**
88
     * Schedule the event to run between start and end time.
89
     *
90
     * @param  string  $startTime
91
     * @param  string  $endTime
92
     * @return \Closure
93
     */
94
    private function inTimeInterval($startTime, $endTime)
95
    {
96
        return function () use ($startTime, $endTime) {
97
            $now = Carbon::now()->getTimestamp();
98
            return $now >= strtotime($startTime) && $now <= strtotime($endTime);
99
        };
100
    }
101
102
    /**
103
     * Set the timezone the date should be evaluated on.
104
     *
105
     * @return $this
106
     */
107
    public function timezone(\DateTimeZone $timezone)
108
    {
109
        $this->timezone = $timezone;
110
111
        return $this;
112
    }
113
114
    /**
115
     * Determine if the given event should run based on the Cron expression.
116
     *
117
     * @return bool
118
     */
119 2
    public function isDue()
120
    {
121 2
        return $this->expressionPasses() && $this->filtersPass();
122
    }
123
124
    /**
125
     * Determine if the Cron expression passes.
126
     *
127
     * @return boolean
128
     */
129 2
    protected function expressionPasses()
130
    {
131 2
        $date = Carbon::now();
132
133 2
        if ($this->timezone) {
134
            $date->setTimezone($this->timezone);
135
        }
136
137 2
        return $this->getCronExpression()->isDue($date->toDateTimeString());
138
    }
139
140
    /**
141
     * Determine if the filters pass for the event.
142
     *
143
     * @return boolean
144
     */
145 2
    protected function filtersPass()
146
    {
147 2
        foreach ($this->filters as $callback) {
148 1
            if (!call_user_func($callback)) {
149 1
                return false;
150
            }
151 2
        }
152
153 2
        foreach ($this->rejects as $callback) {
154 1
            if (call_user_func($callback)) {
155 1
                return false;
156
            }
157 2
        }
158
159 2
        return true;
160
    }
161
162
    /**
163
     * The Cron expression representing the event's frequency.
164
     *
165
     * @param  string  $expression
166
     * @return $this
167
     */
168 14
    public function cron(/* string */ $expression)
169
    {
170 14
        Assert::stringNotEmpty($expression);
171
172 14
        $this->expression = $expression;
173
174 14
        return $this;
175
    }
176
177
    /**
178
     * @return CronExpression
179
     */
180 14
    public function getCronExpression()
181
    {
182 14
        return CronExpression::factory($this->expression);
183
    }
184
185
    /**
186
     * Change the minute when the job should run (0-59, *, *\/2 etc)
187
     *
188
     * @param  string|int $minute
189
     * @return $this
190
     */
191 4
    public function minute($minute)
192
    {
193 4
        return $this->spliceIntoPosition(1, $minute);
194
    }
195
196
    /**
197
     * Schedule the event to run every minute.
198
     *
199
     * @return $this
200
     */
201 3
    public function everyMinute()
202
    {
203 3
        return $this->minute('*');
204
    }
205
206
    /**
207
     * Schedule this event to run every 5 minutes
208
     *
209
     * @return $this
210
     */
211
    public function everyFiveMinutes()
212
    {
213
        return $this->everyNMinutes(5);
214
    }
215
216
    /**
217
     * Schedule the event to run every N minutes
218
     *
219
     * @param  int $n
220
     * @return $this
221
     */
222 1
    public function everyNMinutes(/* int */ $n)
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $n. Configured minimum length is 2.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
223
    {
224 1
        Assert::integer($n);
225
226 1
        return $this->minute("*/{$n}");
0 ignored issues
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $n instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
227
    }
228
229
    /**
230
     * Set the hour when the job should run (0-23, *, *\/2, etc)
231
     *
232
     * @param  string|int $hour
233
     * @return $this
234
     */
235 1
    public function hour($hour)
236
    {
237 1
        return $this->spliceIntoPosition(2, $hour);
238
    }
239
240
    /**
241
     * Schedule the event to run hourly.
242
     *
243
     * @return $this
244
     */
245 1
    public function hourly()
246
    {
247 1
        return $this
248 1
            ->spliceIntoPosition(1, 0)
249 1
            ->spliceIntoPosition(2, '*');
250
    }
251
252
    /**
253
     * Schedule the event to run daily.
254
     *
255
     * @return $this
256
     */
257 1
    public function daily()
258
    {
259 1
        return $this
260 1
            ->spliceIntoPosition(1, 0)
261 1
            ->spliceIntoPosition(2, 0);
262
    }
263
264
    /**
265
     * Schedule the event to run daily at a given time (10:00, 19:30, etc).
266
     *
267
     * @param  string  $time
268
     * @return $this
269
     */
270 1
    public function dailyAt(/* string */ $time)
271
    {
272 1
        Assert::stringNotEmpty($time);
273
274 1
        $segments = explode(':', $time);
275
276 1
        return $this->spliceIntoPosition(2, (int) $segments[0])
277 1
            ->spliceIntoPosition(1, count($segments) == 2 ? (int) $segments[1] : '0');
278
    }
279
280
    /**
281
     * Set the days of the week the command should run on.
282
     *
283
     * @param  array|mixed  $days
284
     * @return $this
285
     */
286 1
    public function days($days)
287
    {
288 1
        $days = is_array($days) ? $days : func_get_args();
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $days. This often makes code more readable.
Loading history...
289
290 1
        return $this->spliceIntoPosition(5, implode(',', $days));
291
    }
292
293
    /**
294
     * Schedule the event to run only on weekdays.
295
     *
296
     * @return $this
297
     */
298 1
    public function weekdays()
299
    {
300 1
        return $this->spliceIntoPosition(5, '1-5');
301
    }
302
303
    /**
304
     * Schedule the event to run only on Mondays.
305
     *
306
     * @return $this
307
     */
308
    public function mondays()
309
    {
310
        return $this->days(1);
311
    }
312
313
    /**
314
     * Schedule the event to run only on Tuesdays.
315
     *
316
     * @return $this
317
     */
318
    public function tuesdays()
319
    {
320
        return $this->days(2);
321
    }
322
323
    /**
324
     * Schedule the event to run only on Wednesdays.
325
     *
326
     * @return $this
327
     */
328
    public function wednesdays()
329
    {
330
        return $this->days(3);
331
    }
332
333
    /**
334
     * Schedule the event to run only on Thursdays.
335
     *
336
     * @return $this
337
     */
338
    public function thursdays()
339
    {
340
        return $this->days(4);
341
    }
342
343
    /**
344
     * Schedule the event to run only on Fridays.
345
     *
346
     * @return $this
347
     */
348
    public function fridays()
349
    {
350
        return $this->days(5);
351
    }
352
353
    /**
354
     * Schedule the event to run only on Saturdays.
355
     *
356
     * @return $this
357
     */
358
    public function saturdays()
359
    {
360
        return $this->days(6);
361
    }
362
363
    /**
364
     * Schedule the event to run only on Sundays.
365
     *
366
     * @return $this
367
     */
368
    public function sundays()
369
    {
370
        return $this->days(0);
371
    }
372
373
    /**
374
     * Schedule the event to run weekly.
375
     *
376
     * @return $this
377
     */
378 1
    public function weekly()
379
    {
380 1
        return $this->spliceIntoPosition(1, 0)
381 1
            ->spliceIntoPosition(2, 0)
382 1
            ->spliceIntoPosition(5, 0);
383
    }
384
385
    /**
386
     * Schedule the event to run weekly on a given day and time.
387
     *
388
     * @param  int  $day
389
     * @param  string  $time
390
     * @return $this
391
     */
392
    public function weeklyOn($day, $time = '0:0')
393
    {
394
        $this->dailyAt($time);
395
        return $this->spliceIntoPosition(5, $day);
396
    }
397
398
    /**
399
     * Schedule the event to run monthly.
400
     *
401
     * @return $this
402
     */
403 1
    public function monthly()
404
    {
405 1
        return $this->spliceIntoPosition(1, 0)
406 1
            ->spliceIntoPosition(2, 0)
407 1
            ->spliceIntoPosition(3, 1);
408
    }
409
410
    /**
411
     * Schedule the event to run monthly on a given day and time.
412
     *
413
     * @param int  $day
414
     * @param string  $time
415
     * @return $this
416
     */
417
    public function monthlyOn($day = 1, $time = '0:0')
418
    {
419
        $this->dailyAt($time);
420
        return $this->spliceIntoPosition(3, $day);
421
    }
422
423
    /**
424
     * Schedule the event to run quarterly.
425
     *
426
     * @return $this
427
     */
428 1
    public function quarterly()
429
    {
430 1
        return $this->spliceIntoPosition(1, 0)
431 1
            ->spliceIntoPosition(2, 0)
432 1
            ->spliceIntoPosition(3, 1)
433 1
            ->spliceIntoPosition(4, '*/3');
434
    }
435
436
    /**
437
     * Schedule the event to run yearly.
438
     *
439
     * @return $this
440
     */
441 1
    public function yearly()
442
    {
443 1
        return $this->spliceIntoPosition(1, 0)
444 1
            ->spliceIntoPosition(2, 0)
445 1
            ->spliceIntoPosition(3, 1)
446 1
            ->spliceIntoPosition(4, 1);
447
    }
448
449
    /**
450
     * Splice the given value into the given position of the expression.
451
     *
452
     * @param  int  $position
453
     * @param  string  $value
454
     * @return $this
455
     */
456 14
    protected function spliceIntoPosition($position, $value)
457
    {
458 14
        $segments = explode(' ', $this->expression);
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 16 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
459 14
        $segments[$position - 1] = $value;
460 14
        return $this->cron(implode(' ', $segments));
461
    }
462
463
464
    /**
465
     * Register a callback to further filter the schedule.
466
     *
467
     * @param  callable  $callback
468
     * @return $this
469
     */
470 1
    public function when(callable $callback)
471
    {
472 1
        $this->filters[] = $callback;
473
474 1
        return $this;
475
    }
476
477
    /**
478
     * Register a callback to further filter the schedule.
479
     *
480
     * @param  callable  $callback
481
     * @return $this
482
     */
483 1
    public function skip(callable $callback)
484
    {
485 1
        $this->rejects[] = $callback;
486
487 1
        return $this;
488
    }
489
490
    /**
491
     * Register a callback to be called before the operation.
492
     *
493
     * @param callable $callback
494
     * @return $this
495
     */
496
    public function before(callable $callback)
497
    {
498
        $this->beforeCallbacks[] = $callback;
499
500
        return $this;
501
    }
502
503
    /**
504
     * Register a callback to be called after the operation.
505
     *
506
     * @param  callable  $callback
507
     * @return $this
508
     */
509
    public function after(callable $callback)
510
    {
511
        $this->afterCallbacks[] = $callback;
512
513
        return $this;
514
    }
515
}
516