Test Failed
Push — 1.0.0-dev ( 5d6670...5195bb )
by nguereza
03:46
created

FormValidation::setSmpleFieldError()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 2
c 0
b 0
f 0
nc 2
nop 6
dl 0
loc 3
rs 10
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->forceError   = false;
148
            $this->data         = array();
149
            return $this;
150
        }
151
        
152
        /**
153
         * Set the validation data
154
         * @param array $data the data to be validated
155
         *
156
         * @return object the current instance.
157
         */
158
        public function setData(array $data) {
159
            $this->logger->debug('Setting the form validation data, the values are: ' . stringfy_vars($data));
160
            $this->data = $data;
161
            return $this;
162
        }
163
164
         /**
165
         * Return the validation data
166
         * 
167
         * @return array the validation data
168
         */
169
        public function getData() {
170
            return $this->data;
171
        }
172
173
        /**
174
         * Add new validation rule.
175
         *
176
         * @param string $field name of the field or the data key to add a rule to
177
         * @param string $label the value of the field label
178
         * @param string|array $rule pipe seperated string or array of validation rules
179
         *
180
         * @return object the current instance.
181
         */
182
        public function setRule($field, $label, $rule) {
183
            $rules = array();
184
            //if the rule is array
185
            if (is_array($rule)) {
186
                $rules = $rule;
187
            } else {
188
                //the rule is not an array explode pipe values
189
                $rules = explode('|', $rule);
190
            }
191
            $this->rules[$field] = $rules;
192
            $this->labels[$field] = $label;
193
            return $this;
194
        }
195
196
        /**
197
         * Takes an array of rules and uses $this->setRule() to set them.
198
         * @param array $rules the array of rule
199
         *
200
         * @return object the current instance.
201
         */
202
        public function setRules(array $rules) {
203
            foreach ($rules as $rule) {
204
                call_user_func_array(array($this, 'setRule'), array($rule['name'], $rule['label'], $rule['rules']));
205
            }
206
            return $this;
207
        }
208
209
        /**
210
         * Return the list of the validations rules
211
         * @return array
212
         */
213
        public function getRules() {
214
            return $this->rules;
215
        }
216
217
         /**
218
         * Return the list of the validations rules for the given field
219
         * 
220
         * @return array
221
         */
222
        public function getFieldRules($field) {
223
            $rules = array();
224
            if (array_key_exists($field, $this->rules)) {
225
                $rules = $this->rules[$field];
226
            }
227
            return $rules;
228
        }
229
230
        /**
231
         * Return the value for the given field if exists otherwise null
232
         * will be returned
233
         * 
234
         * @return string|null
235
         */
236
        public function getFieldValue($field) {
237
             $value = null;
238
            if (array_key_exists($field, $this->data)) {
239
                $value = $this->data[$field];
240
            }
241
            return $value;
242
        }
243
244
        /**
245
         * Return the label for the given field if exists otherwise null
246
         * will be returned
247
         * 
248
         * @return string|null
249
         */
250
        public function getFieldLabel($field) {
251
            $label = null;
252
            if (array_key_exists($field, $this->labels)) {
253
                $label = $this->labels[$field];
254
            }
255
            return $label;
256
        }
257
            
258
        
259
       /**
260
        * Return the list of validation errors
261
        * 
262
        * @return array the errors list. 
263
        * Format:
264
        *  [field1] => 'error message 1', 
265
        *  [field2] => 'error message 2' 
266
        */
267
       public function getErrors() {
268
            return $this->errors;
269
        }
270
271
        /**
272
         * Process the data validation for each field, if it has any rules, run
273
         * each rule against the data value. 
274
         * and finally set $this->valid to true if there are no errors otherwise set to false
275
         * in case of error
276
         */
277
        public function validate() {
278
            //if the data is empty just return false
279
            if (empty($this->data)) {
280
                return false;
281
            }
282
            //Apply some filter/clean in the data to validate
283
            $this->filterValidationData();
284
285
            //Check the CSRF status
286
            $this->checkCsrf();
287
288
            //Now loop in each field rule and validate it
289
            foreach ($this->rules as $field => $rules) {
290
                $this->validateField($field, $rules);
291
            }
292
            $this->valid = empty($this->errors) && $this->forceError === false;
293
            return $this->valid;
294
        }
295
296
        /**
297
         * Return the validation status
298
         * @return boolean
299
         */
300
        public function isValid() {
301
            return $this->valid;
302
        }
303
304
        /**
305
         * Set a custom error message that can override the default error phrase provided.
306
         *  
307
         * If the parameter $field is null so means will set the error message for
308
         * all fields for the given rule, otherwise only error message for this field and rule will be set
309
         * the others fields use the default one for this rule.
310
         *
311
         * @param string $rule the name of the rule to set error message for.
312
         * @param string $message the error message it can contains the placeholder
313
         * {field}, {label}, {value}, {paramValue}, {field2}.
314
         * @param string|null $field if not null will set the error message only for this field and rule
315
         *
316
         * @return object the current instance.
317
         */
318
        public function setCustomErrorMessage($rule, $message, $field = null) {
319
            //1st if field is null all fields for this rule will be set to the same message
320
            //2nd if field is not null set only for this field
321
            if ($field !== null) {
322
                $this->customErrors[$field][$rule] = $message;
323
            } else {
324
                foreach (array_keys($this->rules) as $field) {
325
                    $this->customErrors[$field][$rule] = $message;
326
                }
327
            }
328
            return $this;
329
        }
330
331
        /**
332
         * Get the database instance
333
         * @return object the database instance
334
         */
335
        public function getDatabase() {
336
            return $this->database;
337
        }
338
339
        /**
340
         * Set the database instance
341
         * @param object $database the database instance
342
         *
343
         * @return object the current instance
344
         */
345
        public function setDatabase(Database $database) {
346
            $this->database = $database;
347
            return $this;
348
        }
349
350
         /**
351
         * Set the database instance using get_instance() if is null
352
         *
353
         * @return object the current instance
354
         */
355
        protected function setDatabaseFromSuperInstanceIfNotSet() {
356
            if (!is_object($this->database)) {
357
                $this->database = get_instance()->database;
358
            }
359
            return $this;
360
        }
361
362
        /**
363
         * Set the validation error for the given field
364
         * @param string $field      the error field
365
         * @param string $rule       the name of the rule raise this error
366
         * @param mixed $paramValue the value of rule parameter
367
         * Example: min_length[17], the $paramValue will be "17"
368
         * @param string|null $field2     the second field used in some validation rule like "matches", "not_equal"
369
         *
370
         * @return object the current instance
371
         */
372
        protected function setFieldError($field, $rule, $paramValue = null, $field2 = null) {
373
            //do we have error before?
374
            if (!array_key_exists($field, $this->errors)) {
375
                $this->errors[$field] = $this->getFieldErrorMessage($field, $rule, $paramValue, $field2);
376
            }
377
            return $this;
378
        }
379
380
        /**
381
         * Set the validation error for the given field by checking if the field is not required
382
         * or contains the value
383
         * @param string $field      the error field
384
         * @param mixed $value      the value of field
385
         * @param string $rule       the name of the rule raise this error
386
         * @param mixed $paramValue the value of rule parameter
387
         * Example: min_length[17], the $paramValue will be "17"
388
         * @param string|null $field2     the second field used in some validation rule like "matches", "not_equal"
389
         *
390
         */
391
         protected function setFieldErrorWithRequiredCheck($field, $value, $rule, $paramValue = null, $field2 = null) {
392
            //if the field is not required and his value is not set don't set error
393
            //but in case the field have value validate it
394
            if (!$this->fieldIsRequired($field) && strlen($value) <= 0) {
395
                return;
396
            }
397
            $this->setFieldError($field, $rule, $paramValue, $field2);
398
        }
399
400
        /**
401
         * Set the error for given field if condition(s) match(es).
402
         * 
403
         * @param boolean $conditions the condtion to evaluate, if true so means set the error for given field
404
         * @param string $field      the error field
405
         * @param mixed $value      the value of field
406
         * @param string $rule       the name of the rule raise this error
407
         * @param mixed $paramValue the value of rule parameter
408
         * Example: min_length[17], the $paramValue will be "17"
409
         * @param string|null $field2     the second field used in some validation rule like "matches", "not_equal"
410
         *
411
         */
412
        protected function setSimpleFieldError($conditions, $field, $value, $rule, $paramValue = null, $field2 = null) {
413
            if ($conditions) {
414
                $this->setFieldErrorWithRequiredCheck($field, $value, $rule, $paramValue, $field2);
415
            }
416
        }
417
418
        /**
419
         * Check whether the given field is required or not
420
         * @param  string $field the name of the field
421
         * @return boolean
422
         */
423
        protected function fieldIsRequired($field) {
424
            $rules = $this->getFieldRules($field);
425
            return in_array('required', $rules);
426
        }
427
        
428
        /**
429
         * Return the name of the method to use to validate the given rule
430
         * each method has a prefix of "checkRule"
431
         * @param  string $rule the name of the rule
432
         * @return string       the name of the validation method
433
         */
434
        protected function getRuleValidationMethod($rule) {
435
             $parts = explode('_', $rule);
436
             $parts = array_map('ucfirst', $parts);
437
             return 'checkRule' . implode('', $parts);
438
        }
439
        
440
        /**
441
         * This method is used to apply some filter rule on the validation data
442
         * like remove space, do some clean, etc.
443
         * @return object the current instance
444
         */
445
        protected function filterValidationData() {
446
            foreach ($this->data as $key => $value ) {
447
                if (is_string($value)) {
448
                   $this->data[$key] = trim($value);
449
                } else if(is_array($value)) {
450
                    $this->data[$key] = array_map('trim', $value);
451
                }
452
            }
453
            return $this;
454
        }
455
456
        /**
457
         * Validate the CSRF if the current request method is POST
458
         * and the check of CSRF is enabled in the configuration
459
         */
460
        protected function checkCsrf() {
461
            if (get_instance()->request->method() == 'POST') {
462
                $this->logger->debug('Check if CSRF is enabled in configuration');
463
                //first check for CSRF
464
                if (get_config('csrf_enable', false) && !get_instance()->security->validateCSRF()) {
465
                    $this->forceError = true;
466
                    show_error('Invalid data, Cross Site Request Forgery do his job, the data to validate is corrupted.');
467
                } else {
468
                    $this->logger->info('CSRF is not enabled in configuration or not set manully, no need to check it');
469
                }
470
            }
471
        }
472
              
473
        /**
474
         * Return the validation error message content for the given field
475
         * after replace all placeholders with their values
476
         * @param string $field      the error field
477
         * @param string $rule       the name of the rule raise this error
478
         * @param mixed $paramValue the value of rule parameter
479
         * Example: min_length[17], the $paramValue will be "17"
480
         * @param string|null $field2     the second field used in some validation rule like "matches", "not_equal"
481
         *
482
         * @return string the error message
483
         */
484
        protected function getFieldErrorMessage($field, $rule, $paramValue = null, $field2 = null) {
485
            $template = array(
486
                            '{field}'      => $field,
487
                            '{value}'      => $this->getFieldValue($field),
488
                            '{label}'      => $this->getFieldLabel($field),
489
                            '{paramValue}' => $paramValue
490
                            );
491
            if ($field2 !== null) {
492
                $template['field2}']  = $field2;
493
                $template['{value2}'] = $this->getFieldValue($field2);
494
                $template['{label2}'] = $this->getFieldLabel($field2);
495
             }     
496
            $message = $this->messages[$rule];
497
            //Check for custom message
498
            if (isset($this->customErrors[$field][$rule])) {
499
                $message = $this->customErrors[$field][$rule];
500
            }
501
            return strtr($message, $template);
502
        }
503
504
        /**
505
         * Perform validation for the given field
506
         * @param  string $field the field name
507
         * @param  array $rules the list of rule to validate
508
         */
509
        protected function validateField($field, array $rules) {
510
            foreach ($rules as $rule) {
511
                $match = array();
512
                $paramValue = null;
513
                //Is the rule with parameter ??
514
                preg_match('/\[(.*)\]/', $rule, $match);
515
                if (isset($match[1])) {
516
                    $paramValue = $match[1];
517
                }
518
                //Now get the real rule name for example 
519
                //min_length[34]
520
                //the name will be "min_length" and paramValue will be "14"
521
                $realRuleName = preg_replace('/\[(.*)\]/', '', $rule);
522
523
                //Get the name of the method to validate this rule
524
                $method = $this->getRuleValidationMethod($realRuleName);
525
                if (method_exists($this, $method)) {
526
                       call_user_func_array(array($this, $method), array($field, $realRuleName, $paramValue));
527
                } else {
528
                    $this->forceError = true;
529
                    show_error('Invalid validaton rule "' . $realRuleName . '"');
530
                }
531
            }
532
        }
533
        
534
        /**
535
         * Set the validation messages using translation messages
536
         */
537
        protected function setValidationMessages() {
538
            //Load form validation language message
539
            get_instance()->loader->lang('form_validation');
540
            
541
            $this->messages['required']         = get_instance()->lang->get('fv_required');
542
            $this->messages['min_length']       = get_instance()->lang->get('fv_min_length');
543
            $this->messages['max_length']       = get_instance()->lang->get('fv_max_length');
544
            $this->messages['exact_length']     = get_instance()->lang->get('fv_exact_length');
545
            $this->messages['matches']          = get_instance()->lang->get('fv_matches');
546
            $this->messages['not_equal']        = get_instance()->lang->get('fv_not_equal');
547
            $this->messages['min']              = get_instance()->lang->get('fv_min');
548
            $this->messages['max']              = get_instance()->lang->get('fv_max');
549
            $this->messages['between']          = get_instance()->lang->get('fv_between');
550
            $this->messages['in_list']          = get_instance()->lang->get('fv_in_list');
551
            $this->messages['numeric']          = get_instance()->lang->get('fv_numeric');
552
            $this->messages['integer']          = get_instance()->lang->get('fv_integer');
553
            $this->messages['integer_natural']  = get_instance()->lang->get('fv_integer_natural');
554
            $this->messages['alpha']            = get_instance()->lang->get('fv_alpha');
555
            $this->messages['alpha_dash']       = get_instance()->lang->get('fv_alpha_dash');
556
            $this->messages['alnum']            = get_instance()->lang->get('fv_alnum');
557
            $this->messages['alnum_dash']       = get_instance()->lang->get('fv_alnum_dash');
558
            $this->messages['email']            = get_instance()->lang->get('fv_email');
559
            $this->messages['date']             = get_instance()->lang->get('fv_date');
560
            $this->messages['date_before']      = get_instance()->lang->get('fv_date_before');
561
            $this->messages['date_after']       = get_instance()->lang->get('fv_date_after');
562
            $this->messages['url']              = get_instance()->lang->get('fv_url');
563
            $this->messages['ip']               = get_instance()->lang->get('fv_ip');
564
            $this->messages['ipv4']             = get_instance()->lang->get('fv_ipv4');
565
            $this->messages['ipv6']             = get_instance()->lang->get('fv_ipv6');
566
            $this->messages['is_unique']        = get_instance()->lang->get('fv_is_unique');
567
            $this->messages['is_unique_update'] = get_instance()->lang->get('fv_is_unique_update');
568
            $this->messages['exists']           = get_instance()->lang->get('fv_exists');
569
            $this->messages['regex']            = get_instance()->lang->get('fv_regex');
570
            $this->messages['callback']         = get_instance()->lang->get('fv_callback');
571
        }
572
        
573
574
        /* ---------------------------------------------------------------------------------- */
575
        ///////////////////////////////////////////////////////////////////////////////////////
576
        /**************************** RULES VALIDATION METHODS ******************************/
577
        /////////////////////////////////////////////////////////////////////////////////////
578
        
579
        /**
580
         * Validation of rule "default_value[param]"
581
         *
582
         * NOTE: This one it's not a validation rule it just check if the value for the
583
         * given field is null, empty and set it by the parameter value.
584
         * 
585
         * @param  string $field the name of the field or data key name used
586
         * @param  string $rule  the rule name for this validation ("default_value")
587
         * @param  string|null  $paramValue  the rule parameter
588
         */
589
        protected function checkRuleDefaultValue($field, $rule, $paramValue) {
590
            $value = $this->getFieldValue($field);
591
            if (strlen($value) <= 0) {
592
                $this->data[$field] = $paramValue;
593
            }
594
        }
595
            
596
        /**
597
         * Validation of rule "required"
598
         * 
599
         * @param  string $field the name of the field or data key name used
600
         * @param  string $rule  the rule name for this validation ("required")
601
         * @param  string|null  $paramValue  the rule parameter
602
         */
603
        protected function checkRuleRequired($field, $rule, $paramValue) {
604
            $value = $this->getFieldValue($field);
605
            if ($value == '') {
606
                $this->setFieldError($field, $rule, $paramValue);
607
            }
608
        }
609
        
610
        /**
611
         * Validation of rule "min_length[param]"
612
         * 
613
         * @param  string $field the name of the field or data key name used
614
         * @param  string $rule  the rule name for this validation ("min_length")
615
         * @param  string|null  $paramValue  the rule parameter
616
         */ 
617
        protected function checkRuleMinLength($field, $rule, $paramValue) {
618
           $value = $this->getFieldValue($field);  
619
           $this->setSimpleFieldError(
620
                                     strlen($value) < $paramValue, 
621
                                     $field, 
622
                                     $value, 
623
                                     $rule, 
624
                                     $paramValue
625
                                 );
626
        }
627
628
        /**
629
         * Validation of rule "max_length[param]"
630
         * 
631
         * @param  string $field the name of the field or data key name used
632
         * @param  string $rule  the rule name for this validation ("max_length")
633
         * @param  string|null  $paramValue  the rule parameter
634
         */
635
        protected function checkRuleMaxLength($field, $rule, $paramValue) {
636
           $value = $this->getFieldValue($field);
637
           $this->setSimpleFieldError(
638
                                     strlen($value) > $paramValue, 
639
                                     $field, 
640
                                     $value, 
641
                                     $rule, 
642
                                     $paramValue
643
                                 );
644
        }
645
646
        /**
647
         * Validation of rule "exact_length[param]"
648
         * 
649
         * @param  string $field the name of the field or data key name used
650
         * @param  string $rule  the rule name for this validation ("exact_length")
651
         * @param  string|null  $paramValue  the rule parameter
652
         */
653
        protected function checkRuleExactLength($field, $rule, $paramValue) {
654
           $value = $this->getFieldValue($field);
655
           $this->setSimpleFieldError(
656
                                     strlen($value) != $paramValue, 
657
                                     $field, 
658
                                     $value, 
659
                                     $rule, 
660
                                     $paramValue
661
                                 );
662
        }
663
664
        /**
665
         * Validation of rule "matches[param]"
666
         * 
667
         * @param  string $field the name of the field or data key name used
668
         * @param  string $rule  the rule name for this validation ("matches")
669
         * @param  string|null  $paramValue  the rule parameter
670
         */
671
        protected function checkRuleMatches($field, $rule, $paramValue) {
672
            $value = $this->getFieldValue($field);    
673
            $this->setSimpleFieldError(
674
                                     $value != $this->getFieldValue($paramValue), 
675
                                     $field, 
676
                                     $value, 
677
                                     $rule, 
678
                                     $paramValue,
679
                                     $paramValue //field2
680
                                 );
681
        }
682
683
        /**
684
         * Validation of rule "not_equal[param]"
685
         * 
686
         * @param  string $field the name of the field or data key name used
687
         * @param  string $rule  the rule name for this validation ("not_equal")
688
         * @param  string|null  $paramValue  the rule parameter
689
         */
690
        protected function checkRuleNotEqual($field, $rule, $paramValue) {
691
            $value = $this->getFieldValue($field);    
692
            $this->setSimpleFieldError(
693
                                     $value == $this->getFieldValue($paramValue), 
694
                                     $field, 
695
                                     $value, 
696
                                     $rule, 
697
                                     $paramValue,
698
                                     $paramValue //field2
699
                                 );
700
        }
701
702
        /**
703
         * Validation of rule "min[param]"
704
         * 
705
         * @param  string $field the name of the field or data key name used
706
         * @param  string $rule  the rule name for this validation ("min")
707
         * @param  string|null  $paramValue  the rule parameter
708
         */
709
        protected function checkRuleMin($field, $rule, $paramValue) {
710
            $value = $this->getFieldValue($field);  
711
            $this->setSimpleFieldError(
712
                                 $value < $paramValue, 
713
                                 $field, 
714
                                 $value, 
715
                                 $rule, 
716
                                 $paramValue
717
                             );
718
        }
719
720
        /**
721
         * Validation of rule "max[param]"
722
         * 
723
         * @param  string $field the name of the field or data key name used
724
         * @param  string $rule  the rule name for this validation ("max")
725
         * @param  string|null  $paramValue  the rule parameter
726
         */
727
        protected function checkRuleMax($field, $rule, $paramValue) {
728
            $value = $this->getFieldValue($field); 
729
            $this->setSimpleFieldError(
730
                                 $value > $paramValue, 
731
                                 $field, 
732
                                 $value, 
733
                                 $rule, 
734
                                 $paramValue
735
                             );
736
        }
737
738
        /**
739
         * Validation of rule "between[param]" param format is x,y
740
         * Example: between[1,100]
741
         * 
742
         * @param  string $field the name of the field or data key name used
743
         * @param  string $rule  the rule name for this validation ("between")
744
         * @param  string|null  $paramValue  the rule parameter
745
         */
746
        protected function checkRuleBetween($field, $rule, $paramValue) {
747
            $value = $this->getFieldValue($field);    
748
            $betweens = explode(',', $paramValue, 2);
749
            $betweens = array_map('trim', $betweens);
750
            $this->setSimpleFieldError(
751
                                 ($value < $betweens[0]) || ($value > $betweens[1]), 
752
                                 $field, 
753
                                 $value, 
754
                                 $rule, 
755
                                 $paramValue
756
                             );
757
        }
758
759
        /**
760
         * Validation of rule "in_list[param]" param format is a,b,c,d
761
         * Example: in_list[1,3,56,100]
762
         * 
763
         * @param  string $field the name of the field or data key name used
764
         * @param  string $rule  the rule name for this validation ("in_list")
765
         * @param  string|null  $paramValue  the rule parameter
766
         */
767
        protected function checkRuleInList($field, $rule, $paramValue) {
768
            $value = $this->getFieldValue($field);    
769
            $list = explode(',', $paramValue);
770
            $list = array_map('trim', $list);
771
            $paramValue = implode(',', $list);
772
            $this->setSimpleFieldError(
773
                                 !in_array($value, $list), 
774
                                 $field, 
775
                                 $value, 
776
                                 $rule, 
777
                                 $paramValue
778
                             ); 
779
        }
780
781
        /**
782
         * Validation of rule "numeric"
783
         * 
784
         * @param  string $field the name of the field or data key name used
785
         * @param  string $rule  the rule name for this validation ("numeric")
786
         * @param  string|null  $paramValue  the rule parameter
787
         */
788
        protected function checkRuleNumeric($field, $rule, $paramValue) {
789
            $value = $this->getFieldValue($field);    
790
            $this->setSimpleFieldError(
791
                                 !is_numeric($value), 
792
                                 $field, 
793
                                 $value, 
794
                                 $rule, 
795
                                 $paramValue
796
                             );
797
        }
798
799
        /**
800
         * Validation of rule "integer"
801
         * 
802
         * @param  string $field the name of the field or data key name used
803
         * @param  string $rule  the rule name for this validation ("integer")
804
         * @param  string|null  $paramValue  the rule parameter
805
         */
806
        protected function checkRuleInteger($field, $rule, $paramValue) {
807
            $value = $this->getFieldValue($field);  
808
             $this->setSimpleFieldError(
809
                                 filter_var($value, FILTER_VALIDATE_INT) === false, 
810
                                 $field, 
811
                                 $value, 
812
                                 $rule, 
813
                                 $paramValue
814
                             );
815
        }
816
817
        /**
818
         * Validation of rule "integer_natural"
819
         * 
820
         * @param  string $field the name of the field or data key name used
821
         * @param  string $rule  the rule name for this validation ("integer_natural")
822
         * @param  string|null  $paramValue  the rule parameter
823
         */
824
        protected function checkRuleIntegerNatural($field, $rule, $paramValue) {
825
            $value = $this->getFieldValue($field);
826
            $this->setSimpleFieldError(
827
                                 filter_var($value, FILTER_VALIDATE_INT) === false || $value < 0, 
828
                                 $field, 
829
                                 $value, 
830
                                 $rule, 
831
                                 $paramValue
832
                             );
833
        }
834
835
        /**
836
         * Validation of rule "alpha"
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 ("alpha")
840
         * @param  string|null  $paramValue  the rule parameter
841
         */
842
        protected function checkRuleAlpha($field, $rule, $paramValue) {
843
            $value = $this->getFieldValue($field);
844
            $this->setSimpleFieldError(
845
                                 !preg_match('/^[\pL\pM\s]+$/u', $value), 
846
                                 $field, 
847
                                 $value, 
848
                                 $rule, 
849
                                 $paramValue
850
                             );
851
        }
852
853
        /**
854
         * Validation of rule "alpha_dash"
855
         * 
856
         * @param  string $field the name of the field or data key name used
857
         * @param  string $rule  the rule name for this validation ("alpha_dash")
858
         * @param  string|null  $paramValue  the rule parameter
859
         */
860
        protected function checkRuleAlphaDash($field, $rule, $paramValue) {
861
            $value = $this->getFieldValue($field);
862
            $this->setSimpleFieldError(
863
                                 !preg_match('/^[\pL\pM_-]+$/u', $value), 
864
                                 $field, 
865
                                 $value, 
866
                                 $rule, 
867
                                 $paramValue
868
                             );
869
        }
870
871
        /**
872
         * Validation of rule "alnum"
873
         * 
874
         * @param  string $field the name of the field or data key name used
875
         * @param  string $rule  the rule name for this validation ("alnum")
876
         * @param  string|null  $paramValue  the rule parameter
877
         */
878
        protected function checkRuleAlnum($field, $rule, $paramValue) {
879
            $value = $this->getFieldValue($field);
880
            $this->setSimpleFieldError(
881
                                 !preg_match('/^[\pL\pM\pN\s]+$/u', $value), 
882
                                 $field, 
883
                                 $value, 
884
                                 $rule, 
885
                                 $paramValue
886
                             );
887
        }
888
889
        /**
890
         * Validation of rule "alnum_dash"
891
         * 
892
         * @param  string $field the name of the field or data key name used
893
         * @param  string $rule  the rule name for this validation ("alnum_dash")
894
         * @param  string|null  $paramValue  the rule parameter
895
         */
896
        protected function checkRuleAlnumDash($field, $rule, $paramValue) {
897
            $value = $this->getFieldValue($field);
898
            $this->setSimpleFieldError(
899
                                 !preg_match('/^[\pL\pM\pN_-]+$/u', $value), 
900
                                 $field, 
901
                                 $value, 
902
                                 $rule, 
903
                                 $paramValue
904
                             );
905
        }
906
907
        /**
908
         * Validation of rule "email"
909
         * 
910
         * @param  string $field the name of the field or data key name used
911
         * @param  string $rule  the rule name for this validation ("email")
912
         * @param  string|null  $paramValue  the rule parameter
913
         */
914
        protected function checkRuleEmail($field, $rule, $paramValue) {
915
            $value = $this->getFieldValue($field); 
916
            $this->setSimpleFieldError(
917
                                 filter_var($value, FILTER_VALIDATE_EMAIL) === false, 
918
                                 $field, 
919
                                 $value, 
920
                                 $rule, 
921
                                 $paramValue
922
                             );
923
        }
924
925
        /**
926
         * Validation of rule "date[param]" param can be a valid 
927
         * value supported by function date()
928
         * 
929
         * @param  string $field the name of the field or data key name used
930
         * @param  string $rule  the rule name for this validation ("date")
931
         * @param  string|null  $paramValue  the rule parameter
932
         */
933
        protected function checkRuleDate($field, $rule, $paramValue) {
934
            $value = $this->getFieldValue($field);
935
            $format = $paramValue;
936
            $dateValue = date_create_from_format($format, $value);  
937
            $this->setSimpleFieldError(
938
                                 $dateValue === false || $dateValue->format($format) !== $value, 
939
                                 $field, 
940
                                 $value, 
941
                                 $rule, 
942
                                 $paramValue
943
                             );
944
        }
945
946
        /**
947
         * Validation of rule "date_before[param]" param can be a valid 
948
         * value supported by function strtotime()
949
         * 
950
         * @param  string $field the name of the field or data key name used
951
         * @param  string $rule  the rule name for this validation ("date_before")
952
         * @param  string|null  $paramValue  the rule parameter
953
         */
954
        protected function checkRuleDateBefore($field, $rule, $paramValue) {
955
            $value = $this->getFieldValue($field);
956
             $this->setSimpleFieldError(
957
                                 strtotime($value) >= strtotime($paramValue), 
958
                                 $field, 
959
                                 $value, 
960
                                 $rule, 
961
                                 $paramValue
962
                             );
963
        }
964
965
        /**
966
         * Validation of rule "date_after[param]" param can be a valid 
967
         * value supported by function strtotime()
968
         * 
969
         * @param  string $field the name of the field or data key name used
970
         * @param  string $rule  the rule name for this validation ("date_after")
971
         * @param  string|null  $paramValue  the rule parameter
972
         */
973
        protected function checkRuleDateAfter($field, $rule, $paramValue) {
974
            $value = $this->getFieldValue($field);
975
            $this->setSimpleFieldError(
976
                                 strtotime($value) <= strtotime($paramValue), 
977
                                 $field, 
978
                                 $value, 
979
                                 $rule, 
980
                                 $paramValue
981
                             );
982
        }
983
984
        /**
985
         * Validation of rule "url"
986
         * 
987
         * @param  string $field the name of the field or data key name used
988
         * @param  string $rule  the rule name for this validation ("url")
989
         * @param  string|null  $paramValue  the rule parameter
990
         */
991
        protected function checkRuleUrl($field, $rule, $paramValue) {
992
            $value = $this->getFieldValue($field);
993
            $this->setSimpleFieldError(
994
                                 filter_var($value, FILTER_VALIDATE_URL) === false, 
995
                                 $field, 
996
                                 $value, 
997
                                 $rule, 
998
                                 $paramValue
999
                             );
1000
        }
1001
1002
        /**
1003
         * Validation of rule "ip", the correct value can be ipv4, ipv6, for specific rule
1004
         * use the rule below like ipv4 or ipv6.
1005
         * 
1006
         * @param  string $field the name of the field or data key name used
1007
         * @param  string $rule  the rule name for this validation ("ip")
1008
         * @param  string|null  $paramValue  the rule parameter
1009
         */
1010
        protected function checkRuleIp($field, $rule, $paramValue) {
1011
            $value = $this->getFieldValue($field);   
1012
            $this->setSimpleFieldError(
1013
                                 filter_var($value, FILTER_VALIDATE_IP) === false, 
1014
                                 $field, 
1015
                                 $value, 
1016
                                 $rule, 
1017
                                 $paramValue
1018
                             );
1019
        }
1020
1021
        /**
1022
         * Validation of rule "ipv4"
1023
         * 
1024
         * @param  string $field the name of the field or data key name used
1025
         * @param  string $rule  the rule name for this validation ("ipv4")
1026
         * @param  string|null  $paramValue  the rule parameter
1027
         */
1028
        protected function checkRuleIpv4($field, $rule, $paramValue) {
1029
            $value = $this->getFieldValue($field);  
1030
            $this->setSimpleFieldError(
1031
                                 filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) === false, 
1032
                                 $field, 
1033
                                 $value, 
1034
                                 $rule, 
1035
                                 $paramValue
1036
                             );
1037
        }
1038
1039
        /**
1040
         * Validation of rule "ipv6"
1041
         * 
1042
         * @param  string $field the name of the field or data key name used
1043
         * @param  string $rule  the rule name for this validation ("ipv6")
1044
         * @param  string|null  $paramValue  the rule parameter
1045
         */
1046
        protected function checkRuleIpv6($field, $rule, $paramValue) {
1047
            $value = $this->getFieldValue($field);   
1048
            $this->setSimpleFieldError(
1049
                                 filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) === false, 
1050
                                 $field, 
1051
                                 $value, 
1052
                                 $rule, 
1053
                                 $paramValue
1054
                             );
1055
        }
1056
1057
        /**
1058
         * Validation of rule "is_unique[param]" param value format is
1059
         * [tablename.fieldname]
1060
         * 
1061
         * @param  string $field the name of the field or data key name used
1062
         * @param  string $rule  the rule name for this validation ("is_unique")
1063
         * @param  string|null  $paramValue  the rule parameter
1064
         */
1065
        protected function checkRuleIsUnique($field, $rule, $paramValue) {
1066
            $this->setDatabaseFromSuperInstanceIfNotSet();
1067
            $value = $this->getFieldValue($field);    
1068
            list($table, $column) = explode('.', $paramValue);
1069
            $this->database->getQueryBuilder()->from($table)
1070
                                              ->where($column, $value);
1071
            $this->database->get();
1072
            if ($this->database->numRows() > 0) {
1073
                $this->setFieldErrorWithRequiredCheck($field, $value, $rule, $paramValue);
1074
            }
1075
        }
1076
1077
        /**
1078
         * Validation of rule "is_unique_update[param]" param value format is
1079
         * [tablename.fieldname,keyfield=value]
1080
         * 
1081
         * @param  string $field the name of the field or data key name used
1082
         * @param  string $rule  the rule name for this validation ("is_unique_update")
1083
         * @param  string|null  $paramValue  the rule parameter
1084
         */
1085
        protected function checkRuleIsUniqueUpdate($field, $rule, $paramValue) {
1086
            $this->setDatabaseFromSuperInstanceIfNotSet();
1087
            $value = $this->getFieldValue($field);  
1088
            $data = explode(',', $paramValue, 2);
1089
            list($table, $column) = explode('.', $data[0]);
1090
            list($columnKey, $valueKey) = explode('=', $data[1]);
1091
            $this->database->getQueryBuilder()->from($table)
1092
                                              ->where($column, $value)
1093
                                              ->where($columnKey, '!=', trim($valueKey));
1094
            $this->database->get();
1095
            if ($this->database->numRows() > 0) {
1096
                $this->setFieldErrorWithRequiredCheck($field, $value, $rule, $paramValue);
1097
            }
1098
        }
1099
1100
        /**
1101
         * Validation of rule "exists[param]" param value format is
1102
         * [tablename.fieldname]
1103
         * 
1104
         * @param  string $field the name of the field or data key name used
1105
         * @param  string $rule  the rule name for this validation ("exists")
1106
         * @param  string|null  $paramValue  the rule parameter
1107
         */
1108
        protected function checkRuleExists($field, $rule, $paramValue) {
1109
            $this->setDatabaseFromSuperInstanceIfNotSet();
1110
            $value = $this->getFieldValue($field);    
1111
            list($table, $column) = explode('.', $paramValue);
1112
            $this->database->getQueryBuilder()->from($table)
1113
                                              ->where($column, $value);
1114
            $this->database->get();
1115
            if ($this->database->numRows() <= 0) {
1116
                $this->setFieldErrorWithRequiredCheck($field, $value, $rule, $paramValue);
1117
            }
1118
        }
1119
1120
        /**
1121
         * Validation of rule "regex[param]" param can be any value supported by
1122
         * function preg_match()
1123
         * 
1124
         * @param  string $field the name of the field or data key name used
1125
         * @param  string $rule  the rule name for this validation ("regex")
1126
         * @param  string|null  $paramValue  the rule parameter
1127
         */
1128
        protected function checkRuleRegex($field, $rule, $paramValue) {
1129
            $value = $this->getFieldValue($field);
1130
             $this->setSimpleFieldError(
1131
                                 !preg_match($paramValue, $value), 
1132
                                 $field, 
1133
                                 $value, 
1134
                                 $rule, 
1135
                                 $paramValue
1136
                             );       
1137
        }
1138
1139
        /**
1140
         * Validation of rule "callback[param]" param can be any value supported by
1141
         * function is_callable() and this callable must accept one argument for
1142
         * the field value and must return false or true for the validation status.
1143
         * Example:
1144
         *
1145
         * function check_username_exists($value) {
1146
         *   //some check
1147
         *   return {true|false}
1148
         * }
1149
         * 
1150
         * @param  string $field the name of the field or data key name used
1151
         * @param  string $rule  the rule name for this validation ("required")
1152
         * @param  string|null  $paramValue  the rule parameter
1153
         */
1154
        protected function checkRuleCallback($field, $rule, $paramValue) {
1155
            $value = $this->getFieldValue($field);    
1156
            if (is_callable($paramValue)) {
1157
                $this->setSimpleFieldError(
1158
                                 call_user_func_array($paramValue, array($value)) === false, 
1159
                                 $field, 
1160
                                 $value, 
1161
                                 $rule, 
1162
                                 $paramValue
1163
                             ); 
1164
            } else{
1165
                $this->forceError = true;
1166
                show_error('The callback validation function/method "' . $paramValue . '" does not exist');
1167
            }
1168
        }
1169
1170
    }
1171