Form::setMethod()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 5
ccs 0
cts 4
cp 0
rs 9.4285
cc 1
eloc 3
nc 1
nop 1
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
    public function setName($name) {
61
      $this->uid = $name;
62
      $this->attributes['name'] = $name;
63
      return $this;
64
    }
65
66
67
    /**
68
     * @param FormData $data
69
     * @return $this
70
     */
71
    public function handle(FormData $data) {
72
      $this->cleanValidationFlag();
73
74
      $this->isSubmitted = false;
75
      if ($data->isMethod($this->getMethod()) and $data->has($this->getUid())) {
76
        $this->isSubmitted = true;
77
        foreach ($this->getElements() as $element) {
78
          $element->handle($data);
79
        }
80
81
      }
82
83
      return $this;
84
    }
85
86
87
    /**
88
     * @return string
89
     */
90
    public function getMethod() {
91
      if (!empty($this->attributes['method'])) {
92
        return strtolower($this->attributes['method']);
93
      }
94
95
      return null;
96
    }
97
98
99
    /**
100
     * @param string $method
101
     * @return $this
102
     */
103
    public function setMethod($method) {
104
      $this->attributes['method'] = $method;
105
106
      return $this;
107
    }
108
109
110
    /**
111
     *
112
     */
113
    protected function cleanValidationFlag() {
114
      $this->errorList = [];
115
      $this->validationResult = null;
116
    }
117
118
119
    /**
120
     * Check if form is submitted and all elements are valid
121
     *
122
     * @return boolean
123
     */
124
    public function isValid() {
125
      if ($this->validationResult !== null) {
126
        return $this->validationResult;
127
      }
128
129
      if (!$this->isSubmitted()) {
130
        return false;
131
      }
132
133
      $this->validationResult = true;
134
135
      foreach ($this->getElements() as $element) {
136
        if ($element instanceof ValidatableElementInterface) {
137
          $validationResult = $element->validate();
138
          foreach ($validationResult->getErrors() as $errorMessage) {
139
            $this->addError($errorMessage);
140
          }
141
        }
142
143
        if (!$element instanceof ElementInterface) {
144
          continue;
145
        }
146
147
        if ($element->isValid()) {
148
          continue;
149
        }
150
151
        foreach ($element->getValidatorsErrors() as $errorMessage) {
152
          $this->addError($errorMessage);
153
        }
154
      }
155
156
      return $this->validationResult;
157
    }
158
159
160
    /**
161
     * @return array
162
     */
163
    public function getErrors() {
164
      return $this->errorList;
165
    }
166
167
168
    /**
169
     * @param string $error
170
     * @return $this
171
     */
172
    protected function addError($error) {
173
      if (!is_string($error)) {
174
        throw new \InvalidArgumentException('Error should be a string, ' . gettype($error) . ' given.');
175
      }
176
      $this->validationResult = false;
177
      $this->errorList[] = $error;
178
      return $this;
179
    }
180
181
182
    /**
183
     * Check if form is submitted
184
     *
185
     * @return bool
186
     */
187
    public function isSubmitted() {
188
      return $this->isSubmitted;
189
    }
190
191
192
    /**
193
     * Return unique id of form
194
     *
195
     * @return string
196
     */
197
    public function getUid() {
198
      if (empty($this->uid)) {
199
        $this->uid = md5(get_called_class());
200
      }
201
202
      return $this->uid;
203
    }
204
205
206
    /**
207
     * @return DataElementInterface[]
208
     */
209
    public function getElements() {
210
      return $this->elements;
211
    }
212
213
214
    /**
215
     * @param string $name
216
     * @return DataElementInterface
217
     * @throws \InvalidArgumentException
218
     */
219
    public function getElement($name) {
220
      if (empty($this->elements[$name])) {
221
        throw new \InvalidArgumentException('Element with name "' . $name . '" not found');
222
      }
223
      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
    public function setElement(DataElementInterface $element) {
234
      $this->cleanValidationFlag();
235
      $this->elements[$element->getName()] = $element;
236
      return $this;
237
    }
238
239
240
    /**
241
     * @param DataElementInterface $element
242
     * @return $this
243
     * @throws \Exception
244
     */
245
    public function addElement(DataElementInterface $element) {
246
      if (isset($this->elements[$element->getName()])) {
247
        throw new \Exception('Element with name ' . $element->getName() . ' is already added. Use setElement to overwrite it or change name');
248
      }
249
250
      $this->cleanValidationFlag();
251
      $this->elements[$element->getName()] = $element;
252
      return $this;
253
    }
254
255
256
    /**
257
     * @param string $name
258
     * @param string|null $text
259
     * @return \Fiv\Form\Element\Input
260
     */
261
    public function input($name, $text = null) {
262
      $input = new Element\Input();
263
      $input->setName($name);
264
      $input->setText($text);
265
      $this->addElement($input);
266
      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
     * @deprecated
314
     * @see TextArea
315
     *
316
     * @param string $name
317
     * @param null $text
318
     * @return TextArea
319
     */
320
    public function textarea($name, $text = null) {
321
      trigger_error('Deprecated. Create new element and add it to the form manually', E_USER_DEPRECATED);
322
      $input = new TextArea($name);
323
      if (!empty($text)) {
324
        $input->setText((string) $text);
325
      }
326
      $this->addElement($input);
327
      return $input;
328
    }
329
    
330
331
    /**
332
     * ```
333
     * $form->submit('register', 'зареєструватись');
334
     * ```
335
     * @param string $name
336
     * @param null $value
337
     * @return Submit
338
     */
339
    public function submit($name, $value = null) {
340
      $input = new Submit();
341
      $input->setName($name);
342
      $input->setValue($value);
343
      $this->addElement($input);
344
      return $input;
345
    }
346
347
348
    /**
349
     * ```
350
     * $form->checkbox('subscribe', 'Підписка на новини');
351
     * ```
352
     * @param string $name
353
     * @param string|null $label
354
     * @return Checkbox
355
     */
356
    public function checkbox($name, $label = null) {
357
      trigger_error('Deprecated', E_USER_DEPRECATED);
358
      $checkbox = new Checkbox($name, $label);
359
      $this->addElement($checkbox);
360
      return $checkbox;
361
    }
362
363
364
    /**
365
     * @param string $name
366
     * @param null $text
367
     * @return CheckboxList
368
     */
369
    public function checkboxList($name, $text = null) {
370
      $checkbox = new CheckboxList();
371
      $checkbox->setName($name);
372
      $checkbox->setText($text);
373
      $this->addElement($checkbox);
374
      return $checkbox;
375
    }
376
377
378
    /**
379
     * Render full form
380
     *
381
     * @return string
382
     */
383
    public function render() {
384
      return $this->renderStart() . $this->renderElements() . $this->renderEnd();
385
    }
386
387
388
    /**
389
     * You can easy rewrite this method for custom design of your forms
390
     *
391
     * @return string
392
     */
393
    protected function renderElements() {
394
      $formHtml = '<dl>';
395
396
      foreach ($this->getElements() as $element) {
397
        # skip hidden element
398
        if ($element instanceof Element\Hidden) {
399
          continue;
400
        }
401
402
        if ($element instanceof Element\Input and $element->getType() === 'hidden') {
403
          continue;
404
        }
405
406
        $elementText = '';
407
408
        if ($element instanceof Element\BaseElement) {
409
          $elementText = $element->getText();
410
        }
411
412
        $formHtml .=
413
          '<dt>' . $elementText . '</dt>' .
414
          '<dd>' . $element->render() . '</dd>';
415
      }
416
417
      $formHtml .= '</dl>';
418
      return $formHtml;
419
    }
420
421
422
    /**
423
     * @return string
424
     */
425
    public function renderStart() {
426
      $hidden = new Element\Input();
427
      $hidden->setType('hidden');
428
      $hidden->addAttributes([
429
        'name' => $this->getUid(),
430
      ]);
431
      $hidden->setValue(1);
432
433
434
      # get default attribute
435
      $method = $this->getMethod();
436
      $this->setAttribute('method', $method);
437
438
      $html = '<form ' . Element\Html::renderAttributes($this->getAttributes()) . '>';
439
      $html .= $hidden->render();
440
441
      # render hidden element
442
      foreach ($this->getElements() as $element) {
443
        if ($element instanceof Element\Input and $element->getType() === 'hidden') {
444
          $html .= $element->render();
445
        }
446
447
        if ($element instanceof Element\Hidden) {
448
          $html .= $element->render();
449
        }
450
451
      }
452
453
454
      return $html;
455
    }
456
457
458
    /**
459
     * @return string
460
     */
461
    public function renderEnd() {
462
      return '</form>';
463
    }
464
  }