Completed
Push — 1.x ( 1753bb...f099fc )
by Pol
02:45 queued 01:20
created

Attributes::prepareValues()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 31

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 4

Importance

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