Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
99.42% covered (success)
99.42%
170 / 171
95.83% covered (success)
95.83%
23 / 24
CRAP
0.00% covered (danger)
0.00%
0 / 1
Calendar
99.42% covered (success)
99.42%
170 / 171
95.83% covered (success)
95.83%
23 / 24
57
0.00% covered (danger)
0.00%
0 / 1
 getDefaults
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
1
 addDates
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 addFirstAndLastDay
100.00% covered (success)
100.00%
15 / 15
100.00% covered (success)
100.00%
1 / 1
1
 addProvider
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
3
 addCluster
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 addRequest
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
3
 addScope
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
3
 getScopeList
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
3
 getRequestList
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 getProviderList
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 getDayList
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 hasDay
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getDay
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getDayByDateTime
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getDateTimeFromDate
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 hasFirstAndLastDay
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 getFirstDay
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
2
 getLastDay
91.67% covered (success)
91.67%
11 / 12
0.00% covered (danger)
0.00%
0 / 1
4.01
 setLastDayTime
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 setFirstDayTime
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 getMonthList
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
2
 withLessData
100.00% covered (success)
100.00%
16 / 16
100.00% covered (success)
100.00%
1 / 1
5
 withFilledEmptyDays
100.00% covered (success)
100.00%
22 / 22
100.00% covered (success)
100.00%
1 / 1
4
 __toString
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
5
1<?php
2
3namespace BO\Zmsentities;
4
5/**
6 *
7 * @SuppressWarnings(CouplingBetweenObjects)
8 * @SuppressWarnings(TooManyPublicMethods)
9 * @SuppressWarnings(Complexity)
10 */
11class Calendar extends Schema\Entity
12{
13    public const string PRIMARY = 'days';
14
15    public static $schema = "calendar.json";
16
17    /**
18     * @return (Collection\DayList|Day|array|null)[]
19     *
20     */
21    #[\Override]
22    public function getDefaults()
23    {
24        return [
25            'firstDay' => new Day(),
26            'lastDay' => null,
27            'days' => new Collection\DayList(),
28            'clusters' => [ ],
29            'providers' => [ ],
30            'scopes' => [ ],
31            'requests' => [ ]
32        ];
33    }
34
35    public function addDates($date, \DateTimeInterface $now, $timeZone): static
36    {
37        $validDate = \BO\Mellon\Validator::value($date)->isDate();
38        $date = (! $validDate->hasFailed()) ? $validDate->getValue() : $now->format('U');
39        if (! $this->toProperty()->firstDay->day->get()) {
40            $this->addFirstAndLastDay($date, $timeZone);
41        }
42        return $this;
43    }
44
45    /**
46     * Returns calendar with first and last day
47     *
48     * @return $this
49     */
50    public function addFirstAndLastDay($date, $timeZone)
51    {
52        $timeZone = new \DateTimeZone($timeZone);
53        $dateTime = Helper\DateTime::create()->setTimezone($timeZone)->setTimestamp($date);
54        $firstDay = $dateTime->setTime(0, 0, 0);
55        $lastDay = $dateTime->modify('last day of next month')->setTime(23, 59, 59);
56        $this->firstDay = array(
57            'year' => $firstDay->format('Y'),
58            'month' => $firstDay->format('m'),
59            'day' => $firstDay->format('d')
60        );
61        $this->lastDay = array(
62            'year' => $lastDay->format('Y'),
63            'month' => $lastDay->format('m'),
64            'day' => $lastDay->format('d')
65        );
66        return $this;
67    }
68
69    /**
70     * Returns calendar with added Providers
71     *
72     * @return $this
73     */
74    public function addProvider($source, $idList)
75    {
76        foreach (explode(',', $idList) as $id) {
77            if ($id) {
78                $provider = new Provider();
79                $provider->source = $source;
80                $provider->id = $id;
81                $this->providers[] = $provider;
82            }
83        }
84        return $this;
85    }
86
87    /**
88     * Returns calendar with added Clusters
89     *
90     * @return $this
91     */
92    public function addCluster($idList)
93    {
94        foreach (explode(',', $idList) as $id) {
95            $cluster = new Cluster();
96            $cluster->id = $id;
97            $this->clusters[] = $cluster;
98        }
99        return $this;
100    }
101
102    /**
103     * Returns calendar with added requests
104     *
105     * @return $this
106     */
107    public function addRequest($source, $requestList)
108    {
109        foreach (explode(',', $requestList) as $id) {
110            if ($id) {
111                $request = new Request();
112                $request->source = $source;
113                $request->id = $id;
114                $this->requests[] = $request;
115            }
116        }
117        return $this;
118    }
119
120    /**
121     * Returns calendar with added scopes
122     *
123     * @return $this
124     */
125    public function addScope($scopeList)
126    {
127        foreach (explode(',', $scopeList) as $id) {
128            if ($id) {
129                $scope = new Scope();
130                $scope->id = $id;
131                $this->scopes[] = $scope;
132            }
133        }
134        return $this;
135    }
136
137    /**
138     * Returns a list of associated scope ids
139     *
140     * @return array
141     */
142    public function getScopeList()
143    {
144        $scopeList = new \BO\Zmsentities\Collection\ScopeList();
145        if (isset($this->scopes)) {
146            foreach ($this->scopes as $scope) {
147                $scope = new Scope($scope);
148                $scopeList->addEntity($scope);
149            }
150        }
151        return $scopeList;
152    }
153
154    /**
155     * Returns a list of associated request entities
156     *
157     * @return array
158     */
159    public function getRequestList()
160    {
161        $requestList = new \BO\Zmsentities\Collection\RequestList();
162        foreach ($this->requests as $request) {
163            $request = new Request($request);
164            $requestList->addEntity($request);
165        }
166        return $requestList;
167    }
168
169    /**
170     * Returns a list of associated provider ids
171     *
172     * @return array
173     */
174    public function getProviderList()
175    {
176        $providerList = new \BO\Zmsentities\Collection\ProviderList();
177        foreach ($this->providers as $provider) {
178            $entity = new Provider($provider);
179            $providerList->addEntity($entity);
180        }
181        return $providerList;
182    }
183
184    public function getDayList()
185    {
186        if (!$this->days instanceof Collection\DayList) {
187            $this->days = new Collection\DayList($this->days);
188        }
189        return $this->days->setSortByDate();
190    }
191
192    /**
193     * Check if given day exists in calendar
194     *
195     * @return bool
196     */
197    public function hasDay($year, $month, $dayNumber)
198    {
199        return $this->getDayList()->hasDay($year, $month, $dayNumber);
200    }
201
202    /**
203     * Returns a day by given year, month and daynumber
204     *
205     * @return \ArrayObject
206     */
207    public function getDay($year, $month, $dayNumber)
208    {
209        return $this->getDayList()->getDay($year, $month, $dayNumber);
210    }
211
212    public function getDayByDateTime(\DateTimeInterface $datetime)
213    {
214        return $this->getDayList()->getDayByDateTime($datetime);
215    }
216
217    public function getDateTimeFromDate(array $date)
218    {
219        $day = (isset($date['day'])) ? $date['day'] : 1;
220        $date = Helper\DateTime::createFromFormat('Y-m-d', $date['year'] . '-' . $date['month'] . '-' . $day);
221        return Helper\DateTime::create($date);
222    }
223
224    /**
225     * Simple quick check, if first and last day are defined
226     */
227    public function hasFirstAndLastDay(): bool
228    {
229        if (!$this->toProperty()->firstDay->day->get()) {
230            return false;
231        }
232        if (!$this->toProperty()->lastDay->day->get()) {
233            return false;
234        }
235        return true;
236    }
237
238    public function getFirstDay()
239    {
240        if (isset($this['firstDay'])) {
241            $dateTime = $this->getDateTimeFromDate(
242                array(
243                    'year' => $this['firstDay']['year'],
244                    'month' => $this['firstDay']['month'],
245                    'day' => $this['firstDay']['day']
246                )
247            );
248        } else {
249            $dateTime = Helper\DateTime::create();
250        }
251        return $dateTime->modify('00:00:00');
252    }
253
254    public function getLastDay($createIfNotProvided = true)
255    {
256        if (! $createIfNotProvided && ! isset($this['lastDay'])) {
257            return null;
258        }
259
260        if (isset($this['lastDay'])) {
261            $dateTime = $this->getDateTimeFromDate(
262                array(
263                    'year' => $this['lastDay']['year'],
264                    'month' => $this['lastDay']['month'],
265                    'day' => $this['lastDay']['day']
266                )
267            );
268        } else {
269            $dateTime = Helper\DateTime::create();
270        }
271        return $dateTime->modify('23:59:59');
272    }
273
274    public function setLastDayTime($date): static
275    {
276        $day = new Day();
277        $day->setDateTime($date);
278        $this['lastDay'] = $day;
279        return $this;
280    }
281
282    public function setFirstDayTime($date): static
283    {
284        $day = new Day();
285        $day->setDateTime($date);
286        $this['firstDay'] = $day;
287        return $this;
288    }
289
290    /**
291     * Returns a list of contained month given by firstDay and lastDay
292     * The return value is a month entity object for the first day of the month
293     */
294    public function getMonthList(): Collection\MonthList
295    {
296        $firstDay = $this->getFirstDay()->modify('first day of this month')->modify('00:00:00');
297        $lastDay = $this->getLastDay()->modify('last day of this month')->modify('23:59:59');
298        $currentDate = $firstDay;
299        if ($firstDay->getTimestamp() > $lastDay->getTimestamp()) {
300            // switch first and last day if necessary
301            $currentDate = $lastDay;
302            $lastDay = $firstDay;
303        }
304        $monthList = new Collection\MonthList();
305        do {
306            $monthList->addEntity(Month::createForDateFromDayList($currentDate, $this->days));
307            $currentDate = $currentDate->modify('+1 month');
308        } while ($currentDate->getTimestamp() < $lastDay->getTimestamp());
309        return $monthList;
310    }
311
312    /**
313     * Reduce data of dereferenced entities to a required minimum
314     *
315     * @return static
316     */
317    #[\Override]
318    public function withLessData()
319    {
320        $entity = clone $this;
321
322        foreach ($entity['scopes'] as $scope) {
323            if ($scope->toProperty()->provider->data->isAvailable()) {
324                $payment = $scope->toProperty()->provider->data->payment->get();
325                unset($scope['provider']['data']);
326                $scope['provider']['data'] = ['payment' => $payment];
327                unset($scope['dayoff']);
328                unset($scope['status']);
329                unset($scope['preferences']);
330            }
331        }
332        foreach ($entity['days'] as $day) {
333            if (isset($day['allAppointments'])) {
334                unset($day['allAppointments']);
335            }
336        }
337        unset($entity['providers']);
338        unset($entity['clusters']);
339        unset($entity['freeProcesses']);
340        return $entity;
341    }
342
343    public function withFilledEmptyDays(): static
344    {
345        $entity = clone $this;
346
347        $firstDay = $this->getFirstDay()->modify('first day of this month')->modify('00:00:00');
348        $lastDay = $this->getLastDay()->modify('last day of this month')->modify('23:59:59');
349        $currentDate = $firstDay;
350        $dayList = new Collection\DayList($entity->days);
351
352        do {
353            $day = new Day([
354                'year' => $currentDate->format('Y'),
355                'month' => $currentDate->format('m'),
356                'day' => $currentDate->format('d')
357            ]);
358            $dayTimestamp = $day->toDateTime()->getTimestamp();
359            $dayFound = false;
360
361            foreach ($dayList as $checkingDay) {
362                $checkingTimestamp = $checkingDay->toDateTime()->getTimestamp();
363                if ($checkingTimestamp === $dayTimestamp) {
364                    $dayFound = true;
365                }
366            }
367
368            if (!$dayFound) {
369                $dayList->addEntity($day);
370            }
371
372            $currentDate = $currentDate->modify('+1 day');
373        } while ($currentDate->getTimestamp() < $lastDay->getTimestamp());
374
375        $entity->days = $dayList;
376
377        return $entity;
378    }
379
380    public function __toString()
381    {
382        $string = '';
383        foreach ($this->days as $day) {
384            $day = ($day instanceof Day) ? $day : new Day($day);
385            $string .= "$day\n";
386        }
387        foreach ($this->scopes as $scope) {
388            $scope = ($scope instanceof Scope) ? $scope : new Scope($scope);
389            $string .= "$scope\n";
390        }
391        return $string;
392    }
393}