From 4b109020d02cdfe02ff1e5096fc58aab12323e62 Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Mon, 24 Jul 2023 13:41:55 +0200 Subject: [PATCH] [Routing] Remove Doctrine annotations support --- UPGRADE-7.0.md | 2 + composer.json | 2 - .../Component/Routing/Annotation/Route.php | 6 - src/Symfony/Component/Routing/CHANGELOG.md | 2 + .../Routing/Loader/AnnotationClassLoader.php | 134 +++++------------- .../Routing/Tests/Annotation/RouteTest.php | 36 +---- .../AbstractClassController.php | 7 - .../ActionPathController.php | 15 -- .../Fixtures/AnnotationFixtures/BazClass.php | 25 ---- .../DefaultValueController.php | 39 ----- .../AnnotationFixtures/EncodingClass.php | 15 -- .../ExplicitLocalizedActionPathController.php | 15 -- .../AnnotationFixtures/FooController.php | 78 ---------- .../GlobalDefaultsClass.php | 48 ------- .../InvokableController.php | 15 -- .../InvokableLocalizedController.php | 15 -- .../InvokableMethodController.php | 15 -- .../LocalizedActionPathController.php | 15 -- .../LocalizedMethodActionControllers.php | 25 ---- ...calizedPrefixLocalizedActionController.php | 18 --- ...zedPrefixMissingLocaleActionController.php | 18 --- ...efixMissingRouteLocaleActionController.php | 18 --- .../LocalizedPrefixWithRouteWithoutLocale.php | 18 --- .../MethodActionControllers.php | 25 ---- .../AnnotationFixtures/MethodsAndSchemes.php | 29 ---- .../MissingRouteNameController.php | 15 -- .../NothingButNameController.php | 15 -- ...PrefixedActionLocalizedRouteController.php | 18 --- .../PrefixedActionPathController.php | 18 --- ...ementsWithoutPlaceholderNameController.php | 27 ---- .../AnnotationFixtures/RouteWithEnv.php | 25 ---- .../RouteWithPrefixController.php | 18 --- .../Utf8ActionControllers.php | 25 ---- .../AbstractClassController.php | 7 + .../AnonymousClassInTrait.php | 24 ---- ...Case.php => AnnotationClassLoaderTest.php} | 116 ++++++++++----- ...notationClassLoaderWithAnnotationsTest.php | 40 ------ ...nnotationClassLoaderWithAttributesTest.php | 35 ----- .../Tests/Loader/AnnotationFileLoaderTest.php | 13 -- src/Symfony/Component/Routing/composer.json | 2 - 40 files changed, 123 insertions(+), 910 deletions(-) delete mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/AnnotationFixtures/AbstractClassController.php delete mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/AnnotationFixtures/ActionPathController.php delete mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/AnnotationFixtures/BazClass.php delete mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/AnnotationFixtures/DefaultValueController.php delete mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/AnnotationFixtures/EncodingClass.php delete mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/AnnotationFixtures/ExplicitLocalizedActionPathController.php delete mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/AnnotationFixtures/FooController.php delete mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/AnnotationFixtures/GlobalDefaultsClass.php delete mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/AnnotationFixtures/InvokableController.php delete mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/AnnotationFixtures/InvokableLocalizedController.php delete mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/AnnotationFixtures/InvokableMethodController.php delete mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/AnnotationFixtures/LocalizedActionPathController.php delete mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/AnnotationFixtures/LocalizedMethodActionControllers.php delete mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/AnnotationFixtures/LocalizedPrefixLocalizedActionController.php delete mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/AnnotationFixtures/LocalizedPrefixMissingLocaleActionController.php delete mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/AnnotationFixtures/LocalizedPrefixMissingRouteLocaleActionController.php delete mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/AnnotationFixtures/LocalizedPrefixWithRouteWithoutLocale.php delete mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/AnnotationFixtures/MethodActionControllers.php delete mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/AnnotationFixtures/MethodsAndSchemes.php delete mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/AnnotationFixtures/MissingRouteNameController.php delete mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/AnnotationFixtures/NothingButNameController.php delete mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/AnnotationFixtures/PrefixedActionLocalizedRouteController.php delete mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/AnnotationFixtures/PrefixedActionPathController.php delete mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/AnnotationFixtures/RequirementsWithoutPlaceholderNameController.php delete mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/AnnotationFixtures/RouteWithEnv.php delete mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/AnnotationFixtures/RouteWithPrefixController.php delete mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/AnnotationFixtures/Utf8ActionControllers.php create mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/AttributeFixtures/AbstractClassController.php delete mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/OtherAnnotatedClasses/AnonymousClassInTrait.php rename src/Symfony/Component/Routing/Tests/Loader/{AnnotationClassLoaderTestCase.php => AnnotationClassLoaderTest.php} (63%) delete mode 100644 src/Symfony/Component/Routing/Tests/Loader/AnnotationClassLoaderWithAnnotationsTest.php delete mode 100644 src/Symfony/Component/Routing/Tests/Loader/AnnotationClassLoaderWithAttributesTest.php diff --git a/UPGRADE-7.0.md b/UPGRADE-7.0.md index ae620a5a7ead4..3bf1d36c83b1b 100644 --- a/UPGRADE-7.0.md +++ b/UPGRADE-7.0.md @@ -198,6 +198,8 @@ Routing ------- * Add argument `$routeParameters` to `UrlMatcher::handleRouteRequirements()` + * Remove Doctrine annotations support in favor of native attributes + * Change the constructor signature of `AnnotationClassLoader` to `__construct(?string $env = null)`, passing an annotation reader as first argument is not supported anymore Security -------- diff --git a/composer.json b/composer.json index 0a270471df520..b91c622653603 100644 --- a/composer.json +++ b/composer.json @@ -126,7 +126,6 @@ "async-aws/sqs": "^1.0", "async-aws/sns": "^1.0", "cache/integration-tests": "dev-master", - "doctrine/annotations": "^1.13.1|^2", "doctrine/collections": "^1.0|^2.0", "doctrine/data-fixtures": "^1.1", "doctrine/dbal": "^3.6", @@ -159,7 +158,6 @@ "conflict": { "ext-psr": "<1.1|>=2", "async-aws/core": "<1.5", - "doctrine/annotations": "<1.13.1", "doctrine/dbal": "<3.6", "doctrine/orm": "<2.15", "egulias/email-validator": "~3.0.0", diff --git a/src/Symfony/Component/Routing/Annotation/Route.php b/src/Symfony/Component/Routing/Annotation/Route.php index 26b5853a119ac..712ce5d50bb33 100644 --- a/src/Symfony/Component/Routing/Annotation/Route.php +++ b/src/Symfony/Component/Routing/Annotation/Route.php @@ -12,12 +12,6 @@ namespace Symfony\Component\Routing\Annotation; /** - * Annotation class for @Route(). - * - * @Annotation - * @NamedArgumentConstructor - * @Target({"CLASS", "METHOD"}) - * * @author Fabien Potencier * @author Alexander M. Turek */ diff --git a/src/Symfony/Component/Routing/CHANGELOG.md b/src/Symfony/Component/Routing/CHANGELOG.md index 5ef8a9af8b3c6..31c6bc2587b74 100644 --- a/src/Symfony/Component/Routing/CHANGELOG.md +++ b/src/Symfony/Component/Routing/CHANGELOG.md @@ -5,6 +5,8 @@ CHANGELOG --- * Add argument `$routeParameters` to `UrlMatcher::handleRouteRequirements()` + * Remove Doctrine annotations support in favor of native attributes + * Change the constructor signature of `AnnotationClassLoader` to `__construct(?string $env = null)`, passing an annotation reader as first argument is not supported anymore 6.4 --- diff --git a/src/Symfony/Component/Routing/Loader/AnnotationClassLoader.php b/src/Symfony/Component/Routing/Loader/AnnotationClassLoader.php index 66e3df3b7696a..8e5d01a68f560 100644 --- a/src/Symfony/Component/Routing/Loader/AnnotationClassLoader.php +++ b/src/Symfony/Component/Routing/Loader/AnnotationClassLoader.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Routing\Loader; -use Doctrine\Common\Annotations\Reader; use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\Config\Loader\LoaderResolverInterface; use Symfony\Component\Config\Resource\FileResource; @@ -52,49 +51,12 @@ */ abstract class AnnotationClassLoader implements LoaderInterface { - /** - * @var Reader|null - * - * @deprecated in Symfony 6.4, this property will be removed in Symfony 7. - */ - protected $reader; - - /** - * @var string|null - */ - protected $env; - - /** - * @var string - */ - protected $routeAnnotationClass = RouteAnnotation::class; - - /** - * @var int - */ - protected $defaultRouteIndex = 0; - - private bool $hasDeprecatedAnnotations = false; - - /** - * @param string|null $env - */ - public function __construct($env = null) - { - if ($env instanceof Reader || null === $env && \func_num_args() > 1 && null !== func_get_arg(1)) { - trigger_deprecation('symfony/routing', '6.4', 'Passing an instance of "%s" as first and the environment as second argument to "%s" is deprecated. Pass the environment as first argument instead.', Reader::class, __METHOD__); + protected string $routeAnnotationClass = RouteAnnotation::class; + protected int $defaultRouteIndex = 0; - $this->reader = $env; - $env = \func_num_args() > 1 ? func_get_arg(1) : null; - } - - if (\is_string($env) || null === $env) { - $this->env = $env; - } elseif ($env instanceof \Stringable || \is_scalar($env)) { - $this->env = (string) $env; - } else { - throw new \TypeError(__METHOD__.sprintf(': Parameter $env was expected to be a string or null, "%s" given.', get_debug_type($env))); - } + public function __construct( + protected readonly ?string $env = null, + ) { } /** @@ -121,48 +83,38 @@ public function load(mixed $class, string $type = null): RouteCollection throw new \InvalidArgumentException(sprintf('Annotations from class "%s" cannot be read as it is abstract.', $class->getName())); } - $this->hasDeprecatedAnnotations = false; - - try { - $globals = $this->getGlobals($class); - $collection = new RouteCollection(); - $collection->addResource(new FileResource($class->getFileName())); - if ($globals['env'] && $this->env !== $globals['env']) { - return $collection; - } - $fqcnAlias = false; - foreach ($class->getMethods() as $method) { - $this->defaultRouteIndex = 0; - $routeNamesBefore = array_keys($collection->all()); - foreach ($this->getAnnotations($method) as $annot) { - $this->addRoute($collection, $annot, $globals, $class, $method); - if ('__invoke' === $method->name) { - $fqcnAlias = true; - } - } - - if (1 === $collection->count() - \count($routeNamesBefore)) { - $newRouteName = current(array_diff(array_keys($collection->all()), $routeNamesBefore)); - $collection->addAlias(sprintf('%s::%s', $class->name, $method->name), $newRouteName); - } - } - if (0 === $collection->count() && $class->hasMethod('__invoke')) { - $globals = $this->resetGlobals(); - foreach ($this->getAnnotations($class) as $annot) { - $this->addRoute($collection, $annot, $globals, $class, $class->getMethod('__invoke')); + $globals = $this->getGlobals($class); + $collection = new RouteCollection(); + $collection->addResource(new FileResource($class->getFileName())); + if ($globals['env'] && $this->env !== $globals['env']) { + return $collection; + } + $fqcnAlias = false; + foreach ($class->getMethods() as $method) { + $this->defaultRouteIndex = 0; + $routeNamesBefore = array_keys($collection->all()); + foreach ($this->getAnnotations($method) as $annot) { + $this->addRoute($collection, $annot, $globals, $class, $method); + if ('__invoke' === $method->name) { $fqcnAlias = true; } } - if ($fqcnAlias && 1 === $collection->count()) { - $collection->addAlias($class->name, $invokeRouteName = key($collection->all())); - $collection->addAlias(sprintf('%s::__invoke', $class->name), $invokeRouteName); - } - if ($this->hasDeprecatedAnnotations) { - trigger_deprecation('symfony/routing', '6.4', 'Class "%s" uses Doctrine Annotations to configure routes, which is deprecated. Use PHP attributes instead.', $class->getName()); + if (1 === $collection->count() - \count($routeNamesBefore)) { + $newRouteName = current(array_diff(array_keys($collection->all()), $routeNamesBefore)); + $collection->addAlias(sprintf('%s::%s', $class->name, $method->name), $newRouteName); } - } finally { - $this->hasDeprecatedAnnotations = false; + } + if (0 === $collection->count() && $class->hasMethod('__invoke')) { + $globals = $this->resetGlobals(); + foreach ($this->getAnnotations($class) as $annot) { + $this->addRoute($collection, $annot, $globals, $class, $class->getMethod('__invoke')); + $fqcnAlias = true; + } + } + if ($fqcnAlias && 1 === $collection->count()) { + $collection->addAlias($class->name, $invokeRouteName = key($collection->all())); + $collection->addAlias(sprintf('%s::__invoke', $class->name), $invokeRouteName); } return $collection; @@ -291,15 +243,9 @@ protected function getGlobals(\ReflectionClass $class): array { $globals = $this->resetGlobals(); - $annot = null; if ($attribute = $class->getAttributes($this->routeAnnotationClass, \ReflectionAttribute::IS_INSTANCEOF)[0] ?? null) { $annot = $attribute->newInstance(); - } - if (!$annot && $annot = $this->reader?->getClassAnnotation($class, $this->routeAnnotationClass)) { - $this->hasDeprecatedAnnotations = true; - } - if ($annot) { if (null !== $annot->getName()) { $globals['name'] = $annot->getName(); } @@ -387,21 +333,5 @@ private function getAnnotations(\ReflectionClass|\ReflectionMethod $reflection): foreach ($reflection->getAttributes($this->routeAnnotationClass, \ReflectionAttribute::IS_INSTANCEOF) as $attribute) { yield $attribute->newInstance(); } - - if (!$this->reader) { - return; - } - - $annotations = $reflection instanceof \ReflectionClass - ? $this->reader->getClassAnnotations($reflection) - : $this->reader->getMethodAnnotations($reflection); - - foreach ($annotations as $annotation) { - if ($annotation instanceof $this->routeAnnotationClass) { - $this->hasDeprecatedAnnotations = true; - - yield $annotation; - } - } } } diff --git a/src/Symfony/Component/Routing/Tests/Annotation/RouteTest.php b/src/Symfony/Component/Routing/Tests/Annotation/RouteTest.php index de671ed961e8a..817a14a202b3a 100644 --- a/src/Symfony/Component/Routing/Tests/Annotation/RouteTest.php +++ b/src/Symfony/Component/Routing/Tests/Annotation/RouteTest.php @@ -11,49 +11,19 @@ namespace Symfony\Component\Routing\Tests\Annotation; -use Doctrine\Common\Annotations\AnnotationReader; use PHPUnit\Framework\TestCase; use Symfony\Component\Routing\Annotation\Route; -use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\FooController; -use Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\FooController as FooAttributesController; +use Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\FooController; class RouteTest extends TestCase { - private function getMethodAnnotation(string $method, bool $attributes): Route - { - $class = $attributes ? FooAttributesController::class : FooController::class; - $reflection = new \ReflectionMethod($class, $method); - - if ($attributes) { - $attributes = $reflection->getAttributes(Route::class); - $route = $attributes[0]->newInstance(); - } else { - $reader = new AnnotationReader(); - $route = $reader->getMethodAnnotation($reflection, Route::class); - } - - if (!$route instanceof Route) { - throw new \Exception('Can\'t parse annotation'); - } - - return $route; - } - /** * @dataProvider getValidParameters */ - public function testLoadFromAttribute(string $methodName, string $getter, $expectedReturn) + public function testLoadFromAttribute(string $methodName, string $getter, mixed $expectedReturn) { - $route = $this->getMethodAnnotation($methodName, true); - $this->assertEquals($route->$getter(), $expectedReturn); - } + $route = (new \ReflectionMethod(FooController::class, $methodName))->getAttributes(Route::class)[0]->newInstance(); - /** - * @dataProvider getValidParameters - */ - public function testLoadFromDoctrineAnnotation(string $methodName, string $getter, $expectedReturn) - { - $route = $this->getMethodAnnotation($methodName, false); $this->assertEquals($route->$getter(), $expectedReturn); } diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/AnnotationFixtures/AbstractClassController.php b/src/Symfony/Component/Routing/Tests/Fixtures/AnnotationFixtures/AbstractClassController.php deleted file mode 100644 index 50576bcf1027e..0000000000000 --- a/src/Symfony/Component/Routing/Tests/Fixtures/AnnotationFixtures/AbstractClassController.php +++ /dev/null @@ -1,7 +0,0 @@ - - * - * 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() - { - } -} diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/AnnotationFixtures/DefaultValueController.php b/src/Symfony/Component/Routing/Tests/Fixtures/AnnotationFixtures/DefaultValueController.php deleted file mode 100644 index c5e0c20d356e1..0000000000000 --- a/src/Symfony/Component/Routing/Tests/Fixtures/AnnotationFixtures/DefaultValueController.php +++ /dev/null @@ -1,39 +0,0 @@ -}", name="hello_without_default") - * @Route("/hello/{name<\w+>?Symfony}", name="hello_with_default") - */ - public function hello(string $name = 'World') - { - } - - /** - * @Route("/enum/{default}", name="string_enum_action") - */ - public function stringEnumAction(TestStringBackedEnum $default = TestStringBackedEnum::Diamonds) - { - } - - /** - * @Route("/enum/{default<\d+>}", name="int_enum_action") - */ - public function intEnumAction(TestIntBackedEnum $default = TestIntBackedEnum::Diamonds) - { - } -} diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/AnnotationFixtures/EncodingClass.php b/src/Symfony/Component/Routing/Tests/Fixtures/AnnotationFixtures/EncodingClass.php deleted file mode 100644 index 52c7b267276ad..0000000000000 --- a/src/Symfony/Component/Routing/Tests/Fixtures/AnnotationFixtures/EncodingClass.php +++ /dev/null @@ -1,15 +0,0 @@ - - * - * 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("/defaults", methods="GET", schemes="https", locale="g_locale", format="g_format") - */ -class GlobalDefaultsClass -{ - /** - * @Route("/specific-locale", name="specific_locale", locale="s_locale") - */ - public function locale() - { - } - - /** - * @Route("/specific-format", name="specific_format", format="s_format") - */ - public function format() - { - } - - /** - * @Route("/redundant-method", name="redundant_method", methods="GET") - */ - public function redundantMethod() - { - } - - /** - * @Route("/redundant-scheme", name="redundant_scheme", methods="https") - */ - public function redundantScheme() - { - } -} diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/AnnotationFixtures/InvokableController.php b/src/Symfony/Component/Routing/Tests/Fixtures/AnnotationFixtures/InvokableController.php deleted file mode 100644 index c70793a81d7a8..0000000000000 --- a/src/Symfony/Component/Routing/Tests/Fixtures/AnnotationFixtures/InvokableController.php +++ /dev/null @@ -1,15 +0,0 @@ - - * - * 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("/", requirements={"foo", "\d+"}) - */ -class RequirementsWithoutPlaceholderNameController -{ - /** - * @Route("/{foo}", name="foo", requirements={"foo", "\d+"}) - */ - public function foo() - { - } -} diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/AnnotationFixtures/RouteWithEnv.php b/src/Symfony/Component/Routing/Tests/Fixtures/AnnotationFixtures/RouteWithEnv.php deleted file mode 100644 index dcc94e7a174e3..0000000000000 --- a/src/Symfony/Component/Routing/Tests/Fixtures/AnnotationFixtures/RouteWithEnv.php +++ /dev/null @@ -1,25 +0,0 @@ - - * - * 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\OtherAnnotatedClasses; - -trait AnonymousClassInTrait -{ - public function test() - { - return new class() { - public function foo() - { - } - }; - } -} diff --git a/src/Symfony/Component/Routing/Tests/Loader/AnnotationClassLoaderTestCase.php b/src/Symfony/Component/Routing/Tests/Loader/AnnotationClassLoaderTest.php similarity index 63% rename from src/Symfony/Component/Routing/Tests/Loader/AnnotationClassLoaderTestCase.php rename to src/Symfony/Component/Routing/Tests/Loader/AnnotationClassLoaderTest.php index 1b43aedc5a7da..b3509a8e11b57 100644 --- a/src/Symfony/Component/Routing/Tests/Loader/AnnotationClassLoaderTestCase.php +++ b/src/Symfony/Component/Routing/Tests/Loader/AnnotationClassLoaderTest.php @@ -14,11 +14,42 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Routing\Alias; use Symfony\Component\Routing\Loader\AnnotationClassLoader; -use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\AbstractClassController; - -abstract class AnnotationClassLoaderTestCase extends TestCase +use Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\AbstractClassController; +use Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\ActionPathController; +use Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\BazClass; +use Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\DefaultValueController; +use Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\EncodingClass; +use Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\ExplicitLocalizedActionPathController; +use Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\GlobalDefaultsClass; +use Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\InvokableController; +use Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\InvokableLocalizedController; +use Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\InvokableMethodController; +use Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\LocalizedActionPathController; +use Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\LocalizedMethodActionControllers; +use Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\LocalizedPrefixLocalizedActionController; +use Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\LocalizedPrefixMissingLocaleActionController; +use Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\LocalizedPrefixMissingRouteLocaleActionController; +use Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\LocalizedPrefixWithRouteWithoutLocale; +use Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\MethodActionControllers; +use Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\MethodsAndSchemes; +use Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\MissingRouteNameController; +use Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\NothingButNameController; +use Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\PrefixedActionLocalizedRouteController; +use Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\PrefixedActionPathController; +use Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\RequirementsWithoutPlaceholderNameController; +use Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\RouteWithEnv; +use Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\RouteWithPrefixController; +use Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\Utf8ActionControllers; +use Symfony\Component\Routing\Tests\Fixtures\TraceableAnnotationClassLoader; + +class AnnotationClassLoaderTest extends TestCase { - protected AnnotationClassLoader $loader; + private AnnotationClassLoader $loader; + + protected function setUp(string $env = null): void + { + $this->loader = new TraceableAnnotationClassLoader($env); + } /** * @dataProvider provideTestSupportsChecksResource @@ -50,10 +81,10 @@ public function testSupportsChecksTypeIfSpecified() public function testSimplePathRoute() { - $routes = $this->loader->load($this->getNamespace().'\ActionPathController'); + $routes = $this->loader->load(ActionPathController::class); $this->assertCount(1, $routes); $this->assertEquals('/path', $routes->get('action')->getPath()); - $this->assertEquals(new Alias('action'), $routes->getAlias($this->getNamespace().'\ActionPathController::action')); + $this->assertEquals(new Alias('action'), $routes->getAlias('Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures' .'\ActionPathController::action')); } public function testRequirementsWithoutPlaceholderName() @@ -61,34 +92,34 @@ public function testRequirementsWithoutPlaceholderName() $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->loader->load($this->getNamespace().'\RequirementsWithoutPlaceholderNameController'); + $this->loader->load(RequirementsWithoutPlaceholderNameController::class); } public function testInvokableControllerLoader() { - $routes = $this->loader->load($this->getNamespace().'\InvokableController'); + $routes = $this->loader->load(InvokableController::class); $this->assertCount(1, $routes); $this->assertEquals('/here', $routes->get('lol')->getPath()); $this->assertEquals(['GET', 'POST'], $routes->get('lol')->getMethods()); $this->assertEquals(['https'], $routes->get('lol')->getSchemes()); - $this->assertEquals(new Alias('lol'), $routes->getAlias($this->getNamespace().'\InvokableController')); - $this->assertEquals(new Alias('lol'), $routes->getAlias($this->getNamespace().'\InvokableController::__invoke')); + $this->assertEquals(new Alias('lol'), $routes->getAlias(InvokableController::class)); + $this->assertEquals(new Alias('lol'), $routes->getAlias('Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\InvokableController::__invoke')); } public function testInvokableMethodControllerLoader() { - $routes = $this->loader->load($this->getNamespace().'\InvokableMethodController'); + $routes = $this->loader->load(InvokableMethodController::class); $this->assertCount(1, $routes); $this->assertEquals('/here', $routes->get('lol')->getPath()); $this->assertEquals(['GET', 'POST'], $routes->get('lol')->getMethods()); $this->assertEquals(['https'], $routes->get('lol')->getSchemes()); - $this->assertEquals(new Alias('lol'), $routes->getAlias($this->getNamespace().'\InvokableMethodController')); - $this->assertEquals(new Alias('lol'), $routes->getAlias($this->getNamespace().'\InvokableMethodController::__invoke')); + $this->assertEquals(new Alias('lol'), $routes->getAlias(InvokableMethodController::class)); + $this->assertEquals(new Alias('lol'), $routes->getAlias('Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\InvokableMethodController::__invoke')); } public function testInvokableLocalizedControllerLoading() { - $routes = $this->loader->load($this->getNamespace().'\InvokableLocalizedController'); + $routes = $this->loader->load(InvokableLocalizedController::class); $this->assertCount(2, $routes); $this->assertEquals('/here', $routes->get('action.en')->getPath()); $this->assertEquals('/hier', $routes->get('action.nl')->getPath()); @@ -96,7 +127,7 @@ public function testInvokableLocalizedControllerLoading() public function testLocalizedPathRoutes() { - $routes = $this->loader->load($this->getNamespace().'\LocalizedActionPathController'); + $routes = $this->loader->load(LocalizedActionPathController::class); $this->assertCount(2, $routes); $this->assertEquals('/path', $routes->get('action.en')->getPath()); $this->assertEquals('/pad', $routes->get('action.nl')->getPath()); @@ -107,7 +138,7 @@ public function testLocalizedPathRoutes() public function testLocalizedPathRoutesWithExplicitPathPropety() { - $routes = $this->loader->load($this->getNamespace().'\ExplicitLocalizedActionPathController'); + $routes = $this->loader->load(ExplicitLocalizedActionPathController::class); $this->assertCount(2, $routes); $this->assertEquals('/path', $routes->get('action.en')->getPath()); $this->assertEquals('/pad', $routes->get('action.nl')->getPath()); @@ -115,7 +146,7 @@ public function testLocalizedPathRoutesWithExplicitPathPropety() public function testDefaultValuesForMethods() { - $routes = $this->loader->load($this->getNamespace().'\DefaultValueController'); + $routes = $this->loader->load(DefaultValueController::class); $this->assertCount(5, $routes); $this->assertEquals('/{default}/path', $routes->get('action')->getPath()); $this->assertEquals('value', $routes->get('action')->getDefault('default')); @@ -127,17 +158,17 @@ public function testDefaultValuesForMethods() public function testMethodActionControllers() { - $routes = $this->loader->load($this->getNamespace().'\MethodActionControllers'); + $routes = $this->loader->load(MethodActionControllers::class); $this->assertSame(['put', 'post'], array_keys($routes->all())); $this->assertEquals('/the/path', $routes->get('put')->getPath()); $this->assertEquals('/the/path', $routes->get('post')->getPath()); - $this->assertEquals(new Alias('post'), $routes->getAlias($this->getNamespace().'\MethodActionControllers::post')); - $this->assertEquals(new Alias('put'), $routes->getAlias($this->getNamespace().'\MethodActionControllers::put')); + $this->assertEquals(new Alias('post'), $routes->getAlias('Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures' .'\MethodActionControllers::post')); + $this->assertEquals(new Alias('put'), $routes->getAlias('Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures' .'\MethodActionControllers::put')); } public function testInvokableClassRouteLoadWithMethodAnnotation() { - $routes = $this->loader->load($this->getNamespace().'\LocalizedMethodActionControllers'); + $routes = $this->loader->load(LocalizedMethodActionControllers::class); $this->assertCount(4, $routes); $this->assertEquals('/the/path', $routes->get('put.en')->getPath()); $this->assertEquals('/the/path', $routes->get('post.en')->getPath()); @@ -145,7 +176,7 @@ public function testInvokableClassRouteLoadWithMethodAnnotation() public function testGlobalDefaultsRoutesLoadWithAnnotation() { - $routes = $this->loader->load($this->getNamespace().'\GlobalDefaultsClass'); + $routes = $this->loader->load(GlobalDefaultsClass::class); $this->assertCount(4, $routes); $specificLocaleRoute = $routes->get('specific_locale'); @@ -166,7 +197,7 @@ public function testGlobalDefaultsRoutesLoadWithAnnotation() public function testUtf8RoutesLoadWithAnnotation() { - $routes = $this->loader->load($this->getNamespace().'\Utf8ActionControllers'); + $routes = $this->loader->load(Utf8ActionControllers::class); $this->assertSame(['one', 'two'], array_keys($routes->all())); $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'); @@ -174,7 +205,7 @@ public function testUtf8RoutesLoadWithAnnotation() public function testRouteWithPathWithPrefix() { - $routes = $this->loader->load($this->getNamespace().'\PrefixedActionPathController'); + $routes = $this->loader->load(PrefixedActionPathController::class); $this->assertCount(1, $routes); $route = $routes->get('action'); $this->assertEquals('/prefix/path', $route->getPath()); @@ -184,7 +215,7 @@ public function testRouteWithPathWithPrefix() public function testLocalizedRouteWithPathWithPrefix() { - $routes = $this->loader->load($this->getNamespace().'\PrefixedActionLocalizedRouteController'); + $routes = $this->loader->load(PrefixedActionLocalizedRouteController::class); $this->assertCount(2, $routes); $this->assertEquals('/prefix/path', $routes->get('action.en')->getPath()); $this->assertEquals('/prefix/pad', $routes->get('action.nl')->getPath()); @@ -192,7 +223,7 @@ public function testLocalizedRouteWithPathWithPrefix() public function testLocalizedPrefixLocalizedRoute() { - $routes = $this->loader->load($this->getNamespace().'\LocalizedPrefixLocalizedActionController'); + $routes = $this->loader->load(LocalizedPrefixLocalizedActionController::class); $this->assertCount(2, $routes); $this->assertEquals('/nl/actie', $routes->get('action.nl')->getPath()); $this->assertEquals('/en/action', $routes->get('action.en')->getPath()); @@ -200,7 +231,7 @@ public function testLocalizedPrefixLocalizedRoute() public function testInvokableClassMultipleRouteLoad() { - $routeCollection = $this->loader->load($this->getNamespace().'\BazClass'); + $routeCollection = $this->loader->load(BazClass::class); $route = $routeCollection->get('route1'); $this->assertSame('/1', $route->getPath(), '->load preserves class route path'); @@ -217,27 +248,27 @@ public function testInvokableClassMultipleRouteLoad() public function testMissingPrefixLocale() { $this->expectException(\LogicException::class); - $this->expectExceptionMessage(sprintf('Route to "action" with locale "en" is missing a corresponding prefix in class "%s\LocalizedPrefixMissingLocaleActionController".', $this->getNamespace())); - $this->loader->load($this->getNamespace().'\LocalizedPrefixMissingLocaleActionController'); + $this->expectExceptionMessage('Route to "action" with locale "en" is missing a corresponding prefix in class "Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\LocalizedPrefixMissingLocaleActionController".'); + $this->loader->load(LocalizedPrefixMissingLocaleActionController::class); } public function testMissingRouteLocale() { $this->expectException(\LogicException::class); - $this->expectExceptionMessage(sprintf('Route to "%s\LocalizedPrefixMissingRouteLocaleActionController::action" is missing paths for locale(s) "en".', $this->getNamespace())); - $this->loader->load($this->getNamespace().'\LocalizedPrefixMissingRouteLocaleActionController'); + $this->expectExceptionMessage('Route to "Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\LocalizedPrefixMissingRouteLocaleActionController::action" is missing paths for locale(s) "en".'); + $this->loader->load(LocalizedPrefixMissingRouteLocaleActionController::class); } public function testRouteWithoutName() { - $routes = $this->loader->load($this->getNamespace().'\MissingRouteNameController')->all(); + $routes = $this->loader->load(MissingRouteNameController::class)->all(); $this->assertCount(1, $routes); $this->assertEquals('/path', reset($routes)->getPath()); } public function testNothingButName() { - $routes = $this->loader->load($this->getNamespace().'\NothingButNameController')->all(); + $routes = $this->loader->load(NothingButNameController::class)->all(); $this->assertCount(1, $routes); $this->assertEquals('/', reset($routes)->getPath()); } @@ -256,7 +287,7 @@ public function testLoadingAbstractClass() public function testLocalizedPrefixWithoutRouteLocale() { - $routes = $this->loader->load($this->getNamespace().'\LocalizedPrefixWithRouteWithoutLocale'); + $routes = $this->loader->load(LocalizedPrefixWithRouteWithoutLocale::class); $this->assertCount(2, $routes); $this->assertEquals('/en/suffix', $routes->get('action.en')->getPath()); $this->assertEquals('/nl/suffix', $routes->get('action.nl')->getPath()); @@ -264,25 +295,25 @@ public function testLocalizedPrefixWithoutRouteLocale() public function testLoadingRouteWithPrefix() { - $routes = $this->loader->load($this->getNamespace().'\RouteWithPrefixController'); + $routes = $this->loader->load(RouteWithPrefixController::class); $this->assertCount(1, $routes); $this->assertEquals('/prefix/path', $routes->get('action')->getPath()); } public function testWhenEnv() { - $routes = $this->loader->load($this->getNamespace().'\RouteWithEnv'); + $routes = $this->loader->load(RouteWithEnv::class); $this->assertCount(0, $routes); $this->setUp('some-env'); - $routes = $this->loader->load($this->getNamespace().'\RouteWithEnv'); + $routes = $this->loader->load(RouteWithEnv::class); $this->assertCount(1, $routes); $this->assertSame('/path', $routes->get('action')->getPath()); } public function testMethodsAndSchemes() { - $routes = $this->loader->load($this->getNamespace().'\MethodsAndSchemes'); + $routes = $this->loader->load(MethodsAndSchemes::class); $this->assertSame(['GET', 'POST'], $routes->get('array_many')->getMethods()); $this->assertSame(['http', 'https'], $routes->get('array_many')->getSchemes()); @@ -292,5 +323,12 @@ public function testMethodsAndSchemes() $this->assertSame(['https'], $routes->get('string')->getSchemes()); } - abstract protected function getNamespace(): string; + public function testDefaultRouteName() + { + $routeCollection = $this->loader->load(EncodingClass::class); + $defaultName = array_keys($routeCollection->all())[0]; + + $this->assertSame('symfony_component_routing_tests_fixtures_attributefixtures_encodingclass_routeàction', $defaultName); + } + } diff --git a/src/Symfony/Component/Routing/Tests/Loader/AnnotationClassLoaderWithAnnotationsTest.php b/src/Symfony/Component/Routing/Tests/Loader/AnnotationClassLoaderWithAnnotationsTest.php deleted file mode 100644 index f53e4e3ef3baf..0000000000000 --- a/src/Symfony/Component/Routing/Tests/Loader/AnnotationClassLoaderWithAnnotationsTest.php +++ /dev/null @@ -1,40 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Tests\Loader; - -use Doctrine\Common\Annotations\AnnotationReader; -use Symfony\Component\Routing\Tests\Fixtures\TraceableAnnotationClassLoader; - -/** - * @group legacy - */ -class AnnotationClassLoaderWithAnnotationsTest extends AnnotationClassLoaderTestCase -{ - protected function setUp(string $env = null): void - { - $reader = new AnnotationReader(); - $this->loader = new TraceableAnnotationClassLoader($reader, $env); - } - - 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'; - } -} diff --git a/src/Symfony/Component/Routing/Tests/Loader/AnnotationClassLoaderWithAttributesTest.php b/src/Symfony/Component/Routing/Tests/Loader/AnnotationClassLoaderWithAttributesTest.php deleted file mode 100644 index 2fe0f903189fd..0000000000000 --- a/src/Symfony/Component/Routing/Tests/Loader/AnnotationClassLoaderWithAttributesTest.php +++ /dev/null @@ -1,35 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Tests\Loader; - -use Symfony\Component\Routing\Tests\Fixtures\TraceableAnnotationClassLoader; - -class AnnotationClassLoaderWithAttributesTest extends AnnotationClassLoaderTestCase -{ - protected function setUp(string $env = null): void - { - $this->loader = new TraceableAnnotationClassLoader($env); - } - - 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'; - } -} diff --git a/src/Symfony/Component/Routing/Tests/Loader/AnnotationFileLoaderTest.php b/src/Symfony/Component/Routing/Tests/Loader/AnnotationFileLoaderTest.php index d92760ae729cb..8451430ce0706 100644 --- a/src/Symfony/Component/Routing/Tests/Loader/AnnotationFileLoaderTest.php +++ b/src/Symfony/Component/Routing/Tests/Loader/AnnotationFileLoaderTest.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Routing\Tests\Loader; -use Doctrine\Common\Annotations\AnnotationReader; use PHPUnit\Framework\TestCase; use Symfony\Component\Config\FileLocator; use Symfony\Component\Routing\Loader\AnnotationFileLoader; @@ -65,18 +64,6 @@ public function testLoadVariadic() self::assertSame([VariadicClass::class], $this->classLoader->foundClasses); } - /** - * @group legacy - */ - public function testLoadAnonymousClass() - { - $this->classLoader = new TraceableAnnotationClassLoader(new AnnotationReader()); - $this->loader = new AnnotationFileLoader(new FileLocator(), $this->classLoader); - - self::assertCount(0, $this->loader->load(__DIR__.'/../Fixtures/OtherAnnotatedClasses/AnonymousClassInTrait.php')); - self::assertSame([], $this->classLoader->foundClasses); - } - public function testLoadAbstractClass() { self::assertNull($this->loader->load(__DIR__.'/../Fixtures/AnnotatedClasses/AbstractClass.php')); diff --git a/src/Symfony/Component/Routing/composer.json b/src/Symfony/Component/Routing/composer.json index a67c957752f92..1a099d8238596 100644 --- a/src/Symfony/Component/Routing/composer.json +++ b/src/Symfony/Component/Routing/composer.json @@ -24,11 +24,9 @@ "symfony/yaml": "^6.4|^7.0", "symfony/expression-language": "^6.4|^7.0", "symfony/dependency-injection": "^6.4|^7.0", - "doctrine/annotations": "^1.12|^2", "psr/log": "^1|^2|^3" }, "conflict": { - "doctrine/annotations": "<1.12", "symfony/config": "<6.4", "symfony/dependency-injection": "<6.4", "symfony/yaml": "<6.4"