Completed
Push — master ( 5e206d...a5ddc8 )
by Amine
06:41 queued 14s
created

DayAttendance::setDescription()   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

Importance

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