Completed
Push — develop ( b2b49f...eda620 )
by Mathieu
01:53
created

Validator::validate()   A

Complexity

Conditions 5
Paths 4

Size

Total Lines 22
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 0
Metric Value
cc 5
eloc 13
nc 4
nop 1
dl 0
loc 22
ccs 0
cts 14
cp 0
crap 30
rs 9.5222
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
namespace Suricate;
3
4
/**
5
 * Validator
6
 * Inspired from Kieron Wilson PHP Validator
7
 *
8
 * @method Validator true(string $errorMessage)
9
 * @method Validator false(string $errorMessage)
10
 * @method Validator equalTo(mixed $toTest, string $errorMessage)
11
 * @method Validator identicalTo(mixed $toTest, string $errorMessage)
12
 * @method Validator lessThan(mixed $toTest, string $errorMessage)
13
 * @method Validator lessThanOrEqual(mixed $toTest, string $errorMessage)
14
 * @method Validator greaterThan(mixed $toTest, string $errorMessage)
15
 * @method Validator greaterThanOrEqual(mixed $toTest, string $errorMessage)
16
 * @method Validator blank(string $errorMessage)
17
 * @method Validator null(string $errorMessage)
18
 * @method Validator type(string $testType, string $errorMessage)
19
 * &method Validator email(string $errorMessage)
20
 * &method Validator url(string $errorMessage)
21
 * &method Validator ip(string $errorMessage)
22
 * &method Validator regexp(string $errorMessage)
23
 * @author      Mathieu LESNIAK <[email protected]>
24
 * @copyright   Mathieu LESNIAK
25
 * @package     Suricate
26
 */
27
class Validator
28
{
29
    private $errors = [];
30
    private $checks = [];
31
    private $datas;
32
    private $value;
33
    private $index;
34
    private $stop = false;
35
36 15
    public function __construct($input)
37
    {
38 15
        $this->datas = $input;
39 15
        $this->value = $input;
40 15
        $this->createChecks();
41 15
    }
42
43
    private function createChecks()
44
    {
45 1
        $this->checks['equalTo'] = function ($value, $compare) {
46 1
            return $value == $compare;
47
        };
48
49 1
        $this->checks['identicalTo'] = function ($value, $compare) {
50 1
            return $value === $compare;
51
        };
52
53 1
        $this->checks['lessThan'] = function ($value, $compare) {
54 1
            return $value < $compare;
55
        };
56
57 1
        $this->checks['lessThanOrEqual'] = function ($value, $compare) {
58 1
            return $value <= $compare;
59
        };
60
61 1
        $this->checks['greaterThan'] = function ($value, $compare) {
62 1
            return $value > $compare;
63
        };
64
65 1
        $this->checks['greaterThanOrEqual'] = function ($value, $compare) {
66 1
            return $value >= $compare;
67
        };
68
69 1
        $this->checks['blank'] = function ($value) {
70 1
            return $value == '';
71
        };
72
73 1
        $this->checks['null'] = function ($value) {
74 1
            return is_null($value);
75
        };
76
77 1
        $this->checks['true'] = function ($value) {
78 1
            return $value === true;
79
        };
80
81 1
        $this->checks['false'] = function ($value) {
82 1
            return !($value === true);
83
        };
84
85 1
        $this->checks['type'] = function ($value, $type) {
86
            switch ($type) {
87 1
                case 'array':
88 1
                    return is_array($value);
89 1
                case 'bool':
90 1
                    return is_bool($value);
91 1
                case 'callable':
92
                    return is_callable($value);
93 1
                case 'float':
94 1
                    return is_float($value);
95 1
                case 'int':
96 1
                    return is_int($value);
97 1
                case 'numeric':
98 1
                    return is_numeric($value);
99 1
                case 'object':
100 1
                    return is_object($value);
101 1
                case 'resource':
102
                    return is_resource($value);
103 1
                case 'scalar':
104
                    return is_scalar($value);
105 1
                case 'string':
106 1
                    return is_string($value);
107
                default:
108
                    throw new \InvalidArgumentException('Unknown type to check ' . $type);
109
            }
110
        };
111
112 1
        $this->checks['email'] = function ($value) {
113 1
            return filter_var($value, FILTER_VALIDATE_EMAIL) !== false;
114
        };
115
116 1
        $this->checks['url'] = function ($value) {
117 1
            return filter_var($value, FILTER_VALIDATE_URL) !== false;
118
        };
119
120 1
        $this->checks['ip'] = function ($value) {
121 1
            return filter_var($value, FILTER_VALIDATE_IP) !== false;
122
        };
123
124
        $this->checks['regexp'] = function ($value, $regexp) {
125
            return filter_var($value, FILTER_VALIDATE_REGEXP, $regexp) !== false;
126
        };
127
128
        $this->checks['longerThan'] = function ($value, $length) {
129
            return strlen($value) > $length;
130
        };
131
132
        $this->checks['longerThanOrEqual'] = function ($value, $length) {
133
            return strlen($value) >= $length;
134
        };
135
136
        $this->checks['shorterThan'] = function ($value, $length) {
137
            return strlen($value) < $length;
138
        };
139
140
        $this->checks['shortThanOrEqual'] = function ($value, $length) {
141
            return strlen($value) <= $length;
142
        };
143
144
        $this->checks['contains'] = function ($value, $toFind) {
145
            return strpos($value, $toFind) !== false;
146
        };
147
        
148 1
        $this->checks['alnum'] = function ($value) {
149 1
            return ctype_alnum($value);
150
        };
151
152
        $this->checks['alpha'] = function ($value) {
153
            return ctype_alpha($value);
154
        };
155
156
        $this->checks['digit'] = function ($value) {
157
            return ctype_digit($value);
158
        };
159
        
160
        $this->checks['lower'] = function ($value) {
161
            return ctype_lower($value);
162
        };
163
164
        $this->checks['upper'] = function ($value) {
165
            return ctype_upper($value);
166
        };
167
168
        $this->checks['space'] = function ($value) {
169
            return ctype_space($value);
170
        };
171 15
    }
172
173
    public function validate($index = null)
174
    {
175
        if ($index === null) {
176
            $this->value = $this->datas;
177
            $this->index = null;
178
            return $this;
179
        }
180
181
        if (is_object($this->datas) && isset($this->datas->$index)) {
182
            $this->value = $this->datas->$index;
183
            $this->index = $index;
184
185
            return $this;
186
        } 
187
        if (array_key_exists($index, $this->datas)) {
188
            $this->value = $this->datas[$index];
189
            $this->index = $index;
190
191
            return $this;
192
        }
193
        
194
        throw new \InvalidArgumentException('Index / Property "' . $index . '" does not exists');
195
    }
196
197
    public function callValidate()
198
    {
199
        $args = func_get_args();
200
        if (count($args) < 1) {
201
            throw new \InvalidArgumentException('bad number of arguments');
202
        }
203
        
204
        $method = array_shift($args);
205
        // Object method
206
        if (is_array($method) || is_string($method)) {
207
            $this->index = null;
208
            $this->value = call_user_func_array($method, $args);
209
210
            return $this;
211
        }
212
213
        if (is_object($method) && ($method instanceof \Closure)) {
214
            $this->index = null;
215
            $this->value = call_user_func_array($method, $args);
216
217
            return $this;
218
        }
219
        throw new \InvalidArgumentException('Bad method');
220
221
    }
222
223 15
    public function __call($method, $parameters)
224
    {
225 15
        if (!$this->stop) {
226
            // Stop on error, ignore others tests if fails
227 15
            if (substr($method, 0, 4) == 'stop') {
228
                $stopOnError = true;
229
                $method = lcFirst(substr($method, 4));
230
            } else {
231 15
                $stopOnError = false;
232
            }
233
234
            // Negation check
235 15
            if (substr(strtolower($method), 0, 3) == 'not') {
236
                $negation   = true;
237
                $method     = lcFirst(substr($method, 3));
238
            } else {
239 15
                $negation = false;
240
            }
241
242 15
            if (!isset($this->checks[$method])) {
243
                throw new \BadMethodCallException('Unknown check ' . $method);
244
            } else {
245 15
                $validator = $this->checks[$method];
246
            }
247
248 15
            $errorMessage = array_pop($parameters);
249
250 15
            array_unshift($parameters, $this->value);
251
252 15
            $validation = (bool) (call_user_func_array($validator, $parameters) ^ $negation);
253 15
            if (!$validation) {
254 9
                if ($stopOnError) {
255
                    $this->stop = true;
256
                }
257 9
                if ($this->index === null) {
258 9
                    $this->errors[] = $errorMessage;
259
                } else {
260
                    $this->errors[$this->index][] = $errorMessage;
261
                }
262
            }
263
        }
264
265 15
        return $this;
266
    }
267
268 2
    public function getErrors($index = null)
269
    {
270
271 2
        if ($index === null) {
272 2
            return $this->errors;
273
        } else {
274
            return isset($this->errors[$index]) ? $this->errors[$index] : [];
275
        }
276
    }
277
278 15
    public function pass()
279
    {
280 15
        return count($this->errors) == 0;
281
    }
282
283 8
    public function fails()
284
    {
285 8
        return !$this->pass();
286
    }
287
}
288