Completed
Push — master ( c13e4a...5e206d )
by Amine
02:04
created

DayAttendance::getTimeLine()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 2

Importance

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