AbstractAttribute::setBoolean()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2

Importance

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