Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
86.26% covered (warning)
86.26%
270 / 313
70.15% covered (warning)
70.15%
47 / 67
CRAP
0.00% covered (danger)
0.00%
0 / 1
Process
86.26% covered (warning)
86.26%
270 / 313
70.15% covered (warning)
70.15%
47 / 67
203.03
0.00% covered (danger)
0.00%
0 / 1
 getDefaults
100.00% covered (success)
100.00%
21 / 21
100.00% covered (success)
100.00%
1 / 1
1
 createFromScope
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
1
 getRequests
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
4
 getRequestIds
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getRequestCSV
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 addScope
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 addQueue
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
 addRequests
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
3
 updateRequests
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
3
 hasScopeAdmin
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 sendAdminMailOnConfirmation
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 sendAdminMailOnDeleted
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 sendAdminMailOnUpdated
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 shouldSendAdminMailOnClerkMail
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 withUpdatedData
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
3
 addAppointmentFromRequest
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
4
 addClientFromForm
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
5
 setStatus
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getStatus
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getReminderTimestamp
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 addReminderTimestamp
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 getAppointments
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
4
 getClients
83.33% covered (warning)
83.33%
5 / 6
0.00% covered (danger)
0.00%
0 / 1
4.07
 hasAppointment
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 isWithAppointment
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 hasProcessCredentials
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
4
 withReassignedCredentials
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 hasQueueNumber
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
3
 addAppointment
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getScopeId
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getCurrentScope
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getAmendment
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getShowUpTime
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
6
 getWaitingTime
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getProcessingTime
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getFinishTime
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 addAmendment
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
3
 getCustomTextfield
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 addCustomTextfield
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
3
 getCustomTextfield2
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 addCustomTextfield2
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
3
 getAuthKey
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setRandomAuthKey
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setCallTime
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 getCallTimeString
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getCallTime
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 getFirstClient
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 getFirstAppointment
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
2
 setStatusBySettings
88.89% covered (warning)
88.89%
8 / 9
0.00% covered (danger)
0.00%
0 / 1
5.03
 setClientsCount
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 withoutPersonalData
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
2
 withLessData
100.00% covered (success)
100.00%
30 / 30
100.00% covered (success)
100.00%
1 / 1
20
 toCalendar
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
1
 toQueue
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
5
 hasArrivalTime
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 getArrivalTime
72.73% covered (warning)
72.73%
8 / 11
0.00% covered (danger)
0.00%
0 / 1
4.32
 setArrivalTime
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
6
 getWaitedSeconds
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getWaitedMinutes
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getWaySeconds
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getWayMinutes
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setWasMissed
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 getWasMissed
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 toDerefencedAmendment
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
1
 toDerefencedCustomTextfield
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
2
 toDerefencedCustomTextfield2
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
2
 __toString
100.00% covered (success)
100.00%
15 / 15
100.00% covered (success)
100.00%
1 / 1
4
1<?php
2
3namespace BO\Zmsentities;
4
5use BO\Zmsentities\Helper\Property;
6
7/**
8 * @SuppressWarnings(Complexity)
9 * @SuppressWarnings(Coupling)
10 * @SuppressWarnings(Public)
11 *
12 */
13class Process extends Schema\Entity
14{
15    public const PRIMARY = 'id';
16    public const STATUS_FREE = 'free';
17    public const STATUS_RESERVED = 'reserved';
18    public const STATUS_CONFIRMED = 'confirmed';
19    public const STATUS_PRECONFIRMED = 'preconfirmed';
20    public const STATUS_QUEUED = 'queued';
21    public const STATUS_CALLED = 'called';
22    public const STATUS_PROCESSING = 'processing';
23    public const STATUS_PENDING = 'pending';
24    public const STATUS_PICKUP = 'pickup';
25    public const STATUS_FINISHED = 'finished';
26    public const STATUS_MISSED = 'missed';
27    public const STATUS_PARKED = 'parked';
28    public const STATUS_ARCHIVED = 'archived';
29    public const STATUS_DELETED = 'deleted';
30    public const STATUS_ANONYMIZED = 'anonymized';
31    public const STATUS_BLOCKED = 'blocked';
32    public const STATUS_CONFLICT = 'conflict';
33    public static $schema = "process.json";
34    public function getDefaults()
35    {
36        return [
37            'amendment' => '',
38            'customTextfield' => '',
39            'customTextfield2' => '',
40            'appointments' => new Collection\AppointmentList(),
41            'apiclient' => new Apiclient(),
42            'authKey' => '',
43            'captchaToken' => '',
44            'clients' => new Collection\ClientList(),
45            'createIP' => '',
46            'createTimestamp' => time(),
47            'id' => 0,
48            'archiveId' => 0,
49            'queue' => new Queue(),
50            'reminderTimestamp' => 0,
51            'requests' => new Collection\RequestList(),
52            'scope' => new Scope(),
53            'status' => 'free',
54            'lastChange' => time(),
55            'wasMissed' => false,
56        ];
57    }
58
59    public static function createFromScope(Scope $scope, \DateTimeInterface $dateTime)
60    {
61        $appointment = new Appointment();
62        $appointment->addScope($scope->id);
63        $appointment->addSlotCount(0);
64        $appointment->addDate($dateTime->modify('00:00:00')->getTimestamp());
65        $process = new static();
66        $process->scope = $scope;
67        $process->setStatus('queued');
68        $process->addAppointment($appointment);
69        return $process;
70    }
71
72    /**
73     * @return Collection\RequestList
74     *
75     */
76    public function getRequests()
77    {
78        if (!$this->requests instanceof Collection\RequestList) {
79            $requestList = new Collection\RequestList();
80            foreach ($this->requests as $request) {
81                $request = ($request instanceof Request) ? $request : new Request($request);
82                $requestList->addEntity($request);
83            }
84            $this->requests = $requestList;
85        }
86        return $this->requests;
87    }
88
89    public function getRequestIds()
90    {
91        return $this->getRequests()->getIds();
92    }
93
94    public function getRequestCSV()
95    {
96        return $this->getRequests()->getIdsCsv();
97    }
98
99    public function addScope($scopeId)
100    {
101        $this->scope = new Scope(array('id' => $scopeId));
102        return $this;
103    }
104
105    public function addQueue($number, \DateTimeInterface $dateTime)
106    {
107        $this->queue = new Queue(array(
108            'number' => $number,
109            'arrivalTime' => $dateTime->getTimestamp()
110        ));
111        return $this;
112    }
113
114    public function addRequests($source, $requestCSV)
115    {
116        $requestList = $this->getRequests();
117        foreach (explode(',', $requestCSV) as $id) {
118            if (!$requestList->hasRequests($id)) {
119                $this->requests[] = new Request(array(
120                    'source' => $source,
121                    'id' => $id
122                ));
123            }
124        }
125        return $this;
126    }
127
128    public function updateRequests($source, $requestCSV = '')
129    {
130        $this->requests = new Collection\RequestList();
131        if ($requestCSV) {
132            foreach (explode(',', $requestCSV) as $id) {
133                $this->requests->addEntity(new Request(array(
134                            'source' => $source,
135                            'id' => $id
136                        )));
137            }
138        }
139        return $this;
140    }
141
142    public function hasScopeAdmin()
143    {
144        return ('' != $this->toProperty()->scope->contact->email->get());
145    }
146
147    public function sendAdminMailOnConfirmation()
148    {
149        return (bool) ((int) $this->toProperty()->scope->preferences->client->adminMailOnAppointment->get());
150    }
151
152    public function sendAdminMailOnDeleted()
153    {
154        return (bool) ((int) $this->toProperty()->scope->preferences->client->adminMailOnDeleted->get());
155    }
156
157    public function sendAdminMailOnUpdated()
158    {
159        return (bool) ((int) $this->toProperty()->scope->preferences->client->adminMailOnUpdated->get());
160    }
161
162    public function shouldSendAdminMailOnClerkMail()
163    {
164        return (bool) ((int) $this->toProperty()->scope->preferences->client->adminMailOnMailSent->get());
165    }
166
167    public function withUpdatedData($requestData, \DateTimeInterface $dateTime, $scope = null, $notice = '')
168    {
169        $this->scope = ($scope) ? $scope : $this->scope;
170        $this->addAppointmentFromRequest($requestData, $dateTime);
171        $requestCsv = isset($requestData['requests']) ? implode(',', $requestData['requests']) : 0;
172        $this->updateRequests($scope->getSource(), $requestCsv);
173        $this->addClientFromForm($requestData);
174        $this->addReminderTimestamp($requestData, $dateTime);
175        $this->addAmendment($requestData, $notice);
176        $this->addCustomTextfield($requestData, $notice);
177        $this->addCustomTextfield2($requestData, $notice);
178        return $this;
179    }
180
181    public function addAppointmentFromRequest($requestData, \DateTimeInterface $dateTime)
182    {
183        $this->appointments = null;
184        if (isset($requestData['selecteddate'])) {
185            $dateTime = new \DateTime($requestData['selecteddate']);
186        }
187        if (isset($requestData['selectedtime'])) {
188            $time = explode('-', $requestData['selectedtime']);
189            $dateTime->setTime($time[0], $time[1]);
190        }
191
192        $appointment = (new Appointment())
193            ->addDate($dateTime->getTimestamp())
194            ->addScope($this->scope['id']);
195        if (isset($requestData['slotCount'])) {
196            $appointment->addSlotCount($requestData['slotCount']);
197        }
198        $this->addAppointment($appointment);
199        return $this;
200    }
201
202    public function addClientFromForm($requestData)
203    {
204        $client = new Client();
205        foreach ($requestData as $key => $value) {
206            if (null !== $value && $client->offsetExists($key)) {
207                $client[$key] = (isset($value['value'])) ? $value['value'] : $value;
208            }
209        }
210        $this->clients = array();
211        $this->clients[] = $client;
212        return $this;
213    }
214
215    public function setStatus($status)
216    {
217        $this->status = $status;
218        return $this;
219    }
220
221    public function getStatus()
222    {
223        return $this->status;
224    }
225
226    public function getReminderTimestamp()
227    {
228        $timestamp = $this->toProperty()->reminderTimestamp->get();
229        return ($timestamp) ? $timestamp : 0;
230    }
231
232    public function addReminderTimestamp($input, \DateTimeInterface $dateTime)
233    {
234        $this->reminderTimestamp = (
235            Property::__keyExists('headsUpTime', $input) &&
236            $input['headsUpTime'] > 0
237        ) ? $dateTime->getTimestamp() - $input['headsUpTime'] : 0;
238        return $this;
239    }
240
241    /**
242     * @return \BO\Zmsentities\Collection\AppointmentList
243     *
244     */
245    public function getAppointments()
246    {
247        if (!$this['appointments'] instanceof Collection\AppointmentList) {
248            $this['appointments'] = new Collection\AppointmentList($this['appointments']);
249            foreach ($this['appointments'] as $index => $appointment) {
250                if (!$appointment instanceof Appointment) {
251                    $this['appointments'][$index] = new Appointment($appointment);
252                }
253            }
254        }
255        return $this['appointments'];
256    }
257
258    /**
259     * @return \BO\Zmsentities\Collection\ClientList
260     *
261     */
262    public function getClients()
263    {
264        if (!$this['clients'] instanceof Collection\ClientList) {
265            $this['clients'] = new Collection\ClientList($this['clients']);
266            foreach ($this['clients'] as $index => $client) {
267                if (!$client instanceof Client) {
268                    $this['clients'][$index] = new Client($client);
269                }
270            }
271        }
272        return $this['clients'];
273    }
274
275    public function hasAppointment($date, $scopeId)
276    {
277        return $this->getAppointments()->hasDateScope($date, $scopeId);
278    }
279
280    /**
281     * check if process is with appointment and not only queued
282     * return Boolean
283     */
284    public function isWithAppointment()
285    {
286        $appointment = $this->getFirstAppointment();
287        if ($appointment->hasTime()) {
288            return true;
289        }
290        return (1 == $this->toProperty()->queue->withAppointment->get());
291    }
292
293    public function hasProcessCredentials()
294    {
295        return (isset($this['id']) && isset($this['authKey']) && $this['id'] && $this['authKey']);
296    }
297
298    public function withReassignedCredentials($process)
299    {
300        $this->id = $process->getId();
301        $this->authKey = $process->getAuthKey();
302        return $this;
303    }
304
305    public function hasQueueNumber()
306    {
307        return (isset($this['queue']) && isset($this['queue']['number']) && $this['queue']['number']);
308    }
309
310    public function addAppointment(Appointment $newappointment)
311    {
312        $this->appointments[] = $newappointment;
313        return $this;
314    }
315
316    /**
317     * Reminder: A process might have multiple scopes. Each appointment can
318     * have his own scope. The scope in $this->scope is the current/next scope.
319     * This function returns the original scope ID and ignores internal scope
320     * which are used for processing like to pick up documents
321     *
322     */
323    public function getScopeId()
324    {
325        //TK 2020-09-28 changed because pickup and pending processes have assigned pickup scope
326        //as current scope - see zmsdb Query/Process EntityMapping
327        return $this->toProperty()->scope->id->get();
328    }
329
330    public function getCurrentScope(): Scope
331    {
332        return $this->getProperty('scope');
333    }
334
335    public function getAmendment()
336    {
337        return $this->toProperty()->amendment->get();
338    }
339
340    /*public function getShowUpTime()
341    {
342        return $this->toProperty()->showUpTime->get();
343    }*/
344
345    public function getShowUpTime($default = 'now', $timezone = null)
346    {
347        $showUpTime = $this->toProperty()->showUpTime->get();
348        $showDateTime = Helper\DateTime::create($default, $timezone);
349        if ($showUpTime) {
350            list($hours, $minutes, $seconds) = explode(':', $showUpTime);
351            $showDateTime = $showDateTime->setTime(intval($hours), intval($minutes), intval($seconds));
352        }
353        return $showDateTime;
354    }
355
356    public function getWaitingTime()
357    {
358        return $this->toProperty()->queue->waitingTime->get();
359    }
360
361    public function getProcessingTime()
362    {
363        return $this->toProperty()->processingTime->get();
364    }
365
366    public function getFinishTime()
367    {
368        return $this->toProperty()->finishTime->get();
369    }
370
371    public function addAmendment($input, $notice = '')
372    {
373        $this->amendment = $notice;
374        $this->amendment .= (isset($input['amendment']) && $input['amendment']) ? $input['amendment'] : '';
375        trim($this->amendment);
376        return $this;
377    }
378
379    public function getCustomTextfield()
380    {
381        return $this->toProperty()->customTextfield->get();
382    }
383
384    public function addCustomTextfield($input, $notice = '')
385    {
386        $this->customTextfield = $notice;
387        $this->customTextfield .= (
388            isset($input['customTextfield']) && $input['customTextfield']
389        ) ? $input['customTextfield'] : '';
390        trim($this->customTextfield);
391        return $this;
392    }
393
394    public function getCustomTextfield2()
395    {
396        return $this->toProperty()->customTextfield2->get();
397    }
398
399    public function addCustomTextfield2($input, $notice = '')
400    {
401        $this->customTextfield2 = $notice;
402        $this->customTextfield2 .= (
403            isset($input['customTextfield2']) && $input['customTextfield2']
404        ) ? $input['customTextfield2'] : '';
405        trim($this->customTextfield2);
406        return $this;
407    }
408
409    public function getAuthKey()
410    {
411        return $this->toProperty()->authKey->get();
412    }
413
414    public function setRandomAuthKey()
415    {
416        $this->authKey = substr(md5(rand()), 0, 4);
417    }
418
419    public function setCallTime($dateTime = null)
420    {
421        $this->queue['callTime'] = ($dateTime) ? $dateTime->getTimestamp() : 0;
422        return $this;
423    }
424
425    public function getCallTimeString()
426    {
427        return $this->getCallTime()->format('H:i:s');
428    }
429
430    public function getCallTime($default = 'now', $timezone = null)
431    {
432        $callTime = $this->toProperty()->queue->callTime->get();
433        $callDateTime = Helper\DateTime::create($default, $timezone);
434        if ($callTime) {
435            $callDateTime = $callDateTime->setTimestamp($callTime);
436        }
437        return $callDateTime;
438    }
439
440    public function getFirstClient()
441    {
442        $client = $this->getClients()->getFirst();
443        if (!$client) {
444            $client = new Client();
445            $this->clients->addEntity($client);
446        }
447        return $client;
448    }
449
450    public function getFirstAppointment(): Appointment
451    {
452        $appointment = $this->getAppointments()->getFirst();
453        if (!$appointment) {
454            $appointment = new Appointment();
455            $appointment->scope = $this->scope;
456            $this->appointments->addEntity($appointment);
457        }
458        return $appointment;
459    }
460
461    public function setStatusBySettings()
462    {
463        $scope = new Scope($this->scope);
464        if ('called' == $this->status && $this->queue['callCount'] > $scope->getPreference('queue', 'callCountMax')) {
465            $this->status = 'missed';
466        } elseif ('parked' == $this->status) {
467            $this->status = 'parked';
468        } elseif ('pickup' == $this->status) {
469            $this->status = 'queued';
470        } else {
471            $this->status = 'confirmed';
472        }
473        return $this;
474    }
475
476    public function setClientsCount($count)
477    {
478        $clientList = $this->getClients();
479        while ($clientList->count() < $count) {
480            $clientList->addEntity(new Client());
481        }
482        return $this;
483    }
484
485
486    public function withoutPersonalData()
487    {
488        $entity = clone $this;
489        if ($this->toProperty()->clients->isAvailable()) {
490            $client = $entity->getFirstClient();
491            unset($client['familyName']);
492            unset($client['email']);
493        }
494        return $entity;
495    }
496
497    /**
498     * Reduce data of dereferenced entities to a required minimum
499     *
500     */
501    public function withLessData(array $keepArray = [])
502    {
503        $entity = clone $this;
504        if (!in_array('availability', $keepArray)) {
505            foreach ($entity['appointments'] as $appointment) {
506                if ($appointment->toProperty()->scope->isAvailable()) {
507                    $scopeId = $appointment['scope']['id'];
508                    $appointment['scope'] = [
509                        'id' => $scopeId,
510                        'provider' => $appointment['scope']['provider'] ?? [],
511                        'shortName' => $appointment['scope']['shortName'] ?? ''
512                    ];
513                }
514                if ($appointment->toProperty()->availability->isAvailable()) {
515                    unset($appointment['availability']);
516                }
517            }
518        }
519
520        unset($entity['createTimestamp']);
521        unset($entity['createIP']);
522        if ($entity->toProperty()->scope->status->isAvailable()) {
523            unset($entity['scope']['status']);
524        }
525
526        if ($entity->status == 'free') {
527// delete keys
528            foreach (['authKey', 'queue', 'requests',] as $key) {
529                if (!in_array($key, $keepArray) && $entity->toProperty()->$key->isAvailable()) {
530                    unset($entity[$key]);
531                }
532            }
533            // delete if empty
534            foreach (['amendment', 'id', 'authKey', 'archiveId', 'reminderTimestamp',] as $key) {
535                if (!in_array($key, $keepArray) && $entity->toProperty()->$key->isAvailable() && !$entity[$key]) {
536                    unset($entity[$key]);
537                }
538            }
539            if (!in_array('provider', $keepArray) && $entity->toProperty()->scope->provider->data->isAvailable()) {
540                unset($entity['scope']['provider']['data']);
541            }
542        }
543
544        if (!in_array('dayoff', $keepArray) && $entity->toProperty()->scope->dayoff->isAvailable()) {
545            unset($entity['scope']['dayoff']);
546        }
547        if (!in_array('scope', $keepArray) && $entity->toProperty()->scope->preferences->isAvailable()) {
548            unset($entity['scope']['preferences']);
549        }
550        return $entity;
551    }
552
553    public function toCalendar()
554    {
555        $calendar = new Calendar();
556        $dateTime = $this->getFirstAppointment()->toDateTime();
557        $day = new Day();
558        $day->setDateTime($dateTime);
559        $calendar->firstDay = $day;
560        $calendar->lastDay = $day;
561        $calendar->requests = clone $this->getRequests();
562        $calendar->scopes = new Collection\ScopeList([$this->scope]);
563        return $calendar;
564    }
565
566    public function toQueue(\DateTimeInterface $dateTime)
567    {
568        $queue = new Queue($this->queue);
569        $queue->withAppointment = ($this->getFirstAppointment()->hasTime()) ? true : false;
570        $queue->waitingTime = ($queue->waitingTime) ? $queue->waitingTime : 0;
571        $queue->wayTime = ($queue->wayTime) ? $queue->wayTime : 0;
572        if ($queue->withAppointment) {
573            $queue->number = $this->id;
574        } else {
575            $queue->number = $this->toProperty()->queue->number->get();
576        }
577        $queue->arrivalTime = $this->getArrivalTime($dateTime)->getTimestamp();
578        return $queue->setProcess($this);
579    }
580
581    public function hasArrivalTime()
582    {
583        $arrivalTime = 0;
584        if ($this->isWithAppointment()) {
585            $arrivalTime = $this->getFirstAppointment()->date;
586        } else {
587            $arrivalTime = $this->toProperty()->queue->arrivalTime->get();
588        }
589        return ($arrivalTime) ? true : false;
590    }
591
592    public function getArrivalTime($default = 'now', $timezone = null)
593    {
594        $queueArrivalTime = $this->toProperty()->queue->arrivalTime->get();
595
596        if ($queueArrivalTime) {
597            // Falls der Queue-Wert vorhanden ist – auch wenn ein Termin existiert – verwende diesen (dabei ist handelt es sich, um verpasste Termine)
598            $arrivalTime = $queueArrivalTime;
599        } elseif ($this->isWithAppointment()) {
600            $arrivalTime = $this->getFirstAppointment()->date;
601        } else {
602            $arrivalTime = 0;
603        }
604
605        $arrivalTime = (int)$arrivalTime;
606        $arrivalDateTime = Helper\DateTime::create($default, $timezone);
607        if ($arrivalTime) {
608            $arrivalDateTime = $arrivalDateTime->setTimestamp($arrivalTime);
609        }
610        return $arrivalDateTime;
611    }
612
613    public function setArrivalTime(\DateTimeInterface $dateTime = null)
614    {
615        $this->queue['arrivalTime'] = ($dateTime) ? $dateTime->getTimestamp() : 0;
616        return $this;
617    }
618
619    /**
620     * Calculate real waiting time, only available after called
621     */
622    public function getWaitedSeconds($defaultTime = 'now')
623    {
624        return $this->getCallTime($defaultTime)->getTimestamp() - $this->getArrivalTime($defaultTime)->getTimestamp();
625    }
626
627    public function getWaitedMinutes($defaultTime = 'now')
628    {
629        return $this->getWaitedSeconds($defaultTime) / 60;
630    }
631
632    public function getWaySeconds($defaultTime = 'now')
633    {
634        return $this->getShowUpTime($defaultTime)->getTimestamp() - $this->getCallTime($defaultTime)->getTimestamp();
635    }
636
637    public function getWayMinutes($defaultTime = 'now')
638    {
639        return $this->getWaySeconds($defaultTime) / 60;
640    }
641
642    public function setWasMissed(bool $bool)
643    {
644        $this->wasMissed = $bool;
645        return $this;
646    }
647
648    public function getWasMissed(): bool
649    {
650        return (bool) $this->wasMissed;
651    }
652
653    public function toDerefencedAmendment()
654    {
655        $lastChange = (new \DateTimeImmutable())->setTimestamp($this->createTimestamp)->format('c');
656        return var_export(array(
657                'BuergerID' => $this->id,
658                'StandortID' => $this->scope['id'],
659                'Anmerkung' => null,
660                'IPTimeStamp' => $this->createTimestamp,
661                'LastChange' => $lastChange,
662            ), 1);
663    }
664
665    public function toDerefencedCustomTextfield()
666    {
667        $lastChange = (new \DateTimeImmutable())->setTimestamp($this->createTimestamp)->format('c');
668        return var_export(array(
669                'BuergerID' => $this->id,
670                'StandortID' => $this->scope['id'],
671                'CustomTextfield' => null,
672                'IPTimeStamp' => $this->createTimestamp,
673                'LastChange' => $lastChange,
674            ), 1);
675    }
676
677    public function toDerefencedCustomTextfield2()
678    {
679        $lastChange = (new \DateTimeImmutable())->setTimestamp($this->createTimestamp)->format('c');
680        return var_export(array(
681                'BuergerID' => $this->id,
682                'StandortID' => $this->scope['id'],
683                'CustomTextfield2' => null,
684                'IPTimeStamp' => $this->createTimestamp,
685                'LastChange' => $lastChange,
686            ), 1);
687    }
688
689    public function __toString()
690    {
691        $string = "process#";
692        $string .= $this->id ?: $this->archiveId;
693        $string .= ":" . $this->authKey;
694        $string .= " (" . $this->status . ")";
695        $string .= " " . $this->getFirstAppointment()->toDateTime()->format('c');
696        $string .= " " . ($this->isWithAppointment() ? "appoint" : "arrival:" . $this->getArrivalTime()->format('c'));
697        $string .= " " . $this->getFirstAppointment()->slotCount . "slots";
698        $string .= "*" . count($this->appointments);
699        foreach ($this->getRequests() as $request) {
700            $string .= " " . $request['source'] . "." . $request['id'];
701        }
702        $string .= " scope." . $this['scope']['id'];
703        $string .= " ~" . base_convert($this['lastChange'], 10, 35);
704        $string .= " client:" . $this['apiclient']['shortname'];
705        $string .= " token:" . ($this['captchaToken'] ?? '(none)');
706        return $string;
707    }
708}