[Routing] Fix route URL generation in CLI context

This commit is contained in:
Antonio Pauletich 2019-04-08 20:40:53 +02:00 committed by Fabien Potencier
parent c248646e59
commit 4a1ad4a5d6
6 changed files with 141 additions and 7 deletions

View File

@ -71,6 +71,7 @@
<argument type="service" id="router.request_context" on-invalid="ignore" /> <argument type="service" id="router.request_context" on-invalid="ignore" />
<argument type="service" id="parameter_bag" on-invalid="ignore" /> <argument type="service" id="parameter_bag" on-invalid="ignore" />
<argument type="service" id="logger" on-invalid="ignore" /> <argument type="service" id="logger" on-invalid="ignore" />
<argument>%kernel.default_locale%</argument>
<call method="setConfigCacheFactory"> <call method="setConfigCacheFactory">
<argument type="service" id="config_cache_factory" /> <argument type="service" id="config_cache_factory" />
</call> </call>

View File

@ -43,7 +43,7 @@ class Router extends BaseRouter implements WarmableInterface, ServiceSubscriberI
* @param ContainerInterface|null $parameters A ContainerInterface instance allowing to fetch parameters * @param ContainerInterface|null $parameters A ContainerInterface instance allowing to fetch parameters
* @param LoggerInterface|null $logger * @param LoggerInterface|null $logger
*/ */
public function __construct(ContainerInterface $container, $resource, array $options = [], RequestContext $context = null, ContainerInterface $parameters = null, LoggerInterface $logger = null) public function __construct(ContainerInterface $container, $resource, array $options = [], RequestContext $context = null, ContainerInterface $parameters = null, LoggerInterface $logger = null, string $defaultLocale = null)
{ {
$this->container = $container; $this->container = $container;
$this->resource = $resource; $this->resource = $resource;
@ -58,6 +58,8 @@ class Router extends BaseRouter implements WarmableInterface, ServiceSubscriberI
} else { } else {
throw new \LogicException(sprintf('You should either pass a "%s" instance or provide the $parameters argument of the "%s" method.', SymfonyContainerInterface::class, __METHOD__)); throw new \LogicException(sprintf('You should either pass a "%s" instance or provide the $parameters argument of the "%s" method.', SymfonyContainerInterface::class, __METHOD__));
} }
$this->defaultLocale = $defaultLocale;
} }
/** /**

View File

@ -82,6 +82,32 @@ class RouterTest extends TestCase
$this->assertSame('"bar" == "bar"', $router->getRouteCollection()->get('foo')->getCondition()); $this->assertSame('"bar" == "bar"', $router->getRouteCollection()->get('foo')->getCondition());
} }
public function testGenerateWithDefaultLocale()
{
$routes = new RouteCollection();
$route = new Route('');
$name = 'testFoo';
foreach (['hr' => '/test-hr', 'en' => '/test-en'] as $locale => $path) {
$localizedRoute = clone $route;
$localizedRoute->setDefault('_locale', $locale);
$localizedRoute->setDefault('_canonical_route', $name);
$localizedRoute->setPath($path);
$routes->add($name.'.'.$locale, $localizedRoute);
}
$sc = $this->getServiceContainer($routes);
$router = new Router($sc, '', [], null, null, null, 'hr');
$this->assertSame('/test-hr', $router->generate($name));
$this->assertSame('/test-en', $router->generate($name, ['_locale' => 'en']));
$this->assertSame('/test-hr', $router->generate($name, ['_locale' => 'hr']));
}
public function testDefaultsPlaceholders() public function testDefaultsPlaceholders()
{ {
$routes = new RouteCollection(); $routes = new RouteCollection();

View File

@ -28,7 +28,7 @@
"symfony/polyfill-mbstring": "~1.0", "symfony/polyfill-mbstring": "~1.0",
"symfony/filesystem": "~3.4|~4.0", "symfony/filesystem": "~3.4|~4.0",
"symfony/finder": "~3.4|~4.0", "symfony/finder": "~3.4|~4.0",
"symfony/routing": "^4.1" "symfony/routing": "^4.2.6"
}, },
"require-dev": { "require-dev": {
"doctrine/cache": "~1.0", "doctrine/cache": "~1.0",

View File

@ -73,6 +73,11 @@ class Router implements RouterInterface, RequestMatcherInterface
*/ */
protected $logger; protected $logger;
/**
* @var string|null
*/
protected $defaultLocale;
/** /**
* @var ConfigCacheFactoryInterface|null * @var ConfigCacheFactoryInterface|null
*/ */
@ -90,13 +95,14 @@ class Router implements RouterInterface, RequestMatcherInterface
* @param RequestContext $context The context * @param RequestContext $context The context
* @param LoggerInterface $logger A logger instance * @param LoggerInterface $logger A logger instance
*/ */
public function __construct(LoaderInterface $loader, $resource, array $options = [], RequestContext $context = null, LoggerInterface $logger = null) public function __construct(LoaderInterface $loader, $resource, array $options = [], RequestContext $context = null, LoggerInterface $logger = null, string $defaultLocale = null)
{ {
$this->loader = $loader; $this->loader = $loader;
$this->resource = $resource; $this->resource = $resource;
$this->logger = $logger; $this->logger = $logger;
$this->context = $context ?: new RequestContext(); $this->context = $context ?: new RequestContext();
$this->setOptions($options); $this->setOptions($options);
$this->defaultLocale = $defaultLocale;
} }
/** /**
@ -321,7 +327,7 @@ class Router implements RouterInterface, RequestMatcherInterface
} }
if (null === $this->options['cache_dir'] || null === $this->options['generator_cache_class']) { if (null === $this->options['cache_dir'] || null === $this->options['generator_cache_class']) {
$this->generator = new $this->options['generator_class']($this->getRouteCollection(), $this->context, $this->logger); $this->generator = new $this->options['generator_class']($this->getRouteCollection(), $this->context, $this->logger, $this->defaultLocale);
} else { } else {
$cache = $this->getConfigCacheFactory()->cache($this->options['cache_dir'].'/'.$this->options['generator_cache_class'].'.php', $cache = $this->getConfigCacheFactory()->cache($this->options['cache_dir'].'/'.$this->options['generator_cache_class'].'.php',
function (ConfigCacheInterface $cache) { function (ConfigCacheInterface $cache) {
@ -340,7 +346,7 @@ class Router implements RouterInterface, RequestMatcherInterface
require_once $cache->getPath(); require_once $cache->getPath();
} }
$this->generator = new $this->options['generator_cache_class']($this->context, $this->logger); $this->generator = new $this->options['generator_cache_class']($this->context, $this->logger, $this->defaultLocale);
} }
if ($this->generator instanceof ConfigurableRequirementsInterface) { if ($this->generator instanceof ConfigurableRequirementsInterface) {

View File

@ -162,6 +162,82 @@ class UrlGeneratorTest extends TestCase
$this->assertSame('/app.php/de', $url); $this->assertSame('/app.php/de', $url);
} }
public function testGenerateWithDefaultLocale()
{
$routes = new RouteCollection();
$route = new Route('');
$name = 'test';
foreach (['hr' => '/foo', 'en' => '/bar'] as $locale => $path) {
$localizedRoute = clone $route;
$localizedRoute->setDefault('_locale', $locale);
$localizedRoute->setDefault('_canonical_route', $name);
$localizedRoute->setPath($path);
$routes->add($name.'.'.$locale, $localizedRoute);
}
$generator = $this->getGenerator($routes, [], null, 'hr');
$this->assertSame(
'http://localhost/app.php/foo',
$generator->generate($name, [], UrlGeneratorInterface::ABSOLUTE_URL)
);
}
public function testGenerateWithOverriddenParameterLocale()
{
$routes = new RouteCollection();
$route = new Route('');
$name = 'test';
foreach (['hr' => '/foo', 'en' => '/bar'] as $locale => $path) {
$localizedRoute = clone $route;
$localizedRoute->setDefault('_locale', $locale);
$localizedRoute->setDefault('_canonical_route', $name);
$localizedRoute->setPath($path);
$routes->add($name.'.'.$locale, $localizedRoute);
}
$generator = $this->getGenerator($routes, [], null, 'hr');
$this->assertSame(
'http://localhost/app.php/bar',
$generator->generate($name, ['_locale' => 'en'], UrlGeneratorInterface::ABSOLUTE_URL)
);
}
public function testGenerateWithOverriddenParameterLocaleFromRequestContext()
{
$routes = new RouteCollection();
$route = new Route('');
$name = 'test';
foreach (['hr' => '/foo', 'en' => '/bar'] as $locale => $path) {
$localizedRoute = clone $route;
$localizedRoute->setDefault('_locale', $locale);
$localizedRoute->setDefault('_canonical_route', $name);
$localizedRoute->setPath($path);
$routes->add($name.'.'.$locale, $localizedRoute);
}
$generator = $this->getGenerator($routes, [], null, 'hr');
$context = new RequestContext('/app.php');
$context->setParameter('_locale', 'en');
$generator->setContext($context);
$this->assertSame(
'http://localhost/app.php/bar',
$generator->generate($name, [], UrlGeneratorInterface::ABSOLUTE_URL)
);
}
/** /**
* @expectedException \Symfony\Component\Routing\Exception\RouteNotFoundException * @expectedException \Symfony\Component\Routing\Exception\RouteNotFoundException
*/ */
@ -171,6 +247,29 @@ class UrlGeneratorTest extends TestCase
$this->getGenerator($routes)->generate('test', [], UrlGeneratorInterface::ABSOLUTE_URL); $this->getGenerator($routes)->generate('test', [], UrlGeneratorInterface::ABSOLUTE_URL);
} }
/**
* @expectedException \Symfony\Component\Routing\Exception\RouteNotFoundException
*/
public function testGenerateWithInvalidLocale()
{
$routes = new RouteCollection();
$route = new Route('');
$name = 'test';
foreach (['hr' => '/foo', 'en' => '/bar'] as $locale => $path) {
$localizedRoute = clone $route;
$localizedRoute->setDefault('_locale', $locale);
$localizedRoute->setDefault('_canonical_route', $name);
$localizedRoute->setPath($path);
$routes->add($name.'.'.$locale, $localizedRoute);
}
$generator = $this->getGenerator($routes, [], null, 'fr');
$generator->generate($name);
}
/** /**
* @expectedException \Symfony\Component\Routing\Exception\MissingMandatoryParametersException * @expectedException \Symfony\Component\Routing\Exception\MissingMandatoryParametersException
*/ */
@ -720,7 +819,7 @@ class UrlGeneratorTest extends TestCase
yield ['/app.php/bar/a/b/bam/c/d/e', '/bar/{foo}/bam/{baz}', '(?<!^).+']; yield ['/app.php/bar/a/b/bam/c/d/e', '/bar/{foo}/bam/{baz}', '(?<!^).+'];
} }
protected function getGenerator(RouteCollection $routes, array $parameters = [], $logger = null) protected function getGenerator(RouteCollection $routes, array $parameters = [], $logger = null, string $defaultLocale = null)
{ {
$context = new RequestContext('/app.php'); $context = new RequestContext('/app.php');
foreach ($parameters as $key => $value) { foreach ($parameters as $key => $value) {
@ -728,7 +827,7 @@ class UrlGeneratorTest extends TestCase
$context->$method($value); $context->$method($value);
} }
return new UrlGenerator($routes, $context, $logger); return new UrlGenerator($routes, $context, $logger, $defaultLocale);
} }
protected function getRoutes($name, Route $route) protected function getRoutes($name, Route $route)