Passed
Push — release/0.4.3 ( 7fe33b...6b2903 )
by Mathieu
04:50
created

Validator::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 3
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 5
ccs 4
cts 4
cp 1
crap 1
rs 10
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, [
141
                "options" => ['regexp' => $regexp]
142
            ]) !== false;
143
        };
144
145
        $this->checks['longerThan'] = function ($value, $length) {
146
            return strlen($value) > $length;
147
        };
148
149
        $this->checks['longerThanOrEqual'] = function ($value, $length) {
150
            return strlen($value) >= $length;
151
        };
152
153
        $this->checks['shorterThan'] = function ($value, $length) {
154
            return strlen($value) < $length;
155
        };
156
157
        $this->checks['shortThanOrEqual'] = function ($value, $length) {
158
            return strlen($value) <= $length;
159
        };
160
161
        $this->checks['contains'] = function ($value, $toFind) {
162
            return strpos($value, $toFind) !== false;
163
        };
164
165
        $this->checks['alnum'] = function ($value) {
166 1
            return ctype_alnum($value);
167
        };
168
169
        $this->checks['alpha'] = function ($value) {
170
            return ctype_alpha($value);
171
        };
172
173
        $this->checks['digit'] = function ($value) {
174
            return ctype_digit($value);
175
        };
176
177
        $this->checks['lower'] = function ($value) {
178
            return ctype_lower($value);
179
        };
180
181
        $this->checks['upper'] = function ($value) {
182
            return ctype_upper($value);
183
        };
184
185
        $this->checks['space'] = function ($value) {
186
            return ctype_space($value);
187
        };
188 15
    }
189
190
    public function validate($index = null)
191
    {
192
        if ($index === null) {
193
            $this->value = $this->datas;
194
            $this->index = null;
195
            return $this;
196
        }
197
198
        if (is_object($this->datas) && isset($this->datas->$index)) {
199
            $this->value = $this->datas->$index;
200
            $this->index = $index;
201
202
            return $this;
203
        }
204
        if (array_key_exists($index, $this->datas)) {
205
            $this->value = $this->datas[$index];
206
            $this->index = $index;
207
208
            return $this;
209
        }
210
211
        throw new InvalidArgumentException(
212
            'Index / Property "' . $index . '" does not exists'
213
        );
214
    }
215
216
    public function callValidate()
217
    {
218
        $args = func_get_args();
219
        if (count($args) < 1) {
220
            throw new InvalidArgumentException('bad number of arguments');
221
        }
222
223
        $method = array_shift($args);
224
        if (is_callable($method)) {
225
            $this->index = null;
226
            $this->value = call_user_func_array($method, $args);
227
228
            return $this;
229
        }
230
231
        throw new InvalidArgumentException('Bad method');
232
    }
233
234 15
    public function __call($method, $parameters)
235
    {
236 15
        if (!$this->stop) {
237
            // Stop on error, ignore others tests if fails
238 15
            if (substr($method, 0, 4) == 'stop') {
239
                $stopOnError = true;
240
                $method = lcFirst(substr($method, 4));
241
            } else {
242 15
                $stopOnError = false;
243
            }
244
245
            // Negation check
246 15
            if (substr(strtolower($method), 0, 3) == 'not') {
247
                $negation = true;
248
                $method = lcFirst(substr($method, 3));
249
            } else {
250 15
                $negation = false;
251
            }
252
253 15
            if (!isset($this->checks[$method])) {
254
                throw new BadMethodCallException('Unknown check ' . $method);
255
            } else {
256 15
                $validator = $this->checks[$method];
257
            }
258
259 15
            $errorMessage = array_pop($parameters);
260
261 15
            array_unshift($parameters, $this->value);
262
263 15
            $validation = (bool) (call_user_func_array(
264 15
                $validator,
265 15
                $parameters
266 15
            ) ^ $negation);
267 15
            if (!$validation) {
268 9
                if ($stopOnError) {
269
                    $this->stop = true;
270
                }
271 9
                if ($this->index === null) {
272 9
                    $this->errors[] = $errorMessage;
273
                } else {
274
                    $this->errors[$this->index][] = $errorMessage;
275
                }
276
            }
277
        }
278
279 15
        return $this;
280
    }
281
282 2
    public function getErrors($index = null)
283
    {
284 2
        if ($index === null) {
285 2
            return $this->errors;
286
        } else {
287
            return isset($this->errors[$index]) ? $this->errors[$index] : [];
288
        }
289
    }
290
291 15
    public function pass()
292
    {
293 15
        return count($this->errors) == 0;
294
    }
295
296 8
    public function fails()
297
    {
298 8
        return !$this->pass();
299
    }
300
}
301