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