Validator::getValidatorClass()   B
last analyzed

Complexity

Conditions 5
Paths 4

Size

Total Lines 12
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 12
c 0
b 0
f 0
rs 8.8571
cc 5
eloc 8
nc 4
nop 1
1
<?php /** MicroValidator */
2
3
namespace Micro\Validator;
4
5
use Micro\Base\Exception;
6
use Micro\Base\KernelInjector;
7
use Micro\Form\IFormModel;
8
9
/**
10
 * Validator is a runner validation process
11
 *
12
 * @author Oleg Lunegov <[email protected]>
13
 * @link https://github.com/linpax/microphp-framework
14
 * @copyright Copyright (c) 2013 Oleg Lunegov
15
 * @license https://github.com/linpax/microphp-framework/blob/master/LICENSE
16
 * @package Micro
17
 * @subpackage Validator
18
 * @version 1.0
19
 * @since 1.0
20
 */
21
class Validator
22
{
23
    /** @var array $validators supported validations */
24
    protected static $validators = [
25
        'required' => 'RequiredValidator',
26
        'captcha' => 'CaptchaValidator',
27
        'boolean' => 'BooleanValidator',
28
        'compare' => 'CompareValidator',
29
        'string' => 'StringValidator',
30
        'regexp' => 'RegexpValidator',
31
        'number' => 'NumberValidator',
32
        'unique' => 'UniqueValidator',
33
        'range' => 'RangeValidator',
34
        'email' => 'EmailValidator',
35
        'file' => 'FileValidator',
36
        'url' => 'UrlValidator'
37
    ];
38
    /** @var array $errors errors summary */
39
    public $errors = [];
40
    /** @var array $elements validation elements */
41
    public $elements = [];
42
    /** @var array $params validation parameters */
43
    public $params = [];
44
    /** @var array $rule current rule */
45
    protected $rule = [];
46
47
48
    /**
49
     * Constructor validator object
50
     *
51
     * @access public
52
     *
53
     * @param array $params configuration array
54
     *
55
     * @result void
56
     */
57
    public function __construct(array $params)
58
    {
59
        $this->rule = $params['rule'];
60
    }
61
62
    /**
63
     * Running validation process
64
     *
65
     * @access public
66
     *
67
     * @param IFormModel $model model
68
     * @param bool $client run on client side?
69
     *
70
     * @return bool|string
71
     * @throws Exception
72
     */
73
    public function run($model, $client = false)
74
    {
75
        $elements = explode(',', str_replace(' ', '', array_shift($this->rule)));
76
        $name = array_shift($this->rule);
77
78
        $className = $this->getValidatorClass($name);
79
        if (!$className) {
80
            if (function_exists($name)) {
81
                foreach ($elements AS $element) {
82
                    if (property_exists($model, $element)) {
83
                        $model->$element = call_user_func($name, $model->$element);
84
                    }
85
                }
86
87
                return true;
88
            } elseif (method_exists($model, $name)) {
89
                foreach ($elements AS $element) {
90
                    if (property_exists($model, $element) && !call_user_func([$model, $name], $element)) {
91
                        return false;
92
                    }
93
                }
94
95
                return true;
96
            } else {
97
                throw new Exception('Validator '.$name.' not defined.');
98
            }
99
        }
100
101
        /** @var IValidator $valid */
102
        $valid = new $className(['params' => $this->rule]);
103
        $valid->elements = $elements;
0 ignored issues
show
Bug introduced by
Accessing elements on the interface Micro\Validator\IValidator suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
104
105
        if ($client && method_exists($valid, 'client')) {
106
            $result = $this->clientValidate($valid, $model);
107
        } else {
108
            $result = $valid->validate($model);
109
        }
110
111
        if ($valid->errors) {
0 ignored issues
show
Bug introduced by
Accessing errors on the interface Micro\Validator\IValidator suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
112
            $this->errors[] = $valid->errors;
0 ignored issues
show
Bug introduced by
Accessing errors on the interface Micro\Validator\IValidator suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
113
        }
114
115
        return $result;
116
    }
117
118
    /**
119
     * @param $name
120
     * @return bool|string
121
     * @throws Exception
122
     */
123
    protected function getValidatorClass($name)
124
    {
125
        if (!empty(self::$validators[$name])) {
126
            return '\\Micro\\Validator\\'.self::$validators[$name];
127
        } elseif (class_exists($name) && is_subclass_of($name, '\Micro\Validator\IValidator')) {
128
            return $name;
129
        } elseif (file_exists((new KernelInjector)->build()->getAppDir().'/validator/'.$name.'.php')) {
130
            return '\\App\\Validator\\'.$name;
131
        }
132
133
        return false;
134
    }
135
136
    /**
137
     * Client validation making
138
     *
139
     * @access public
140
     *
141
     * @param IValidator $validator
142
     * @param IFormModel $model
143
     *
144
     * @return string
145
     */
146
    public function clientValidate(IValidator $validator, IFormModel $model)
147
    {
148
        $object = substr(get_class($model), strrpos(get_class($model), '\\') + 1);
149
150
        $result = null;
151
        foreach ($validator->elements AS $element) {
0 ignored issues
show
Bug introduced by
Accessing elements on the interface Micro\Validator\IValidator suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
152
            $id = $object.'_'.$element;
153
            /** @noinspection PhpUndefinedMethodInspection */
154
            $result .= 'jQuery("#'.$id.'").bind("change blur submit", function(e){ ';
155
            /** @noinspection DisconnectedForeachInstructionInspection */
156
            $result .= $validator->client($model);
157
            $result .= ' });';
158
        }
159
160
        return $result;
161
    }
162
163
    /**
164
     * Get errors after run validation
165
     *
166
     * @access public
167
     * @return array
168
     */
169
    public function getErrors()
170
    {
171
        return $this->errors;
172
    }
173
174
    /**
175
     * Check is empty property
176
     *
177
     * @access protected
178
     *
179
     * @param mixed $value check value is empty
180
     * @param bool $trim run trim?
181
     *
182
     * @return bool
183
     */
184
    protected function isEmpty($value, $trim = false)
185
    {
186
        return $value === null || $value === [] || $value === '' || $trim && is_scalar($value) && trim($value) === '';
187
    }
188
}
189