1 | <?php |
||
2 | |||
3 | declare(strict_types=1); |
||
4 | |||
5 | namespace Del\Form; |
||
6 | |||
7 | use Del\Form\Collection\FieldCollection; |
||
8 | use Del\Form\Field\CheckBox; |
||
9 | use Del\Form\Field\FieldInterface; |
||
10 | use Del\Form\Field\FileUpload; |
||
11 | use Del\Form\Renderer\FormRenderer; |
||
12 | use Del\Form\Renderer\FormRendererInterface; |
||
13 | use Del\Form\Traits\HasAttributesTrait; |
||
14 | |||
15 | abstract class AbstractForm implements FormInterface |
||
16 | { |
||
17 | const ENC_TYPE_MULTIPART_FORM_DATA = 'multipart/form-data'; |
||
18 | const ENC_TYPE_URL_ENCODED = 'application/x-www-form-urlencoded'; |
||
19 | const ENC_TYPE_TEXT_PLAIN = 'text/plain'; |
||
20 | |||
21 | const METHOD_POST = 'post'; |
||
22 | const METHOD_GET = 'get'; |
||
23 | |||
24 | private FieldCollection $fieldCollection; |
||
25 | private FormRendererInterface $formRenderer; |
||
26 | private array $errorMessages; |
||
27 | private bool $displayErrors; |
||
28 | |||
29 | use HasAttributesTrait; |
||
30 | |||
31 | 67 | public function __construct(string $name) |
|
32 | { |
||
33 | 67 | $this->fieldCollection = new FieldCollection(); |
|
34 | 67 | $this->formRenderer = new FormRenderer(); |
|
35 | 67 | $this->attributes = [ |
|
36 | 67 | 'name' => $name, |
|
37 | 67 | 'method' => self::METHOD_POST, |
|
38 | 67 | ]; |
|
39 | 67 | $this->displayErrors = false; |
|
40 | 67 | $this->init(); |
|
41 | } |
||
42 | |||
43 | abstract public function init(); |
||
44 | |||
45 | 16 | public function isValid(): bool |
|
46 | { |
||
47 | 16 | $this->errorMessages = []; |
|
48 | 16 | $fields = $this->fieldCollection; |
|
49 | 16 | $this->validateFields($fields); |
|
50 | 16 | $count = count($this->errorMessages); |
|
51 | 16 | $valid = ($count == 0); |
|
52 | |||
53 | 16 | if ($valid) { |
|
54 | 10 | $this->moveUploadedFiles(); |
|
55 | } |
||
56 | |||
57 | 15 | return $valid; |
|
58 | } |
||
59 | |||
60 | 3 | public function getErrorMessages(): array |
|
61 | { |
||
62 | 3 | return $this->errorMessages; |
|
63 | } |
||
64 | |||
65 | 16 | private function validateFields(FieldCollection $fields): void |
|
66 | { |
||
67 | 16 | $fields->rewind(); |
|
68 | |||
69 | 16 | while ($fields->valid()) { |
|
70 | 16 | $this->checkFieldForErrors($fields->current()); |
|
71 | 16 | $this->checkDynamicFormsForErrors($fields->current()); |
|
72 | 16 | $fields->next(); |
|
73 | } |
||
74 | |||
75 | 16 | $fields->rewind(); |
|
76 | } |
||
77 | |||
78 | 16 | private function checkFieldForErrors(FieldInterface $field): void |
|
79 | { |
||
80 | 16 | if (!$field->isValid()) { |
|
81 | 12 | $this->errorMessages[$field->getName()] = $field->getMessages(); |
|
82 | } |
||
83 | } |
||
84 | |||
85 | 16 | public function checkDynamicFormsForErrors(FieldInterface $field): void |
|
86 | { |
||
87 | 16 | if ($field->hasDynamicForms()) { |
|
88 | 1 | $forms = $field->getDynamicForms(); |
|
89 | 1 | $value = $field->getValue(); |
|
90 | |||
91 | 1 | if (isset($forms[$value])) { |
|
92 | 1 | $form = $forms[$value]; |
|
93 | 1 | $fields = $form->getFields(); |
|
94 | 1 | $this->validateFields($fields); |
|
95 | } |
||
96 | } |
||
97 | } |
||
98 | |||
99 | 8 | public function getValues(bool $transform = false): array |
|
100 | { |
||
101 | 8 | $values = []; |
|
102 | 8 | $fields = $this->fieldCollection; |
|
103 | 8 | $values = $this->getFieldValues($fields, $values, $transform); |
|
104 | |||
105 | 8 | return $values; |
|
106 | } |
||
107 | |||
108 | 8 | private function getFieldValues(FieldCollection $fields, array $values, bool $transform): array |
|
109 | { |
||
110 | 8 | $fields->rewind(); |
|
111 | |||
112 | 8 | while ($fields->valid()) { |
|
113 | /** @var FieldInterface $field */ |
||
114 | 8 | $field = $fields->current(); |
|
115 | 8 | $value = $field->getValue(); |
|
116 | |||
117 | 8 | if ($transform && $field->hasTransformer()) { |
|
118 | 2 | $value = $field->getTransformer()->output($value); |
|
119 | } |
||
120 | |||
121 | 8 | $values[$field->getName()] = $value; |
|
122 | |||
123 | 8 | if ($field->hasDynamicForms()) { |
|
124 | 1 | $forms = $field->getDynamicForms(); |
|
125 | 1 | if (isset($forms[$value])) { |
|
126 | 1 | $form = $forms[$value]; |
|
127 | 1 | $dynamicFormFields = $form->getFields(); |
|
128 | 1 | $values = $this->getFieldValues($dynamicFormFields, $values, $transform); |
|
129 | } |
||
130 | } |
||
131 | |||
132 | 8 | $fields->next(); |
|
133 | } |
||
134 | |||
135 | 8 | $fields->rewind(); |
|
136 | |||
137 | 8 | return $values; |
|
138 | } |
||
139 | |||
140 | 16 | public function populate(array $values): void |
|
141 | { |
||
142 | 16 | $fields = $this->fieldCollection; |
|
143 | 16 | $this->populateFields($fields, $values); |
|
144 | 16 | $this->displayErrors = true; |
|
145 | } |
||
146 | |||
147 | 2 | private function populateDynamicForms(array $dynamicForms, array $data): void |
|
148 | { |
||
149 | /** @var FormInterface $form **/ |
||
150 | 2 | foreach ($dynamicForms as $form) { |
|
151 | 2 | $fields = $form->getFields(); |
|
152 | 2 | $this->populateFields($fields, $data); |
|
153 | } |
||
154 | } |
||
155 | |||
156 | 16 | private function populateFields(FieldCollection $fields, array $data): void |
|
157 | { |
||
158 | 16 | $fields->rewind(); |
|
159 | |||
160 | 16 | while ($fields->valid()) { |
|
161 | 16 | $field = $fields->current(); |
|
162 | 16 | $this->populateField($field, $data); |
|
163 | 16 | $fields->next(); |
|
164 | } |
||
165 | |||
166 | 16 | $fields->rewind(); |
|
167 | } |
||
168 | |||
169 | 16 | private function populateField(FieldInterface $field, array $data): void |
|
170 | { |
||
171 | 16 | $name = $field->getName(); |
|
172 | |||
173 | 16 | if (isset($data[$name]) && $field->hasTransformer()) { |
|
174 | 2 | $value = $field->getTransformer()->input($data[$name]); |
|
175 | 2 | $field->setValue($value); |
|
176 | 14 | } elseif (isset($data[$name])) { |
|
177 | 10 | $field->setValue($data[$name]); |
|
178 | 9 | } elseif ($field instanceof CheckBox) { |
|
179 | 1 | $field->setValue(false); |
|
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||
180 | } |
||
181 | |||
182 | 16 | if ($field->hasDynamicForms()) { |
|
183 | 2 | $forms = $field->getDynamicForms(); |
|
184 | 2 | $this->populateDynamicForms($forms, $data); |
|
185 | } |
||
186 | } |
||
187 | |||
188 | 3 | public function getField(string $name): ?FieldInterface |
|
189 | { |
||
190 | 3 | return $this->fieldCollection->findByName($name); |
|
191 | } |
||
192 | |||
193 | 42 | public function getFields(): FieldCollection |
|
194 | { |
||
195 | 42 | return $this->fieldCollection; |
|
196 | } |
||
197 | |||
198 | 58 | public function addField(FieldInterface $field): void |
|
199 | { |
||
200 | 58 | $this->fieldCollection->append($field); |
|
201 | } |
||
202 | |||
203 | 36 | public function render(): string |
|
204 | { |
||
205 | 36 | return $this->formRenderer->render($this, $this->isDisplayErrors()); |
|
206 | } |
||
207 | |||
208 | 2 | public function setAction(string $url): void |
|
209 | { |
||
210 | 2 | $this->setAttribute('action', $url); |
|
211 | } |
||
212 | |||
213 | 2 | public function getAction(): string |
|
214 | { |
||
215 | 2 | return $this->getAttribute('action'); |
|
216 | } |
||
217 | |||
218 | 37 | public function getId(): ?string |
|
219 | { |
||
220 | 37 | return $this->getAttribute('id'); |
|
221 | } |
||
222 | |||
223 | 2 | public function setId(string $id): void |
|
224 | { |
||
225 | 2 | $this->setAttribute('id', $id); |
|
226 | } |
||
227 | |||
228 | 3 | public function setEncType(string $encType): void |
|
229 | { |
||
230 | 3 | $this->setAttribute('enctype', $encType); |
|
231 | } |
||
232 | |||
233 | 1 | public function getEncType(): string |
|
234 | { |
||
235 | 1 | return $this->getAttribute('enctype'); |
|
236 | } |
||
237 | |||
238 | 2 | public function setMethod(string $method): void |
|
239 | { |
||
240 | 2 | $this->setAttribute('method', $method); |
|
241 | } |
||
242 | |||
243 | 37 | public function getMethod(): string |
|
244 | { |
||
245 | 37 | return $this->getAttribute('method'); |
|
246 | } |
||
247 | |||
248 | 2 | public function setClass(string $class): void |
|
249 | { |
||
250 | 2 | $this->setAttribute('class', $class); |
|
251 | } |
||
252 | |||
253 | 2 | public function getClass(): string |
|
254 | { |
||
255 | 2 | return $this->getAttribute('class'); |
|
256 | } |
||
257 | |||
258 | 37 | public function isDisplayErrors(): bool |
|
259 | { |
||
260 | 37 | return $this->displayErrors; |
|
261 | } |
||
262 | |||
263 | 3 | public function setDisplayErrors(bool $displayErrors): void |
|
264 | { |
||
265 | 3 | $this->displayErrors = $displayErrors; |
|
266 | } |
||
267 | |||
268 | 5 | public function setFormRenderer(FormRendererInterface $renderer): AbstractForm |
|
269 | { |
||
270 | 5 | $this->formRenderer = $renderer; |
|
271 | |||
272 | 5 | return $this; |
|
273 | } |
||
274 | |||
275 | 10 | public function moveUploadedFiles(): void |
|
276 | { |
||
277 | 10 | $this->fieldCollection->rewind(); |
|
278 | |||
279 | 10 | while ($this->fieldCollection->valid()) { |
|
280 | 10 | $current = $this->fieldCollection->current(); |
|
281 | 10 | $this->moveFileIfUploadField($current); |
|
282 | 9 | $this->fieldCollection->next(); |
|
283 | } |
||
284 | } |
||
285 | |||
286 | 10 | public function moveFileIfUploadField(FieldInterface $field): bool |
|
287 | { |
||
288 | 10 | if ($field instanceof FileUpload) { |
|
289 | 2 | $field->moveUploadToDestination(); |
|
290 | 1 | return true; |
|
291 | } |
||
292 | 8 | return false; |
|
293 | } |
||
294 | |||
295 | |||
296 | } |
||
297 |