Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
80.16% covered (warning)
80.16%
101 / 126
71.43% covered (warning)
71.43%
10 / 14
CRAP
0.00% covered (danger)
0.00%
0 / 1
ProcessValidator
80.16% covered (warning)
80.16%
101 / 126
71.43% covered (warning)
71.43%
10 / 14
64.25
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
5
 validateAuthKey
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
1 / 1
7
 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;
17
18    protected $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 (!$length && $isRequiredCallback && $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 && $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            } elseif ($isRequiredCallback && $isRequiredCallback()) {
72                $valid->isRequired("Ein Absagecode wird benötigt");
73            }
74            $this->getCollection()->validatedAction($valid, $setter);
75            return $this;
76        }
77    }
78
79    public function validateMail(Unvalidated $unvalid, callable $setter, callable $isRequiredCallback = null): self
80    {
81        $valid = $unvalid->isString();
82        $length = strlen((string)$valid->getUnvalidated());
83        $process = $this->getProcess();
84
85        /*
86        error_log(
87            "Mail validate: ".$valid->getUnvalidated()
88            ." ($length) with scope mail required="
89            . ($process->getCurrentScope()->isEmailRequired() ? 'yes' : 'no')
90            ." with appointment="
91            . ($process->isWithAppointment() ? 'yes' : 'no')
92            ." with callback="
93            . ( ($isRequiredCallback && $isRequiredCallback()) ? 'yes' : 'no')
94        );
95        */
96        if (!$length && $process->getCurrentScope()->isEmailRequired() && $process->isWithAppointment()) {
97            $valid->isBiggerThan(
98                6,
99                "Für den Standort muss eine gültige E-Mail Adresse eingetragen werden"
100            );
101        } elseif (!$length && $isRequiredCallback && $isRequiredCallback()) {
102            $valid->isBiggerThan(
103                6,
104                "Für den Email-Versand muss eine gültige E-Mail Adresse angegeben werden"
105            );
106        } elseif ($length) {
107            $valid = $unvalid
108                ->isMail("Die E-Mail Adresse muss im Format max@mustermann.de eingeben werden.")
109                ->hasDNS(
110                    "Zu der angegebenen E-Mail-Adresse können keine Mails verschickt werden. " .
111                    "Der Host zur Domain nach dem '@' ist nicht erreichbar. "
112                );
113        }
114        $this->getCollection()->validatedAction($valid, $setter);
115        return $this;
116    }
117
118    public function validateName(Unvalidated $unvalid, callable $setter): self
119    {
120        $valid = $unvalid->isString();
121        $length = strlen((string)$valid->getValue());
122        if ($length || $this->getProcess()->isWithAppointment()) {
123            $valid
124                ->isBiggerThan(2, "Es muss ein aussagekräftiger Name eingegeben werden")
125                ->isSmallerThan(50, "Der Name sollte 50 Zeichen nicht überschreiten");
126        }
127        $this->getCollection()->validatedAction($valid, $setter);
128        return $this;
129    }
130
131    /**
132     * Validates a scope custom text field (max 250 chars), with optional HTML stripped to plain text.
133     */
134    public function validateCustomTextfield(Unvalidated $unvalid, callable $setter, bool $required): self
135    {
136        $valid = $unvalid->isString('Ungültige Zeichenkette', false);
137        if ($valid->hasFailed()) {
138            $this->getCollection()->validatedAction($valid, $setter);
139            return $this;
140        }
141        $normalized = ProcessPlainText::normalize($valid->getValue());
142        if ($required && trim($normalized) === '') {
143            $valid->setFailure('Dieses Feld darf nicht leer sein');
144        } elseif (mb_strlen($normalized, 'UTF-8') > ProcessPlainText::MAX_CUSTOM_TEXTFIELD_CHARS) {
145            $valid->setFailure(
146                'Der Eintrag überschreitet die maximal erlaubte Länge von ' .
147                ProcessPlainText::MAX_CUSTOM_TEXTFIELD_CHARS .
148                ' Zeichen'
149            );
150        }
151        $this->getCollection()->validatedAction($valid, function ($raw) use ($setter) {
152            $setter(ProcessPlainText::normalize($raw));
153        });
154        return $this;
155    }
156
157    public function validateTelephone(Unvalidated $unvalid, callable $setter): self
158    {
159        $valid = $unvalid->isString();
160        $length = strlen((string)$valid->getValue());
161
162        try {
163            $phoneNumberUtil = \libphonenumber\PhoneNumberUtil::getInstance();
164            $phoneNumberObject = $phoneNumberUtil->parse($valid->getValue(), 'DE');
165            $telephone = '+' . $phoneNumberObject->getCountryCode() . $phoneNumberObject->getNationalNumber();
166        } catch (\Exception $exception) {
167            $telephone = $valid->getValue();
168        }
169        $valid = (new \BO\Mellon\Unvalidated($telephone, 'telephone'))->isString();
170
171        if (
172            !$length
173            && $this->getProcess()->getCurrentScope()->isTelephoneRequired()
174            && $this->getProcess()->isWithAppointment()
175        ) {
176            $valid
177                ->isBiggerThan(10, "Für den Standort muss eine gültige Telefonnummer eingetragen werden");
178        } elseif ($length) {
179            $valid
180                ->isSmallerThan(
181                    15,
182                    "Die Telefonnummer ist zu lang, bitte prüfen Sie Ihre Eingabe"
183                )
184                ->isBiggerThan(10, "Für den Standort muss eine gültige Telefonnummer eingetragen werden")
185                ->isMatchOf("/^\+?[\d\s]*$/", "Die Telefonnummer muss im Format 0170 1234567 eingegeben werden");
186        }
187        $this->getCollection()->validatedAction($valid, $setter);
188        return $this;
189    }
190
191    public function validateSurvey(Unvalidated $unvalid, callable $setter): self
192    {
193        $valid = $unvalid->isNumber("Bitte wählen Sie eine Option");
194        $this->getCollection()->validatedAction($valid, $setter);
195        return $this;
196    }
197
198    public function validateText(Unvalidated $unvalid, callable $setter): self
199    {
200        $valid = $unvalid->isString('Ungültige Zeichenkette', false);
201        if ($valid->hasFailed()) {
202            $this->getCollection()->validatedAction($valid, $setter);
203            return $this;
204        }
205        $normalized = ProcessPlainText::normalize($valid->getValue());
206        $length = mb_strlen($normalized, 'UTF-8');
207        if ($length > ProcessPlainText::MAX_AMENDMENT_CHARS) {
208            $valid->setFailure('Die Anmerkung sollte 500 Zeichen nicht überschreiten');
209        }
210        $this->getCollection()->validatedAction($valid, function () use ($setter, $normalized) {
211            $setter($normalized);
212        });
213        return $this;
214    }
215
216    public function validateReminderTimestamp(Unvalidated $unvalid, callable $setter, callable $conditionCallback): self
217    {
218        $valid = $unvalid->isNumber();
219        if ($conditionCallback && $conditionCallback()) {
220            $this->getCollection()->validatedAction($valid, $setter);
221        } else {
222            $this->getCollection()->addValid($valid);
223        }
224        return $this;
225    }
226
227    public function validateRequests(Unvalidated $unvalid, callable $setter): self
228    {
229        if ($this->getProcess()->isWithAppointment()) {
230             $valid = $unvalid->isArray("Es muss mindestens eine Dienstleistung ausgewählt werden!");
231             $this->getCollection()->validatedAction($valid, $setter);
232        }
233        return $this;
234    }
235}