Passed
Branch master (e894a3)
by Melech
15:39 queued 01:19
created

Value   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 185
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 31
c 1
b 0
f 0
dl 0
loc 185
rs 10
wmc 20
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Valkyrja Framework package.
7
 *
8
 * (c) Melech Mizrachi <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Valkyrja\Http\Message\Header\Value;
15
16
use Valkyrja\Http\Message\Header\Exception\UnsupportedOffsetSetException;
17
use Valkyrja\Http\Message\Header\Exception\UnsupportedOffsetUnsetException;
18
use Valkyrja\Http\Message\Header\Value\Component\Component as HeaderPart;
19
use Valkyrja\Http\Message\Header\Value\Component\Contract\Component;
20
use Valkyrja\Http\Message\Header\Value\Contract\Value as Contract;
21
22
use function array_filter;
23
use function array_map;
24
use function array_merge;
25
use function count;
26
use function explode;
27
use function implode;
28
use function is_string;
29
30
/**
31
 * Class Value.
32
 *
33
 * @author Melech Mizrachi
34
 */
35
class Value implements Contract
36
{
37
    /**
38
     * Deliminator to use for value components.
39
     *
40
     * @var non-empty-string
41
     */
42
    protected const string DELIMINATOR = ';';
0 ignored issues
show
Bug introduced by
A parse error occurred: Syntax error, unexpected T_STRING, expecting '=' on line 42 at column 27
Loading history...
43
44
    /**
45
     * @var Component[]
46
     */
47
    protected array $components = [];
48
49
    /**
50
     * The position during iteration.
51
     *
52
     * @var int
53
     */
54
    protected int $position = 0;
55
56
    /**
57
     * @param Component|string ...$components
58
     */
59
    public function __construct(Component|string ...$components)
60
    {
61
        $this->components = $this->mapToPart(...$components);
62
    }
63
64
    /**
65
     * @inheritDoc
66
     */
67
    public static function fromValue(string $value): static
68
    {
69
        $parts = [$value];
70
71
        if (str_contains($value, static::DELIMINATOR)) {
72
            $parts = explode(static::DELIMINATOR, $value);
73
        }
74
75
        return new static(...$parts);
76
    }
77
78
    /**
79
     * @inheritDoc
80
     */
81
    public function getComponents(): array
82
    {
83
        return $this->components;
84
    }
85
86
    /**
87
     * @inheritDoc
88
     */
89
    public function withComponents(Component|string ...$components): static
90
    {
91
        $new = clone $this;
92
93
        $new->components = $this->mapToPart(...$components);
94
95
        return $new;
96
    }
97
98
    /**
99
     * @inheritDoc
100
     */
101
    public function withAddedComponents(Component|string ...$components): static
102
    {
103
        $new = $this->withComponents(...$components);
104
105
        $new->components = array_merge($this->components, $new->components);
106
107
        return $new;
108
    }
109
110
    /**
111
     * @inheritDoc
112
     */
113
    public function jsonSerialize(): string
114
    {
115
        return $this->__toString();
116
    }
117
118
    /**
119
     * @inheritDoc
120
     */
121
    public function __toString(): string
122
    {
123
        $filteredParts = array_filter($this->components, static fn (Component $component): bool => $component->__toString() !== '');
124
125
        return implode(';', $filteredParts);
126
    }
127
128
    /**
129
     * @inheritDoc
130
     */
131
    public function offsetExists(mixed $offset): bool
132
    {
133
        return isset($this->components[$offset]);
134
    }
135
136
    /**
137
     * @inheritDoc
138
     */
139
    public function offsetGet(mixed $offset): Component
140
    {
141
        return $this->components[$offset];
142
    }
143
144
    /**
145
     * @inheritDoc
146
     */
147
    public function offsetSet(mixed $offset, mixed $value): void
148
    {
149
        throw new UnsupportedOffsetSetException('Use withValues or withAddedValues');
150
    }
151
152
    /**
153
     * @inheritDoc
154
     */
155
    public function offsetUnset(mixed $offset): void
156
    {
157
        throw new UnsupportedOffsetUnsetException('Use withValues or withAddedValues');
158
    }
159
160
    /**
161
     * @inheritDoc
162
     */
163
    public function count(): int
164
    {
165
        return count($this->components);
166
    }
167
168
    /**
169
     * @inheritDoc
170
     */
171
    public function current(): Component
172
    {
173
        return $this->components[$this->position];
174
    }
175
176
    /**
177
     * @inheritDoc
178
     */
179
    public function next(): void
180
    {
181
        $this->position++;
182
    }
183
184
    /**
185
     * @inheritDoc
186
     */
187
    public function key(): int
188
    {
189
        return $this->position;
190
    }
191
192
    /**
193
     * @inheritDoc
194
     */
195
    public function valid(): bool
196
    {
197
        return isset($this->components[$this->position]);
198
    }
199
200
    /**
201
     * @inheritDoc
202
     */
203
    public function rewind(): void
204
    {
205
        $this->position = 0;
206
    }
207
208
    /**
209
     * Map string parts to Part objects.
210
     *
211
     * @param Component|string ...$parts
212
     *
213
     * @return Component[]
214
     */
215
    protected function mapToPart(Component|string ...$parts): array
216
    {
217
        return array_map(
218
            static fn (Component|string $part): Component => is_string($part) ? HeaderPart::fromValue($part) : $part,
219
            $parts
220
        );
221
    }
222
}
223