Completed
Push — master ( 9c1626...6bcea8 )
by Shcherbak
22:09 queued 19:43
created

Form::renderElements()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 17
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 4.0218

Importance

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