Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
73.66% covered (warning)
73.66%
151 / 205
64.52% covered (warning)
64.52%
20 / 31
CRAP
0.00% covered (danger)
0.00%
0 / 1
ProcessList
73.66% covered (warning)
73.66%
151 / 205
64.52% covered (warning)
64.52%
20 / 31
242.36
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
 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 withDepartmentHasMailFrom()
226    {
227        $processList = new static();
228        foreach ($this as $process) {
229            if ($process->scope->hasEmailFrom()) {
230                $entity = clone $process;
231                $processList->addEntity($entity);
232            }
233        }
234        return $processList;
235    }
236
237
238
239    public function setConflictAmendment()
240    {
241        foreach ($this as $process) {
242            $process->amendment = 'Die Slots für diesen Zeitraum wurden Ã¼berbucht';
243            if (! $process->getFirstAppointment()->availability->hasId()) {
244                $process->amendment = sprintf(
245                    'Der Vorgang (%s) befindet sich außerhalb der Ã–ffnungszeit!',
246                    $process->getId()
247                );
248            }
249        }
250        return $this;
251    }
252
253    public function withOutAvailability(\BO\Zmsentities\Collection\AvailabilityList $availabilityList)
254    {
255        $processList = new static();
256        foreach ($this->toProcessListByTime('Y-m-d') as $processListByDate) {
257            $dateTime = $processListByDate[0]->getFirstAppointment()->toDateTime();
258            $slotList = $availabilityList->withType('appointment')->withDateTime($dateTime)->getSlotList();
259            foreach ($processListByDate as $process) {
260                try {
261                    $slotList->withSlotsForAppointment($process->getFirstAppointment());
262                    if (!$slotList->removeAppointment($process->getFirstAppointment())) {
263                        $process->amendment = "";
264                        $processList[] = clone $process;
265                    }
266                } catch (\BO\Zmsentities\Exception\AppointmentNotFitInSlotList $exception) {
267                    $process->amendment = "";
268                    $processList[] = clone $process;
269                }
270            }
271        }
272        return $processList;
273    }
274
275    public function withUniqueScope($oncePerHour = false)
276    {
277        $processList = new static();
278        $scopeKeyList = [];
279        foreach ($this as $process) {
280            $scopeKey = $process->scope->id . '-';
281            if ($oncePerHour) {
282                $scopeKey .= $process->getFirstAppointment()->toDateTime()->format('H');
283            } else {
284                $scopeKey .= $process->getFirstAppointment()->toDateTime()->format('H:i');
285            }
286            if (!in_array($scopeKey, $scopeKeyList)) {
287                $processList[] = clone $process;
288                $scopeKeyList[] = $scopeKey;
289            }
290        }
291        return $processList;
292    }
293
294    public function withAccess(\BO\Zmsentities\Useraccount $useraccount)
295    {
296        $list = new static();
297        foreach ($this as $process) {
298            $process = clone $process;
299            if ($process->getCurrentScope()->hasAccess($useraccount)) {
300                $list[] = $process;
301            }
302        }
303        return $list;
304    }
305
306    public function withScopeId($scopeId)
307    {
308        $processList = new static();
309        foreach ($this as $process) {
310            if ($scopeId == $process->scope['id']) {
311                $processList[] = clone $process;
312            }
313        }
314        return $processList;
315    }
316
317    public function withOutScopeId($scopeId)
318    {
319        $processList = new static();
320        foreach ($this as $process) {
321            if ($scopeId != $process->scope['id']) {
322                $processList[] = clone $process;
323            }
324        }
325        return $processList;
326    }
327
328    public function withOutProcessId($processId)
329    {
330        $processList = new static();
331        foreach ($this as $process) {
332            if ($processId != $process->getId()) {
333                $processList[] = clone $process;
334            }
335        }
336        return $processList;
337    }
338
339    public function withoutExpiredAppointmentDate(\DateTimeInterface $now)
340    {
341        $conflictList = new self();
342        foreach ($this as $process) {
343            if ($process->getFirstAppointment()->date > $now->getTimestamp()) {
344                $conflictList->addEntity(clone $process);
345            }
346        }
347        return $conflictList;
348    }
349
350    public function withinExactDate(\DateTimeInterface $now)
351    {
352        $processList = new self();
353        foreach ($this as $process) {
354            if ($process->getFirstAppointment()->toDateTime()->format('Y-m-d') == $now->format('Y-m-d')) {
355                $processList->addEntity(clone $process);
356            }
357        }
358        return $processList;
359    }
360
361    public function withoutDublicatedConflicts()
362    {
363        $collection = new self();
364        foreach ($this as $conflict) {
365            if (! $collection->getAppointmentList()->hasAppointment($conflict->getFirstAppointment())) {
366                $collection->addEntity(clone $conflict);
367            }
368        }
369        return $collection;
370    }
371
372    public function testProcessListLength($processList, bool $isEmptyAllowed = false): ProcessList
373    {
374        $collection = ($processList instanceof Process) ?
375            (new self())->addEntity($processList) :
376            $processList;
377
378        if (0 === $collection->count() && ! $isEmptyAllowed) {
379            throw new \BO\Zmsentities\Exception\ProcessListEmpty();
380        }
381        return $collection;
382    }
383
384    public function withoutProcessByStatus($process, $status)
385    {
386        $collection = clone $this;
387        $collection = (1 <= $collection->count() && ! Messaging::isEmptyProcessListAllowed($status)) ?
388            $collection->withOutProcessId($process->getId()) :
389            $collection;
390        return $collection;
391    }
392
393    /*
394    * reduce process list to items with appointment time in range of given appointment
395    */
396    public function withTimeRangeByAppointment(\BO\Zmsentities\Appointment $appointment)
397    {
398        $processList = new self();
399        if ($this->count()) {
400            foreach ($this as $process) {
401                if (
402                    $appointment->getEndTime() > $process->getFirstAppointment()->getStartTime() &&
403                    $appointment->getStartTime() < $process->getFirstAppointment()->getEndTime()
404                ) {
405                    $processList->addEntity(clone $process);
406                }
407            }
408        }
409        return $processList;
410    }
411}