Completed
Push — master ( b09caf...256371 )
by Shcherbak
03:10
created

Form::radioList()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 3
Bugs 0 Features 0
Metric Value
c 3
b 0
f 0
dl 0
loc 7
ccs 0
cts 6
cp 0
rs 9.4285
cc 1
eloc 6
nc 1
nop 2
crap 2
1
<?php
2
3
4
  namespace Fiv\Form;
5
6
  use Fiv\Form\Element;
7
  use Fiv\Form\Element\Checkbox;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Fiv\Form\Checkbox.

Let’s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let’s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
8
  use Fiv\Form\Element\CheckboxList;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Fiv\Form\CheckboxList.

Let’s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let’s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
9
  use Fiv\Form\Element\Submit;
10
  use Fiv\Form\Element\TextArea;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Fiv\Form\TextArea.

Let’s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let’s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

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