ValidatorChain   A
last analyzed

Complexity

Total Complexity 21

Size/Duplication

Total Lines 198
Duplicated Lines 0 %

Test Coverage

Coverage 98%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 40
c 1
b 0
f 0
dl 0
loc 198
ccs 49
cts 50
cp 0.98
rs 10
wmc 21

13 Methods

Rating   Name   Duplication   Size   Complexity  
A getDescription() 0 9 2
A getError() 0 3 1
A callback() 0 8 2
A __toString() 0 3 1
A regexp() 0 8 2
A setDescription() 0 4 1
A isRequired() 0 8 3
A validate() 0 11 3
A addRule() 0 4 1
A setError() 0 4 1
A assert() 0 4 2
A __call() 0 4 1
A __invoke() 0 3 1
1
<?php
2
3
/**
4
 * Bluz Framework Component
5
 *
6
 * @copyright Bluz PHP Team
7
 * @link      https://github.com/bluzphp/framework
8
 */
9
10
declare(strict_types=1);
11
12
namespace Bluz\Validator;
13
14
use Bluz\Validator\Exception\ComponentException;
15
use Bluz\Validator\Exception\ValidatorException;
16
use Bluz\Validator\Rule\RequiredRule;
17
use Bluz\Validator\Rule\RuleInterface;
18
19
/**
20
 * Chain of Validators
21
 *
22
 * Chain can consists one or more validation rules
23
 *
24
 * @package  Bluz\Validator
25
 * @author   Anton Shevchuk
26
 *
27
 * @method ValidatorChain alpha($additionalCharacters = '')
28
 * @method ValidatorChain alphaNumeric($additionalCharacters = '')
29
 * @method ValidatorChain array($callback)
30
 * @method ValidatorChain between($min, $max)
31
 * @method ValidatorChain betweenInclusive($min, $max)
32
 * @method ValidatorChain condition($condition)
33
 * @method ValidatorChain contains($containsValue)
34
 * @method ValidatorChain containsStrict($containsValue)
35
 * @method ValidatorChain countryCode()
36
 * @method ValidatorChain creditCard()
37
 * @method ValidatorChain date($format)
38
 * @method ValidatorChain domain($checkDns = false)
39
 * @method ValidatorChain email($checkDns = false)
40
 * @method ValidatorChain equals($compareTo)
41
 * @method ValidatorChain equalsStrict($compareTo)
42
 * @method ValidatorChain float()
43
 * @method ValidatorChain in($haystack)
44
 * @method ValidatorChain inStrict($haystack)
45
 * @method ValidatorChain integer()
46
 * @method ValidatorChain ip($options = null)
47
 * @method ValidatorChain json()
48
 * @method ValidatorChain latin($additionalCharacters = '')
49
 * @method ValidatorChain latinNumeric($additionalCharacters = '')
50
 * @method ValidatorChain length($min = null, $max = null)
51
 * @method ValidatorChain less($maxValue)
52
 * @method ValidatorChain lessOrEqual($maxValue)
53
 * @method ValidatorChain more($minValue)
54
 * @method ValidatorChain moreOrEqual($minValue)
55
 * @method ValidatorChain notEmpty()
56
 * @method ValidatorChain noWhitespace()
57
 * @method ValidatorChain numeric()
58
 * @method ValidatorChain required()
59
 * @method ValidatorChain slug()
60
 * @method ValidatorChain string()
61
 */
62
class ValidatorChain implements ValidatorInterface
63
{
64
    /**
65
     * @var string description of rules chain
66
     */
67
    protected $description;
68
69
    /**
70
     * @var RuleInterface[] list of validation rules
71
     */
72
    protected $rules = [];
73
74
    /**
75
     * @var string Error message
76
     */
77
    protected $error;
78
79
    /**
80
     * Magic call for create new rule
81
     *
82
     * @param  string $ruleName
83
     * @param  array  $arguments
84
     *
85
     * @return ValidatorChain
86
     * @throws Exception\ComponentException
87
     */
88 13
    public function __call($ruleName, $arguments): ValidatorChain
89
    {
90 13
        $this->addRule(Validator::rule($ruleName, $arguments));
91 12
        return $this;
92
    }
93
94
    /**
95
     * Add Rule to ValidatorChain
96
     *
97
     * @param RuleInterface $rule
98
     *
99
     * @return ValidatorChain
100
     */
101 21
    public function addRule(RuleInterface $rule): ValidatorChain
102
    {
103 21
        $this->rules[] = $rule;
104 21
        return $this;
105
    }
106
107
    /**
108
     * Get required flag
109
     *
110
     * @return bool
111
     */
112 3
    public function isRequired(): bool
113
    {
114 3
        foreach ($this->rules as $rule) {
115 3
            if ($rule instanceof RequiredRule) {
116 3
                return true;
117
            }
118
        }
119 2
        return false;
120
    }
121
122
    /**
123
     * Add Callback Rule to ValidatorChain
124
     *
125
     * @param mixed       $callable
126
     * @param string|null $description
127
     *
128
     * @return ValidatorChain
129
     * @throws ComponentException
130
     */
131 10
    public function callback($callable, ?string $description = null): ValidatorChain
132
    {
133 10
        $rule = Validator::rule('callback', [$callable]);
134 10
        if (null !== $description) {
135 3
            $rule->setDescription($description);
136
        }
137 10
        $this->addRule($rule);
138 10
        return $this;
139
    }
140
141
    /**
142
     * Add Regexp Rule to ValidatorChain
143
     *
144
     * @param string $expression
145
     * @param string|null $description
146
     *
147
     * @return ValidatorChain
148
     * @throws ComponentException
149
     */
150 1
    public function regexp(string $expression, ?string $description = null): ValidatorChain
151
    {
152 1
        $rule = Validator::rule('regexp', [$expression]);
153 1
        if (null !== $description) {
154 1
            $rule->setDescription($description);
155
        }
156 1
        $this->addRule($rule);
157 1
        return $this;
158
    }
159
160
    /**
161
     * Validate chain of rules
162
     *
163
     * @param mixed $input
164
     *
165
     * @return bool
166
     */
167 15
    public function validate($input): bool
168
    {
169 15
        $this->error = null; // clean
170 15
        foreach ($this->rules as $rule) {
171 15
            if (!$rule->validate($input)) {
172
                // apply custom description or use description from rule
173 9
                $this->setError($this->description ?? $rule->getDescription());
174 9
                return false;
175
            }
176
        }
177 7
        return true;
178
    }
179
180
    /**
181
     * Assert
182
     *
183
     * @param  mixed $input
184
     *
185
     * @throws ValidatorException
186
     */
187 3
    public function assert($input): void
188
    {
189 3
        if (!$this->validate($input)) {
190 3
            throw new ValidatorException($this->getError());
191
        }
192
    }
193
194
    /**
195
     * @inheritdoc
196
     */
197 2
    public function __invoke($input): bool
198
    {
199 2
        return $this->validate($input);
200
    }
201
202
    /**
203
     * @inheritdoc
204
     */
205 1
    public function __toString(): string
206
    {
207 1
        return implode("\n", $this->getDescription());
208
    }
209
210
    /**
211
     * Get error message
212
     *
213
     * @return null|string
214
     */
215 8
    public function getError(): ?string
216
    {
217 8
        return $this->error;
218
    }
219
220
    /**
221
     * Set error message for replace text from rule
222
     *
223
     * @param string $message
224
     *
225
     * @return ValidatorChain
226
     */
227 9
    protected function setError(string $message): ValidatorChain
228
    {
229 9
        $this->error = $message;
230 9
        return $this;
231
    }
232
233
    /**
234
     * Get validation description
235
     *
236
     * @return array
237
     */
238 5
    public function getDescription(): array
239
    {
240
        // apply custom description
241 5
        if ($this->description) {
242 2
            return [$this->description];
243
        }
244
245
        // eject description from rules
246 4
        return array_map('\strval', $this->rules);
247
    }
248
249
    /**
250
     * Set validation description
251
     *
252
     * @param string $message
253
     *
254
     * @return ValidatorChain
255
     */
256 4
    public function setDescription(string $message): ValidatorChain
257
    {
258 4
        $this->description = $message;
259 4
        return $this;
260
    }
261
}
262