Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
74 / 74
100.00% covered (success)
100.00%
14 / 14
CRAP
100.00% covered (success)
100.00%
1 / 1
ScopeList
100.00% covered (success)
100.00%
74 / 74
100.00% covered (success)
100.00%
14 / 14
43
100.00% covered (success)
100.00%
1 / 1
 getShortestBookableStart
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 getGreatestBookableEnd
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 getShortestBookableStartOnOpenedScope
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
4
 getGreatestBookableEndOnOpenedScope
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
4
 withoutDublicates
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
4
 withUniqueScopes
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
4
 addScopeList
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 withLessData
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 sortByName
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
3
 withProviderID
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
4
 addRequiredSlots
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
3
 getRequiredSlotsByScope
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 hasOpenedScope
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 getProviderList
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2
3namespace BO\Zmsentities\Collection;
4
5use BO\Zmsentities\Helper\Sorter;
6use BO\Zmsentities\Scope;
7
8/**
9 * @extends Base<\BO\Zmsentities\Scope>
10 */
11class ScopeList extends Base
12{
13    public const string ENTITY_CLASS = '\BO\Zmsentities\Scope';
14
15    protected array $slotsByID = [];
16
17    /**
18    * Get shortest bookable start date of a scope in scopelist
19    *
20    * @return \DateTimeImmutable $date
21    */
22    public function getShortestBookableStart(mixed $now)
23    {
24        $date = $now;
25        foreach ($this as $scope) {
26            $startDate = $scope->getBookableStartDate($now);
27            $date = ($startDate > $date) ? $startDate : $date;
28        }
29        return $date;
30    }
31
32    /**
33    * Get longest bookable end date of a scope in scopelist
34    *
35    * @return \DateTimeImmutable $date
36    */
37    public function getGreatestBookableEnd(mixed $now)
38    {
39        $date = $now;
40        foreach ($this as $scope) {
41            $endDate = $scope->getBookableEndDate($now);
42            $date = ($endDate > $date) ? $endDate : $date;
43        }
44        return $date;
45    }
46
47    /**
48    * Get shortest bookable start date of a opened scope in scopelist
49    *
50    * @return \DateTimeInterface|null
51    */
52    public function getShortestBookableStartOnOpenedScope(mixed $now)
53    {
54        $date = null;
55        foreach ($this as $scope) {
56            if ($scope->getStatus('availability', 'isOpened')) {
57                $date = $now;
58                $startDate = $scope->getBookableStartDate($date);
59                $date = ($startDate > $date) ? $startDate : $date;
60            }
61        }
62        return $date;
63    }
64
65    /**
66    * Get longest bookable end date of a opened scope in scopelist
67    *
68    * @return \DateTimeInterface|null
69    */
70    public function getGreatestBookableEndOnOpenedScope(mixed $now)
71    {
72        $date = null;
73        foreach ($this as $scope) {
74            if ($scope->getStatus('availability', 'isOpened')) {
75                $date = $now;
76                $endDate = $scope->getBookableEndDate($date);
77                $date = ($endDate > $date) ? $endDate : $date;
78            }
79        }
80        return $date;
81    }
82
83    public function withoutDublicates(mixed $scopeList = null): self
84    {
85        $collection = new self();
86        foreach ($this as $scope) {
87            if (! $scopeList || ! $scopeList->hasEntity($scope->getId())) {
88                $collection->addEntity(clone $scope);
89            }
90        }
91        return $collection;
92    }
93
94    public function withUniqueScopes(): self
95    {
96        $scopeList = new self();
97        foreach ($this as $scope) {
98            if ($scope->getId() && ! $scopeList->hasEntity($scope->getId())) {
99                $scopeList->addEntity(clone $scope);
100            }
101        }
102        return $scopeList;
103    }
104
105    public function addScopeList(mixed $scopeList): static
106    {
107        foreach ($scopeList as $scope) {
108            $this->addEntity($scope);
109        }
110        return $this;
111    }
112
113    /**
114     * @return static
115     */
116    #[\Override]
117    public function withLessData(array $keepArray = [])
118    {
119        /** @psalm-suppress UnsafeGenericInstantiation */
120        $scopeList = new static();
121        foreach ($this as $scope) {
122            $scopeList->addEntity(clone $scope->withLessData($keepArray));
123        }
124        return $scopeList;
125    }
126
127    /**
128     * @return static
129     */
130    #[\Override]
131    public function sortByName()
132    {
133        $this->uasort(function ($a, $b) {
134            $nameA = (isset($a->provider['name'])) ? $a->provider['name'] : ($a->shortName ?? '');
135            $nameB = (isset($b->provider['name'])) ? $b->provider['name'] : ($b->shortName ?? '');
136            return strcmp(
137                Sorter::toSortableString(ucfirst($nameA ?? '')),
138                Sorter::toSortableString(ucfirst($nameB ?? ''))
139            );
140        });
141        return $this;
142    }
143
144    public function withProviderID(mixed $source, mixed $providerID): self
145    {
146        $list = new ScopeList();
147        foreach ($this as $scope) {
148            if ($scope->provider['source'] == $source && $scope->provider['id'] == $providerID) {
149                $list->addEntity(clone $scope);
150            }
151        }
152        return $list;
153    }
154
155    public function addRequiredSlots(mixed $source, mixed $providerID, mixed $slotsRequired): static
156    {
157        $scopeList = $this->withProviderID($source, $providerID);
158        foreach ($scopeList as $scope) {
159            if (!isset($this->slotsByID[$scope->id])) {
160                $this->slotsByID[$scope->id] = 0;
161            }
162            $this->slotsByID[$scope->id] += $slotsRequired;
163        }
164        return $this;
165    }
166
167    public function getRequiredSlotsByScope(Scope $scope): mixed
168    {
169        if (isset($this->slotsByID[$scope->id])) {
170            return $this->slotsByID[$scope->id];
171        }
172        return 0;
173    }
174
175    public function hasOpenedScope(): bool
176    {
177        $isOpened = false;
178        foreach ($this as $entity) {
179            if ($entity->getStatus('availability', 'isOpened')) {
180                $isOpened = true;
181            }
182        }
183        return $isOpened;
184    }
185
186    public function getProviderList(): \BO\Zmsentities\Collection\ProviderList
187    {
188        $list = new ProviderList();
189        foreach ($this as $scope) {
190            $provider = $scope->getProvider();
191            $list->addEntity($provider);
192        }
193        return $list->withUniqueProvider();
194    }
195}