Completed
Push — 1.x ( f9e31b...bd3256 )
by Pol
01:31
created

Attributes::contains()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 8
ccs 0
cts 4
cp 0
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 2
crap 6
1
<?php
2
3
namespace drupol\htmltag;
4
5
/**
6
 * Class Attributes.
7
 */
8
class Attributes implements \ArrayAccess, \IteratorAggregate
9
{
10
    /**
11
     * Stores the attribute data.
12
     *
13
     * @var \drupol\htmltag\Attribute[]
14
     */
15
    private $storage = array();
16
17
    /**
18
     * {@inheritdoc}
19
     */
20 7
    public function __construct(array $attributes = array())
21
    {
22 7
        $this->setAttributes($attributes);
23 7
    }
24
25
    /**
26
     * Normalize a value.
27
     *
28
     * @param mixed $value
29
     *  The value to normalize.
30
     *
31
     * @return array
32
     *   The value normalized.
33
     */
34 3
    private function normalizeValue($value)
35
    {
36 3
        return $this->ensureFlatArray($value);
37
    }
38
39
    /**
40
     * Todo.
41
     *
42
     * @param mixed $value
43
     *   Todo.
44
     *
45
     * @return array
46
     *   The array, flattened.
47
     */
48 3
    private function ensureFlatArray($value)
49
    {
50 3
        $type = gettype($value);
51
52 3
        $return = array();
53
54
        switch ($type) {
55 3
            case 'string':
56 2
                $return = explode(
57 2
                    ' ',
58 2
                    $this->ensureString($value)
59
                );
60 2
                break;
61
62 2
            case 'array':
63
                $return = iterator_to_array(
64
                    new \RecursiveIteratorIterator(
65
                        new \RecursiveArrayIterator(
66
                            $value
67
                        )
68
                    ),
69
                    false
70
                );
71
                break;
72
73 2
            case 'double':
74 2
            case 'integer':
75
                $return = array($value);
76
                break;
77 2
            case 'object':
78 2
            case 'boolean':
79 2
            case 'resource':
80 2
            case 'NULL':
81
        }
82
83 3
        return $return;
84
    }
85
86
    /**
87
     * Todo.
88
     *
89
     * @param mixed $value
90
     *   Todo.
91
     *
92
     * @return string
93
     *   A string.
94
     */
95 3
    private function ensureString($value)
96
    {
97 3
        $type = gettype($value);
98
99 3
        $return = '';
100
101
        switch ($type) {
102 3
            case 'string':
103 2
                $return = $value;
104 2
                break;
105
106 2
            case 'array':
107
                $return = implode(
108
                    ' ',
109
                    $this->ensureFlatArray($value)
110
                );
111
                break;
112
113 2
            case 'double':
114 2
            case 'integer':
115
                 $return = (string) $value;
116
                break;
117 2
            case 'object':
118 2
            case 'boolean':
119 2
            case 'resource':
120 2
            case 'NULL':
121
        }
122
123 3
        return $return;
124
    }
125
126
    /**
127
     * Set attributes.
128
     *
129
     * @param array|Attributes $attributes
130
     *   The attributes.
131
     *
132
     * @return $this
133
     */
134 7
    public function setAttributes($attributes = array())
135
    {
136 7
        foreach ($attributes as $name => $value) {
137
            $this->storage[$name] = new Attribute(
138
                $name,
139
                $this->ensureString($value)
140
            );
141
        }
142
143 7
        return $this;
144
    }
145
146
    /**
147
     * {@inheritdoc}
148
     */
149 1
    public function &offsetGet($name)
150
    {
151 1
        if (!isset($this->storage[$name])) {
152 1
            $attribute = new Attribute(
153 1
                $name
154
            );
155 1
            $this->storage[$attribute->getName()] = $attribute;
156
        }
157
158 1
        return $this->storage[$name];
159
    }
160
161
    /**
162
     * {@inheritdoc}
163
     */
164
    public function offsetSet($name, $value = null)
165
    {
166
        $this->storage[$name] = new Attribute(
167
            $name,
168
            $this->ensureString($value)
169
        );
170
    }
171
172
    /**
173
     * {@inheritdoc}
174
     */
175
    public function offsetUnset($name)
176
    {
177
        unset($this->storage[$name]);
178
    }
179
180
    /**
181
     * {@inheritdoc}
182
     */
183
    public function offsetExists($name)
184
    {
185
        return isset($this->storage[$name]);
186
    }
187
188
    /**
189
     * Sets values for an attribute key.
190
     *
191
     * @param string $attribute
192
     *   Name of the attribute.
193
     * @param string|array|bool $value
194
     *   Value(s) to set for the given attribute key.
195
     *
196
     * @return $this
197
     */
198
    public function setAttribute($attribute, $value = false)
199
    {
200
        $this->offsetSet($attribute, $value);
201
202
        return $this;
203
    }
204
205
    /**
206
     * Append a value into an attribute.
207
     *
208
     * @param string $key
209
     *   The attribute's name.
210
     * @param string|array|bool $value
211
     *   The attribute's value.
212
     *
213
     * @return $this
214
     */
215 3 View Code Duplication
    public function append($key, $value = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
216
    {
217
        $this->storage += array(
218 3
            $key => new Attribute(
219 3
                $key,
220 3
                $this->ensureString($value)
221
            )
222
        );
223
224 3
        $value = $this->normalizeValue($value);
225
226 3
        foreach ($value as $value_item) {
227 2
            $this->storage[$key]->append($value_item);
228
        }
229
230 3
        return $this;
231
    }
232
233
    /**
234
     * Remove a value from a specific attribute.
235
     *
236
     * @param string $key
237
     *   The attribute's name.
238
     * @param string|array|bool $value
239
     *   The attribute's value.
240
     *
241
     * @return $this
242
     */
243 2
    public function remove($key, $value = false)
244
    {
245 2
        if (!isset($this->storage[$key])) {
246 1
            return $this;
247
        }
248
249 1
        $value = $this->normalizeValue($value);
250
251 1
        foreach ($value as $value_item) {
252 1
            $this->storage[$key]->remove($value_item);
253
        }
254
255 1
        return $this;
256
    }
257
258
    /**
259
     * Delete an attribute.
260
     *
261
     * @param string|array $name
262
     *   The name of the attribute key to delete.
263
     *
264
     * @return $this
265
     */
266 1
    public function delete($name = array())
267
    {
268 1
        $name = $this->normalizeValue($name);
269
270 1
        foreach ($name as $attribute_name) {
271 1
            unset($this->storage[$attribute_name]);
272
        }
273
274 1
        return $this;
275
    }
276
277
    /**
278
     * Return the attributes.
279
     *
280
     * @param string $key
281
     *   The attributes's name.
282
     * @param array|string $value
283
     *   The attribute's value.
284
     *
285
     * @return \drupol\htmltag\Attributes
286
     */
287
    public function without($key, $value)
288
    {
289
        $attributes = clone $this;
290
291
        return $attributes->remove($key, $value);
292
    }
293
294
    /**
295
     * Replace a value with another.
296
     *
297
     * @param string $key
298
     *   The attributes's name.
299
     * @param string $value
300
     *   The attribute's value.
301
     * @param array|string $replacement
302
     *   The replacement value.
303
     *
304
     * @return $this
305
     */
306 View Code Duplication
    public function replace($key, $value, $replacement)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
307
    {
308
        $this->storage += array(
309
            $key => new Attribute(
310
                $key,
311
                $this->ensureString($value)
312
            )
313
        );
314
315
        $replacement = $this->normalizeValue($replacement);
316
317
        foreach ($replacement as $replacement_value) {
318
            $this->storage[$key]->replace($value, $replacement_value);
319
        }
320
321
        return $this;
322
    }
323
324
    /**
325
     * Merge attributes.
326
     *
327
     * @param array $data
328
     *   The data to merge.
329
     *
330
     * @return $this
331
     */
332 View Code Duplication
    public function merge(array $data = array())
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
333
    {
334
        foreach ($data as $key => $value) {
335
            $this->storage += array(
336
                $key => new Attribute(
337
                    $key,
338
                    $this->ensureString($value)
339
                )
340
            );
341
342
            $this->storage[$key]->merge(
343
                $this->normalizeValue($value)
344
            );
345
        }
346
347
        return $this;
348
    }
349
350
    /**
351
     * Check if an attribute exists and if a value if provided check it as well.
352
     *
353
     * @param string $key
354
     *   Attribute name.
355
     * @param string $value
356
     *   Todo.
357
     *
358
     * @return bool
359
     *   Whereas an attribute exists.
360
     */
361
    public function exists($key, $value = null)
362
    {
363
        if (isset($this->storage[$key])) {
364
            $attribute = $this->storage[$key];
365
        } else {
366
            return false;
367
        }
368
369
        if (null !== $value) {
370
            return $attribute->contains($value);
371
        }
372
373
        return true;
374
    }
375
376
    /**
377
     * Check if attribute contains a value.
378
     *
379
     * @param string $key
380
     *   Attribute name.
381
     * @param string $value
382
     *   Attribute value.
383
     *
384
     * @return bool
385
     *   Whereas an attribute contains a value.
386
     */
387
    public function contains($key, $value)
388
    {
389
        if (!isset($this->storage[$key])) {
390
            return false;
391
        }
392
393
        return $this->storage[$key]->contains($value);
394
    }
395
396
    /**
397
     * {@inheritdoc}
398
     */
399 4
    public function __toString()
400
    {
401 4
        $attributes = $this->storage;
402
403
        // If empty, just return an empty string.
404 4
        if (empty($attributes)) {
405 2
            return '';
406
        }
407
408 4
        $result = implode(' ', $this->prepareValues());
409
410 4
        return $result ? ' ' . $result : '';
411
    }
412
413
    /**
414
     * Returns all storage elements as an array.
415
     *
416
     * @return \drupol\htmltag\Attribute[]
417
     *   An associative array of attributes.
418
     */
419 4
    private function prepareValues()
420
    {
421 4
        $attributes = $this->storage;
422
423
        // If empty, just return an empty array.
424 4
        if (empty($attributes)) {
425
            return array();
426
        }
427
428
        // Sort the attributes.
429 4
        ksort($attributes);
430
431 4
        $result = [];
432
433 4
        foreach ($attributes as $attribute_name => $attribute) {
434
            switch ($attribute_name) {
435 4
                case 'class':
436 3
                    $classes = $attribute->getValueAsArray();
437 3
                    asort($classes);
438 3
                    $result[$attribute->getName()] = $attribute
439 3
                    ->withValue(
440 3
                        implode(' ', $classes)
441
                    );
442 3
                    break;
443
444 2
                case 'placeholder':
445
                    $result[$attribute->getName()] = $attribute
446
                    ->withValue(
447
                        strip_tags($attribute->getValueAsString())
448
                    );
449
                    break;
450
451
                default:
452 4
                    $result[$attribute->getName()] = $attribute;
453
            }
454
        }
455
456 4
        return $result;
457
    }
458
459
    /**
460
     * Returns all storage elements as an array.
461
     *
462
     * @return array
463
     *   An associative array of attributes.
464
     */
465
    public function toArray()
466
    {
467
        $attributes = $this->storage;
468
469
        // If empty, just return an empty array.
470
        if (empty($attributes)) {
471
            return array();
472
        }
473
474
        $result = [];
475
476
        foreach ($this->prepareValues() as $attribute) {
477
            $result[$attribute->getName()] = $attribute->getValueAsArray();
478
        }
479
480
        return $result;
481
    }
482
483
    /**
484
     * Get storage.
485
     *
486
     * @return \drupol\htmltag\Attribute[]
487
     *   Todo.
488
     */
489
    public function getStorage()
490
    {
491
        return $this->storage;
492
    }
493
494
    /**
495
     * {@inheritdoc}
496
     */
497
    public function getIterator()
498
    {
499
        return new \ArrayIterator($this->toArray());
500
    }
501
}
502