[WebLink] implement PSR-13 directly
This commit is contained in:
parent
1aa41ed918
commit
b570ee1103
@ -20,7 +20,6 @@
|
||||
"ext-xml": "*",
|
||||
"doctrine/event-manager": "~1.0",
|
||||
"doctrine/persistence": "~1.0",
|
||||
"fig/link-util": "^1.0",
|
||||
"twig/twig": "^1.41|^2.10",
|
||||
"psr/cache": "~1.0",
|
||||
"psr/container": "^1.0",
|
||||
|
@ -11,9 +11,9 @@
|
||||
|
||||
namespace Symfony\Bridge\Twig\Extension;
|
||||
|
||||
use Fig\Link\GenericLinkProvider;
|
||||
use Fig\Link\Link;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\WebLink\GenericLinkProvider;
|
||||
use Symfony\Component\WebLink\Link;
|
||||
use Twig\Extension\AbstractExtension;
|
||||
use Twig\TwigFunction;
|
||||
|
||||
|
@ -11,11 +11,11 @@
|
||||
|
||||
namespace Symfony\Bridge\Twig\Tests\Extension;
|
||||
|
||||
use Fig\Link\Link;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Bridge\Twig\Extension\WebLinkExtension;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\WebLink\Link;
|
||||
|
||||
/**
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
|
@ -42,7 +42,7 @@
|
||||
"symfony/console": "^3.4|^4.0|^5.0",
|
||||
"symfony/var-dumper": "^3.4|^4.0|^5.0",
|
||||
"symfony/expression-language": "^3.4|^4.0|^5.0",
|
||||
"symfony/web-link": "^3.4|^4.0|^5.0",
|
||||
"symfony/web-link": "^4.4|^5.0",
|
||||
"symfony/workflow": "^4.3|^5.0"
|
||||
},
|
||||
"conflict": {
|
||||
|
@ -12,9 +12,8 @@
|
||||
namespace Symfony\Bundle\FrameworkBundle\Controller;
|
||||
|
||||
use Doctrine\Common\Persistence\ManagerRegistry;
|
||||
use Fig\Link\GenericLinkProvider;
|
||||
use Fig\Link\Link;
|
||||
use Psr\Container\ContainerInterface;
|
||||
use Psr\Link\LinkInterface;
|
||||
use Symfony\Component\Form\Extension\Core\Type\FormType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
@ -33,6 +32,7 @@ use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
|
||||
use Symfony\Component\Security\Csrf\CsrfToken;
|
||||
use Symfony\Component\WebLink\EventListener\AddLinkHeaderListener;
|
||||
use Symfony\Component\WebLink\GenericLinkProvider;
|
||||
|
||||
/**
|
||||
* Common features needed in controllers.
|
||||
@ -420,7 +420,7 @@ trait ControllerTrait
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
protected function addLink(Request $request, Link $link)
|
||||
protected function addLink(Request $request, LinkInterface $link)
|
||||
{
|
||||
if (!class_exists(AddLinkHeaderListener::class)) {
|
||||
throw new \LogicException('You can not use the "addLink" method if the WebLink component is not available. Try running "composer require symfony/web-link".');
|
||||
|
@ -11,7 +11,6 @@
|
||||
|
||||
namespace Symfony\Bundle\FrameworkBundle\Tests\Controller;
|
||||
|
||||
use Fig\Link\Link;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\ControllerTrait;
|
||||
use Symfony\Bundle\FrameworkBundle\Tests\TestCase;
|
||||
use Symfony\Component\DependencyInjection\Container;
|
||||
@ -29,6 +28,7 @@ use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
|
||||
use Symfony\Component\Security\Core\User\User;
|
||||
use Symfony\Component\Serializer\SerializerInterface;
|
||||
use Symfony\Component\WebLink\Link;
|
||||
|
||||
abstract class ControllerTraitTest extends TestCase
|
||||
{
|
||||
|
@ -31,7 +31,6 @@
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/cache": "~1.0",
|
||||
"fig/link-util": "^1.0",
|
||||
"symfony/asset": "^3.4|^4.0|^5.0",
|
||||
"symfony/browser-kit": "^4.3|^5.0",
|
||||
"symfony/console": "^4.3|^5.0",
|
||||
@ -58,7 +57,7 @@
|
||||
"symfony/workflow": "^4.3|^5.0",
|
||||
"symfony/yaml": "^3.4|^4.0|^5.0",
|
||||
"symfony/property-info": "^3.4|^4.0|^5.0",
|
||||
"symfony/web-link": "^3.4|^4.0|^5.0",
|
||||
"symfony/web-link": "^4.4|^5.0",
|
||||
"doctrine/annotations": "~1.0",
|
||||
"phpdocumentor/reflection-docblock": "^3.0|^4.0",
|
||||
"twig/twig": "~1.34|~2.4"
|
||||
|
@ -1,6 +1,11 @@
|
||||
CHANGELOG
|
||||
=========
|
||||
|
||||
4.4.0
|
||||
-----
|
||||
|
||||
* implement PSR-13 directly
|
||||
|
||||
3.3.0
|
||||
-----
|
||||
|
||||
|
83
src/Symfony/Component/WebLink/GenericLinkProvider.php
Normal file
83
src/Symfony/Component/WebLink/GenericLinkProvider.php
Normal file
@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\WebLink;
|
||||
|
||||
use Psr\Link\EvolvableLinkProviderInterface;
|
||||
use Psr\Link\LinkInterface;
|
||||
|
||||
class GenericLinkProvider implements EvolvableLinkProviderInterface
|
||||
{
|
||||
/**
|
||||
* @var LinkInterface[]
|
||||
*/
|
||||
private $links = [];
|
||||
|
||||
/**
|
||||
* @param LinkInterface[] $links
|
||||
*/
|
||||
public function __construct(array $links = [])
|
||||
{
|
||||
$that = $this;
|
||||
|
||||
foreach ($links as $link) {
|
||||
$that = $that->withLink($link);
|
||||
}
|
||||
|
||||
$this->links = $that->links;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getLinks(): array
|
||||
{
|
||||
return array_values($this->links);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getLinksByRel($rel): array
|
||||
{
|
||||
$links = [];
|
||||
|
||||
foreach ($this->links as $link) {
|
||||
if (\in_array($rel, $link->getRels())) {
|
||||
$links[] = $link;
|
||||
}
|
||||
}
|
||||
|
||||
return $links;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function withLink(LinkInterface $link)
|
||||
{
|
||||
$that = clone $this;
|
||||
$that->links[spl_object_id($link)] = $link;
|
||||
|
||||
return $that;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function withoutLink(LinkInterface $link)
|
||||
{
|
||||
$that = clone $this;
|
||||
unset($that->links[spl_object_id($link)]);
|
||||
|
||||
return $that;
|
||||
}
|
||||
}
|
153
src/Symfony/Component/WebLink/Link.php
Normal file
153
src/Symfony/Component/WebLink/Link.php
Normal file
@ -0,0 +1,153 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\WebLink;
|
||||
|
||||
use Psr\Link\EvolvableLinkInterface;
|
||||
|
||||
class Link implements EvolvableLinkInterface
|
||||
{
|
||||
// Relations defined in https://www.w3.org/TR/html5/links.html#links and applicable on link elements
|
||||
public const REL_ALTERNATE = 'alternate';
|
||||
public const REL_AUTHOR = 'author';
|
||||
public const REL_HELP = 'help';
|
||||
public const REL_ICON = 'icon';
|
||||
public const REL_LICENSE = 'license';
|
||||
public const REL_SEARCH = 'search';
|
||||
public const REL_STYLESHEET = 'stylesheet';
|
||||
public const REL_NEXT = 'next';
|
||||
public const REL_PREV = 'prev';
|
||||
|
||||
// Relation defined in https://www.w3.org/TR/preload/
|
||||
public const REL_PRELOAD = 'preload';
|
||||
|
||||
// Relations defined in https://www.w3.org/TR/resource-hints/
|
||||
public const REL_DNS_PREFETCH = 'dns-prefetch';
|
||||
public const REL_PRECONNECT = 'preconnect';
|
||||
public const REL_PREFETCH = 'prefetch';
|
||||
public const REL_PRERENDER = 'prerender';
|
||||
|
||||
// Extra relations
|
||||
public const REL_MERCURE = 'mercure';
|
||||
|
||||
private $href = '';
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
private $rel = [];
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
private $attributes = [];
|
||||
|
||||
public function __construct(string $rel = null, string $href = '')
|
||||
{
|
||||
if (null !== $rel) {
|
||||
$this->rel[$rel] = $rel;
|
||||
}
|
||||
$this->href = $href;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getHref(): string
|
||||
{
|
||||
return $this->href;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isTemplated(): bool
|
||||
{
|
||||
return $this->hrefIsTemplated($this->href);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getRels(): array
|
||||
{
|
||||
return array_values($this->rel);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getAttributes(): array
|
||||
{
|
||||
return $this->attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function withHref($href)
|
||||
{
|
||||
$that = clone $this;
|
||||
$that->href = $href;
|
||||
$that->templated = $this->hrefIsTemplated($href);
|
||||
|
||||
return $that;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function withRel($rel)
|
||||
{
|
||||
$that = clone $this;
|
||||
$that->rel[$rel] = $rel;
|
||||
|
||||
return $that;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function withoutRel($rel)
|
||||
{
|
||||
$that = clone $this;
|
||||
unset($that->rel[$rel]);
|
||||
|
||||
return $that;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function withAttribute($attribute, $value)
|
||||
{
|
||||
$that = clone $this;
|
||||
$that->attributes[$attribute] = $value;
|
||||
|
||||
return $that;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function withoutAttribute($attribute)
|
||||
{
|
||||
$that = clone $this;
|
||||
unset($that->attributes[$attribute]);
|
||||
|
||||
return $that;
|
||||
}
|
||||
|
||||
private function hrefIsTemplated(string $href): bool
|
||||
{
|
||||
return false !== strpos($href, '{') || false !== strpos($href, '}');
|
||||
}
|
||||
}
|
@ -11,8 +11,6 @@
|
||||
|
||||
namespace Symfony\Component\WebLink\Tests\EventListener;
|
||||
|
||||
use Fig\Link\GenericLinkProvider;
|
||||
use Fig\Link\Link;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
@ -20,6 +18,8 @@ use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Event\ResponseEvent;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
use Symfony\Component\WebLink\EventListener\AddLinkHeaderListener;
|
||||
use Symfony\Component\WebLink\GenericLinkProvider;
|
||||
use Symfony\Component\WebLink\Link;
|
||||
|
||||
/**
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
|
@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\WebLink\Tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\WebLink\GenericLinkProvider;
|
||||
use Symfony\Component\WebLink\Link;
|
||||
|
||||
/**
|
||||
* Test case borrowed from https://github.com/php-fig/link/.
|
||||
*/
|
||||
class GenericLinkProviderTest extends TestCase
|
||||
{
|
||||
public function testCanAddLinksByMethod()
|
||||
{
|
||||
$link = (new Link())
|
||||
->withHref('http://www.google.com')
|
||||
->withRel('next')
|
||||
->withAttribute('me', 'you')
|
||||
;
|
||||
|
||||
$provider = (new GenericLinkProvider())
|
||||
->withLink($link);
|
||||
|
||||
$this->assertContains($link, $provider->getLinks());
|
||||
}
|
||||
|
||||
public function testCanAddLinksByConstructor()
|
||||
{
|
||||
$link = (new Link())
|
||||
->withHref('http://www.google.com')
|
||||
->withRel('next')
|
||||
->withAttribute('me', 'you')
|
||||
;
|
||||
|
||||
$provider = (new GenericLinkProvider())
|
||||
->withLink($link);
|
||||
|
||||
$this->assertContains($link, $provider->getLinks());
|
||||
}
|
||||
|
||||
public function testCanGetLinksByRel()
|
||||
{
|
||||
$link1 = (new Link())
|
||||
->withHref('http://www.google.com')
|
||||
->withRel('next')
|
||||
->withAttribute('me', 'you')
|
||||
;
|
||||
$link2 = (new Link())
|
||||
->withHref('http://www.php-fig.org/')
|
||||
->withRel('home')
|
||||
->withAttribute('me', 'you')
|
||||
;
|
||||
|
||||
$provider = (new GenericLinkProvider())
|
||||
->withLink($link1)
|
||||
->withLink($link2);
|
||||
|
||||
$links = $provider->getLinksByRel('home');
|
||||
$this->assertContains($link2, $links);
|
||||
$this->assertNotContains($link1, $links);
|
||||
}
|
||||
|
||||
public function testCanRemoveLinks()
|
||||
{
|
||||
$link = (new Link())
|
||||
->withHref('http://www.google.com')
|
||||
->withRel('next')
|
||||
->withAttribute('me', 'you')
|
||||
;
|
||||
|
||||
$provider = (new GenericLinkProvider())
|
||||
->withLink($link)
|
||||
->withoutLink($link);
|
||||
|
||||
$this->assertNotContains($link, $provider->getLinks());
|
||||
}
|
||||
}
|
@ -11,9 +11,9 @@
|
||||
|
||||
namespace Symfony\Component\WebLink\Tests;
|
||||
|
||||
use Fig\Link\Link;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\WebLink\HttpHeaderSerializer;
|
||||
use Symfony\Component\WebLink\Link;
|
||||
|
||||
class HttpHeaderSerializerTest extends TestCase
|
||||
{
|
||||
|
109
src/Symfony/Component/WebLink/Tests/LinkTest.php
Normal file
109
src/Symfony/Component/WebLink/Tests/LinkTest.php
Normal file
@ -0,0 +1,109 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\WebLink\Tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\WebLink\Link;
|
||||
|
||||
/**
|
||||
* Test case borrowed from https://github.com/php-fig/link/.
|
||||
*/
|
||||
class LinkTest extends TestCase
|
||||
{
|
||||
public function testCanSetAndRetrieveValues()
|
||||
{
|
||||
$link = (new Link())
|
||||
->withHref('http://www.google.com')
|
||||
->withRel('next')
|
||||
->withAttribute('me', 'you')
|
||||
;
|
||||
|
||||
$this->assertEquals('http://www.google.com', $link->getHref());
|
||||
$this->assertContains('next', $link->getRels());
|
||||
$this->assertArrayHasKey('me', $link->getAttributes());
|
||||
$this->assertEquals('you', $link->getAttributes()['me']);
|
||||
}
|
||||
|
||||
public function testCanRemoveValues()
|
||||
{
|
||||
$link = (new Link())
|
||||
->withHref('http://www.google.com')
|
||||
->withRel('next')
|
||||
->withAttribute('me', 'you')
|
||||
;
|
||||
|
||||
$link = $link->withoutAttribute('me')
|
||||
->withoutRel('next');
|
||||
|
||||
$this->assertEquals('http://www.google.com', $link->getHref());
|
||||
$this->assertFalse(\in_array('next', $link->getRels()));
|
||||
$this->assertArrayNotHasKey('me', $link->getAttributes());
|
||||
}
|
||||
|
||||
public function testMultipleRels()
|
||||
{
|
||||
$link = (new Link())
|
||||
->withHref('http://www.google.com')
|
||||
->withRel('next')
|
||||
->withRel('reference');
|
||||
|
||||
$this->assertCount(2, $link->getRels());
|
||||
$this->assertContains('next', $link->getRels());
|
||||
$this->assertContains('reference', $link->getRels());
|
||||
}
|
||||
|
||||
public function testConstructor()
|
||||
{
|
||||
$link = new Link('next', 'http://www.google.com');
|
||||
|
||||
$this->assertEquals('http://www.google.com', $link->getHref());
|
||||
$this->assertContains('next', $link->getRels());
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider templatedHrefProvider
|
||||
*/
|
||||
public function testTemplated(string $href)
|
||||
{
|
||||
$link = (new Link())
|
||||
->withHref($href);
|
||||
|
||||
$this->assertTrue($link->isTemplated());
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider notTemplatedHrefProvider
|
||||
*/
|
||||
public function testNotTemplated(string $href)
|
||||
{
|
||||
$link = (new Link())
|
||||
->withHref($href);
|
||||
|
||||
$this->assertFalse($link->isTemplated());
|
||||
}
|
||||
|
||||
public function templatedHrefProvider()
|
||||
{
|
||||
return [
|
||||
['http://www.google.com/{param}/foo'],
|
||||
['http://www.google.com/foo?q={param}'],
|
||||
];
|
||||
}
|
||||
|
||||
public function notTemplatedHrefProvider()
|
||||
{
|
||||
return [
|
||||
['http://www.google.com/foo'],
|
||||
['/foo/bar/baz'],
|
||||
];
|
||||
}
|
||||
}
|
@ -15,10 +15,13 @@
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"provide": {
|
||||
"psr/link-implementation": "1.0"
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.1.3",
|
||||
"fig/link-util": "^1.0",
|
||||
"psr/link": "^1.0"
|
||||
"psr/link": "^1.0",
|
||||
"symfony/polyfill-php72": "^1.5"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/http-kernel": ""
|
||||
|
Reference in New Issue
Block a user