Completed
Push — master ( fdda97...b0b47a )
by Arman
17s queued 11s
created

src/Libraries/Validation/Validator.php (4 issues)

Labels
Severity
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
    {
116
        $this->rules = [];
117
        $this->flushErrors();
118
    }
119
120
    /**
121
     * Validates the data against the rules
122
     * @param array $data
123
     * @return mixed
124
     */
125
    public function isValid(array $data)
126
    {
127
        $this->data = $data;
128
129
        if (count($this->rules)) {
130
131
            foreach ($this->rules as $field => $rule) {
132
                if (!array_key_exists($field, $data)) {
133
                    $data[$field] = '';
134
                }
135
            }
136
137
            foreach ($data as $field => $value) {
138
139
                if (isset($this->rules[$field])) {
140
                    foreach ($this->rules[$field] as $method => $param) {
141
142
                        if (is_callable([$this, $method])) {
143
                            $this->$method($field, $value, $param);
144
                        } elseif (isset($this->customValidations[$method])) {
145
                            $data = [
146
                                'rule' => $method,
147
                                'field' => $field,
148
                                'value' => $value,
149
                                'param' => $param ?? null
150
                            ];
151
152
                            $this->callCustomFunction($this->customValidations[$method], $data);
153
                        }
154
                    }
155
                }
156
            }
157
        }
158
        return count($this->errors) ? false : true;
159
    }
160
161
    /**
162
     * Adds custom validation
163
     * @param string $rule
164
     * @param \Closure $function
165
     * @param null|mixed $params
166
     * @return mixed
167
     */
168
    public function addValidation(string $rule, \Closure $function)
169
    {
170
        if (!empty($rule) && is_callable($function)) {
171
            $this->customValidations[$rule] = $function;
172
        }
173
    }
174
175
    /**
176
     * Gets validation errors
177
     * @return array
178
     */
179
    public function getErrors(): array
180
    {
181
        if (count($this->errors)) {
182
            $messages = [];
183
            foreach ($this->errors as $field => $errors) {
184
                if (count($errors)) {
185
                    foreach ($errors as $rule => $param) {
186
                        $translatoinParams = [ucfirst($field)];
187
188
                        if ($param) {
189
                            $translatoinParams[] = $param;
190
                        }
191
192
                        if (!isset($messages[$field])) {
193
                            $messages[$field] = [];
194
                        }
195
196
                        $messages[$field][] = t("validation.$rule", $translatoinParams);
197
                    }
198
                }
199
            }
200
201
            return $messages;
202
        }
203
204
        return [];
205
    }
206
207
    /**
208
     * Adds validation Error
209
     * @param string $field
210
     * @param string $rule
211
     * @param null|mixed $param
212
     */
213
    protected function addError($field, $rule, $param = null)
214
    {
215
        if (!isset($this->errors[$field])) {
216
            $this->errors[$field] = [];
217
        }
218
219
        $this->errors[$field][$rule] = $param;
220
    }
221
222
    public function flushErrors()
223
    {
224
        $this->errors = [];
225
    }
226
227
    /**
228
     * Calls custom function defined by developer
229
     * @param \Closure $function : boolean
230
     * @param array $data
231
     */
232
    protected function callCustomFunction(\Closure $function, array $data)
233
    {
234
        if (empty($data['value'])) {
235
            return true;
236
        }
237
238
        if (is_callable($function)) {
239
            if (!$function($data['value'], $data['param'])) {
240
                $this->addError($data['field'], $data['rule'], $data['param']);
241
            }
242
        }
243
    }
244
245
    /**
246
     * Checks Field Required
247
     * @param string $field
248
     * @param string $value
249
     * @param null|mixed $param
250
     */
251
    protected function required(string $field, string $value, $param = null)
252
    {
253
        if ($value === false || $value === '0' || empty($value)) {
254
            $this->addError($field, 'required', $param);
255
        }
256
    }
257
258
    /**
259
     * Checks Email
260
     * @param string $field
261
     * @param string $value
262
     * @param null|mixed $param
263
     */
264
    protected function email(string $field, string $value, $param = null)
265
    {
266
        if (empty($value)) {
267
            return true;
268
        }
269
270
        if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {
271
            $this->addError($field, 'email', $param);
272
        }
273
    }
274
275
    /**
276
     * Checks the min Length
277
     * @param string $field
278
     * @param string $value
279
     * @param null|mixed $param
280
     */
281
    protected function minLen(string $field, string $value, $param = null)
282
    {
283
        $error = false;
284
285
        if (empty($value)) {
286
            return true;
287
        }
288
289
        if (function_exists('mb_strlen')) {
290
            if (mb_strlen($value) < (int) $param) {
291
                $error = true;
292
            }
293
        } else {
294
            if (strlen($value) < (int) $param) {
295
                $error = true;
296
            }
297
        }
298
299
        if ($error) {
300
            $this->addError($field, 'minLen', $param);
301
        }
302
    }
303
304
    /**
305
     * Checks the max Length
306
     * @param string $field
307
     * @param string $value
308
     * @param null|mixed $param
309
     */
310
    protected function maxLen(string $field, string $value, $param = null)
311
    {
312
        $error = false;
313
314
        if (empty($value)) {
315
            return true;
316
        }
317
318
        if (function_exists('mb_strlen')) {
319
            if (mb_strlen($value) > (int) $param) {
320
                $error = true;
321
            }
322
        } else {
323
            if (strlen($value) > (int) $param) {
324
                $error = true;
325
            }
326
        }
327
328
        if ($error) {
329
            $this->addError($field, 'maxLen', $param);
330
        }
331
    }
332
333
    /**
334
     * Checks the exact length
335
     * @param string $field
336
     * @param string $value
337
     * @param null|mixed $param
338
     */
339
    protected function exactLen(string $field, string $value, $param = null)
340
    {
341
        $error = false;
342
343
        if (empty($value)) {
344
            return true;
345
        }
346
347
        if (function_exists('mb_strlen')) {
348
            if (mb_strlen($value) !== (int) $param) {
349
                $error = true;
350
            }
351
        } else {
352
            if (strlen($value) !== (int) $param) {
353
                $error = true;
354
            }
355
        }
356
357
        if ($error) {
358
            $this->addError($field, 'exactLen', $param);
359
        }
360
    }
361
362
    /**
363
     * Checks the alpha characters
364
     * @param string $field
365
     * @param string $value
366
     * @param null|mixed $param
367
     */
368
    protected function alpha(string $field, string $value, $param = null)
369
    {
370
        if (empty($value)) {
371
            return true;
372
        }
373
374
        if (preg_match('/^([a-zÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÒÓÔÕÖßÙÚÛÜÝàáâãäåçèéêëìíîïðòóôõöùúûüýÿ])+$/i', $value) === 0) {
375
            $this->addError($field, 'alpha', $param);
376
        }
377
    }
378
379
    /**
380
     * Checks the alpha and numeric characters
381
     * @param string $field
382
     * @param string $value
383
     * @param null|mixed $param
384
     */
385
    protected function alphaNumeric(string $field, string $value, $param = null)
386
    {
387
        if (empty($value)) {
388
            return true;
389
        }
390
391
        if (preg_match('/^([a-z0-9ÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÒÓÔÕÖßÙÚÛÜÝàáâãäåçèéêëìíîïðòóôõöùúûüýÿ])+$/i', $value) === 0) {
392
            $this->addError($field, 'alphaNumeric', $param);
393
        }
394
    }
395
396
    /**
397
     * Checks the alpha and dash characters
398
     * @param string $field
399
     * @param string $value
400
     * @param null|mixed $param
401
     */
402
    protected function alphaDash(string $field, string $value, $param = null)
403
    {
404
        if (empty($value)) {
405
            return true;
406
        }
407
408
        if (preg_match('/^([a-zÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÒÓÔÕÖßÙÚÛÜÝàáâãäåçèéêëìíîïðòóôõöùúûüýÿ_-])+$/i', $value) === 0) {
409
            $this->addError($field, 'alphaDash', $param);
410
        }
411
    }
412
413
    /**
414
     * Checks the alpha numeric and space characters
415
     * @param string $field
416
     * @param string $value
417
     * @param null|mixed $param
418
     */
419
    protected function alphaSpace(string $field, string $value, $param = null)
420
    {
421
        if (empty($value)) {
422
            return true;
423
        }
424
425
        if (preg_match('/^([a-z0-9ÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÒÓÔÕÖßÙÚÛÜÝàáâãäåçèéêëìíîïðòóôõöùúûüýÿ\s])+$/i', $value) === 0) {
426
            $this->addError($field, 'alphaSpace', $param);
427
        }
428
    }
429
430
    /**
431
     * Checks the numeric value
432
     * @param string $field
433
     * @param string $value
434
     * @param null|mixed $param
435
     */
436
    protected function numeric(string $field, string $value, $param = null)
437
    {
438
        if (empty($value)) {
439
            return true;
440
        }
441
442
        if (!is_numeric($value)) {
443
            $this->addError($field, 'numeric', $param);
444
        }
445
    }
446
447
    /**
448
     * Checks the integer value
449
     * @param string $field
450
     * @param string $value
451
     * @param null|mixed $param
452
     */
453
    protected function integer(string $field, string $value, $param = null)
454
    {
455
        if (empty($value)) {
456
            return true;
457
        }
458
459
        if (filter_var($value, FILTER_VALIDATE_INT) === false) {
460
            $this->addError($field, 'integer', $param);
461
        }
462
    }
463
464
    /**
465
     * Checks the float value
466
     * @param string $field
467
     * @param string $value
468
     * @param null|mixed $param
469
     */
470
    protected function float(string $field, string $value, $param = null)
471
    {
472
    if(empty($value)) {
473
    return true;
474
    }
475
476
    if(  filter_var($value, FILTER_VALIDATE_FLOAT) === false) {
477
        $this->addError($field, 'float', $param);
478
    }
479
}
480
481
/**
482
 * Checks the boolean value
483
 * @param string $field
484
 * @param string $value
485
 * @param null|mixed $param
486
 */
487
protected function boolean(string $field, string $value, $param = null)
488
{
489
    if (empty($value) && $value !== 0) {
490
        return true;
491
    }
492
493
    $booleans = ['1', 'true', true, 1, '0', 'false', false, 0, 'yes', 'no', 'on', 'off'];
494
495
    if (!in_array($value, $booleans, true)) {
496
        $this->addError($field, 'boolean', $param);
497
    }
498
}
499
500
/**
501
 * Checks for valid URL or subdomain
502
 * @param string $field
503
 * @param string $value
504
 * @param null|mixed $param
505
 */
506
protected function url(string $field, string $value, $param = null)
507
{
508
    if (empty($value)) {
509
        return true;
510
    }
511
512
    if (filter_var($value, FILTER_VALIDATE_URL) === false) {
513
        $this->addError($field, 'url', $param);
514
    }
515
}
516
517
/**
518
 * Checks to see if the url exists
519
 * @param string $field
520
 * @param string $value
521
 * @param null|mixed $param
522
 */
523
protected function urlExists(string $field, string $value, $param = null)
524
{
525
    if (empty($value)) {
526
        return true;
527
    }
528
529
    $error = false;
530
531
    if (filter_var($value, FILTER_VALIDATE_URL) !== false) {
532
        $url = parse_url(strtolower($value));
533
534
        if (isset($url['host'])) {
535
            $url = $url['host'];
536
        }
537
538
        if (function_exists('checkdnsrr') && function_exists('idn_to_ascii')) {
539
            if (checkdnsrr(idn_to_ascii($url, 0, INTL_IDNA_VARIANT_UTS46), 'A') === false) {
540
                $error = true;
541
            }
542
        } else {
543
            if (gethostbyname($url) == $url) {
544
                $error = true;
545
            }
546
        }
547
548
        if ($error) {
549
            $this->addError($field, 'urlExists', $param);
550
        }
551
    } else {
552
        $this->addError($field, 'url', $param);
553
    }
554
}
555
556
/**
557
 * Checks for valid IP address
558
 * @param string $field
559
 * @param string $value
560
 * @param null|mixed $param
561
 */
562
protected function ip(string $field, string $value, $param = null)
563
{
564
    if (empty($value)) {
565
        return true;
566
    }
567
568
    if (filter_var($value, FILTER_VALIDATE_IP) === false) {
569
        $this->addError($field, 'ip', $param);
570
    }
571
}
572
573
/**
574
 * Checks for valid IPv4 address
575
 * @param string $field
576
 * @param string $value
577
 * @param null|mixed $param
578
 */
579
protected function ipv4(string $field, string $value, $param = null)
580
{
581
    if (empty($value)) {
582
        return true;
583
    }
584
585
    if (filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) === false) {
586
        $this->addError($field, 'ipv4', $param);
587
    }
588
}
589
590
/**
591
 * Check sfor valid IPv6 address
592
 * @param string $field
593
 * @param string $value
594
 * @param null|mixed $param
595
 */
596
protected function ipv6(string $field, string $value, $param = null)
597
{
598
    if (empty($value)) {
599
        return true;
600
    }
601
602
    if (filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) === false) {
603
        $this->addError($field, 'ipv6', $param);
604
    }
605
}
606
607
/**
608
 * Checks for a valid credit card number
609
 * @param string $field
610
 * @param string $value
611
 * @param null|mixed $param
612
 */
613
protected function creditCard(string $field, string $value, $param = null)
614
{
615
    if (empty($value)) {
616
        return true;
617
    }
618
619
    $number = preg_replace('/\D/', '', $value);
620
621
    if (function_exists('mb_strlen')) {
622
        $number_length = mb_strlen($number);
623
    } else {
624
        $number_length = strlen($number);
625
    }
626
627
    if ($number_length == 0) {
628
        $this->addError($field, 'creditCard', $param);
629
    }
630
631
    $parity = $number_length % 2;
632
633
    $total = 0;
634
635
    for ($i = 0; $i < $number_length; ++$i) {
636
        $digit = $number[$i];
637
638
        if ($i % 2 == $parity) {
639
            $digit *= 2;
640
641
            if ($digit > 9) {
642
                $digit -= 9;
643
            }
644
        }
645
646
        $total += $digit;
647
    }
648
649
    if ($total % 10 != 0) {
650
        $this->addError($field, 'creditCard', $param);
651
    }
652
}
653
654
/**
655
 * Checks for a valid format human name
656
 * @param string $field
657
 * @param string $value
658
 * @param null|mixed $param
659
 */
660
protected function name(string $field, string $value, $param = null)
661
{
662
    if (empty($value)) {
663
        return true;
664
    }
665
666
    if (preg_match("/^([a-z \p{L} '-])+$/i", $value) === 0) {
667
        $this->addError($field, 'name', $param);
668
    }
669
}
670
671
/**
672
 * Verifies that a value is contained within the pre-defined value set
673
 * @param string $field
674
 * @param string $value
675
 * @param null|mixed $param
676
 */
677
protected function contains(string $field, string $value, $param = null)
678
{
679
    if (empty($value)) {
680
        return true;
681
    }
682
683
    $param = trim(strtolower($param));
0 ignored issues
show
It seems like $param can also be of type null; however, parameter $string of strtolower() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

683
    $param = trim(strtolower(/** @scrutinizer ignore-type */ $param));
Loading history...
684
    $value = trim(strtolower($value));
685
686
    if (preg_match_all('#\'(.+?)\'#', $param, $matches, PREG_PATTERN_ORDER)) {
687
        $param = $matches[1];
688
    } else {
689
        $param = explode(chr(32), $param);
690
    }
691
692
    if (!in_array($value, $param)) {
693
        $this->addError($field, 'contains', null);
694
    }
695
}
696
697
/**
698
 * Verifies that a value is contained within the pre-defined value set.
699
 * @param string $field
700
 * @param string $value
701
 * @param array $param
702
 */
703
protected function containsList(string $field, string $value, array $param)
704
{
705
    if (empty($value)) {
706
        return true;
707
    }
708
709
    $param = array_map(function($param) {
710
        return trim(strtolower($param));
711
    }, $param);
712
713
    $value = trim(strtolower($value));
714
715
    if (!in_array($value, $param)) {
716
        $this->addError($field, 'containsList', 'null');
717
    }
718
}
719
720
/**
721
 * Verifies that a value is not contained within the pre-defined value set.
722
 * @param string $field
723
 * @param string $value
724
 * @param array $param
725
 */
726
protected function doesntContainsList(string $field, string $value, array $param)
727
{
728
    if (empty($value)) {
729
        return true;
730
    }
731
732
    $param = array_map(function($param) {
733
        return trim(strtolower($param));
734
    }, $param);
735
736
    $value = trim(strtolower($value));
737
738
    if (in_array($value, $param)) {
739
        $this->addError($field, 'doesntContainsList', null);
740
    }
741
}
742
743
/**
744
 * Checks that the provided string is a likely street address.
745
 * @param string $field
746
 * @param string $value
747
 * @param null|mixed $param
748
 */
749
protected function streetAddress(string $field, string $value, $param = null)
750
{
751
    if (empty($value)) {
752
        return true;
753
    }
754
755
    $hasLetter = preg_match('/[a-zA-Z]/', $value);
756
    $hasDigit = preg_match('/\d/', $value);
757
    $hasSpace = preg_match('/\s/', $value);
758
759
    $passes = $hasLetter && $hasDigit && $hasSpace;
760
761
    if (!$passes) {
762
        $this->addError($field, 'streetAddress', $param);
763
    }
764
}
765
766
/**
767
 * Checks for a valid IBAN
768
 * @param string $field
769
 * @param string $value
770
 * @param null|mixed $param
771
 */
772
protected function iban(string $field, string $value, $param = null)
773
{
774
    if (empty($value)) {
775
        return true;
776
    }
777
778
    static $character = [
779
        'A' => 10, 'C' => 12, 'D' => 13, 'E' => 14, 'F' => 15, 'G' => 16,
780
        'H' => 17, 'I' => 18, 'J' => 19, 'K' => 20, 'L' => 21, 'M' => 22,
781
        'N' => 23, 'O' => 24, 'P' => 25, 'Q' => 26, 'R' => 27, 'S' => 28,
782
        'T' => 29, 'U' => 30, 'V' => 31, 'W' => 32, 'X' => 33, 'Y' => 34,
783
        'Z' => 35, 'B' => 11,
784
    ];
785
786
    if (!preg_match("/\A[A-Z]{2}\d{2} ?[A-Z\d]{4}( ?\d{4}){1,} ?\d{1,4}\z/", $value)) {
787
        $this->addError($field, 'iban', $param);
788
    }
789
790
    $iban = str_replace(' ', '', $value);
791
    $iban = substr($iban, 4) . substr($iban, 0, 4);
792
    $iban = strtr($iban, $character);
793
794
    if (bcmod($iban, 97) != 1) {
795
        $this->addError($field, 'iban', $param);
796
    }
797
}
798
799
/**
800
 * Determines if the provided numeric value is lower to a specific value
801
 * @param string $field
802
 * @param string $value
803
 * @param null|mixed $param
804
 */
805
protected function minNumeric(string $field, string $value, $param = null)
806
{
807
    if (empty($value)) {
808
        return true;
809
    }
810
811
    if (!is_numeric($value) || !is_numeric($param) || ($value < $param)) {
812
        $this->addError($field, 'minNumeric', $param);
813
    }
814
}
815
816
/**
817
 * Determines if the provided numeric value is higher to a specific value
818
 * @param string $field
819
 * @param string $value
820
 * @param null|mixed $param
821
 */
822
protected function maxNumeric(string $field, string $value, $param = null)
823
{
824
    if (empty($value)) {
825
        return true;
826
    }
827
828
    if (!is_numeric($value) || !is_numeric($param) || ($value > $param)) {
829
        $this->addError($field, 'maxNumeric', $param);
830
    }
831
}
832
833
/**
834
 * Determines if the provided input is a valid date
835
 * @param string $field
836
 * @param string $value
837
 * @param null|string $param format
838
 */
839
protected function date(string $field, string $value, $param = null)
840
{
841
    if (empty($value)) {
842
        return true;
843
    }
844
845
    if (!$param) {
846
        $cdate1 = date('Y-m-d', strtotime($value));
847
        $cdate2 = date('Y-m-d H:i:s', strtotime($value));
848
849
        if ($cdate1 != $value && $cdate2 != $value) {
850
            $this->addError($field, 'date', $param);
851
        }
852
    } else {
853
        $date = \DateTime::createFromFormat($param, $value);
854
855
        if ($date === false || $value != date($param, $date->getTimestamp())) {
856
            $this->addError($field, 'date', $param);
857
        }
858
    }
859
}
860
861
/**
862
 * Ensures the value starts with a certain character / set of character
863
 * @param string $field
864
 * @param string $value
865
 * @param null|mixed $param
866
 */
867
protected function starts(string $field, string $value, $param = null)
868
{
869
    if (empty($value)) {
870
        return true;
871
    }
872
873
    if (strpos($value, $param) !== 0) {
0 ignored issues
show
It seems like $param can also be of type null; however, parameter $needle of strpos() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

873
    if (strpos($value, /** @scrutinizer ignore-type */ $param) !== 0) {
Loading history...
874
        $this->addError($field, 'starts', $param);
875
    }
876
}
877
878
/**
879
 * Validates the phone number // 555-555-5555 , 5555425555, 555 555 5555, 1(519) 555-4444, 1 (519) 555-4422, +1-555-555-5555
880
 * @param string $field
881
 * @param string $value
882
 * @param null|mixed $param
883
 */
884
protected function phoneNumber(string $field, string $value, $param = null)
885
{
886
    if (empty($value)) {
887
        return true;
888
    }
889
890
    $regex = '/^(\+*\d[\s-]?)?[\(\[\s-]{0,2}?\d{3}[\)\]\s-]{0,2}?\d{3}[\s-]?\d{4}$/i';
891
892
    if (!preg_match($regex, $value)) {
893
        $this->addError($field, 'phoneNumber', $param);
894
    }
895
}
896
897
/**
898
 * Custom regex validator
899
 * @param string $field
900
 * @param string $value
901
 * @param null|mixed $param
902
 */
903
protected function regex(string $field, string $value, $param = null)
904
{
905
    if (empty($value)) {
906
        return true;
907
    }
908
909
    if (!preg_match($param, $value)) {
0 ignored issues
show
It seems like $param can also be of type null; however, parameter $pattern of preg_match() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

909
    if (!preg_match(/** @scrutinizer ignore-type */ $param, $value)) {
Loading history...
910
        $this->addError($field, 'regex', $param);
911
    }
912
}
913
914
/**
915
 * Validates JSON string
916
 * @param string $field
917
 * @param string $value
918
 * @param null|mixed $param
919
 */
920
protected function jsonString(string $field, string $value, $param = null)
921
{
922
    if (empty($value)) {
923
        return true;
924
    }
925
926
    $value = htmlspecialchars_decode($value, ENT_QUOTES);
927
928
    if (!is_object(json_decode($value))) {
929
        $this->addError($field, 'jsonString', $param);
930
    }
931
}
932
933
/**
934
 * Validates same value for both fields
935
 * @param string $field
936
 * @param string $value
937
 * @param null|mixed $param
938
 */
939
protected function same(string $field, string $value, $param = null)
940
{
941
    if (empty($value)) {
942
        return true;
943
    }
944
945
    if ($value != $this->data[$param]) {
946
        $this->addError($field, 'same', $param);
947
    }
948
}
949
950
/**
951
 * Validates uniqueness
952
 * @param string $field
953
 * @param object $value
954
 * @param null|mixed $param
955
 */
956
protected function unique(string $field, $value, $param = null)
957
{
958
    if (empty($value)) {
959
        return true;
960
    }
961
962
    $model = (new ModelFactory())->get(ucfirst($param));
0 ignored issues
show
It seems like $param can also be of type null; however, parameter $string of ucfirst() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

962
    $model = (new ModelFactory())->get(ucfirst(/** @scrutinizer ignore-type */ $param));
Loading history...
963
964
    $row = $model->findOneBy($field, $value);
965
966
    if ($row->count()) {
967
        $this->addError($field, 'unique', null);
968
    }
969
}
970
971
/**
972
 * Validates file size
973
 * @param string $field
974
 * @param object $value
975
 * @param mixed $param
976
 */
977
protected function fileSize(string $field, $value, $param)
978
{
979
    if (empty($value)) {
980
        return true;
981
    }
982
983
    $file = new File($value);
984
985
    if (!is_array($param)) {
986
        if ($file->getSize() > $param) {
987
            $this->addError($field, 'fileSize', $param);
988
        }
989
    } else {
990
        if ($file->getSize() < $param[0] || $file->getSize() > $param[1]) {
991
            $this->addError($field, 'fileSize', $param);
992
        }
993
    }
994
}
995
996
/**
997
 * Validates file mime type
998
 * @param string $field
999
 * @param object $value
1000
 * @param mixed $param
1001
 */
1002
protected function fileMimeType(string $field, $value, $param)
1003
{
1004
    if (empty($value)) {
1005
        return true;
1006
    }
1007
1008
    $file = new File($value);
1009
1010
    if (!is_array($param)) {
1011
        if ($file->getMimetype() != $param) {
1012
            $this->addError($field, 'fileMimeType', $param);
1013
        }
1014
    } else {
1015
        if (!in_array($file->getMimetype(), $param)) {
1016
            $this->addError($field, 'fileMimeType', $param);
1017
        }
1018
    }
1019
}
1020
1021
/**
1022
 * Validates file extension
1023
 * @param string $field
1024
 * @param object $value
1025
 * @param mixed $param
1026
 */
1027
protected function fileExtension(string $field, $value, $param)
1028
{
1029
    if (empty($value)) {
1030
        return true;
1031
    }
1032
1033
    $file = new File($value);
1034
1035
    if (!is_array($param)) {
1036
        if ($file->getExtension() != $param) {
1037
            $this->addError($field, 'fileExtension', $param);
1038
        }
1039
    } else {
1040
        if (!in_array($file->getExtension(), $param)) {
1041
            $this->addError($field, 'fileExtension', $param);
1042
        }
1043
    }
1044
}
1045
1046
/**
1047
 * Validates image dimensions
1048
 * @param string $field
1049
 * @param object $value
1050
 * @param array $param
1051
 */
1052
protected function imageDimensions(string $field, $value, $param)
1053
{
1054
    if (empty($value)) {
1055
        return true;
1056
    }
1057
1058
    $file = new File($value);
1059
1060
    $dimensions = $file->getDimensions();
1061
1062
    if (!empty($dimensions)) {
1063
        if ($dimensions['width'] != $param[0] || $dimensions['height'] != $param[1]) {
1064
            $this->addError($field, 'imageDimensions', $param);
1065
        }
1066
    }
1067
}
1068
1069
}
1070