|
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\NestedElementInterface; |
|
16
|
|
|
use WebHemi\Form\Element\Traits\IteratorTrait; |
|
17
|
|
|
|
|
18
|
|
|
/** |
|
19
|
|
|
* Class AbstractForm |
|
20
|
|
|
*/ |
|
21
|
|
|
abstract class AbstractForm implements FormInterface, Iterator |
|
22
|
|
|
{ |
|
23
|
|
|
/** @var NestedElementInterface */ |
|
24
|
|
|
protected $form; |
|
25
|
|
|
/** @var string */ |
|
26
|
|
|
protected $name; |
|
27
|
|
|
/** @var string */ |
|
28
|
|
|
protected $salt; |
|
29
|
|
|
|
|
30
|
|
|
/** @var string */ |
|
31
|
|
|
protected $uniqueFormNamePostfix = ''; |
|
32
|
|
|
|
|
33
|
|
|
// The implementation of the Iterator interface. |
|
34
|
|
|
use IteratorTrait; |
|
35
|
|
|
|
|
36
|
|
|
/** |
|
37
|
|
|
* AbstractForm constructor. |
|
38
|
|
|
* |
|
39
|
|
|
* @param string $name |
|
40
|
|
|
* @param string $action |
|
41
|
|
|
* @param string $method |
|
42
|
|
|
*/ |
|
43
|
|
|
final public function __construct($name, $action = '', $method = 'POST') |
|
44
|
|
|
{ |
|
45
|
|
|
$this->form = $this->getFormContainer(); |
|
46
|
|
|
$this->form->setName($name) |
|
47
|
|
|
->setAttributes( |
|
48
|
|
|
[ |
|
49
|
|
|
'action' => $action, |
|
50
|
|
|
'method' => strtoupper($method) |
|
51
|
|
|
] |
|
52
|
|
|
); |
|
53
|
|
|
|
|
54
|
|
|
// For simplicity in rendering (twig macro), we store it in an array. |
|
55
|
|
|
$this->nodes[0] =& $this->form; |
|
56
|
|
|
// Set a default salt for the form name. If the AutoComplete attribute is 'off', it will be added to the form's |
|
57
|
|
|
// name attribute. The default salt will change every hour. |
|
58
|
|
|
$this->salt = md5(gmdate('YmdH')); |
|
59
|
|
|
|
|
60
|
|
|
$this->initForm(); |
|
61
|
|
|
} |
|
62
|
|
|
|
|
63
|
|
|
/** |
|
64
|
|
|
* Returns the form container element. E.g.: for HTML forms it is the <form> tag. |
|
65
|
|
|
* |
|
66
|
|
|
* @return NestedElementInterface |
|
67
|
|
|
*/ |
|
68
|
|
|
abstract protected function getFormContainer(); |
|
69
|
|
|
|
|
70
|
|
|
/** |
|
71
|
|
|
* Initialize form. |
|
72
|
|
|
* |
|
73
|
|
|
* @return void |
|
74
|
|
|
*/ |
|
75
|
|
|
abstract protected function initForm(); |
|
76
|
|
|
|
|
77
|
|
|
/** |
|
78
|
|
|
* Gets form name. |
|
79
|
|
|
* |
|
80
|
|
|
* @return string |
|
81
|
|
|
*/ |
|
82
|
|
|
public function getName() |
|
83
|
|
|
{ |
|
84
|
|
|
return $this->form->getName(); |
|
85
|
|
|
} |
|
86
|
|
|
|
|
87
|
|
|
/** |
|
88
|
|
|
* Set unique identifier for the form. |
|
89
|
|
|
* |
|
90
|
|
|
* @param string $salt |
|
91
|
|
|
* @return AbstractForm |
|
92
|
|
|
*/ |
|
93
|
|
|
public function setNameSalt($salt) |
|
94
|
|
|
{ |
|
95
|
|
|
$this->salt = md5($salt); |
|
96
|
|
|
|
|
97
|
|
|
return $this; |
|
98
|
|
|
} |
|
99
|
|
|
|
|
100
|
|
|
/** |
|
101
|
|
|
* Sets form action. |
|
102
|
|
|
* |
|
103
|
|
|
* @param string $action |
|
104
|
|
|
* @return AbstractForm |
|
105
|
|
|
*/ |
|
106
|
|
View Code Duplication |
protected function setAction($action) |
|
|
|
|
|
|
107
|
|
|
{ |
|
108
|
|
|
$attributes = $this->form->getAttributes(); |
|
109
|
|
|
$attributes['action'] = $action; |
|
110
|
|
|
|
|
111
|
|
|
$this->form->setAttributes($attributes); |
|
112
|
|
|
|
|
113
|
|
|
return $this; |
|
114
|
|
|
} |
|
115
|
|
|
|
|
116
|
|
|
/** |
|
117
|
|
|
* Sets form submit. |
|
118
|
|
|
* |
|
119
|
|
|
* @param string $method |
|
120
|
|
|
* @return AbstractForm |
|
121
|
|
|
*/ |
|
122
|
|
View Code Duplication |
protected function setMethod($method = 'POST') |
|
|
|
|
|
|
123
|
|
|
{ |
|
124
|
|
|
$attributes = $this->form->getAttributes(); |
|
125
|
|
|
$attributes['method'] = $method; |
|
126
|
|
|
|
|
127
|
|
|
$this->form->setAttributes($attributes); |
|
128
|
|
|
|
|
129
|
|
|
return $this; |
|
130
|
|
|
} |
|
131
|
|
|
|
|
132
|
|
|
/** |
|
133
|
|
|
* Sets form auto-complete option. |
|
134
|
|
|
* |
|
135
|
|
|
* @param bool $autoComplete |
|
136
|
|
|
* @return AbstractForm |
|
137
|
|
|
*/ |
|
138
|
|
|
public function setAutoComplete($autoComplete = true) |
|
139
|
|
|
{ |
|
140
|
|
|
$name = $this->form->getName(false); |
|
141
|
|
|
$md5Match = []; |
|
142
|
|
|
|
|
143
|
|
|
// Search for the unique form prefix. |
|
144
|
|
|
preg_match('/^[a-z0-9]+\_(?P<md5>[a-f0-9]{32}).*$/', $name, $md5Match); |
|
145
|
|
|
|
|
146
|
|
|
// When it's necessary, add/remove the salt to/from the name |
|
147
|
|
|
if ($autoComplete && !empty($md5Match)) { |
|
148
|
|
|
$name = str_replace('_'.$md5Match['md5'], '', $name); |
|
149
|
|
|
} elseif (!$autoComplete && empty($md5Match)) { |
|
150
|
|
|
$name = $name.'_'.$this->salt; |
|
151
|
|
|
} |
|
152
|
|
|
|
|
153
|
|
|
$this->form->setName($name); |
|
154
|
|
|
|
|
155
|
|
|
$attributes = $this->form->getAttributes(); |
|
156
|
|
|
$attributes['autocomplete'] = $autoComplete; |
|
157
|
|
|
|
|
158
|
|
|
$this->form->setAttributes($attributes); |
|
159
|
|
|
|
|
160
|
|
|
return $this; |
|
161
|
|
|
} |
|
162
|
|
|
|
|
163
|
|
|
/** |
|
164
|
|
|
* Sets form encoding type. |
|
165
|
|
|
* |
|
166
|
|
|
* @param string $encodingType |
|
167
|
|
|
* @return AbstractForm |
|
168
|
|
|
*/ |
|
169
|
|
|
protected function setEnctype($encodingType = 'application/x-www-form-urlencoded') |
|
170
|
|
|
{ |
|
171
|
|
|
$attributes = $this->form->getAttributes(); |
|
172
|
|
|
$attributes['enctype'] = $encodingType; |
|
173
|
|
|
|
|
174
|
|
|
$this->form->setAttributes($attributes); |
|
175
|
|
|
|
|
176
|
|
|
return $this; |
|
177
|
|
|
} |
|
178
|
|
|
|
|
179
|
|
|
/** |
|
180
|
|
|
* Adds a form element to the form. |
|
181
|
|
|
* |
|
182
|
|
|
* @param array<FormElementInterface> $nodes |
|
183
|
|
|
* @return AbstractForm |
|
184
|
|
|
*/ |
|
185
|
|
|
protected function setNodes(array $nodes) |
|
186
|
|
|
{ |
|
187
|
|
|
$this->form->setNodes($nodes); |
|
188
|
|
|
|
|
189
|
|
|
return $this; |
|
190
|
|
|
} |
|
191
|
|
|
|
|
192
|
|
|
/** |
|
193
|
|
|
* Gets the form elements. |
|
194
|
|
|
* |
|
195
|
|
|
* @return array<FormElementInterface> |
|
196
|
|
|
*/ |
|
197
|
|
|
public function getNodes() |
|
198
|
|
|
{ |
|
199
|
|
|
return $this->form->getNodes(); |
|
200
|
|
|
} |
|
201
|
|
|
|
|
202
|
|
|
/** |
|
203
|
|
|
* Validates the form. |
|
204
|
|
|
* |
|
205
|
|
|
* @return boolean |
|
206
|
|
|
*/ |
|
207
|
|
|
public function isValid() |
|
208
|
|
|
{ |
|
209
|
|
|
return $this->form->isValid(); |
|
210
|
|
|
} |
|
211
|
|
|
|
|
212
|
|
|
/** |
|
213
|
|
|
* Sets form data. |
|
214
|
|
|
* |
|
215
|
|
|
* @param array $data |
|
216
|
|
|
* @return FormInterface |
|
217
|
|
|
*/ |
|
218
|
|
|
public function setData(array $data) |
|
219
|
|
|
{ |
|
220
|
|
|
if (isset($data[$this->form->getName()])) { |
|
221
|
|
|
$data = $data[$this->form->getName()]; |
|
222
|
|
|
} elseif (isset($data[$this->form->getName(false)])) { |
|
223
|
|
|
$data = $data[$this->form->getName(false)]; |
|
224
|
|
|
} |
|
225
|
|
|
|
|
226
|
|
|
$this->form->setValue($data); |
|
227
|
|
|
|
|
228
|
|
|
return $this; |
|
229
|
|
|
} |
|
230
|
|
|
|
|
231
|
|
|
/** |
|
232
|
|
|
* Returns the form data. |
|
233
|
|
|
* |
|
234
|
|
|
* @return array |
|
235
|
|
|
*/ |
|
236
|
|
|
public function getData() |
|
237
|
|
|
{ |
|
238
|
|
|
return $this->form->getValue(); |
|
239
|
|
|
} |
|
240
|
|
|
} |
|
241
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.