Completed
Push — master ( 523786...0f3281 )
by Arman
16s queued 13s
created

Validator::updateRule()   A

Complexity

Conditions 5
Paths 3

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 3
c 2
b 0
f 0
dl 0
loc 5
rs 9.6111
cc 5
nc 3
nop 2
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) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $dimensions of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

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.

Loading history...
introduced by
$dimensions is a non-empty array, thus is always true.
Loading history...
1062
            if ($dimensions['width'] != $param[0] || $dimensions['height'] != $param[1]) {
1063
                $this->addError($field, 'imageDimensions', $param);
1064
            }
1065
        }
1066
    }
1067
1068
}
1069