Skip to content

Commit 95cf5ab

Browse files
committed
[Routing] Allow to inject service to expression condition
1 parent ba67bc9 commit 95cf5ab

File tree

4 files changed

+85
-1
lines changed

4 files changed

+85
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
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\DependencyInjection\Compiler;
13+
14+
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
15+
use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait;
16+
use Symfony\Component\DependencyInjection\ContainerBuilder;
17+
use Symfony\Component\DependencyInjection\Reference;
18+
19+
class ExpressionConditionVariableResolverPass implements CompilerPassInterface
20+
{
21+
use PriorityTaggedServiceTrait;
22+
23+
public function process(ContainerBuilder $container): void
24+
{
25+
if (false === $container->hasDefinition('routing.router')) {
26+
return;
27+
}
28+
29+
$routerDefinition = $container->getDefinition('routing.router');
30+
31+
foreach ($this->findAndSortTaggedServices('routing.expression_condition_variable', $container) as $reference) {
32+
$serviceId = (string) $reference;
33+
$serviceDefinition = $container->getDefinition($serviceId);
34+
$tag = $serviceDefinition->getTag('routing.expression_condition_variable');
35+
$name = $tag[0]['name'] ?? null;
36+
$routerDefinition->addMethodCall('setExpressionConditionVariable', [$name, $reference]);
37+
}
38+
}
39+
}

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

+7
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@
170170
use Symfony\Component\RateLimiter\LimiterInterface;
171171
use Symfony\Component\RateLimiter\RateLimiterFactory;
172172
use Symfony\Component\RateLimiter\Storage\CacheStorage;
173+
use Symfony\Component\Routing\Attribute\AsRouteExpressionConditionVariable;
173174
use Symfony\Component\Routing\Loader\AnnotationDirectoryLoader;
174175
use Symfony\Component\Routing\Loader\AnnotationFileLoader;
175176
use Symfony\Component\Security\Core\Exception\AuthenticationException;
@@ -616,6 +617,12 @@ public function load(array $configs, ContainerBuilder $container)
616617
'kernel.locale_aware',
617618
'kernel.reset',
618619
]);
620+
621+
$container->registerAttributeForAutoconfiguration(AsRouteExpressionConditionVariable::class, static function (ChildDefinition $definition, AsRouteExpressionConditionVariable $attribute): void {
622+
$definition->addTag('routing.expression_condition_variable', [
623+
'name' => $attribute->name,
624+
]);
625+
});
619626
}
620627

621628
/**
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\Component\Routing\Attribute;
13+
14+
#[\Attribute(\Attribute::TARGET_CLASS)]
15+
class AsRouteExpressionConditionVariable
16+
{
17+
public function __construct(
18+
public string $name,
19+
public int $priority = 0,
20+
) {
21+
}
22+
}

src/Symfony/Component/Routing/Matcher/UrlMatcher.php

+17-1
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,11 @@ class UrlMatcher implements UrlMatcherInterface, RequestMatcherInterface
5656
*/
5757
protected $expressionLanguageProviders = [];
5858

59+
/**
60+
* @var array<string, mixed>
61+
*/
62+
private $expressionConditionVariables = [];
63+
5964
public function __construct(RouteCollection $routes, RequestContext $context)
6065
{
6166
$this->routes = $routes;
@@ -115,6 +120,11 @@ public function addExpressionLanguageProvider(ExpressionFunctionProviderInterfac
115120
$this->expressionLanguageProviders[] = $provider;
116121
}
117122

123+
public function setExpressionConditionVariable(string $name, mixed $value): void
124+
{
125+
$this->expressionConditionVariables[$name] = $value;
126+
}
127+
118128
/**
119129
* Tries to match a URL with a set of routes.
120130
*
@@ -223,7 +233,13 @@ protected function getAttributes(Route $route, string $name, array $attributes):
223233
protected function handleRouteRequirements(string $pathinfo, string $name, Route $route): array
224234
{
225235
// expression condition
226-
if ($route->getCondition() && !$this->getExpressionLanguage()->evaluate($route->getCondition(), ['context' => $this->context, 'request' => $this->request ?: $this->createRequest($pathinfo)])) {
236+
if (
237+
$route->getCondition() &&
238+
!$this->getExpressionLanguage()->evaluate($route->getCondition(), array_merge($this->expressionConditionVariables, [
239+
'context' => $this->context,
240+
'request' => $this->request ?: $this->createRequest($pathinfo),
241+
]))
242+
) {
227243
return [self::REQUIREMENT_MISMATCH, null];
228244
}
229245

0 commit comments

Comments
 (0)