Passed
Push — 1.0.0-dev ( e83bbe...49e148 )
by nguereza
02:46
created

FormValidation::checkRuleExactLength()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 3
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
    defined('ROOT_PATH') || exit('Access denied');
3
    /**
4
     * TNH Framework
5
     *
6
     * A simple PHP framework using HMVC architecture
7
     *
8
     * This content is released under the MIT License (MIT)
9
     *
10
     * Copyright (c) 2017 TNH Framework
11
     *
12
     * Permission is hereby granted, free of charge, to any person obtaining a copy
13
     * of this software and associated documentation files (the "Software"), to deal
14
     * in the Software without restriction, including without limitation the rights
15
     * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16
     * copies of the Software, and to permit persons to whom the Software is
17
     * furnished to do so, subject to the following conditions:
18
     *
19
     * The above copyright notice and this permission notice shall be included in all
20
     * copies or substantial portions of the Software.
21
     *
22
     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23
     * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24
     * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25
     * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26
     * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27
     * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28
     * SOFTWARE.
29
     */
30
    
31
    class FormValidation extends BaseClass {
32
33
        /**
34
         * The list of validation rules
35
         *
36
         * Format:
37
         * [field1] => array(rule1, rule2)
38
         * [field2] => array(rule3, rule3)
39
         *
40
         * @var array
41
         */
42
        private $rules = array();
43
44
        /**
45
         * The list of field labels
46
         *
47
         * Format:
48
         * [field1] => 'label 1'
49
         * [field2] => 'label 2'
50
         *
51
         * @var array
52
         */
53
        private $labels = array();
54
55
        /**
56
         * The list of errors messages
57
         * Format:
58
         * [field1] => 'error message 1';
59
         * [field2] => 'error message 2';
60
         * 
61
         * @var array
62
         */
63
        private $errors = array();
64
65
        /**
66
         * The validation status
67
         * @var boolean
68
         */
69
        private $valid = false;
70
71
        /**
72
         * Whether we force validation to be an error
73
         * @var boolean
74
         */
75
        private $forceError = false;
76
        
77
        /**
78
         * The list of rules errors messages
79
         *
80
         * Format:
81
         * [rule1] => 'message 1';
82
         * [rule2] => 'message 2';
83
         * Message can contain placeholder: {field}, {label}, {value}, {paramValue}, {field2}'
84
         *
85
         * @var array
86
         */
87
        private $messages = array();
88
        
89
        /**
90
         * The list of the custom errors messages overrides by the original
91
         *
92
         * Format:
93
         * [field1][rule1] = message 1
94
         * [field2][rule2] = message 2
95
         *
96
         * @var array
97
         */
98
        private $customErrors = array();
99
        
100
        /**
101
         * The data to be validated, the default is to use $_POST
102
         * @var array
103
         */
104
        private $data = array();
105
106
        /**
107
         * The database instance to use to validate rules:
108
         * - exists
109
         * - is_unique
110
         * - is_unique_update
111
         * @var object
112
         */
113
        private $database = null;
114
        
115
        /**
116
         * Construct new Form Validation instance
117
         * Reset the field to the default value
118
         * Set the rules validations messages
119
         * And if data of $_POST exists set it as the default
120
         */
121
        public function __construct() {
122
            parent::__construct();
123
124
            //Reset the validation instance
125
            $this->reset();
126
127
            //Set default messages for each validation rule
128
            $this->setValidationMessages();
129
130
            //Set default data to validation from $_POST
131
            if (is_array(get_instance()->request->post(null))) {
132
                $this->setData(get_instance()->request->post(null));
133
            }
134
        }
135
136
         /**
137
         * Reset the form validation instance
138
         *
139
         * @return object the current instance
140
         */
141
        public function reset() {
142
            $this->rules        = array();
143
            $this->labels       = array();
144
            $this->errors       = array();
145
            $this->customErrors = array();
146
            $this->valid        = false;
147
            $this->data         = array();
148
            return $this;
149
        }
150
        
151
        /**
152
         * Set the validation data
153
         * @param array $data the data to be validated
154
         *
155
         * @return object the current instance.
156
         */
157
        public function setData(array $data) {
158
            $this->logger->debug('Setting the form validation data, the values are: ' . stringfy_vars($data));
159
            $this->data = $data;
160
            return $this;
161
        }
162
163
         /**
164
         * Return the validation data
165
         * 
166
         * @return array the validation data
167
         */
168
        public function getData() {
169
            return $this->data;
170
        }
171
172
        /**
173
         * Add new validation rule.
174
         *
175
         * @param string $field name of the field or the data key to add a rule to
176
         * @param string $label the value of the field label
177
         * @param string|array $rule pipe seperated string or array of validation rules
178
         *
179
         * @return object the current instance.
180
         */
181
        public function setRule($field, $label, $rule) {
182
            $rules = array();
183
            //if the rule is array
184
            if (is_array($rule)) {
185
                $rules = $rule;
186
            } else{
187
                //the rule is not an array explode pipe values
188
                $rules = explode('|', $rule);
189
            }
190
            $this->rules[$field] = $rules;
191
            $this->labels[$field] = $label;
192
            return $this;
193
        }
194
195
        /**
196
         * Takes an array of rules and uses $this->setRule() to set them.
197
         * @param array $rules the array of rule
198
         *
199
         * @return object the current instance.
200
         */
201
        public function setRules(array $rules) {
202
            foreach ($rules as $rule) {
203
                call_user_func_array(array($this, 'setRule'), array($rule['name'], $rule['label'], $rule['rules']));
204
            }
205
            return $this;
206
        }
207
208
        /**
209
         * Return the list of the validations rules
210
         * @return array
211
         */
212
        public function getRules() {
213
            return $this->rules;
214
        }
215
216
         /**
217
         * Return the list of the validations rules for the given field
218
         * 
219
         * @return array
220
         */
221
        public function getFieldRules($field) {
222
            $rules = array();
223
            if (array_key_exists($field, $this->rules)) {
224
                $rules = $this->rules[$field];
225
            }
226
            return $rules;
227
        }
228
229
        /**
230
         * Return the value for the given field if exists otherwise null
231
         * will be returned
232
         * 
233
         * @return string|null
234
         */
235
        public function getFieldValue($field) {
236
             $value = null;
237
            if (array_key_exists($field, $this->data)) {
238
                $value = $this->data[$field];
239
            }
240
            return $value;
241
        }
242
243
        /**
244
         * Return the label for the given field if exists otherwise null
245
         * will be returned
246
         * 
247
         * @return string|null
248
         */
249
        public function getFieldLabel($field) {
250
            $label = null;
251
            if (array_key_exists($field, $this->labels)) {
252
                $label = $this->labels[$field];
253
            }
254
            return $label;
255
        }
256
            
257
        
258
       /**
259
        * Return the list of validation errors
260
        * 
261
        * @return array the errors list. 
262
        * Format:
263
        *  [field1] => 'error message 1', 
264
        *  [field2] => 'error message 2' 
265
        */
266
       public function getErrors() {
267
            return $this->errors;
268
        }
269
270
        /**
271
         * Process the data validation of each field, if it has any rules, run
272
         * each rule against the data value. 
273
         * and finally set $this->valid to true if there are no errors otherwise set to false
274
         * in case of error
275
         */
276
        public function validate() {
277
            //if the data is empty just return false
278
            if (empty($this->data)) {
279
                return false;
280
            }
281
            //Apply some filter/clean in the data to validate
282
            $this->filterValidationData();
283
284
            //Check the CSRF status
285
            $this->checkCsrf();
286
287
            //Now loop in each field rule and validate it
288
            foreach($this->rules as $field => $rules) {
289
                $this->validateField($field, $rules);
290
            }
291
            $this->valid = empty($this->errors) && $this->forceError === false;
292
            return $this->valid;
293
        }
294
295
        /**
296
         * Return the validation status
297
         * @return boolean
298
         */
299
        public function isValid() {
300
            return $this->valid;
301
        }
302
303
        /**
304
         * Set a custom error message that can override the default error phrase provided.
305
         *  
306
         * If the parameter $field is null so means will set the error message for
307
         * all fields for the given rule, otherwise only error message for this field and rule will be set
308
         * the others fields use the default one for this rule.
309
         *
310
         * @param string $rule the name of the rule to set error message for.
311
         * @param string $message the error message it can contains the placeholder
312
         * {field}, {label}, {value}, {paramValue}, {field2}.
313
         * @param string|null $field if not null will set the error message only for this field and rule
314
         *
315
         * @return object the current instance.
316
         */
317
        public function setCustomErrorMessage($rule, $message, $field = null) {
318
            //1st if field is null all fields for this rule will be set to the same message
319
            //2nd if field is not null set only for this field
320
            if ($field !== null) {
321
                $this->customErrors[$field][$rule] = $message;
322
            } else {
323
                foreach(array_keys($this->rules) as $field) {
324
                    $this->customErrors[$field][$rule] = $message;
325
                }
326
            }
327
            return $this;
328
        }
329
330
        /**
331
         * Get the database instance
332
         * @return object the database instance
333
         */
334
        public function getDatabase() {
335
            return $this->database;
336
        }
337
338
        /**
339
         * Set the database instance
340
         * @param object $database the database instance
341
         *
342
         * @return object the current instance
343
         */
344
        public function setDatabase(Database $database) {
345
            $this->database = $database;
346
            return $this;
347
        }
348
349
         /**
350
         * Set the database instance using get_instance() if is null
351
         *
352
         * @return object the current instance
353
         */
354
        protected function setDatabaseFromSuperInstanceIfNotSet(){
355
            if (!is_object($this->database)) {
356
                $this->database = get_instance()->database;
357
            }
358
            return $this;
359
        }
360
361
        /**
362
         * Set the validation error for the given field
363
         * @param string $field      the error field
364
         * @param string $rule       the name of the rule raise this error
365
         * @param mixed $paramValue the value of rule parameter
366
         * Example: min_length[17], the $paramValue will be "17"
367
         * @param string|null $field2     the second field used in some validation rule like "matches", "not_equal"
368
         *
369
         * @return object the current instance
370
         */
371
        protected function setFieldError($field, $rule, $paramValue = null, $field2 = null) {
372
            //do we have error before?
373
            if (!array_key_exists($field, $this->errors)) {
374
                $this->errors[$field] = $this->getFieldErrorMessage($field, $rule, $paramValue, $field2);
375
            }
376
            return $this;
377
        }
378
379
        /**
380
         * Set the validation error for the given field by checking if the field is not required
381
         * or contains the value
382
         * @param string $field      the error field
383
         * @param mixed $value      the value of field
384
         * @param string $rule       the name of the rule raise this error
385
         * @param mixed $paramValue the value of rule parameter
386
         * Example: min_length[17], the $paramValue will be "17"
387
         * @param string|null $field2     the second field used in some validation rule like "matches", "not_equal"
388
         *
389
         */
390
         protected function setFieldErrorWithRequiredCheck($field, $value, $rule, $paramValue = null, $field2 = null) {
391
            //if the field is not required and his value is not set don't set error
392
            //but in case the field have value validate it
393
            if (!$this->fieldIsRequired($field) && strlen($value) <= 0) {
394
                return;
395
            }
396
            $this->setFieldError($field, $rule, $paramValue, $field2);
397
        }
398
399
        /**
400
         * Check whether the given field is required or not
401
         * @param  string $field the name of the field
402
         * @return boolean
403
         */
404
        protected function fieldIsRequired($field) {
405
            $rules = $this->getFieldRules($field);
406
            return in_array('required', $rules);
407
        }
408
        
409
        /**
410
         * Return the name of the method to use to validate the given rule
411
         * each method has a prefix of "checkRule"
412
         * @param  string $rule the name of the rule
413
         * @return string       the name of the validation method
414
         */
415
        protected function getRuleValidationMethod($rule) {
416
             $parts = explode('_', $rule);
417
             $parts = array_map('ucfirst', $parts);
418
             return 'checkRule' . implode('', $parts);
419
        }
420
        
421
        /**
422
         * This method is used to apply some filter rule on the validation data
423
         * like remove space, do some clean, etc.
424
         * @return object the current instance
425
         */
426
        protected function filterValidationData() {
427
            foreach($this->data as $key => $value ) {
428
                $this->data[$key] = trim($value);
429
            }
430
            return $this;
431
        }
432
433
        /**
434
         * Validate the CSRF if the current request method is POST
435
         * and the check of CSRF is enabled in the configuration
436
         */
437
        protected function checkCsrf() {
438
            if (get_instance()->request->method() == 'POST') {
439
                $this->logger->debug('Check if CSRF is enabled in configuration');
440
                //first check for CSRF
441
                if (get_config('csrf_enable', false) && !Security::validateCSRF()) {
442
                    $this->forceError = true;
443
                    show_error('Invalide data, Cross Site Request Forgery do his job, the data to validate is corrupted.');
444
                } else {
445
                    $this->logger->info('CSRF is not enabled in configuration or not set manully, no need to check it');
446
                }
447
            }
448
        }
449
              
450
        /**
451
         * Return the validation error message content for the given field
452
         * after replace all placeholders with their values
453
         * @param string $field      the error field
454
         * @param string $rule       the name of the rule raise this error
455
         * @param mixed $paramValue the value of rule parameter
456
         * Example: min_length[17], the $paramValue will be "17"
457
         * @param string|null $field2     the second field used in some validation rule like "matches", "not_equal"
458
         *
459
         * @return string the error message
460
         */
461
        protected function getFieldErrorMessage($field, $rule, $paramValue = null, $field2 = null) {
462
            $template = array(
463
                            '{field}'      => $field,
464
                            '{value}'      => $this->getFieldValue($field),
465
                            '{label}'      => $this->getFieldLabel($field),
466
                            '{paramValue}' => $paramValue
467
                            );
468
            if ($field2 !== null) {
469
                $template['field2}']  = $field2;
470
                $template['{value2}'] = $this->getFieldValue($field2);
471
                $template['{label2}'] = $this->getFieldLabel($field2);
472
             }     
473
            $message = $this->messages[$rule];
474
            //Check for custom message
475
            if (isset($this->customErrors[$field][$rule])) {
476
                $message = $this->customErrors[$field][$rule];
477
            }
478
            return strtr($message, $template);
479
        }
480
481
        /**
482
         * Perform validation for the given field
483
         * @param  string $field the field name
484
         * @param  array $rules the list of rule to validate
485
         */
486
        protected function validateField($field, array $rules) {
487
            foreach($rules as $rule) {
488
                $match = array();
489
                $paramValue = null;
490
                //Is the rule with parameter ??
491
                preg_match('/\[(.*)\]/', $rule, $match);
492
                if (isset($match[1])) {
493
                    $paramValue = $match[1];
494
                }
495
                //Now get the real rule name for example 
496
                //min_length[34]
497
                //the name will be "min_length" and paramValue will be "14"
498
                $realRuleName = preg_replace('/\[(.*)\]/', '', $rule);
499
500
                //Get the name of the method to validate this rule
501
                $method = $this->getRuleValidationMethod($realRuleName);
502
                if (method_exists($this, $method)) {
503
                       call_user_func_array(array($this, $method), array($field, $realRuleName, $paramValue));
504
                }
505
                else{
506
                    $this->forceError = true;
507
                    show_error('Invalid validaton rule "' . $realRuleName . '"');
508
                }
509
            }
510
        }
511
        
512
        /**
513
         * Set the rules validation messages using translation messages
514
         */
515
        protected function setValidationMessages() {
516
            //Load form validation language message
517
            Loader::lang('form_validation');
518
            $obj = & get_instance();
519
520
            $this->messages['required']         = $obj->lang->get('fv_required');
521
            $this->messages['min_length']       = $obj->lang->get('fv_min_length');
522
            $this->messages['max_length']       = $obj->lang->get('fv_max_length');
523
            $this->messages['exact_length']     = $obj->lang->get('fv_exact_length');
524
            $this->messages['matches']          = $obj->lang->get('fv_matches');
525
            $this->messages['not_equal']        = $obj->lang->get('fv_not_equal');
526
            $this->messages['min']              = $obj->lang->get('fv_min');
527
            $this->messages['max']              = $obj->lang->get('fv_max');
528
            $this->messages['between']          = $obj->lang->get('fv_between');
529
            $this->messages['in_list']          = $obj->lang->get('fv_in_list');
530
            $this->messages['numeric']          = $obj->lang->get('fv_numeric');
531
            $this->messages['integer']          = $obj->lang->get('fv_integer');
532
            $this->messages['integer_natural']  = $obj->lang->get('fv_integer_natural');
533
            $this->messages['alpha']            = $obj->lang->get('fv_alpha');
534
            $this->messages['alpha_dash']       = $obj->lang->get('fv_alpha_dash');
535
            $this->messages['alnum']            = $obj->lang->get('fv_alnum');
536
            $this->messages['alnum_dash']       = $obj->lang->get('fv_alnum_dash');
537
            $this->messages['email']            = $obj->lang->get('fv_email');
538
            $this->messages['date']             = $obj->lang->get('fv_date');
539
            $this->messages['date_before']      = $obj->lang->get('fv_date_before');
540
            $this->messages['date_after']       = $obj->lang->get('fv_date_after');
541
            $this->messages['url']              = $obj->lang->get('fv_url');
542
            $this->messages['ip']               = $obj->lang->get('fv_ip');
543
            $this->messages['ipv4']             = $obj->lang->get('fv_ipv4');
544
            $this->messages['ipv6']             = $obj->lang->get('fv_ipv6');
545
            $this->messages['is_unique']        = $obj->lang->get('fv_is_unique');
546
            $this->messages['is_unique_update'] = $obj->lang->get('fv_is_unique_update');
547
            $this->messages['exists']           = $obj->lang->get('fv_exists');
548
            $this->messages['regex']            = $obj->lang->get('fv_regex');
549
            $this->messages['callback']         = $obj->lang->get('fv_callback');
550
        }
551
        
552
553
        /* ---------------------------------------------------------------------------------- */
554
        ///////////////////////////////////////////////////////////////////////////////////////
555
        /**************************** RULES VALIDATION METHODS ******************************/
556
        /////////////////////////////////////////////////////////////////////////////////////
557
        
558
        /**
559
         * Validation of rule "default_value[param]"
560
         *
561
         * NOTE: This one it's not a validation rule it just check if the value for the
562
         * given field is null, empty and set it by the paramter value.
563
         * 
564
         * @param  string $field the name of the field or data key name used
565
         * @param  string $rule  the rule name for this validation ("default_value")
566
         * @param  string|null  $paramValue  the rule parameter
567
         */
568
        protected function checkRuleDefaultValue($field, $rule, $paramValue) {
569
            $value = $this->getFieldValue($field);
570
            if (strlen($value) <= 0) {
571
                $this->data[$field] = $paramValue;
572
            }
573
        }
574
            
575
        /**
576
         * Validation of rule "required"
577
         * 
578
         * @param  string $field the name of the field or data key name used
579
         * @param  string $rule  the rule name for this validation ("required")
580
         * @param  string|null  $paramValue  the rule parameter
581
         */
582
        protected function checkRuleRequired($field, $rule, $paramValue) {
583
            $value = $this->getFieldValue($field);
584
            if ($value == '') {
585
                $this->setFieldError($field, $rule, $paramValue);
586
            }
587
        }
588
        
589
        /**
590
         * Validation of rule "min_length[param]"
591
         * 
592
         * @param  string $field the name of the field or data key name used
593
         * @param  string $rule  the rule name for this validation ("min_length")
594
         * @param  string|null  $paramValue  the rule parameter
595
         */ 
596
        protected function checkRuleMinLength($field, $rule, $paramValue) {
597
           $value = $this->getFieldValue($field);    
598
            if (strlen($value) < $paramValue) {
599
                $this->setFieldErrorWithRequiredCheck($field, $value, $rule, $paramValue);
600
            }
601
        }
602
603
        /**
604
         * Validation of rule "max_length[param]"
605
         * 
606
         * @param  string $field the name of the field or data key name used
607
         * @param  string $rule  the rule name for this validation ("max_length")
608
         * @param  string|null  $paramValue  the rule parameter
609
         */
610
        protected function checkRuleMaxLength($field, $rule, $paramValue) {
611
           $value = $this->getFieldValue($field);    
612
            if (strlen($value) > $paramValue) {
613
                $this->setFieldErrorWithRequiredCheck($field, $value, $rule, $paramValue);
614
            }
615
        }
616
617
        /**
618
         * Validation of rule "exact_length[param]"
619
         * 
620
         * @param  string $field the name of the field or data key name used
621
         * @param  string $rule  the rule name for this validation ("exact_length")
622
         * @param  string|null  $paramValue  the rule parameter
623
         */
624
        protected function checkRuleExactLength($field, $rule, $paramValue) {
625
           $value = $this->getFieldValue($field);    
626
            if (strlen($value) != $paramValue) {
627
                $this->setFieldErrorWithRequiredCheck($field, $value, $rule, $paramValue);
628
            }
629
        }
630
631
        /**
632
         * Validation of rule "matches[param]"
633
         * 
634
         * @param  string $field the name of the field or data key name used
635
         * @param  string $rule  the rule name for this validation ("matches")
636
         * @param  string|null  $paramValue  the rule parameter
637
         */
638
        protected function checkRuleMatches($field, $rule, $paramValue) {
639
            $value = $this->getFieldValue($field);    
640
            if ($value != $this->getFieldValue($paramValue)) {
641
                $this->setFieldErrorWithRequiredCheck($field, $value, $rule, $paramValue, $field2 = $paramValue);
642
            }
643
        }
644
645
        /**
646
         * Validation of rule "not_equal[param]"
647
         * 
648
         * @param  string $field the name of the field or data key name used
649
         * @param  string $rule  the rule name for this validation ("not_equal")
650
         * @param  string|null  $paramValue  the rule parameter
651
         */
652
        protected function checkRuleNotEqual($field, $rule, $paramValue) {
653
            $value = $this->getFieldValue($field);    
654
            if ($value == $this->getFieldValue($paramValue)) {
655
                $this->setFieldErrorWithRequiredCheck($field, $value, $rule, $paramValue, $field2 = $paramValue);
656
            }
657
        }
658
659
        /**
660
         * Validation of rule "min[param]"
661
         * 
662
         * @param  string $field the name of the field or data key name used
663
         * @param  string $rule  the rule name for this validation ("min")
664
         * @param  string|null  $paramValue  the rule parameter
665
         */
666
        protected function checkRuleMin($field, $rule, $paramValue) {
667
            $value = $this->getFieldValue($field);    
668
            if ($value < $paramValue) {
669
                $this->setFieldErrorWithRequiredCheck($field, $value, $rule, $paramValue);
670
            }
671
        }
672
673
        /**
674
         * Validation of rule "max[param]"
675
         * 
676
         * @param  string $field the name of the field or data key name used
677
         * @param  string $rule  the rule name for this validation ("max")
678
         * @param  string|null  $paramValue  the rule parameter
679
         */
680
        protected function checkRuleMax($field, $rule, $paramValue) {
681
            $value = $this->getFieldValue($field);    
682
            if ($value > $paramValue) {
683
                $this->setFieldErrorWithRequiredCheck($field, $value, $rule, $paramValue);
684
            }
685
        }
686
687
        /**
688
         * Validation of rule "between[param]" param format is x,y
689
         * Example: between[1,100]
690
         * 
691
         * @param  string $field the name of the field or data key name used
692
         * @param  string $rule  the rule name for this validation ("between")
693
         * @param  string|null  $paramValue  the rule parameter
694
         */
695
        protected function checkRuleBetween($field, $rule, $paramValue) {
696
            $value = $this->getFieldValue($field);    
697
            $betweens = explode(',', $paramValue, 2);
698
            $betweens = array_map('trim', $betweens);
699
            if (($value < $betweens[0]) || ($value > $betweens[1])) {
700
                $this->setFieldErrorWithRequiredCheck($field, $value, $rule, $paramValue);
701
            }
702
        }
703
704
        /**
705
         * Validation of rule "in_list[param]" param format is a,b,c,d
706
         * Example: in_list[1,3,56,100]
707
         * 
708
         * @param  string $field the name of the field or data key name used
709
         * @param  string $rule  the rule name for this validation ("in_list")
710
         * @param  string|null  $paramValue  the rule parameter
711
         */
712
        protected function checkRuleInList($field, $rule, $paramValue) {
713
            $value = $this->getFieldValue($field);    
714
            $list = explode(',', $paramValue);
715
            $list = array_map('trim', $list);
716
            $paramValue = implode(',', $list);
717
            if (!in_array($value, $list)) {
718
                $this->setFieldErrorWithRequiredCheck($field, $value, $rule, $paramValue);
719
            }
720
        }
721
722
        /**
723
         * Validation of rule "numeric"
724
         * 
725
         * @param  string $field the name of the field or data key name used
726
         * @param  string $rule  the rule name for this validation ("numeric")
727
         * @param  string|null  $paramValue  the rule parameter
728
         */
729
        protected function checkRuleNumeric($field, $rule, $paramValue) {
730
            $value = $this->getFieldValue($field);    
731
            if (!is_numeric($value)) {
732
               $this->setFieldErrorWithRequiredCheck($field, $value, $rule, $paramValue);
733
            }
734
        }
735
736
        /**
737
         * Validation of rule "integer"
738
         * 
739
         * @param  string $field the name of the field or data key name used
740
         * @param  string $rule  the rule name for this validation ("integer")
741
         * @param  string|null  $paramValue  the rule parameter
742
         */
743
        protected function checkRuleInteger($field, $rule, $paramValue) {
744
            $value = $this->getFieldValue($field);    
745
            if (filter_var($value, FILTER_VALIDATE_INT) === false) {
746
               $this->setFieldErrorWithRequiredCheck($field, $value, $rule, $paramValue);
747
            }
748
        }
749
750
        /**
751
         * Validation of rule "integer_natural"
752
         * 
753
         * @param  string $field the name of the field or data key name used
754
         * @param  string $rule  the rule name for this validation ("integer_natural")
755
         * @param  string|null  $paramValue  the rule parameter
756
         */
757
        protected function checkRuleIntegerNatural($field, $rule, $paramValue) {
758
            $value = $this->getFieldValue($field);    
759
            if (filter_var($value, FILTER_VALIDATE_INT) === false || $value < 0) {
760
               $this->setFieldErrorWithRequiredCheck($field, $value, $rule, $paramValue);
761
            }
762
        }
763
764
        /**
765
         * Validation of rule "alpha"
766
         * 
767
         * @param  string $field the name of the field or data key name used
768
         * @param  string $rule  the rule name for this validation ("alpha")
769
         * @param  string|null  $paramValue  the rule parameter
770
         */
771
        protected function checkRuleAlpha($field, $rule, $paramValue) {
772
            $value = $this->getFieldValue($field);    
773
            if (!preg_match('/^[\pL\pM\s]+$/u', $value)) {
774
                $this->setFieldErrorWithRequiredCheck($field, $value, $rule, $paramValue);
775
            }
776
        }
777
778
        /**
779
         * Validation of rule "alpha_dash"
780
         * 
781
         * @param  string $field the name of the field or data key name used
782
         * @param  string $rule  the rule name for this validation ("alpha_dash")
783
         * @param  string|null  $paramValue  the rule parameter
784
         */
785
        protected function checkRuleAlphaDash($field, $rule, $paramValue) {
786
            $value = $this->getFieldValue($field);
787
            if (!preg_match('/^[\pL\pM_-]+$/u', $value)) {
788
                $this->setFieldErrorWithRequiredCheck($field, $value, $rule, $paramValue);
789
            }
790
        }
791
792
        /**
793
         * Validation of rule "alnum"
794
         * 
795
         * @param  string $field the name of the field or data key name used
796
         * @param  string $rule  the rule name for this validation ("alnum")
797
         * @param  string|null  $paramValue  the rule parameter
798
         */
799
        protected function checkRuleAlnum($field, $rule, $paramValue) {
800
            $value = $this->getFieldValue($field);
801
            if (!preg_match('/^[\pL\pM\pN\s]+$/u', $value)) {
802
                $this->setFieldErrorWithRequiredCheck($field, $value, $rule, $paramValue);
803
            }
804
        }
805
806
        /**
807
         * Validation of rule "alnum_dash"
808
         * 
809
         * @param  string $field the name of the field or data key name used
810
         * @param  string $rule  the rule name for this validation ("alnum_dash")
811
         * @param  string|null  $paramValue  the rule parameter
812
         */
813
        protected function checkRuleAlnumDash($field, $rule, $paramValue) {
814
            $value = $this->getFieldValue($field);
815
            if (!preg_match('/^[\pL\pM\pN_-]+$/u', $value)) {
816
                $this->setFieldErrorWithRequiredCheck($field, $value, $rule, $paramValue);
817
            }
818
        }
819
820
        /**
821
         * Validation of rule "email"
822
         * 
823
         * @param  string $field the name of the field or data key name used
824
         * @param  string $rule  the rule name for this validation ("email")
825
         * @param  string|null  $paramValue  the rule parameter
826
         */
827
        protected function checkRuleEmail($field, $rule, $paramValue) {
828
            $value = $this->getFieldValue($field);    
829
            if (filter_var($value, FILTER_VALIDATE_EMAIL) === false) {
830
                $this->setFieldErrorWithRequiredCheck($field, $value, $rule, $paramValue);
831
            }
832
        }
833
834
        /**
835
         * Validation of rule "date[param]" param can be a valid 
836
         * value supported by function date()
837
         * 
838
         * @param  string $field the name of the field or data key name used
839
         * @param  string $rule  the rule name for this validation ("date")
840
         * @param  string|null  $paramValue  the rule parameter
841
         */
842
        protected function checkRuleDate($field, $rule, $paramValue) {
843
            $value = $this->getFieldValue($field);
844
            $format = $paramValue;
845
            $dateValue = date_create_from_format($format, $value);    
846
            if ($dateValue === false || $dateValue->format($format) !== $value) {
847
               $this->setFieldErrorWithRequiredCheck($field, $value, $rule, $paramValue);
848
            }
849
        }
850
851
        /**
852
         * Validation of rule "date_before[param]" param can be a valid 
853
         * value supported by function strtotime()
854
         * 
855
         * @param  string $field the name of the field or data key name used
856
         * @param  string $rule  the rule name for this validation ("date_before")
857
         * @param  string|null  $paramValue  the rule parameter
858
         */
859
        protected function checkRuleDateBefore($field, $rule, $paramValue) {
860
            $value = $this->getFieldValue($field);    
861
            if (strtotime($value) >= strtotime($paramValue)) {
862
                $this->setFieldErrorWithRequiredCheck($field, $value, $rule, $paramValue);
863
            }
864
        }
865
866
        /**
867
         * Validation of rule "date_after[param]" param can be a valid 
868
         * value supported by function strtotime()
869
         * 
870
         * @param  string $field the name of the field or data key name used
871
         * @param  string $rule  the rule name for this validation ("date_after")
872
         * @param  string|null  $paramValue  the rule parameter
873
         */
874
        protected function checkRuleDateAfter($field, $rule, $paramValue) {
875
            $value = $this->getFieldValue($field);    
876
            if (strtotime($value) <= strtotime($paramValue)) {
877
                $this->setFieldErrorWithRequiredCheck($field, $value, $rule, $paramValue);
878
            }
879
        }
880
881
        /**
882
         * Validation of rule "url"
883
         * 
884
         * @param  string $field the name of the field or data key name used
885
         * @param  string $rule  the rule name for this validation ("url")
886
         * @param  string|null  $paramValue  the rule parameter
887
         */
888
        protected function checkRuleUrl($field, $rule, $paramValue) {
889
            $value = $this->getFieldValue($field);    
890
            if (filter_var($value, FILTER_VALIDATE_URL) === false) {
891
               $this->setFieldErrorWithRequiredCheck($field, $value, $rule, $paramValue);
892
            }
893
        }
894
895
        /**
896
         * Validation of rule "ip", the correct value can be ipv4, ipv6, for specific rule
897
         * use the rule below like ipv4 or ipv6.
898
         * 
899
         * @param  string $field the name of the field or data key name used
900
         * @param  string $rule  the rule name for this validation ("ip")
901
         * @param  string|null  $paramValue  the rule parameter
902
         */
903
        protected function checkRuleIp($field, $rule, $paramValue) {
904
            $value = $this->getFieldValue($field);    
905
            if (filter_var($value, FILTER_VALIDATE_IP) === false) {
906
               $this->setFieldErrorWithRequiredCheck($field, $value, $rule, $paramValue);
907
            }
908
        }
909
910
        /**
911
         * Validation of rule "ipv4"
912
         * 
913
         * @param  string $field the name of the field or data key name used
914
         * @param  string $rule  the rule name for this validation ("ipv4")
915
         * @param  string|null  $paramValue  the rule parameter
916
         */
917
        protected function checkRuleIpv4($field, $rule, $paramValue) {
918
            $value = $this->getFieldValue($field);    
919
            if (filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) === false) {
920
                $this->setFieldErrorWithRequiredCheck($field, $value, $rule, $paramValue);
921
            }
922
        }
923
924
        /**
925
         * Validation of rule "ipv6"
926
         * 
927
         * @param  string $field the name of the field or data key name used
928
         * @param  string $rule  the rule name for this validation ("ipv6")
929
         * @param  string|null  $paramValue  the rule parameter
930
         */
931
        protected function checkRuleIpv6($field, $rule, $paramValue) {
932
            $value = $this->getFieldValue($field);    
933
            if (filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) === false) {
934
                $this->setFieldErrorWithRequiredCheck($field, $value, $rule, $paramValue);
935
            }
936
        }
937
938
        /**
939
         * Validation of rule "is_unique[param]" param value format is
940
         * [tablename.fieldname]
941
         * 
942
         * @param  string $field the name of the field or data key name used
943
         * @param  string $rule  the rule name for this validation ("is_unique")
944
         * @param  string|null  $paramValue  the rule parameter
945
         */
946
        protected function checkRuleIsUnique($field, $rule, $paramValue) {
947
            $this->setDatabaseFromSuperInstanceIfNotSet();
948
            $value = $this->getFieldValue($field);    
949
            list($table, $column) = explode('.', $paramValue);
950
            $this->database->getQueryBuilder()->from($table)
951
                                              ->where($column, $value);
952
            $this->database->get();
953
            if ($this->database->numRows() > 0) {
954
                $this->setFieldErrorWithRequiredCheck($field, $value, $rule, $paramValue);
955
            }
956
        }
957
958
        /**
959
         * Validation of rule "is_unique_update[param]" param value format is
960
         * [tablename.fieldname,keyfield=value]
961
         * 
962
         * @param  string $field the name of the field or data key name used
963
         * @param  string $rule  the rule name for this validation ("is_unique_update")
964
         * @param  string|null  $paramValue  the rule parameter
965
         */
966
        protected function checkRuleIsUniqueUpdate($field, $rule, $paramValue) {
967
            $this->setDatabaseFromSuperInstanceIfNotSet();
968
            $value = $this->getFieldValue($field);  
969
            $data = explode(',', $paramValue, 2);
970
            list($table, $column) = explode('.', $data[0]);
971
            list($columnKey, $valueKey) = explode('=', $data[1]);
972
            $this->database->getQueryBuilder()->from($table)
973
                                              ->where($column, $value)
974
                                              ->where($columnKey, '!=', trim($valueKey));
975
            $this->database->get();
976
            if ($this->database->numRows() > 0) {
977
                $this->setFieldErrorWithRequiredCheck($field, $value, $rule, $paramValue);
978
            }
979
        }
980
981
        /**
982
         * Validation of rule "exists[param]" param value format is
983
         * [tablename.fieldname]
984
         * 
985
         * @param  string $field the name of the field or data key name used
986
         * @param  string $rule  the rule name for this validation ("exists")
987
         * @param  string|null  $paramValue  the rule parameter
988
         */
989
        protected function checkRuleExists($field, $rule, $paramValue) {
990
            $this->setDatabaseFromSuperInstanceIfNotSet();
991
            $value = $this->getFieldValue($field);    
992
            list($table, $column) = explode('.', $paramValue);
993
            $this->database->getQueryBuilder()->from($table)
994
                                              ->where($column, $value);
995
            $this->database->get();
996
            if ($this->database->numRows() <= 0) {
997
                $this->setFieldErrorWithRequiredCheck($field, $value, $rule, $paramValue);
998
            }
999
        }
1000
1001
        /**
1002
         * Validation of rule "regex[param]" param can be any value supported by
1003
         * function preg_match()
1004
         * 
1005
         * @param  string $field the name of the field or data key name used
1006
         * @param  string $rule  the rule name for this validation ("regex")
1007
         * @param  string|null  $paramValue  the rule parameter
1008
         */
1009
        protected function checkRuleRegex($field, $rule, $paramValue) {
1010
            $value = $this->getFieldValue($field);    
1011
            if (!preg_match($paramValue, $value)) {
1012
                $this->setFieldErrorWithRequiredCheck($field, $value, $rule, $paramValue);
1013
            }
1014
        }
1015
1016
        /**
1017
         * Validation of rule "callback[param]" param can be any value supported by
1018
         * function is_callable() and this callable must accept one argument for
1019
         * the field value and must return false or true for the validation status.
1020
         * Example:
1021
         *
1022
         * function check_username_exists($value) {
1023
         *   //some check
1024
         *   return {true|false}
1025
         * }
1026
         * 
1027
         * @param  string $field the name of the field or data key name used
1028
         * @param  string $rule  the rule name for this validation ("required")
1029
         * @param  string|null  $paramValue  the rule parameter
1030
         */
1031
        protected function checkRuleCallback($field, $rule, $paramValue) {
1032
            $value = $this->getFieldValue($field);    
1033
            if (is_callable($paramValue)) {
1034
                if (call_user_func_array($paramValue, array($value)) === false) {
1035
                    $this->setFieldErrorWithRequiredCheck($field, $value, $rule, $paramValue);
1036
                }
1037
            } else{
1038
                $this->forceError = true;
1039
                show_error('The callback validation function/method "' . $paramValue . '" does not exist');
1040
            }
1041
        }
1042
1043
    }
1044