Completed
Push — master ( 7bea36...115690 )
by Rick
03:28
created

Chain   B

Complexity

Total Complexity 43

Size/Duplication

Total Lines 464
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 100%

Importance

Changes 22
Bugs 1 Features 9
Metric Value
wmc 43
c 22
b 1
f 9
lcom 1
cbo 3
dl 0
loc 464
ccs 100
cts 100
cp 1
rs 8.3157

36 Methods

Rating   Name   Duplication   Size   Complexity  
A alnum() 0 4 1
A alpha() 0 4 1
A bool() 0 4 1
A callback() 0 4 1
A __construct() 0 8 1
A __clone() 0 8 2
A creditCard() 0 4 1
A datetime() 0 4 1
A digits() 0 4 1
A each() 0 4 1
A email() 0 4 1
A equals() 0 4 1
A between() 0 4 1
A float() 0 4 1
A integer() 0 4 1
A isArray() 0 4 1
A json() 0 4 1
A lengthBetween() 0 4 1
A lessThan() 0 4 1
A mount() 0 4 1
A phone() 0 4 1
A regex() 0 4 1
A greaterThan() 0 4 1
A inArray() 0 4 1
A length() 0 4 1
A numeric() 0 4 1
A string() 0 4 1
A url() 0 4 1
A getRequiredRule() 0 4 1
A uuid() 0 4 1
A required() 0 5 1
A allowEmpty() 0 5 1
A output() 0 12 2
B validate() 0 19 6
A addRule() 0 6 1
A getNotEmptyRule() 0 4 1

How to fix   Complexity   

Complex Class

Complex classes like Chain often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Chain, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * Particle.
4
 *
5
 * @link      http://github.com/particle-php for the canonical source repository
6
 * @copyright Copyright (c) 2005-2016 Particle (http://particle-php.com)
7
 * @license   https://github.com/particle-php/validator/blob/master/LICENSE New BSD License
8
 */
9
namespace Particle\Validator;
10
11
use Particle\Validator\Output\Structure;
12
use Particle\Validator\Output\Subject;
13
use Particle\Validator\Value\Container;
14
15
/**
16
 * Represents a collection of Rules which may break the chain of validation (but usually don't).
17
 *
18
 * @package Particle\Validator
19
 */
20
class Chain
21
{
22
    /**
23
     * The key we want to validate.
24
     *
25
     * @var string
26
     */
27
    protected $key;
28
29
    /**
30
     * The name that we can use in error messages.
31
     *
32
     * @var string
33
     */
34
    protected $name;
35
36
    /**
37
     * The array of all rules for this chain.
38
     *
39
     * @var Rule[]
40
     */
41
    protected $rules = [];
42
43
    /**
44
     * The message stack to append messages to.
45
     *
46
     * @var MessageStack
47
     */
48
    protected $messageStack;
49
50
    /**
51
     * Construct the chain.
52
     *
53
     * @param string $key
54
     * @param string $name
55
     * @param bool $required
56
     * @param bool $allowEmpty
57
     */
58 207
    public function __construct($key, $name, $required, $allowEmpty)
59
    {
60 207
        $this->key = $key;
61 207
        $this->name = $name;
62
63 207
        $this->addRule(new Rule\Required($required));
64 207
        $this->addRule(new Rule\NotEmpty($allowEmpty));
65 207
    }
66
67
    /**
68
     * Overwrite the default __clone behaviour to make sure the rules are cloned too.
69
     */
70 3
    public function __clone()
71
    {
72 3
        $rules = [];
73 3
        foreach ($this->rules as $rule) {
74 3
            $rules[] = clone $rule;
75 3
        }
76 3
        $this->rules = $rules;
77 3
    }
78
79
    /**
80
     * Validate the value to consist only out of alphanumeric characters.
81
     *
82
     * @param bool $allowWhitespace
83
     * @return $this
84
     */
85 7
    public function alnum($allowWhitespace = false)
86
    {
87 7
        return $this->addRule(new Rule\Alnum($allowWhitespace));
88
    }
89
90
    /**
91
     * Validate that the value only consists our of alphabetic characters.
92
     *
93
     * @param bool $allowWhitespace
94
     * @return $this
95
     */
96 7
    public function alpha($allowWhitespace = false)
97
    {
98 7
        return $this->addRule(new Rule\Alpha($allowWhitespace));
99
    }
100
101
    /**
102
     * Validate that the value is between $min and $max (inclusive).
103
     *
104
     * @param int $min
105
     * @param int $max
106
     * @return $this
107
     */
108 6
    public function between($min, $max)
109
    {
110 6
        return $this->addRule(new Rule\Between($min, $max));
111
    }
112
113
    /**
114
     * Validate that the value is a boolean.
115
     *
116
     * @return $this
117
     */
118 9
    public function bool()
119
    {
120 9
        return $this->addRule(new Rule\Boolean());
121
    }
122
123
    /**
124
     * Validate by executing a callback function, and returning its result.
125
     *
126
     * @param callable $callable
127
     * @return $this
128
     */
129 5
    public function callback(callable $callable)
130
    {
131 5
        return $this->addRule(new Rule\Callback($callable));
132
    }
133
134
    /**
135
     * Validates that the value is a valid credit card number.
136
     * @return $this
137
     */
138 15
    public function creditCard()
139
    {
140 15
        return $this->addRule(new Rule\CreditCard());
141
    }
142
143
    /**
144
     * Validates that the value is a date. If format is passed, it *must* be in that format.
145
     *
146
     * @param string|null $format
147
     * @return $this
148
     */
149 8
    public function datetime($format = null)
150
    {
151 8
        return $this->addRule(new Rule\Datetime($format));
152
    }
153
154
    /**
155
     * Validates that all characters of the value are decimal digits.
156
     *
157
     * @return $this
158
     */
159 4
    public function digits()
160
    {
161 4
        return $this->addRule(new Rule\Digits());
162
    }
163
164
    /**
165
     * Validates a value to be a nested array, which can then be validated using a new Validator instance.
166
     *
167
     * @param callable $callback
168
     * @return $this
169
     */
170 5
    public function each(callable $callback)
171
    {
172 5
        return $this->addRule(new Rule\Each($callback));
173
    }
174
175
    /**
176
     * Validates that the value is a valid email address (format only).
177
     * @return $this
178
     */
179 6
    public function email()
180
    {
181 6
        return $this->addRule(new Rule\Email());
182
    }
183
184
    /**
185
     * Validates that the value is equal to $value.
186
     *
187
     * @param string $value
188
     * @return $this
189
     */
190 2
    public function equals($value)
191
    {
192 2
        return $this->addRule(new Rule\Equal($value));
193
    }
194
195
    /**
196
     * Validates that the value represents a float.
197
     *
198
     * @return $this
199
     */
200 6
    public function float()
201
    {
202 6
        return $this->addRule(new Rule\IsFloat());
203
    }
204
205
    /**
206
     * Validates that the value is greater than $value.
207
     *
208
     * @param int $value
209
     * @return $this
210
     */
211 3
    public function greaterThan($value)
212
    {
213 3
        return $this->addRule(new Rule\GreaterThan($value));
214
    }
215
216
    /**
217
     * Validates that the value is in the array with optional "loose" checking.
218
     *
219
     * @param array $array
220
     * @param bool $strict
221
     * @return $this
222
     */
223 4
    public function inArray(array $array, $strict = true)
224
    {
225 4
        return $this->addRule(new Rule\InArray($array, $strict));
226
    }
227
228
    /**
229
     * Validates the value represents a valid integer
230
     *
231
     * @param bool $strict
232
     * @return $this
233
     * @see \Particle\Validator\Rule\Integer
234
     */
235 18
    public function integer($strict = false)
236
    {
237 18
        return $this->addRule(new Rule\Integer($strict));
238
    }
239
240
    /**
241
     * Validates the value is an array
242
     *
243
     * @return $this
244
     * @see \Particle\Validator\Rule\IsArray
245
     */
246 7
    public function isArray()
247
    {
248 7
        return $this->addRule(new Rule\IsArray());
249
    }
250
251
    /**
252
     * Validates that the value represents a valid JSON string
253
     *
254
     * @return $this
255
     * @see \Particle\Validator\Rule\Json
256
     */
257 11
    public function json()
258
    {
259 11
        return $this->addRule(new Rule\Json());
260
    }
261
262
    /**
263
     * Validate the value to be of precisely length $length.
264
     *
265
     * @param int $length
266
     * @return $this
267
     */
268 13
    public function length($length)
269
    {
270 13
        return $this->addRule(new Rule\Length($length));
271
    }
272
273
    /**
274
     * Validates that the length of the value is between $min and $max.
275
     *
276
     * If $max is null, it has no upper limit. The default is inclusive.
277
     *
278
     * @param int $min
279
     * @param int|null $max
280
     * @return $this
281
     */
282 7
    public function lengthBetween($min, $max)
283
    {
284 7
        return $this->addRule(new Rule\LengthBetween($min, $max));
285
    }
286
287
    /**
288
     * Validates that the value is less than $value.
289
     *
290
     * @param int $value
291
     * @return $this
292
     */
293 3
    public function lessThan($value)
294
    {
295 3
        return $this->addRule(new Rule\LessThan($value));
296
    }
297
298
    /**
299
     * Mount a rule object onto this chain.
300
     *
301
     * @param Rule $rule
302
     * @return $this
303
     */
304 1
    public function mount(Rule $rule)
305
    {
306 1
        return $this->addRule($rule);
307
    }
308
309
    /**
310
     * Validates that the value is either a integer or a float.
311
     *
312
     * @return $this
313
     */
314 11
    public function numeric()
315
    {
316 11
        return $this->addRule(new Rule\Numeric());
317
    }
318
319
    /**
320
     * Validates that the value is a valid phone number for $countryCode.
321
     *
322
     * @param string $countryCode
323
     * @see \Particle\Validator\Rule\Phone
324
     * @return $this
325
     */
326 13
    public function phone($countryCode)
327
    {
328 13
        return $this->addRule(new Rule\Phone($countryCode));
329
    }
330
331
    /**
332
     * Validates that the value matches the regular expression $regex.
333
     *
334
     * @param string $regex
335
     * @return $this
336
     */
337 2
    public function regex($regex)
338
    {
339 2
        return $this->addRule(new Rule\Regex($regex));
340
    }
341
342
    /**
343
     * Validates that the value represents a string.
344
     *
345
     * @return $this
346
     */
347 5
    public function string()
348
    {
349 5
        return $this->addRule(new Rule\IsString());
350
    }
351
352
    /**
353
     * Validates that the value is a valid URL. The schemes array is to selectively whitelist URL schemes.
354
     *
355
     * @param array $schemes
356
     * @return $this
357
     */
358 7
    public function url(array $schemes = [])
359
    {
360 7
        return $this->addRule(new Rule\Url($schemes));
361
    }
362
363
    /**
364
     * Validates that the value is a valid UUID
365
     *
366
     * @param int $version
367
     * @return $this
368
     */
369 12
    public function uuid($version = Rule\Uuid::UUID_V4)
370
    {
371 12
        return $this->addRule(new Rule\Uuid($version));
372
    }
373
374
    /**
375
     * Set a callable or boolean value which may be used to alter the required requirement on validation time.
376
     *
377
     * This may be incredibly helpful when doing conditional validation.
378
     *
379
     * @param callable|bool $required
380
     * @return $this
381
     */
382 5
    public function required($required)
383
    {
384 5
        $this->getRequiredRule()->setRequired($required);
385 5
        return $this;
386
    }
387
388
    /**
389
     * Set a callable or boolean value which may be used to alter the allow empty requirement on validation time.
390
     *
391
     * This may be incredibly helpful when doing conditional validation.
392
     *
393
     * @param callable|bool $allowEmpty
394
     * @return $this
395
     */
396 11
    public function allowEmpty($allowEmpty)
397
    {
398 11
        $this->getNotEmptyRule()->setAllowEmpty($allowEmpty);
399 11
        return $this;
400
    }
401
402
    /**
403
     * Attach a representation of this Chain to the Output\Structure $structure.
404
     *
405
     * @internal
406
     * @param Structure $structure
407
     * @param MessageStack $messageStack
408
     * @return Structure
409
     */
410 2
    public function output(Structure $structure, MessageStack $messageStack)
411
    {
412 2
        $subject = new Subject($this->key, $this->name);
413
414 2
        foreach ($this->rules as $rule) {
415 2
            $rule->output($subject, $messageStack);
416 2
        }
417
418 2
        $structure->addSubject($subject);
419
420 2
        return $structure;
421
    }
422
423
    /**
424
     * Validates the values in the $values array and appends messages to $messageStack. Returns the result as a bool.
425
     *
426
     * @param MessageStack $messageStack
427
     * @param Container $input
428
     * @param Container $output
429
     * @return bool
430
     */
431 204
    public function validate(MessageStack $messageStack, Container $input, Container $output)
432
    {
433 204
        $valid = true;
434 204
        foreach ($this->rules as $rule) {
435 204
            $rule->setMessageStack($messageStack);
436 204
            $rule->setParameters($this->key, $this->name);
437
438 204
            $valid = $rule->isValid($this->key, $input) && $valid;
439
440 204
            if ($rule->shouldBreakChain()) {
441 17
                break;
442
            }
443 204
        }
444
445 204
        if ($valid && $input->has($this->key)) {
446 104
            $output->set($this->key, $input->get($this->key));
447 104
        }
448 204
        return $valid;
449
    }
450
451
    /**
452
     * Shortcut method for storing a rule on this chain, and returning the chain.
453
     *
454
     * @param Rule $rule
455
     * @return $this
456
     */
457 207
    protected function addRule(Rule $rule)
458
    {
459 207
        $this->rules[] = $rule;
460
461 207
        return $this;
462
    }
463
464
    /**
465
     * Returns the first rule, which is always the required rule.
466
     *
467
     * @return Rule\Required
468
     */
469 5
    protected function getRequiredRule()
470
    {
471 5
        return $this->rules[0];
472
    }
473
474
    /**
475
     * Returns the second rule, which is always the allow empty rule.
476
     *
477
     * @return Rule\NotEmpty
478
     */
479 11
    protected function getNotEmptyRule()
480
    {
481 11
        return $this->rules[1];
482
    }
483
}
484