Validator::checkChildren()   B
last analyzed

Complexity

Conditions 5
Paths 4

Size

Total Lines 17
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 5.1158

Importance

Changes 0
Metric Value
cc 5
eloc 12
nc 4
nop 6
dl 0
loc 17
ccs 10
cts 12
cp 0.8333
crap 5.1158
rs 8.8571
c 0
b 0
f 0
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