Completed
Push — master ( c629cf...cdf94f )
by Runner
04:12
created

Validator::getSize()   A

Complexity

Conditions 6
Paths 5

Size

Total Lines 13
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 6

Importance

Changes 0
Metric Value
eloc 11
dl 0
loc 13
ccs 10
cts 10
cp 1
rs 9.2222
c 0
b 0
f 0
cc 6
nc 5
nop 2
crap 6
1
<?php
2
/**
3
 * @author: RunnerLee
4
 * @email: [email protected]
5
 * @time: 17-2-20 15:22
6
 */
7
8
namespace Runner\Validator;
9
10
use Runner\Validator\Concerns\MessagesAttributes;
11
use Runner\Validator\Concerns\ValidatesAttributes;
12
13
/**
14
 * Class Validator.
15
 */
16
class Validator
17
{
18
    use ValidatesAttributes, MessagesAttributes;
19
20
    /**
21
     * @var array
22
     */
23
    protected $data = [];
24
25
    /**
26
     * @var array
27
     */
28
    protected $ruleGroups = [];
29
30
    /**
31
     * @var array
32
     */
33
    protected $messages = [];
34
35
    /**
36
     * @var array
37
     */
38
    protected static $forceRules = ['Required', 'RequiredIf', 'RequiredWith', 'RequiredUnless', 'RequiredWithout'];
39
40
    /**
41
     * @var array
42
     */
43
    protected static $extensions = [];
44
45
    /**
46
     * @var array
47
     */
48
    protected static $extensionTemplates = [];
49
50
    /**
51
     * Validator constructor.
52
     *
53
     * @param array  $data
54
     * @param array  $rules
55
     * @param array  $customMessages
56
     * @param string $file
57
     */
58 3
    public function __construct(array $data, array $rules, array $customMessages = [], $file = __DIR__.'/messages/en.php')
59
    {
60 3
        $this->data = $data;
61 3
        $this->parseRules($rules);
62 3
        $this->loadMessageTemplate($file, $customMessages);
63 3
    }
64
65
    /**
66
     * @param $name
67
     * @param $callback
68
     * @param bool   $isForce
69
     * @param string $message
70
     */
71 2
    public static function addExtension($name, $callback, $isForce = false, $message = null)
72
    {
73 2
        $name = self::formatRuleName($name);
74
75 2
        self::$extensions[$name] = $callback;
76
77 2
        $isForce && self::$forceRules[] = $name;
78
79 2
        !empty($message) && (static::$extensionTemplates[$name] = $message);
80 2
    }
81
82
    /**
83
     * @return bool
84
     */
85 3
    public function validate()
86
    {
87 3
        foreach ($this->ruleGroups as $field => $rules) {
88 3
            if ($this->hasField($field)) {
89 3
                $value = $this->getField($field);
90 3
                foreach ($rules as $rule => $parameters) {
91 3
                    if (!$this->runValidateRule($field, $value, $rule, $parameters)) {
92 3
                        $this->messages[$field][$rule] = $this->buildMessage($rule, $field, $parameters);
93
                    }
94
                }
95 1
            } elseif ($forceRules = array_intersect(self::$forceRules, array_keys($rules))) {
96 1
                $value = null;
97 1
                foreach ($forceRules as $rule) {
98 1
                    if (!$this->runValidateRule($field, null, $rule, $rules[$rule])) {
99 3
                        $this->messages[$field][$rule] = $this->buildMessage($rule, $field, $rules[$rule]);
100
                    }
101
                }
102
            }
103
        }
104
105 3
        return 0 === count($this->messages);
106
    }
107
108
    /**
109
     * @return array
110
     */
111 1
    public function fails()
112
    {
113 1
        return array_keys($this->messages);
114
    }
115
116
    /**
117
     * @return array
118
     */
119 2
    public function messages()
120
    {
121 2
        return $this->messages;
122
    }
123
124
    /**
125
     * @return array
126
     */
127 1
    public function data()
128
    {
129 1
        return $this->data;
130
    }
131
132
    /**
133
     * @param array $ruleGroups
134
     */
135 3
    protected function parseRules(array $ruleGroups)
136
    {
137 3
        $map = [];
138 3
        foreach ($ruleGroups as $field => $rules) {
139 3
            foreach (explode('|', $rules) as $rule) {
140 3
                list($rule, $parameters) = explode(':', (false === strpos($rule, ':') ? ($rule.':') : $rule), 2);
141 3
                !isset($map[$rule]) && $map[$rule] = self::formatRuleName($rule);
142 3
                $rule = $map[$rule];
143 3
                $this->ruleGroups[$field][$rule] = ('' === $parameters ? [] : explode(',', $parameters));
144
            }
145
        }
146 3
        unset($map);
147 3
    }
148
149
    /**
150
     * @param $name
151
     *
152
     * @return string
153
     */
154 3
    protected static function formatRuleName($name)
155
    {
156 3
        return implode(
157 3
            '',
158 3
            array_map(
159 3
                function ($value) {
160 3
                    return ucfirst($value);
161 3
                },
162 3
                explode('_', $name)
163
            )
164
        );
165
    }
166
167
    /**
168
     * @param string $field
169
     *
170
     * @return bool
171
     */
172 3
    protected function hasField($field)
173
    {
174 3
        $field = explode('.', $field);
175 3
        $item = array_shift($field);
176 3
        if (!array_key_exists($item, $this->data)) {
177 1
            return false;
178
        }
179 3
        $value = $this->data[$item];
180
181 3
        foreach ($field as $item) {
182 1
            if (!array_key_exists($item, $value)) {
183 1
                return false;
184
            }
185 1
            $value = $value[$item];
186
        }
187
188 3
        return true;
189
    }
190
191
    /**
192
     * @param string $field
193
     *
194
     * @return mixed
195
     */
196 3
    protected function getField($field)
197
    {
198 3
        $field = explode('.', $field);
199 3
        $item = array_shift($field);
200 3
        $value = $this->data[$item];
201 3
        foreach ($field as $item) {
202 1
            $value = $value[$item];
203
        }
204
205 3
        return $value;
206
    }
207
208
    /**
209
     * @param $field
210
     * @param $value
211
     * @param $rule
212
     * @param array $parameters
213
     *
214
     * @return bool
215
     */
216 3
    protected function runValidateRule($field, $value, $rule, array $parameters = [])
217
    {
218 3
        $callback = array_key_exists($rule, self::$extensions) ? self::$extensions[$rule] : [$this, "validate{$rule}"];
219
220 3
        return (bool) call_user_func($callback, $field, $value, $parameters, $this);
221
    }
222
}
223