Skip to content

Commit 034ff81

Browse files
[WebLink] implement PSR-13 directly
1 parent d21728d commit 034ff81

File tree

8 files changed

+445
-5
lines changed

8 files changed

+445
-5
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
4.4.0
5+
-----
6+
7+
* implement PSR-13 directly
8+
49
3.3.0
510
-----
611

GenericLinkProvider.php

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\WebLink;
13+
14+
use Psr\Link\EvolvableLinkProviderInterface;
15+
use Psr\Link\LinkInterface;
16+
17+
class GenericLinkProvider implements EvolvableLinkProviderInterface
18+
{
19+
/**
20+
* @var LinkInterface[]
21+
*/
22+
private $links = [];
23+
24+
/**
25+
* @param LinkInterface[] $links
26+
*/
27+
public function __construct(array $links = [])
28+
{
29+
$that = $this;
30+
31+
foreach ($links as $link) {
32+
$that = $that->withLink($link);
33+
}
34+
35+
$this->links = $that->links;
36+
}
37+
38+
/**
39+
* {@inheritdoc}
40+
*/
41+
public function getLinks(): array
42+
{
43+
return array_values($this->links);
44+
}
45+
46+
/**
47+
* {@inheritdoc}
48+
*/
49+
public function getLinksByRel($rel): array
50+
{
51+
$links = [];
52+
53+
foreach ($this->links as $link) {
54+
if (\in_array($rel, $link->getRels())) {
55+
$links[] = $link;
56+
}
57+
}
58+
59+
return $links;
60+
}
61+
62+
/**
63+
* {@inheritdoc}
64+
*/
65+
public function withLink(LinkInterface $link)
66+
{
67+
$that = clone $this;
68+
$that->links[spl_object_id($link)] = $link;
69+
70+
return $that;
71+
}
72+
73+
/**
74+
* {@inheritdoc}
75+
*/
76+
public function withoutLink(LinkInterface $link)
77+
{
78+
$that = clone $this;
79+
unset($that->links[spl_object_id($link)]);
80+
81+
return $that;
82+
}
83+
}

Link.php

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\WebLink;
13+
14+
use Psr\Link\EvolvableLinkInterface;
15+
16+
class Link implements EvolvableLinkInterface
17+
{
18+
// Relations defined in https://www.w3.org/TR/html5/links.html#links and applicable on link elements
19+
public const REL_ALTERNATE = 'alternate';
20+
public const REL_AUTHOR = 'author';
21+
public const REL_HELP = 'help';
22+
public const REL_ICON = 'icon';
23+
public const REL_LICENSE = 'license';
24+
public const REL_SEARCH = 'search';
25+
public const REL_STYLESHEET = 'stylesheet';
26+
public const REL_NEXT = 'next';
27+
public const REL_PREV = 'prev';
28+
29+
// Relation defined in https://www.w3.org/TR/preload/
30+
public const REL_PRELOAD = 'preload';
31+
32+
// Relations defined in https://www.w3.org/TR/resource-hints/
33+
public const REL_DNS_PREFETCH = 'dns-prefetch';
34+
public const REL_PRECONNECT = 'preconnect';
35+
public const REL_PREFETCH = 'prefetch';
36+
public const REL_PRERENDER = 'prerender';
37+
38+
// Extra relations
39+
public const REL_MERCURE = 'mercure';
40+
41+
private $href = '';
42+
43+
/**
44+
* @var string[]
45+
*/
46+
private $rel = [];
47+
48+
/**
49+
* @var string[]
50+
*/
51+
private $attributes = [];
52+
53+
public function __construct(string $rel = null, string $href = '')
54+
{
55+
if (null !== $rel) {
56+
$this->rel[$rel] = $rel;
57+
}
58+
$this->href = $href;
59+
}
60+
61+
/**
62+
* {@inheritdoc}
63+
*/
64+
public function getHref(): string
65+
{
66+
return $this->href;
67+
}
68+
69+
/**
70+
* {@inheritdoc}
71+
*/
72+
public function isTemplated(): bool
73+
{
74+
return $this->hrefIsTemplated($this->href);
75+
}
76+
77+
/**
78+
* {@inheritdoc}
79+
*/
80+
public function getRels(): array
81+
{
82+
return array_values($this->rel);
83+
}
84+
85+
/**
86+
* {@inheritdoc}
87+
*/
88+
public function getAttributes(): array
89+
{
90+
return $this->attributes;
91+
}
92+
93+
/**
94+
* {@inheritdoc}
95+
*/
96+
public function withHref($href)
97+
{
98+
$that = clone $this;
99+
$that->href = $href;
100+
$that->templated = $this->hrefIsTemplated($href);
101+
102+
return $that;
103+
}
104+
105+
/**
106+
* {@inheritdoc}
107+
*/
108+
public function withRel($rel)
109+
{
110+
$that = clone $this;
111+
$that->rel[$rel] = $rel;
112+
113+
return $that;
114+
}
115+
116+
/**
117+
* {@inheritdoc}
118+
*/
119+
public function withoutRel($rel)
120+
{
121+
$that = clone $this;
122+
unset($that->rel[$rel]);
123+
124+
return $that;
125+
}
126+
127+
/**
128+
* {@inheritdoc}
129+
*/
130+
public function withAttribute($attribute, $value)
131+
{
132+
$that = clone $this;
133+
$that->attributes[$attribute] = $value;
134+
135+
return $that;
136+
}
137+
138+
/**
139+
* {@inheritdoc}
140+
*/
141+
public function withoutAttribute($attribute)
142+
{
143+
$that = clone $this;
144+
unset($that->attributes[$attribute]);
145+
146+
return $that;
147+
}
148+
149+
private function hrefIsTemplated(string $href): bool
150+
{
151+
return false !== strpos($href, '{') || false !== strpos($href, '}');
152+
}
153+
}

Tests/EventListener/AddLinkHeaderListenerTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@
1111

1212
namespace Symfony\Component\WebLink\Tests\EventListener;
1313

14-
use Fig\Link\GenericLinkProvider;
15-
use Fig\Link\Link;
1614
use PHPUnit\Framework\TestCase;
1715
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
1816
use Symfony\Component\HttpFoundation\Request;
1917
use Symfony\Component\HttpFoundation\Response;
2018
use Symfony\Component\HttpKernel\Event\ResponseEvent;
2119
use Symfony\Component\HttpKernel\KernelEvents;
2220
use Symfony\Component\WebLink\EventListener\AddLinkHeaderListener;
21+
use Symfony\Component\WebLink\GenericLinkProvider;
22+
use Symfony\Component\WebLink\Link;
2323

2424
/**
2525
* @author Kévin Dunglas <[email protected]>

Tests/GenericLinkProviderTest.php

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\WebLink\Tests;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\WebLink\GenericLinkProvider;
16+
use Symfony\Component\WebLink\Link;
17+
18+
/**
19+
* Test case borrowed from https://github.com/php-fig/link/.
20+
*/
21+
class GenericLinkProviderTest extends TestCase
22+
{
23+
public function testCanAddLinksByMethod()
24+
{
25+
$link = (new Link())
26+
->withHref('http://www.google.com')
27+
->withRel('next')
28+
->withAttribute('me', 'you')
29+
;
30+
31+
$provider = (new GenericLinkProvider())
32+
->withLink($link);
33+
34+
$this->assertContains($link, $provider->getLinks());
35+
}
36+
37+
public function testCanAddLinksByConstructor()
38+
{
39+
$link = (new Link())
40+
->withHref('http://www.google.com')
41+
->withRel('next')
42+
->withAttribute('me', 'you')
43+
;
44+
45+
$provider = (new GenericLinkProvider())
46+
->withLink($link);
47+
48+
$this->assertContains($link, $provider->getLinks());
49+
}
50+
51+
public function testCanGetLinksByRel()
52+
{
53+
$link1 = (new Link())
54+
->withHref('http://www.google.com')
55+
->withRel('next')
56+
->withAttribute('me', 'you')
57+
;
58+
$link2 = (new Link())
59+
->withHref('http://www.php-fig.org/')
60+
->withRel('home')
61+
->withAttribute('me', 'you')
62+
;
63+
64+
$provider = (new GenericLinkProvider())
65+
->withLink($link1)
66+
->withLink($link2);
67+
68+
$links = $provider->getLinksByRel('home');
69+
$this->assertContains($link2, $links);
70+
$this->assertNotContains($link1, $links);
71+
}
72+
73+
public function testCanRemoveLinks()
74+
{
75+
$link = (new Link())
76+
->withHref('http://www.google.com')
77+
->withRel('next')
78+
->withAttribute('me', 'you')
79+
;
80+
81+
$provider = (new GenericLinkProvider())
82+
->withLink($link)
83+
->withoutLink($link);
84+
85+
$this->assertNotContains($link, $provider->getLinks());
86+
}
87+
}

Tests/HttpHeaderSerializerTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@
1111

1212
namespace Symfony\Component\WebLink\Tests;
1313

14-
use Fig\Link\Link;
1514
use PHPUnit\Framework\TestCase;
1615
use Symfony\Component\WebLink\HttpHeaderSerializer;
16+
use Symfony\Component\WebLink\Link;
1717

1818
class HttpHeaderSerializerTest extends TestCase
1919
{

0 commit comments

Comments
 (0)