1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace drupol\htmltag; |
4
|
|
|
|
5
|
|
|
/** |
6
|
|
|
* Class Attributes. |
7
|
|
|
*/ |
8
|
|
|
class Attributes implements AttributesInterface |
9
|
|
|
{ |
10
|
|
|
/** |
11
|
|
|
* Stores the attribute data. |
12
|
|
|
* |
13
|
|
|
* @var \drupol\htmltag\Attribute[] |
14
|
|
|
*/ |
15
|
|
|
private $storage = array(); |
16
|
|
|
|
17
|
|
|
/** |
18
|
|
|
* {@inheritdoc} |
19
|
|
|
*/ |
20
|
24 |
|
public function __construct(array $attributes = array()) |
21
|
|
|
{ |
22
|
24 |
|
foreach ($attributes as $name => $value) { |
23
|
2 |
|
$this->storage[$name] = new Attribute( |
24
|
2 |
|
$name, |
25
|
2 |
|
$this->ensureString($value) |
26
|
|
|
); |
27
|
|
|
} |
28
|
24 |
|
} |
29
|
|
|
|
30
|
|
|
/** |
31
|
|
|
* {@inheritdoc} |
32
|
|
|
*/ |
33
|
2 |
|
public function offsetGet($name) |
34
|
|
|
{ |
35
|
2 |
|
if (!isset($this->storage[$name])) { |
36
|
2 |
|
$this->storage[$name] = new Attribute( |
37
|
2 |
|
$name |
38
|
|
|
); |
39
|
|
|
} |
40
|
|
|
|
41
|
2 |
|
return $this->storage[$name]; |
42
|
|
|
} |
43
|
|
|
|
44
|
|
|
/** |
45
|
|
|
* {@inheritdoc} |
46
|
|
|
*/ |
47
|
1 |
|
public function offsetSet($name, $value = null) |
48
|
|
|
{ |
49
|
1 |
|
$this->storage[$name] = new Attribute( |
50
|
1 |
|
$name, |
51
|
1 |
|
$this->ensureString($value) |
52
|
|
|
); |
53
|
1 |
|
} |
54
|
|
|
|
55
|
|
|
/** |
56
|
|
|
* {@inheritdoc} |
57
|
|
|
*/ |
58
|
1 |
|
public function offsetUnset($name) |
59
|
|
|
{ |
60
|
1 |
|
unset($this->storage[$name]); |
61
|
1 |
|
} |
62
|
|
|
|
63
|
|
|
/** |
64
|
|
|
* {@inheritdoc} |
65
|
|
|
*/ |
66
|
2 |
|
public function offsetExists($name) |
67
|
|
|
{ |
68
|
2 |
|
return isset($this->storage[$name]); |
69
|
|
|
} |
70
|
|
|
|
71
|
|
|
/** |
72
|
|
|
* {@inheritdoc} |
73
|
|
|
*/ |
74
|
14 |
View Code Duplication |
public function append($key, $value = '') |
|
|
|
|
75
|
|
|
{ |
76
|
|
|
$this->storage += array( |
77
|
14 |
|
$key => new Attribute( |
78
|
14 |
|
$key, |
79
|
14 |
|
$this->ensureString($value) |
80
|
|
|
) |
81
|
|
|
); |
82
|
|
|
|
83
|
14 |
|
foreach ($this->normalizeValue($value) as $value_item) { |
84
|
14 |
|
$this->storage[$key]->append($value_item); |
85
|
|
|
} |
86
|
|
|
|
87
|
14 |
|
return $this; |
88
|
|
|
} |
89
|
|
|
|
90
|
|
|
/** |
91
|
|
|
* {@inheritdoc} |
92
|
|
|
*/ |
93
|
2 |
|
public function remove($key, $value = '') |
94
|
|
|
{ |
95
|
2 |
|
if (!isset($this->storage[$key])) { |
96
|
1 |
|
return $this; |
97
|
|
|
} |
98
|
|
|
|
99
|
1 |
|
foreach ($this->normalizeValue($value) as $value_item) { |
100
|
1 |
|
$this->storage[$key]->remove($value_item); |
101
|
|
|
} |
102
|
|
|
|
103
|
1 |
|
return $this; |
104
|
|
|
} |
105
|
|
|
|
106
|
|
|
/** |
107
|
|
|
* {@inheritdoc} |
108
|
|
|
*/ |
109
|
2 |
|
public function delete($name = array()) |
110
|
|
|
{ |
111
|
2 |
|
foreach ($this->normalizeValue($name) as $attribute_name) { |
112
|
2 |
|
unset($this->storage[$attribute_name]); |
113
|
|
|
} |
114
|
|
|
|
115
|
2 |
|
return $this; |
116
|
|
|
} |
117
|
|
|
|
118
|
|
|
/** |
119
|
|
|
* {@inheritdoc} |
120
|
|
|
*/ |
121
|
1 |
|
public function without($key) |
122
|
|
|
{ |
123
|
1 |
|
$attributes = clone $this; |
124
|
|
|
|
125
|
1 |
|
return $attributes->delete($key); |
|
|
|
|
126
|
|
|
} |
127
|
|
|
|
128
|
|
|
/** |
129
|
|
|
* {@inheritdoc} |
130
|
|
|
*/ |
131
|
1 |
|
public function replace($key, $value, $replacement) |
132
|
|
|
{ |
133
|
1 |
|
if (!isset($this->storage[$key])) { |
134
|
1 |
|
return $this; |
135
|
|
|
} |
136
|
|
|
|
137
|
1 |
|
if (!$this->contains($key, $value)) { |
138
|
1 |
|
return $this; |
139
|
|
|
} |
140
|
|
|
|
141
|
1 |
|
$this->storage[$key]->remove($value); |
142
|
1 |
|
foreach ($this->normalizeValue($replacement) as $replacement_value) { |
143
|
1 |
|
$this->storage[$key]->append($replacement_value); |
144
|
|
|
} |
145
|
|
|
|
146
|
1 |
|
return $this; |
147
|
|
|
} |
148
|
|
|
|
149
|
|
|
/** |
150
|
|
|
* {@inheritdoc} |
151
|
|
|
*/ |
152
|
1 |
View Code Duplication |
public function merge(array $data = array()) |
|
|
|
|
153
|
|
|
{ |
154
|
1 |
|
foreach ($data as $key => $value) { |
155
|
|
|
$this->storage += array( |
156
|
1 |
|
$key => new Attribute( |
157
|
1 |
|
$key |
158
|
|
|
) |
159
|
|
|
); |
160
|
|
|
|
161
|
1 |
|
$this->storage[$key]->merge( |
162
|
1 |
|
$this->normalizeValue($value) |
163
|
|
|
); |
164
|
|
|
} |
165
|
|
|
|
166
|
1 |
|
return $this; |
167
|
|
|
} |
168
|
|
|
|
169
|
|
|
/** |
170
|
|
|
* {@inheritdoc} |
171
|
|
|
*/ |
172
|
1 |
|
public function exists($key, $value = null) |
173
|
|
|
{ |
174
|
1 |
|
if (!isset($this->storage[$key])) { |
175
|
1 |
|
return false; |
176
|
|
|
} |
177
|
|
|
|
178
|
1 |
|
if (null !== $value) { |
179
|
1 |
|
return $this->contains($key, $value); |
180
|
|
|
} |
181
|
|
|
|
182
|
1 |
|
return true; |
183
|
|
|
} |
184
|
|
|
|
185
|
|
|
/** |
186
|
|
|
* {@inheritdoc} |
187
|
|
|
*/ |
188
|
3 |
|
public function contains($key, $value) |
189
|
|
|
{ |
190
|
3 |
|
if (!isset($this->storage[$key])) { |
191
|
1 |
|
return false; |
192
|
|
|
} |
193
|
|
|
|
194
|
3 |
|
return $this->storage[$key]->contains($value); |
195
|
|
|
} |
196
|
|
|
|
197
|
|
|
/** |
198
|
|
|
* {@inheritdoc} |
199
|
|
|
*/ |
200
|
7 |
|
public function __toString() |
201
|
|
|
{ |
202
|
7 |
|
return $this->render(); |
203
|
|
|
} |
204
|
|
|
|
205
|
|
|
/** |
206
|
|
|
* {@inheritdoc} |
207
|
|
|
*/ |
208
|
13 |
|
public function render() |
209
|
|
|
{ |
210
|
13 |
|
$attributes = implode(' ', $this->prepareValues()); |
211
|
|
|
|
212
|
13 |
|
return $attributes ? ' ' . $attributes : ''; |
213
|
|
|
} |
214
|
|
|
|
215
|
|
|
/** |
216
|
|
|
* {@inheritdoc} |
217
|
|
|
*/ |
218
|
2 |
|
public function toArray() |
219
|
|
|
{ |
220
|
2 |
|
$attributes = $this->storage; |
221
|
|
|
|
222
|
|
|
// If empty, just return an empty array. |
223
|
2 |
|
if (empty($attributes)) { |
224
|
2 |
|
return array(); |
225
|
|
|
} |
226
|
|
|
|
227
|
1 |
|
$result = []; |
228
|
|
|
|
229
|
1 |
|
foreach ($this->prepareValues() as $attribute) { |
230
|
1 |
|
$result[$attribute->getName()] = $attribute->getValueAsArray(); |
231
|
|
|
} |
232
|
|
|
|
233
|
1 |
|
return $result; |
234
|
|
|
} |
235
|
|
|
|
236
|
|
|
/** |
237
|
|
|
* {@inheritdoc} |
238
|
|
|
*/ |
239
|
1 |
|
public function getStorage() |
240
|
|
|
{ |
241
|
1 |
|
return $this->storage; |
242
|
|
|
} |
243
|
|
|
|
244
|
|
|
/** |
245
|
|
|
* {@inheritdoc} |
246
|
|
|
*/ |
247
|
1 |
|
public function getIterator() |
248
|
|
|
{ |
249
|
1 |
|
return new \ArrayIterator($this->toArray()); |
250
|
|
|
} |
251
|
|
|
|
252
|
|
|
/** |
253
|
|
|
* {@inheritdoc} |
254
|
|
|
*/ |
255
|
1 |
|
public function count() |
256
|
|
|
{ |
257
|
1 |
|
return count($this->storage); |
258
|
|
|
} |
259
|
|
|
|
260
|
|
|
/** |
261
|
|
|
* Returns all storage elements as an array. |
262
|
|
|
* |
263
|
|
|
* @return \drupol\htmltag\Attribute[] |
264
|
|
|
* An associative array of attributes. |
265
|
|
|
*/ |
266
|
14 |
|
private function prepareValues() |
267
|
|
|
{ |
268
|
14 |
|
$attributes = $this->storage; |
269
|
|
|
|
270
|
|
|
// If empty, just return an empty array. |
271
|
14 |
|
if (empty($attributes)) { |
272
|
5 |
|
return array(); |
273
|
|
|
} |
274
|
|
|
|
275
|
|
|
// Sort the attributes. |
276
|
12 |
|
ksort($attributes); |
277
|
|
|
|
278
|
12 |
|
$result = []; |
279
|
|
|
|
280
|
12 |
|
foreach ($attributes as $attribute_name => $attribute) { |
281
|
|
|
switch ($attribute_name) { |
282
|
12 |
|
case 'class': |
283
|
10 |
|
$classes = $attribute->getValueAsArray(); |
284
|
10 |
|
asort($classes); |
285
|
10 |
|
$result[$attribute->getName()] = $attribute->set( |
286
|
10 |
|
implode(' ', $classes) |
287
|
|
|
); |
288
|
10 |
|
break; |
289
|
|
|
|
290
|
|
|
default: |
291
|
12 |
|
$result[$attribute->getName()] = $attribute; |
292
|
|
|
} |
293
|
|
|
} |
294
|
|
|
|
295
|
12 |
|
return $result; |
296
|
|
|
} |
297
|
|
|
|
298
|
|
|
/** |
299
|
|
|
* Normalize a value. |
300
|
|
|
* |
301
|
|
|
* @param mixed $value |
302
|
|
|
* The value to normalize. |
303
|
|
|
* |
304
|
|
|
* @return array |
305
|
|
|
* The value normalized. |
306
|
|
|
*/ |
307
|
16 |
|
private function normalizeValue($value) |
308
|
|
|
{ |
309
|
16 |
|
return $this->ensureFlatArray($value); |
310
|
|
|
} |
311
|
|
|
|
312
|
|
|
/** |
313
|
|
|
* Todo. |
314
|
|
|
* |
315
|
|
|
* @param mixed $value |
316
|
|
|
* Todo. |
317
|
|
|
* |
318
|
|
|
* @return array |
319
|
|
|
* The array, flattened. |
320
|
|
|
*/ |
321
|
16 |
|
private function ensureFlatArray($value) |
322
|
|
|
{ |
323
|
16 |
|
$type = gettype($value); |
324
|
|
|
|
325
|
16 |
|
$return = array(); |
326
|
|
|
|
327
|
|
|
switch ($type) { |
328
|
16 |
|
case 'string': |
329
|
16 |
|
$return = explode( |
330
|
16 |
|
' ', |
331
|
16 |
|
$this->ensureString($value) |
332
|
|
|
); |
333
|
16 |
|
break; |
334
|
|
|
|
335
|
5 |
|
case 'array': |
336
|
4 |
|
$flat_array = iterator_to_array( |
337
|
4 |
|
new \RecursiveIteratorIterator( |
338
|
4 |
|
new \RecursiveArrayIterator( |
339
|
4 |
|
$value |
340
|
|
|
) |
341
|
|
|
), |
342
|
4 |
|
false |
343
|
|
|
); |
344
|
|
|
|
345
|
4 |
|
$return = []; |
346
|
4 |
|
foreach ($flat_array as $item) { |
347
|
4 |
|
$return = array_merge( |
348
|
4 |
|
$return, |
349
|
4 |
|
$this->normalizeValue($item) |
350
|
|
|
); |
351
|
|
|
} |
352
|
4 |
|
break; |
353
|
|
|
|
354
|
2 |
|
case 'double': |
355
|
2 |
|
case 'integer': |
356
|
1 |
|
$return = array($value); |
357
|
1 |
|
break; |
358
|
1 |
|
case 'object': |
359
|
1 |
|
case 'boolean': |
360
|
1 |
|
case 'resource': |
361
|
1 |
|
case 'NULL': |
362
|
|
|
} |
363
|
|
|
|
364
|
16 |
|
return $return; |
365
|
|
|
} |
366
|
|
|
|
367
|
|
|
/** |
368
|
|
|
* Todo. |
369
|
|
|
* |
370
|
|
|
* @param mixed $value |
371
|
|
|
* Todo. |
372
|
|
|
* |
373
|
|
|
* @return string |
374
|
|
|
* A string. |
375
|
|
|
*/ |
376
|
16 |
|
private function ensureString($value) |
377
|
|
|
{ |
378
|
16 |
|
$type = gettype($value); |
379
|
|
|
|
380
|
16 |
|
$return = ''; |
381
|
|
|
|
382
|
|
|
switch ($type) { |
383
|
16 |
|
case 'string': |
384
|
16 |
|
$return = $value; |
385
|
16 |
|
break; |
386
|
|
|
|
387
|
4 |
|
case 'array': |
388
|
3 |
|
$return = implode( |
389
|
3 |
|
' ', |
390
|
3 |
|
$this->ensureFlatArray($value) |
391
|
|
|
); |
392
|
3 |
|
break; |
393
|
|
|
|
394
|
3 |
|
case 'double': |
395
|
3 |
|
case 'integer': |
396
|
1 |
|
$return = (string) $value; |
397
|
1 |
|
break; |
398
|
2 |
|
case 'object': |
399
|
2 |
|
case 'boolean': |
400
|
2 |
|
case 'resource': |
401
|
2 |
|
case 'NULL': |
402
|
|
|
} |
403
|
|
|
|
404
|
16 |
|
return $return; |
405
|
|
|
} |
406
|
|
|
} |
407
|
|
|
|
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.