FormValidator::validate()   F
last analyzed

Complexity

Conditions 32
Paths 270

Size

Total Lines 133
Code Lines 84

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 62
CRAP Score 46.8571

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 32
eloc 84
c 3
b 0
f 0
nc 270
nop 0
dl 0
loc 133
ccs 62
cts 82
cp 0.7561
crap 46.8571
rs 2.4583

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * DronePHP (http://www.dronephp.com)
4
 *
5
 * @link      http://github.com/Pleets/DronePHP
6
 * @copyright Copyright (c) 2016-2018 Pleets. (http://www.pleets.org)
7
 * @license   http://www.dronephp.com/license
8
 * @author    Darío Rivera <[email protected]>
9
 */
10
11
namespace Drone\Validator;
12
13
use Drone\Dom\Element\Form;
14
use Zend\Validator\Date;
15
use Zend\Validator\Digits;
16
use Zend\Validator\EmailAddress;
17
use Zend\Validator\GreaterThan;
18
use Zend\Validator\LessThan;
19
use Zend\Validator\NotEmpty;
20
use Zend\Validator\Step;
21
use Zend\Validator\StringLength;
22
use Zend\Validator\Uri;
23
24
/**
25
 * FormValidator class
26
 *
27
 * Form validation implements Zend validator to check html form parameters.
28
 * n-dimensional arrays (name='example[][]') are supported.
29
 */
30
class FormValidator
31
{
32
    use \Drone\Error\ErrorTrait;
33
34
    /**
35
     * The result of latest validation
36
     *
37
     * It's null before validate() execution
38
     *
39
     * @var boolean|null
40
     */
41
    private $valid;
42
43
    /**
44
     * Form instance
45
     *
46
     * @var Form
47
     */
48
    private $form;
49
50
    /**
51
     * Element options
52
     *
53
     * @var array
54
     */
55
    private $options;
0 ignored issues
show
introduced by
The private property $options is not used, and could be removed.
Loading history...
56
57
    /**
58
     * Translator object
59
     *
60
     * @var \Zend\Mvc\I18n\Translator
61
     */
62
    private $translator;
63
64
    /**
65
     * Returns the valid attribute after validation
66
     *
67
     * @return boolean
68
     */
69 5
    public function isValid()
70
    {
71 5
        if (is_null($this->valid)) {
72
            # This error is thrown because of 'setValid' method has not been executed.
73
            throw new \LogicException('No validation has been executed!');
74
        }
75
76 5
        return $this->valid;
77
    }
78
79
    /**
80
     * Sets valid atribute after each validation
81
     *
82
     * @param boolean $valid
83
     *
84
     * @return null
85
     */
86 5
    private function setValid($valid)
87
    {
88 5
        $this->valid = (is_null($this->valid) ? true : $this->valid) && $valid;
89 5
    }
90
91
    /**
92
     * Constructor
93
     *
94
     * @param Form   $form
95
     * @param string $locale
96
     */
97 5
    public function __construct(Form $form, $locale = null)
98
    {
99 5
        $this->form = $form;
100
101 5
        if (is_null($locale)) {
102
            $locale = 'en';
103
        }
104
105 5
        $i18nTranslator = \Zend\I18n\Translator\Translator::factory(
106
            [
107 5
                'locale'  => "$locale",
108
                'translation_files' => [
109
                    [
110 5
                        "type" => 'phparray',
111 5
                        "filename" => "vendor/zendframework/zend-i18n-resources/languages/$locale/Zend_Validate.php",
112
                    ],
113
                ],
114
            ]
115
        );
116
117 5
        $this->translator = new \Zend\Mvc\I18n\Translator($i18nTranslator);
118 5
    }
119
120
    /**
121
     * Checks all form rules
122
     *
123
     * @throws LogicException
124
     * @throws RuntimeException
125
     *
126
     * @return null
127
     */
128 5
    public function validate()
129
    {
130 5
        $this->valid = null;
131
132 5
        $this->setValid(true);
133 5
        $elements = $this->form->getChildren();
134
135 5
        foreach ($elements as $label => $element) {
136 5
            if (!$element->isFormControl()) {
137
                continue;
138
            }
139
140 5
            $attribs = $element->getAttributes();
141
142 5
            $all_attribs = [];
143
144 5
            foreach ($attribs as $attr) {
145 5
                $all_attribs[$attr->getName()] = $attr->getValue();
146
            }
147
148 5
            $required = array_key_exists('required', $all_attribs) ? $all_attribs["required"] : false;
149
150 5
            foreach ($attribs as $attr) {
151 5
                $name  = $attr->getName();
152 5
                $value = $attr->getValue();
153
154 5
                $attrib = $element->getAttribute("value");
155 5
                $form_value = (!is_null($attrib)) ? $attrib->getValue() : null;
156
157 5
                $validator = null;
158
159 5
                switch ($name) {
160 5
                    case 'required':
161 1
                        $validator = new NotEmpty();
162 1
                        break;
163
164 5
                    case 'minlength':
165 5
                        $validator = new StringLength(['min' => $value]);
166 5
                        break;
167
168 5
                    case 'maxlength':
169 5
                        $validator = new StringLength(['max' => $value]);
170 5
                        break;
171
172 5
                    case 'type':
173 5
                        switch ($value) {
174 5
                            case 'number':
175 1
                                $validator = new Digits();
176 1
                                break;
177
178 5
                            case 'email':
179 2
                                $validator = new EmailAddress();
180 2
                                break;
181
182 5
                            case 'date':
183
                                $validator = new Date();
184
                                break;
185
186 5
                            case 'url':
187
                                $validator = new Uri();
188
                                break;
189
                        }
190
191 5
                        break;
192
193 5
                    case 'min':
194 1
                        if (array_key_exists('type', $all_attribs) &&
195 1
                            in_array($all_attribs['type'], ['number', 'range'])
196
                        ) {
197 1
                            $validator = new GreaterThan(['min' => $value, 'inclusive' => true]);
198
                        } else {
199
                            throw new \LogicException("The input type must be 'range' or 'number'");
200
                        }
201
202 1
                        break;
203
204 5
                    case 'max':
205
                        if (array_key_exists('type', $all_attribs) &&
206
                            in_array($all_attribs['type'], ['number', 'range'])
207
                        ) {
208
                            $validator = new LessThan(['max' => $value, 'inclusive' => true]);
209
                        } else {
210
                            throw new \LogicException("The input type must be 'range' or 'number'");
211
                        }
212
213
                        break;
214
215 5
                    case 'step':
216
                        $baseValue = (array_key_exists('min', $all_attribs)) ? $all_attribs['min'] : 0;
217
218
                        if (array_key_exists('type', $all_attribs) && in_array($all_attribs['type'], ['range'])) {
219
                            $validator = new Step(['baseValue' => $baseValue, 'step' => $value]);
220
                        } else {
221
                            throw new \LogicException("The input type must be 'range'");
222
                        }
223
224
                        break;
225
226 5
                    case 'data-validators':
227 1
                        if (!is_array($value)) {
228
                            throw new \InvalidArgumentException(
229
                                "Invalid type given. Array expected in 'data-validators' attribute."
230
                            );
231
                        }
232
233 1
                        foreach ($value as $class => $params) {
234 1
                            $className = "\Zend\Validator\\" . $class;
235
236 1
                            if (!class_exists($className)) {
237 1
                                $className = "\Zend\I18n\Validator\\" . $class;
238
239 1
                                if (!class_exists($className)) {
240
                                    throw new \RuntimeException(
241
                                        "The class '$userInputClass' or '$className' does not exists"
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $userInputClass seems to be never defined.
Loading history...
242
                                    );
243
                                }
244
                            }
245
246 1
                            $validator = new $className($params);
247
248 1
                            $validator->setTranslator($this->translator);
249 1
                            $this->validation($validator, $form_value, $label, $required);
250
                        }
251
252 1
                        break;
253
                }
254
255 5
                if (in_array(
256 5
                    $name,
257 5
                    ['required', 'digits', 'minlength', 'maxlength', 'type', 'min', 'max', 'date', 'step']
258 5
                ) && !is_null($validator)) {
259 5
                    $validator->setTranslator($this->translator);
260 5
                    $this->validation($validator, $form_value, $label, $required);
261
                }
262
            }
263
        }
264 5
    }
265
266
    /**
267
     * Validate all field values iteratively
268
     *
269
     * Supports n-dimensional arrays (name='example[][]')
270
     *
271
     * @param \Zend\Validator $validator
272
     * @param mixed           $form_value
273
     * @param string          $label
274
     * @param boolean         $required
275
     *
276
     * @return null
277
     */
278 5
    private function validation($validator, $form_value, $label, $required)
279
    {
280 5
        if (gettype($form_value) != 'array') {
281 5
            $val = $form_value;
282
283
            # Check if the value is required. If it is, check the other rules.
284 5
            $v = new NotEmpty();
285 5
            $v->setTranslator($this->translator);
286 5
            $notEmpty = $v->isValid($val);
287
288 5
            if (!$required && !$notEmpty) {
289 1
                return null;
290
            }
291
292 5
            $valid = $validator->isValid($val);
293 5
            $this->setValid($valid);
294
295 5
            if (!$valid) {
296 4
                foreach ($validator->getMessages() as $message) {
297 5
                    $this->error($label ."-~-". (count($this->getErrors()) + 1), $message);
0 ignored issues
show
Bug introduced by
The method error() does not exist on Drone\Validator\FormValidator. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

297
                    $this->/** @scrutinizer ignore-call */ 
298
                           error($label ."-~-". (count($this->getErrors()) + 1), $message);
Loading history...
298
                }
299
            }
300
        } else {
301 1
            foreach ($form_value as $val) {
302 1
                $this->validation($validator, $val, $label, $required);
303
            }
304
        }
305 5
    }
306
307
    /**
308
     * {@inheritdoc}
309
     *
310
     * @return array
311
     */
312 5
    public function getErrors()
313
    {
314 5
        $errors = [];
315
316 5
        if (count($this->errors)) {
317 4
            foreach ($this->errors as $key => $value) {
318 4
                $errorLbl = explode("-~-", $key);
319 4
                $label = array_shift($errorLbl);
320
321 4
                if (!array_key_exists($label, $errors)) {
322 4
                    $errors[$label] = [];
323
                }
324
325 4
                $errors[$label][] = $value;
326
            }
327
        }
328
329 5
        return $errors;
330
    }
331
}
332