Completed
Push — master ( 19b369...87a841 )
by Amine
02:43
created

DayAttendance::isValidDayAttendanceLine()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 1
crap 1
1
<?php
2
3
namespace AmineBenHariz\Attendance;
4
5
/**
6
 * Class DayAttendance
7
 * @package AmineBenHariz\Attendance
8
 */
9
class DayAttendance
10
{
11
    /**
12
     * example: 2015-12-12|08:30 (10:00-10:30) (12:30-13:30) (16:00-16:30) 17:30
13
     */
14
    const DAY_ATTENDANCE_LINE_REGEX = '/^\d{4}-\d{2}-\d{2}\|\d{2}:\d{2}( \(\d{2}:\d{2}-\d{2}:\d{2}\))* \d{2}:\d{2}$/';
15
16
    /**
17
     * @var \DateTime
18
     */
19
    private $arrival;
20
21
    /**
22
     * @var \DateTime
23
     */
24
    private $departure;
25
26
    /**
27
     * @var Pause[]
28
     */
29
    private $pauseList = [];
30
31
    /**
32
     * DayAttendance constructor.
33
     * @param \DateTime $arrival
34
     * @param \DateTime $departure
35
     * @param Pause[] $pauseList
36
     */
37 21
    public function __construct(\DateTime $arrival, \DateTime $departure, array $pauseList = [])
38
    {
39 21
        if ($arrival > $departure) {
40 3
            throw new \InvalidArgumentException;
41
        }
42
43 18
        if ($arrival->format('Y-m-d') !== $departure->format('Y-m-d')) {
44 3
            throw new \InvalidArgumentException;
45
        }
46
47 15
        $this->arrival = $arrival;
48 15
        $this->departure = $departure;
49
50 15
        if (!empty($pauseList)) {
51 15
            foreach ($pauseList as $pause) {
52 15
                $this->addPause($pause);
53 12
            }
54 6
        }
55 6
    }
56
57
    /**
58
     * @return \DateTime
59
     */
60 21
    public function getArrival()
61
    {
62 21
        return $this->arrival;
63
    }
64
65
    /**
66
     * @return \DateTime
67
     */
68 18
    public function getDeparture()
69
    {
70 18
        return $this->departure;
71
    }
72
73
    /**
74
     * @return Pause[]
75
     */
76 18
    public function getPauseList()
77
    {
78 18
        return $this->pauseList;
79
    }
80
81
    /**
82
     * @param Pause $pause
83
     */
84 15
    private function addPause(Pause $pause)
85
    {
86 15
        if ($pause->getStart() < $this->getArrival()) {
87 3
            throw new \InvalidArgumentException;
88
        }
89
90 12
        if ($pause->getEnd() > $this->getDeparture()) {
91 3
            throw new \InvalidArgumentException;
92
        }
93
94 12
        if ($this->isPauseOverlapping($pause)) {
95 3
            throw new \InvalidArgumentException;
96
        }
97
98
99 12
        $this->pauseList[] = $pause;
100 12
    }
101
102
    /**
103
     * @param Pause $pause
104
     * @return bool
105
     */
106 12
    private function isPauseOverlapping(Pause $pause)
107
    {
108 12
        $existingPauseList = $this->getPauseList();
109 12
        if (empty($existingPauseList)) {
110 12
            return false;
111
        }
112
113 9
        foreach ($existingPauseList as $existingPause) {
114 9
            if ($pause->isOverlapping($existingPause)) {
115 3
                return true;
116
            }
117 6
        }
118
119 6
        return false;
120
    }
121
122
    /**
123
     * @return \DateInterval
124
     */
125 3
    public function getDuration()
126
    {
127 3
        $cursor = clone $this->getArrival();
128
129
        // PHP 5.4 : empty() can only handle variables
130 3
        $pauseList = $this->getPauseList();
131
132 3
        if (!empty($pauseList)) {
133 3
            foreach ($pauseList as $pause) {
134 3
                $cursor->add($pause->getDuration());
135 3
            }
136 3
        }
137
138 3
        return $cursor->diff($this->getDeparture());
139
    }
140
141
    /**
142
     * @param $dayAttendanceLine
143
     * @return DayAttendance
144
     */
145 6
    public static function parseDayAttendanceLine($dayAttendanceLine)
146
    {
147 6
        if (!self::isValidDayAttendanceLine($dayAttendanceLine)) {
148 3
            throw new \InvalidArgumentException;
149
        }
150
151 3
        list($date, $timeLine) = explode('|', $dayAttendanceLine);
152
153 3
        $times = explode(' ', $timeLine);
154
155 3
        $arrival = new \DateTime($date . ' ' . array_shift($times));
156 3
        $departure = new \DateTime($date . ' ' . array_pop($times));
157
158 3
        $pauseList = [];
159 3
        if (!empty($times)) {
160 3
            foreach ($times as $pauseBlock) {
161
                // Pause Block: '(10:00-10:30)'
162 3
                $pauseStart = new \DateTime($date . ' ' . substr($pauseBlock, 1, 5));
163 3
                $pauseEnd = new \DateTime($date . ' ' . substr($pauseBlock, 7, 5));
164 3
                $pauseList[] = new Pause($pauseStart, $pauseEnd);
165 3
            }
166 3
        }
167
168 3
        $dayAttendance = new DayAttendance($arrival, $departure, $pauseList);
169 3
        return $dayAttendance;
170
    }
171
172
    /**
173
     * @param $dayAttendanceLine
174
     * @return int
175
     */
176 33
    public static function isValidDayAttendanceLine($dayAttendanceLine)
177
    {
178 33
        return preg_match(self::DAY_ATTENDANCE_LINE_REGEX, $dayAttendanceLine) === 1;
179
    }
180
181
    /**
182
     * @return string
183
     */
184 3
    public function exportLine()
185
    {
186 3
        $date = $this->getArrival()->format('Y-m-d');
187 3
        $line = $date. '|' . $this->getArrival()->format('H:i');
188
189 3
        foreach ($this->getPauseList() as $pause) {
190 3
            $line .= ' ' . $pause->exportBlock();
191 3
        }
192
193 3
        $line .= ' ' . $this->getDeparture()->format('H:i');
194
195 3
        return $line;
196
    }
197
}
198