1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* Quantum PHP Framework |
5
|
|
|
* |
6
|
|
|
* An open source software development framework for PHP |
7
|
|
|
* |
8
|
|
|
* @package Quantum |
9
|
|
|
* @author Arman Ag. <[email protected]> |
10
|
|
|
* @copyright Copyright (c) 2018 Softberg LLC (https://softberg.org) |
11
|
|
|
* @link http://quantum.softberg.org/ |
12
|
|
|
* @since 2.0.0 |
13
|
|
|
*/ |
14
|
|
|
|
15
|
|
|
namespace Quantum\Libraries\Validation; |
16
|
|
|
|
17
|
|
|
use Quantum\Libraries\Upload\File; |
18
|
|
|
use Quantum\Factory\ModelFactory; |
19
|
|
|
|
20
|
|
|
/** |
21
|
|
|
* Class Validator |
22
|
|
|
* @package Quantum\Libraries\Validator |
23
|
|
|
*/ |
24
|
|
|
class Validator |
25
|
|
|
{ |
26
|
|
|
|
27
|
|
|
/** |
28
|
|
|
* Rules |
29
|
|
|
* @var array |
30
|
|
|
*/ |
31
|
|
|
private $rules = []; |
32
|
|
|
|
33
|
|
|
/** |
34
|
|
|
* Validation Errors |
35
|
|
|
* @var array |
36
|
|
|
*/ |
37
|
|
|
private $errors = []; |
38
|
|
|
|
39
|
|
|
/** |
40
|
|
|
* Request data |
41
|
|
|
* @var array |
42
|
|
|
*/ |
43
|
|
|
private $data = []; |
44
|
|
|
|
45
|
|
|
/** |
46
|
|
|
* Custom validations |
47
|
|
|
* @var array |
48
|
|
|
*/ |
49
|
|
|
private $customValidations = []; |
50
|
|
|
|
51
|
|
|
/** |
52
|
|
|
* Add a rules for given field |
53
|
|
|
* @param string $field |
54
|
|
|
* @param array $rules |
55
|
|
|
*/ |
56
|
|
|
public function addRule(string $field, array $rules) |
57
|
|
|
{ |
58
|
|
|
if (!empty($field) && is_array($rules)) { |
59
|
|
|
foreach ($rules as $rule) { |
60
|
|
|
if (!isset($this->rules[$field])) { |
61
|
|
|
$this->rules[$field] = []; |
62
|
|
|
} |
63
|
|
|
|
64
|
|
|
$this->rules[$field][array_keys($rule)[0]] = array_values($rule)[0]; |
65
|
|
|
} |
66
|
|
|
} |
67
|
|
|
} |
68
|
|
|
|
69
|
|
|
/** |
70
|
|
|
* Adds rules for multiple fields |
71
|
|
|
* @param array $rules |
72
|
|
|
*/ |
73
|
|
|
public function addRules(array $rules) |
74
|
|
|
{ |
75
|
|
|
foreach ($rules as $field => $params) { |
76
|
|
|
$this->addRule($field, $params); |
77
|
|
|
} |
78
|
|
|
} |
79
|
|
|
|
80
|
|
|
/** |
81
|
|
|
* Updates the single rule in rules list for given field |
82
|
|
|
* @param string $field |
83
|
|
|
* @param array $rule |
84
|
|
|
*/ |
85
|
|
|
public function updateRule(string $field, array $rule) |
86
|
|
|
{ |
87
|
|
|
if (!empty($field) && is_array($rule)) { |
88
|
|
|
if (isset($this->rules[$field]) && isset($this->rules[$field][array_keys($rule)[0]])) { |
89
|
|
|
$this->rules[$field][array_keys($rule)[0]] = array_values($rule)[0]; |
90
|
|
|
} |
91
|
|
|
} |
92
|
|
|
} |
93
|
|
|
|
94
|
|
|
/** |
95
|
|
|
* Deletes the the rule in rules list for given field |
96
|
|
|
* @param string $field |
97
|
|
|
* @param string|null $rule |
98
|
|
|
*/ |
99
|
|
|
public function deleteRule(string $field, string $rule = null) |
100
|
|
|
{ |
101
|
|
|
if (!empty($field)) { |
102
|
|
|
if (isset($this->rules[$field])) { |
103
|
|
|
if (!empty($rule) && isset($this->rules[$field][$rule])) { |
104
|
|
|
unset($this->rules[$field][$rule]); |
105
|
|
|
} else { |
106
|
|
|
if (empty($rule)) { |
107
|
|
|
unset($this->rules[$field]); |
108
|
|
|
} |
109
|
|
|
} |
110
|
|
|
} |
111
|
|
|
} |
112
|
|
|
} |
113
|
|
|
|
114
|
|
|
public function flushRules(){ |
115
|
|
|
$this->rules = []; |
116
|
|
|
$this->flushErrors(); |
117
|
|
|
} |
118
|
|
|
|
119
|
|
|
/** |
120
|
|
|
* Validates the data against the rules |
121
|
|
|
* @param array $data |
122
|
|
|
* @return mixed |
123
|
|
|
*/ |
124
|
|
|
public function isValid(array $data) |
125
|
|
|
{ |
126
|
|
|
$this->data = $data; |
127
|
|
|
|
128
|
|
|
if (count($this->rules)) { |
129
|
|
|
|
130
|
|
|
foreach($this->rules as $field => $rule){ |
131
|
|
|
if(!array_key_exists($field, $data)){ |
132
|
|
|
$data[$field] = ''; |
133
|
|
|
} |
134
|
|
|
} |
135
|
|
|
|
136
|
|
|
foreach ($data as $field => $value) { |
137
|
|
|
|
138
|
|
|
if (isset($this->rules[$field])) { |
139
|
|
|
foreach ($this->rules[$field] as $method => $param) { |
140
|
|
|
|
141
|
|
|
if (is_callable([$this, $method])) { |
142
|
|
|
$this->$method($field, $value, $param); |
143
|
|
|
} elseif (isset($this->customValidations[$method])) { |
144
|
|
|
$data = [ |
145
|
|
|
'rule' => $method, |
146
|
|
|
'field' => $field, |
147
|
|
|
'value' => $value, |
148
|
|
|
'param' => $param ?? null |
149
|
|
|
]; |
150
|
|
|
|
151
|
|
|
$this->callCustomFunction($this->customValidations[$method], $data); |
152
|
|
|
} |
153
|
|
|
} |
154
|
|
|
} |
155
|
|
|
} |
156
|
|
|
} |
157
|
|
|
return count($this->errors) ? false : true; |
158
|
|
|
} |
159
|
|
|
|
160
|
|
|
/** |
161
|
|
|
* Adds custom validation |
162
|
|
|
* @param string $rule |
163
|
|
|
* @param \Closure $function |
164
|
|
|
* @param null|mixed $params |
165
|
|
|
* @return mixed |
166
|
|
|
*/ |
167
|
|
|
public function addValidation(string $rule, \Closure $function) |
168
|
|
|
{ |
169
|
|
|
if (!empty($rule) && is_callable($function)) { |
170
|
|
|
$this->customValidations[$rule] = $function; |
171
|
|
|
} |
172
|
|
|
} |
173
|
|
|
|
174
|
|
|
/** |
175
|
|
|
* Gets validation errors |
176
|
|
|
* @return array |
177
|
|
|
*/ |
178
|
|
|
public function getErrors(): array |
179
|
|
|
{ |
180
|
|
|
if (count($this->errors)) { |
181
|
|
|
$messages = []; |
182
|
|
|
foreach ($this->errors as $field => $errors) { |
183
|
|
|
if (count($errors)) { |
184
|
|
|
foreach ($errors as $rule => $param) { |
185
|
|
|
$translatoinParams = [ucfirst($field)]; |
186
|
|
|
|
187
|
|
|
if ($param) { |
188
|
|
|
$translatoinParams[] = $param; |
189
|
|
|
} |
190
|
|
|
|
191
|
|
|
if (!isset($messages[$field])) { |
192
|
|
|
$messages[$field] = []; |
193
|
|
|
} |
194
|
|
|
|
195
|
|
|
$messages[$field][] = t("validation.$rule", $translatoinParams); |
196
|
|
|
} |
197
|
|
|
} |
198
|
|
|
} |
199
|
|
|
|
200
|
|
|
return $messages; |
201
|
|
|
} |
202
|
|
|
|
203
|
|
|
return []; |
204
|
|
|
} |
205
|
|
|
|
206
|
|
|
/** |
207
|
|
|
* Adds validation Error |
208
|
|
|
* @param string $field |
209
|
|
|
* @param string $rule |
210
|
|
|
* @param null|mixed $param |
211
|
|
|
*/ |
212
|
|
|
protected function addError($field, $rule, $param = null) |
213
|
|
|
{ |
214
|
|
|
if (!isset($this->errors[$field])) { |
215
|
|
|
$this->errors[$field] = []; |
216
|
|
|
} |
217
|
|
|
|
218
|
|
|
$this->errors[$field][$rule] = $param; |
219
|
|
|
} |
220
|
|
|
|
221
|
|
|
public function flushErrors() |
222
|
|
|
{ |
223
|
|
|
$this->errors = []; |
224
|
|
|
} |
225
|
|
|
|
226
|
|
|
/** |
227
|
|
|
* Calls custom function defined by developer |
228
|
|
|
* @param \Closure $function : boolean |
229
|
|
|
* @param array $data |
230
|
|
|
*/ |
231
|
|
|
protected function callCustomFunction(\Closure $function, array $data) |
232
|
|
|
{ |
233
|
|
|
if (empty($data['value'])) { |
234
|
|
|
return true; |
235
|
|
|
} |
236
|
|
|
|
237
|
|
|
if (is_callable($function)) { |
238
|
|
|
if (!$function($data['value'], $data['param'])) { |
239
|
|
|
$this->addError($data['field'], $data['rule'], $data['param']); |
240
|
|
|
} |
241
|
|
|
} |
242
|
|
|
} |
243
|
|
|
|
244
|
|
|
/** |
245
|
|
|
* Checks Field Required |
246
|
|
|
* @param string $field |
247
|
|
|
* @param string $value |
248
|
|
|
* @param null|mixed $param |
249
|
|
|
*/ |
250
|
|
|
protected function required(string $field, string $value, $param = null) |
251
|
|
|
{ |
252
|
|
|
if ($value === false || $value === '0' || empty($value)) { |
253
|
|
|
$this->addError($field, 'required', $param); |
254
|
|
|
} |
255
|
|
|
} |
256
|
|
|
|
257
|
|
|
/** |
258
|
|
|
* Checks Email |
259
|
|
|
* @param string $field |
260
|
|
|
* @param string $value |
261
|
|
|
* @param null|mixed $param |
262
|
|
|
*/ |
263
|
|
|
protected function email(string $field, string $value, $param = null) |
264
|
|
|
{ |
265
|
|
|
if (empty($value)) { |
266
|
|
|
return true; |
267
|
|
|
} |
268
|
|
|
|
269
|
|
|
if (!filter_var($value, FILTER_VALIDATE_EMAIL)) { |
270
|
|
|
$this->addError($field, 'email', $param); |
271
|
|
|
} |
272
|
|
|
} |
273
|
|
|
|
274
|
|
|
/** |
275
|
|
|
* Checks the min Length |
276
|
|
|
* @param string $field |
277
|
|
|
* @param string $value |
278
|
|
|
* @param null|mixed $param |
279
|
|
|
*/ |
280
|
|
|
protected function minLen(string $field, string $value, $param = null) |
281
|
|
|
{ |
282
|
|
|
$error = false; |
283
|
|
|
|
284
|
|
|
if (empty($value)) { |
285
|
|
|
return true; |
286
|
|
|
} |
287
|
|
|
|
288
|
|
|
if (function_exists('mb_strlen')) { |
289
|
|
|
if (mb_strlen($value) < (int) $param) { |
290
|
|
|
$error = true; |
291
|
|
|
} |
292
|
|
|
} else { |
293
|
|
|
if (strlen($value) < (int) $param) { |
294
|
|
|
$error = true; |
295
|
|
|
} |
296
|
|
|
} |
297
|
|
|
|
298
|
|
|
if ($error) { |
299
|
|
|
$this->addError($field, 'minLen', $param); |
300
|
|
|
} |
301
|
|
|
} |
302
|
|
|
|
303
|
|
|
/** |
304
|
|
|
* Checks the max Length |
305
|
|
|
* @param string $field |
306
|
|
|
* @param string $value |
307
|
|
|
* @param null|mixed $param |
308
|
|
|
*/ |
309
|
|
|
protected function maxLen(string $field, string $value, $param = null) |
310
|
|
|
{ |
311
|
|
|
$error = false; |
312
|
|
|
|
313
|
|
|
if (empty($value)) { |
314
|
|
|
return true; |
315
|
|
|
} |
316
|
|
|
|
317
|
|
|
if (function_exists('mb_strlen')) { |
318
|
|
|
if (mb_strlen($value) > (int) $param) { |
319
|
|
|
$error = true; |
320
|
|
|
} |
321
|
|
|
} else { |
322
|
|
|
if (strlen($value) > (int) $param) { |
323
|
|
|
$error = true; |
324
|
|
|
} |
325
|
|
|
} |
326
|
|
|
|
327
|
|
|
if ($error) { |
328
|
|
|
$this->addError($field, 'maxLen', $param); |
329
|
|
|
} |
330
|
|
|
} |
331
|
|
|
|
332
|
|
|
/** |
333
|
|
|
* Checks the exact length |
334
|
|
|
* @param string $field |
335
|
|
|
* @param string $value |
336
|
|
|
* @param null|mixed $param |
337
|
|
|
*/ |
338
|
|
|
protected function exactLen(string $field, string $value, $param = null) |
339
|
|
|
{ |
340
|
|
|
$error = false; |
341
|
|
|
|
342
|
|
|
if (empty($value)) { |
343
|
|
|
return true; |
344
|
|
|
} |
345
|
|
|
|
346
|
|
|
if (function_exists('mb_strlen')) { |
347
|
|
|
if (mb_strlen($value) !== (int) $param) { |
348
|
|
|
$error = true; |
349
|
|
|
} |
350
|
|
|
} else { |
351
|
|
|
if (strlen($value) !== (int) $param) { |
352
|
|
|
$error = true; |
353
|
|
|
} |
354
|
|
|
} |
355
|
|
|
|
356
|
|
|
if ($error) { |
357
|
|
|
$this->addError($field, 'exactLen', $param); |
358
|
|
|
} |
359
|
|
|
} |
360
|
|
|
|
361
|
|
|
/** |
362
|
|
|
* Checks the alpha characters |
363
|
|
|
* @param string $field |
364
|
|
|
* @param string $value |
365
|
|
|
* @param null|mixed $param |
366
|
|
|
*/ |
367
|
|
|
protected function alpha(string $field, string $value, $param = null) |
368
|
|
|
{ |
369
|
|
|
if (empty($value)) { |
370
|
|
|
return true; |
371
|
|
|
} |
372
|
|
|
|
373
|
|
|
if (preg_match('/^([a-zÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÒÓÔÕÖßÙÚÛÜÝàáâãäåçèéêëìíîïðòóôõöùúûüýÿ])+$/i', $value) === 0) { |
374
|
|
|
$this->addError($field, 'alpha', $param); |
375
|
|
|
} |
376
|
|
|
} |
377
|
|
|
|
378
|
|
|
/** |
379
|
|
|
* Checks the alpha and numeric characters |
380
|
|
|
* @param string $field |
381
|
|
|
* @param string $value |
382
|
|
|
* @param null|mixed $param |
383
|
|
|
*/ |
384
|
|
|
protected function alphaNumeric(string $field, string $value, $param = null) |
385
|
|
|
{ |
386
|
|
|
if (empty($value)) { |
387
|
|
|
return true; |
388
|
|
|
} |
389
|
|
|
|
390
|
|
|
if (preg_match('/^([a-z0-9ÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÒÓÔÕÖßÙÚÛÜÝàáâãäåçèéêëìíîïðòóôõöùúûüýÿ])+$/i', $value) === 0) { |
391
|
|
|
$this->addError($field, 'alphaNumeric', $param); |
392
|
|
|
} |
393
|
|
|
} |
394
|
|
|
|
395
|
|
|
/** |
396
|
|
|
* Checks the alpha and dash characters |
397
|
|
|
* @param string $field |
398
|
|
|
* @param string $value |
399
|
|
|
* @param null|mixed $param |
400
|
|
|
*/ |
401
|
|
|
protected function alphaDash(string $field, string $value, $param = null) |
402
|
|
|
{ |
403
|
|
|
if (empty($value)) { |
404
|
|
|
return true; |
405
|
|
|
} |
406
|
|
|
|
407
|
|
|
if (preg_match('/^([a-zÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÒÓÔÕÖßÙÚÛÜÝàáâãäåçèéêëìíîïðòóôõöùúûüýÿ_-])+$/i', $value) === 0) { |
408
|
|
|
$this->addError($field, 'alphaDash', $param); |
409
|
|
|
} |
410
|
|
|
} |
411
|
|
|
|
412
|
|
|
/** |
413
|
|
|
* Checks the alpha numeric and space characters |
414
|
|
|
* @param string $field |
415
|
|
|
* @param string $value |
416
|
|
|
* @param null|mixed $param |
417
|
|
|
*/ |
418
|
|
|
protected function alphaSpace(string $field, string $value, $param = null) |
419
|
|
|
{ |
420
|
|
|
if (empty($value)) { |
421
|
|
|
return true; |
422
|
|
|
} |
423
|
|
|
|
424
|
|
|
if (preg_match('/^([a-z0-9ÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÒÓÔÕÖßÙÚÛÜÝàáâãäåçèéêëìíîïðòóôõöùúûüýÿ\s])+$/i', $value) === 0) { |
425
|
|
|
$this->addError($field, 'alphaSpace', $param); |
426
|
|
|
} |
427
|
|
|
} |
428
|
|
|
|
429
|
|
|
/** |
430
|
|
|
* Checks the numeric value |
431
|
|
|
* @param string $field |
432
|
|
|
* @param string $value |
433
|
|
|
* @param null|mixed $param |
434
|
|
|
*/ |
435
|
|
|
protected function numeric(string $field, string $value, $param = null) |
436
|
|
|
{ |
437
|
|
|
if (empty($value)) { |
438
|
|
|
return true; |
439
|
|
|
} |
440
|
|
|
|
441
|
|
|
if (!is_numeric($value)) { |
442
|
|
|
$this->addError($field, 'numeric', $param); |
443
|
|
|
} |
444
|
|
|
} |
445
|
|
|
|
446
|
|
|
/** |
447
|
|
|
* Checks the integer value |
448
|
|
|
* @param string $field |
449
|
|
|
* @param string $value |
450
|
|
|
* @param null|mixed $param |
451
|
|
|
*/ |
452
|
|
|
protected function integer(string $field, string $value, $param = null) |
453
|
|
|
{ |
454
|
|
|
if (empty($value)) { |
455
|
|
|
return true; |
456
|
|
|
} |
457
|
|
|
|
458
|
|
|
if (filter_var($value, FILTER_VALIDATE_INT) === false) { |
459
|
|
|
$this->addError($field, 'integer', $param); |
460
|
|
|
} |
461
|
|
|
} |
462
|
|
|
|
463
|
|
|
/** |
464
|
|
|
* Checks the float value |
465
|
|
|
* @param string $field |
466
|
|
|
* @param string $value |
467
|
|
|
* @param null|mixed $param |
468
|
|
|
*/ |
469
|
|
|
protected function float(string $field, string $value, $param = null) |
470
|
|
|
{ |
471
|
|
|
if (empty($value)) { |
472
|
|
|
return true; |
473
|
|
|
} |
474
|
|
|
|
475
|
|
|
if (filter_var($value, FILTER_VALIDATE_FLOAT) === false) { |
476
|
|
|
$this->addError($field, 'float', $param); |
477
|
|
|
} |
478
|
|
|
} |
479
|
|
|
|
480
|
|
|
/** |
481
|
|
|
* Checks the boolean value |
482
|
|
|
* @param string $field |
483
|
|
|
* @param string $value |
484
|
|
|
* @param null|mixed $param |
485
|
|
|
*/ |
486
|
|
|
protected function boolean(string $field, string $value, $param = null) |
487
|
|
|
{ |
488
|
|
|
if (empty($value) && $value !== 0) { |
489
|
|
|
return true; |
490
|
|
|
} |
491
|
|
|
|
492
|
|
|
$booleans = ['1', 'true', true, 1, '0', 'false', false, 0, 'yes', 'no', 'on', 'off']; |
493
|
|
|
|
494
|
|
|
if (!in_array($value, $booleans, true)) { |
495
|
|
|
$this->addError($field, 'boolean', $param); |
496
|
|
|
} |
497
|
|
|
} |
498
|
|
|
|
499
|
|
|
/** |
500
|
|
|
* Checks for valid URL or subdomain |
501
|
|
|
* @param string $field |
502
|
|
|
* @param string $value |
503
|
|
|
* @param null|mixed $param |
504
|
|
|
*/ |
505
|
|
|
protected function url(string $field, string $value, $param = null) |
506
|
|
|
{ |
507
|
|
|
if (empty($value)) { |
508
|
|
|
return true; |
509
|
|
|
} |
510
|
|
|
|
511
|
|
|
if (filter_var($value, FILTER_VALIDATE_URL) === false) { |
512
|
|
|
$this->addError($field, 'url', $param); |
513
|
|
|
} |
514
|
|
|
} |
515
|
|
|
|
516
|
|
|
/** |
517
|
|
|
* Checks to see if the url exists |
518
|
|
|
* @param string $field |
519
|
|
|
* @param string $value |
520
|
|
|
* @param null|mixed $param |
521
|
|
|
*/ |
522
|
|
|
protected function urlExists(string $field, string $value, $param = null) |
523
|
|
|
{ |
524
|
|
|
if (empty($value)) { |
525
|
|
|
return true; |
526
|
|
|
} |
527
|
|
|
|
528
|
|
|
$error = false; |
529
|
|
|
|
530
|
|
|
if (filter_var($value, FILTER_VALIDATE_URL) !== false) { |
531
|
|
|
$url = parse_url(strtolower($value)); |
532
|
|
|
|
533
|
|
|
if (isset($url['host'])) { |
534
|
|
|
$url = $url['host']; |
535
|
|
|
} |
536
|
|
|
|
537
|
|
|
if (function_exists('checkdnsrr') && function_exists('idn_to_ascii')) { |
538
|
|
|
if (checkdnsrr(idn_to_ascii($url, 0, INTL_IDNA_VARIANT_UTS46), 'A') === false) { |
539
|
|
|
$error = true; |
540
|
|
|
} |
541
|
|
|
} else { |
542
|
|
|
if (gethostbyname($url) == $url) { |
543
|
|
|
$error = true; |
544
|
|
|
} |
545
|
|
|
} |
546
|
|
|
|
547
|
|
|
if ($error) { |
548
|
|
|
$this->addError($field, 'urlExists', $param); |
549
|
|
|
} |
550
|
|
|
} else { |
551
|
|
|
$this->addError($field, 'url', $param); |
552
|
|
|
} |
553
|
|
|
} |
554
|
|
|
|
555
|
|
|
/** |
556
|
|
|
* Checks for valid IP address |
557
|
|
|
* @param string $field |
558
|
|
|
* @param string $value |
559
|
|
|
* @param null|mixed $param |
560
|
|
|
*/ |
561
|
|
|
protected function ip(string $field, string $value, $param = null) |
562
|
|
|
{ |
563
|
|
|
if (empty($value)) { |
564
|
|
|
return true; |
565
|
|
|
} |
566
|
|
|
|
567
|
|
|
if (filter_var($value, FILTER_VALIDATE_IP) === false) { |
568
|
|
|
$this->addError($field, 'ip', $param); |
569
|
|
|
} |
570
|
|
|
} |
571
|
|
|
|
572
|
|
|
/** |
573
|
|
|
* Checks for valid IPv4 address |
574
|
|
|
* @param string $field |
575
|
|
|
* @param string $value |
576
|
|
|
* @param null|mixed $param |
577
|
|
|
*/ |
578
|
|
|
protected function ipv4(string $field, string $value, $param = null) |
579
|
|
|
{ |
580
|
|
|
if (empty($value)) { |
581
|
|
|
return true; |
582
|
|
|
} |
583
|
|
|
|
584
|
|
|
if (filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) === false) { |
585
|
|
|
$this->addError($field, 'ipv4', $param); |
586
|
|
|
} |
587
|
|
|
} |
588
|
|
|
|
589
|
|
|
/** |
590
|
|
|
* Check sfor valid IPv6 address |
591
|
|
|
* @param string $field |
592
|
|
|
* @param string $value |
593
|
|
|
* @param null|mixed $param |
594
|
|
|
*/ |
595
|
|
|
protected function ipv6(string $field, string $value, $param = null) |
596
|
|
|
{ |
597
|
|
|
if (empty($value)) { |
598
|
|
|
return true; |
599
|
|
|
} |
600
|
|
|
|
601
|
|
|
if (filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) === false) { |
602
|
|
|
$this->addError($field, 'ipv6', $param); |
603
|
|
|
} |
604
|
|
|
} |
605
|
|
|
|
606
|
|
|
/** |
607
|
|
|
* Checks for a valid credit card number |
608
|
|
|
* @param string $field |
609
|
|
|
* @param string $value |
610
|
|
|
* @param null|mixed $param |
611
|
|
|
*/ |
612
|
|
|
protected function creditCard(string $field, string $value, $param = null) |
613
|
|
|
{ |
614
|
|
|
if (empty($value)) { |
615
|
|
|
return true; |
616
|
|
|
} |
617
|
|
|
|
618
|
|
|
$number = preg_replace('/\D/', '', $value); |
619
|
|
|
|
620
|
|
|
if (function_exists('mb_strlen')) { |
621
|
|
|
$number_length = mb_strlen($number); |
622
|
|
|
} else { |
623
|
|
|
$number_length = strlen($number); |
624
|
|
|
} |
625
|
|
|
|
626
|
|
|
if ($number_length == 0) { |
627
|
|
|
$this->addError($field, 'creditCard', $param); |
628
|
|
|
} |
629
|
|
|
|
630
|
|
|
$parity = $number_length % 2; |
631
|
|
|
|
632
|
|
|
$total = 0; |
633
|
|
|
|
634
|
|
|
for ($i = 0; $i < $number_length; ++$i) { |
635
|
|
|
$digit = $number[$i]; |
636
|
|
|
|
637
|
|
|
if ($i % 2 == $parity) { |
638
|
|
|
$digit *= 2; |
639
|
|
|
|
640
|
|
|
if ($digit > 9) { |
641
|
|
|
$digit -= 9; |
642
|
|
|
} |
643
|
|
|
} |
644
|
|
|
|
645
|
|
|
$total += $digit; |
646
|
|
|
} |
647
|
|
|
|
648
|
|
|
if ($total % 10 != 0) { |
649
|
|
|
$this->addError($field, 'creditCard', $param); |
650
|
|
|
} |
651
|
|
|
} |
652
|
|
|
|
653
|
|
|
/** |
654
|
|
|
* Checks for a valid format human name |
655
|
|
|
* @param string $field |
656
|
|
|
* @param string $value |
657
|
|
|
* @param null|mixed $param |
658
|
|
|
*/ |
659
|
|
|
protected function name(string $field, string $value, $param = null) |
660
|
|
|
{ |
661
|
|
|
if (empty($value)) { |
662
|
|
|
return true; |
663
|
|
|
} |
664
|
|
|
|
665
|
|
|
if (preg_match("/^([a-z \p{L} '-])+$/i", $value) === 0) { |
666
|
|
|
$this->addError($field, 'name', $param); |
667
|
|
|
} |
668
|
|
|
} |
669
|
|
|
|
670
|
|
|
/** |
671
|
|
|
* Verifies that a value is contained within the pre-defined value set |
672
|
|
|
* @param string $field |
673
|
|
|
* @param string $value |
674
|
|
|
* @param null|mixed $param |
675
|
|
|
*/ |
676
|
|
|
protected function contains(string $field, string $value, $param = null) |
677
|
|
|
{ |
678
|
|
|
if (empty($value)) { |
679
|
|
|
return true; |
680
|
|
|
} |
681
|
|
|
|
682
|
|
|
$param = trim(strtolower($param)); |
683
|
|
|
$value = trim(strtolower($value)); |
684
|
|
|
|
685
|
|
|
if (preg_match_all('#\'(.+?)\'#', $param, $matches, PREG_PATTERN_ORDER)) { |
686
|
|
|
$param = $matches[1]; |
687
|
|
|
} else { |
688
|
|
|
$param = explode(chr(32), $param); |
689
|
|
|
} |
690
|
|
|
|
691
|
|
|
if (!in_array($value, $param)) { |
692
|
|
|
$this->addError($field, 'contains', null); |
693
|
|
|
} |
694
|
|
|
} |
695
|
|
|
|
696
|
|
|
/** |
697
|
|
|
* Verifies that a value is contained within the pre-defined value set. |
698
|
|
|
* @param string $field |
699
|
|
|
* @param string $value |
700
|
|
|
* @param array $param |
701
|
|
|
*/ |
702
|
|
|
protected function containsList(string $field, string $value, array $param) |
703
|
|
|
{ |
704
|
|
|
if (empty($value)) { |
705
|
|
|
return true; |
706
|
|
|
} |
707
|
|
|
|
708
|
|
|
$param = array_map(function($param) { |
709
|
|
|
return trim(strtolower($param)); |
710
|
|
|
}, $param); |
711
|
|
|
|
712
|
|
|
$value = trim(strtolower($value)); |
713
|
|
|
|
714
|
|
|
if (!in_array($value, $param)) { |
715
|
|
|
$this->addError($field, 'containsList', 'null'); |
716
|
|
|
} |
717
|
|
|
} |
718
|
|
|
|
719
|
|
|
/** |
720
|
|
|
* Verifies that a value is not contained within the pre-defined value set. |
721
|
|
|
* @param string $field |
722
|
|
|
* @param string $value |
723
|
|
|
* @param array $param |
724
|
|
|
*/ |
725
|
|
|
protected function doesntContainsList(string $field, string $value, array $param) |
726
|
|
|
{ |
727
|
|
|
if (empty($value)) { |
728
|
|
|
return true; |
729
|
|
|
} |
730
|
|
|
|
731
|
|
|
$param = array_map(function($param) { |
732
|
|
|
return trim(strtolower($param)); |
733
|
|
|
}, $param); |
734
|
|
|
|
735
|
|
|
$value = trim(strtolower($value)); |
736
|
|
|
|
737
|
|
|
if (in_array($value, $param)) { |
738
|
|
|
$this->addError($field, 'doesntContainsList', null); |
739
|
|
|
} |
740
|
|
|
} |
741
|
|
|
|
742
|
|
|
/** |
743
|
|
|
* Checks that the provided string is a likely street address. |
744
|
|
|
* @param string $field |
745
|
|
|
* @param string $value |
746
|
|
|
* @param null|mixed $param |
747
|
|
|
*/ |
748
|
|
|
protected function streetAddress(string $field, string $value, $param = null) |
749
|
|
|
{ |
750
|
|
|
if (empty($value)) { |
751
|
|
|
return true; |
752
|
|
|
} |
753
|
|
|
|
754
|
|
|
$hasLetter = preg_match('/[a-zA-Z]/', $value); |
755
|
|
|
$hasDigit = preg_match('/\d/', $value); |
756
|
|
|
$hasSpace = preg_match('/\s/', $value); |
757
|
|
|
|
758
|
|
|
$passes = $hasLetter && $hasDigit && $hasSpace; |
759
|
|
|
|
760
|
|
|
if (!$passes) { |
761
|
|
|
$this->addError($field, 'streetAddress', $param); |
762
|
|
|
} |
763
|
|
|
} |
764
|
|
|
|
765
|
|
|
/** |
766
|
|
|
* Checks for a valid IBAN |
767
|
|
|
* @param string $field |
768
|
|
|
* @param string $value |
769
|
|
|
* @param null|mixed $param |
770
|
|
|
*/ |
771
|
|
|
protected function iban(string $field, string $value, $param = null) |
772
|
|
|
{ |
773
|
|
|
if (empty($value)) { |
774
|
|
|
return true; |
775
|
|
|
} |
776
|
|
|
|
777
|
|
|
static $character = [ |
778
|
|
|
'A' => 10, 'C' => 12, 'D' => 13, 'E' => 14, 'F' => 15, 'G' => 16, |
779
|
|
|
'H' => 17, 'I' => 18, 'J' => 19, 'K' => 20, 'L' => 21, 'M' => 22, |
780
|
|
|
'N' => 23, 'O' => 24, 'P' => 25, 'Q' => 26, 'R' => 27, 'S' => 28, |
781
|
|
|
'T' => 29, 'U' => 30, 'V' => 31, 'W' => 32, 'X' => 33, 'Y' => 34, |
782
|
|
|
'Z' => 35, 'B' => 11, |
783
|
|
|
]; |
784
|
|
|
|
785
|
|
|
if (!preg_match("/\A[A-Z]{2}\d{2} ?[A-Z\d]{4}( ?\d{4}){1,} ?\d{1,4}\z/", $value)) { |
786
|
|
|
$this->addError($field, 'iban', $param); |
787
|
|
|
} |
788
|
|
|
|
789
|
|
|
$iban = str_replace(' ', '', $value); |
790
|
|
|
$iban = substr($iban, 4) . substr($iban, 0, 4); |
791
|
|
|
$iban = strtr($iban, $character); |
792
|
|
|
|
793
|
|
|
if (bcmod($iban, 97) != 1) { |
794
|
|
|
$this->addError($field, 'iban', $param); |
795
|
|
|
} |
796
|
|
|
} |
797
|
|
|
|
798
|
|
|
/** |
799
|
|
|
* Determines if the provided numeric value is lower to a specific value |
800
|
|
|
* @param string $field |
801
|
|
|
* @param string $value |
802
|
|
|
* @param null|mixed $param |
803
|
|
|
*/ |
804
|
|
|
protected function minNumeric(string $field, string $value, $param = null) |
805
|
|
|
{ |
806
|
|
|
if (empty($value)) { |
807
|
|
|
return true; |
808
|
|
|
} |
809
|
|
|
|
810
|
|
|
if (!is_numeric($value) || !is_numeric($param) || ($value < $param)) { |
811
|
|
|
$this->addError($field, 'minNumeric', $param); |
812
|
|
|
} |
813
|
|
|
} |
814
|
|
|
|
815
|
|
|
/** |
816
|
|
|
* Determines if the provided numeric value is higher to a specific value |
817
|
|
|
* @param string $field |
818
|
|
|
* @param string $value |
819
|
|
|
* @param null|mixed $param |
820
|
|
|
*/ |
821
|
|
|
protected function maxNumeric(string $field, string $value, $param = null) |
822
|
|
|
{ |
823
|
|
|
if (empty($value)) { |
824
|
|
|
return true; |
825
|
|
|
} |
826
|
|
|
|
827
|
|
|
if (!is_numeric($value) || !is_numeric($param) || ($value > $param)) { |
828
|
|
|
$this->addError($field, 'maxNumeric', $param); |
829
|
|
|
} |
830
|
|
|
} |
831
|
|
|
|
832
|
|
|
/** |
833
|
|
|
* Determines if the provided input is a valid date |
834
|
|
|
* @param string $field |
835
|
|
|
* @param string $value |
836
|
|
|
* @param null|string $param format |
837
|
|
|
*/ |
838
|
|
|
protected function date(string $field, string $value, $param = null) |
839
|
|
|
{ |
840
|
|
|
if (empty($value)) { |
841
|
|
|
return true; |
842
|
|
|
} |
843
|
|
|
|
844
|
|
|
if (!$param) { |
845
|
|
|
$cdate1 = date('Y-m-d', strtotime($value)); |
846
|
|
|
$cdate2 = date('Y-m-d H:i:s', strtotime($value)); |
847
|
|
|
|
848
|
|
|
if ($cdate1 != $value && $cdate2 != $value) { |
849
|
|
|
$this->addError($field, 'date', $param); |
850
|
|
|
} |
851
|
|
|
} else { |
852
|
|
|
$date = \DateTime::createFromFormat($param, $value); |
853
|
|
|
|
854
|
|
|
if ($date === false || $value != date($param, $date->getTimestamp())) { |
855
|
|
|
$this->addError($field, 'date', $param); |
856
|
|
|
} |
857
|
|
|
} |
858
|
|
|
} |
859
|
|
|
|
860
|
|
|
/** |
861
|
|
|
* Ensures the value starts with a certain character / set of character |
862
|
|
|
* @param string $field |
863
|
|
|
* @param string $value |
864
|
|
|
* @param null|mixed $param |
865
|
|
|
*/ |
866
|
|
|
protected function starts(string $field, string $value, $param = null) |
867
|
|
|
{ |
868
|
|
|
if (empty($value)) { |
869
|
|
|
return true; |
870
|
|
|
} |
871
|
|
|
|
872
|
|
|
if (strpos($value, $param) !== 0) { |
873
|
|
|
$this->addError($field, 'starts', $param); |
874
|
|
|
} |
875
|
|
|
} |
876
|
|
|
|
877
|
|
|
/** |
878
|
|
|
* Validates the phone number // 555-555-5555 , 5555425555, 555 555 5555, 1(519) 555-4444, 1 (519) 555-4422, +1-555-555-5555 |
879
|
|
|
* @param string $field |
880
|
|
|
* @param string $value |
881
|
|
|
* @param null|mixed $param |
882
|
|
|
*/ |
883
|
|
|
protected function phoneNumber(string $field, string $value, $param = null) |
884
|
|
|
{ |
885
|
|
|
if (empty($value)) { |
886
|
|
|
return true; |
887
|
|
|
} |
888
|
|
|
|
889
|
|
|
$regex = '/^(\+*\d[\s-]?)?[\(\[\s-]{0,2}?\d{3}[\)\]\s-]{0,2}?\d{3}[\s-]?\d{4}$/i'; |
890
|
|
|
|
891
|
|
|
if (!preg_match($regex, $value)) { |
892
|
|
|
$this->addError($field, 'phoneNumber', $param); |
893
|
|
|
} |
894
|
|
|
} |
895
|
|
|
|
896
|
|
|
/** |
897
|
|
|
* Custom regex validator |
898
|
|
|
* @param string $field |
899
|
|
|
* @param string $value |
900
|
|
|
* @param null|mixed $param |
901
|
|
|
*/ |
902
|
|
|
protected function regex(string $field, string $value, $param = null) |
903
|
|
|
{ |
904
|
|
|
if (empty($value)) { |
905
|
|
|
return true; |
906
|
|
|
} |
907
|
|
|
|
908
|
|
|
if (!preg_match($param, $value)) { |
909
|
|
|
$this->addError($field, 'regex', $param); |
910
|
|
|
} |
911
|
|
|
} |
912
|
|
|
|
913
|
|
|
/** |
914
|
|
|
* Validates JSON string |
915
|
|
|
* @param string $field |
916
|
|
|
* @param string $value |
917
|
|
|
* @param null|mixed $param |
918
|
|
|
*/ |
919
|
|
|
protected function jsonString(string $field, string $value, $param = null) |
920
|
|
|
{ |
921
|
|
|
if (empty($value)) { |
922
|
|
|
return true; |
923
|
|
|
} |
924
|
|
|
|
925
|
|
|
$value = htmlspecialchars_decode($value, ENT_QUOTES); |
926
|
|
|
|
927
|
|
|
if (!is_object(json_decode($value))) { |
928
|
|
|
$this->addError($field, 'jsonString', $param); |
929
|
|
|
} |
930
|
|
|
} |
931
|
|
|
|
932
|
|
|
/** |
933
|
|
|
* Validates same value for both fields |
934
|
|
|
* @param string $field |
935
|
|
|
* @param string $value |
936
|
|
|
* @param null|mixed $param |
937
|
|
|
*/ |
938
|
|
|
protected function same(string $field, string $value, $param = null) |
939
|
|
|
{ |
940
|
|
|
if (empty($value)) { |
941
|
|
|
return true; |
942
|
|
|
} |
943
|
|
|
|
944
|
|
|
if ($value != $this->data[$param]) { |
945
|
|
|
$this->addError($field, 'same', $param); |
946
|
|
|
} |
947
|
|
|
} |
948
|
|
|
|
949
|
|
|
/** |
950
|
|
|
* Validates uniqueness |
951
|
|
|
* @param string $field |
952
|
|
|
* @param object $value |
953
|
|
|
* @param null|mixed $param |
954
|
|
|
*/ |
955
|
|
|
protected function unique(string $field, $value, $param = null) |
956
|
|
|
{ |
957
|
|
|
if (empty($value)) { |
958
|
|
|
return true; |
959
|
|
|
} |
960
|
|
|
|
961
|
|
|
$model = (new ModelFactory())->get(ucfirst($param)); |
962
|
|
|
|
963
|
|
|
$row = $model->findOneBy($field, $value); |
964
|
|
|
|
965
|
|
|
if ($row->count()) { |
966
|
|
|
$this->addError($field, 'unique', null); |
967
|
|
|
} |
968
|
|
|
} |
969
|
|
|
|
970
|
|
|
/** |
971
|
|
|
* Validates file size |
972
|
|
|
* @param string $field |
973
|
|
|
* @param object $value |
974
|
|
|
* @param mixed $param |
975
|
|
|
*/ |
976
|
|
|
protected function fileSize(string $field, $value, $param) |
977
|
|
|
{ |
978
|
|
|
if (empty($value)) { |
979
|
|
|
return true; |
980
|
|
|
} |
981
|
|
|
|
982
|
|
|
$file = new File($value); |
983
|
|
|
|
984
|
|
|
if (!is_array($param)) { |
985
|
|
|
if ($file->getSize() > $param) { |
986
|
|
|
$this->addError($field, 'fileSize', $param); |
987
|
|
|
} |
988
|
|
|
} else { |
989
|
|
|
if ($file->getSize() < $param[0] || $file->getSize() > $param[1]) { |
990
|
|
|
$this->addError($field, 'fileSize', $param); |
991
|
|
|
} |
992
|
|
|
} |
993
|
|
|
} |
994
|
|
|
|
995
|
|
|
/** |
996
|
|
|
* Validates file mime type |
997
|
|
|
* @param string $field |
998
|
|
|
* @param object $value |
999
|
|
|
* @param mixed $param |
1000
|
|
|
*/ |
1001
|
|
|
protected function fileMimeType(string $field, $value, $param) |
1002
|
|
|
{ |
1003
|
|
|
if (empty($value)) { |
1004
|
|
|
return true; |
1005
|
|
|
} |
1006
|
|
|
|
1007
|
|
|
$file = new File($value); |
1008
|
|
|
|
1009
|
|
|
if (!is_array($param)) { |
1010
|
|
|
if ($file->getMimetype() != $param) { |
1011
|
|
|
$this->addError($field, 'fileMimeType', $param); |
1012
|
|
|
} |
1013
|
|
|
} else { |
1014
|
|
|
if (!in_array($file->getMimetype(), $param)) { |
1015
|
|
|
$this->addError($field, 'fileMimeType', $param); |
1016
|
|
|
} |
1017
|
|
|
} |
1018
|
|
|
} |
1019
|
|
|
|
1020
|
|
|
/** |
1021
|
|
|
* Validates file extension |
1022
|
|
|
* @param string $field |
1023
|
|
|
* @param object $value |
1024
|
|
|
* @param mixed $param |
1025
|
|
|
*/ |
1026
|
|
|
protected function fileExtension(string $field, $value, $param) |
1027
|
|
|
{ |
1028
|
|
|
if (empty($value)) { |
1029
|
|
|
return true; |
1030
|
|
|
} |
1031
|
|
|
|
1032
|
|
|
$file = new File($value); |
1033
|
|
|
|
1034
|
|
|
if (!is_array($param)) { |
1035
|
|
|
if ($file->getExtension() != $param) { |
1036
|
|
|
$this->addError($field, 'fileExtension', $param); |
1037
|
|
|
} |
1038
|
|
|
} else { |
1039
|
|
|
if (!in_array($file->getExtension(), $param)) { |
1040
|
|
|
$this->addError($field, 'fileExtension', $param); |
1041
|
|
|
} |
1042
|
|
|
} |
1043
|
|
|
} |
1044
|
|
|
|
1045
|
|
|
/** |
1046
|
|
|
* Validates image dimensions |
1047
|
|
|
* @param string $field |
1048
|
|
|
* @param object $value |
1049
|
|
|
* @param array $param |
1050
|
|
|
*/ |
1051
|
|
|
protected function imageDimensions(string $field, $value, $param) |
1052
|
|
|
{ |
1053
|
|
|
if (empty($value)) { |
1054
|
|
|
return true; |
1055
|
|
|
} |
1056
|
|
|
|
1057
|
|
|
$file = new File($value); |
1058
|
|
|
|
1059
|
|
|
$dimensions = $file->getDimensions(); |
1060
|
|
|
|
1061
|
|
|
if ($dimensions) { |
|
|
|
|
1062
|
|
|
if ($dimensions['width'] != $param[0] || $dimensions['height'] != $param[1]) { |
1063
|
|
|
$this->addError($field, 'imageDimensions', $param); |
1064
|
|
|
} |
1065
|
|
|
} |
1066
|
|
|
} |
1067
|
|
|
|
1068
|
|
|
} |
1069
|
|
|
|
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.