Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
79.37% covered (warning)
79.37%
100 / 126
64.29% covered (warning)
64.29%
9 / 14
CRAP
0.00% covered (danger)
0.00%
0 / 1
ProcessValidator
79.37% covered (warning)
79.37%
100 / 126
64.29% covered (warning)
64.29%
9 / 14
61.01
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getCollection
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getProcess
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getDelegatedProcess
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 validateId
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
4
 validateAuthKey
92.86% covered (success)
92.86%
13 / 14
0.00% covered (danger)
0.00%
0 / 1
5.01
 validateMail
100.00% covered (success)
100.00%
22 / 22
100.00% covered (success)
100.00%
1 / 1
8
 validateName
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
3
 validateCustomTextfield
0.00% covered (danger)
0.00%
0 / 17
0.00% covered (danger)
0.00%
0 / 1
30
 validateTelephone
82.61% covered (warning)
82.61%
19 / 23
0.00% covered (danger)
0.00%
0 / 1
6.19
 validateSurvey
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 validateText
75.00% covered (warning)
75.00%
9 / 12
0.00% covered (danger)
0.00%
0 / 1
3.14
 validateReminderTimestamp
80.00% covered (warning)
80.00%
4 / 5
0.00% covered (danger)
0.00%
0 / 1
3.07
 validateRequests
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2
3namespace BO\Zmsentities\Validator;
4
5use BO\Mellon\Unvalidated;
6use BO\Mellon\Collection;
7use BO\Zmsentities\Helper\Delegate;
8use BO\Zmsentities\Helper\ProcessPlainText;
9use BO\Zmsentities\Process;
10
11/**
12 *
13 */
14class ProcessValidator
15{
16    protected Process $process;
17
18    protected Collection $collection;
19
20    public function __construct(Process $process)
21    {
22        $this->process = $process;
23        $this->collection = new Collection([]);
24    }
25
26    public function getCollection(): Collection
27    {
28        return $this->collection;
29    }
30
31    public function getProcess(): Process
32    {
33        return $this->process;
34    }
35
36    public function getDelegatedProcess(): Delegate
37    {
38        $process = $this->getProcess();
39        $delegatedProcess = new Delegate($process);
40        return $delegatedProcess;
41    }
42
43    public function validateId(Unvalidated $unvalid, callable $setter, callable $isRequiredCallback = null): self
44    {
45        $valid = $unvalid->isNumber(
46            "Eine gültige Vorgangsnummer ist in der Regel eine sechsstellige Nummer wie '123456'"
47        );
48        $length = strlen((string)$valid->getValue());
49        if ($length) {
50            $valid->isGreaterThan(100000, "Eine Vorgangsnummer besteht aus mindestens 6 Ziffern");
51            $valid->isLowerEqualThan(99999999999, "Eine Vorgangsnummer besteht aus maximal 11 Ziffern");
52        } elseif ($isRequiredCallback !== null && $isRequiredCallback()) {
53            $valid->isRequired("Eine Vorgangsnummer wird benötigt.");
54        }
55        $this->getCollection()->validatedAction($valid, $setter);
56        return $this;
57    }
58
59    public function validateAuthKey(Unvalidated $unvalid, callable $setter, callable $isRequiredCallback = null): self
60    {
61        $trimmed = trim((string) $unvalid->getUnvalidated());
62        $valid = (new Unvalidated($trimmed, $unvalid->getName()))->isString();
63        $length = strlen($trimmed);
64        if ($length || ($isRequiredCallback !== null && $isRequiredCallback())) {
65            if ($length) {
66                $valid
67                ->isMatchOf(
68                    '/^(?:[a-f0-9]{4}|[a-f0-9]{64})$/i',
69                    "Der Absagecode ist nicht korrekt"
70                );
71            } else {
72                $valid->isRequired("Ein Absagecode wird benötigt");
73            }
74            $this->getCollection()->validatedAction($valid, $setter);
75            return $this;
76        }
77        return $this;
78    }
79
80    public function validateMail(Unvalidated $unvalid, callable $setter, callable $isRequiredCallback = null): self
81    {
82        $valid = $unvalid->isString();
83        $length = strlen((string)$valid->getUnvalidated());
84        $process = $this->getProcess();
85
86        if (!$length && $process->getCurrentScope()->isEmailRequired() && $process->isWithAppointment()) {
87            $valid->isBiggerThan(
88                6,
89                "Für den Standort muss eine gültige E-Mail Adresse eingetragen werden"
90            );
91        } elseif (!$length && $isRequiredCallback !== null && $isRequiredCallback()) {
92            $valid->isBiggerThan(
93                6,
94                "Für den Email-Versand muss eine gültige E-Mail Adresse angegeben werden"
95            );
96        } elseif ($length) {
97            $valid = $unvalid
98                ->isMail("Die E-Mail Adresse muss im Format max@mustermann.de eingeben werden.")
99                ->hasDNS(
100                    "Zu der angegebenen E-Mail-Adresse können keine Mails verschickt werden. " .
101                    "Der Host zur Domain nach dem '@' ist nicht erreichbar. "
102                );
103        }
104        $this->getCollection()->validatedAction($valid, $setter);
105        return $this;
106    }
107
108    public function validateName(Unvalidated $unvalid, callable $setter): self
109    {
110        $valid = $unvalid->isString();
111        $length = strlen((string)$valid->getValue());
112        if ($length || $this->getProcess()->isWithAppointment()) {
113            $valid
114                ->isBiggerThan(2, "Es muss ein aussagekräftiger Name eingegeben werden")
115                ->isSmallerThan(50, "Der Name sollte 50 Zeichen nicht überschreiten");
116        }
117        $this->getCollection()->validatedAction($valid, $setter);
118        return $this;
119    }
120
121    /**
122     * Validates a scope custom text field (max 250 chars), with optional HTML stripped to plain text.
123     */
124    public function validateCustomTextfield(Unvalidated $unvalid, callable $setter, bool $required): self
125    {
126        $valid = $unvalid->isString('Ungültige Zeichenkette', false);
127        if ($valid->hasFailed()) {
128            $this->getCollection()->validatedAction($valid, $setter);
129            return $this;
130        }
131        $normalized = ProcessPlainText::normalize($valid->getValue());
132        if ($required && trim($normalized) === '') {
133            $valid->setFailure('Dieses Feld darf nicht leer sein');
134        } elseif (mb_strlen($normalized, 'UTF-8') > ProcessPlainText::MAX_CUSTOM_TEXTFIELD_CHARS) {
135            $valid->setFailure(
136                'Der Eintrag überschreitet die maximal erlaubte Länge von ' .
137                ProcessPlainText::MAX_CUSTOM_TEXTFIELD_CHARS .
138                ' Zeichen'
139            );
140        }
141        $this->getCollection()->validatedAction($valid, function (mixed $raw) use ($setter) {
142            $setter(ProcessPlainText::normalize($raw));
143        });
144        return $this;
145    }
146
147    public function validateTelephone(Unvalidated $unvalid, callable $setter): self
148    {
149        $valid = $unvalid->isString();
150        $length = strlen((string)$valid->getValue());
151
152        try {
153            $phoneNumberUtil = \libphonenumber\PhoneNumberUtil::getInstance();
154            $phoneNumberObject = $phoneNumberUtil->parse($valid->getValue(), 'DE');
155            $telephone = '+' . (string) $phoneNumberObject->getCountryCode() . (string) $phoneNumberObject->getNationalNumber();
156        } catch (\Exception $exception) {
157            $telephone = $valid->getValue();
158        }
159        $valid = (new \BO\Mellon\Unvalidated($telephone, 'telephone'))->isString();
160
161        if (
162            !$length
163            && $this->getProcess()->getCurrentScope()->isTelephoneRequired()
164            && $this->getProcess()->isWithAppointment()
165        ) {
166            $valid
167                ->isBiggerThan(10, "Für den Standort muss eine gültige Telefonnummer eingetragen werden");
168        } elseif ($length) {
169            $valid
170                ->isSmallerThan(
171                    15,
172                    "Die Telefonnummer ist zu lang, bitte prüfen Sie Ihre Eingabe"
173                )
174                ->isBiggerThan(10, "Für den Standort muss eine gültige Telefonnummer eingetragen werden")
175                ->isMatchOf("/^\+?[\d\s]*$/", "Die Telefonnummer muss im Format 0170 1234567 eingegeben werden");
176        }
177        $this->getCollection()->validatedAction($valid, $setter);
178        return $this;
179    }
180
181    public function validateSurvey(Unvalidated $unvalid, callable $setter): self
182    {
183        $valid = $unvalid->isNumber("Bitte wählen Sie eine Option");
184        $this->getCollection()->validatedAction($valid, $setter);
185        return $this;
186    }
187
188    public function validateText(Unvalidated $unvalid, callable $setter): self
189    {
190        $valid = $unvalid->isString('Ungültige Zeichenkette', false);
191        if ($valid->hasFailed()) {
192            $this->getCollection()->validatedAction($valid, $setter);
193            return $this;
194        }
195        $normalized = ProcessPlainText::normalize($valid->getValue());
196        $length = mb_strlen($normalized, 'UTF-8');
197        if ($length > ProcessPlainText::MAX_AMENDMENT_CHARS) {
198            $valid->setFailure('Die Anmerkung sollte 500 Zeichen nicht überschreiten');
199        }
200        $this->getCollection()->validatedAction($valid, function () use ($setter, $normalized) {
201            $setter($normalized);
202        });
203        return $this;
204    }
205
206    public function validateReminderTimestamp(Unvalidated $unvalid, callable $setter, callable $conditionCallback): self
207    {
208        $valid = $unvalid->isNumber();
209        if ($conditionCallback && $conditionCallback()) {
210            $this->getCollection()->validatedAction($valid, $setter);
211        } else {
212            $this->getCollection()->addValid($valid);
213        }
214        return $this;
215    }
216
217    public function validateRequests(Unvalidated $unvalid, callable $setter): self
218    {
219        if ($this->getProcess()->isWithAppointment()) {
220             $valid = $unvalid->isArray("Es muss mindestens eine Dienstleistung ausgewählt werden!");
221             $this->getCollection()->validatedAction($valid, $setter);
222        }
223        return $this;
224    }
225}