[Routing] Added the Route attribute.
This commit is contained in:
parent
9150590818
commit
f0978de493
1
.github/patch-types.php
vendored
1
.github/patch-types.php
vendored
@ -31,6 +31,7 @@ foreach ($loader->getClassMap() as $class => $file) {
|
|||||||
case false !== strpos($file, '/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Dummy.php'):
|
case false !== strpos($file, '/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Dummy.php'):
|
||||||
case false !== strpos($file, '/src/Symfony/Component/PropertyInfo/Tests/Fixtures/ParentDummy.php'):
|
case false !== strpos($file, '/src/Symfony/Component/PropertyInfo/Tests/Fixtures/ParentDummy.php'):
|
||||||
case false !== strpos($file, '/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Php80Dummy.php'):
|
case false !== strpos($file, '/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Php80Dummy.php'):
|
||||||
|
case false !== strpos($file, '/src/Symfony/Component/Routing/Tests/Fixtures/AttributeFixtures'):
|
||||||
case false !== strpos($file, '/src/Symfony/Component/Serializer/Tests/Normalizer/Features/ObjectOuter.php'):
|
case false !== strpos($file, '/src/Symfony/Component/Serializer/Tests/Normalizer/Features/ObjectOuter.php'):
|
||||||
case false !== strpos($file, '/src/Symfony/Component/VarDumper/Tests/Fixtures/NotLoadableClass.php'):
|
case false !== strpos($file, '/src/Symfony/Component/VarDumper/Tests/Fixtures/NotLoadableClass.php'):
|
||||||
case false !== strpos($file, '/src/Symfony/Component/VarDumper/Tests/Fixtures/Php74.php') && \PHP_VERSION_ID < 70400:
|
case false !== strpos($file, '/src/Symfony/Component/VarDumper/Tests/Fixtures/Php74.php') && \PHP_VERSION_ID < 70400:
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\Routing\Annotation;
|
namespace Symfony\Component\Routing\Annotation;
|
||||||
|
|
||||||
|
use Attribute;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Annotation class for @Route().
|
* Annotation class for @Route().
|
||||||
*
|
*
|
||||||
@ -18,7 +20,9 @@ namespace Symfony\Component\Routing\Annotation;
|
|||||||
* @Target({"CLASS", "METHOD"})
|
* @Target({"CLASS", "METHOD"})
|
||||||
*
|
*
|
||||||
* @author Fabien Potencier <fabien@symfony.com>
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
* @author Alexander M. Turek <me@derrabus.de>
|
||||||
*/
|
*/
|
||||||
|
#[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_CLASS | Attribute::TARGET_METHOD)]
|
||||||
class Route
|
class Route
|
||||||
{
|
{
|
||||||
private $path;
|
private $path;
|
||||||
@ -34,12 +38,59 @@ class Route
|
|||||||
private $priority;
|
private $priority;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array $data An array of key/value parameters
|
* @param array|string $data data array managed by the Doctrine Annotations library or the path
|
||||||
|
* @param array|string|null $path
|
||||||
|
* @param string[] $requirements
|
||||||
|
* @param string[] $methods
|
||||||
|
* @param string[] $schemes
|
||||||
*
|
*
|
||||||
* @throws \BadMethodCallException
|
* @throws \BadMethodCallException
|
||||||
*/
|
*/
|
||||||
public function __construct(array $data)
|
public function __construct(
|
||||||
{
|
$data = [],
|
||||||
|
$path = null,
|
||||||
|
string $name = null,
|
||||||
|
array $requirements = [],
|
||||||
|
array $options = [],
|
||||||
|
array $defaults = [],
|
||||||
|
string $host = null,
|
||||||
|
array $methods = [],
|
||||||
|
array $schemes = [],
|
||||||
|
string $condition = null,
|
||||||
|
int $priority = null,
|
||||||
|
string $locale = null,
|
||||||
|
string $format = null,
|
||||||
|
bool $utf8 = null,
|
||||||
|
bool $stateless = null
|
||||||
|
) {
|
||||||
|
if (\is_string($data)) {
|
||||||
|
$data = ['path' => $data];
|
||||||
|
} elseif (!\is_array($data)) {
|
||||||
|
throw new \TypeError(sprintf('"%s": Argument $data is expected to be a string or array, got "%s".', __METHOD__, get_debug_type($data)));
|
||||||
|
}
|
||||||
|
if (null !== $path && !\is_string($path) && !\is_array($path)) {
|
||||||
|
throw new \TypeError(sprintf('"%s": Argument $path is expected to be a string, array or null, got "%s".', __METHOD__, get_debug_type($path)));
|
||||||
|
}
|
||||||
|
|
||||||
|
$data['path'] = $data['path'] ?? $path;
|
||||||
|
$data['name'] = $data['name'] ?? $name;
|
||||||
|
$data['requirements'] = $data['requirements'] ?? $requirements;
|
||||||
|
$data['options'] = $data['options'] ?? $options;
|
||||||
|
$data['defaults'] = $data['defaults'] ?? $defaults;
|
||||||
|
$data['host'] = $data['host'] ?? $host;
|
||||||
|
$data['methods'] = $data['methods'] ?? $methods;
|
||||||
|
$data['schemes'] = $data['schemes'] ?? $schemes;
|
||||||
|
$data['condition'] = $data['condition'] ?? $condition;
|
||||||
|
$data['priority'] = $data['priority'] ?? $priority;
|
||||||
|
$data['locale'] = $data['locale'] ?? $locale;
|
||||||
|
$data['format'] = $data['format'] ?? $format;
|
||||||
|
$data['utf8'] = $data['utf8'] ?? $utf8;
|
||||||
|
$data['stateless'] = $data['stateless'] ?? $stateless;
|
||||||
|
|
||||||
|
$data = array_filter($data, static function ($value): bool {
|
||||||
|
return null !== $value;
|
||||||
|
});
|
||||||
|
|
||||||
if (isset($data['localized_paths'])) {
|
if (isset($data['localized_paths'])) {
|
||||||
throw new \BadMethodCallException(sprintf('Unknown property "localized_paths" on annotation "%s".', static::class));
|
throw new \BadMethodCallException(sprintf('Unknown property "localized_paths" on annotation "%s".', static::class));
|
||||||
}
|
}
|
||||||
|
@ -51,8 +51,24 @@ use Symfony\Component\Routing\RouteCollection;
|
|||||||
* {
|
* {
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
|
*
|
||||||
|
* On PHP 8, the annotation class can be used as an attribute as well:
|
||||||
|
* #[Route('/Blog')]
|
||||||
|
* class Blog
|
||||||
|
* {
|
||||||
|
* #[Route('/', name: 'blog_index')]
|
||||||
|
* public function index()
|
||||||
|
* {
|
||||||
|
* }
|
||||||
|
* #[Route('/{id}', name: 'blog_post', requirements: ["id" => '\d+'])]
|
||||||
|
* public function show()
|
||||||
|
* {
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
|
||||||
*
|
*
|
||||||
* @author Fabien Potencier <fabien@symfony.com>
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
* @author Alexander M. Turek <me@derrabus.de>
|
||||||
*/
|
*/
|
||||||
abstract class AnnotationClassLoader implements LoaderInterface
|
abstract class AnnotationClassLoader implements LoaderInterface
|
||||||
{
|
{
|
||||||
@ -61,14 +77,14 @@ abstract class AnnotationClassLoader implements LoaderInterface
|
|||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $routeAnnotationClass = 'Symfony\\Component\\Routing\\Annotation\\Route';
|
protected $routeAnnotationClass = RouteAnnotation::class;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var int
|
* @var int
|
||||||
*/
|
*/
|
||||||
protected $defaultRouteIndex = 0;
|
protected $defaultRouteIndex = 0;
|
||||||
|
|
||||||
public function __construct(Reader $reader)
|
public function __construct(Reader $reader = null)
|
||||||
{
|
{
|
||||||
$this->reader = $reader;
|
$this->reader = $reader;
|
||||||
}
|
}
|
||||||
@ -108,19 +124,15 @@ abstract class AnnotationClassLoader implements LoaderInterface
|
|||||||
|
|
||||||
foreach ($class->getMethods() as $method) {
|
foreach ($class->getMethods() as $method) {
|
||||||
$this->defaultRouteIndex = 0;
|
$this->defaultRouteIndex = 0;
|
||||||
foreach ($this->reader->getMethodAnnotations($method) as $annot) {
|
foreach ($this->getAnnotations($method) as $annot) {
|
||||||
if ($annot instanceof $this->routeAnnotationClass) {
|
$this->addRoute($collection, $annot, $globals, $class, $method);
|
||||||
$this->addRoute($collection, $annot, $globals, $class, $method);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0 === $collection->count() && $class->hasMethod('__invoke')) {
|
if (0 === $collection->count() && $class->hasMethod('__invoke')) {
|
||||||
$globals = $this->resetGlobals();
|
$globals = $this->resetGlobals();
|
||||||
foreach ($this->reader->getClassAnnotations($class) as $annot) {
|
foreach ($this->getAnnotations($class) as $annot) {
|
||||||
if ($annot instanceof $this->routeAnnotationClass) {
|
$this->addRoute($collection, $annot, $globals, $class, $class->getMethod('__invoke'));
|
||||||
$this->addRoute($collection, $annot, $globals, $class, $class->getMethod('__invoke'));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,7 +142,7 @@ abstract class AnnotationClassLoader implements LoaderInterface
|
|||||||
/**
|
/**
|
||||||
* @param RouteAnnotation $annot or an object that exposes a similar interface
|
* @param RouteAnnotation $annot or an object that exposes a similar interface
|
||||||
*/
|
*/
|
||||||
protected function addRoute(RouteCollection $collection, $annot, array $globals, \ReflectionClass $class, \ReflectionMethod $method)
|
protected function addRoute(RouteCollection $collection, object $annot, array $globals, \ReflectionClass $class, \ReflectionMethod $method)
|
||||||
{
|
{
|
||||||
$name = $annot->getName();
|
$name = $annot->getName();
|
||||||
if (null === $name) {
|
if (null === $name) {
|
||||||
@ -257,7 +269,15 @@ abstract class AnnotationClassLoader implements LoaderInterface
|
|||||||
{
|
{
|
||||||
$globals = $this->resetGlobals();
|
$globals = $this->resetGlobals();
|
||||||
|
|
||||||
if ($annot = $this->reader->getClassAnnotation($class, $this->routeAnnotationClass)) {
|
$annot = null;
|
||||||
|
if (\PHP_VERSION_ID >= 80000 && ($attribute = $class->getAttributes($this->routeAnnotationClass)[0] ?? null)) {
|
||||||
|
$annot = $attribute->newInstance();
|
||||||
|
}
|
||||||
|
if (!$annot && $this->reader) {
|
||||||
|
$annot = $this->reader->getClassAnnotation($class, $this->routeAnnotationClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($annot) {
|
||||||
if (null !== $annot->getName()) {
|
if (null !== $annot->getName()) {
|
||||||
$globals['name'] = $annot->getName();
|
$globals['name'] = $annot->getName();
|
||||||
}
|
}
|
||||||
@ -330,5 +350,33 @@ abstract class AnnotationClassLoader implements LoaderInterface
|
|||||||
return new Route($path, $defaults, $requirements, $options, $host, $schemes, $methods, $condition);
|
return new Route($path, $defaults, $requirements, $options, $host, $schemes, $methods, $condition);
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract protected function configureRoute(Route $route, \ReflectionClass $class, \ReflectionMethod $method, $annot);
|
abstract protected function configureRoute(Route $route, \ReflectionClass $class, \ReflectionMethod $method, object $annot);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \ReflectionClass|\ReflectionMethod $reflection
|
||||||
|
*
|
||||||
|
* @return iterable|RouteAnnotation[]
|
||||||
|
*/
|
||||||
|
private function getAnnotations(object $reflection): iterable
|
||||||
|
{
|
||||||
|
if (\PHP_VERSION_ID >= 80000) {
|
||||||
|
foreach ($reflection->getAttributes($this->routeAnnotationClass) as $attribute) {
|
||||||
|
yield $attribute->newInstance();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$this->reader) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$anntotations = $reflection instanceof \ReflectionClass
|
||||||
|
? $this->reader->getClassAnnotations($reflection)
|
||||||
|
: $this->reader->getMethodAnnotations($reflection);
|
||||||
|
|
||||||
|
foreach ($anntotations as $annotation) {
|
||||||
|
if ($annotation instanceof $this->routeAnnotationClass) {
|
||||||
|
yield $annotation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
<?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\Routing\Tests\Fixtures\AnnotationFixtures;
|
||||||
|
|
||||||
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Route("/1", name="route1", schemes={"https"}, methods={"GET"})
|
||||||
|
* @Route("/2", name="route2", schemes={"https"}, methods={"GET"})
|
||||||
|
*/
|
||||||
|
class BazClass
|
||||||
|
{
|
||||||
|
public function __invoke()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures;
|
||||||
|
|
||||||
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
|
|
||||||
|
class EncodingClass
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @Route
|
||||||
|
*/
|
||||||
|
public function routeÀction()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures;
|
||||||
|
|
||||||
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
|
|
||||||
|
class ActionPathController
|
||||||
|
{
|
||||||
|
#[Route('/path', name: 'action')]
|
||||||
|
public function action()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
<?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\Routing\Tests\Fixtures\AttributeFixtures;
|
||||||
|
|
||||||
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
|
|
||||||
|
#[
|
||||||
|
Route(path: '/1', name: 'route1', schemes: ['https'], methods: ['GET']),
|
||||||
|
Route(path: '/2', name: 'route2', schemes: ['https'], methods: ['GET']),
|
||||||
|
]
|
||||||
|
class BazClass
|
||||||
|
{
|
||||||
|
public function __invoke()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures;
|
||||||
|
|
||||||
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
|
|
||||||
|
class DefaultValueController
|
||||||
|
{
|
||||||
|
#[Route(path: '/{default}/path', name: 'action')]
|
||||||
|
public function action($default = 'value')
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#[
|
||||||
|
Route(path: '/hello/{name<\w+>}', name: 'hello_without_default'),
|
||||||
|
Route(path: 'hello/{name<\w+>?Symfony}', name: 'hello_with_default'),
|
||||||
|
]
|
||||||
|
public function hello(string $name = 'World')
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures;
|
||||||
|
|
||||||
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
|
|
||||||
|
class EncodingClass
|
||||||
|
{
|
||||||
|
#[Route]
|
||||||
|
public function routeÀction()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures;
|
||||||
|
|
||||||
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
|
|
||||||
|
class ExplicitLocalizedActionPathController
|
||||||
|
{
|
||||||
|
#[Route(path: ['en' => '/path', 'nl' => '/pad'], name: 'action')]
|
||||||
|
public function action()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
<?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\Routing\Tests\Fixtures\AttributeFixtures;
|
||||||
|
|
||||||
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
|
|
||||||
|
#[Route(path: '/defaults', locale: 'g_locale', format: 'g_format')]
|
||||||
|
class GlobalDefaultsClass
|
||||||
|
{
|
||||||
|
#[Route(path: '/specific-locale', name: 'specific_locale', locale: 's_locale')]
|
||||||
|
public function locale()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#[Route(path: '/specific-format', name: 'specific_format', format: 's_format')]
|
||||||
|
public function format()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures;
|
||||||
|
|
||||||
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
|
|
||||||
|
#[Route(path: '/here', name: 'lol', methods: ["GET", "POST"], schemes: ['https'])]
|
||||||
|
class InvokableController
|
||||||
|
{
|
||||||
|
public function __invoke()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures;
|
||||||
|
|
||||||
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
|
|
||||||
|
#[Route(path: ["nl" => "/hier", "en" => "/here"], name: 'action')]
|
||||||
|
class InvokableLocalizedController
|
||||||
|
{
|
||||||
|
public function __invoke()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures;
|
||||||
|
|
||||||
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
|
|
||||||
|
class LocalizedActionPathController
|
||||||
|
{
|
||||||
|
#[Route(path: ['en' => '/path', 'nl' => '/pad'], name: 'action')]
|
||||||
|
public function action()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures;
|
||||||
|
|
||||||
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
|
|
||||||
|
#[Route(path: ['en' => '/the/path', 'nl' => '/het/pad'])]
|
||||||
|
class LocalizedMethodActionControllers
|
||||||
|
{
|
||||||
|
#[Route(name: 'post', methods: ['POST'])]
|
||||||
|
public function post()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#[Route(name: 'put', methods: ['PUT'])]
|
||||||
|
public function put()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures;
|
||||||
|
|
||||||
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
|
|
||||||
|
#[Route(path: ['nl' => '/nl', 'en' => '/en'])]
|
||||||
|
class LocalizedPrefixLocalizedActionController
|
||||||
|
{
|
||||||
|
#[Route(path: ['nl' => '/actie', 'en' => '/action'], name: 'action')]
|
||||||
|
public function action()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures;
|
||||||
|
|
||||||
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
|
|
||||||
|
#[Route(path: ['en' => '/en', 'nl' => '/nl'])]
|
||||||
|
class LocalizedPrefixWithRouteWithoutLocale
|
||||||
|
{
|
||||||
|
#[Route(path: '/suffix', name: 'action')]
|
||||||
|
public function action()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures;
|
||||||
|
|
||||||
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
|
|
||||||
|
#[Route('/the/path')]
|
||||||
|
class MethodActionControllers
|
||||||
|
{
|
||||||
|
#[Route(name: 'post', methods: ['POST'])]
|
||||||
|
public function post()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#[Route(name: 'put', methods: ['PUT'], priority: 10)]
|
||||||
|
public function put()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures;
|
||||||
|
|
||||||
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
|
|
||||||
|
class MissingRouteNameController
|
||||||
|
{
|
||||||
|
#[Route('/path')]
|
||||||
|
public function action()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures;
|
||||||
|
|
||||||
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
|
|
||||||
|
class NothingButNameController
|
||||||
|
{
|
||||||
|
#[Route(name: 'action')]
|
||||||
|
public function action()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures;
|
||||||
|
|
||||||
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
|
|
||||||
|
#[Route('/prefix')]
|
||||||
|
class PrefixedActionLocalizedRouteController
|
||||||
|
{
|
||||||
|
#[Route(path: ['en' => '/path', 'nl' => '/pad'], name: 'action')]
|
||||||
|
public function action()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures;
|
||||||
|
|
||||||
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
|
|
||||||
|
#[Route(path: '/prefix', host: 'frankdejonge.nl', condition: 'lol=fun')]
|
||||||
|
class PrefixedActionPathController
|
||||||
|
{
|
||||||
|
#[Route(path: '/path', name: 'action')]
|
||||||
|
public function action()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
<?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\Routing\Tests\Fixtures\AttributeFixtures;
|
||||||
|
|
||||||
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
|
|
||||||
|
#[Route(path: '/', requirements: ['foo', '\d+'])]
|
||||||
|
class RequirementsWithoutPlaceholderNameController
|
||||||
|
{
|
||||||
|
#[Route(path: '/{foo}', name: 'foo', requirements: ['foo', '\d+'])]
|
||||||
|
public function foo()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures;
|
||||||
|
|
||||||
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
|
|
||||||
|
#[Route('/prefix')]
|
||||||
|
class RouteWithPrefixController
|
||||||
|
{
|
||||||
|
#[Route(path: '/path', name: 'action')]
|
||||||
|
public function action()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures;
|
||||||
|
|
||||||
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
|
|
||||||
|
#[Route('/test', utf8: true)]
|
||||||
|
class Utf8ActionControllers
|
||||||
|
{
|
||||||
|
#[Route(name: 'one')]
|
||||||
|
public function one()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#[Route(name: 'two', utf8: false)]
|
||||||
|
public function two()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -11,50 +11,16 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\Routing\Tests\Loader;
|
namespace Symfony\Component\Routing\Tests\Loader;
|
||||||
|
|
||||||
use Doctrine\Common\Annotations\AnnotationReader;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Doctrine\Common\Annotations\AnnotationRegistry;
|
|
||||||
use Symfony\Component\Routing\Annotation\Route as RouteAnnotation;
|
|
||||||
use Symfony\Component\Routing\Loader\AnnotationClassLoader;
|
use Symfony\Component\Routing\Loader\AnnotationClassLoader;
|
||||||
use Symfony\Component\Routing\Route;
|
|
||||||
use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\AbstractClassController;
|
use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\AbstractClassController;
|
||||||
use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\ActionPathController;
|
|
||||||
use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\DefaultValueController;
|
|
||||||
use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\ExplicitLocalizedActionPathController;
|
|
||||||
use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\GlobalDefaultsClass;
|
|
||||||
use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\InvokableController;
|
|
||||||
use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\InvokableLocalizedController;
|
|
||||||
use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\LocalizedActionPathController;
|
|
||||||
use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\LocalizedMethodActionControllers;
|
|
||||||
use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\LocalizedPrefixLocalizedActionController;
|
|
||||||
use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\LocalizedPrefixMissingLocaleActionController;
|
|
||||||
use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\LocalizedPrefixMissingRouteLocaleActionController;
|
|
||||||
use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\LocalizedPrefixWithRouteWithoutLocale;
|
|
||||||
use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\MethodActionControllers;
|
|
||||||
use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\MissingRouteNameController;
|
|
||||||
use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\NothingButNameController;
|
|
||||||
use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\PrefixedActionLocalizedRouteController;
|
|
||||||
use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\PrefixedActionPathController;
|
|
||||||
use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\RequirementsWithoutPlaceholderNameController;
|
|
||||||
use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\RouteWithPrefixController;
|
|
||||||
use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\Utf8ActionControllers;
|
|
||||||
|
|
||||||
class AnnotationClassLoaderTest extends AbstractAnnotationLoaderTest
|
abstract class AnnotationClassLoaderTest extends TestCase
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @var AnnotationClassLoader
|
* @var AnnotationClassLoader
|
||||||
*/
|
*/
|
||||||
private $loader;
|
protected $loader;
|
||||||
|
|
||||||
protected function setUp(): void
|
|
||||||
{
|
|
||||||
$reader = new AnnotationReader();
|
|
||||||
$this->loader = new class($reader) extends AnnotationClassLoader {
|
|
||||||
protected function configureRoute(Route $route, \ReflectionClass $class, \ReflectionMethod $method, $annot): void
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
AnnotationRegistry::registerLoader('class_exists');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider provideTestSupportsChecksResource
|
* @dataProvider provideTestSupportsChecksResource
|
||||||
@ -85,7 +51,7 @@ class AnnotationClassLoaderTest extends AbstractAnnotationLoaderTest
|
|||||||
|
|
||||||
public function testSimplePathRoute()
|
public function testSimplePathRoute()
|
||||||
{
|
{
|
||||||
$routes = $this->loader->load(ActionPathController::class);
|
$routes = $this->loader->load($this->getNamespace().'\ActionPathController');
|
||||||
$this->assertCount(1, $routes);
|
$this->assertCount(1, $routes);
|
||||||
$this->assertEquals('/path', $routes->get('action')->getPath());
|
$this->assertEquals('/path', $routes->get('action')->getPath());
|
||||||
}
|
}
|
||||||
@ -95,12 +61,12 @@ class AnnotationClassLoaderTest extends AbstractAnnotationLoaderTest
|
|||||||
$this->expectException(\InvalidArgumentException::class);
|
$this->expectException(\InvalidArgumentException::class);
|
||||||
$this->expectExceptionMessage('A placeholder name must be a string (0 given). Did you forget to specify the placeholder key for the requirement "foo"');
|
$this->expectExceptionMessage('A placeholder name must be a string (0 given). Did you forget to specify the placeholder key for the requirement "foo"');
|
||||||
|
|
||||||
$this->loader->load(RequirementsWithoutPlaceholderNameController::class);
|
$this->loader->load($this->getNamespace().'\RequirementsWithoutPlaceholderNameController');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testInvokableControllerLoader()
|
public function testInvokableControllerLoader()
|
||||||
{
|
{
|
||||||
$routes = $this->loader->load(InvokableController::class);
|
$routes = $this->loader->load($this->getNamespace().'\InvokableController');
|
||||||
$this->assertCount(1, $routes);
|
$this->assertCount(1, $routes);
|
||||||
$this->assertEquals('/here', $routes->get('lol')->getPath());
|
$this->assertEquals('/here', $routes->get('lol')->getPath());
|
||||||
$this->assertEquals(['GET', 'POST'], $routes->get('lol')->getMethods());
|
$this->assertEquals(['GET', 'POST'], $routes->get('lol')->getMethods());
|
||||||
@ -109,7 +75,7 @@ class AnnotationClassLoaderTest extends AbstractAnnotationLoaderTest
|
|||||||
|
|
||||||
public function testInvokableLocalizedControllerLoading()
|
public function testInvokableLocalizedControllerLoading()
|
||||||
{
|
{
|
||||||
$routes = $this->loader->load(InvokableLocalizedController::class);
|
$routes = $this->loader->load($this->getNamespace().'\InvokableLocalizedController');
|
||||||
$this->assertCount(2, $routes);
|
$this->assertCount(2, $routes);
|
||||||
$this->assertEquals('/here', $routes->get('action.en')->getPath());
|
$this->assertEquals('/here', $routes->get('action.en')->getPath());
|
||||||
$this->assertEquals('/hier', $routes->get('action.nl')->getPath());
|
$this->assertEquals('/hier', $routes->get('action.nl')->getPath());
|
||||||
@ -117,7 +83,7 @@ class AnnotationClassLoaderTest extends AbstractAnnotationLoaderTest
|
|||||||
|
|
||||||
public function testLocalizedPathRoutes()
|
public function testLocalizedPathRoutes()
|
||||||
{
|
{
|
||||||
$routes = $this->loader->load(LocalizedActionPathController::class);
|
$routes = $this->loader->load($this->getNamespace().'\LocalizedActionPathController');
|
||||||
$this->assertCount(2, $routes);
|
$this->assertCount(2, $routes);
|
||||||
$this->assertEquals('/path', $routes->get('action.en')->getPath());
|
$this->assertEquals('/path', $routes->get('action.en')->getPath());
|
||||||
$this->assertEquals('/pad', $routes->get('action.nl')->getPath());
|
$this->assertEquals('/pad', $routes->get('action.nl')->getPath());
|
||||||
@ -128,7 +94,7 @@ class AnnotationClassLoaderTest extends AbstractAnnotationLoaderTest
|
|||||||
|
|
||||||
public function testLocalizedPathRoutesWithExplicitPathPropety()
|
public function testLocalizedPathRoutesWithExplicitPathPropety()
|
||||||
{
|
{
|
||||||
$routes = $this->loader->load(ExplicitLocalizedActionPathController::class);
|
$routes = $this->loader->load($this->getNamespace().'\ExplicitLocalizedActionPathController');
|
||||||
$this->assertCount(2, $routes);
|
$this->assertCount(2, $routes);
|
||||||
$this->assertEquals('/path', $routes->get('action.en')->getPath());
|
$this->assertEquals('/path', $routes->get('action.en')->getPath());
|
||||||
$this->assertEquals('/pad', $routes->get('action.nl')->getPath());
|
$this->assertEquals('/pad', $routes->get('action.nl')->getPath());
|
||||||
@ -136,7 +102,7 @@ class AnnotationClassLoaderTest extends AbstractAnnotationLoaderTest
|
|||||||
|
|
||||||
public function testDefaultValuesForMethods()
|
public function testDefaultValuesForMethods()
|
||||||
{
|
{
|
||||||
$routes = $this->loader->load(DefaultValueController::class);
|
$routes = $this->loader->load($this->getNamespace().'\DefaultValueController');
|
||||||
$this->assertCount(3, $routes);
|
$this->assertCount(3, $routes);
|
||||||
$this->assertEquals('/{default}/path', $routes->get('action')->getPath());
|
$this->assertEquals('/{default}/path', $routes->get('action')->getPath());
|
||||||
$this->assertEquals('value', $routes->get('action')->getDefault('default'));
|
$this->assertEquals('value', $routes->get('action')->getDefault('default'));
|
||||||
@ -146,7 +112,7 @@ class AnnotationClassLoaderTest extends AbstractAnnotationLoaderTest
|
|||||||
|
|
||||||
public function testMethodActionControllers()
|
public function testMethodActionControllers()
|
||||||
{
|
{
|
||||||
$routes = $this->loader->load(MethodActionControllers::class);
|
$routes = $this->loader->load($this->getNamespace().'\MethodActionControllers');
|
||||||
$this->assertSame(['put', 'post'], array_keys($routes->all()));
|
$this->assertSame(['put', 'post'], array_keys($routes->all()));
|
||||||
$this->assertEquals('/the/path', $routes->get('put')->getPath());
|
$this->assertEquals('/the/path', $routes->get('put')->getPath());
|
||||||
$this->assertEquals('/the/path', $routes->get('post')->getPath());
|
$this->assertEquals('/the/path', $routes->get('post')->getPath());
|
||||||
@ -154,7 +120,7 @@ class AnnotationClassLoaderTest extends AbstractAnnotationLoaderTest
|
|||||||
|
|
||||||
public function testInvokableClassRouteLoadWithMethodAnnotation()
|
public function testInvokableClassRouteLoadWithMethodAnnotation()
|
||||||
{
|
{
|
||||||
$routes = $this->loader->load(LocalizedMethodActionControllers::class);
|
$routes = $this->loader->load($this->getNamespace().'\LocalizedMethodActionControllers');
|
||||||
$this->assertCount(4, $routes);
|
$this->assertCount(4, $routes);
|
||||||
$this->assertEquals('/the/path', $routes->get('put.en')->getPath());
|
$this->assertEquals('/the/path', $routes->get('put.en')->getPath());
|
||||||
$this->assertEquals('/the/path', $routes->get('post.en')->getPath());
|
$this->assertEquals('/the/path', $routes->get('post.en')->getPath());
|
||||||
@ -162,7 +128,7 @@ class AnnotationClassLoaderTest extends AbstractAnnotationLoaderTest
|
|||||||
|
|
||||||
public function testGlobalDefaultsRoutesLoadWithAnnotation()
|
public function testGlobalDefaultsRoutesLoadWithAnnotation()
|
||||||
{
|
{
|
||||||
$routes = $this->loader->load(GlobalDefaultsClass::class);
|
$routes = $this->loader->load($this->getNamespace().'\GlobalDefaultsClass');
|
||||||
$this->assertCount(2, $routes);
|
$this->assertCount(2, $routes);
|
||||||
|
|
||||||
$specificLocaleRoute = $routes->get('specific_locale');
|
$specificLocaleRoute = $routes->get('specific_locale');
|
||||||
@ -180,7 +146,7 @@ class AnnotationClassLoaderTest extends AbstractAnnotationLoaderTest
|
|||||||
|
|
||||||
public function testUtf8RoutesLoadWithAnnotation()
|
public function testUtf8RoutesLoadWithAnnotation()
|
||||||
{
|
{
|
||||||
$routes = $this->loader->load(Utf8ActionControllers::class);
|
$routes = $this->loader->load($this->getNamespace().'\Utf8ActionControllers');
|
||||||
$this->assertSame(['one', 'two'], array_keys($routes->all()));
|
$this->assertSame(['one', 'two'], array_keys($routes->all()));
|
||||||
$this->assertTrue($routes->get('one')->getOption('utf8'), 'The route must accept utf8');
|
$this->assertTrue($routes->get('one')->getOption('utf8'), 'The route must accept utf8');
|
||||||
$this->assertFalse($routes->get('two')->getOption('utf8'), 'The route must not accept utf8');
|
$this->assertFalse($routes->get('two')->getOption('utf8'), 'The route must not accept utf8');
|
||||||
@ -188,7 +154,7 @@ class AnnotationClassLoaderTest extends AbstractAnnotationLoaderTest
|
|||||||
|
|
||||||
public function testRouteWithPathWithPrefix()
|
public function testRouteWithPathWithPrefix()
|
||||||
{
|
{
|
||||||
$routes = $this->loader->load(PrefixedActionPathController::class);
|
$routes = $this->loader->load($this->getNamespace().'\PrefixedActionPathController');
|
||||||
$this->assertCount(1, $routes);
|
$this->assertCount(1, $routes);
|
||||||
$route = $routes->get('action');
|
$route = $routes->get('action');
|
||||||
$this->assertEquals('/prefix/path', $route->getPath());
|
$this->assertEquals('/prefix/path', $route->getPath());
|
||||||
@ -198,7 +164,7 @@ class AnnotationClassLoaderTest extends AbstractAnnotationLoaderTest
|
|||||||
|
|
||||||
public function testLocalizedRouteWithPathWithPrefix()
|
public function testLocalizedRouteWithPathWithPrefix()
|
||||||
{
|
{
|
||||||
$routes = $this->loader->load(PrefixedActionLocalizedRouteController::class);
|
$routes = $this->loader->load($this->getNamespace().'\PrefixedActionLocalizedRouteController');
|
||||||
$this->assertCount(2, $routes);
|
$this->assertCount(2, $routes);
|
||||||
$this->assertEquals('/prefix/path', $routes->get('action.en')->getPath());
|
$this->assertEquals('/prefix/path', $routes->get('action.en')->getPath());
|
||||||
$this->assertEquals('/prefix/pad', $routes->get('action.nl')->getPath());
|
$this->assertEquals('/prefix/pad', $routes->get('action.nl')->getPath());
|
||||||
@ -206,7 +172,7 @@ class AnnotationClassLoaderTest extends AbstractAnnotationLoaderTest
|
|||||||
|
|
||||||
public function testLocalizedPrefixLocalizedRoute()
|
public function testLocalizedPrefixLocalizedRoute()
|
||||||
{
|
{
|
||||||
$routes = $this->loader->load(LocalizedPrefixLocalizedActionController::class);
|
$routes = $this->loader->load($this->getNamespace().'\LocalizedPrefixLocalizedActionController');
|
||||||
$this->assertCount(2, $routes);
|
$this->assertCount(2, $routes);
|
||||||
$this->assertEquals('/nl/actie', $routes->get('action.nl')->getPath());
|
$this->assertEquals('/nl/actie', $routes->get('action.nl')->getPath());
|
||||||
$this->assertEquals('/en/action', $routes->get('action.en')->getPath());
|
$this->assertEquals('/en/action', $routes->get('action.en')->getPath());
|
||||||
@ -214,73 +180,42 @@ class AnnotationClassLoaderTest extends AbstractAnnotationLoaderTest
|
|||||||
|
|
||||||
public function testInvokableClassMultipleRouteLoad()
|
public function testInvokableClassMultipleRouteLoad()
|
||||||
{
|
{
|
||||||
$classRouteData1 = [
|
$routeCollection = $this->loader->load($this->getNamespace().'\BazClass');
|
||||||
'name' => 'route1',
|
$route = $routeCollection->get('route1');
|
||||||
'path' => '/1',
|
|
||||||
'schemes' => ['https'],
|
|
||||||
'methods' => ['GET'],
|
|
||||||
];
|
|
||||||
|
|
||||||
$classRouteData2 = [
|
$this->assertSame('/1', $route->getPath(), '->load preserves class route path');
|
||||||
'name' => 'route2',
|
$this->assertSame(['https'], $route->getSchemes(), '->load preserves class route schemes');
|
||||||
'path' => '/2',
|
$this->assertSame(['GET'], $route->getMethods(), '->load preserves class route methods');
|
||||||
'schemes' => ['https'],
|
|
||||||
'methods' => ['GET'],
|
|
||||||
];
|
|
||||||
|
|
||||||
$reader = $this->getReader();
|
$route = $routeCollection->get('route2');
|
||||||
$reader
|
|
||||||
->expects($this->exactly(1))
|
|
||||||
->method('getClassAnnotations')
|
|
||||||
->willReturn([new RouteAnnotation($classRouteData1), new RouteAnnotation($classRouteData2)])
|
|
||||||
;
|
|
||||||
$reader
|
|
||||||
->expects($this->once())
|
|
||||||
->method('getMethodAnnotations')
|
|
||||||
->willReturn([])
|
|
||||||
;
|
|
||||||
$loader = new class($reader) extends AnnotationClassLoader {
|
|
||||||
protected function configureRoute(Route $route, \ReflectionClass $class, \ReflectionMethod $method, $annot): void
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
$routeCollection = $loader->load('Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\BazClass');
|
$this->assertSame('/2', $route->getPath(), '->load preserves class route path');
|
||||||
$route = $routeCollection->get($classRouteData1['name']);
|
$this->assertEquals(['https'], $route->getSchemes(), '->load preserves class route schemes');
|
||||||
|
$this->assertEquals(['GET'], $route->getMethods(), '->load preserves class route methods');
|
||||||
$this->assertSame($classRouteData1['path'], $route->getPath(), '->load preserves class route path');
|
|
||||||
$this->assertEquals($classRouteData1['schemes'], $route->getSchemes(), '->load preserves class route schemes');
|
|
||||||
$this->assertEquals($classRouteData1['methods'], $route->getMethods(), '->load preserves class route methods');
|
|
||||||
|
|
||||||
$route = $routeCollection->get($classRouteData2['name']);
|
|
||||||
|
|
||||||
$this->assertSame($classRouteData2['path'], $route->getPath(), '->load preserves class route path');
|
|
||||||
$this->assertEquals($classRouteData2['schemes'], $route->getSchemes(), '->load preserves class route schemes');
|
|
||||||
$this->assertEquals($classRouteData2['methods'], $route->getMethods(), '->load preserves class route methods');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testMissingPrefixLocale()
|
public function testMissingPrefixLocale()
|
||||||
{
|
{
|
||||||
$this->expectException(\LogicException::class);
|
$this->expectException(\LogicException::class);
|
||||||
$this->loader->load(LocalizedPrefixMissingLocaleActionController::class);
|
$this->loader->load($this->getNamespace().'\LocalizedPrefixMissingLocaleActionController');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testMissingRouteLocale()
|
public function testMissingRouteLocale()
|
||||||
{
|
{
|
||||||
$this->expectException(\LogicException::class);
|
$this->expectException(\LogicException::class);
|
||||||
$this->loader->load(LocalizedPrefixMissingRouteLocaleActionController::class);
|
$this->loader->load($this->getNamespace().'\LocalizedPrefixMissingRouteLocaleActionController');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testRouteWithoutName()
|
public function testRouteWithoutName()
|
||||||
{
|
{
|
||||||
$routes = $this->loader->load(MissingRouteNameController::class)->all();
|
$routes = $this->loader->load($this->getNamespace().'\MissingRouteNameController')->all();
|
||||||
$this->assertCount(1, $routes);
|
$this->assertCount(1, $routes);
|
||||||
$this->assertEquals('/path', reset($routes)->getPath());
|
$this->assertEquals('/path', reset($routes)->getPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testNothingButName()
|
public function testNothingButName()
|
||||||
{
|
{
|
||||||
$routes = $this->loader->load(NothingButNameController::class)->all();
|
$routes = $this->loader->load($this->getNamespace().'\NothingButNameController')->all();
|
||||||
$this->assertCount(1, $routes);
|
$this->assertCount(1, $routes);
|
||||||
$this->assertEquals('/', reset($routes)->getPath());
|
$this->assertEquals('/', reset($routes)->getPath());
|
||||||
}
|
}
|
||||||
@ -299,44 +234,18 @@ class AnnotationClassLoaderTest extends AbstractAnnotationLoaderTest
|
|||||||
|
|
||||||
public function testLocalizedPrefixWithoutRouteLocale()
|
public function testLocalizedPrefixWithoutRouteLocale()
|
||||||
{
|
{
|
||||||
$routes = $this->loader->load(LocalizedPrefixWithRouteWithoutLocale::class);
|
$routes = $this->loader->load($this->getNamespace().'\LocalizedPrefixWithRouteWithoutLocale');
|
||||||
$this->assertCount(2, $routes);
|
$this->assertCount(2, $routes);
|
||||||
$this->assertEquals('/en/suffix', $routes->get('action.en')->getPath());
|
$this->assertEquals('/en/suffix', $routes->get('action.en')->getPath());
|
||||||
$this->assertEquals('/nl/suffix', $routes->get('action.nl')->getPath());
|
$this->assertEquals('/nl/suffix', $routes->get('action.nl')->getPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @requires function mb_strtolower
|
|
||||||
*/
|
|
||||||
public function testDefaultRouteName()
|
|
||||||
{
|
|
||||||
$methodRouteData = [
|
|
||||||
'name' => null,
|
|
||||||
];
|
|
||||||
|
|
||||||
$reader = $this->getReader();
|
|
||||||
$reader
|
|
||||||
->expects($this->once())
|
|
||||||
->method('getMethodAnnotations')
|
|
||||||
->willReturn([new RouteAnnotation($methodRouteData)])
|
|
||||||
;
|
|
||||||
|
|
||||||
$loader = new class($reader) extends AnnotationClassLoader {
|
|
||||||
protected function configureRoute(Route $route, \ReflectionClass $class, \ReflectionMethod $method, $annot): void
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
$routeCollection = $loader->load('Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\EncodingClass');
|
|
||||||
|
|
||||||
$defaultName = array_keys($routeCollection->all())[0];
|
|
||||||
|
|
||||||
$this->assertSame($defaultName, 'symfony_component_routing_tests_fixtures_annotatedclasses_encodingclass_routeàction');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testLoadingRouteWithPrefix()
|
public function testLoadingRouteWithPrefix()
|
||||||
{
|
{
|
||||||
$routes = $this->loader->load(RouteWithPrefixController::class);
|
$routes = $this->loader->load($this->getNamespace().'\RouteWithPrefixController');
|
||||||
$this->assertCount(1, $routes);
|
$this->assertCount(1, $routes);
|
||||||
$this->assertEquals('/prefix/path', $routes->get('action')->getPath());
|
$this->assertEquals('/prefix/path', $routes->get('action')->getPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract protected function getNamespace(): string;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Symfony\Component\Routing\Tests\Loader;
|
||||||
|
|
||||||
|
use Doctrine\Common\Annotations\AnnotationReader;
|
||||||
|
use Doctrine\Common\Annotations\AnnotationRegistry;
|
||||||
|
use Symfony\Component\Routing\Loader\AnnotationClassLoader;
|
||||||
|
use Symfony\Component\Routing\Route;
|
||||||
|
|
||||||
|
class AnnotationClassLoaderWithAnnotationsTest extends AnnotationClassLoaderTest
|
||||||
|
{
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
$reader = new AnnotationReader();
|
||||||
|
$this->loader = new class($reader) extends AnnotationClassLoader {
|
||||||
|
protected function configureRoute(Route $route, \ReflectionClass $class, \ReflectionMethod $method, object $annot): void
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
AnnotationRegistry::registerLoader('class_exists');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testDefaultRouteName()
|
||||||
|
{
|
||||||
|
$routeCollection = $this->loader->load($this->getNamespace().'\EncodingClass');
|
||||||
|
$defaultName = array_keys($routeCollection->all())[0];
|
||||||
|
|
||||||
|
$this->assertSame('symfony_component_routing_tests_fixtures_annotationfixtures_encodingclass_routeàction', $defaultName);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getNamespace(): string
|
||||||
|
{
|
||||||
|
return 'Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures';
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Symfony\Component\Routing\Tests\Loader;
|
||||||
|
|
||||||
|
use Symfony\Component\Routing\Loader\AnnotationClassLoader;
|
||||||
|
use Symfony\Component\Routing\Route;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @requires PHP 8
|
||||||
|
*/
|
||||||
|
class AnnotationClassLoaderWithAttributesTest extends AnnotationClassLoaderTest
|
||||||
|
{
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
$this->loader = new class() extends AnnotationClassLoader {
|
||||||
|
protected function configureRoute(Route $route, \ReflectionClass $class, \ReflectionMethod $method, object $annot): void
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testDefaultRouteName()
|
||||||
|
{
|
||||||
|
$routeCollection = $this->loader->load($this->getNamespace().'\EncodingClass');
|
||||||
|
$defaultName = array_keys($routeCollection->all())[0];
|
||||||
|
|
||||||
|
$this->assertSame('symfony_component_routing_tests_fixtures_attributefixtures_encodingclass_routeàction', $defaultName);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getNamespace(): string
|
||||||
|
{
|
||||||
|
return 'Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures';
|
||||||
|
}
|
||||||
|
}
|
@ -26,7 +26,7 @@
|
|||||||
"symfony/yaml": "^4.4|^5.0",
|
"symfony/yaml": "^4.4|^5.0",
|
||||||
"symfony/expression-language": "^4.4|^5.0",
|
"symfony/expression-language": "^4.4|^5.0",
|
||||||
"symfony/dependency-injection": "^4.4|^5.0",
|
"symfony/dependency-injection": "^4.4|^5.0",
|
||||||
"doctrine/annotations": "~1.2",
|
"doctrine/annotations": "^1.7",
|
||||||
"psr/log": "~1.0"
|
"psr/log": "~1.0"
|
||||||
},
|
},
|
||||||
"conflict": {
|
"conflict": {
|
||||||
|
Reference in New Issue
Block a user