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 */
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                $availability = $appointment->getAvailability();
121                $availabilityId = $availability->getId()
122                    ? $availability->getId()
123                    : ($availability['tempId'] ?? null);
124                $appointmentList[] = [
125                    'startTime' => $appointment->getStartTime()->format('H:i'),
126                    'endTime' => $appointment->getEndTime()->format('H:i'),
127                    'availability' => $availabilityId
128                ];
129            }
130            $list[$process->getFirstAppointment()->getStartTime()->format('Y-m-d')][] = [
131                'message' => $process->amendment,
132                'appointments' => $appointmentList
133            ];
134        }
135        return $list;
136    }
137
138    public function getScopeList()
139    {
140        $list = new ScopeList();
141        foreach ($this as $process) {
142            if (Property::__keyExists('scope', $process)) {
143                $list[] = new \BO\Zmsentities\Scope($process['scope']);
144            }
145        }
146        return $list->withUniqueScopes();
147    }
148
149    public function getRequestList()
150    {
151        $list = new RequestList();
152        foreach ($this as $process) {
153            if (Property::__keyExists('requests', $process)) {
154                $list->addList($process->getRequests());
155            }
156        }
157        return $list->withUniqueRequests();
158    }
159
160    public function getAppointmentList()
161    {
162        $appointmentList = new AppointmentList();
163        foreach ($this as $process) {
164            if (Property::__keyExists('appointments', $process)) {
165                foreach ($process["appointments"] as $appointment) {
166                    $appointmentList->addEntity(new \BO\Zmsentities\Appointment($appointment));
167                }
168            }
169        }
170        return $appointmentList;
171    }
172
173    public function setTempAppointmentToProcess($dateTime, $scopeId)
174    {
175        $addedAppointment = false;
176        $appointment = (new \BO\Zmsentities\Appointment())->addDate($dateTime->getTimestamp())->addScope($scopeId);
177        foreach ($this as $process) {
178            if ($process->hasAppointment($dateTime->getTimestamp(), $scopeId) && !$addedAppointment) {
179                $entity = clone $process;
180                $this->addEntity($entity);
181                $addedAppointment = true;
182            }
183        }
184        if (!$addedAppointment) {
185            $entity = new \BO\Zmsentities\Process();
186            $entity->addAppointment($appointment);
187            $this->addEntity($entity);
188        }
189        return $this;
190    }
191
192    public function toQueueList($now)
193    {
194        $queueList = new QueueList();
195        foreach ($this as $process) {
196            $queue = $process->toQueue($now);
197            $queueList->addEntity($queue);
198        }
199        $queueList->setTransferedProcessList(true);
200        return $queueList;
201    }
202
203    public function withAvailability(\BO\Zmsentities\Availability $availability)
204    {
205        $processList = new static();
206        foreach ($this as $process) {
207            if ($availability->hasAppointment($process->getFirstAppointment())) {
208                $processList[] = clone $process;
209            }
210        }
211        return $processList;
212    }
213
214    public function withAvailabilityStrict(\BO\Zmsentities\Availability $availability)
215    {
216        $processList = new static();
217        $slotList = $availability->getSlotList();
218        foreach ($this as $process) {
219            if ($slotList->removeAppointment($process->getFirstAppointment())) {
220                $processList[] = clone $process;
221            }
222        }
223        return $processList;
224    }
225
226    public function withDepartmentHasMailFrom()
227    {
228        $processList = new static();
229        foreach ($this as $process) {
230            if ($process->scope->hasEmailFrom()) {
231                $entity = clone $process;
232                $processList->addEntity($entity);
233            }
234        }
235        return $processList;
236    }
237
238
239
240    public function setConflictAmendment()
241    {
242        foreach ($this as $process) {
243            $process->amendment = 'Die Slots für diesen Zeitraum wurden Ã¼berbucht';
244            if (! $process->getFirstAppointment()->availability->hasId()) {
245                $process->amendment = sprintf(
246                    'Der Vorgang (%s) befindet sich außerhalb der Ã–ffnungszeit!',
247                    $process->getId()
248                );
249            }
250        }
251        return $this;
252    }
253
254    public function withOutAvailability(\BO\Zmsentities\Collection\AvailabilityList $availabilityList)
255    {
256        $processList = new static();
257        foreach ($this->toProcessListByTime('Y-m-d') as $processListByDate) {
258            $dateTime = $processListByDate[0]->getFirstAppointment()->toDateTime();
259            $slotList = $availabilityList->withType('appointment')->withDateTime($dateTime)->getSlotList();
260            foreach ($processListByDate as $process) {
261                try {
262                    $slotList->withSlotsForAppointment($process->getFirstAppointment());
263                    if (!$slotList->removeAppointment($process->getFirstAppointment())) {
264                        $process->amendment = "";
265                        $processList[] = clone $process;
266                    }
267                } catch (\BO\Zmsentities\Exception\AppointmentNotFitInSlotList $exception) {
268                    $process->amendment = "";
269                    $processList[] = clone $process;
270                }
271            }
272        }
273        return $processList;
274    }
275
276    public function withUniqueScope($oncePerHour = false)
277    {
278        $processList = new static();
279        $scopeKeyList = [];
280        foreach ($this as $process) {
281            $scopeKey = $process->scope->id . '-';
282            if ($oncePerHour) {
283                $scopeKey .= $process->getFirstAppointment()->toDateTime()->format('H');
284            } else {
285                $scopeKey .= $process->getFirstAppointment()->toDateTime()->format('H:i');
286            }
287            if (!in_array($scopeKey, $scopeKeyList)) {
288                $processList[] = clone $process;
289                $scopeKeyList[] = $scopeKey;
290            }
291        }
292        return $processList;
293    }
294
295    public function withAccess(\BO\Zmsentities\Useraccount $useraccount)
296    {
297        $list = new static();
298        foreach ($this as $process) {
299            $process = clone $process;
300            if ($process->getCurrentScope()->hasAccess($useraccount)) {
301                $list[] = $process;
302            }
303        }
304        return $list;
305    }
306
307    public function withScopeId($scopeId)
308    {
309        $processList = new static();
310        foreach ($this as $process) {
311            if ($scopeId == $process->scope['id']) {
312                $processList[] = clone $process;
313            }
314        }
315        return $processList;
316    }
317
318    public function withOutScopeId($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 withOutProcessId($processId)
330    {
331        $processList = new static();
332        foreach ($this as $process) {
333            if ($processId != $process->getId()) {
334                $processList[] = clone $process;
335            }
336        }
337        return $processList;
338    }
339
340    public function withoutExpiredAppointmentDate(\DateTimeInterface $now)
341    {
342        $conflictList = new self();
343        foreach ($this as $process) {
344            if ($process->getFirstAppointment()->date > $now->getTimestamp()) {
345                $conflictList->addEntity(clone $process);
346            }
347        }
348        return $conflictList;
349    }
350
351    public function withinExactDate(\DateTimeInterface $now)
352    {
353        $processList = new self();
354        foreach ($this as $process) {
355            if ($process->getFirstAppointment()->toDateTime()->format('Y-m-d') == $now->format('Y-m-d')) {
356                $processList->addEntity(clone $process);
357            }
358        }
359        return $processList;
360    }
361
362    public function withoutDublicatedConflicts()
363    {
364        $collection = new self();
365        foreach ($this as $conflict) {
366            if (! $collection->getAppointmentList()->hasAppointment($conflict->getFirstAppointment())) {
367                $collection->addEntity(clone $conflict);
368            }
369        }
370        return $collection;
371    }
372
373    public function testProcessListLength($processList, bool $isEmptyAllowed = false): ProcessList
374    {
375        $collection = ($processList instanceof Process) ?
376            (new self())->addEntity($processList) :
377            $processList;
378
379        if (0 === $collection->count() && ! $isEmptyAllowed) {
380            throw new \BO\Zmsentities\Exception\ProcessListEmpty();
381        }
382        return $collection;
383    }
384
385    public function withoutProcessByStatus($process, $status)
386    {
387        $collection = clone $this;
388        $collection = (1 <= $collection->count() && ! Messaging::isEmptyProcessListAllowed($status)) ?
389            $collection->withOutProcessId($process->getId()) :
390            $collection;
391        return $collection;
392    }
393
394    /*
395    * reduce process list to items with appointment time in range of given appointment
396    */
397    public function withTimeRangeByAppointment(\BO\Zmsentities\Appointment $appointment)
398    {
399        $processList = new self();
400        if ($this->count()) {
401            foreach ($this as $process) {
402                if (
403                    $appointment->getEndTime() > $process->getFirstAppointment()->getStartTime() &&
404                    $appointment->getStartTime() < $process->getFirstAppointment()->getEndTime()
405                ) {
406                    $processList->addEntity(clone $process);
407                }
408            }
409        }
410        return $processList;
411    }
412}