[Routing] Handle "_canonical_route"

This commit is contained in:
Nicolas Grekas 2018-02-27 22:29:31 +01:00
parent e32c414b04
commit 4ae66dc18d
11 changed files with 44 additions and 18 deletions

View File

@ -113,9 +113,9 @@ EOF;
?? $this->context->getParameter('_locale')
?: $this->defaultLocale;
if (null !== $locale && isset(self::$declaredRoutes[$name.'.'.$locale])) {
if (null !== $locale && (self::$declaredRoutes[$name.'.'.$locale][1]['_canonical_route'] ?? null) === $name) {
unset($parameters['_locale']);
$name = $name.'.'.$locale;
$name .= '.'.$locale;
} elseif (!isset(self::$declaredRoutes[$name])) {
throw new RouteNotFoundException(sprintf('Unable to generate a URL for the named route "%s" as such route does not exist.', $name));
}

View File

@ -116,7 +116,7 @@ class UrlGenerator implements UrlGeneratorInterface, ConfigurableRequirementsInt
?? $this->context->getParameter('_locale')
?: $this->defaultLocale;
if (null !== $locale && null !== $route = $this->routes->get($name.'.'.$locale)) {
if (null !== $locale && null !== ($route = $this->routes->get($name.'.'.$locale)) && $route->getDefault('_canonical_route') === $name) {
unset($parameters['_locale']);
} elseif (null === $route = $this->routes->get($name)) {
throw new RouteNotFoundException(sprintf('Unable to generate a URL for the named route "%s" as such route does not exist.', $name));

View File

@ -200,6 +200,7 @@ abstract class AnnotationClassLoader implements LoaderInterface
$this->configureRoute($route, $class, $method, $annot);
if (0 !== $locale) {
$route->setDefault('_locale', $locale);
$route->setDefault('_canonical_route', $name);
$collection->add($name.'.'.$locale, $route);
} else {
$collection->add($name, $route);

View File

@ -54,6 +54,7 @@ class ImportConfigurator
foreach ($prefix as $locale => $localePrefix) {
$localizedRoute = clone $route;
$localizedRoute->setDefault('_locale', $locale);
$localizedRoute->setDefault('_canonical_route', $name);
$localizedRoute->setPath($localePrefix.$route->getPath());
$this->route->add($name.'.'.$locale, $localizedRoute);
}

View File

@ -67,6 +67,7 @@ trait AddTrait
$routes->add($name.'.'.$locale, $route = $this->createRoute($path));
$this->collection->add($this->name.$name.'.'.$locale, $route);
$route->setDefault('_locale', $locale);
$route->setDefault('_canonical_route', $this->name.$name);
}
return new RouteConfigurator($this->collection, $routes, $this->name, $parentConfigurator, $this->prefixes);

View File

@ -130,9 +130,9 @@ class XmlFileLoader extends FileLoader
} else {
foreach ($paths as $locale => $p) {
$defaults['_locale'] = $locale;
$routeName = $id.'.'.$locale;
$defaults['_canonical_route'] = $id;
$route = new Route($p, $defaults, $requirements, $options, $node->getAttribute('host'), $schemes, $methods, $condition);
$collection->add($routeName, $route);
$collection->add($id.'.'.$locale, $route);
}
}
}
@ -183,6 +183,7 @@ class XmlFileLoader extends FileLoader
$localizedRoute = clone $route;
$localizedRoute->setPath($localePrefix.$route->getPath());
$localizedRoute->setDefault('_locale', $locale);
$localizedRoute->setDefault('_canonical_route', $name);
$subCollection->add($name.'.'.$locale, $localizedRoute);
}
} elseif (!isset($prefixes[$locale])) {

View File

@ -126,6 +126,7 @@ class YamlFileLoader extends FileLoader
foreach ($config['path'] as $locale => $path) {
$localizedRoute = clone $route;
$localizedRoute->setDefault('_locale', $locale);
$localizedRoute->setDefault('_canonical_route', $name);
$localizedRoute->setPath($path);
$collection->add($name.'.'.$locale, $localizedRoute);
}
@ -176,6 +177,7 @@ class YamlFileLoader extends FileLoader
foreach ($prefix as $locale => $localePrefix) {
$localizedRoute = clone $route;
$localizedRoute->setDefault('_locale', $locale);
$localizedRoute->setDefault('_canonical_route', $name);
$localizedRoute->setPath($localePrefix.$route->getPath());
$subCollection->add($name.'.'.$locale, $localizedRoute);
}

View File

@ -256,10 +256,15 @@ EOF
}
if (!$route->getCondition()) {
$defaults = $route->getDefaults();
if (isset($defaults['_canonical_route'])) {
$name = $defaults['_canonical_route'];
unset($defaults['_canonical_route']);
}
$default .= sprintf(
"%s => array(%s, %s, %s, %s),\n",
self::export($url),
self::export(array('_route' => $name) + $route->getDefaults()),
self::export(array('_route' => $name) + $defaults),
self::export(!$route->compile()->getHostVariables() ? $route->getHost() : $route->compile()->getHostRegex() ?: null),
self::export(array_flip($route->getMethods()) ?: null),
self::export(array_flip($route->getSchemes()) ?: null)
@ -490,10 +495,15 @@ EOF;
if (!$route->getCondition() && (!is_array($next = $routes[1 + $i] ?? null) || $regex !== $next[1])) {
$prevRegex = null;
$defaults = $route->getDefaults();
if (isset($defaults['_canonical_route'])) {
$name = $defaults['_canonical_route'];
unset($defaults['_canonical_route']);
}
$state->default .= sprintf(
"%s => array(%s, %s, %s, %s),\n",
$state->mark,
self::export(array('_route' => $name) + $route->getDefaults()),
self::export(array('_route' => $name) + $defaults),
self::export($vars),
self::export(array_flip($route->getMethods()) ?: null),
self::export(array_flip($route->getSchemes()) ?: null)
@ -619,6 +629,11 @@ EOF;
// the offset where the return value is appended below, with indendation
$retOffset = 12 + strlen($code);
$defaults = $route->getDefaults();
if (isset($defaults['_canonical_route'])) {
$name = $defaults['_canonical_route'];
unset($defaults['_canonical_route']);
}
// optimize parameters array
if ($matches || $hostMatches) {
@ -633,10 +648,10 @@ EOF;
$code .= sprintf(
" \$ret = \$this->mergeDefaults(%s, %s);\n",
implode(' + ', $vars),
self::export($route->getDefaults())
self::export($defaults)
);
} elseif ($route->getDefaults()) {
$code .= sprintf(" \$ret = %s;\n", self::export(array_replace($route->getDefaults(), array('_route' => $name))));
} elseif ($defaults) {
$code .= sprintf(" \$ret = %s;\n", self::export(array('_route' => $name) + $defaults));
} else {
$code .= sprintf(" \$ret = array('_route' => '%s');\n", $name);
}

View File

@ -194,9 +194,14 @@ class UrlMatcher implements UrlMatcherInterface, RequestMatcherInterface
*/
protected function getAttributes(Route $route, $name, array $attributes)
{
$defaults = $route->getDefaults();
if (isset($defaults['_canonical_route'])) {
$name = $defaults['_canonical_route'];
unset($defaults['_canonical_route']);
}
$attributes['_route'] = $name;
return $this->mergeDefaults($attributes, $route->getDefaults());
return $this->mergeDefaults($attributes, $defaults);
}
/**

View File

@ -86,8 +86,8 @@ class PhpGeneratorDumperTest extends TestCase
public function testDumpWithLocalizedRoutes()
{
$this->routeCollection->add('test.en', (new Route('/testing/is/fun'))->setDefault('_locale', 'en'));
$this->routeCollection->add('test.nl', (new Route('/testen/is/leuk'))->setDefault('_locale', 'nl'));
$this->routeCollection->add('test.en', (new Route('/testing/is/fun'))->setDefault('_locale', 'en')->setDefault('_canonical_route', 'test'));
$this->routeCollection->add('test.nl', (new Route('/testen/is/leuk'))->setDefault('_locale', 'nl')->setDefault('_canonical_route', 'test'));
$code = $this->generatorDumper->dump([
'class' => 'LocalizedProjectUrlGenerator',

View File

@ -126,11 +126,11 @@ class PhpFileLoaderTest extends TestCase
$expectedCollection = new RouteCollection();
$expectedCollection->add('foo.en', (new Route('/glish/foo'))->setDefaults(array('_locale' => 'en')));
$expectedCollection->add('bar.en', (new Route('/glish/bar'))->setDefaults(array('_locale' => 'en')));
$expectedCollection->add('baz.en', (new Route('/baz'))->setDefaults(array('_locale' => 'en')));
$expectedCollection->add('c_foo.fr', (new Route('/ench/pub/foo'))->setDefaults(array('_locale' => 'fr')));
$expectedCollection->add('c_bar.fr', (new Route('/ench/pub/bar'))->setDefaults(array('_locale' => 'fr')));
$expectedCollection->add('foo.en', (new Route('/glish/foo'))->setDefaults(array('_locale' => 'en', '_canonical_route' => 'foo')));
$expectedCollection->add('bar.en', (new Route('/glish/bar'))->setDefaults(array('_locale' => 'en', '_canonical_route' => 'bar')));
$expectedCollection->add('baz.en', (new Route('/baz'))->setDefaults(array('_locale' => 'en', '_canonical_route' => 'baz')));
$expectedCollection->add('c_foo.fr', (new Route('/ench/pub/foo'))->setDefaults(array('_locale' => 'fr', '_canonical_route' => 'c_foo')));
$expectedCollection->add('c_bar.fr', (new Route('/ench/pub/bar'))->setDefaults(array('_locale' => 'fr', '_canonical_route' => 'c_bar')));
$expectedCollection->addResource(new FileResource(realpath(__DIR__.'/../Fixtures/php_dsl_sub_i18n.php')));
$expectedCollection->addResource(new FileResource(realpath(__DIR__.'/../Fixtures/php_dsl_i18n.php')));