Passed
Push — master ( 5c2907...37dc07 )
by Sergei
24:35 queued 21:56
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\Validator\Exception\UnexpectedRuleException;
9
use Yiisoft\Validator\Result;
10
use Yiisoft\Validator\RuleHandlerInterface;
11
use Yiisoft\Validator\ValidationContext;
12
13
/**
14
 * Can be used for early stopping the validation process of the value when the validation on the stage was failed.
15
 *
16
 * For example, we have several rules, but we want not to process the rest rules when fail was ocurred:
17
 *
18
 * ```php
19
 * $request = [
20
 *     'username' => 'yiisoft',
21
 * ];
22
 * ```
23
 *
24
 * So to make validation we can configure it like this:
25
 *
26
 * ```php
27
 * $rule = new StopOnError([
28
 *      new HasLength(min: 3),
29
 *      new ExistInDatabase(), // Heavy operation. It would be great not to call it if the previous rule was failed.
30
 *     )];
31
 * ]);
32
 * ```
33
 */
34
final class StopOnErrorHandler implements RuleHandlerInterface
35
{
36 5
    public function validate(mixed $value, object $rule, ValidationContext $context): Result
37
    {
38 5
        if (!$rule instanceof StopOnError) {
39 1
            throw new UnexpectedRuleException(StopOnError::class, $rule);
40
        }
41
42 4
        if ($rule->getRules() === []) {
43
            throw new InvalidArgumentException(
44
                'Rules for StopOnError rule are required.'
45
            );
46
        }
47
48 4
        $compoundResult = new Result();
49 4
        $results = [];
50
51 4
        foreach ($rule->getRules() as $rule) {
52 4
            $rules = [$rule];
53
54 4
            if (is_iterable($rule)) {
55 1
                $rules = [new StopOnError($rule)];
56
            }
57
58 4
            $lastResult = $context->getValidator()->validate($value, $rules);
59 4
            $results[] = $lastResult;
60
61 4
            if (!$lastResult->isValid()) {
62 3
                break;
63
            }
64
        }
65
66 4
        foreach ($results as $result) {
67 4
            foreach ($result->getErrors() as $error) {
68 3
                $compoundResult->addError($error->getMessage(), $error->getParameters(), $error->getValuePath());
69
            }
70
        }
71
72 4
        return $compoundResult;
73
    }
74
}
75