Passed
Push — master ( 893d1e...31005e )
by Kirill
03:35
created

Validator::validate()   B

Complexity

Conditions 10
Paths 9

Size

Total Lines 29
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 15
c 1
b 0
f 0
dl 0
loc 29
rs 7.6666
cc 10
nc 9
nop 0

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
/**
4
 * Spiral Framework.
5
 *
6
 * @license   MIT
7
 * @author    Anton Titov (Wolfy-J)
8
 */
9
10
declare(strict_types=1);
11
12
namespace Spiral\Validation;
13
14
use Spiral\Validation\Exception\ValidationException;
15
16
final class Validator implements ValidatorInterface
17
{
18
    /** @var RulesInterface */
19
    private $provider;
20
21
    /** @var array|\ArrayAccess */
22
    private $data;
23
24
    /** @var array */
25
    private $errors;
26
27
    /** @var mixed */
28
    private $context;
29
30
    /** @var array */
31
    private $rules;
32
33
    /**
34
     * @param array|\ArrayAccess $data
35
     * @param array              $rules
36
     * @param mixed              $context
37
     * @param RulesInterface     $ruleProvider
38
     */
39
    public function __construct($data, array $rules, $context, RulesInterface $ruleProvider)
40
    {
41
        $this->data = $data;
42
        $this->errors = [];
43
        $this->rules = $rules;
44
        $this->context = $context;
45
        $this->provider = $ruleProvider;
46
    }
47
48
    /**
49
     * Destruct the service.
50
     */
51
    public function __destruct()
52
    {
53
        $this->data = null;
54
        $this->rules = [];
55
        $this->provider = null;
56
        $this->errors = [];
57
    }
58
59
    /**
60
     * @inheritdoc
61
     */
62
    public function withData($data): ValidatorInterface
63
    {
64
        $validator = clone $this;
65
        $validator->data = $data;
66
        $validator->errors = [];
67
68
        return $validator;
69
    }
70
71
    /**
72
     * @inheritdoc
73
     */
74
    public function getValue(string $field, $default = null)
75
    {
76
        $value = $this->data[$field] ?? $default;
77
78
        if (is_object($value) && method_exists($value, 'getValue')) {
79
            return $value->getValue();
80
        }
81
82
        return $value;
83
    }
84
85
    /**
86
     * @inheritdoc
87
     */
88
    public function hasValue(string $field): bool
89
    {
90
        if (is_array($this->data)) {
91
            return array_key_exists($field, $this->data);
92
        }
93
94
        return isset($this->data[$field]);
95
    }
96
97
    /**
98
     * @inheritdoc
99
     */
100
    public function withContext($context): ValidatorInterface
101
    {
102
        $validator = clone $this;
103
        $validator->context = $context;
104
        $validator->errors = [];
105
106
        return $validator;
107
    }
108
109
    /**
110
     * @inheritdoc
111
     */
112
    public function getContext()
113
    {
114
        return $this->context;
115
    }
116
117
    /**
118
     * @inheritdoc
119
     */
120
    public function isValid(): bool
121
    {
122
        return $this->getErrors() === [];
123
    }
124
125
    /**
126
     * @inheritdoc
127
     */
128
    public function getErrors(): array
129
    {
130
        $this->validate();
131
132
        return $this->errors;
133
    }
134
135
    /**
136
     * Check if value has any error associated.
137
     *
138
     * @param string $field
139
     *
140
     * @return bool
141
     */
142
    public function hasError(string $field): bool
143
    {
144
        return isset($this->getErrors()[$field]);
145
    }
146
147
    /**
148
     * Validate data over given rules and context.
149
     *
150
     * @throws ValidationException
151
     */
152
    protected function validate(): void
153
    {
154
        if ($this->errors !== []) {
155
            // already validated
156
            return;
157
        }
158
159
        $this->errors = [];
160
161
        foreach ($this->rules as $field => $rules) {
162
            $hasValue = $this->hasValue($field);
163
            $value = $this->getValue($field);
164
165
            foreach ($this->provider->getRules($rules) as $rule) {
166
                if (!$hasValue && $rule->ignoreEmpty($value) && !$rule->hasConditions()) {
167
                    continue;
168
                }
169
170
                foreach ($rule->getConditions() as $condition) {
171
                    if (!$condition->isMet($this, $field, $value)) {
172
                        // condition is not met, skipping validation
173
                        continue 2;
174
                    }
175
                }
176
177
                if (!$rule->validate($this, $field, $value)) {
178
                    // got error, jump to next field
179
                    $this->errors[$field] = $rule->getMessage($field, $value);
180
                    break;
181
                }
182
            }
183
        }
184
    }
185
}
186