Completed
Push — master ( 51d4a3...e0bbf9 )
by Pol
01:46
created

Attributes::offsetSet()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 2
crap 1
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 View Code Duplication
    public function remove($key, $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...
114
    {
115 2
        if (!isset($this->storage[$key])) {
116 1
            return $this;
117
        }
118
119 1
        $this->storage[$key]->remove($value);
120
121 1
        return $this;
122
    }
123
124
    /**
125
     * {@inheritdoc}
126
     */
127 2
    public function delete($name)
128
    {
129 2
        foreach (ArrayUtils::normalizeValue($name) as $attribute_name) {
130 2
            unset($this->storage[$attribute_name]);
131
        }
132
133 2
        return $this;
134
    }
135
136
    /**
137
     * {@inheritdoc}
138
     */
139 1
    public function without($key)
140
    {
141 1
        $attributes = clone $this;
142
143 1
        return $attributes->delete($key);
144
    }
145
146
    /**
147
     * {@inheritdoc}
148
     */
149 1
    public function replace($key, $value, $replacement)
150
    {
151 1
        if (!isset($this->storage[$key])) {
152 1
            return $this;
153
        }
154
155 1
        if (!$this->contains($key, $value)) {
156 1
            return $this;
157
        }
158
159 1
        $this->storage[$key]->remove($value);
160 1
        $this->storage[$key]->append($replacement);
0 ignored issues
show
Bug introduced by
It seems like $replacement defined by parameter $replacement on line 149 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...
161
162 1
        return $this;
163
    }
164
165
    /**
166
     * {@inheritdoc}
167
     */
168 1
    public function merge(array $data = array())
169
    {
170 1
        foreach ($data as $key => $value) {
171
            $this->storage += array(
172 1
                $key => ($this->attributeFactory)::build($key)
173
            );
174
175 1
            $this->storage[$key]->merge((array) $value);
176
        }
177
178 1
        return $this;
179
    }
180
181
    /**
182
     * {@inheritdoc}
183
     */
184 1
    public function exists($key, $value = null)
185
    {
186 1
        if (!isset($this->storage[$key])) {
187 1
            return false;
188
        }
189
190 1
        if (null !== $value) {
191 1
            return $this->contains($key, $value);
192
        }
193
194 1
        return true;
195
    }
196
197
    /**
198
     * {@inheritdoc}
199
     */
200 3 View Code Duplication
    public function contains($key, $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...
201
    {
202 3
        if (!isset($this->storage[$key])) {
203 1
            return false;
204
        }
205
206 3
        return $this->storage[$key]->contains($value);
207
    }
208
209
    /**
210
     * {@inheritdoc}
211
     */
212 4
    public function __toString()
213
    {
214 4
        return $this->render();
215
    }
216
217
    /**
218
     * {@inheritdoc}
219
     */
220 15
    public function render()
221
    {
222 15
        $attributes = implode(' ', $this->prepareValues());
223
224 15
        return $attributes ? ' ' . $attributes : '';
225
    }
226
227
    /**
228
     * {@inheritdoc}
229
     */
230 2
    public function toArray()
231
    {
232 2
        $attributes = $this->storage;
233
234
        // If empty, just return an empty array.
235 2
        if (empty($attributes)) {
236 2
            return array();
237
        }
238
239 1
        $result = [];
240
241 1
        foreach ($this->prepareValues() as $attribute) {
242 1
            $result[$attribute->getName()] = $attribute->getValueAsArray();
243
        }
244
245 1
        return $result;
246
    }
247
248
    /**
249
     * {@inheritdoc}
250
     */
251 1
    public function getStorage()
252
    {
253 1
        return $this->storage;
254
    }
255
256
    /**
257
     * {@inheritdoc}
258
     */
259 1
    public function getIterator()
260
    {
261 1
        return new \ArrayIterator($this->toArray());
262
    }
263
264
    /**
265
     * {@inheritdoc}
266
     */
267 1
    public function count()
268
    {
269 1
        return count($this->storage);
270
    }
271
272
    /**
273
     * Returns all storage elements as an array.
274
     *
275
     * @return \drupol\htmltag\AttributeInterface[]
276
     *   An associative array of attributes.
277
     */
278 16
    private function prepareValues()
279
    {
280 16
        $attributes = $this->storage;
281
282
        // If empty, just return an empty array.
283 16
        if (empty($attributes)) {
284 5
            return array();
285
        }
286
287
        // Sort the attributes.
288 14
        ksort($attributes);
289
290 14
        $result = [];
291
292 14
        foreach ($attributes as $attribute_name => $attribute) {
293
            switch ($attribute_name) {
294 14
                case 'class':
295 12
                    $classes = $attribute->getValueAsArray();
296 12
                    asort($classes);
297 12
                    $result[$attribute->getName()] = $attribute->set($classes);
298 12
                    break;
299
300
                default:
301 14
                    $result[$attribute->getName()] = $attribute;
302
            }
303
        }
304
305 14
        return $result;
306
    }
307
}
308