1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
|
4
|
|
|
namespace Fiv\Form; |
5
|
|
|
|
6
|
|
|
use Fiv\Form\Element; |
7
|
|
|
use Fiv\Form\Element\Submit; |
8
|
|
|
|
9
|
|
|
/** |
10
|
|
|
* @method Form setAction($action); |
11
|
|
|
* @method string|null getAction(); |
12
|
|
|
* |
13
|
|
|
* @author Ivan Shcherbak <[email protected]> |
14
|
|
|
*/ |
15
|
|
|
class Form extends Element\Html { |
16
|
|
|
|
17
|
|
|
/** |
18
|
|
|
* @var null|string |
19
|
|
|
*/ |
20
|
|
|
protected $uid = null; |
21
|
|
|
|
22
|
|
|
/** |
23
|
|
|
* @var boolean|null |
24
|
|
|
*/ |
25
|
|
|
protected $validationResult = null; |
26
|
|
|
|
27
|
|
|
/** |
28
|
|
|
* @var array|null |
29
|
|
|
*/ |
30
|
|
|
protected $data = null; |
31
|
|
|
|
32
|
|
|
/** |
33
|
|
|
* @var Element\Base[] |
34
|
|
|
*/ |
35
|
|
|
protected $elements = []; |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* Default form attributes |
39
|
|
|
* |
40
|
|
|
* @var array |
41
|
|
|
*/ |
42
|
|
|
protected $attributes = [ |
43
|
|
|
'method' => 'post', |
44
|
|
|
]; |
45
|
|
|
|
46
|
|
|
|
47
|
|
|
/** |
48
|
|
|
* @param $name |
49
|
|
|
* @return $this |
50
|
|
|
*/ |
51
|
4 |
|
public function setName($name) { |
52
|
4 |
|
$this->uid = $name; |
53
|
4 |
|
$this->attributes['name'] = $name; |
54
|
4 |
|
return $this; |
55
|
|
|
} |
56
|
|
|
|
57
|
|
|
|
58
|
|
|
/** |
59
|
|
|
* @return array |
60
|
|
|
* @throws \Exception |
61
|
|
|
*/ |
62
|
9 |
|
public function getData() { |
63
|
9 |
|
if (!isset($this->data)) { |
64
|
1 |
|
throw new \Exception("Data does not exist!"); |
65
|
|
|
} |
66
|
|
|
|
67
|
8 |
|
return $this->data; |
68
|
|
|
} |
69
|
|
|
|
70
|
|
|
|
71
|
|
|
/** |
72
|
|
|
* @param array|\Iterator $data |
73
|
|
|
* @throws \Exception |
74
|
|
|
*/ |
75
|
9 |
|
public function setData($data) { |
76
|
9 |
|
if ($data instanceof \Iterator) { |
77
|
|
|
$data = iterator_to_array($data); |
78
|
|
|
} |
79
|
|
|
|
80
|
9 |
|
if (!is_array($data)) { |
81
|
1 |
|
throw new \Exception('Data should be an array'); |
82
|
|
|
} |
83
|
|
|
|
84
|
|
|
|
85
|
8 |
|
$this->cleanValidationFlag(); |
86
|
|
|
|
87
|
8 |
|
foreach ($this->elements as $element) { |
88
|
7 |
|
$name = $element->getName(); |
89
|
|
|
|
90
|
7 |
|
if ($element instanceof Checkbox) { |
91
|
|
|
$data[$name] = isset($data[$name]) ? 1 : 0; |
92
|
7 |
|
} elseif ($element instanceof CheckboxList) { |
93
|
|
|
$data[$name] = isset($data[$name]) ? $data[$name] : []; |
94
|
|
|
} |
95
|
|
|
|
96
|
7 |
|
if (array_key_exists($name, $data)) { |
97
|
6 |
|
$element->setValue($data[$name]); |
98
|
7 |
|
$data[$name] = $element->getValue(); |
99
|
|
|
} |
100
|
|
|
|
101
|
|
|
} |
102
|
|
|
|
103
|
8 |
|
$this->data = $data; |
104
|
8 |
|
} |
105
|
|
|
|
106
|
|
|
|
107
|
|
|
/** |
108
|
|
|
* @return string |
109
|
|
|
*/ |
110
|
2 |
|
public function getMethod() { |
111
|
2 |
|
if (!empty($this->attributes['method'])) { |
112
|
2 |
|
return strtolower($this->attributes['method']); |
113
|
|
|
} |
114
|
|
|
|
115
|
|
|
return false; |
116
|
|
|
} |
117
|
|
|
|
118
|
|
|
|
119
|
|
|
/** |
120
|
|
|
* @param string $method |
121
|
|
|
* @return $this |
122
|
|
|
*/ |
123
|
2 |
|
public function setMethod($method) { |
124
|
2 |
|
$this->attributes['method'] = $method; |
125
|
|
|
|
126
|
2 |
|
return $this; |
127
|
|
|
} |
128
|
|
|
|
129
|
|
|
|
130
|
|
|
/** |
131
|
|
|
* |
132
|
|
|
*/ |
133
|
13 |
|
protected function cleanValidationFlag() { |
134
|
13 |
|
$this->validationResult = null; |
135
|
13 |
|
} |
136
|
|
|
|
137
|
|
|
|
138
|
|
|
/** |
139
|
|
|
* Check if form is submitted and all elements are valid |
140
|
|
|
* |
141
|
|
|
* @return bool|null |
142
|
|
|
*/ |
143
|
7 |
|
public function isValid() { |
144
|
7 |
|
if ($this->validationResult !== null) { |
145
|
|
|
return $this->validationResult; |
146
|
|
|
} |
147
|
|
|
|
148
|
7 |
|
if (!$this->isSubmitted()) { |
149
|
1 |
|
return false; |
150
|
|
|
} |
151
|
|
|
|
152
|
6 |
|
$this->validationResult = true; |
153
|
6 |
|
foreach ($this->elements as $element) { |
154
|
6 |
|
if (!$element->validate()) { |
155
|
6 |
|
$this->validationResult = false; |
156
|
|
|
} |
157
|
|
|
} |
158
|
|
|
|
159
|
6 |
|
return $this->validationResult; |
160
|
|
|
} |
161
|
|
|
|
162
|
|
|
|
163
|
|
|
/** |
164
|
|
|
* Check if form is submitted |
165
|
|
|
* |
166
|
|
|
* @return bool |
167
|
|
|
*/ |
168
|
9 |
|
public function isSubmitted() { |
169
|
9 |
|
$data = $this->getData(); |
170
|
|
|
|
171
|
8 |
|
return isset($data[$this->getUid()]); |
172
|
|
|
} |
173
|
|
|
|
174
|
|
|
|
175
|
|
|
/** |
176
|
|
|
* Return unique id of form |
177
|
|
|
* |
178
|
|
|
* @return string |
179
|
|
|
*/ |
180
|
10 |
|
public function getUid() { |
181
|
10 |
|
if (empty($this->uid)) { |
182
|
10 |
|
$this->uid = md5(get_called_class()); |
183
|
|
|
} |
184
|
|
|
|
185
|
10 |
|
return $this->uid; |
186
|
|
|
} |
187
|
|
|
|
188
|
|
|
|
189
|
|
|
/** |
190
|
|
|
* @return \Fiv\Form\Element\Base[] |
191
|
|
|
*/ |
192
|
1 |
|
public function getElements() { |
193
|
1 |
|
return $this->elements; |
194
|
|
|
} |
195
|
|
|
|
196
|
|
|
|
197
|
|
|
/** |
198
|
|
|
* @param string $name |
199
|
|
|
* @param string|null $text |
200
|
|
|
* @return \Fiv\Form\Element\Input |
201
|
|
|
*/ |
202
|
6 |
|
public function input($name, $text = null) { |
203
|
6 |
|
$input = new Element\Input(); |
204
|
6 |
|
$input->setName($name); |
205
|
6 |
|
$input->setText($text); |
206
|
6 |
|
$this->setElement($input); |
207
|
6 |
|
return $input; |
208
|
|
|
} |
209
|
|
|
|
210
|
|
|
|
211
|
|
|
/** |
212
|
|
|
* @param string $name |
213
|
|
|
* @param string|null $text |
214
|
|
|
* @return \Fiv\Form\Element\Input |
215
|
|
|
*/ |
216
|
|
|
public function password($name, $text = null) { |
217
|
|
|
$input = new Element\Password(); |
218
|
|
|
$input->setName($name); |
219
|
|
|
$input->setText($text); |
220
|
|
|
$this->setElement($input); |
221
|
|
|
return $input; |
222
|
|
|
} |
223
|
|
|
|
224
|
|
|
|
225
|
|
|
/** |
226
|
|
|
* @param $name |
227
|
|
|
* @param null $text |
228
|
|
|
* @return Select |
229
|
|
|
*/ |
230
|
|
|
public function select($name, $text = null) { |
231
|
|
|
$select = new Select(); |
232
|
|
|
$select->setName($name); |
233
|
|
|
$select->setText($text); |
234
|
|
|
$this->setElement($select); |
235
|
|
|
return $select; |
236
|
|
|
} |
237
|
|
|
|
238
|
|
|
|
239
|
|
|
/** |
240
|
|
|
* @param $name |
241
|
|
|
* @param string $text |
242
|
|
|
* @return RadioList |
243
|
|
|
*/ |
244
|
|
|
public function radioList($name, $text = null) { |
245
|
|
|
$radio = new RadioList(); |
246
|
|
|
$radio->setName($name); |
247
|
|
|
$radio->setText($text); |
248
|
|
|
$this->setElement($radio); |
249
|
|
|
return $radio; |
250
|
|
|
} |
251
|
|
|
|
252
|
|
|
|
253
|
|
|
/** |
254
|
|
|
* @param $name |
255
|
|
|
* @param null $text |
256
|
|
|
* @return TextArea |
257
|
|
|
*/ |
258
|
3 |
|
public function textarea($name, $text = null) { |
259
|
3 |
|
$input = new TextArea(); |
260
|
3 |
|
$input->setName($name); |
261
|
3 |
|
$input->setText($text); |
262
|
3 |
|
$this->setElement($input); |
263
|
3 |
|
return $input; |
264
|
|
|
} |
265
|
|
|
|
266
|
|
|
|
267
|
|
|
/** |
268
|
|
|
* ``` |
269
|
|
|
* $form->hidden('key', md5($this-user->id . HASH_A); |
270
|
|
|
* ``` |
271
|
|
|
* @param $name |
272
|
|
|
* @param null $value |
273
|
|
|
* @return \Fiv\Form\Element\Input |
274
|
|
|
*/ |
275
|
2 |
|
public function hidden($name, $value = null) { |
276
|
2 |
|
$hidden = new \Fiv\Form\Element\Input(); |
277
|
2 |
|
$hidden->setType('hidden'); |
278
|
2 |
|
$hidden->setName($name); |
279
|
2 |
|
$hidden->setValue($value); |
280
|
2 |
|
$this->setElement($hidden); |
281
|
2 |
|
return $hidden; |
282
|
|
|
} |
283
|
|
|
|
284
|
|
|
|
285
|
|
|
/** |
286
|
|
|
* ``` |
287
|
|
|
* $form->submit('register', 'зареєструватись'); |
288
|
|
|
* ``` |
289
|
|
|
* @param $name |
290
|
|
|
* @param null $value |
291
|
|
|
* @return Submit |
292
|
|
|
*/ |
293
|
1 |
|
public function submit($name, $value = null) { |
294
|
1 |
|
$input = new Submit(); |
295
|
1 |
|
$input->setName($name); |
296
|
1 |
|
$input->setValue($value); |
297
|
1 |
|
$this->setElement($input); |
298
|
1 |
|
return $input; |
299
|
|
|
} |
300
|
|
|
|
301
|
|
|
|
302
|
|
|
/** |
303
|
|
|
* ``` |
304
|
|
|
* $form->checkbox('subscribe', 'Підписка на новини'); |
305
|
|
|
* ``` |
306
|
|
|
* @param string $name |
307
|
|
|
* @param string|null $label |
308
|
|
|
* @return Checkbox |
309
|
|
|
*/ |
310
|
|
|
public function checkbox($name, $label = null) { |
311
|
|
|
$checkbox = new Checkbox(); |
312
|
|
|
$checkbox->setName($name); |
313
|
|
|
$checkbox->setLabel($label); |
314
|
|
|
$this->setElement($checkbox); |
315
|
|
|
return $checkbox; |
316
|
|
|
} |
317
|
|
|
|
318
|
|
|
|
319
|
|
|
/** |
320
|
|
|
* @param string $name |
321
|
|
|
* @param null $text |
322
|
|
|
* @return CheckboxList |
323
|
|
|
*/ |
324
|
|
|
public function checkboxList($name, $text = null) { |
325
|
|
|
$checkbox = new CheckboxList(); |
326
|
|
|
$checkbox->setName($name); |
327
|
|
|
$checkbox->setText($text); |
328
|
|
|
$this->setElement($checkbox); |
329
|
|
|
return $checkbox; |
330
|
|
|
} |
331
|
|
|
|
332
|
|
|
|
333
|
|
|
/** |
334
|
|
|
* Connect element to block and to form |
335
|
|
|
* |
336
|
|
|
* @param Element\Base $element |
337
|
|
|
* @return $this |
338
|
|
|
*/ |
339
|
12 |
|
protected function setElement(\Fiv\Form\Element\Base $element) { |
340
|
12 |
|
$this->cleanValidationFlag(); |
341
|
12 |
|
$this->elements[$element->getName()] = $element; |
342
|
12 |
|
return $this; |
343
|
|
|
} |
344
|
|
|
|
345
|
|
|
|
346
|
|
|
/** |
347
|
|
|
* Render full form |
348
|
|
|
* |
349
|
|
|
* @return string |
350
|
|
|
*/ |
351
|
1 |
|
public function render() { |
352
|
1 |
|
return $this->renderStart() . $this->renderElements() . $this->renderEnd(); |
353
|
|
|
} |
354
|
|
|
|
355
|
|
|
|
356
|
|
|
/** |
357
|
|
|
* You can easy rewrite this method for custom design of your forms |
358
|
|
|
* |
359
|
|
|
* @return string |
360
|
|
|
*/ |
361
|
1 |
|
protected function renderElements() { |
362
|
1 |
|
$formHtml = '<dl>'; |
363
|
|
|
|
364
|
1 |
|
foreach ($this->elements as $element) { |
365
|
|
|
$formHtml .= |
366
|
|
|
'<dt>' . $element->getText() . '</dt>' . |
367
|
|
|
'<dd>' . $element->render() . '</dd>'; |
368
|
|
|
} |
369
|
|
|
|
370
|
1 |
|
$formHtml .= '</dl>'; |
371
|
1 |
|
return $formHtml; |
372
|
|
|
} |
373
|
|
|
|
374
|
|
|
|
375
|
|
|
/** |
376
|
|
|
* @return string |
377
|
|
|
*/ |
378
|
1 |
|
public function renderStart() { |
379
|
1 |
|
$hidden = new Element\Input(); |
380
|
1 |
|
$hidden->setType('hidden'); |
381
|
1 |
|
$hidden->addAttributes([ |
382
|
1 |
|
'name' => $this->getUid(), |
383
|
|
|
]); |
384
|
1 |
|
$hidden->setValue(1); |
385
|
|
|
|
386
|
|
|
|
387
|
|
|
# get default attribute |
388
|
1 |
|
$method = $this->getMethod(); |
389
|
1 |
|
$this->setAttribute('method', $method); |
|
|
|
|
390
|
|
|
|
391
|
1 |
|
return '<form ' . $this->getAttributesAsString() . '>' . $hidden->render(); |
392
|
|
|
} |
393
|
|
|
|
394
|
|
|
|
395
|
|
|
/** |
396
|
|
|
* @return string |
397
|
|
|
*/ |
398
|
1 |
|
public function renderEnd() { |
399
|
1 |
|
return '</form> '; |
400
|
|
|
} |
401
|
|
|
|
402
|
|
|
} |
This check looks for type mismatches where the missing type is
false
. This is usually indicative of an error condtion.Consider the follow example
This function either returns a new
DateTime
object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returnedfalse
before passing on the value to another function or method that may not be able to handle afalse
.