Validator   A
last analyzed

Complexity

Total Complexity 27

Size/Duplication

Total Lines 215
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 0
Metric Value
wmc 27
lcom 1
cbo 3
dl 0
loc 215
rs 10
c 0
b 0
f 0

16 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A extractWildCardData() 0 12 3
A setRules() 0 4 1
A validate() 0 11 3
A resolveRulesContainOptional() 0 10 3
A resolveRules() 0 10 2
A getRuleFromString() 0 6 1
A ruleFromMap() 0 4 1
A validateRule() 0 11 4
A validateUsingRuleObject() 0 6 2
A getMatchingData() 0 10 1
A getFieldValue() 0 4 1
A getErrors() 0 4 1
A setAliases() 0 4 1
A alias() 0 4 1
A aliases() 0 6 1
1
<?php
2
3
namespace Infinitypaul\Validator;
4
5
use Infinitypaul\Validator\Errors\ErrorBag;
6
use Infinitypaul\Validator\Rules\Optional;
7
use Infinitypaul\Validator\Rules\Rule;
8
9
class Validator
10
{
11
    /**
12
     * @var array
13
     */
14
    protected $data;
15
16
    /**
17
     * @var array
18
     */
19
    protected $rules;
20
21
    /**
22
     * @var \Infinitypaul\Validator\Errors\ErrorBag
23
     */
24
    protected $errors;
25
26
    /**
27
     * @var array
28
     */
29
    protected static $aliases = [];
30
31
    /**
32
     * Validator constructor.
33
     *
34
     * @param array $data
35
     */
36
    public function __construct(array $data)
37
    {
38
        $this->data = $this->extractWildCardData($data);
39
        $this->errors = new ErrorBag();
40
    }
41
42
    /**
43
     * @param array $data
44
     * @param string $root
45
     * @param array $results
46
     *
47
     * @return array
48
     */
49
    protected function extractWildCardData(array $data, $root = '', $results = []): array
50
    {
51
        foreach ($data as $key=>$value) {
52
            if (is_array($value)) {
53
                $results = array_merge($results, $this->extractWildCardData($value, $root.$key.'.'));
54
            } else {
55
                $results[$root.$key] = $value;
56
            }
57
        }
58
59
        return $results;
60
    }
61
62
    /**
63
     * @param array $rules
64
     */
65
    public function setRules(array $rules)
66
    {
67
        $this->rules = $rules;
68
    }
69
70
    /**
71
     *  Loop Through The Rules.
72
     */
73
    public function validate()
74
    {
75
        foreach ($this->rules as $field=>$rules) {
76
            $resolved = $this->resolveRules($rules);
77
            foreach ($resolved as $rule) {
78
                $this->validateRule($field, $rule, $this->resolveRulesContainOptional($resolved));
79
            }
80
        }
81
82
        return $this->errors->hasErrors();
83
    }
84
85
    protected function resolveRulesContainOptional(array $rules)
86
    {
87
        foreach ($rules as $rule) {
88
            if ($rule instanceof Optional) {
89
                return true;
90
            }
91
        }
92
93
        return false;
94
    }
95
96
    /**
97
     * @param $rules
98
     *
99
     * @return array
100
     */
101
    protected function resolveRules($rules)
102
    {
103
        return array_map(function ($rule) {
104
            if (is_string($rule)) {
105
                return $this->getRuleFromString($rule);
106
            }
107
108
            return $rule;
109
        }, $rules);
110
    }
111
112
    /**
113
     * @param $rule
114
     *
115
     * @return mixed
116
     */
117
    protected function getRuleFromString($rule)
118
    {
119
        return $this->ruleFromMap(
120
           ($exploded = explode(':', $rule))[0],
121
           explode(',', end($exploded)));
122
    }
123
124
    /**
125
     * @param $rule
126
     * @param $options
127
     *
128
     * @return mixed
129
     */
130
    protected function ruleFromMap($rule, $options)
131
    {
132
        return RuleMap::resolve($rule, $options);
133
    }
134
135
    /**
136
     * @param $field
137
     * @param \Infinitypaul\Validator\Rules\Rule $rule
138
     * @param bool $optional
139
     */
140
    protected function validateRule($field, Rule $rule, $optional = false)
141
    {
142
        foreach ($this->getMatchingData($field) as $matchedField) {
143
            if (($value = $this->getFieldValue($matchedField, $this->data)) === '' && $optional) {
144
                continue;
145
            }
146
            $this->validateUsingRuleObject(
147
                $matchedField,
148
                $value, $rule);
149
        }
150
    }
151
152
    /**
153
     * @param $field
154
     * @param $value
155
     * @param \Infinitypaul\Validator\Rules\Rule $rule
156
     */
157
    protected function validateUsingRuleObject($field, $value, Rule $rule)
158
    {
159
        if (! $rule->passes($field, $value, $this->data)) {
160
            $this->errors->add($field, $rule->message(self::alias($field)));
161
        }
162
    }
163
164
    /**
165
     * @param $field
166
     *
167
     * @return array
168
     */
169
    protected function getMatchingData($field)
170
    {
171
        //Replace Asterisk With Regular Expression
172
        $fieldRegex = str_replace('*', '([^\.]+)', $field);
173
        //Take The keys for the data
174
        $dataKeys = array_keys($this->data);
175
        //Find The Value That Relate
176
        //return preg_grep('/^'.$fieldRegex.'/', $dataKeys);
177
        return preg_grep('/^'.$fieldRegex.'$/', $dataKeys);
178
    }
179
180
    /**
181
     * @param $field
182
     * @param $data
183
     *
184
     * @return mixed|null
185
     */
186
    protected function getFieldValue($field, $data)
187
    {
188
        return $data[$field] ?? null;
189
    }
190
191
    /**
192
     * @return array
193
     */
194
    public function getErrors(): array
195
    {
196
        return $this->errors->getErrors();
197
    }
198
199
    /*
200
     * Set Aliases
201
     */
202
    public function setAliases(array $aliases)
203
    {
204
        self::$aliases = $aliases;
205
    }
206
207
    public static function alias($field)
208
    {
209
        return self::$aliases[$field] ?? $field;
210
    }
211
212
    /**
213
     * @param array $fields
214
     *
215
     * @return array
216
     */
217
    public static function aliases(array $fields): array
218
    {
219
        return array_map(function ($field) {
220
            return self::alias($field);
221
        }, $fields);
222
    }
223
}
224