Passed
Push — release/0.4.3 ( 7fe33b )
by Mathieu
04:23
created

Validator::getErrors()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 3.1406

Importance

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