Completed
Push — master ( e86fc0...6fccf5 )
by Jitendra
02:51
created

Validator::inStepRange()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 11
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 5
dl 0
loc 11
rs 10
c 0
b 0
f 0
cc 4
nc 3
nop 4
1
<?php
2
3
/*
4
 * This file is part of the PHP-CRON-EXPR package.
5
 *
6
 * (c) Jitendra Adhikari <[email protected]>
7
 *     <https://github.com/adhocore>
8
 *
9
 * Licensed under MIT license.
10
 */
11
12
namespace Ahc\Cron;
13
14
/**
15
 * Cron segment validator.
16
 *
17
 * This class checks if a cron segment is valid.
18
 *
19
 * @author Jitendra Adhikari <[email protected]>
20
 */
21
class Validator
22
{
23
    public function inRange($value, $offset)
24
    {
25
        $parts = \explode('-', $offset);
26
27
        return $parts[0] <= $value && $value <= $parts[1];
28
    }
29
30
    public function inStep($value, $offset)
31
    {
32
        $parts = \explode('/', $offset, 2);
33
34
        if (empty($parts[1])) {
35
            return false;
36
        }
37
38
        if (\strpos($offset, '*/') !== false || \strpos($offset, '0/') !== false) {
39
            return $value % $parts[1] === 0;
40
        }
41
42
        $parts    = \explode('/', $offset, 2);
43
        $subparts = \explode('-', $parts[0], 2) + [1 => $value];
44
45
        return $this->inStepRange($value, $subparts[0], $subparts[1], $parts[1]);
46
    }
47
48
    public function inStepRange($value, $start, $end, $step)
49
    {
50
        if (($start + $step) > $end) {
51
            return false;
52
        }
53
54
        if ($start <= $value && $value <= $end) {
55
            return \in_array($value, \range($start, $end, $step));
56
        }
57
58
        return false;
59
    }
60
61
    /**
62
     * Check if month modifiers [L C W #] are satisfied.
63
     *
64
     * @internal
65
     *
66
     * @param string $value
67
     * @param array  $time
68
     *
69
     * @return bool|null
70
     */
71
    public function isValidMonthDay($value, $time)
72
    {
73
        if ($value == 'L') {
74
            return $time[2] == $time[6];
75
        }
76
77
        if ($pos = \strpos($value, 'W')) {
78
            $value = \substr($value, 0, $pos);
79
            $month = \str_pad($time[8], 2, '0', \STR_PAD_LEFT);
80
81
            return $this->isClosestWeekDay($value, $month, $time);
82
        }
83
    }
84
85
    protected function isClosestWeekDay($value, $month, $time)
86
    {
87
        foreach ([0, -1, 1, -2, 2] as $i) {
88
            $incr = $value + $i;
89
            if ($incr < 1 || $incr > $time[6]) {
90
                continue;
91
            }
92
93
            $incr  = \str_pad($incr, 2, '0', \STR_PAD_LEFT);
94
            $parts = \explode(' ', \date('N m j', \strtotime("{$time[5]}-$month-$incr")));
95
            if ($parts[0] < 6 && $parts[1] == $month) {
96
                return $time[2] == $parts[2];
97
            }
98
        }
99
100
        // @codeCoverageIgnoreStart
101
        return false;
102
        // @codeCoverageIgnoreEnd
103
    }
104
105
    /**
106
     * Check if week modifiers [L C W #] are satisfied.
107
     *
108
     * @internal
109
     *
110
     * @param string $value
111
     * @param array  $time
112
     *
113
     * @return bool|null
114
     */
115
    public function isValidWeekDay($value, $time)
116
    {
117
        $month = \str_pad($time[8], 2, '0', \STR_PAD_LEFT);
118
119
        if (\strpos($value, 'L')) {
120
            return $this->isLastWeekDay($value, $month, $time);
121
        }
122
123
        if (!\strpos($value, '#')) {
124
            return null;
125
        }
126
127
        list($day, $nth) = \explode('#', \str_replace('0#', '7#', $value));
128
129
        if (!$this->isNthWeekDay($day, $nth) || $time[9] != $day) {
130
            return false;
131
        }
132
133
        return \intval($time[7] / 7) == $nth - 1;
134
    }
135
136
    protected function isLastWeekDay($value, $month, $time)
137
    {
138
        $value = \explode('L', \str_replace('7L', '0L', $value));
139
        $decr  = $time[6];
140
141
        for ($i = 0; $i < 7; $i++) {
142
            $decr -= $i;
143
            if (\date('w', \strtotime("{$time[5]}-$month-$decr")) == $value[0]) {
144
                return $time[2] == $decr;
145
            }
146
        }
147
148
        return false;
149
    }
150
151
    protected function isNthWeekDay($day, $nth)
152
    {
153
        return !($day < 0 || $day > 7 || $nth < 1 || $nth > 5);
154
    }
155
}
156