8000 Implement no-rel and multiple-rel attributes · symfony/symfony@d0308a2 · GitHub
[go: up one dir, main page]

Skip to content

Commit d0308a2

Browse files
committed
Implement no-rel and multiple-rel attributes
1 parent 199000d commit d0308a2

File tree

2 files changed

+30
-11
lines changed

2 files changed

+30
-11
lines changed

src/Symfony/Component/WebLink/HttpHeaderParser.php

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ public function parse(string|array $headers): EvolvableLinkProviderInterface
4848

4949
$params = [];
5050
if (preg_match_all(self::PARAM_PATTERN, $paramsString, $paramMatches, \PREG_SET_ORDER)) {
51+
$rels = null;
5152
foreach ($paramMatches as $pm) {
5253
$key = $pm[1];
5354
$value = match (true) {
@@ -57,7 +58,10 @@ public function parse(string|array $headers): EvolvableLinkProviderInterface
5758
default => true,
5859
};
5960

60-
if (is_array($params[$key] ?? null)) {
61+
if ($key === 'rel') {
62+
// Only the first occurrence of the "rel" attribute is read
63+
$rels ??= $value === true ? [] : preg_split('/\s+/', $value, 0,\PREG_SPLIT_NO_EMPTY);
64+
} elseif (is_array($params[$key] ?? null)) {
6165
$params[$key][] = $value;
6266
} elseif (isset($params[$key])) {
6367
$params[$key] = [$params[$key], $value];
@@ -67,15 +71,9 @@ public function parse(string|array $headers): EvolvableLinkProviderInterface
6771
}
6872
}
6973

70-
if (!isset($params['rel'])) {
71-
continue;
72-
}
73-
$rels = preg_split('/\s+/', trim($params['rel']));
74-
unset($params['rel']);
75-
7674
$link = new Link(null, $href);
77-
foreach ($rels as $r) {
78-
$link = $link->withRel($r);
75+
foreach ($rels ?? [] as $rel) {
76+
$link = $link->withRel($rel);
7977
}
8078
foreach ($params as $k => $v) {
8179
$link = $link->withAttribute($k, $v);

src/Symfony/Component/WebLink/Tests/HttpHeaderParserTest.php

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,32 +60,53 @@ public function testParseEmpty()
6060

6161
/** @dataProvider provideHeaderParsingCases */
6262
#[DataProvider('provideHeaderParsingCases')]
63-
public function testParseVariousAttributes(string $header, array $expectedAttributes)
63+
public function testParseVariousAttributes(string $header, array $expectedRels, array $expectedAttributes)
6464
{
6565
$parser = new HttpHeaderParser();
6666
$links = $parser->parse($header)->getLinks();
6767

6868
self::assertCount(1, $links);
69-
self::assertSame(['alternate'], $links[0]->getRels());
7069
self::assertSame('/foo', $links[0]->getHref());
70+
self::assertSame($expectedRels, $links[0]->getRels());
7171
self::assertSame($expectedAttributes, $links[0]->getAttributes());
7272
}
7373

7474
public static function provideHeaderParsingCases()
7575
{
7676
yield 'double_quotes_in_attribute_value' => [
7777
'</foo>; rel="alternate"; title="\"escape me\" \"already escaped\" \"\"\""',
78+
['alternate'],
7879
['title' => '"escape me" "already escaped" """'],
7980
];
8081

8182
yield 'unquoted_attribute_value' => [
8283
'</foo>; rel=alternate; type=text/html',
84+
['alternate'],
8385
['type' => 'text/html'],
8486
];
8587

8688
yield 'attribute_with_punctuation' => [
8789
'</foo>; rel="alternate"; title=">; hello, world; test:case"',
90+
['alternate'],
8891
['title' => '>; hello, world; test:case'],
8992
];
93+
94+
yield 'no_rel' => [
95+
'</foo>; type=text/html',
96+
[],
97+
['type' => 'text/html'],
98+
];
99+
100+
yield 'empty_rel' => [
101+
'</foo>; rel',
102+
[],
103+
[],
104+
];
105+
106+
yield 'multiple_rel_attributes_get_first' => [
107+
'</foo>; rel="alternate" rel="next"',
108+
['alternate'],
109+
[],
110+
];
90111
}
91112
}

0 commit comments

Comments
 (0)
0