Passed
Pull Request — master (#222)
by Alexander
04:54 queued 02:26
created

Validator::validate()   C

Complexity

Conditions 10
Paths 204

Size

Total Lines 50
Code Lines 30

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 26
CRAP Score 10.005

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 10
eloc 30
c 2
b 0
f 0
nc 204
nop 2
dl 0
loc 50
ccs 26
cts 27
cp 0.963
crap 10.005
rs 6.7833

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;
6
7
use InvalidArgumentException;
8
use JetBrains\PhpStorm\Pure;
9
use Psr\Container\ContainerExceptionInterface;
10
use Psr\Container\NotFoundExceptionInterface;
11
use Yiisoft\Validator\DataSet\ArrayDataSet;
12
use Yiisoft\Validator\DataSet\ScalarDataSet;
13
use Yiisoft\Validator\Rule\Callback\Callback;
14
use function is_array;
15
use function is_object;
16
17
/**
18
 * Validator validates {@link DataSetInterface} against rules set for data set attributes.
19
 */
20
final class Validator implements ValidatorInterface
21
{
22
    public const PARAMETER_PREVIOUS_RULES_ERRORED = 'previousRulesErrored';
23
24
    private RuleHandlerResolverInterface $ruleHandlerResolver;
25
26 513
    public function __construct(RuleHandlerResolverInterface $ruleHandlerResolver)
27
    {
28 513
        $this->ruleHandlerResolver = $ruleHandlerResolver;
29
    }
30
31
    /**
32
     * @param DataSetInterface|mixed|RulesProviderInterface $data
33
     * @param iterable<RuleInterface|RuleInterface[]> $rules
34
     */
35 28
    public function validate($data, iterable $rules = []): Result
36
    {
37 28
        $data = $this->normalizeDataSet($data);
38 28
        if ($data instanceof RulesProviderInterface) {
39 2
            $rules = $data->getRules();
40
        }
41
42 28
        $context = new ValidationContext($data);
43 28
        $compoundResult = new Result();
44
45 28
        $results = [];
46
47 28
        foreach ($rules as $attribute => $attributeRules) {
48 28
            $attributeName = is_string($attribute) ? $attribute : null;
49 28
            $result = new Result($attributeName);
50
51 28
            $tempRule = is_array($attributeRules) ? $attributeRules : [$attributeRules];
52 28
            $attributeRules = $this->normalizeRules($tempRule);
53
54 28
            if (is_int($attribute)) {
55 16
                $validatedData = $data->getData();
56 16
                $validatedContext = $context;
57
            } else {
58 12
                $validatedData = $data->getAttributeValue($attribute);
59 12
                $validatedContext = $context->withAttribute($attribute);
60
            }
61
62 28
            $tempResult = $this->validateInternal(
63
                $validatedData,
64
                $attributeRules,
65
                $validatedContext
66
            );
67
68 28
            foreach ($tempResult->getErrors() as $error) {
69 14
                $result->merge($error);
70
            }
71 28
            $results[] = $result;
72
        }
73
74 28
        foreach ($results as $result) {
75 28
            foreach ($result->getErrors() as $error) {
76 14
                $compoundResult->merge($error);
77
            }
78
        }
79
80 28
        if ($data instanceof PostValidationHookInterface) {
81
            $data->processValidationResult($compoundResult);
82
        }
83
84 28
        return $compoundResult;
85
    }
86
87 28
    #[Pure]
88
    private function normalizeDataSet($data): DataSetInterface
89
    {
90 28
        if ($data instanceof DataSetInterface) {
91 5
            return $data;
92
        }
93
94 23
        if (is_object($data) || is_array($data)) {
95 4
            return new ArrayDataSet((array)$data);
96
        }
97
98 22
        return new ScalarDataSet($data);
99
    }
100
101
    /**
102
     * @param $value
103
     * @param iterable<RuleInterface> $rules
104
     * @param ValidationContext $context
105
     *
106
     * @throws ContainerExceptionInterface
107
     * @throws NotFoundExceptionInterface
108
     *
109
     * @return Result
110
     */
111 28
    private function validateInternal($value, iterable $rules, ValidationContext $context): Result
112
    {
113 28
        $compoundResult = new Result();
114 28
        foreach ($rules as $rule) {
115 28
            $ruleHandler = $this->ruleHandlerResolver->resolve($rule);
116 28
            $ruleResult = $ruleHandler->validate($value, $rule, $this, $context);
117 28
            if ($ruleResult->isValid()) {
118 23
                continue;
119
            }
120
121 14
            $context->setParameter(self::PARAMETER_PREVIOUS_RULES_ERRORED, true);
122
123 14
            foreach ($ruleResult->getErrors() as $error) {
124 14
                $compoundResult->merge($error);
125
            }
126
        }
127 28
        return $compoundResult;
128
    }
129
130
    /**
131
     * @param array $rules
132
     *
133
     * @return iterable<RuleInterface>
134
     */
135 28
    private function normalizeRules(iterable $rules): iterable
136
    {
137 28
        foreach ($rules as $rule) {
138 28
            yield $this->normalizeRule($rule);
139
        }
140
    }
141
142 28
    private function normalizeRule($rule): RuleInterface
143
    {
144 28
        if (is_callable($rule)) {
145 3
            return new Callback($rule);
146
        }
147
148 28
        if (!$rule instanceof RuleInterface) {
149
            throw new InvalidArgumentException(sprintf(
150
                'Rule should be either an instance of %s or a callable, %s given.',
151
                RuleInterface::class,
152
                gettype($rule)
153
            ));
154
        }
155
156 28
        return $rule;
157
    }
158
}
159