Passed
Pull Request — master (#316)
by Dmitriy
02:46
created

StopOnErrorHandler::validate()   B

Complexity

Conditions 8
Paths 17

Size

Total Lines 37
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 8.0093

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 19
c 1
b 0
f 0
dl 0
loc 37
ccs 18
cts 19
cp 0.9474
rs 8.4444
cc 8
nc 17
nop 3
crap 8.0093
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Validator\Rule;
6
7
use InvalidArgumentException;
8
use Yiisoft\Translator\TranslatorInterface;
9
use Yiisoft\Validator\Exception\UnexpectedRuleException;
10
use Yiisoft\Validator\Result;
11
use Yiisoft\Validator\RuleHandlerInterface;
12
use Yiisoft\Validator\ValidationContext;
13
14
/**
15
 * Can be used for early stopping the validation process of the value when the validation on the stage was failed.
16
 *
17
 * For example, we have several rules, but we want not to process the rest rules when fail was ocurred:
18
 *
19
 * ```php
20
 * $request = [
21
 *     'username' => 'yiisoft',
22
 * ];
23
 * ```
24
 *
25
 * So to make validation we can configure it like this:
26
 *
27
 * ```php
28
 * $rule = new StopOnError([
29
 *      new HasLength(min: 3),
30
 *      new ExistInDatabase(), // Heavy operation. It would be great not to call it if the previous rule was failed.
31
 *     )];
32
 * ]);
33
 * ```
34
 */
35
final class StopOnErrorHandler implements RuleHandlerInterface
36
{
37 6
    public function __construct(private TranslatorInterface $translator)
38
    {
39
    }
40
41 5
    public function validate(mixed $value, object $rule, ValidationContext $context): Result
42
    {
43 5
        if (!$rule instanceof StopOnError) {
44 1
            throw new UnexpectedRuleException(StopOnError::class, $rule);
45
        }
46
47 4
        if ($rule->getRules() === []) {
48
            throw new InvalidArgumentException(
49
                'Rules for StopOnError rule are required.'
50
            );
51
        }
52
53 4
        $compoundResult = new Result();
54 4
        $results = [];
55
56 4
        foreach ($rule->getRules() as $rule) {
57 4
            $rules = [$rule];
58
59 4
            if (is_iterable($rule)) {
60 1
                $rules = [new StopOnError($rule)];
61
            }
62
63 4
            $lastResult = $context->getValidator()->validate($value, $rules);
64 4
            $results[] = $lastResult;
65
66 4
            if (!$lastResult->isValid()) {
67 3
                break;
68
            }
69
        }
70
71 4
        foreach ($results as $result) {
72 4
            foreach ($result->getErrors() as $error) {
73 3
                $compoundResult->addError($error->getMessage(), $error->getValuePath());
74
            }
75
        }
76
77 4
        return $compoundResult;
78
    }
79
}
80