Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
71.56% covered (warning)
71.56%
151 / 211
62.50% covered (warning)
62.50%
20 / 32
CRAP
0.00% covered (danger)
0.00%
0 / 1
ProcessList
71.56% covered (warning)
71.56%
151 / 211
62.50% covered (warning)
62.50%
20 / 32
297.17
0.00% covered (danger)
0.00%
0 / 1
 toProcessListByTime
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
3
 withRequest
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 sortByScopeName
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
2
 sortByAppointmentDate
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 sortByArrivalTime
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 sortByEstimatedWaitingTime
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 sortByClientName
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
1
 sortByTimeKey
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 toProcessListByStatusList
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
12
 toConflictListByDay
95.00% covered (success)
95.00%
19 / 20
0.00% covered (danger)
0.00%
0 / 1
5
 getScopeList
100.00% covered (success)
100.00%
5 / 5
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
3
 getAppointmentList
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
4
 setTempAppointmentToProcess
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
1 / 1
5
 toQueueList
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
2
 withAvailability
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 withAvailabilityStrict
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
3
 withDepartmentNotificationEnabled
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
12
 withDepartmentHasMailFrom
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
12
 setConflictAmendment
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
3
 withOutAvailability
76.92% covered (warning)
76.92%
10 / 13
0.00% covered (danger)
0.00%
0 / 1
5.31
 withUniqueScope
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
4
 withAccess
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
12
 withScopeId
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 withOutScopeId
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 withOutProcessId
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 withoutExpiredAppointmentDate
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
12
 withinExactDate
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
12
 withoutDublicatedConflicts
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
12
 testProcessListLength
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
4
 withoutProcessByStatus
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 withTimeRangeByAppointment
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
30
1<?php
2
3namespace BO\Zmsentities\Collection;
4
5use BO\Zmsentities\Helper\Sorter;
6use BO\Zmsentities\Helper\Property;
7use BO\Zmsentities\Helper\Messaging;
8use BO\Zmsentities\Process;
9
10/**
11 * @SuppressWarnings(Complexity)
12 * @SuppressWarnings(Public)
13 * @SuppressWarnings(Coupling)
14 *
15 */
16class ProcessList extends Base
17{
18    public const ENTITY_CLASS = '\BO\Zmsentities\Process';
19
20    public function toProcessListByTime($format = null)
21    {
22        $list = new self();
23        foreach ($this as $process) {
24            $appointment = $process->getFirstAppointment();
25            $formattedDate = $appointment['date'];
26            if ($format) {
27                $formattedDate = $appointment->toDateTime()->format($format);
28            }
29            $list[$formattedDate][] = clone $process;
30        }
31        return $list;
32    }
33
34    public function withRequest($requestId)
35    {
36        $list = new self();
37        foreach ($this as $process) {
38            if ($process->requests->hasEntity($requestId)) {
39                $list->addEntity(clone $process);
40            }
41        }
42        return $list;
43    }
44
45    public function sortByScopeName()
46    {
47        $this->uasort(function ($a, $b) {
48            return strcmp(
49                Sorter::toSortableString(ucfirst($a->scope->contact['name'] ?? '')),
50                Sorter::toSortableString(ucfirst($b->scope->contact['name'] ?? ''))
51            );
52        });
53        return $this;
54    }
55
56    public function sortByAppointmentDate()
57    {
58        $this->uasort(function ($a, $b) {
59            return ($a->getFirstAppointment()->date - $b->getFirstAppointment()->date);
60        });
61        return $this;
62    }
63
64    public function sortByArrivalTime()
65    {
66        $this->uasort(function ($a, $b) {
67            return ($a->queue['arrivalTime'] - $b->queue['arrivalTime']);
68        });
69        return $this;
70    }
71
72    public function sortByEstimatedWaitingTime()
73    {
74        $this->uasort(function ($a, $b) {
75            return ($a->queue['waitingTimeEstimate'] - $b->queue['waitingTimeEstimate']);
76        });
77        return $this;
78    }
79
80    public function sortByClientName()
81    {
82        $this->uasort(function ($a, $b) {
83            return strcmp(
84                Sorter::toSortableString($a->getFirstClient()['familyName']),
85                Sorter::toSortableString($b->getFirstClient()['familyName'])
86            );
87        });
88        return $this;
89    }
90
91    public function sortByTimeKey()
92    {
93        $this->uksort(function ($a, $b) {
94            return ($a - $b);
95        });
96        return $this;
97    }
98
99    public function toProcessListByStatusList(array $statusList)
100    {
101        $collection = new self();
102        foreach ($this as $process) {
103            if (in_array($process->getStatus(), $statusList)) {
104                $collection->addEntity($process);
105            }
106        }
107        return $collection;
108    }
109
110    public function toConflictListByDay()
111    {
112        $list = [];
113        $oldList = clone $this;
114        foreach ($oldList as $process) {
115            $appointmentList = [];
116            if (!isset($list[$process->getFirstAppointment()->getStartTime()->format('Y-m-d')])) {
117                $list[$process->getFirstAppointment()->getStartTime()->format('Y-m-d')] = [];
118            }
119            foreach ($process->getAppointments() as $appointment) {
120                $availabilityId = ($appointment->getAvailability()->getId()) ?
121                    $appointment->getAvailability()->getId() :
122                    $appointment->getAvailability()->tempId;
123                $appointmentList[] = [
124                    'startTime' => $appointment->getStartTime()->format('H:i'),
125                    'endTime' => $appointment->getEndTime()->format('H:i'),
126                    'availability' => $availabilityId
127                ];
128            }
129            $list[$process->getFirstAppointment()->getStartTime()->format('Y-m-d')][] = [
130                'message' => $process->amendment,
131                'appointments' => $appointmentList
132            ];
133        }
134        return $list;
135    }
136
137    public function getScopeList()
138    {
139        $list = new ScopeList();
140        foreach ($this as $process) {
141            if (Property::__keyExists('scope', $process)) {
142                $list[] = new \BO\Zmsentities\Scope($process['scope']);
143            }
144        }
145        return $list->withUniqueScopes();
146    }
147
148    public function getRequestList()
149    {
150        $list = new RequestList();
151        foreach ($this as $process) {
152            if (Property::__keyExists('requests', $process)) {
153                $list->addList($process->getRequests());
154            }
155        }
156        return $list->withUniqueRequests();
157    }
158
159    public function getAppointmentList()
160    {
161        $appointmentList = new AppointmentList();
162        foreach ($this as $process) {
163            if (Property::__keyExists('appointments', $process)) {
164                foreach ($process["appointments"] as $appointment) {
165                    $appointmentList->addEntity(new \BO\Zmsentities\Appointment($appointment));
166                }
167            }
168        }
169        return $appointmentList;
170    }
171
172    public function setTempAppointmentToProcess($dateTime, $scopeId)
173    {
174        $addedAppointment = false;
175        $appointment = (new \BO\Zmsentities\Appointment())->addDate($dateTime->getTimestamp())->addScope($scopeId);
176        foreach ($this as $process) {
177            if ($process->hasAppointment($dateTime->getTimestamp(), $scopeId) && !$addedAppointment) {
178                $entity = clone $process;
179                $this->addEntity($entity);
180                $addedAppointment = true;
181            }
182        }
183        if (!$addedAppointment) {
184            $entity = new \BO\Zmsentities\Process();
185            $entity->addAppointment($appointment);
186            $this->addEntity($entity);
187        }
188        return $this;
189    }
190
191    public function toQueueList($now)
192    {
193        $queueList = new QueueList();
194        foreach ($this as $process) {
195            $queue = $process->toQueue($now);
196            $queueList->addEntity($queue);
197        }
198        $queueList->setTransferedProcessList(true);
199        return $queueList;
200    }
201
202    public function withAvailability(\BO\Zmsentities\Availability $availability)
203    {
204        $processList = new static();
205        foreach ($this as $process) {
206            if ($availability->hasAppointment($process->getFirstAppointment())) {
207                $processList[] = clone $process;
208            }
209        }
210        return $processList;
211    }
212
213    public function withAvailabilityStrict(\BO\Zmsentities\Availability $availability)
214    {
215        $processList = new static();
216        $slotList = $availability->getSlotList();
217        foreach ($this as $process) {
218            if ($slotList->removeAppointment($process->getFirstAppointment())) {
219                $processList[] = clone $process;
220            }
221        }
222        return $processList;
223    }
224
225    public function withDepartmentNotificationEnabled()
226    {
227        $processList = new static();
228        foreach ($this as $process) {
229            if ($process->scope->hasNotificationReminderEnabled()) {
230                $entity = clone $process;
231                $processList->addEntity($entity);
232            }
233        }
234        return $processList;
235    }
236
237    public function withDepartmentHasMailFrom()
238    {
239        $processList = new static();
240        foreach ($this as $process) {
241            if ($process->scope->hasEmailFrom()) {
242                $entity = clone $process;
243                $processList->addEntity($entity);
244            }
245        }
246        return $processList;
247    }
248
249
250
251    public function setConflictAmendment()
252    {
253        foreach ($this as $process) {
254            $process->amendment = 'Die Slots für diesen Zeitraum wurden Ã¼berbucht';
255            if (! $process->getFirstAppointment()->availability->hasId()) {
256                $process->amendment = sprintf(
257                    'Der Vorgang (%s) befindet sich außerhalb der Ã–ffnungszeit!',
258                    $process->getId()
259                );
260            }
261        }
262        return $this;
263    }
264
265    public function withOutAvailability(\BO\Zmsentities\Collection\AvailabilityList $availabilityList)
266    {
267        $processList = new static();
268        foreach ($this->toProcessListByTime('Y-m-d') as $processListByDate) {
269            $dateTime = $processListByDate[0]->getFirstAppointment()->toDateTime();
270            $slotList = $availabilityList->withType('appointment')->withDateTime($dateTime)->getSlotList();
271            foreach ($processListByDate as $process) {
272                try {
273                    $slotList->withSlotsForAppointment($process->getFirstAppointment());
274                    if (!$slotList->removeAppointment($process->getFirstAppointment())) {
275                        $process->amendment = "";
276                        $processList[] = clone $process;
277                    }
278                } catch (\BO\Zmsentities\Exception\AppointmentNotFitInSlotList $exception) {
279                    $process->amendment = "";
280                    $processList[] = clone $process;
281                }
282            }
283        }
284        return $processList;
285    }
286
287    public function withUniqueScope($oncePerHour = false)
288    {
289        $processList = new static();
290        $scopeKeyList = [];
291        foreach ($this as $process) {
292            $scopeKey = $process->scope->id . '-';
293            if ($oncePerHour) {
294                $scopeKey .= $process->getFirstAppointment()->toDateTime()->format('H');
295            } else {
296                $scopeKey .= $process->getFirstAppointment()->toDateTime()->format('H:i');
297            }
298            if (!in_array($scopeKey, $scopeKeyList)) {
299                $processList[] = clone $process;
300                $scopeKeyList[] = $scopeKey;
301            }
302        }
303        return $processList;
304    }
305
306    public function withAccess(\BO\Zmsentities\Useraccount $useraccount)
307    {
308        $list = new static();
309        foreach ($this as $process) {
310            $process = clone $process;
311            if ($process->getCurrentScope()->hasAccess($useraccount)) {
312                $list[] = $process;
313            }
314        }
315        return $list;
316    }
317
318    public function withScopeId($scopeId)
319    {
320        $processList = new static();
321        foreach ($this as $process) {
322            if ($scopeId == $process->scope['id']) {
323                $processList[] = clone $process;
324            }
325        }
326        return $processList;
327    }
328
329    public function withOutScopeId($scopeId)
330    {
331        $processList = new static();
332        foreach ($this as $process) {
333            if ($scopeId != $process->scope['id']) {
334                $processList[] = clone $process;
335            }
336        }
337        return $processList;
338    }
339
340    public function withOutProcessId($processId)
341    {
342        $processList = new static();
343        foreach ($this as $process) {
344            if ($processId != $process->getId()) {
345                $processList[] = clone $process;
346            }
347        }
348        return $processList;
349    }
350
351    public function withoutExpiredAppointmentDate(\DateTimeInterface $now)
352    {
353        $conflictList = new self();
354        foreach ($this as $process) {
355            if ($process->getFirstAppointment()->date > $now->getTimestamp()) {
356                $conflictList->addEntity(clone $process);
357            }
358        }
359        return $conflictList;
360    }
361
362    public function withinExactDate(\DateTimeInterface $now)
363    {
364        $processList = new self();
365        foreach ($this as $process) {
366            if ($process->getFirstAppointment()->toDateTime()->format('Y-m-d') == $now->format('Y-m-d')) {
367                $processList->addEntity(clone $process);
368            }
369        }
370        return $processList;
371    }
372
373    public function withoutDublicatedConflicts()
374    {
375        $collection = new self();
376        foreach ($this as $conflict) {
377            if (! $collection->getAppointmentList()->hasAppointment($conflict->getFirstAppointment())) {
378                $collection->addEntity(clone $conflict);
379            }
380        }
381        return $collection;
382    }
383
384    public function testProcessListLength($processList, bool $isEmptyAllowed = false): ProcessList
385    {
386        $collection = ($processList instanceof Process) ?
387            (new self())->addEntity($processList) :
388            $processList;
389
390        if (0 === $collection->count() && ! $isEmptyAllowed) {
391            throw new \BO\Zmsentities\Exception\ProcessListEmpty();
392        }
393        return $collection;
394    }
395
396    public function withoutProcessByStatus($process, $status)
397    {
398        $collection = clone $this;
399        $collection = (1 <= $collection->count() && ! Messaging::isEmptyProcessListAllowed($status)) ?
400            $collection->withOutProcessId($process->getId()) :
401            $collection;
402        return $collection;
403    }
404
405    /*
406    * reduce process list to items with appointment time in range of given appointment
407    */
408    public function withTimeRangeByAppointment(\BO\Zmsentities\Appointment $appointment)
409    {
410        $processList = new self();
411        if ($this->count()) {
412            foreach ($this as $process) {
413                if (
414                    $appointment->getEndTime() > $process->getFirstAppointment()->getStartTime() &&
415                    $appointment->getStartTime() < $process->getFirstAppointment()->getEndTime()
416                ) {
417                    $processList->addEntity(clone $process);
418                }
419            }
420        }
421        return $processList;
422    }
423}