Passed
Pull Request — master (#222)
by Dmitriy
02:26
created

NestedHandler::validate()   C

Complexity

Conditions 12
Paths 26

Size

Total Lines 48
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 27
CRAP Score 12

Importance

Changes 0
Metric Value
eloc 26
dl 0
loc 48
ccs 27
cts 27
cp 1
rs 6.9666
c 0
b 0
f 0
cc 12
nc 26
nop 4
crap 12

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Validator\Rule\Nested;
6
7
use Yiisoft\Arrays\ArrayHelper;
8
use Yiisoft\Validator\Result;
9
use Yiisoft\Validator\Rule\RuleHandlerInterface;
10
use Yiisoft\Validator\ValidationContext;
11
use Yiisoft\Validator\ValidatorInterface;
12
use function is_array;
13
use function is_object;
14
use Yiisoft\Validator\Exception\UnexpectedRuleException;
15
16
/**
17
 * Can be used for validation of nested structures.
18
 *
19
 * For example, we have an inbound request with the following structure:
20
 *
21
 * ```php
22
 * $request = [
23
 *     'author' => [
24
 *         'name' => 'Dmitry',
25
 *         'age' => 18,
26
 *     ],
27
 * ];
28
 * ```
29
 *
30
 * So to make validation we can configure it like this:
31
 *
32
 * ```php
33
 * $rule = new Nested([
34
 *     'author' => new Nested([
35
 *         'name' => [new HasLength(min: 3)],
36
 *         'age' => [new Number(min: 18)],
37
 *     )];
38
 * ]);
39
 * ```
40
 */
41
final class NestedHandler implements RuleHandlerInterface
42
{
43 12
    public function validate(mixed $value, object $rule, ValidatorInterface $validator, ?ValidationContext $context = null): Result
44
    {
45 12
        if (!$rule instanceof Nested) {
46 1
            throw new UnexpectedRuleException(Nested::class, $rule);
47
        }
48
49 11
        $compoundResult = new Result();
50 11
        if (!is_object($value) && !is_array($value)) {
51 1
            $message = sprintf('Value should be an array or an object. %s given.', gettype($value));
52 1
            $compoundResult->addError($message);
53
54 1
            return $compoundResult;
55
        }
56
57 10
        $value = (array)$value;
58
59 10
        $results = [];
60 10
        foreach ($rule->rules as $valuePath => $rules) {
61 10
            $result = new Result((string)$valuePath);
62
63 10
            if ($rule->errorWhenPropertyPathIsNotFound && !ArrayHelper::pathExists($value, $valuePath)) {
64 2
                $compoundResult->addError($rule->propertyPathIsNotFoundMessage, ['path' => $valuePath], $valuePath);
65
66 2
                continue;
67
            }
68
69 8
            $rules = is_array($rules) ? $rules : [$rules];
70 8
            $validatedValue = ArrayHelper::getValueByPath($value, $valuePath);
71
72 8
            $itemResult = $validator->validate($validatedValue, $rules);
73
74 8
            if ($itemResult->isValid()) {
75 3
                continue;
76
            }
77
78 5
            foreach ($itemResult->getErrors() as $error) {
79 5
                $result->mergeError($error);
80
            }
81 5
            $results[] = $result;
82
        }
83
84 10
        foreach ($results as $result) {
85 5
            foreach ($result->getErrors() as $error) {
86 5
                $compoundResult->mergeError($error);
87
            }
88
        }
89
90 10
        return $compoundResult;
91
    }
92
}
93