Completed
Push — master ( 5149ce...fe70b5 )
by Pol
01:34
created

Attributes::ensureFlatArray()   B

Complexity

Conditions 10
Paths 9

Size

Total Lines 44

Duplication

Lines 44
Ratio 100 %

Code Coverage

Tests 28
CRAP Score 10.0296

Importance

Changes 0
Metric Value
dl 44
loc 44
ccs 28
cts 30
cp 0.9333
rs 7.6666
c 0
b 0
f 0
cc 10
nc 9
nop 1
crap 10.0296

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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
     * The attribute factory.
19
     *
20
     * @var \drupol\htmltag\AttributeFactoryInterface
21
     */
22
    private $attributeFactory;
23
24
    /**
25
     * Attributes constructor.
26
     *
27
     * @param \drupol\htmltag\AttributeFactoryInterface $attributeFactory
28
     *   The attribute factory.
29
     * @param mixed[] $attributes
30
     *   The input attributes.
31
     */
32 26
    public function __construct(AttributeFactoryInterface $attributeFactory, $attributes = array())
33
    {
34 26
        $this->attributeFactory = $attributeFactory;
35 26
        $this->import($attributes);
36 26
    }
37
38
    /**
39
     * {@inheritdoc}
40
     */
41 26
    public function import($attributes = array())
42
    {
43 26
        foreach ($attributes as $name => $value) {
44 4
            $this->set($name, $value);
45
        }
46
47 26
        return $this;
48
    }
49
50
    /**
51
     * {@inheritdoc}
52
     */
53 8
    public function set($name, $value = null)
54
    {
55 8
        $this->storage[$name] = ($this->attributeFactory)::build($name, $value);
56
57 8
        return $this;
58
    }
59
60
    /**
61
     * {@inheritdoc}
62
     */
63 2
    public function offsetGet($name)
64
    {
65 2
        if (!isset($this->storage[$name])) {
66 2
            $this->set($name);
67
        }
68
69 2
        return $this->storage[$name];
70
    }
71
72
    /**
73
     * {@inheritdoc}
74
     */
75 1
    public function offsetSet($name, $value = null)
76
    {
77 1
        $this->set($name, $value);
78 1
    }
79
80
    /**
81
     * {@inheritdoc}
82
     */
83 1
    public function offsetUnset($name)
84
    {
85 1
        unset($this->storage[$name]);
86 1
    }
87
88
    /**
89
     * {@inheritdoc}
90
     */
91 2
    public function offsetExists($name)
92
    {
93 2
        return isset($this->storage[$name]);
94
    }
95
96
    /**
97
     * {@inheritdoc}
98
     */
99 14
    public function append($key, $value = null)
100
    {
101
        $this->storage += array(
102 14
            $key => ($this->attributeFactory)::build($key)
103
        );
104
105 14
        $this->storage[$key]->append($value);
0 ignored issues
show
Bug introduced by
It seems like $value defined by parameter $value on line 99 can also be of type array; however, drupol\htmltag\AttributeInterface::append() does only seem to accept string|array<integer,*>|null, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
106
107 14
        return $this;
108
    }
109
110
    /**
111
     * {@inheritdoc}
112
     */
113 2
    public function remove($key, $value = '')
114
    {
115 2
        if (!isset($this->storage[$key])) {
116 1
            return $this;
117
        }
118
119 1
        foreach ($this->normalizeValue($value) as $value_item) {
120 1
            $this->storage[$key]->remove($value_item);
121
        }
122
123 1
        return $this;
124
    }
125
126
    /**
127
     * {@inheritdoc}
128
     */
129 2
    public function delete($name)
130
    {
131 2
        foreach ($this->normalizeValue($name) as $attribute_name) {
132 2
            unset($this->storage[$attribute_name]);
133
        }
134
135 2
        return $this;
136
    }
137
138
    /**
139
     * {@inheritdoc}
140
     */
141 1
    public function without($key)
142
    {
143 1
        $attributes = clone $this;
144
145 1
        return $attributes->delete($key);
146
    }
147
148
    /**
149
     * {@inheritdoc}
150
     */
151 1
    public function replace($key, $value, $replacement)
152
    {
153 1
        if (!isset($this->storage[$key])) {
154 1
            return $this;
155
        }
156
157 1
        if (!$this->contains($key, $value)) {
158 1
            return $this;
159
        }
160
161 1
        $this->storage[$key]->remove($value);
162 1
        foreach ($this->normalizeValue($replacement) as $replacement_value) {
163 1
            $this->storage[$key]->append($replacement_value);
164
        }
165
166 1
        return $this;
167
    }
168
169
    /**
170
     * {@inheritdoc}
171
     */
172 1
    public function merge(array $data = array())
173
    {
174 1
        foreach ($data as $key => $value) {
175
            $this->storage += array(
176 1
                $key => ($this->attributeFactory)::build($key)
177
            );
178
179 1
            $this->storage[$key]->merge(
180 1
                $this->normalizeValue($value)
181
            );
182
        }
183
184 1
        return $this;
185
    }
186
187
    /**
188
     * {@inheritdoc}
189
     */
190 1
    public function exists($key, $value = null)
191
    {
192 1
        if (!isset($this->storage[$key])) {
193 1
            return false;
194
        }
195
196 1
        if (null !== $value) {
197 1
            return $this->contains($key, $value);
198
        }
199
200 1
        return true;
201
    }
202
203
    /**
204
     * {@inheritdoc}
205
     */
206 3
    public function contains($key, $value)
207
    {
208 3
        if (!isset($this->storage[$key])) {
209 1
            return false;
210
        }
211
212 3
        return $this->storage[$key]->contains($value);
213
    }
214
215
    /**
216
     * {@inheritdoc}
217
     */
218 4
    public function __toString()
219
    {
220 4
        return $this->render();
221
    }
222
223
    /**
224
     * {@inheritdoc}
225
     */
226 15
    public function render()
227
    {
228 15
        $attributes = implode(' ', $this->prepareValues());
229
230 15
        return $attributes ? ' ' . $attributes : '';
231
    }
232
233
    /**
234
     * {@inheritdoc}
235
     */
236 2
    public function toArray()
237
    {
238 2
        $attributes = $this->storage;
239
240
        // If empty, just return an empty array.
241 2
        if (empty($attributes)) {
242 2
            return array();
243
        }
244
245 1
        $result = [];
246
247 1
        foreach ($this->prepareValues() as $attribute) {
248 1
            $result[$attribute->getName()] = $attribute->getValueAsArray();
249
        }
250
251 1
        return $result;
252
    }
253
254
    /**
255
     * {@inheritdoc}
256
     */
257 1
    public function getStorage()
258
    {
259 1
        return $this->storage;
260
    }
261
262
    /**
263
     * {@inheritdoc}
264
     */
265 1
    public function getIterator()
266
    {
267 1
        return new \ArrayIterator($this->toArray());
268
    }
269
270
    /**
271
     * {@inheritdoc}
272
     */
273 1
    public function count()
274
    {
275 1
        return count($this->storage);
276
    }
277
278
    /**
279
     * Returns all storage elements as an array.
280
     *
281
     * @return \drupol\htmltag\AttributeInterface[]
282
     *   An associative array of attributes.
283
     */
284 16
    private function prepareValues()
285
    {
286 16
        $attributes = $this->storage;
287
288
        // If empty, just return an empty array.
289 16
        if (empty($attributes)) {
290 5
            return array();
291
        }
292
293
        // Sort the attributes.
294 14
        ksort($attributes);
295
296 14
        $result = [];
297
298 14
        foreach ($attributes as $attribute_name => $attribute) {
299
            switch ($attribute_name) {
300 14
                case 'class':
301 12
                    $classes = $attribute->getValueAsArray();
302 12
                    asort($classes);
303 12
                    $result[$attribute->getName()] = $attribute->set($classes);
304 12
                    break;
305
306
                default:
307 14
                    $result[$attribute->getName()] = $attribute;
308
            }
309
        }
310
311 14
        return $result;
312
    }
313
314
    /**
315
     * Normalize a value.
316
     *
317
     * @param mixed $value
318
     *  The value to normalize.
319
     *
320
     * @return array
321
     *   The value normalized.
322
     */
323 4
    private function normalizeValue($value)
324
    {
325 4
        return $this->ensureFlatArray($value);
326
    }
327
328
    /**
329
     * Todo.
330
     *
331
     * @param mixed $value
332
     *   Todo.
333
     *
334
     * @return array
335
     *   The array, flattened.
336
     */
337 4 View Code Duplication
    private function ensureFlatArray($value)
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...
338
    {
339 4
        switch (gettype($value)) {
340 4
            case 'string':
341 4
                $return = explode(
342 4
                    ' ',
343 4
                    $value
344
                );
345 4
                break;
346
347 1
            case 'array':
348 1
                $flat_array = iterator_to_array(
349 1
                    new \RecursiveIteratorIterator(
350 1
                        new \RecursiveArrayIterator(
351 1
                            $value
352
                        )
353
                    ),
354 1
                    false
355
                );
356
357 1
                $return = [];
358 1
                foreach ($flat_array as $item) {
359 1
                    $return = array_merge(
360 1
                        $return,
361 1
                        $this->normalizeValue($item)
362
                    );
363
                }
364 1
                break;
365
366 1
            case 'double':
367 1
            case 'integer':
368
                $return = array($value);
369
                break;
370 1
            case 'object':
371 1
            case 'boolean':
372 1
            case 'resource':
373 1
            case 'NULL':
374
            default:
375 1
                $return = array();
376 1
                break;
377
        }
378
379 4
        return array_filter($return, 'is_string');
380
    }
381
}
382