Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
71 / 71
100.00% covered (success)
100.00%
13 / 13
CRAP
100.00% covered (success)
100.00%
1 / 1
DayList
100.00% covered (success)
100.00%
71 / 71
100.00% covered (success)
100.00%
13 / 13
32
100.00% covered (success)
100.00%
1 / 1
 getDay
100.00% covered (success)
100.00%
20 / 20
100.00% covered (success)
100.00%
1 / 1
8
 getDayByDateTime
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getDayByDay
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 hasDay
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 withAssociatedDays
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
2
 setStatusByType
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 withAddedDayList
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
3
 setSortByDate
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
1
 setSort
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 hasDayWithAppointments
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 getFirstBookableDay
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 withDaysInDateRange
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
4
 withDaysFromPeriod
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3namespace BO\Zmsentities\Collection;
4
5use BO\Zmsentities\Day;
6
7/**
8 * @extends Base<\BO\Zmsentities\Day>
9 */
10class DayList extends Base implements JsonUnindexed
11{
12    public const string ENTITY_CLASS = '\BO\Zmsentities\Day';
13
14    /**
15     * ATTENTION: Performance critical, keep highly optimized
16     */
17    public function getDay(string $year, string $month, string $dayNumber, bool $createDay = true): Day|null
18    {
19        $dateHash = Day::getCalculatedDayHash($dayNumber, $month, $year);
20        if ($this->offsetExists($dateHash)) {
21            return $this[$dateHash];
22        }
23        foreach ($this as $key => $day) {
24            if (!$day instanceof Day) {
25                $day = new Day($day);
26                $this[$key] = $day;
27            }
28            if ($day->day == $dayNumber && $day->month == $month && $day->year == $year) {
29                unset($this[$key]);
30                $this[$dateHash] = $day;
31                return $day;
32            }
33        }
34        if ($createDay) {
35            $day  = new \BO\Zmsentities\Day([
36                'year' => $year,
37                'month' => $month,
38                'day' => $dayNumber
39            ]);
40            $this[$dateHash] = $day;
41            return $day;
42        }
43        return null;
44    }
45
46    public function getDayByDateTime(\DateTimeInterface $datetime)
47    {
48        return $this->getDay($datetime->format('Y'), $datetime->format('m'), $datetime->format('d'));
49    }
50
51    public function getDayByDay(\BO\Zmsentities\Day $day)
52    {
53        return $this->getDay($day->year, $day->month, $day->day);
54    }
55
56
57    public function hasDay($year, $month, $dayNumber): bool
58    {
59        $day = $this->getDay($year, $month, $dayNumber, false);
60        return ($day === null) ? false : true;
61    }
62
63    public function withAssociatedDays(\DateTimeInterface $currentDate)
64    {
65        $dayList = new self();
66        $lastDay = $currentDate->format('t');
67        for ($dayNumber = 1; $dayNumber <= $lastDay; $dayNumber++) {
68            $day = str_pad($dayNumber, 2, '0', STR_PAD_LEFT);
69            $entity = $this->getDay($currentDate->format('Y'), $currentDate->format('m'), $day);
70            $dayList->addEntity($entity);
71        }
72        return $dayList->sortByCustomKey('day');
73    }
74
75    public function setStatusByType($slotType, \DateTimeInterface $dateTime): static
76    {
77        foreach ($this as $day) {
78            $day->getWithStatus($slotType, $dateTime);
79        }
80        return $this;
81    }
82
83    public function withAddedDayList(DayList $dayList): self
84    {
85        $merged = new DayList();
86        foreach ($dayList as $day) {
87            // @codeCoverageIgnoreStart
88            if (!$day instanceof Day) {
89                $day = new Day($day);
90            }
91            // @codeCoverageIgnoreEnd
92            $merged->addEntity($day->withAddedDay($this->getDayByDay($day)));
93        }
94        return $merged;
95    }
96
97    public function setSortByDate(): static
98    {
99        $this->uasort(function ($dayA, $dayB) {
100            return (
101                intval($dayA['year'] . $dayA['month'] . $dayA['day']) -
102                intval($dayB['year'] . $dayB['month'] . $dayB['day'])
103            );
104        });
105        return $this;
106    }
107
108    public function setSort($property = 'day'): static
109    {
110        $this->uasort(function ($dayA, $dayB) use ($property) {
111            return strnatcmp($dayA[$property], $dayB[$property]);
112        });
113        return $this;
114    }
115
116    public function hasDayWithAppointments(): bool
117    {
118        foreach ($this as $day) {
119            $day = new Day($day);
120            if ($day->hasAppointments()) {
121                return true;
122            }
123        }
124        return false;
125    }
126
127    public function getFirstBookableDay()
128    {
129        foreach ($this as $day) {
130            $day = new Day($day);
131            if ($day->isBookable()) {
132                return $day->toDateTime();
133            }
134        }
135        return null;
136    }
137
138    public function withDaysInDateRange(\DateTimeInterface $startDate, \DateTimeInterface $endDate): self
139    {
140        $list = new self();
141        foreach ($this as $day) {
142            if (
143                $day->toDateTime() >= $startDate->modify('00:00:00') &&
144                $day->toDateTime() <= $endDate->modify('23:59:59')
145            ) {
146                $list->addEntity($day);
147            }
148        }
149        return $list;
150    }
151
152    public function withDaysFromPeriod(\DateTimeInterface $startDate, \DateTimeInterface $endDate): self
153    {
154        $list = new self();
155        do {
156            $day = (new Day())->setDateTime($startDate);
157            $list->addEntity($day);
158            $startDate = $startDate->modify('+1 day');
159        } while ($startDate <= $endDate);
160        return $list;
161    }
162}