Completed
Push — master ( 14565d...9435d2 )
by Shcherbak
09:17
created

Form::checkbox()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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