FormValidator::isValid()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2.0625

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 3
c 1
b 0
f 0
nc 2
nop 0
dl 0
loc 8
ccs 3
cts 4
cp 0.75
crap 2.0625
rs 10
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