8000 Deal with hosts per locale config · symfony/symfony@79942b2 · GitHub
[go: up one dir, main page]

Skip to content

Commit 79942b2

Browse files
author
Olivier Dolbeau
committed
Deal with hosts per locale config
Ensure prefix & host are working well together Improve tests Implement XML routing Implement PHP routing Make fabbot happy
1 parent 1fc7b86 commit 79942b2

20 files changed

+489
-33
lines changed

src/Symfony/Component/Routing/Loader/Configurator/CollectionConfigurator.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,13 @@
2020
class CollectionConfigurator
2121
{
2222
use Traits\AddTrait;
23+
use Traits\HostTrait;
2324
use Traits\RouteTrait;
2425

2526
private $parent;
2627
private $parentConfigurator;
2728
private $parentPrefixes;
29+
private $host;
2830

2931
public function __construct(RouteCollection $parent, string $name, self $parentConfigurator = null, array $parentPrefixes = null)
3032
{
@@ -41,6 +43,7 @@ public function __destruct()
4143
if (null === $this->prefixes) {
4244
$this->collection->addPrefix($this->route->getPath());
4345
}
46+
$this->addHost($this->collection, $this->host);
4447

4548
$this->parent->addCollection($this->collection);
4649
}
@@ -86,6 +89,20 @@ final public function prefix($prefix): self
8689
return $this;
8790
}
8891

92+
/**
93+
* Sets the host to use for all child routes.
94+
*
95+
* @param string|array $host the host, or the localized hosts
96+
*
97+
* @return $this
98+
*/
99+
final public function host($host): self
100+
{
101+
$this->host = $host;
102+
103+
return $this;
104+
}
105+
89106
private function createRoute(string $path): Route
90107
{
91108
return (clone $this->route)->setPath($path);

src/Symfony/Component/Routing/Loader/Configurator/ImportConfigurator.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
*/
1919
class ImportConfigurator
2020
{
21+
use Traits\HostTrait;
2122
use Traits\PrefixTrait;
2223
use Traits\RouteTrait;
2324

@@ -59,4 +60,18 @@ final public function namePrefix(string $namePrefix): self
5960

6061
return $this;
6162
}
63+
64+
/**
65+
* Sets the host to add to use for all child routes.
66+
*
67+
* @param string|array $host the host, or the localized hosts
68+
*
69+
* @return $this
70+
*/
71+
final public function host($host): self
72+
{
73+
$this->addHost($this->route, $host);
74+
75+
return $this;
76+
}
6277
}

src/Symfony/Component/Routing/Loader/Configurator/RouteConfigurator.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
class RouteConfigurator
2020
{
2121
use Traits\AddTrait;
22+
use Traits\HostTrait;
2223
use Traits\RouteTrait;
2324

2425
protected $parentConfigurator;
@@ -31,4 +32,18 @@ public function __construct(RouteCollection $collection, $route, string $name =
3132
$this->parentConfigurator = $parentConfigurator; // for GC control
3233
$this->prefixes = $prefixes;
3334
}
35+
36+
/**
37+
* Sets the host to use for all child routes.
38+
*
39+
* @param string|array $host the host, or the localized hosts
40+
*
41+
* @return $this
42+
*/
43+
final public function host($host): self
44+
{
45+
$this->addHost($this->collection, $host);
46+
47+
return $this;
48+
}
3449
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
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\Loader\Configurator\Traits;
13+
14+
use Symfony\Component\Routing\RouteCollection;
15+
16+
/**
17+
* @internal
18+
*/
19+
trait HostTrait
20+
{
21+
final protected function addHost(RouteCollection $routes, $host)
22+
{
23+
if (null === $host) {
24+
return;
25+
}
26+
27+
if (!\is_array($host)) {
28+
$routes->setHost($host);
29+
30+
return;
31+
}
32+
33+
if (0 === \count($host)) {
34+
return;
35+
}
36+
37+
foreach ($host as $locale => $localeHost) {
38+
$host[$locale] = trim(trim($localeHost), '/');
39+
}
40+
41+
foreach ($routes->all() as $name => $route) {
42+
if (null === $locale = $route->getDefault('_locale')) {
43+
$routes->remove($name);
44+
foreach ($host as $locale => $localeHost) {
45+
$localizedRoute = clone $route;
46+
$localizedRoute->setDefault('_locale', $locale);
47+
$localizedRoute->setRequirement('_locale', $locale);
48+
$localizedRoute->setDefault('_canonical_route', $name);
49+
$localizedRoute->setHost($localeHost);
50+
$routes->add($name.'.'.$locale, $localizedRoute);
51+
}
52+
} elseif (!isset($host[$locale])) {
53+
throw new \InvalidArgumentException(sprintf('Route "%s" with locale "%s" is missing a corresponding host in its parent collection.', $name, $locale));
54+
} else {
55+
$route->setHost($host[$locale]);
56+
$route->setRequirement('_locale', $locale);
57+
$routes->add($name, $route);
58+
}
59+
}
60+
}
61+
}

src/Symfony/Component/Routing/Loader/Configurator/Traits/LocalizedRouteTrait.php

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,13 @@ trait LocalizedRouteTrait
2626
* Creates one or many routes.
2727
*
2828
* @param string|array $path the path, or the localized paths of the route
29-
*
30-
* @return Route|RouteCollection
3129
*/
32-
final protected function createLocalizedRoute(RouteCollection $collection, string $name, $path, string $namePrefix = '', array $prefixes = null)
30+
final protected function createLocalizedRoute(RouteCollection $collection, string $name, $path, string $namePrefix = '', array $prefixes = null): RouteCollection
3331
{
3432
$paths = [];
3533

34+
$routes = new RouteCollection();
35+
3636
if (\is_array($path)) {
3737
if (null === $prefixes) {
3838
$paths = $path;
@@ -52,13 +52,12 @@ final protected function createLocalizedRoute(RouteCollection $collection, strin
5252
$paths[$locale] = $prefix.$path;
5353
}
5454
} else {
55-
$collection->add($namePrefix.$name, $route = $this->createRoute($path));
55+
$routes->add($namePrefix.$name, $route = $this->createRoute($path));
56+
$collection->add($namePrefix.$name, $route);
5657

57-
return $route;
58+
return $routes;
5859
}
5960

60-
$routes = new RouteCollection();
61-
6261
foreach ($paths as $locale => $path) {
6362
$routes->add($name.'.'.$locale, $route = $this->createRoute($path));
6463
$collection->add($namePrefix.$name.'.'.$locale, $route);

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

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Symfony\Component\Config\Loader\FileLoader;
1515
use Symfony\Component\Config\Resource\FileResource;
1616
use Symfony\Component\Config\Util\XmlUtils;
17+
use Symfony\Component\Routing\Loader\Configurator\Traits\HostTrait;
1718
use Symfony\Component\Routing\Loader\Configurator\Traits\LocalizedRouteTrait;
1819
use Symfony\Component\Routing\Loader\Configurator\Traits\PrefixTrait;
1920
use Symfony\Component\Routing\RouteCollection;
@@ -26,6 +27,7 @@
2627
*/
2728
class XmlFileLoader extends FileLoader
2829
{
30+
use HostTrait;
2931
use LocalizedRouteTrait;
3032
use PrefixTrait;
3133

@@ -116,7 +118,7 @@ protected function parseRoute(RouteCollection $collection, \DOMElement $node, st
116118
$schemes = preg_split('/[\s,\|]++/', $node->getAttribute('schemes'), -1, PREG_SPLIT_NO_EMPTY);
117119
$methods = preg_split('/[\s,\|]++/', $node->getAttribute('methods'), -1, PREG_SPLIT_NO_EMPTY);
118120

119-
list($defaults, $requirements, $options, $condition, $paths) = $this->parseConfigs($node, $filepath);
121+
list($defaults, $requirements, $options, $condition, $paths, /** $prefixes */, $hosts) = $this->parseConfigs($node, $filepath);
120122

121123
$path = $node->getAttribute('path');
122124

@@ -128,14 +130,15 @@ protected function parseRoute(RouteCollection $collection, \DOMElement $node, st
128130
throw new \InvalidArgumentException(sprintf('The <route> element in file "%s" must not have both a "path" attribute and <path> child nodes.', $filepath));
129131
}
130132

131-
$route = $this->createLocalizedRoute($collection, $id, $paths ?: $path);
132-
$route->addDefaults($defaults);
133-
$route->addRequirements($requirements);
134-
$route->addOptions($options);
135-
$route->setHost($node->getAttribute('host'));
136-
$route->setSchemes($schemes);
137-
$route->setMethods($methods);
138-
$route->setCondition($condition);
133+
$routes = $this->createLocalizedRoute($collection, $id, $paths ?: $path);
134+
$routes->addDefaults($defaults);
135+
$routes->addRequirements($requirements);
136+
$routes->addOptions($options);
137+
//$routes->setHost($node->getAttribute('host'));
138+
$routes->setSchemes($schemes);
139+
$routes->setMethods($methods);
140+
$routes->setCondition($condition);
141+
$this->addHost($routes, $hosts);
139142
}
140143

141144
/**
@@ -155,13 +158,12 @@ protected function parseImport(RouteCollection $collection, \DOMElement $node, s
155158

156159
$type = $node->getAttribute('type');
157160
$prefix = $node->getAttribute('prefix');
158-
$host = $node->hasAttribute('host') ? $node->getAttribute('host') : null;
159161
$schemes = $node->hasAttribute('schemes') ? preg_split('/[\s,\|]++/', $node->getAttribute('schemes'), -1, PREG_SPLIT_NO_EMPTY) : null;
160162
$methods = $node->hasAttribute('methods') ? preg_split('/[\s,\|]++/', $node->getAttribute('methods'), -1, PREG_SPLIT_NO_EMPTY) : null;
161163
$trailingSlashOnRoot = $node->hasAttribute('trailing-slash-on-root') ? XmlUtils::phpize($node->getAttribute('trailing-slash-on-root')) : true;
162164
$namePrefix = $node->getAttribute('name-prefix') ?: null;
163165

164-
list($defaults, $requirements, $options, $condition, /* $paths */, $prefixes) = $this->parseConfigs($node, $path);
166+
list($defaults, $requirements, $options, $condition, $paths, $prefixes, $hosts) = $this->parseConfigs($node, $path);
165167

166168
if ('' !== $prefix && $prefixes) {
167169
throw new \InvalidArgumentException(sprintf('The <route> element in file "%s" must not have both a "prefix" attribute and <prefix> child nodes.', $path));
@@ -192,10 +194,8 @@ protected function parseImport(RouteCollection $collection, \DOMElement $node, s
192194

193195
foreach ($imported as $subCollection) {
194196
$this->addPrefix($subCollection, $prefixes ?: $prefix, $trailingSlashOnRoot);
197+
$this->addHost($subCollection, $hosts);
195198

196-
if (null !== $host) {
197-
$subCollection->setHost($host);
198-
}
199199
if (null !== $condition) {
200200
$subCollection->setCondition($condition);
201201
}
@@ -245,6 +245,7 @@ private function parseConfigs(\DOMElement $node, string $path): array
245245
$condition = null;
246246
$prefixes = [];
247247
$paths = [];
248+
$hosts = [];
248249

249250
/** @var \DOMElement $n */
250251
foreach ($node->getElementsByTagNameNS(self::NAMESPACE_URI, '*') as $n) {
@@ -256,6 +257,9 @@ private function parseConfigs(\DOMElement $node, string $path): array
256257
case 'path':
257258
$paths[$n->getAttribute('locale')] = trim($n->textContent);
258259
break;
260+
case 'host':
261+
$hosts[$n->getAttribute('locale')] = trim($n->textContent);
262+
break;
259263
case 'prefix':
260264
$prefixes[$n->getAttribute('locale')] = trim($n->textContent);
261265
break;
@@ -309,7 +313,11 @@ private function parseConfigs(\DOMElement $node, string $path): array
309313
$defaults['_stateless'] = XmlUtils::phpize($stateless);
310314
}
311315

312-
return [$defaults, $requirements, $options, $condition, $paths, $prefixes];
316+
if ([] === $hosts) {
317+
$hosts = $node->hasAttribute('host') ? $node->getAttribute('host') : null;
318+
}
319+
320+
return [$defaults, $requirements, $options, $condition, $paths< F438 /span>, $prefixes, $hosts];
313321
}
314322

315323
/**

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

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use Symfony\Component\Config\Loader\FileLoader;
1515
use Symfony\Component\Config\Resource\FileResource;
16+
use Symfony\Component\Routing\Loader\Configurator\Traits\HostTrait;
1617
use Symfony\Component\Routing\Loader\Configurator\Traits\LocalizedRouteTrait;
1718
use Symfony\Component\Routing\Loader\Configurator\Traits\PrefixTrait;
1819
use Symfony\Component\Routing\RouteCollection;
@@ -28,6 +29,7 @@
2829
*/
2930
class YamlFileLoader extends FileLoader
3031
{
32+
use HostTrait;
3133
use LocalizedRouteTrait;
3234
use PrefixTrait;
3335

@@ -137,14 +139,14 @@ protected function parseRoute(RouteCollection $collection, string $name, array $
137139
$defaults['_stateless'] = $config['stateless'];
138140
}
139141

140-
$route = $this->createLocalizedRoute($collection, $name, $config['path']);
141-
$route->addDefaults($defaults);
142-
$route->addRequirements($requirements);
143-
$route->addOptions($options);
144-
$route->setHost($config['host'] ?? '');
145-
$route->setSchemes($config['schemes'] ?? []);
146-
$route->setMethods($config['methods'] ?? []);
147-
$route->setCondition($config['condition'] ?? null);
142+
$routes = $this->createLocalizedRoute($collection, $name, $config['path']);
143+
$routes->addDefaults($defaults);
144+
$routes->addRequirements($requirements);
145+
$routes->addOptions($options);
146+
$routes->setSchemes($config['schemes'] ?? []);
147+
$routes->setMethods($config['methods'] ?? []);
148+
$routes->setCondition($config['condition'] ?? null);
149+
$this->addHost($routes, $config['host'] ?? null);
148150
}
149151

150152
/**
@@ -196,10 +198,8 @@ protected function parseImport(RouteCollection $collection, array $config, strin
196198

197199
foreach ($imported as $subCollection) {
198200
$this->addPrefix($subCollection, $prefix, $trailingSlashOnRoot);
201+
$this->addHost($subCollection, $host);
199202

200-
if (null !== $host) {
201-
$subCollection->setHost($host);
202-
}
203203
if (null !== $condition) {
204204
$subCollection->setCondition($condition);
205205
}

src/Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsd

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
<xsd:sequence>
4646
<xsd:group ref="configs" minOccurs="0" maxOccurs="unbounded" />
4747
<xsd:element name="path" type="localized-path" minOccurs="0" maxOccurs="unbounded" />
48+
<xsd:element name="host" type="localized-path" minOccurs="0" maxOccurs="unbounded" />
4849
</xsd:sequence>
4950
<xsd:attribute name="id" type="xsd:string" use="required" />
5051
<xsd:attribute name="path" type="xsd:string" />
@@ -63,6 +64,7 @@
6364
<xsd:group ref="configs" minOccurs="0" maxOccurs="unbounded" />
6465
<xsd:element name="prefix" type="localized-path" minOccurs="0" maxOccurs="unbounded" />
6566
<xsd:element name="exclude" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
67+
<xsd:element name="host" type="localized-path" minOccurs="0" maxOccurs="unbounded" />
6668
</xsd:sequence>
6769
<xsd:attribute name="resource" type="xsd:string" use="required" />
6870
<xsd:attribute name="type" type="xsd:string" />
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
namespace Symfony\Component\Routing\Loader\Configurator;
4+
5+
return function (RoutingConfigurator $routes) {
6+
$routes
7+
->add('imported', ['nl' => '/voorbeeld', 'en' => '/example'])
8+
->controller('ImportedController::someAction')
9+
->host([
10+
'nl' => 'www.example.nl',
11+
'en' => 'www.example.com',
12+
])
13+
->add('imported_not_localized', '/here')
14+
->controller('ImportedController::someAction')
15+
;
16+
};

0 commit comments

Comments
 (0)
0