Validator   A
last analyzed

Complexity

Total Complexity 23

Size/Duplication

Total Lines 98
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 7

Test Coverage

Coverage 92.31%

Importance

Changes 0
Metric Value
dl 0
loc 98
ccs 48
cts 52
cp 0.9231
rs 10
c 0
b 0
f 0
wmc 23
lcom 1
cbo 7

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A assert() 0 8 2
A validate() 0 10 3
A check() 0 4 1
C checkSingle() 0 29 11
B checkChildren() 0 17 5
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