Passed
Branch master (41990d)
by Gabor
03:31
created

AbstractForm::getErrors()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
/**
3
 * WebHemi.
4
 *
5
 * PHP version 5.6
6
 *
7
 * @copyright 2012 - 2016 Gixx-web (http://www.gixx-web.com)
8
 * @license   https://opensource.org/licenses/MIT The MIT License (MIT)
9
 *
10
 * @link      http://www.gixx-web.com
11
 */
12
namespace WebHemi\Form;
13
14
use Iterator;
15
use WebHemi\Form\Element\FormElementContainerInterface;
16
use WebHemi\Form\Element\NestedElementInterface;
17
use WebHemi\Form\Traits\CamelCaseToUnderScoreTrait;
18
use WebHemi\Form\Traits\IteratorTrait;
19
20
/**
21
 * Class AbstractForm
22
 */
23
abstract class AbstractForm implements FormInterface, Iterator
24
{
25
    /** @var FormElementContainerInterface */
26
    private $formElementContainer;
27
    /** @var NestedElementInterface */
28
    protected $form;
29
    /** @var string */
30
    protected $salt;
31
32
    // The implementation of the Iterator interface.
33
    use IteratorTrait;
34
    // CamelCase to under_score converter
35
    use CamelCaseToUnderScoreTrait;
36
37
    /**
38
     * AbstractForm constructor.
39
     *
40
     * @param FormElementContainerInterface $formElementContainer
41
     * @param string                        $name
42
     * @param string                        $action
43
     * @param string                        $method
44
     */
45 8
    final public function __construct(
46
        FormElementContainerInterface $formElementContainer,
47
        $name = '',
48
        $action = '',
49
        $method = 'POST'
50
    ) {
51 8
        $this->formElementContainer = $formElementContainer;
52
53 8
        if (empty($name)) {
54 1
            $name = $this->camelCaseToUnderscore(get_called_class());
55 1
        }
56
57 8
        $this->form = $this->getFormContainer();
58 8
        $this->form->setName($name)
59 8
            ->setAttributes(
60 1
                [
61 8
                    'action' => $action,
62 8
                    'method' => strtoupper($method)
63 8
                ]
64 8
            );
65
66
        // For simplicity in rendering (twig macro), we store it in an array.
67 8
        $this->nodes[0] =& $this->form;
68
        // Set a default salt for the form name. If the AutoComplete attribute is 'off', it will be added to the form's
69
        // name attribute. The default salt will change every hour.
70 8
        $this->salt = md5(gmdate('YmdH'));
71
72 8
        $this->initForm();
73 8
    }
74
75
    /**
76
     * Returns the form element container.
77
     *
78
     * @return FormElementContainerInterface
79
     */
80 1
    protected function getFormElementContainer()
81
    {
82 1
        return $this->formElementContainer;
83
    }
84
85
    /**
86
     * Returns the form container element. E.g.: for HTML forms it is the <form> tag.
87
     *
88
     * @return NestedElementInterface
89
     */
90
    abstract protected function getFormContainer();
91
92
    /**
93
     * Initialize form.
94
     *
95
     * @return void
96
     */
97
    abstract protected function initForm();
98
99
    /**
100
     * Sets form name.
101
     *
102
     * @param string $name
103
     * @return FormInterface
104
     */
105 2
    public function setName($name)
106
    {
107 2
        $this->form->setName($name);
108
109 2
        $formAttributes = $this->form->getAttributes();
110
111 2
        if (isset($formAttributes['autocomplete'])) {
112 1
            $this->setAutoComplete($formAttributes['autocomplete']);
113 1
        }
114 2
    }
115
116
    /**
117
     * Gets form name.
118
     *
119
     * @return string
120
     */
121 3
    public function getName()
122
    {
123 3
        return $this->form->getName();
124
    }
125
126
    /**
127
     * Set unique identifier for the form.
128
     *
129
     * @param string $salt
130
     * @return AbstractForm
131
     */
132 3
    public function setNameSalt($salt)
133
    {
134 3
        $this->salt = md5($salt);
135
136 3
        return $this;
137
    }
138
139
    /**
140
     * Sets form action.
141
     *
142
     * @param string $action
143
     * @return AbstractForm
144
     */
145 1
    final public function setAction($action)
146
    {
147 1
        $this->setAttribute('action', $action);
148
149 1
        return $this;
150
    }
151
152
    /**
153
     * Sets form submit.
154
     *
155
     * @param string $method
156
     * @return AbstractForm
157
     */
158 1
    final public function setMethod($method = 'POST')
159
    {
160 1
        $this->setAttribute('method', $method);
161
162 1
        return $this;
163
    }
164
165
    /**
166
     * Sets form encoding type.
167
     *
168
     * @param string $encodingType
169
     * @return AbstractForm
170
     */
171 1
    final protected function setEnctype($encodingType = 'application/x-www-form-urlencoded')
172
    {
173 1
        $this->setAttribute('enctype', $encodingType);
174
175 1
        return $this;
176
    }
177
178
    /**
179
     * Sets form auto-complete option.
180
     *
181
     * @param bool $autoComplete
182
     * @return AbstractForm
183
     */
184 3
    final public function setAutoComplete($autoComplete = true)
185
    {
186 3
        $name = $this->form->getName(false);
187 3
        $md5Match = [];
188
189
        // Search for the unique form prefix.
190 3
        preg_match('/^[a-z0-9\_\-\[\]]+\_(?P<md5>[a-f0-9]{32}).*$/', $name, $md5Match);
191
192
        // When it's necessary, add/remove the salt to/from the name
193 3
        if ($autoComplete && !empty($md5Match)) {
194 1
            $name = str_replace('_'.$md5Match['md5'], '', $name);
195 3
        } elseif (!$autoComplete && empty($md5Match)) {
196 3
            $name = $name.'_'.$this->salt;
197 3
        }
198
199 3
        $this->form->setName($name);
200
201 3
        $this->setAttribute('autocomplete', $autoComplete);
202
203 3
        return $this;
204
    }
205
206
    /**
207
     * Sets specific form attributes.
208
     *
209
     * @param $name
210
     * @param $value
211
     */
212 4
    private function setAttribute($name, $value)
213
    {
214 4
        $attributes = $this->form->getAttributes();
215 4
        $attributes[$name] = $value;
216
217 4
        $this->form->setAttributes($attributes);
218 4
    }
219
220
    /**
221
     * Adds a form element to the form.
222
     *
223
     * @param array<FormElementInterface> $nodes
224
     * @return AbstractForm
225
     */
226 8
    protected function setNodes(array $nodes)
227
    {
228 8
        $this->form->setNodes($nodes);
229
230 8
        return $this;
231
    }
232
233
    /**
234
     * Gets the form elements.
235
     *
236
     * @return array<FormElementInterface>
237
     */
238 1
    protected function getNodes()
239
    {
240 1
        return $this->form->getNodes();
241
    }
242
243
    /**
244
     * Validates the form.
245
     *
246
     * @param bool $reValidate
247
     * @return bool
248
     */
249 2
    public function isValid($reValidate = false)
250
    {
251 2
        return $this->form->isValid($reValidate);
252
    }
253
254
    /**
255
     * Gets validation errors.
256
     *
257
     * @return array
258
     */
259 1
    public function getErrors()
260
    {
261 1
        return $this->form->getErrors();
262
    }
263
264
    /**
265
     * Sets form data.
266
     *
267
     * @param array $data
268
     * @return FormInterface
269
     */
270 1
    public function setData(array $data)
271
    {
272 1
        if (isset($data[$this->form->getName()])) {
273 1
            $data = $data[$this->form->getName()];
274 1
        }
275
276 1
        $this->form->setValue($data);
277
278 1
        return $this;
279
    }
280
281
    /**
282
     * Returns the form data.
283
     *
284
     * @return array
285
     */
286 1
    public function getData()
287
    {
288 1
        return $this->form->getValue();
289
    }
290
}
291