Completed
Push — master ( 4cc35d...0f472f )
by Michael
02:27
created

TaskBag   B

Complexity

Total Complexity 53

Size/Duplication

Total Lines 480
Duplicated Lines 3.33 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 95.83%

Importance

Changes 4
Bugs 2 Features 0
Metric Value
wmc 53
c 4
b 2
f 0
lcom 1
cbo 3
dl 16
loc 480
ccs 138
cts 144
cp 0.9583
rs 7.4757

42 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 14 4
A getTask() 0 4 1
A setTask() 0 5 1
A getInterval() 0 4 1
A setInterval() 0 5 1
A setTime() 0 8 1
A addTime() 0 8 1
A setDate() 8 8 1
A setMonth() 0 5 1
A getMonth() 0 4 1
A addMonth() 0 5 1
A setDay() 0 5 1
A getDay() 0 4 1
A addDay() 0 5 1
A addDate() 8 8 1
A setMinute() 0 5 1
A getMinute() 0 4 1
A addMinute() 0 5 1
A setHour() 0 5 1
A getHour() 0 4 1
A addHour() 0 5 1
A setWeekday() 0 5 1
A getWeekday() 0 4 1
A addWeekday() 0 5 1
A setEnvironments() 0 9 2
A addEnvironment() 0 5 1
A getEnvironments() 0 4 1
A addFollowedBy() 0 5 1
A getFollowedBy() 0 4 1
A setFollowedBy() 0 5 1
A setCronExpression() 0 8 2
A getCronExpression() 0 4 2
A buildExpression() 0 6 1
A setExpressionBuilder() 0 4 1
A getExpressionBuilder() 0 4 2
A isDue() 0 4 1
A getNextRunDate() 0 4 1
A getPreviousRunDate() 0 4 1
A parseTime() 0 5 1
A parseDate() 0 10 2
A appendValue() 0 12 3
A forceToArray() 0 8 2

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

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

1
<?php
2
namespace Mistletoe;
3
use Cron\CronExpression;
4
use Mistletoe\Contracts\ExpressionBuilderInterface;
5
use Mistletoe\Contracts\TaskBagInterface;
6
7
/**
8
 * Class TaskBag
9
 * @package FBS\Planner
10
 */
11
class TaskBag implements TaskBagInterface
12
{
13
    /** @var string Task */
14
    protected $task;
15
16
    /** @var array */
17
    protected $environments = [TaskPlanner::PRODUCTION_ENVIRONMENT, TaskPlanner::DEVELOPMENT_ENVIRONMENT];
18
19
    /** @var array|string Tasks that must follow this one */
20
    protected $followedBy = [];
21
22
    /** @var  CronExpression */
23
    protected $cronExpression;
24
25
    /* Expressions */
26
    /** @var bool|string */
27
    protected $interval = false; // @daily, @yearly
28
29
    /** @var null|string|int|array */
30
    protected $minute = null;
31
32
    /** @var null|string|int|array */
33
    protected $hour = null;
34
35
    /** @var null|string|int|array */
36
    protected $month = null; // 12
37
38
    /** @var null|string|int|array */
39
    protected $day = null; // 25
40
41
    /** @var null|string|int|array */
42
    protected $weekday = null;
43
44
    /* Dependencies */
45
    /** @var ExpressionBuilderInterface */
46
    protected $expressionBuilder;
47
48
49
    /**
50
     * TaskBag constructor.
51
     * @param string $task
52
     */
53 40
    public function __construct($task = null)
54
    {
55 40
        if (is_string($task)) {
56 37
            $this->task = $task;
57
58 40
        } elseif (is_array($task)) {
59
60
            // You may also pass in an array of values at construction
61
            // They MUST match the property names exactly
62 3
            foreach ($task as $key => $value) {
63 3
                $this->{'set'.ucfirst($key)}($value);
64 3
            }
65 3
        }
66 40
    }
67
68
    /**
69
     * @return string
70
     */
71 4
    public function getTask()
72
    {
73 4
        return $this->task;
74
    }
75
76
    /**
77
     * @param string $task
78
     * @return $this
79
     */
80 29
    public function setTask($task)
81
    {
82 29
        $this->task = $task;
83 29
        return $this;
84
    }
85
86
    /**
87
     * @return bool|string
88
     */
89 14
    public function getInterval()
90
    {
91 14
        return $this->interval;
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->interval; of type boolean|string adds the type boolean to the return on line 91 which is incompatible with the return type declared by the interface Mistletoe\Contracts\TaskBagInterface::getInterval of type null|string.
Loading history...
92
    }
93
94
    /**
95
     * @param string $interval
96
     * @return $this
97
     */
98 15
    public function setInterval($interval)
99
    {
100 15
        $this->interval = $interval;
101 15
        return $this;
102
    }
103
104
    /**
105
     * Parses a time from format 12:14
106
     * @param $time
107
     * @return $this
108
     */
109 5
    public function setTime($time)
110
    {
111 5
        $parts = $this->parseTime($time);
112 5
        $this->setHour($parts[0]);
113 5
        $this->setMinute($parts[1]);
114
115 5
        return $this;
116
    }
117
118
    /**
119
     * @param string $time
120
     * @return $this
121
     */
122 12
    public function addTime($time)
123
    {
124 12
        $parts = $this->parseTime($time);
125 12
        $this->addHour($parts[0]);
126 12
        $this->addMinute($parts[1]);
127
128 12
        return $this;
129
    }
130
131
    /**
132
     * Parses a time from formats 11/15 or 11-15
133
     * @param string $date
134
     * @return $this
135
     */
136 2 View Code Duplication
    public function setDate($date)
0 ignored issues
show
Duplication introduced by
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...
137
    {
138 2
        $parts = $this->parseDate($date);
139 2
        $this->setMonth(intval($parts[0]));
140 2
        $this->setDay(intval($parts[1]));
141
142 2
        return $this;
143
    }
144
145
    /**
146
     * @param string $date
147
     * @return $this
148
     */
149 4 View Code Duplication
    public function addDate($date)
0 ignored issues
show
Duplication introduced by
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...
150
    {
151 4
        $parts = $this->parseDate($date);
152 4
        $this->addMonth(intval($parts[0]));
153 4
        $this->addDay(intval($parts[1]));
154
155 4
        return $this;
156
    }
157
158
    /**
159
     * @param integer $month
160
     * @return $this
161
     */
162 6
    public function setMonth($month)
163
    {
164 6
        $this->month = $month;
165 6
        return $this;
166
    }
167
168
    /**
169
     * @return int|null|string
0 ignored issues
show
Documentation introduced by
Should the return type not be null|string|integer|array?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
170
     */
171 14
    public function getMonth()
172
    {
173 14
        return $this->month;
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->month; of type null|string|integer|array adds the type array to the return on line 173 which is incompatible with the return type declared by the interface Mistletoe\Contracts\TaskBagInterface::getMonth of type integer|null|string.
Loading history...
174
    }
175
176
    /**
177
     * @param string|int|array $month
178
     * @return $this
179
     */
180 7
    public function addMonth($month)
181
    {
182 7
        $this->appendValue('month', $month);
183 7
        return $this;
184
    }
185
186
    /**
187
     * @param integer $day
188
     * @return $this
189
     */
190 8
    public function setDay($day)
191
    {
192 8
        $this->day = $day;
193 8
        return $this;
194
    }
195
196
    /**
197
     * @return int|null|string
0 ignored issues
show
Documentation introduced by
Should the return type not be null|string|integer|array?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
198
     */
199 14
    public function getDay()
200
    {
201 14
        return $this->day;
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->day; of type null|string|integer|array adds the type array to the return on line 201 which is incompatible with the return type declared by the interface Mistletoe\Contracts\TaskBagInterface::getDay of type integer|null|string.
Loading history...
202
    }
203
204
    /**
205
     * @param string|int|array $day
206
     * @return $this
207
     */
208 9
    public function addDay($day)
209
    {
210 9
        $this->appendValue('day', $day);
211 9
        return $this;
212
    }
213
214
    /**
215
     * @param string|int|array $minute
216
     * @return $this
217
     * @throws \Exception
218
     */
219 8
    public function setMinute($minute)
220
    {
221 8
        $this->minute = $minute;
222 8
        return $this;
223
    }
224
225
    /**
226
     * @return int|null|string
0 ignored issues
show
Documentation introduced by
Should the return type not be null|string|integer|array?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
227
     */
228 14
    public function getMinute()
229
    {
230 14
        return $this->minute;
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->minute; of type null|string|integer|array adds the type array to the return on line 230 which is incompatible with the return type declared by the interface Mistletoe\Contracts\TaskBagInterface::getMinute of type integer|null|string.
Loading history...
231
    }
232
233
    /**
234
     * @param string|int|array $minute
235
     * @return $this
236
     */
237 13
    public function addMinute($minute)
238
    {
239 13
        $this->appendValue('minute', $minute);
240 13
        return $this;
241
    }
242
243
    /**
244
     * @param string|int|array $hour
245
     * @return $this
246
     */
247 8
    public function setHour($hour)
248
    {
249 8
        $this->hour = $hour;
250 8
        return $this;
251
    }
252
253
    /**
254
     * @return int|null|string
0 ignored issues
show
Documentation introduced by
Should the return type not be null|string|integer|array?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
255
     */
256 14
    public function getHour()
257
    {
258 14
        return $this->hour;
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->hour; of type null|string|integer|array adds the type array to the return on line 258 which is incompatible with the return type declared by the interface Mistletoe\Contracts\TaskBagInterface::getHour of type integer|null|string.
Loading history...
259
    }
260
261
    /**
262
     * @param string|int|array $hour
263
     * @return $this
264
     */
265 13
    public function addHour($hour)
266
    {
267 13
        $this->appendValue('hour', $hour);
268 13
        return $this;
269
    }
270
271
    /**
272
     * @param string|int|array $weekday
273
     * @return $this
274
     */
275 2
    public function setWeekday($weekday)
276
    {
277 2
        $this->weekday = $weekday;
278 2
        return $this;
279
    }
280
281
    /**
282
     * @return int|null|string
0 ignored issues
show
Documentation introduced by
Should the return type not be null|string|integer|array?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
283
     */
284 10
    public function getWeekday()
285
    {
286 10
        return $this->weekday;
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->weekday; of type null|string|integer|array adds the type array to the return on line 286 which is incompatible with the return type declared by the interface Mistletoe\Contracts\TaskBagInterface::getWeekday of type integer|null|string.
Loading history...
287
    }
288
289
    /**
290
     * @param string|int|array $weekday
291
     * @return $this
292
     */
293 3
    public function addWeekday($weekday)
294
    {
295 3
        $this->appendValue('weekday', $weekday);
296 3
        return $this;
297
    }
298
299 5
    public function setEnvironments($environments)
300
    {
301 5
        if (!is_array($environments)) {
302 2
            $environments = [$environments];
303 2
        }
304
305 5
        $this->environments = $environments;
306 5
        return $this;
307
    }
308
309
    /**
310
     * @param string $environment
311
     * @return $this
312
     */
313 2
    public function addEnvironment($environment)
314
    {
315 2
        $this->environments[] = $environment;
316 2
        return $this;
317
    }
318
319
    /**
320
     * @return array
321
     */
322 4
    public function getEnvironments()
323
    {
324 4
        return $this->environments;
325
    }
326
327
    /**
328
     * @param string $task
329
     * @return $this
330
     */
331 7
    public function addFollowedBy($task)
332
    {
333 7
        $this->followedBy[] = $task;
334 7
        return $this;
335
    }
336
337
    /**
338
     * @return array
0 ignored issues
show
Documentation introduced by
Should the return type not be array|string?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
339
     */
340 3
    public function getFollowedBy()
341
    {
342 3
        return $this->followedBy;
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->followedBy; of type array|string adds the type string to the return on line 342 which is incompatible with the return type declared by the interface Mistletoe\Contracts\Task...nterface::getFollowedBy of type array.
Loading history...
343
    }
344
345
    /**
346
     * @param string $followedBy
347
     * @return $this
348
     */
349 3
    public function setFollowedBy($followedBy)
350
    {
351 3
        $this->followedBy = $followedBy;
352 3
        return $this;
353
    }
354
355
    /**
356
     * @param string|CronExpression $cronExpression
357
     * @return $this
358
     */
359 16
    public function setCronExpression($cronExpression)
360
    {
361 16
        $this->cronExpression = ($cronExpression instanceof CronExpression)
362 16
            ? $cronExpression
363 16
            : CronExpression::factory($cronExpression);
364
365 16
        return $this;
366
    }
367
368
    /**
369
     * @return CronExpression
370
     */
371 12
    public function getCronExpression()
372
    {
373 12
        return ($this->cronExpression instanceof CronExpression) ? $this->cronExpression : $this->buildExpression();
374
    }
375
376
    /**
377
     * @return CronExpression
378
     */
379 8
    protected function buildExpression()
380
    {
381 8
        $expression = $this->getExpressionBuilder()->setTaskBag($this)->build();
382 8
        $this->setCronExpression($expression);
383 8
        return $expression;
384
    }
385
386
    /**
387
     * @param ExpressionBuilderInterface $expressionBuilder
388
     */
389 1
    public function setExpressionBuilder(ExpressionBuilderInterface $expressionBuilder)
390
    {
391 1
        $this->expressionBuilder = $expressionBuilder;
392 1
    }
393
394
    /**
395
     * @return ExpressionBuilder|ExpressionBuilderInterface
396
     */
397 8
    protected function getExpressionBuilder()
398
    {
399 8
        return ($this->expressionBuilder instanceof ExpressionBuilderInterface) ? $this->expressionBuilder : new ExpressionBuilder();
400
    }
401
402
403
    /* Just passed through to CronExpression */
404
    /**
405
     * @param string $currentTime
406
     * @return bool
407
     */
408 2
    public function isDue($currentTime = 'now')
409
    {
410 2
        return $this->getCronExpression()->isDue($currentTime);
411
    }
412
413
    /**
414
     * @param string $currentTime
415
     * @param int $nth
416
     * @param bool $allowCurrentDate
417
     */
418
    public function getNextRunDate($currentTime = 'now', $nth = 0, $allowCurrentDate = false)
419
    {
420
        $this->getCronExpression()->getNextRunDate($currentTime, $nth, $allowCurrentDate);
421
    }
422
423
    /**
424
     * @param string $currentTime
425
     * @param int $nth
426
     * @param bool $allowCurrentDate
427
     */
428
    public function getPreviousRunDate($currentTime = 'now', $nth = 0, $allowCurrentDate = false)
429
    {
430
        $this->getCronExpression()->getPreviousRunDate($currentTime, $nth, $allowCurrentDate);
431
    }
432
433
    /* Internals */
434
    /**
435
     * @param $time
436
     * @return array
437
     */
438 14
    protected function parseTime($time)
439
    {
440 14
        $parts = explode(':', $time);
441 14
        return $parts;
442
    }
443
444
    /**
445
     * @param string $date
446
     * @return array
447
     */
448 6
    protected function parseDate($date)
449
    {
450 6
        if (strpos($date, '-')) {
451 4
            $parts = explode('-', $date);
452 4
            return $parts;
453
        } else {
454 5
            $parts = explode('/', $date);
455 5
            return $parts;
456
        }
457
    }
458
459
    /**
460
     * @param string $key
461
     * @param $value
462
     * @param string $deliminator
463
     */
464 21
    protected function appendValue($key, $value, $deliminator = ',')
465
    {
466 21
        $value = $this->forceToArray($value);
467
468 21
        foreach ($value as $item) {
469 21
            if (!is_null($this->$key)) {
470 12
                $this->$key = (string)$this->$key . $deliminator . $item;
471 12
            } else {
472 21
                $this->$key = (string)$item;
473
            }
474 21
        }
475 21
    }
476
477
    /**
478
     * @param $value
479
     * @return array
480
     * @internal param $minute
481
     */
482 21
    protected function forceToArray($value)
483
    {
484 21
        if (!is_array($value)) {
485 21
            return [$value];
486
        }
487
488 3
        return $value;
489
    }
490
}
491