Completed
Push — master ( f70b57...5f6191 )
by Changwan
06:48
created

Validator::check()   C

Complexity

Conditions 12
Paths 16

Size

Total Lines 34
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 21
CRAP Score 12.0135

Importance

Changes 0
Metric Value
cc 12
eloc 23
nc 16
nop 5
dl 0
loc 34
ccs 21
cts 22
cp 0.9545
crap 12.0135
rs 5.1612
c 0
b 0
f 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
namespace Wandu\Validator;
3
4
use Exception;
5
use Throwable;
6
use Wandu\Validator\Contracts\ErrorThrowable;
7
use Wandu\Validator\Contracts\Validatable;
8
use Wandu\Validator\Exception\InvalidValueException;
9
use Wandu\Validator\Throwable\ErrorBag;
10
use Wandu\Validator\Throwable\ErrorThrower;
11
12
class Validator implements Validatable
13
{
14
    /** @var \Wandu\Validator\TesterLoader */
15
    protected $loader;
16
17
    /** @var \Wandu\Validator\RuleNormalizer */
18
    protected $normalizer;
19
    
20
    /** @var array */
21
    protected $rule;
22
23 6
    public function __construct(TesterLoader $loader, RuleNormalizer $normalizer, $rule)
24
    {
25 6
        $this->loader = $loader;
26 6
        $this->normalizer = $normalizer;
27 6
        $this->rule = $rule;
28 6
    }
29
30
    /**
31
     * {@inheritdoc}
32
     */
33 6
    public function assert($data)
34
    {
35 6
        $errorBag = new ErrorBag();
36 6
        $this->check($this->rule, $errorBag, $data, $data);
37 6
        if (count($errorBag)) {
38 6
            throw new InvalidValueException($errorBag->errors());
39
        }
40 5
    }
41
42
    /**
43
     * @param mixed $data
44
     * @return bool
45
     */
46 6
    public function validate($data): bool
47
    {
48
        try {
49 6
            $this->check($this->rule, new ErrorThrower(), $data, $data);
50 6
            return true;
51 6
        } catch (Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
52
        } catch (Throwable $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
53
        }
54 6
        return false;
55
    }
56
57 6
    public function check($rule, ErrorThrowable $thrower, $data, $origin, $keys = [])
58
    {
59 6
        $dataKeys = array_flip(is_array($data) ? array_keys($data) : []);
60 6
        foreach ($this->normalizer->normalize($rule) as $target => $nextRule) {
61 6
            if (!$target) {
62 6
                foreach ($nextRule as $condition) {
63 6
                    if (!$this->loader->load($condition)->test($data, $origin)) {
64 6
                        $thrower->throws($condition, $keys);
65
                    }
66
                }
67
            } else {
68 5
                $target = TargetName::parse($target);
69 5
                $name = $target->getName();
70 5
                unset($dataKeys[$name]); // remove
71
                // check optional
72 5
                if ($target->isOptional() && !isset($data[$name])) {
73 4
                    continue;
74
                }
75
76 5
                array_push($keys, $name);
77 5
                if (!isset($data[$name])) {
78 5
                    $thrower->throws("required", $keys);
79 5
                } elseif (count($target->getIterator()) && !is_array($data[$name])) {
80
                    $thrower->throws("array", $keys);
81
                } else {
82 5
                    $this->checkIterator($target->getIterator(), $nextRule, $thrower, $data[$name], $origin, $keys);
83
                }
84 6
                array_pop($keys);
85
            }
86
        }
87 6
        foreach ($dataKeys as $dataKey => $_) {
88 3
            $thrower->throws('unknown', array_merge($keys, [$dataKey]));
89
        }
90 6
    }
91
    
92 5
    protected function checkIterator(array $iterators, $rule, ErrorThrowable $thrower, $data, $origin, array $keys = [])
93
    {
94 5
        if (count($iterators)) {
95 3
            $iterator = array_shift($iterators);
96 3
            if ($iterator !== null && $iterator < count($data)) {
97
                $thrower->throws("array_length:{$iterator}", $keys);
98
                return;
99
            }
100 3
            foreach ($data as $index => $value) {
101 3
                array_push($keys, $index);
102 3
                $this->checkIterator($iterators, $rule, $thrower, $value, $origin, $keys);
103 3
                array_pop($keys);
104
            }
105
        } else {
106 5
            $this->check($rule, $thrower, $data, $origin, $keys);
107
        }
108 5
    }
109
}
110