Lines 65.46% 91 / 139
Functions and Methods 50.00% 25 / 50
Classes and Traits 0.00% 0 / 1
Name Lines Functions and Methods CRAP Classes and Traits
Scope 65.46% 91 / 139 50.00% 25 / 50 406.89 0.00% 0 / 1
 getDefaults 100.00% 8 / 8 100.00% 1 / 1 1
 getSource 100.00% 1 / 1 100.00% 1 / 1 1
 getShortName 0.00% 0 / 1 0.00% 0 / 1 2
 getEmailFrom 0.00% 0 / 1 0.00% 0 / 1 2
 getEmailRequired 0.00% 0 / 1 0.00% 0 / 1 2
 getTelephoneActivated 0.00% 0 / 1 0.00% 0 / 1 2
 getTelephoneRequired 0.00% 0 / 1 0.00% 0 / 1 2
 getCustomTextfieldActivated 0.00% 0 / 1 0.00% 0 / 1 2
 getCustomTextfieldRequired 0.00% 0 / 1 0.00% 0 / 1 2
 getCustomTextfieldLabel 0.00% 0 / 1 0.00% 0 / 1 2
 getCustomTextfield2Activated 0.00% 0 / 1 0.00% 0 / 1 2
 getCustomTextfield2Required 0.00% 0 / 1 0.00% 0 / 1 2
 getCustomTextfield2Label 0.00% 0 / 1 0.00% 0 / 1 2
 getCaptchaActivatedRequired 0.00% 0 / 1 0.00% 0 / 1 2
 getInfoForAppointment 0.00% 0 / 1 0.00% 0 / 1 2
 getInfoForAllAppointments 0.00% 0 / 1 0.00% 0 / 1 2
 getProvider 72.72% 8 / 11 0.00% 0 / 1 5.51
 getProviderId 100.00% 1 / 1 100.00% 1 / 1 1
 getDayoffList 33.33% 3 / 9 0.00% 0 / 1 12.41
 getClosureList 0.00% 0 / 9 0.00% 0 / 1 30
 getRequestList 100.00% 1 / 1 100.00% 1 / 1 1
 getPreference 100.00% 4 / 4 100.00% 1 / 1 6
 getStatus 100.00% 1 / 1 100.00% 1 / 1 1
 getContactEmail 100.00% 1 / 1 100.00% 1 / 1 1
 getName 100.00% 1 / 1 100.00% 1 / 1 1
 getScopeInfo 100.00% 1 / 1 100.00% 1 / 1 1
 getScopeHint 100.00% 1 / 1 100.00% 1 / 1 1
 getDisplayNumberPrefix 0.00% 0 / 1 0.00% 0 / 1 2
 getAlternateRedirectUrl 0.00% 0 / 2 0.00% 0 / 1 6
 isRebookingDisabled 0.00% 0 / 1 0.00% 0 / 1 2
 getAppointmentsPerMail 0.00% 0 / 2 0.00% 0 / 1 6
 getSlotsPerAppointment 0.00% 0 / 2 0.00% 0 / 1 6
 getWhitelistedMails 0.00% 0 / 2 0.00% 0 / 1 6
 getReservationDuration 0.00% 0 / 1 0.00% 0 / 1 2
 getWaitingTimeFromQueueList 100.00% 5 / 5 100.00% 1 / 1 1
 getCalculatedWorkstationCount 100.00% 6 / 6 100.00% 1 / 1 3
 getBookableStartDate 100.00% 3 / 3 100.00% 1 / 1 2
 getBookableEndDate 100.00% 3 / 3 100.00% 1 / 1 2
 updateStatusQueue 100.00% 13 / 13 100.00% 1 / 1 4
 incrementDisplayNumber 0.00% 0 / 5 0.00% 0 / 1 6
 hasEmailFrom 100.00% 2 / 2 100.00% 1 / 1 2
 isEmailRequired 100.00% 3 / 3 100.00% 1 / 1 3
 isTelephoneRequired 100.00% 2 / 2 100.00% 1 / 1 2
 hasAccess 100.00% 1 / 1 100.00% 1 / 1 2
 withProviderSourceFrom 100.00% 4 / 4 100.00% 1 / 1 1
 withLessData 100.00% 8 / 8 100.00% 1 / 1 5
 setStatusQueue 100.00% 2 / 2 100.00% 1 / 1 1
 setStatusAvailability 100.00% 2 / 2 100.00% 1 / 1 1
 isNewerThan 100.00% 1 / 1 100.00% 1 / 1 1
 __toString 100.00% 5 / 5 100.00% 1 / 1 1
1<?php
2
3namespace BO\Zmsentities;
4
5use BO\Zmsentities\Collection\ClosureList;
6use BO\Zmsentities\Collection\DayoffList;
7
8/**
9 * @SuppressWarnings(Complexity)
10 */
11class Scope extends Schema\Entity implements Useraccount\AccessInterface
12{
13    public const string PRIMARY = 'id';
14
15    public static $schema = "scope.json";
16
17    /**
18     * @return (Contact|DayoffList|Provider|int|string)[]
19     *
20     */
21    #[\Override]
22    public function getDefaults()
23    {
24        return [
25            'id' => 0,
26            'source' => 'dldb',
27            'contact' => new Contact(),
28            'provider' => new Provider(),
29            'shortName' => '',
30            'dayoff' => new DayoffList()
31        ];
32    }
33
34    public function getSource(): mixed
35    {
36        return $this->toProperty()->source->get();
37    }
38
39    public function getShortName(): mixed
40    {
41        return $this->toProperty()->shortName->get();
42    }
43
44    public function getEmailFrom(): mixed
45    {
46        return $this->getPreference('client', 'emailFrom', null);
47    }
48
49    public function getEmailRequired(): mixed
50    {
51        return $this->getPreference('client', 'emailRequired', null);
52    }
53
54    public function getTelephoneActivated(): mixed
55    {
56        return $this->getPreference('client', 'telephoneActivated', null);
57    }
58
59    public function getTelephoneRequired(): mixed
60    {
61        return $this->getPreference('client', 'telephoneRequired', null);
62    }
63
64    public function getCustomTextfieldActivated(): mixed
65    {
66        return $this->getPreference('client', 'customTextfieldActivated', null);
67    }
68
69    public function getCustomTextfieldRequired(): mixed
70    {
71        return $this->getPreference('client', 'customTextfieldRequired', null);
72    }
73
74    public function getCustomTextfieldLabel(): mixed
75    {
76        return $this->getPreference('client', 'customTextfieldLabel', '');
77    }
78
79    public function getCustomTextfield2Activated(): mixed
80    {
81        return $this->getPreference('client', 'customTextfield2Activated', null);
82    }
83
84    public function getCustomTextfield2Required(): mixed
85    {
86        return $this->getPreference('client', 'customTextfield2Required', null);
87    }
88
89    public function getCustomTextfield2Label(): mixed
90    {
91        return $this->getPreference('client', 'customTextfield2Label', '');
92    }
93
94    public function getCaptchaActivatedRequired(): mixed
95    {
96        return $this->getPreference('client', 'captchaActivatedRequired', null);
97    }
98
99    public function getInfoForAppointment(): mixed
100    {
101        return $this->getPreference('appointment', 'infoForAppointment', null);
102    }
103
104    public function getInfoForAllAppointments(): mixed
105    {
106        return $this->getPreference('appointment', 'infoForAllAppointments', null);
107    }
108
109
110    public function getProvider(): Provider
111    {
112        if (!isset($this->provider)) {
113            throw new Exception\ScopeMissingProvider("Provider is missing", 500);
114        }
115        $provider = $this->provider;
116        if (!$provider instanceof Provider) {
117            $provider = new Provider($this->toProperty()->provider->get());
118            $this->provider = $provider;
119        }
120        if (!isset($provider['id']) || !$provider->id) {
121            $exception = new Exception\ScopeMissingProvider("No reference to a provider found for scope $this->id");
122            $exception->data['scope'] = $this->getArrayCopy();
123            throw $exception;
124        }
125        return $provider;
126    }
127
128    public function getProviderId(): mixed
129    {
130        return $this->getProvider()->id;
131    }
132
133    public function getDayoffList(): DayoffList
134    {
135        $dayoff = $this->dayoff ?? [];
136        if (!$dayoff instanceof Collection\DayoffList) {
137            $dayoff = is_array($dayoff) ? $dayoff : [];
138            $dayoff = new Collection\DayoffList($dayoff);
139            foreach ($dayoff as $key => $entry) {
140                if (!$entry instanceof Dayoff) {
141                    $dayoff[$key] = new Dayoff($entry);
142                }
143            }
144            $this->dayoff = $dayoff;
145        }
146        return $dayoff;
147    }
148
149    public function getClosureList(): ClosureList
150    {
151        $closure = $this->closure ?? [];
152        if (!$closure instanceof Collection\ClosureList) {
153            $closure = is_array($closure) ? $closure : [];
154            $closure = new Collection\ClosureList($closure);
155            foreach ($closure as $key => $entry) {
156                if (!$entry instanceof Closure) {
157                    $closure[$key] = new Closure($entry);
158                }
159            }
160            $this->closure = $closure;
161        }
162        return $closure;
163    }
164
165    public function getRequestList(): \BO\Zmsentities\Collection\RequestList
166    {
167        return $this->getProvider()->getRequestList();
168    }
169
170    /**
171     * @param false|null|string $isBool
172     *
173     */
174    public function getPreference(string $preferenceKey, string $index, string|false|null $isBool = false, mixed $default = null): mixed
175    {
176        $preference = $this->toProperty()->preferences->$preferenceKey->$index->get($default);
177        return ($isBool !== false && $isBool !== null && $isBool !== '' && $isBool !== '0')
178            ? ($preference ? 1 : 0)
179            : $preference;
180    }
181
182    public function getStatus(string $statusKey, string $index): mixed
183    {
184        return $this->toProperty()->status->$statusKey->$index->get();
185    }
186
187    public function getContactEmail(): mixed
188    {
189        return $this->toProperty()->contact->email->get();
190    }
191
192    public function getName(): mixed
193    {
194        return $this->toProperty()->contact->name->get();
195    }
196
197    public function getScopeInfo(): mixed
198    {
199        return $this->toProperty()->preferences->ticketprinter->buttonName->get();
200    }
201
202    public function getScopeHint(): mixed
203    {
204        return $this->toProperty()->hint->get();
205    }
206
207    public function getDisplayNumberPrefix(): mixed
208    {
209        return $this->toProperty()->preferences->queue->displayNumberPrefix->get();
210    }
211
212    public function getAlternateRedirectUrl(): mixed
213    {
214        $alternateUrl = $this->toProperty()->preferences->client->alternateAppointmentUrl->get();
215
216        return ($alternateUrl) ? $alternateUrl : null;
217    }
218
219    public function isRebookingDisabled(): bool
220    {
221        return (bool) $this->getPreference('appointment', 'rebookingDisabled', true);
222    }
223
224    public function getAppointmentsPerMail(): mixed
225    {
226        $appointmentsPerMail = $this->toProperty()->preferences->client->appointmentsPerMail->get();
227
228        return ($appointmentsPerMail) ? $appointmentsPerMail : null;
229    }
230
231    public function getSlotsPerAppointment(): mixed
232    {
233        $slotsPerAppointment = $this->toProperty()->preferences->client->slotsPerAppointment->get();
234
235        return ($slotsPerAppointment) ? $slotsPerAppointment : null;
236    }
237
238    public function getWhitelistedMails(): mixed
239    {
240        $emails = $this->toProperty()->preferences->client->whitelistedMails->get();
241
242        return ($emails) ? $emails : '';
243    }
244
245    public function getReservationDuration(): mixed
246    {
247        return $this->toProperty()->preferences->appointment->reservationDuration->get();
248    }
249
250    public function getWaitingTimeFromQueueList(Collection\QueueList $queueList, \DateTimeInterface $dateTime): mixed
251    {
252        return $queueList->getEstimatedWaitingTime(
253            $this->getPreference('queue', 'processingTimeAverage'),
254            $this->getCalculatedWorkstationCount(),
255            $dateTime
256        );
257    }
258
259    public function getCalculatedWorkstationCount(): mixed
260    {
261        $workstationCount = null;
262        if ($this->getStatus('queue', 'workstationCount') > 0) {
263            $workstationCount = $this->getStatus('queue', 'workstationCount');
264        } elseif ($this->getStatus('queue', 'ghostWorkstationCount') > 0) {
265            $workstationCount = $this->getStatus('queue', 'ghostWorkstationCount');
266        }
267        return $workstationCount;
268    }
269
270    /**
271    * Get last bookable start date of a scope
272    *
273    * @return \DateTimeImmutable $scopeEndDate
274    */
275    public function getBookableStartDate(\DateTimeInterface $now)
276    {
277        $now = Helper\DateTime::create($now);
278        $scopeStartDate = $this->toProperty()->preferences->appointment->startInDaysDefault->get();
279        return ($scopeStartDate) ? $now->modify('+' . $scopeStartDate . 'days') : $now;
280    }
281
282    /**
283    * Get last bookable end date of a scope
284    *
285    * @return \DateTimeImmutable $scopeEndDate
286    */
287    public function getBookableEndDate(\DateTimeInterface $now)
288    {
289        $now = Helper\DateTime::create($now);
290        $scopeEndDate = $this->toProperty()->preferences->appointment->endInDaysDefault->get();
291        return ($scopeEndDate) ? $now->modify('+' . $scopeEndDate . 'days') : $now;
292    }
293
294    public function updateStatusQueue(\DateTimeInterface $dateTime): static
295    {
296        $lastQueueUpdateDate = Helper\DateTime::create()
297            ->setTimestamp($this->getStatus('queue', 'lastGivenNumberTimestamp'));
298        if ($lastQueueUpdateDate->format('Y-m-d') == $dateTime->format('Y-m-d')) {
299            $this->setStatusQueue('lastGivenNumber', $this->getStatus('queue', 'lastGivenNumber') + 1);
300            $this->setStatusQueue('givenNumberCount', $this->getStatus('queue', 'givenNumberCount') + 1);
301        } else {
302            $this->setStatusQueue('lastGivenNumber', $this->getPreference('queue', 'firstNumber'));
303            $this->setStatusQueue('givenNumberCount', 1);
304        }
305        if ($this->getStatus('queue', 'lastGivenNumber') < $this->getPreference('queue', 'firstNumber')) {
306            $this->setStatusQueue('lastGivenNumber', $this->getPreference('queue', 'firstNumber'));
307        } elseif ($this->getStatus('queue', 'lastGivenNumber') > $this->getPreference('queue', 'lastNumber')) {
308            $this->setStatusQueue('lastGivenNumber', $this->getPreference('queue', 'firstNumber'));
309        }
310        $this->setStatusQueue('lastGivenNumberTimestamp', $dateTime->getTimestamp());
311        return $this;
312    }
313
314    public function incrementDisplayNumber(): static
315    {
316        if ($this->getStatus('queue', 'lastDisplayNumber') >= $this->getStatus('queue', 'maxDisplayNumber')) {
317            $this->setStatusQueue('lastDisplayNumber', 1);
318            return $this;
319        }
320
321        $this->setStatusQueue('lastDisplayNumber', $this->getStatus('queue', 'lastDisplayNumber') + 1);
322        return $this;
323    }
324
325    public function hasEmailFrom(): bool
326    {
327        $emailFrom = $this->getPreference('client', 'emailFrom');
328        return ($emailFrom) ? true : false;
329    }
330
331    public function isEmailRequired(): bool
332    {
333        $emailFrom = $this->getPreference('client', 'emailFrom');
334        $emailRequired = $this->getPreference('client', 'emailRequired');
335        return ($emailFrom && $emailRequired) ? true : false;
336    }
337
338    public function isTelephoneRequired(): bool
339    {
340        $telephoneRequired = $this->getPreference('client', 'telephoneRequired');
341        return $telephoneRequired ? true : false;
342    }
343
344    /**
345     * @return bool
346     */
347    #[\Override]
348    public function hasAccess(Useraccount $useraccount): bool
349    {
350        return $useraccount->isSuperUser() ||  $useraccount->hasScope($this->id);
351    }
352
353    /**
354     * Keep provider and source unchanged (non-superusers must not reassign scope location data).
355     */
356    public function withProviderSourceFrom(self $reference): self
357    {
358        $entity = clone $this;
359        $entity['source'] = $reference->getSource();
360        $entity->provider = new Provider($reference->getProvider()->getArrayCopy());
361        return $entity;
362    }
363
364    /**
365     * Reduce data of dereferenced entities to a required minimum
366     *
367     * @return static
368     */
369    #[\Override]
370    public function withLessData(array $keepArray = [])
371    {
372        $entity = clone $this;
373        if (! in_array('dayoff', $keepArray) && $entity->toProperty()->dayoff->isAvailable()) {
374            unset($entity['dayoff']);
375        }
376        if (! in_array('status', $keepArray)) {
377            unset($entity['status']);
378        }
379        if (! in_array('preferences', $keepArray)) {
380            unset($entity['preferences']);
381        }
382
383        return $entity;
384    }
385
386    public function setStatusQueue(string $key, int $value): static
387    {
388        $this->status['queue'][$key] = $value;
389        return $this;
390    }
391
392    public function setStatusAvailability(mixed $key, mixed $value): static
393    {
394        $this->status['availability'][$key] = $value;
395        return $this;
396    }
397
398    /**
399     * Check if scope is newer than given time
400     *
401     * @return bool
402     */
403    public function isNewerThan(\DateTimeInterface $dateTime)
404    {
405        return ($dateTime->getTimestamp() < $this->lastChange);
406    }
407
408    public function __toString()
409    {
410        $string = 'scope#';
411        $string .= $this['id'];
412        $string .= ' ';
413        $string .= $this->getName();
414        return $string;
415    }
416}