Validator::checkSingle()   C
last analyzed

Complexity

Conditions 11
Paths 30

Size

Total Lines 29
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 19
CRAP Score 11.0151

Importance

Changes 0
Metric Value
cc 11
eloc 20
nc 30
nop 5
dl 0
loc 29
ccs 19
cts 20
cp 0.95
crap 11.0151
rs 5.2653
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\RuleNormalizable;
8
use Wandu\Validator\Contracts\Validatable;
9
use Wandu\Validator\Exception\InvalidValueException;
10
use Wandu\Validator\Throwable\ErrorBag;
11
use Wandu\Validator\Throwable\ErrorThrower;
12
13
class Validator implements Validatable
14
{
15
    /** @var \Wandu\Validator\TesterLoader */
16
    protected $loader;
17
18
    /** @var \Wandu\Validator\Contracts\RuleNormalizable */
19
    protected $normalizer;
20
    
21
    /** @var array */
22
    protected $rule;
23
24 8
    public function __construct(TesterLoader $loader, RuleNormalizable $normalizer, $rule)
25
    {
26 8
        $this->loader = $loader;
27 8
        $this->normalizer = $normalizer;
28 8
        $this->rule = $rule;
29 8
    }
30
31
    /**
32
     * {@inheritdoc}
33
     */
34 8
    public function assert($data)
35
    {
36 8
        $errorBag = new ErrorBag();
37 8
        $this->check($this->rule, $errorBag, $data, $data);
38 8
        if (count($errorBag)) {
39 8
            throw new InvalidValueException($errorBag->errors());
40
        }
41 7
    }
42
43
    /**
44
     * @param mixed $data
45
     * @return bool
46
     */
47 6
    public function validate($data): bool
48
    {
49
        try {
50 6
            $this->check($this->rule, new ErrorThrower(), $data, $data);
51 6
            return true;
52 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...
53
        } catch (Throwable $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
54
        }
55 6
        return false;
56
    }
57
58 8
    public function check($rule, ErrorThrowable $thrower, $data, $origin, $keys = [])
59
    {
60 8
        $this->checkSingle($this->normalizer->normalize($rule), $thrower, $data, $origin, $keys);
61 8
    }
62
63 8
    public function checkSingle($normalizedRule, ErrorThrowable $thrower, $data, $origin, $keys = [])
64
    {
65 8
        $dataKeys = array_flip(is_array($data) ? array_keys($data) : []);
66 8
        list($conditions, $attributes) = $normalizedRule;
67 8
        foreach ($conditions as $condition) {
68 8
            if (!$this->loader->load($condition)->test($data, $origin)) {
69 8
                $thrower->throws($condition, $keys);
70
            }
71
        }
72 8
        foreach ($attributes as list(list($name, $iterator, $optional), $children)) {
73 7
            unset($dataKeys[$name]); // remove
74
            // check optional
75 7
            if ($optional && !isset($data[$name])) {
0 ignored issues
show
Bug introduced by
The variable $optional does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $name seems to never exist, and therefore isset should always return false. Did you maybe rename this variable?

This check looks for calls to isset(...) or empty() on variables that are yet undefined. These calls will always produce the same result and can be removed.

This is most likely caused by the renaming of a variable or the removal of a function/method parameter.

Loading history...
76 6
                continue;
77
            }
78 7
            array_push($keys, $name);
0 ignored issues
show
Bug introduced by
The variable $name does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
79 7
            if (!isset($data[$name])) {
80 7
                $thrower->throws("required", $keys);
81 7
            } elseif (count($iterator) && !is_array($data[$name])) {
0 ignored issues
show
Bug introduced by
The variable $iterator does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
82
                $thrower->throws("array", $keys);
83
            } else {
84 7
                $this->checkChildren($iterator, $children, $thrower, $data[$name], $origin, $keys);
85
            }
86 7
            array_pop($keys);
87
        }
88 8
        foreach ($dataKeys as $dataKey => $_) {
89 3
            $thrower->throws('unknown', array_merge($keys, [$dataKey]));
90
        }
91 8
    }
92
    
93 7
    protected function checkChildren(array $iterators, $rule, ErrorThrowable $thrower, $data, $origin, array $keys = [])
94
    {
95 7
        if (count($iterators)) {
96 4
            $iterator = array_shift($iterators);
97 4
            if ($iterator !== null && $iterator < count($data)) {
98
                $thrower->throws("array_length:{$iterator}", $keys);
99
                return;
100
            }
101 4
            foreach ($data as $index => $value) {
102 3
                array_push($keys, $index);
103 3
                $this->checkChildren($iterators, $rule, $thrower, $value, $origin, $keys);
104 4
                array_pop($keys);
105
            }
106
        } else {
107 7
            $this->checkSingle($rule, $thrower, $data, $origin, $keys);
108
        }
109 7
    }
110
}
111