Passed
Pull Request — master (#280)
by Brian
05:07
created

CronExpression_DayOfWeekField   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 105
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 53
c 1
b 0
f 0
dl 0
loc 105
rs 10
wmc 19

3 Methods

Rating   Name   Duplication   Size   Complexity  
A validate() 0 3 1
A increment() 0 11 2
C isSatisfiedBy() 0 76 16
1
<?php
2
3
/**
4
 * Day of week field.  Allows: * / , - ? L #
5
 *
6
 * Days of the week can be represented as a number 0-7 (0|7 = Sunday)
7
 * or as a three letter string: SUN, MON, TUE, WED, THU, FRI, SAT.
8
 *
9
 * 'L' stands for "last". It allows you to specify constructs such as
10
 * "the last Friday" of a given month.
11
 *
12
 * '#' is allowed for the day-of-week field, and must be followed by a
13
 * number between one and five. It allows you to specify constructs such as
14
 * "the second Friday" of a given month.
15
 *
16
 * @author Michael Dowling <[email protected]>
17
 */
18
class CronExpression_DayOfWeekField extends CronExpression_AbstractField
19
{
20
    /**
21
     * {@inheritdoc}
22
     */
23
    public function isSatisfiedBy(DateTime $date, $value)
24
    {
25
        if ($value == '?') {
26
            return true;
27
        }
28
29
        // Convert text day of the week values to integers
30
        $value = str_ireplace(
31
            array('SUN', 'MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT'),
32
            range(0, 6),
33
            $value
34
        );
35
36
        $currentYear = $date->format('Y');
37
        $currentMonth = $date->format('m');
38
        $lastDayOfMonth = $date->format('t');
39
40
        // Find out if this is the last specific weekday of the month
41
        if (strpos($value, 'L')) {
42
            $weekday = str_replace('7', '0', substr($value, 0, strpos($value, 'L')));
43
            $tdate = clone $date;
44
            $tdate->setDate($currentYear, $currentMonth, $lastDayOfMonth);
0 ignored issues
show
Bug introduced by
$currentMonth of type string is incompatible with the type integer expected by parameter $month of DateTime::setDate(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

44
            $tdate->setDate($currentYear, /** @scrutinizer ignore-type */ $currentMonth, $lastDayOfMonth);
Loading history...
Bug introduced by
$lastDayOfMonth of type string is incompatible with the type integer expected by parameter $day of DateTime::setDate(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

44
            $tdate->setDate($currentYear, $currentMonth, /** @scrutinizer ignore-type */ $lastDayOfMonth);
Loading history...
Bug introduced by
$currentYear of type string is incompatible with the type integer expected by parameter $year of DateTime::setDate(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

44
            $tdate->setDate(/** @scrutinizer ignore-type */ $currentYear, $currentMonth, $lastDayOfMonth);
Loading history...
45
            while ($tdate->format('w') != $weekday) {
46
                $tdate->setDate($currentYear, $currentMonth, --$lastDayOfMonth);
47
            }
48
49
            return $date->format('j') == $lastDayOfMonth;
50
        }
51
52
        // Handle # hash tokens
53
        if (strpos($value, '#')) {
54
            list($weekday, $nth) = explode('#', $value);
55
            // Validate the hash fields
56
            if ($weekday < 1 || $weekday > 5) {
57
                throw new InvalidArgumentException("Weekday must be a value between 1 and 5. {$weekday} given");
58
            }
59
            if ($nth > 5) {
60
                throw new InvalidArgumentException('There are never more than 5 of a given weekday in a month');
61
            }
62
            // The current weekday must match the targeted weekday to proceed
63
            if ($date->format('N') != $weekday) {
64
                return false;
65
            }
66
67
            $tdate = clone $date;
68
            $tdate->setDate($currentYear, $currentMonth, 1);
69
            $dayCount = 0;
70
            $currentDay = 1;
71
            while ($currentDay < $lastDayOfMonth + 1) {
72
                if ($tdate->format('N') == $weekday) {
73
                    if (++$dayCount >= $nth) {
74
                        break;
75
                    }
76
                }
77
                $tdate->setDate($currentYear, $currentMonth, ++$currentDay);
78
            }
79
80
            return $date->format('j') == $currentDay;
81
        }
82
83
        // Handle day of the week values
84
        if (strpos($value, '-')) {
85
            $parts = explode('-', $value);
86
            if ($parts[0] == '7') {
87
                $parts[0] = '0';
88
            } elseif ($parts[1] == '0') {
89
                $parts[1] = '7';
90
            }
91
            $value = implode('-', $parts);
92
        }
93
94
        // Test to see which Sunday to use -- 0 == 7 == Sunday
95
        $format = in_array(7, str_split($value)) ? 'N' : 'w';
96
        $fieldValue = $date->format($format);
97
98
        return $this->isSatisfied($fieldValue, $value);
99
    }
100
101
    /**
102
     * {@inheritdoc}
103
     */
104
    public function increment(DateTime $date, $invert = false)
105
    {
106
        if ($invert) {
107
            $date->modify('-1 day');
108
            $date->setTime(23, 59, 0);
109
        } else {
110
            $date->modify('+1 day');
111
            $date->setTime(0, 0, 0);
112
        }
113
114
        return $this;
115
    }
116
117
    /**
118
     * {@inheritdoc}
119
     */
120
    public function validate($value)
121
    {
122
        return (bool) preg_match('/[\*,\/\-0-9A-Z]+/', $value);
123
    }
124
}
125