Skip to content

Commit 08ba905

Browse files
committed
Retrofit add and adapt Parser implementation from gapple
1 parent 9678d25 commit 08ba905

File tree

6 files changed

+245
-133
lines changed

6 files changed

+245
-133
lines changed

src/Dictionary.php

Lines changed: 1 addition & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -63,58 +63,7 @@ public static function fromPairs(iterable $pairs = []): self
6363
*/
6464
public static function fromHttpValue(string $httpValue): self
6565
{
66-
$instance = new self();
67-
$httpValue = trim($httpValue, ' ');
68-
if ('' === $httpValue) {
69-
return $instance;
70-
}
71-
72-
if (1 === preg_match("/[^\x20-\x7E\t]/", $httpValue) || str_starts_with($httpValue, "\t")) {
73-
throw new SyntaxError("The HTTP textual representation `$httpValue` for dictionary contains invalid characters.");
74-
}
75-
76-
$parser = fn (string $element): Item|InnerList => str_starts_with($element, '(')
77-
? InnerList::fromHttpValue($element)
78-
: Item::fromHttpValue($element);
79-
80-
return array_reduce(explode(',', $httpValue), function (self $instance, string $element) use ($parser): self {
81-
[$key, $value] = self::extractPair($element);
82-
83-
$instance->set($key, $parser($value));
84-
85-
return $instance;
86-
}, $instance);
87-
}
88-
89-
/**
90-
* Extracts a dictionary pair from an HTTP textual representation.
91-
*
92-
* @throws SyntaxError
93-
*
94-
* @return array{0:string, 1:string}
95-
*/
96-
private static function extractPair(string $pair): array
97-
{
98-
$pair = trim($pair);
99-
100-
if ('' === $pair) {
101-
throw new SyntaxError('The HTTP textual representation for a dictionary pair can not be empty.');
102-
}
103-
104-
if (1 !== preg_match('/^(?<key>[a-z*][a-z0-9.*_-]*)(=)?(?<value>.*)/', $pair, $found)) {
105-
throw new SyntaxError("The HTTP textual representation `$pair` for a dictionary pair contains invalid characters.");
106-
}
107-
108-
if (rtrim($found['key']) !== $found['key'] || ltrim($found['value']) !== $found['value']) {
109-
throw new SyntaxError("The HTTP textual representation `$pair` for a dictionary pair contains invalid characters.");
110-
}
111-
112-
$found['value'] = trim($found['value']);
113-
if ('' === $found['value'] || str_starts_with($found['value'], ';')) {
114-
$found['value'] = '?1'.$found['value'];
115-
}
116-
117-
return [$found['key'], $found['value']];
66+
return Parser::parseDictionary($httpValue);
11867
}
11968

12069
public function toHttpValue(): string

src/DictionaryTest.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,4 +185,16 @@ public function it_can_merge_without_argument_and_not_throw(): void
185185
$instance->merge();
186186
self::assertCount(1, $instance);
187187
}
188+
189+
/**
190+
* @test
191+
*/
192+
public function it_can_handle_string_with_comma(): void
193+
{
194+
$expected = 'a=foobar;test="bar, baz", b=toto';
195+
$instance = Dictionary::fromHttpValue($expected);
196+
197+
self::assertSame($expected, $instance->toHttpValue());
198+
self::assertCount(2, $instance);
199+
}
188200
}

src/InnerList.php

Lines changed: 0 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -35,61 +35,6 @@ public static function fromElements(iterable $elements = [], iterable $parameter
3535
return new self(Parameters::fromAssociative($parameters), ...$newElements);
3636
}
3737

38-
/**
39-
* Returns an instance from an HTTP textual representation.
40-
*
41-
* @see https://www.rfc-editor.org/rfc/rfc8941.html#section-3.1.1
42-
*/
43-
public static function fromHttpValue(string $httpValue): self
44-
{
45-
$field = trim($httpValue);
46-
47-
if (1 !== preg_match("/^\((?<content>.*)\)(?<parameters>[^,]*)/", $field, $found)) {
48-
throw new SyntaxError("The HTTP textual representation `$httpValue` for a inner list contains invalid characters.");
49-
}
50-
51-
if ('' !== $found['parameters'] && !str_starts_with($found['parameters'], ';')) {
52-
throw new SyntaxError("The HTTP textual representation `$httpValue` for a inner list contains invalid characters.");
53-
}
54-
55-
/** @var string $content */
56-
$content = preg_replace('/[ ]+/', ' ', $found['content']);
57-
$content = trim($content);
58-
59-
$components = array_reduce(explode(' ', $content), function (array $components, string $component): array {
60-
if ([] === $components) {
61-
return [$component];
62-
}
63-
64-
$lastIndex = count($components) - 1;
65-
66-
if (str_starts_with($component, ';')) {
67-
$components[$lastIndex] .= $component;
68-
69-
return $components;
70-
}
71-
72-
$lastAddition = $components[$lastIndex];
73-
if (str_ends_with($lastAddition, ';')) {
74-
$components[$lastIndex] .= $component;
75-
76-
return $components;
77-
}
78-
79-
$components[] = $component;
80-
81-
return $components;
82-
}, []);
83-
84-
return new self(
85-
Parameters::fromHttpValue($found['parameters']),
86-
...array_filter(array_map(
87-
fn (string $field): Item|null => '' === $field ? null : Item::fromHttpValue($field),
88-
$components
89-
))
90-
);
91-
}
92-
9338
public function toHttpValue(): string
9439
{
9540
$returnArray = array_map(fn (Item $value): string => $value->toHttpValue(), $this->elements);

src/InnerListTest.php

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -61,16 +61,6 @@ public function it_can_add_or_remove_elements(): void
6161
self::assertTrue($instance->isEmpty());
6262
}
6363

64-
/**
65-
* @test
66-
*/
67-
public function it_fails_to_instantiate_with_wrong_parameters_in_field(): void
68-
{
69-
$this->expectException(SyntaxError::class);
70-
71-
InnerList::fromHttpValue('(1 42)foobar');
72-
}
73-
7464
/**
7565
* @test
7666
*/

src/OrderedList.php

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -41,22 +41,7 @@ public static function fromElements(iterable $elements = []): self
4141
*/
4242
public static function fromHttpValue(string $httpValue): self
4343
{
44-
$httpValue = trim($httpValue, ' ');
45-
if ('' === $httpValue) {
46-
return new self();
47-
}
48-
49-
$parser = fn (string $element): Item|InnerList => str_starts_with($element, '(')
50-
? InnerList::fromHttpValue($element)
51-
: Item::fromHttpValue($element);
52-
53-
$reducer = function (self $carry, string $element) use ($parser): self {
54-
$carry->push($parser(trim($element, " \t")));
55-
56-
return $carry;
57-
};
58-
59-
return array_reduce(explode(',', $httpValue), $reducer, new self());
44+
return Parser::parseList($httpValue);
6045
}
6146

6247
public function toHttpValue(): string

0 commit comments

Comments
 (0)