DayAttendance   A
last analyzed

Complexity

Total Complexity 32

Size/Duplication

Total Lines 266
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Test Coverage

Coverage 100%

Importance

Changes 18
Bugs 3 Features 6
Metric Value
wmc 32
c 18
b 3
f 6
lcom 1
cbo 1
dl 0
loc 266
ccs 90
cts 90
cp 1
rs 9.6

18 Methods

Rating   Name   Duplication   Size   Complexity  
A getArrival() 0 4 1
A getDeparture() 0 4 1
A getPauseList() 0 4 1
A __construct() 0 13 4
A getDescription() 0 4 1
A setDescription() 0 4 1
A addPause() 0 17 4
A isPauseOverlapping() 0 12 3
A getDuration() 0 13 2
A getTotalMinutes() 0 5 1
A parseDayAttendanceLine() 0 19 2
A explodeDayAttendanceLineParts() 0 11 2
A parsePauseBlocks() 0 9 2
A parsePauseBlock() 0 6 1
A isValidDayAttendanceLine() 0 4 1
A exportLine() 0 10 2
A getDate() 0 4 1
A getTimeLine() 0 12 2
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 =
15
        '/^\d{4}-\d{2}-\d{2}\|\d{2}:\d{2}( \(\d{2}:\d{2}-\d{2}:\d{2}\))* \d{2}:\d{2}(\|[^\|]*)?$/';
16
17
    /**
18
     * @var \DateTime
19
     */
20
    private $arrival;
21
22
    /**
23
     * @var \DateTime
24
     */
25
    private $departure;
26
27
    /**
28
     * @var Pause[]
29
     */
30
    private $pauseList = [];
31
32
    /**
33
     * @var string
34
     */
35
    private $description = "";
36
37
    /**
38
     * DayAttendance constructor.
39
     * @param \DateTime $arrival
40
     * @param \DateTime $departure
41
     * @param Pause[] $pauseList
42
     */
43 33
    public function __construct(\DateTime $arrival, \DateTime $departure, array $pauseList = [])
44
    {
45 33
        if ($arrival > $departure || $arrival->format('Y-m-d') !== $departure->format('Y-m-d')) {
46 6
            throw new \InvalidArgumentException;
47
        }
48
49 27
        $this->arrival = $arrival;
50 27
        $this->departure = $departure;
51
52 27
        foreach ($pauseList as $pause) {
53 24
            $this->addPause($pause);
54 24
        }
55 18
    }
56
57
    /**
58
     * @return \DateTime
59
     */
60 48
    public function getArrival()
61
    {
62 48
        return $this->arrival;
63
    }
64
65
    /**
66
     * @return \DateTime
67
     */
68 42
    public function getDeparture()
69
    {
70 42
        return $this->departure;
71
    }
72
73
    /**
74
     * @return Pause[]
75
     */
76 42
    public function getPauseList()
77
    {
78 42
        return $this->pauseList;
79
    }
80
81
    /**
82
     * @return string
83
     */
84 18
    public function getDescription()
85
    {
86 18
        return $this->description;
87
    }
88
89
    /**
90
     * @param string $description
91
     */
92 18
    public function setDescription($description)
93
    {
94 18
        $this->description = $description;
95 18
    }
96
97
    /**
98
     * @param Pause $pause
99
     */
100 24
    private function addPause(Pause $pause)
101
    {
102 24
        if ($pause->getStart() < $this->getArrival()) {
103 3
            throw new \InvalidArgumentException;
104
        }
105
106 21
        if ($pause->getEnd() > $this->getDeparture()) {
107 3
            throw new \InvalidArgumentException;
108
        }
109
110 21
        if ($this->isPauseOverlapping($pause)) {
111 3
            throw new \InvalidArgumentException;
112
        }
113
114
115 21
        $this->pauseList[] = $pause;
116 21
    }
117
118
    /**
119
     * @param Pause $pause
120
     * @return bool
121
     */
122 21
    private function isPauseOverlapping(Pause $pause)
123
    {
124 21
        $existingPauseList = $this->getPauseList();
125
126 21
        foreach ($existingPauseList as $existingPause) {
127 15
            if ($pause->isOverlapping($existingPause)) {
128 3
                return true;
129
            }
130 21
        }
131
132 21
        return false;
133
    }
134
135
    /**
136
     * @return \DateInterval
137
     */
138 9
    public function getDuration()
139
    {
140 9
        $cursor = clone $this->getArrival();
141
142
        // PHP 5.4 : empty() can only handle variables
143 9
        $pauseList = $this->getPauseList();
144
145 9
        foreach ($pauseList as $pause) {
146 9
            $cursor->add($pause->getDuration());
147 9
        }
148
149 9
        return $cursor->diff($this->getDeparture());
150
    }
151
152
    /**
153
     * @return int
154
     */
155 6
    public function getTotalMinutes()
156
    {
157 6
        $duration = $this->getDuration();
158 6
        return intval($duration->format('%H')) * 60 + intval($duration->format('%I'));
159
    }
160
161
    /**
162
     * @param $dayAttendanceLine
163
     * @return DayAttendance
164
     */
165 18
    public static function parseDayAttendanceLine($dayAttendanceLine)
166
    {
167 18
        if (!self::isValidDayAttendanceLine($dayAttendanceLine)) {
168 3
            throw new \InvalidArgumentException;
169
        }
170
171 15
        list($date, $timeLine, $description) = self::explodeDayAttendanceLineParts($dayAttendanceLine);
172
173 15
        $times = explode(' ', $timeLine);
174
175 15
        $arrival = new \DateTime($date . ' ' . array_shift($times));
176 15
        $departure = new \DateTime($date . ' ' . array_pop($times));
177
178 15
        $pauseList = self::parsePauseBlocks($date, $times);
179
180 15
        $dayAttendance = new DayAttendance($arrival, $departure, $pauseList);
181 15
        $dayAttendance->setDescription($description);
182 15
        return $dayAttendance;
183
    }
184
185
    /**
186
     * @param string $dayAttendanceLine
187
     * @return array
188
     */
189 15
    private static function explodeDayAttendanceLineParts($dayAttendanceLine)
190
    {
191 15
        $parts = explode('|', $dayAttendanceLine);
192
193
        // if empty description
194 15
        if (!isset($parts[2])) {
195 12
            $parts[2] = '';
196 12
        }
197
198 15
        return $parts;
199
    }
200
201
    /**
202
     * @param string $date date in Y-m-d format, ex: 2016-03-29
203
     * @param array $pauseBlocks
204
     * @return Pause[]
205
     */
206 15
    private static function parsePauseBlocks($date, $pauseBlocks)
207
    {
208 15
        $pauseList = [];
209 15
        foreach ($pauseBlocks as $pauseBlock) {
210 12
            $pauseList[] = self::parsePauseBlock($date, $pauseBlock);
211 15
        }
212
213 15
        return $pauseList;
214
    }
215
216
    /**
217
     * @param string $date date in Y-m-d format, ex: 2016-03-29
218
     * @param string $pauseBlock ex: (10:00-10:30)
219
     * @return Pause
220
     */
221 12
    private static function parsePauseBlock($date, $pauseBlock)
222
    {
223 12
        $pauseStart = new \DateTime($date . ' ' . substr($pauseBlock, 1, 5));
224 12
        $pauseEnd = new \DateTime($date . ' ' . substr($pauseBlock, 7, 5));
225 12
        return new Pause($pauseStart, $pauseEnd);
226
    }
227
228
    /**
229
     * @param $dayAttendanceLine
230
     * @return int
231
     */
232 45
    public static function isValidDayAttendanceLine($dayAttendanceLine)
233
    {
234 45
        return preg_match(self::DAY_ATTENDANCE_LINE_REGEX, $dayAttendanceLine) === 1;
235
    }
236
237
    /**
238
     * @return string
239
     */
240 6
    public function exportLine()
241
    {
242 6
        $line = $this->getDate() . '|' . $this->getTimeLine();
243
244 6
        if ($this->getDescription() !== '') {
245 3
            $line .= '|' . $this->getDescription();
246 3
        }
247
248 6
        return $line;
249
    }
250
251
    /**
252
     * @return string
253
     */
254 9
    public function getDate()
255
    {
256 9
        return $this->getArrival()->format('Y-m-d');
257
    }
258
259
    /**
260
     * @return string
261
     */
262 9
    public function getTimeLine()
263
    {
264 9
        $line = $this->getArrival()->format('H:i');
265
266 9
        foreach ($this->getPauseList() as $pause) {
267 9
            $line .= ' ' . $pause->exportBlock();
268 9
        }
269
270 9
        $line .= ' ' . $this->getDeparture()->format('H:i');
271
272 9
        return $line;
273
    }
274
}
275