Completed
Push — master ( 98d3f4...4c2b6a )
by Derek Stephen
01:36 queued 11s
created

AbstractForm::getFieldValues()   B

Complexity

Conditions 6
Paths 7

Size

Total Lines 31

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 31
ccs 18
cts 18
cp 1
rs 8.8017
c 0
b 0
f 0
cc 6
nc 7
nop 3
crap 6
1
<?php
2
3
namespace Del\Form;
4
5
use Del\Form\Collection\FieldCollection;
6
use Del\Form\Field\CheckBox;
7
use Del\Form\Field\FieldInterface;
8
use Del\Form\Field\FileUpload;
9
use Del\Form\Renderer\FormRenderer;
10
use Del\Form\Renderer\FormRendererInterface;
11
use Del\Form\Traits\HasAttributesTrait;
12
13
abstract class AbstractForm implements FormInterface
14
{
15
    const ENC_TYPE_MULTIPART_FORM_DATA = 'multipart/form-data';
16
    const ENC_TYPE_URL_ENCODED = 'application/x-www-form-urlencoded';
17
    const ENC_TYPE_TEXT_PLAIN = 'text/plain';
18
19
    const METHOD_POST = 'post';
20
    const METHOD_GET = 'get';
21
22
    /** @var FieldCollection $fieldCollection */
23
    private $fieldCollection;
24
25
    /** @var FormRendererInterface  */
26
    private $formRenderer;
27
28
    /** @var array $errorMessages */
29
    private $errorMessages;
30
31
    /** @var bool $displayErrors */
32
    private $displayErrors;
33
34
    use HasAttributesTrait;
35
36
    /**
37
     * AbstractForm constructor.
38
     * @param $name
39
     */
40
    public function __construct(string $name)
41
    {
42
        $this->fieldCollection = new FieldCollection();
43
        $this->formRenderer = new FormRenderer();
44 52
        $this->attributes = [
45
            'name' => $name,
46 52
            'method' => self::METHOD_POST,
47 52
        ];
48 52
        $this->displayErrors = false;
49 52
        $this->init();
50 52
    }
51
52 52
    abstract public function init();
53 52
54 52
    /**
55
     * @return bool
56
     * @throws \Exception
57
     */
58
    public function isValid(): bool
59
    {
60
        $this->errorMessages = [];
61
        $fields = $this->fieldCollection;
62 10
        $this->validateFields($fields);
63
        $count = count($this->errorMessages);
64 10
        $valid = ($count == 0);
65 10
        if ($valid) {
66 10
            $this->moveUploadedFiles();
67 10
        }
68 10
        return $valid;
69 10
    }
70 7
71
    public function getErrorMessages(): array
72 9
    {
73
        return $this->errorMessages;
74
    }
75 1
76
    /**
77 1
     * @param FieldCollection $fields
78
     * @throws \Exception
79
     */
80
    private function validateFields(FieldCollection $fields): void
81
    {
82
        $fields->rewind();
83
        while ($fields->valid()) {
84 10
            $this->checkFieldForErrors($fields->current());
85
            $this->checkDynamicFormsForErrors($fields->current());
86 10
            $fields->next();
87 10
        }
88 10
        $fields->rewind();
89 10
    }
90 10
91
    /**
92 10
     * @param FieldInterface $field
93 10
     * @throws \Exception
94
     */
95
    private function checkFieldForErrors(FieldInterface $field): void
96
    {
97
        if (!$field->isValid()) {
98
            $this->errorMessages[$field->getName()] = $field->getMessages();
99 10
        }
100
    }
101 10
102 8
    /**
103
     * @param FieldInterface $field
104 10
     */
105
    public function checkDynamicFormsForErrors(FieldInterface $field): void
106
    {
107
        if ($field->hasDynamicForms()) {
108
            $forms = $field->getDynamicForms();
109 10
            $value = $field->getValue();
110
            if (isset($forms[$value])) {
111 10
                $form = $forms[$value];
112 1
                $fields = $form->getFields();
113 1
                $this->validateFields($fields);
114 1
            }
115 1
        }
116 1
    }
117 1
118
    /**
119
     * @param bool $transform
120 10
     * @return array
121
     */
122
    public function getValues(bool $transform = false): array
123
    {
124
        $values = [];
125 5
        $fields = $this->fieldCollection;
126
        $values = $this->getFieldValues($fields, $values, $transform);
127 5
        
128 5
        return $values;
129 5
    }
130 5
131
    /**
132
     * @param FieldCollection $fields
133
     * @param array $values
134
     * @param bool $transform
135
     * @return array
136
     */
137
    private function getFieldValues(FieldCollection $fields, array $values, bool $transform): array
138 5
    {
139
        $fields->rewind();
140 5
141 5
        while ($fields->valid()) {
142
            /** @var FieldInterface $field */
143 5
            $field = $fields->current();
144 5
            $value = $field->getValue();
145 5
146 5
            if ($transform && $field->hasTransformer()) {
147 1
                $value = $field->getTransformer()->output($value);
148 1
            }
149 1
150 1
            $values[$field->getName()] = $value;
151 1
152
            if ($field->hasDynamicForms()) {
153
                $forms = $field->getDynamicForms();
154 5
                if (isset($forms[$value])) {
155
                    $form = $forms[$value];
156 5
                    $dynamicFormFields = $form->getFields();
157 5
                    $values = $this->getFieldValues($dynamicFormFields, $values, $transform);
158
                }
159
            }
160
161
            $fields->next();
162
        }
163
164 8
        $fields->rewind();
165
166 8
        return $values;
167 8
    }
168 8
169 8
    /**
170
     * @param array $data
171
     */
172
    public function populate(array $data): void
173
    {
174
        $fields = $this->fieldCollection;
175
        $this->populateFields($fields, $data);
176 2
        $this->displayErrors = true;
177
    }
178
179 2
    /**
180 2
     * @param array $dynamicForms
181 2
     * @param array $data
182
     */
183 2
    private function populateDynamicForms(array $dynamicForms, array $data): void
184
    {
185
        /** @var FormInterface $form **/
186
        foreach ($dynamicForms as $form) {
187
            $fields = $form->getFields();
188
            $this->populateFields($fields, $data);
189 8
        }
190
    }
191 8
192 8
    /**
193 8
     * @param FieldCollection $fields
194 8
     * @param array $data
195 8
     */
196
    private function populateFields(FieldCollection $fields, array $data): void
197 8
    {
198 8
        $fields->rewind();
199
        while ($fields->valid()) {
200
            $field = $fields->current();
201
            $this->populateField($field, $data);
202
            $fields->next();
203
        }
204 8
        $fields->rewind();
205
    }
206 8
207 8
    /**
208 5
     * @param FieldInterface $field
209
     * @param array $data
210 8
     */
211 2
    private function populateField(FieldInterface $field, array $data): void
212 2
    {
213
        $name = $field->getName();
214 8
215
        if (isset($data[$name]) && $field->hasTransformer()) {
216
            $value = $field->getTransformer()->input($data[$name]);
217
            $field->setValue($value);
218
        } elseif (isset($data[$name])) {
219
            $field->setValue($data[$name]);
220 2
        } elseif ($field instanceof CheckBox) {
221
            $field->setValue(false);
0 ignored issues
show
Documentation introduced by
false is of type boolean, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
222 2
        }
223
224
        if ($field->hasDynamicForms()) {
225
            $forms = $field->getDynamicForms();
226
            $this->populateDynamicForms($forms, $data);
227
        }
228 34
    }
229
230 34
    /**
231
     * @param string $name
232
     * @return FieldInterface|null
233
     */
234
    public function getField(string $name): ?FieldInterface
235
    {
236
        return $this->fieldCollection->findByName($name);
237 43
    }
238
239 43
    /**
240 43
     * @return FieldCollection
241
     */
242
    public function getFields(): FieldCollection
243
    {
244
        return $this->fieldCollection;
245
    }
246 30
247
    /**
248 30
     * @param FieldInterface $field
249
     */
250
    public function addField(FieldInterface $field): void
251
    {
252
        $this->fieldCollection->append($field);
253
    }
254
255 2
    /**
256
     * @return string
257 2
     */
258
    public function render(): string
259 2
    {
260
        return $this->formRenderer->render($this, $this->isDisplayErrors());
261
    }
262
263
    /**
264
     * @param $url
265 2
     */
266
    public function setAction(string $url): void
267 2
    {
268
        $this->setAttribute('action', $url);
269
    }
270
271
    /**
272
     * @return string
273 31
     */
274
    public function getAction(): string
275 31
    {
276
        return $this->getAttribute('action');
277
    }
278
279
    /**
280
     * @return string
281
     */
282 2
    public function getId(): ?string
283
    {
284 2
        return $this->getAttribute('id');
285
    }
286 2
287
    /**
288
     * @param string $id
289
     */
290
    public function setId(string $id): void
291
    {
292
        $this->setAttribute('id', $id);
293 2
    }
294
295 2
    /**
296
     * @param $encType
297 2
     */
298
    public function setEncType(string $encType): void
299
    {
300
        $this->setAttribute('enctype', $encType);
301
    }
302
303 1
    /**
304
     * @return string
305 1
     */
306
    public function getEncType(): string
307
    {
308
        return $this->getAttribute('enctype');
309
    }
310
311
    /**
312 2
     * @param string $method
313
     * @return FormInterface
314 2
     */
315
    public function setMethod(string $method): void
316 2
    {
317
        $this->setAttribute('method', $method);
318
    }
319
320
    /**
321
     * @return string
322 31
     */
323
    public function getMethod(): string
324 31
    {
325
        return $this->getAttribute('method');
326
    }
327
328
    /**
329
     * @param $class
330
     */
331 2
    public function setClass(string $class): void
332
    {
333 2
        $this->setAttribute('class', $class);
334
    }
335 2
336
    /**
337
     * @return string
338
     */
339
    public function getClass(): string
340
    {
341 2
        return $this->getAttribute('class');
342
    }
343 2
344
    /**
345
     * @return boolean
346
     */
347
    public function isDisplayErrors(): bool
348
    {
349 31
        return $this->displayErrors;
350
    }
351 31
352
    /**
353
     * @param boolean $displayError
0 ignored issues
show
Documentation introduced by
There is no parameter named $displayError. Did you maybe mean $displayErrors?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
354
     */
355
    public function setDisplayErrors(bool $displayErrors): void
356
    {
357
        $this->displayErrors = $displayErrors;
358 3
    }
359
360 3
    /**
361
     * @param FormRendererInterface $renderer
362 3
     * @return AbstractForm
363
     */
364
    public function setFormRenderer(FormRendererInterface $renderer): AbstractForm
365
    {
366
        $this->formRenderer = $renderer;
367
368
        return $this;
369 5
    }
370
371 5
    public function moveUploadedFiles(): void
372
    {
373 5
        $this->fieldCollection->rewind();
374
        while ($this->fieldCollection->valid()) {
375
            $current = $this->fieldCollection->current();
376 7
            $this->moveFileIfUploadField($current);
377
            $this->fieldCollection->next();
378 7
        }
379 7
    }
380 7
381 7
    /**
382 6
     * @param FieldInterface $field
383
     * @return bool
384 6
     */
385
    public function moveFileIfUploadField(FieldInterface $field): bool
386
    {
387
        if ($field instanceof FileUpload) {
388
            $field->moveUploadToDestination();
389
            return true;
390 7
        }
391
        return false;
392
    }
393
}