Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
100.00% |
195 / 195 |
|
100.00% |
36 / 36 |
CRAP | |
100.00% |
1 / 1 |
ValidatorSet | |
100.00% |
195 / 195 |
|
100.00% |
36 / 36 |
114 | |
100.00% |
1 / 1 |
getAvailableValidators | |
100.00% |
20 / 20 |
|
100.00% |
1 / 1 |
3 | |||
add | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
2 | |||
load | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
2 | |||
createFromRules | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
2 | |||
addValidatorFromRule | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
addValidatorsFromRules | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
addValidator | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
3 | |||
addValidatorsToField | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
5 | |||
addValidators | |
100.00% |
8 / 8 |
|
100.00% |
1 / 1 |
7 | |||
loadValidator | |
100.00% |
9 / 9 |
|
100.00% |
1 / 1 |
6 | |||
loadValidatorsToField | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
3 | |||
loadValidators | |
100.00% |
8 / 8 |
|
100.00% |
1 / 1 |
5 | |||
getValidators | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
3 | |||
hasValidators | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
getLoadedValidators | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
3 | |||
hasLoadedValidators | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
isLoaded | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
addConditionFromRule | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
addConditionsFromRules | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
addCondition | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
addConditions | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
getConditions | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
hasConditions | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
addError | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
2 | |||
getErrors | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
3 | |||
getEvaluated | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
3 | |||
hasErrors | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
isEvaluated | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
getValidationStatus | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getConditionStatus | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
evaluateStatus | |
100.00% |
14 / 14 |
|
100.00% |
1 / 1 |
7 | |||
setStrict | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
3 | |||
getStrict | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
isStrict | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
evaluateConditions | |
100.00% |
14 / 14 |
|
100.00% |
1 / 1 |
8 | |||
evaluate | |
100.00% |
28 / 28 |
|
100.00% |
1 / 1 |
19 |
1 | <?php |
2 | /** |
3 | * Pop PHP Framework (http://www.popphp.org/) |
4 | * |
5 | * @link https://github.com/popphp/popphp-framework |
6 | * @author Nick Sagona, III <dev@noladev.com> |
7 | * @copyright Copyright (c) 2009-2025 NOLA Interactive, LLC. |
8 | * @license http://www.popphp.org/license New BSD License |
9 | */ |
10 | |
11 | /** |
12 | * @namespace |
13 | */ |
14 | namespace Pop\Validator; |
15 | |
16 | use Pop\Utils\Arr; |
17 | use Pop\Utils\Str; |
18 | use Pop\Utils\CallableObject; |
19 | |
20 | /** |
21 | * Validator set class |
22 | * |
23 | * @category Pop |
24 | * @package Pop\Validator |
25 | * @author Nick Sagona, III <dev@noladev.com> |
26 | * @copyright Copyright (c) 2009-2025 NOLA Interactive, LLC. |
27 | * @license http://www.popphp.org/license New BSD License |
28 | * @version 4.5.0 |
29 | */ |
30 | class ValidatorSet |
31 | { |
32 | |
33 | /** |
34 | * Constants |
35 | */ |
36 | const PASSED_NONE = 0; |
37 | const PASSED_ALL = 1; |
38 | const PASSED_SOME = 2; |
39 | |
40 | const STRICT_NONE = 0; |
41 | const STRICT_VALIDATIONS_ONLY = 1; |
42 | const STRICT_CONDITIONS_ONLY = 2; |
43 | const STRICT_BOTH = 3; |
44 | |
45 | /** |
46 | * Validators |
47 | * @var array |
48 | */ |
49 | protected array $validators = []; |
50 | |
51 | /** |
52 | * Load validators |
53 | * @var array |
54 | */ |
55 | protected array $loaded = []; |
56 | |
57 | /** |
58 | * Evaluated validators and their true/false results |
59 | * @var array |
60 | */ |
61 | protected array $evaluated = []; |
62 | |
63 | /** |
64 | * Conditions |
65 | * @var array |
66 | */ |
67 | protected array $conditions = []; |
68 | |
69 | /** |
70 | * Errors |
71 | * @var array |
72 | */ |
73 | protected array $errors = []; |
74 | |
75 | /** |
76 | * Validation status |
77 | * @var ?int |
78 | */ |
79 | protected ?int $validationStatus = null; |
80 | |
81 | /** |
82 | * Condition status |
83 | * @var ?int |
84 | */ |
85 | protected ?int $conditionStatus = null; |
86 | |
87 | /** |
88 | * Strict flag |
89 | * @var int |
90 | */ |
91 | protected int $strict = 3; |
92 | |
93 | /** |
94 | * Get available validators over the provided input data |
95 | * |
96 | * @param string $directory |
97 | * @param ?array $exclude |
98 | * @return array |
99 | */ |
100 | public static function getAvailableValidators(string $directory = __DIR__, ?array $exclude = null): array |
101 | { |
102 | if ($exclude === null) { |
103 | $exclude = [ |
104 | '.', '..', |
105 | 'AbstractValidator.php', |
106 | 'Condition.php', |
107 | 'Exception.php', |
108 | 'Rule.php', |
109 | 'TraverseTrait.php', |
110 | 'ValidatorInterface.php', |
111 | 'ValidatorSet.php' |
112 | ]; |
113 | } |
114 | |
115 | $validatorClasses = array_map(function ($value) { |
116 | return str_replace('.php', '', $value); |
117 | }, array_filter(scandir($directory), function ($value) use ($exclude) { |
118 | return !in_array($value, $exclude); |
119 | })); |
120 | |
121 | $validators = []; |
122 | |
123 | foreach ($validatorClasses as $class) { |
124 | $validators[$class] = Str::titleCaseToSnakeCase($class); |
125 | } |
126 | |
127 | return $validators; |
128 | } |
129 | |
130 | /** |
131 | * Add validators |
132 | * |
133 | * @param array|string $validators |
134 | * @param ?string $field |
135 | * @param int $strict |
136 | * @return ValidatorSet |
137 | */ |
138 | public static function add(array|string $validators, ?string $field = null, int $strict = 3): ValidatorSet |
139 | { |
140 | $validatorSet = new static(); |
141 | $validatorSet->setStrict($strict); |
142 | |
143 | $validators = Arr::make($validators); |
144 | |
145 | if ($field !== null) { |
146 | $validatorSet->addValidatorsToField($field, $validators); |
147 | } else { |
148 | $validatorSet->addValidators($validators); |
149 | } |
150 | |
151 | return $validatorSet; |
152 | } |
153 | |
154 | /** |
155 | * Load validator objects directly |
156 | * |
157 | * @param array|string $validators |
158 | * @param ?string $field |
159 | * @param int $strict |
160 | * @return ValidatorSet |
161 | */ |
162 | public static function load(array|string $validators, ?string $field = null, int $strict = 3): ValidatorSet |
163 | { |
164 | $validatorSet = new static(); |
165 | $validatorSet->setStrict($strict); |
166 | |
167 | $validators = Arr::make($validators); |
168 | |
169 | if ($field !== null) { |
170 | $validatorSet->loadValidatorsToField($field, $validators); |
171 | } else { |
172 | $validatorSet->loadValidators($validators); |
173 | } |
174 | |
175 | return $validatorSet; |
176 | } |
177 | |
178 | /** |
179 | * Create validator set from rules |
180 | * |
181 | * @param array|string $rules |
182 | * @param int $strict |
183 | * @param string $prefix |
184 | * @return ValidatorSet |
185 | */ |
186 | public static function createFromRules( |
187 | array|string $rules, int $strict = 3, string $prefix = 'Pop\Validator\\' |
188 | ): ValidatorSet |
189 | { |
190 | $validatorSet = new static(); |
191 | $validatorSet->setStrict($strict); |
192 | |
193 | $rules = Arr::make($rules); |
194 | |
195 | foreach ($rules as $rule) { |
196 | ['field' => $field, 'validator' => $validator, 'value' => $value, 'message' => $message] = Rule::parse($rule, $prefix); |
197 | $validatorSet->addValidator($field, $validator, $value, $message, $prefix); |
198 | } |
199 | |
200 | return $validatorSet; |
201 | } |
202 | |
203 | /** |
204 | * Add validator from rule |
205 | * |
206 | * @param string $rule |
207 | * @param string $prefix |
208 | * @return ValidatorSet |
209 | */ |
210 | public function addValidatorFromRule(string $rule, string $prefix = 'Pop\Validator\\'): ValidatorSet |
211 | { |
212 | ['field' => $field, 'validator' => $validator, 'value' => $value, 'message' => $message] = Rule::parse($rule, $prefix); |
213 | $this->addValidator($field, $validator, $value, $message, $prefix); |
214 | return $this; |
215 | } |
216 | |
217 | /** |
218 | * Add validators from rules |
219 | * |
220 | * @param array $rules |
221 | * @param string $prefix |
222 | * @return ValidatorSet |
223 | */ |
224 | public function addValidatorsFromRules(array $rules, string $prefix = 'Pop\Validator\\'): ValidatorSet |
225 | { |
226 | foreach ($rules as $rule) { |
227 | $this->addValidatorFromRule($rule, $prefix); |
228 | } |
229 | return $this; |
230 | } |
231 | |
232 | /** |
233 | * Add validator |
234 | * |
235 | * @param string $field |
236 | * @param string $validator |
237 | * @param mixed $value |
238 | * @param ?string $message |
239 | * @param ?string $prefix |
240 | * @return ValidatorSet |
241 | */ |
242 | public function addValidator( |
243 | string $field, string $validator, mixed $value = null, ?string $message = null, ?string $prefix = 'Pop\Validator\\' |
244 | ): ValidatorSet |
245 | { |
246 | if (!isset($this->validators[$field])) { |
247 | $this->validators[$field] = []; |
248 | } |
249 | if (!class_exists($prefix . $validator)) { |
250 | throw new \InvalidArgumentException("Error: The validator class '" . $prefix . $validator . "' does not exist."); |
251 | } |
252 | |
253 | $this->validators[$field][] = new CallableObject($prefix . $validator, [$value, $message]); |
254 | return $this; |
255 | } |
256 | |
257 | /** |
258 | * Add validators to specific field |
259 | * |
260 | * @param string $field |
261 | * @param array $validators |
262 | * @param string $prefix |
263 | * @return ValidatorSet |
264 | */ |
265 | public function addValidatorsToField(string $field, array $validators, string $prefix = 'Pop\Validator\\'): ValidatorSet |
266 | { |
267 | foreach ($validators as $validator => $value) { |
268 | if (is_array($value) && array_key_exists('value', $value) && isset($value['message'])) { |
269 | $this->addValidator($field, $validator, $value['value'], $value['message'], $prefix); |
270 | } else { |
271 | $this->addValidator($field, $validator, $value, null, $prefix); |
272 | } |
273 | } |
274 | return $this; |
275 | } |
276 | |
277 | /** |
278 | * Add validators to specific field |
279 | * |
280 | * @param array $validators |
281 | * @param string $prefix |
282 | * @return ValidatorSet |
283 | */ |
284 | public function addValidators(array $validators, string $prefix = 'Pop\Validator\\'): ValidatorSet |
285 | { |
286 | foreach ($validators as $field => $validator) { |
287 | if (is_array($validator)) { |
288 | foreach ($validator as $val => $value) { |
289 | if (is_array($value) && array_key_exists('value', $value) && isset($value['message'])) { |
290 | $this->addValidator($field, $val, $value['value'], $value['message'], $prefix); |
291 | } else { |
292 | $this->addValidator($field, $val, $value, null, $prefix); |
293 | } |
294 | } |
295 | } else { |
296 | $this->addValidator($field, $validator, null, null, $prefix); |
297 | } |
298 | } |
299 | return $this; |
300 | } |
301 | |
302 | /** |
303 | * Load validator |
304 | * |
305 | * @param string $field |
306 | * @param AbstractValidator $validator |
307 | * @param array $input |
308 | * @return ValidatorSet |
309 | */ |
310 | public function loadValidator(string $field, AbstractValidator $validator, array $input = []): ValidatorSet |
311 | { |
312 | if (!isset($this->loaded[$field])) { |
313 | $this->loaded[$field] = []; |
314 | } |
315 | |
316 | // If the value references a value in the input array |
317 | $value = $validator->getValue(); |
318 | if (is_string($value) && str_starts_with($value, '[') && str_ends_with($value, ']')) { |
319 | $value = substr($value, 1, -1); |
320 | if (array_key_exists($value, $input)) { |
321 | $validator->setValue($input[$value]); |
322 | } |
323 | } |
324 | |
325 | $this->loaded[$field][] = $validator; |
326 | return $this; |
327 | } |
328 | |
329 | /** |
330 | * Load validators to specific field |
331 | * |
332 | * @param string $field |
333 | * @param array $validators |
334 | * @param array $input |
335 | * @return ValidatorSet |
336 | */ |
337 | public function loadValidatorsToField(string $field, array $validators, array $input = []): ValidatorSet |
338 | { |
339 | foreach ($validators as $validator) { |
340 | if ($validator instanceof CallableObject) { |
341 | $validator = $validator->call(); |
342 | } |
343 | $this->loadValidator($field, $validator, $input); |
344 | } |
345 | return $this; |
346 | } |
347 | |
348 | /** |
349 | * Load validators to specific field |
350 | * |
351 | * @param ?array $validators |
352 | * @pparam array $input |
353 | * @return ValidatorSet |
354 | */ |
355 | public function loadValidators(?array $validators = null, array $input = []): ValidatorSet |
356 | { |
357 | if ($validators === null) { |
358 | $validators = $this->validators; |
359 | } |
360 | foreach ($validators as $field => $validator) { |
361 | foreach ($validator as $val) { |
362 | if ($val instanceof CallableObject) { |
363 | $val = $val->call(); |
364 | } |
365 | $this->loadValidator($field, $val, $input); |
366 | } |
367 | } |
368 | return $this; |
369 | } |
370 | |
371 | /** |
372 | * Get validators |
373 | * |
374 | * @param ?string $field |
375 | * @return array |
376 | */ |
377 | public function getValidators(?string $field = null): array |
378 | { |
379 | if ($field !== null) { |
380 | return (isset($this->validators[$field])) ? $this->validators[$field] : []; |
381 | } else { |
382 | return $this->validators; |
383 | } |
384 | } |
385 | |
386 | /** |
387 | * Has validators |
388 | * |
389 | * @param ?string $field |
390 | * @return bool |
391 | */ |
392 | public function hasValidators(?string $field = null): bool |
393 | { |
394 | if ($field !== null) { |
395 | return (isset($this->validators[$field])); |
396 | } else { |
397 | return (!empty($this->validators)); |
398 | } |
399 | } |
400 | |
401 | /** |
402 | * Get loaded validators |
403 | * |
404 | * @param ?string $field |
405 | * @return array |
406 | */ |
407 | public function getLoadedValidators(?string $field = null): array |
408 | { |
409 | if ($field !== null) { |
410 | return (isset($this->loaded[$field])) ? $this->loaded[$field] : []; |
411 | } else { |
412 | return $this->loaded; |
413 | } |
414 | } |
415 | |
416 | /** |
417 | * Has loaded validators |
418 | * |
419 | * @param ?string $field |
420 | * @return bool |
421 | */ |
422 | public function hasLoadedValidators(?string $field = null): bool |
423 | { |
424 | if ($field !== null) { |
425 | return (isset($this->loaded[$field])); |
426 | } else { |
427 | return (!empty($this->loaded)); |
428 | } |
429 | } |
430 | |
431 | /** |
432 | * Is loaded |
433 | * |
434 | * @param ?string $field |
435 | * @return bool |
436 | */ |
437 | public function isLoaded(?string $field = null): bool |
438 | { |
439 | if ($field !== null) { |
440 | return (isset($this->loaded[$field])); |
441 | } else { |
442 | return (!empty($this->loaded)); |
443 | } |
444 | } |
445 | |
446 | /** |
447 | * Add condition from rule |
448 | * |
449 | * @param string $rule |
450 | * @param string $prefix |
451 | * @return ValidatorSet |
452 | */ |
453 | public function addConditionFromRule(string $rule, string $prefix = 'Pop\Validator\\'): ValidatorSet |
454 | { |
455 | $this->addCondition(Condition::createFromRule($rule, $prefix)); |
456 | return $this; |
457 | } |
458 | |
459 | /** |
460 | * Add conditions from rules |
461 | * |
462 | * @param array $rules |
463 | * @param string $prefix |
464 | * @return ValidatorSet |
465 | */ |
466 | public function addConditionsFromRules(array $rules, string $prefix = 'Pop\Validator\\'): ValidatorSet |
467 | { |
468 | foreach ($rules as $rule) { |
469 | $this->addConditionFromRule($rule, $prefix); |
470 | } |
471 | return $this; |
472 | } |
473 | |
474 | /** |
475 | * Add condition |
476 | * |
477 | * @param Condition $condition |
478 | * @return ValidatorSet |
479 | */ |
480 | public function addCondition(Condition $condition): ValidatorSet |
481 | { |
482 | $this->conditions[] = $condition; |
483 | return $this; |
484 | } |
485 | |
486 | /** |
487 | * Add conditions |
488 | * |
489 | * @param array $conditions |
490 | * @return ValidatorSet |
491 | */ |
492 | public function addConditions(array $conditions): ValidatorSet |
493 | { |
494 | foreach ($conditions as $condition) { |
495 | $this->addCondition($condition); |
496 | } |
497 | return $this; |
498 | } |
499 | |
500 | /** |
501 | * Get conditions |
502 | * |
503 | * @return array |
504 | */ |
505 | public function getConditions(): array |
506 | { |
507 | return $this->conditions; |
508 | } |
509 | |
510 | /** |
511 | * Has conditions |
512 | * |
513 | * @return bool |
514 | */ |
515 | public function hasConditions(): bool |
516 | { |
517 | return (!empty($this->conditions)); |
518 | } |
519 | |
520 | /** |
521 | * Add error |
522 | * |
523 | * @param string $field |
524 | * @param string $error |
525 | * @return ValidatorSet |
526 | */ |
527 | public function addError(string $field, string $error): ValidatorSet |
528 | { |
529 | if (!isset($this->errors[$field])) { |
530 | $this->errors[$field] = []; |
531 | } |
532 | $this->errors[$field][] = $error; |
533 | return $this; |
534 | } |
535 | |
536 | /** |
537 | * Get errors |
538 | * |
539 | * @param ?string $field |
540 | * @return array |
541 | */ |
542 | public function getErrors(?string $field = null): array |
543 | { |
544 | if ($field !== null) { |
545 | return (isset($this->errors[$field])) ? $this->errors[$field] : []; |
546 | } else { |
547 | return $this->errors; |
548 | } |
549 | } |
550 | |
551 | /** |
552 | * Get evaluated |
553 | * |
554 | * @param ?string $field |
555 | * @return mixed |
556 | */ |
557 | public function getEvaluated(?string $field = null): mixed |
558 | { |
559 | if ($field !== null) { |
560 | return (isset($this->evaluated[$field])) ? $this->evaluated[$field] : null; |
561 | } else { |
562 | return $this->evaluated; |
563 | } |
564 | } |
565 | |
566 | /** |
567 | * Has errors |
568 | * |
569 | * @param ?string $field |
570 | * @return bool |
571 | */ |
572 | public function hasErrors(?string $field = null): bool |
573 | { |
574 | if ($field !== null) { |
575 | return (isset($this->errors[$field])); |
576 | } else { |
577 | return (!empty($this->errors)); |
578 | } |
579 | } |
580 | |
581 | /** |
582 | * Is evaluated |
583 | * |
584 | * @param ?string $field |
585 | * @return bool |
586 | */ |
587 | public function isEvaluated(?string $field = null): bool |
588 | { |
589 | if ($field !== null) { |
590 | return (array_key_exists($field, $this->evaluated)); |
591 | } else { |
592 | return (!empty($this->evaluated)); |
593 | } |
594 | } |
595 | |
596 | /** |
597 | * Get validation status |
598 | * |
599 | * @return ?int |
600 | */ |
601 | public function getValidationStatus(): ?int |
602 | { |
603 | return $this->validationStatus; |
604 | } |
605 | /** |
606 | * Get condition status |
607 | * |
608 | * @return ?int |
609 | */ |
610 | public function getConditionStatus(): ?int |
611 | { |
612 | return $this->conditionStatus; |
613 | } |
614 | |
615 | /** |
616 | * Evaluate status |
617 | * |
618 | * @return ValidatorSet |
619 | */ |
620 | public function evaluateStatus(): ValidatorSet |
621 | { |
622 | $numOfValidators = 0; |
623 | $numOfPassed = 0; |
624 | |
625 | foreach ($this->evaluated as $field => $evaluated) { |
626 | foreach ($evaluated as $result) { |
627 | $numOfValidators++; |
628 | if ($result) { |
629 | $numOfPassed++; |
630 | } |
631 | } |
632 | } |
633 | |
634 | if ($numOfValidators == $numOfPassed) { |
635 | $this->validationStatus = self::PASSED_ALL; |
636 | } else if ($numOfPassed > 0) { |
637 | $this->validationStatus = self::PASSED_SOME; |
638 | } else if ($numOfPassed == 0) { |
639 | $this->validationStatus = self::PASSED_NONE; |
640 | } |
641 | |
642 | return $this; |
643 | } |
644 | |
645 | /** |
646 | * Set strict |
647 | * |
648 | * @param int $strict |
649 | * @return ValidatorSet |
650 | */ |
651 | public function setStrict(int $strict): ValidatorSet |
652 | { |
653 | if ($strict < 0 || $strict > 3) { |
654 | throw new \InvalidArgumentException('Error: Strict must be between 0 and 3'); |
655 | } |
656 | $this->strict = $strict; |
657 | return $this; |
658 | } |
659 | |
660 | /** |
661 | * Get strict |
662 | * |
663 | * @return int |
664 | */ |
665 | public function getStrict(): int |
666 | { |
667 | return $this->strict; |
668 | } |
669 | |
670 | /** |
671 | * Is strict |
672 | * |
673 | * @return bool |
674 | */ |
675 | public function isStrict(): bool |
676 | { |
677 | return ($this->strict > 0); |
678 | } |
679 | |
680 | /** |
681 | * Evaluate all conditions over the provided input data |
682 | * |
683 | * @param mixed $input |
684 | * @return bool |
685 | */ |
686 | public function evaluateConditions(array $input): bool |
687 | { |
688 | $numOfConditions = count($this->conditions); |
689 | $numOfPassed = 0; |
690 | |
691 | foreach ($this->conditions as $condition) { |
692 | if ($condition->evaluate($input)) { |
693 | $numOfPassed++; |
694 | } |
695 | } |
696 | |
697 | if ($numOfConditions == $numOfPassed) { |
698 | $this->conditionStatus = self::PASSED_ALL; |
699 | } else if ($numOfPassed > 0) { |
700 | $this->conditionStatus = self::PASSED_SOME; |
701 | } else if ($numOfPassed == 0) { |
702 | $this->conditionStatus = self::PASSED_NONE; |
703 | } |
704 | |
705 | // Passed all |
706 | if (($this->strict == self::STRICT_BOTH) || ($this->strict == self::STRICT_CONDITIONS_ONLY)) { |
707 | return ($numOfConditions == $numOfPassed); |
708 | // Passed some, or false if none passed |
709 | } else { |
710 | return ($numOfPassed > 0); |
711 | } |
712 | } |
713 | |
714 | /** |
715 | * Evaluate all validators over the provided input data |
716 | * |
717 | * @param mixed $input |
718 | * @param ?string $prefix |
719 | * @return bool |
720 | */ |
721 | public function evaluate(array $input, ?string $prefix = 'Pop\Validator\\'): bool |
722 | { |
723 | $result = $this->evaluateConditions($input); |
724 | // If conditions are met, or there are no conditions |
725 | if (!($this->hasConditions()) || $this->evaluateConditions($input)) { |
726 | if (!$this->isLoaded()) { |
727 | $this->loadValidators(null, $input); |
728 | } |
729 | |
730 | foreach ($this->loaded as $field => $validators) { |
731 | foreach ($validators as $validator) { |
732 | $result = (isset($input[$field]) && !Rule::isHasClass(get_class($validator), true, $prefix)) ? |
733 | $validator->evaluate($input[$field]) : $validator->evaluate($input); |
734 | if (!$result) { |
735 | $this->addError($field, $validator->getMessage()); |
736 | } |
737 | if (!isset($this->evaluated[$field])) { |
738 | $this->evaluated[$field] = []; |
739 | } |
740 | $this->evaluated[$field][] = $result; |
741 | } |
742 | } |
743 | |
744 | // Catch any validators that were added after a load call |
745 | foreach ($this->validators as $field => $validators) { |
746 | if (!$this->isEvaluated($field)) { |
747 | $this->loadValidatorsToField($field, $validators, $input); |
748 | |
749 | if ($this->isLoaded($field)) { |
750 | foreach ($this->loaded[$field] as $validator) { |
751 | $result = (isset($input[$field])) ? $validator->evaluate($input[$field]) : $validator->evaluate(); |
752 | if (!$result) { |
753 | $this->addError($field, $validator->getMessage()); |
754 | } |
755 | if (!isset($this->evaluated[$field])) { |
756 | $this->evaluated[$field] = []; |
757 | } |
758 | $this->evaluated[$field][] = $result; |
759 | } |
760 | } |
761 | } |
762 | } |
763 | |
764 | $this->evaluateStatus(); |
765 | } |
766 | |
767 | // Passed all |
768 | if (($this->strict == self::STRICT_BOTH) || ($this->strict == self::STRICT_VALIDATIONS_ONLY)) { |
769 | return (!$this->hasErrors()); |
770 | // Passed some, or false if none passed |
771 | } else { |
772 | return ($this->validationStatus > 0); |
773 | } |
774 | } |
775 | |
776 | } |