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