Skip to content

Commit 3db2a42

Browse files
author
renanbr
committed
[Routing] Allow to inject service to expression condition
Gather routing variables into a service locator Add service() function for route condition Add missing file Fix psalm remove routing variable concept Add tests and rename routing condition service
1 parent 9cb6274 commit 3db2a42

File tree

17 files changed

+368
-0
lines changed

17 files changed

+368
-0
lines changed

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ class UnusedTagsPass implements CompilerPassInterface
7575
'routing.expression_language_provider',
7676
'routing.loader',
7777
'routing.route_loader',
78+
'routing.condition_service',
7879
'security.authenticator.login_linker',
7980
'security.expression_language_provider',
8081
'security.remember_me_aware',

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
use Symfony\Bridge\Twig\Extension\CsrfExtension;
2828
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
2929
use Symfony\Bundle\FrameworkBundle\Routing\AnnotatedRouteControllerLoader;
30+
use Symfony\Bundle\FrameworkBundle\Routing\Attribute\AsRoutingConditionService;
3031
use Symfony\Bundle\FrameworkBundle\Routing\RouteLoaderInterface;
3132
use Symfony\Bundle\FullStack;
3233
use Symfony\Bundle\MercureBundle\MercureBundle;
@@ -666,6 +667,10 @@ public function load(array $configs, ContainerBuilder $container)
666667
'kernel.locale_aware',
667668
'kernel.reset',
668669
]);
670+
671+
$container->registerAttributeForAutoconfiguration(AsRoutingConditionService::class, static function (ChildDefinition $definition, AsRoutingConditionService $attribute): void {
672+
$definition->addTag('routing.condition_service', (array) $attribute);
673+
});
669674
}
670675

671676
/**

src/Symfony/Bundle/FrameworkBundle/Resources/config/services.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,14 @@ class_exists(WorkflowEvents::class) ? WorkflowEvents::ALIASES : []
200200
])
201201
->tag('routing.expression_language_function', ['function' => 'env'])
202202

203+
->set('container.get_routing_condition_service', \Closure::class)
204+
->public()
205+
->factory([\Closure::class, 'fromCallable'])
206+
->args([
207+
[tagged_locator('routing.condition_service', 'alias'), 'get'],
208+
])
209+
->tag('routing.expression_language_function', ['function' => 'service'])
210+
203211
// inherit from this service to lazily access env vars
204212
->set('container.env', LazyString::class)
205213
->abstract()
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
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\Bundle\FrameworkBundle\Routing\Attribute;
13+
14+
#[\Attribute(\Attribute::TARGET_CLASS)]
15+
class AsRoutingConditionService
16+
{
17+
public function __construct(
18+
public ?string $alias = null,
19+
public int $priority = 0,
20+
) {
21+
}
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
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\Bundle\FrameworkBundle\Tests\Functional\Bundle\RoutingConditionServiceBundle\Controller;
13+
14+
use Symfony\Component\HttpFoundation\Response;
15+
use Symfony\Component\Routing\Annotation\Route;
16+
17+
class DefaultController
18+
{
19+
#[Route(
20+
path: '/allowed/manually-tagged',
21+
condition: 'service("manually_tagged").giveMeTrue()',
22+
)]
23+
public function allowedByManuallyTagged(): Response
24+
{
25+
return new Response();
26+
}
27+
28+
#[Route(
29+
path: '/allowed/auto-configured',
30+
condition: 'service("auto_configured").flip(false)',
31+
)]
32+
public function allowedByAutoConfigured(): Response
33+
{
34+
return new Response();
35+
}
36+
37+
#[Route(
38+
path: '/allowed/auto-configured-non-aliased',
39+
condition: 'service("auto_configured_non_aliased").alwaysTrue()',
40+
)]
41+
public function allowedByAutoConfiguredNonAliased(): Response
42+
{
43+
return new Response();
44+
}
45+
46+
#[Route(
47+
path: '/denied/manually-tagged',
48+
condition: 'service("manually_tagged").giveMeFalse()',
49+
)]
50+
public function deniedByManuallyTagged(): Response
51+
{
52+
return new Response();
53+
}
54+
55+
#[Route(
56+
path: '/denied/auto-configured',
57+
condition: 'service("auto_configured").flip(true)',
58+
)]
59+
public function deniedByAutoConfigured(): Response
60+
{
61+
return new Response();
62+
}
63+
64+
#[Route(
65+
path: '/denied/auto-configured-non-aliased',
66+
condition: 'service("auto_configured_non_aliased").alwaysFalse()',
67+
)]
68+
public function deniedByAutoConfiguredNonAliased(): Response
69+
{
70+
return new Response();
71+
}
72+
73+
#[Route(
74+
path: '/denied/overridden',
75+
condition: 'service("foo").isAllowed()',
76+
)]
77+
public function deniedByOverriddenAlias(): Response
78+
{
79+
return new Response();
80+
}
81+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
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\Bundle\FrameworkBundle\Tests\Functional\Bundle\RoutingConditionServiceBundle;
13+
14+
use Symfony\Component\HttpKernel\Bundle\Bundle;
15+
16+
class RoutingConditionServiceBundle extends Bundle
17+
{
18+
}
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\Bundle\FrameworkBundle\Tests\Functional\Bundle\RoutingConditionServiceBundle\Service;
13+
14+
use Symfony\Bundle\FrameworkBundle\Routing\Attribute\AsRoutingConditionService;
15+
16+
#[AsRoutingConditionService]
17+
class AutoConfiguredNonAliasedService
18+
{
19+
public function alwaysFalse(): bool
20+
{
21+
return false;
22+
}
23+
24+
public function alwaysTrue(): bool
25+
{
26+
return true;
27+
}
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
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\Bundle\FrameworkBundle\Tests\Functional\Bundle\RoutingConditionServiceBundle\Service;
13+
14+
use Symfony\Bundle\FrameworkBundle\Routing\Attribute\AsRoutingConditionService;
15+
16+
#[AsRoutingConditionService('auto_configured')]
17+
class AutoConfiguredService
18+
{
19+
public function flip(bool $value): bool
20+
{
21+
return !$value;
22+
}
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
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\Bundle\FrameworkBundle\Tests\Functional\Bundle\RoutingConditionServiceBundle\Service;
13+
14+
use Symfony\Bundle\FrameworkBundle\Routing\Attribute\AsRoutingConditionService;
15+
16+
#[AsRoutingConditionService('foo')]
17+
class FooOriginalService
18+
{
19+
public function isAllowed(): bool
20+
{
21+
return true;
22+
}
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
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\Bundle\FrameworkBundle\Tests\Functional\Bundle\RoutingConditionServiceBundle\Service;
13+
14+
use Symfony\Bundle\FrameworkBundle\Routing\Attribute\AsRoutingConditionService;
15+
16+
#[AsRoutingConditionService(alias: 'foo', priority: -1)]
17+
class FooReplacementService
18+
{
19+
public function isAllowed(): bool
20+
{
21+
return false;
22+
}
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
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\Bundle\FrameworkBundle\Tests\Functional\Bundle\RoutingConditionServiceBundle\Service;
13+
14+
class ManuallyTaggedService
15+
{
16+
public function giveMeTrue(): bool
17+
{
18+
return true;
19+
}
20+
21+
public function giveMeFalse(): bool
22+
{
23+
return false;
24+
}
25+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
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\Bundle\FrameworkBundle\Tests\Functional;
13+
14+
class RoutingConditionServiceTest extends AbstractWebTestCase
15+
{
16+
/**
17+
* @dataProvider provideRoutes
18+
*/
19+
public function testCondition(int $code, string $path): void
20+
{
21+
$client = static::createClient(['test_case' => 'RoutingConditionService']);
22+
23+
$client->request('GET', $path);
24+
$this->assertSame($code, $client->getResponse()->getStatusCode());
25+
}
26+
27+
public function provideRoutes(): iterable
28+
{
29+
yield 'allowed by an autoconfigured service' => [
30+
200,
31+
'/allowed/manually-tagged',
32+
];
33+
34+
yield 'allowed by a manually tagged service' => [
35+
200,
36+
'/allowed/auto-configured',
37+
];
38+
39+
yield 'allowed by a manually tagged non aliased service' => [
40+
200,
41+
'/allowed/auto-configured-non-aliased',
42+
];
43+
44+
yield 'denied by an autoconfigured service' => [
45+
404,
46+
'/denied/manually-tagged',
47+
];
48+
49+
yield 'denied by a manually tagged service' => [
50+
404,
51+
'/denied/auto-configured',
52+
];
53+
54+
yield 'denied by a manually tagged non aliased service' => [
55+
404,
56+
'/denied/auto-configured-non-aliased',
57+
];
58+
59+
yield 'denied by an overridden service' => [
60+
404,
61+
'/denied/overridden',
62+
];
63+
}
64+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
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+
use Symfony\Bundle\FrameworkBundle\FrameworkBundle;
13+
use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\RoutingConditionServiceBundle\RoutingConditionServiceBundle;
14+
15+
return [
16+
new FrameworkBundle(),
17+
new RoutingConditionServiceBundle(),
18+
];
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
imports:
2+
- { resource: ../config/default.yml }
3+
- { resource: services_auto_configured.yml }
4+
- { resource: services_manually_configured.yml }
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
_routingconditionservice_bundle:
2+
prefix: /
3+
resource: "@RoutingConditionServiceBundle/Controller"
4+
type: annotation

0 commit comments

Comments
 (0)