Passed
Push — master ( 06d537...c6e4cd )
by Darío
01:59
created

FormValidator::getErrors()   A

Complexity

Conditions 4
Paths 2

Size

Total Lines 19
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

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

307
                    $this->/** @scrutinizer ignore-call */ 
308
                           error($label ."-~-". (count($this->getErrors()) + 1), $message);
Loading history...
308
                }
309
            }
310
        }
311
        else
312
        {
313
            foreach ($form_value as $val)
314
            {
315
                $this->_validate($validator, $val, $label, $required);
316
            }
317
        }
318
    }
319
320
    /**
321
     * {@inheritDoc}
322
     *
323
     * @return array
324
     */
325
    public function getErrors()
326
    {
327
        $errors = [];
328
329
        if (count($this->errors))
330
        {
331
            foreach ($this->errors as $key => $value)
332
            {
333
                $errorLbl = explode("-~-", $key);
334
                $label = array_shift($errorLbl);
335
336
                if (!array_key_exists($label, $errors))
337
                    $errors[$label] = [];
338
339
                $errors[$label][] = $value;
340
            }
341
        }
342
343
        return $errors;
344
    }
345
}