AbstractAttributes::merge()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 3

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 4
c 1
b 0
f 0
nc 3
nop 1
dl 0
loc 9
ccs 3
cts 3
cp 1
crap 3
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace drupol\htmltag\Attributes;
6
7
use ArrayIterator;
8
use drupol\htmltag\AbstractBaseHtmlTagObject;
9
use drupol\htmltag\Attribute\AttributeFactoryInterface;
10
11
use function array_key_exists;
12
13
abstract class AbstractAttributes extends AbstractBaseHtmlTagObject implements AttributesInterface
14
{
15
    /**
16
     * The attribute factory.
17
     *
18
     * @var \drupol\htmltag\Attribute\AttributeFactoryInterface
19
     */
20
    private $attributeFactory;
21
22
    /**
23
     * Stores the attribute data.
24
     *
25
     * @var array<string, AttributesInterface>
26
     */
27
    private $storage = [];
28
29
    /**
30
     * Attributes constructor.
31
     *
32
     * @param \drupol\htmltag\Attribute\AttributeFactoryInterface $attributeFactory
33
     *   The attribute factory
34 41
     * @param mixed[] $data
35
     *   The input attributes
36 41
     */
37 41
    public function __construct(AttributeFactoryInterface $attributeFactory, array $data = [])
38 41
    {
39
        $this->attributeFactory = $attributeFactory;
40
        $this->import($data);
41
    }
42
43 1
    public function __toString(): string
44
    {
45 1
        return $this->render();
46
    }
47
48
    public function append($key, ...$values): AttributesInterface
49
    {
50
        $this->storage += [
51 16
            $key => $this->attributeFactory->getInstance($key),
52
        ];
53
54 16
        $this->storage[$key]->append($values);
55
56
        return $this;
57 16
    }
58
59 16
    public function contains(string $key, ...$values): bool
60
    {
61
        return $this->exists($key) && $this->storage[$key]->contains(...$values);
62
    }
63
64
    public function count()
65 3
    {
66
        return $this->getStorage()->count();
67 3
    }
68
69
    public function delete(string ...$keys): AttributesInterface
70
    {
71
        foreach ($this->ensureStrings($this->ensureFlatArray($keys)) as $key) {
72
            unset($this->storage[$key]);
73 1
        }
74
75 1
        return $this;
76
    }
77
78
    public function exists(string $key, ...$values): bool
79
    {
80
        if (!isset($this->storage[$key])) {
81 2
            return false;
82
        }
83 2
84 2
        return [] === $values ?
85
            true :
86
            $this->contains($key, $values);
87 2
    }
88
89
    public function getIterator()
90
    {
91
        return $this->getStorage();
92
    }
93 3
94
    public function getStorage(): ArrayIterator
95 3
    {
96 3
        return new ArrayIterator(array_values($this->preprocess($this->storage)));
97
    }
98
99 3
    public function getValuesAsArray(): array
100 3
    {
101 3
        $values = [];
102
103
        foreach ($this->getStorage() as $attribute) {
104
            $values[$attribute->getName()] = $attribute->getValuesAsArray();
105
        }
106
107 1
        return $values;
108
    }
109 1
110
    public function import($data): AttributesInterface
111
    {
112
        foreach ($data as $key => $value) {
113
            $this->storage[$key] = $this->attributeFactory->getInstance($key, $value);
114
        }
115 30
116
        return $this;
117 30
    }
118
119
    public function merge(array ...$dataset): AttributesInterface
120
    {
121
        foreach ($dataset as $data) {
122
            foreach ($data as $key => $value) {
123 3
                $this->append($key, $value);
124
            }
125 3
        }
126
127 3
        return $this;
128 3
    }
129
130
    /**
131 3
     * @param int $key
132
     *
133
     * @return bool
134
     */
135
    public function offsetExists($key)
136
    {
137 41
        return isset($this->storage[$key]);
138
    }
139 41
140 8
    /**
141
     * @param int $key
142
     *
143 41
     * @return mixed
144
     */
145
    public function offsetGet($key)
146
    {
147
        $this->storage += [
148
            $key => $this->attributeFactory->getInstance((string) $key),
149 1
        ];
150
151 1
        return $this->storage[$key];
152 1
    }
153 1
154
    /**
155
     * @param int $key
156
     * @param mixed $value
157 1
     *
158
     * @return void
159
     */
160
    public function offsetSet($key, $value)
161
    {
162
        $this->storage[$key] = $this->attributeFactory->getInstance((string) $key, $value);
163 2
    }
164
165 2
    /**
166
     * @param int $key
167
     *
168
     * @return void
169
     */
170
    public function offsetUnset($key)
171 4
    {
172
        unset($this->storage[$key]);
173
    }
174 4
175
    public function preprocess(array $values, array $context = []): array
176
    {
177 4
        return $values;
178
    }
179
180
    public function remove(string $key, ...$values): AttributesInterface
181
    {
182
        if (array_key_exists($key, $this->storage)) {
183 1
            $this->storage[$key]->remove(...$values);
184
        }
185 1
186 1
        return $this;
187
    }
188
189
    public function render(): string
190
    {
191 1
        $output = '';
192
193 1
        foreach ($this->getStorage() as $attribute) {
194 1
            $output .= ' ' . $attribute;
195
        }
196
197
        return $output;
198
    }
199 30
200
    public function replace(string $key, string $value, string ...$replacements): AttributesInterface
201 30
    {
202
        if (!$this->contains($key, $value)) {
203
            return $this;
204
        }
205
206
        $this->storage[$key]->replace($value, ...$replacements);
207 2
208
        return $this;
209 2
    }
210 1
211
    public function serialize()
212
    {
213 2
        return serialize([
214
            'storage' => $this->getValuesAsArray(),
215
        ]);
216
    }
217
218
    public function set(string $key, ...$value): AttributesInterface
219 24
    {
220
        $this->storage[$key] = $this->attributeFactory->getInstance($key, $value);
221 24
222
        return $this;
223 24
    }
224 19
225
    public function unserialize($serialized)
226
    {
227 24
        $unserialize = unserialize($serialized);
228
        $attributeFactory = $this->attributeFactory;
229
230
        $this->storage = array_map(
231
            static function ($key, $values) use ($attributeFactory) {
232
                return $attributeFactory::build((string) $key, $values);
233 1
            },
234
            array_keys($unserialize['storage']),
235 1
            array_values($unserialize['storage'])
236 1
        );
237
    }
238
239 1
    public function without(string ...$keys): AttributesInterface
240
    {
241 1
        $attributes = clone $this;
242
243
        return $attributes->delete(...$keys);
244
    }
245
}
246