Skip to content

Commit cb75972

Browse files
committed
wip deprecations in route attributes
1 parent 51d50e7 commit cb75972

File tree

8 files changed

+215
-27
lines changed

8 files changed

+215
-27
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Routing\Attribute;
13+
14+
/**
15+
* This class is meant to be used in {@see \Symfony\Component\Routing\Attribute\Route} to define an alias for a route.
16+
*/
17+
class DeprecatedAlias {
18+
public function __construct(
19+
private string $aliasName,
20+
private string $package,
21+
private string $version,
22+
private string $message = '',
23+
){
24+
}
25+
26+
public function getMessage(): string
27+
{
28+
return $this->message;
29+
}
30+
31+
public function getAliasName(): string
32+
{
33+
return $this->aliasName;
34+
}
35+
36+
public function getPackage(): string
37+
{
38+
return $this->package;
39+
}
40+
41+
public function getVersion(): string
42+
{
43+
return $this->version;
44+
}
45+
}

src/Symfony/Component/Routing/Attribute/Route.php

+11-15
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@ class Route
2424
private array $localizedPaths = [];
2525
private array $methods;
2626
private array $schemes;
27-
private array $aliases;
27+
/**
28+
* @var DeprecatedAlias[]|string[]
29+
*/
30+
private array $aliases = [];
2831

2932
/**
3033
* @param string|array<string,string>|null $path The route path (i.e. "/user/login")
@@ -42,7 +45,7 @@ class Route
4245
* @param bool|null $utf8 Whether the route accepts UTF-8 in its parameters
4346
* @param bool|null $stateless Whether the route is defined as stateless or stateful, @see https://symfony.com/doc/current/routing.html#stateless-routes
4447
* @param string|null $env The env in which the route is defined (i.e. "dev", "test", "prod")
45-
* @param string|string[] $alias The list of aliases for this route
48+
* @param string|string[]|DeprecatedAlias|DeprecatedAlias[] $alias The list of aliases for this route
4649
*/
4750
public function __construct(
4851
string|array|null $path = null,
@@ -60,7 +63,7 @@ public function __construct(
6063
?bool $utf8 = null,
6164
?bool $stateless = null,
6265
private ?string $env = null,
63-
array|string $alias = [],
66+
string|DeprecatedAlias|array $alias = [],
6467
) {
6568
if (\is_array($path)) {
6669
$this->localizedPaths = $path;
@@ -209,28 +212,21 @@ public function getEnv(): ?string
209212
}
210213

211214
/**
212-
* @return string[]
215+
* @return string[]|DeprecatedAlias[]
213216
*/
214217
public function getAliases(): array
215218
{
216219
return $this->aliases;
217220
}
218221

219222
/**
220-
* @param string[]|string $aliases
223+
* @param string|DeprecatedAlias|string[]|DeprecatedAlias[] $aliases
221224
*
222225
* @throws InvalidArgumentException if the "alias" argument is not a string or an array of strings
223226
*/
224-
public function setAliases(array|string $aliases): void
225-
{
226-
if (\is_array($aliases)) {
227-
foreach ($aliases as $a) {
228-
if (!\is_string($a)) {
229-
throw new InvalidArgumentException(\sprintf('The "alias" argument of the Route attribute must be a string or an array of strings. Got "%s".', get_debug_type($a)));
230-
}
231-
}
232-
}
233-
$this->aliases = (array) $aliases;
227+
public function setAliases(string|DeprecatedAlias|array $aliases): void
228+
{
229+
$this->aliases = $aliases instanceof DeprecatedAlias || \is_string($aliases) ? [$aliases] : $aliases;
234230
}
235231
}
236232

src/Symfony/Component/Routing/Loader/AttributeClassLoader.php

+13-3
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ public function load(mixed $class, ?string $type = null): RouteCollection
111111
if (!$class->hasMethod('__invoke')) {
112112
foreach ($this->getAttributes($class) as $attr) {
113113
if ($attr->getAliases()) {
114-
throw new \InvalidArgumentException(\sprintf('Route aliases cannot be used on non-invokable class "%s".', $class->name));
114+
throw new \InvalidArgumentException(\sprintf('Route aliases cannot be used on non-invokable class "%s".', $class->getName()));
115115
}
116116
}
117117
}
@@ -239,8 +239,18 @@ protected function addRoute(RouteCollection $collection, object $attr, array $gl
239239
} else {
240240
$collection->add($name, $route, $priority);
241241
}
242-
foreach ($attr->getAliases() as $alias) {
243-
$collection->addAlias($alias, $name);
242+
foreach ($attr->getAliases() as $aliasAttribute) {
243+
if (\is_string($aliasAttribute)) {
244+
$collection->addAlias($aliasAttribute, $name);
245+
continue;
246+
}
247+
248+
$alias = $collection->addAlias($aliasAttribute->getAliasName(), $name);
249+
$alias->setDeprecated(
250+
$aliasAttribute->getPackage(),
251+
$aliasAttribute->getVersion(),
252+
$aliasAttribute->getMessage()
253+
);
244254
}
245255
}
246256
}

src/Symfony/Component/Routing/Tests/Attribute/RouteTest.php

+1-9
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
* file that was distributed with this source code.
1010
*/
1111

12-
namespace Symfony\Component\Routing\Tests\Annotation;
12+
namespace Symfony\Component\Routing\Tests\Attribute;
1313

1414
use PHPUnit\Framework\TestCase;
1515
use Symfony\Component\Routing\Attribute\Route;
@@ -28,14 +28,6 @@ public function testLoadFromAttribute(string $methodName, string $getter, mixed
2828
$this->assertEquals($route->$getter(), $expectedReturn);
2929
}
3030

31-
public function testAliasIsAnArrayOfString()
32-
{
33-
$this->expectException(InvalidArgumentException::class);
34-
$this->expectExceptionMessage('The "alias" argument of the Route attribute must be a string or an array of strings. Got "stdClass".');
35-
36-
new Route('/hello', alias: ['alias', new \stdClass()]);
37-
}
38-
3931
public static function getValidParameters(): iterable
4032
{
4133
return [
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures;
13+
14+
use Symfony\Component\Routing\Attribute\DeprecatedAlias;
15+
use Symfony\Component\Routing\Attribute\Route;
16+
17+
class DeprecatedAliasCustomMessageRouteController
18+
{
19+
20+
#[Route('/path', name: 'action_with_deprecated_alias', alias: new DeprecatedAlias('my_other_alias_deprecated', 'MyBundleFixture', '1.0', message: '%alias_id% alias is deprecated.'))]
21+
public function action()
22+
{
23+
}
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures;
13+
14+
use Symfony\Component\Routing\Attribute\DeprecatedAlias;
15+
use Symfony\Component\Routing\Attribute\Route;
16+
17+
class DeprecatedAliasRouteController
18+
{
19+
20+
#[Route('/path', name: 'action_with_deprecated_alias', alias: new DeprecatedAlias('my_other_alias_deprecated', 'MyBundleFixture', '1.0'))]
21+
public function action()
22+
{
23+
}
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures;
13+
14+
use Symfony\Component\Routing\Attribute\DeprecatedAlias;
15+
use Symfony\Component\Routing\Attribute\Route;
16+
17+
class MultipleDeprecatedAliasRouteController
18+
{
19+
20+
#[Route('/path', name: 'action_with_multiple_deprecated_alias', alias: [
21+
new DeprecatedAlias('my_first_alias_deprecated', 'MyFirstBundleFixture', '1.0'),
22+
new DeprecatedAlias('my_second_alias_deprecated', 'MySecondBundleFixture', '2.0'),
23+
new DeprecatedAlias('my_third_alias_deprecated', 'SurprisedThirdBundleFixture', '3.0'),
24+
])]
25+
public function action()
26+
{
27+
}
28+
}

src/Symfony/Component/Routing/Tests/Loader/AttributeClassLoaderTest.php

+69
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
use Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\AliasRouteController;
2222
use Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\BazClass;
2323
use Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\DefaultValueController;
24+
use Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\DeprecatedAliasCustomMessageRouteController;
25+
use Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\DeprecatedAliasRouteController;
2426
use Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\EncodingClass;
2527
use Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\ExplicitLocalizedActionPathController;
2628
use Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\ExtendedRouteOnClassController;
@@ -38,6 +40,7 @@
3840
use Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\MethodActionControllers;
3941
use Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\MethodsAndSchemes;
4042
use Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\MissingRouteNameController;
43+
use Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\MultipleDeprecatedAliasRouteController;
4144
use Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\NothingButNameController;
4245
use Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\PrefixedActionLocalizedRouteController;
4346
use Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\PrefixedActionPathController;
@@ -395,4 +398,70 @@ public function testAliasesOnInvokableClass()
395398
$this->assertEquals(new Alias('invokable_path'), $routes->getAlias('alias'));
396399
$this->assertEquals(new Alias('invokable_path'), $routes->getAlias('completely_different_name'));
397400
}
401+
402+
public function testDeprecatedAlias()
403+
{
404+
$routes = $this->loader->load(DeprecatedAliasRouteController::class);
405+
$route = $routes->get('action_with_deprecated_alias');
406+
$expected = (new Alias('action_with_deprecated_alias'))
407+
->setDeprecated(
408+
'MyBundleFixture',
409+
'1.0',
410+
'The "%alias_id%" route alias is deprecated. You should stop using it, as it will be removed in the future.'
411+
);
412+
$actual = $routes->getAlias('my_other_alias_deprecated');
413+
$this->assertCount(1, $routes);
414+
$this->assertSame('/path', $route->getPath());
415+
$this->assertEquals($expected, $actual);
416+
}
417+
418+
public function testDeprecatedAliasWithCustomMessage()
419+
{
420+
$routes = $this->loader->load(DeprecatedAliasCustomMessageRouteController::class);
421+
$route = $routes->get('action_with_deprecated_alias');
422+
$expected = (new Alias('action_with_deprecated_alias'))
423+
->setDeprecated(
424+
'MyBundleFixture',
425+
'1.0',
426+
'%alias_id% alias is deprecated.'
427+
);
428+
$actual = $routes->getAlias('my_other_alias_deprecated');
429+
$this->assertCount(1, $routes);
430+
$this->assertSame('/path', $route->getPath());
431+
$this->assertEquals($expected, $actual);
432+
}
433+
434+
public function testMultipleDeprecatedAlias()
435+
{
436+
$routes = $this->loader->load(MultipleDeprecatedAliasRouteController::class);
437+
$route = $routes->get('action_with_multiple_deprecated_alias');
438+
$this->assertCount(1, $routes);
439+
$this->assertSame('/path', $route->getPath());
440+
441+
$dataset = [
442+
'my_first_alias_deprecated' => [
443+
'package' => 'MyFirstBundleFixture',
444+
'version' => '1.0'
445+
],
446+
'my_second_alias_deprecated' => [
447+
'package' => 'MySecondBundleFixture',
448+
'version' => '2.0'
449+
],
450+
'my_third_alias_deprecated' => [
451+
'package' => 'SurprisedThirdBundleFixture',
452+
'version' => '3.0'
453+
],
454+
];
455+
456+
foreach ($dataset as $aliasName => $aliasData) {
457+
$expected = (new Alias('action_with_multiple_deprecated_alias'))
458+
->setDeprecated(
459+
$aliasData['package'],
460+
$aliasData['version'],
461+
'The "%alias_id%" route alias is deprecated. You should stop using it, as it will be removed in the future.'
462+
);
463+
$actual = $routes->getAlias($aliasName);
464+
$this->assertEquals($expected, $actual);
465+
}
466+
}
398467
}

0 commit comments

Comments
 (0)