Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 2e4d4b0

Browse files
[Routing] allow no-slash root on imported routes
1 parent a38cbd0 commit 2e4d4b0

File tree

9 files changed

+42
-10
lines changed

9 files changed

+42
-10
lines changed

src/Symfony/Component/Routing/Annotation/Route.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class Route
3838
*/
3939
public function __construct(array $data)
4040
{
41-
if (isset($data['value'])) {
41+
if (array_key_exists('value', $data)) {
4242
$data['path'] = $data['value'];
4343
unset($data['value']);
4444
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,9 @@ protected function parseRoute(RouteCollection $collection, \DOMElement $node, $p
115115
$methods = preg_split('/[\s,\|]++/', $node->getAttribute('methods'), -1, PREG_SPLIT_NO_EMPTY);
116116

117117
list($defaults, $requirements, $options, $condition) = $this->parseConfigs($node, $path);
118+
$path = $node->getAttribute('path');
118119

119-
$route = new Route($node->getAttribute('path'), $defaults, $requirements, $options, $node->getAttribute('host'), $schemes, $methods, $condition);
120+
$route = new Route('null' !== $path ? $path : null, $defaults, $requirements, $options, $node->getAttribute('host'), $schemes, $methods, $condition);
120121
$collection->add($id, $route);
121122
}
122123

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ protected function validate($config, $name, $path)
198198
$path, $name, implode('", "', $extraKeys), implode('", "', self::$availableKeys)
199199
));
200200
}
201-
if (isset($config['resource']) && isset($config['path'])) {
201+
if (isset($config['resource']) && array_key_exists('path', $config)) {
202202
throw new \InvalidArgumentException(sprintf(
203203
'The routing file "%s" must not specify both the "resource" key and the "path" key for "%s". Choose between an import and a route definition.',
204204
$path, $name
@@ -210,7 +210,7 @@ protected function validate($config, $name, $path)
210210
$name, $path
211211
));
212212
}
213-
if (!isset($config['resource']) && !isset($config['path'])) {
213+
if (!isset($config['resource']) && !array_key_exists('path', $config)) {
214214
throw new \InvalidArgumentException(sprintf(
215215
'You must define a "path" for the route "%s" in file "%s".',
216216
$name, $path

src/Symfony/Component/Routing/Route.php

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ class Route implements \Serializable
4141
* * compiler_class: A class name able to compile this route instance (RouteCompiler by default)
4242
* * utf8: Whether UTF-8 matching is enforced ot not
4343
*
44-
* @param string $path The path pattern to match
44+
* @param string|null $path The path pattern to match, or null to declare a trailing-slash-less root of a collection
4545
* @param array $defaults An array of default parameter values
4646
* @param array $requirements An array of requirements for parameters (regexes)
4747
* @param array $options An array of options
@@ -50,7 +50,7 @@ class Route implements \Serializable
5050
* @param string|string[] $methods A required HTTP method or an array of restricted methods
5151
* @param string $condition A condition that should evaluate to true for the route to match
5252
*/
53-
public function __construct(string $path, array $defaults = array(), array $requirements = array(), array $options = array(), ?string $host = '', $schemes = array(), $methods = array(), ?string $condition = '')
53+
public function __construct(?string $path, array $defaults = array(), array $requirements = array(), array $options = array(), ?string $host = '', $schemes = array(), $methods = array(), ?string $condition = '')
5454
{
5555
$this->setPath($path);
5656
$this->setDefaults($defaults);
@@ -109,28 +109,33 @@ public function unserialize($serialized)
109109
*/
110110
public function getPath()
111111
{
112-
return $this->path;
112+
return null === $this->path ? '/' : $this->path;
113113
}
114114

115115
/**
116116
* Sets the pattern for the path.
117117
*
118118
* This method implements a fluent interface.
119119
*
120-
* @param string $pattern The path pattern
120+
* @param string|null $pattern The path pattern
121121
*
122122
* @return $this
123123
*/
124124
public function setPath($pattern)
125125
{
126126
// A pattern must start with a slash and must not have multiple slashes at the beginning because the
127127
// generated path for this route would be confused with a network path, e.g. '//domain.com/path'.
128-
$this->path = '/'.ltrim(trim($pattern), '/');
128+
$this->path = null !== $pattern ? '/'.ltrim(trim($pattern), '/') : null;
129129
$this->compiled = null;
130130

131131
return $this;
132132
}
133133

134+
public function hasTrailingSlash(): bool
135+
{
136+
return null !== $this->path && '/' === $this->path[-1];
137+
}
138+
134139
/**
135140
* Returns the pattern for the host.
136141
*

src/Symfony/Component/Routing/RouteCollection.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ public function addPrefix($prefix, array $defaults = array(), array $requirement
147147
}
148148

149149
foreach ($this->routes as $route) {
150-
$route->setPath('/'.$prefix.$route->getPath());
150+
$route->setPath('/'.$prefix.(!$route->hasTrailingSlash() && '/' === $route->getPath() ? '' : $route->getPath()));
151151
$route->addDefaults($defaults);
152152
$route->addRequirements($requirements);
153153
}

src/Symfony/Component/Routing/Tests/Fixtures/controller/routing.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
<route id="app_homepage" path="/" controller="AppBundle:Homepage:show" />
88

9+
<route id="app_homepage_no_slash" path="null" controller="AppBundle:Homepage:show" />
10+
911
<route id="app_blog" path="/blog">
1012
<default key="_controller">AppBundle:Blog:list</default>
1113
</route>

src/Symfony/Component/Routing/Tests/Fixtures/controller/routing.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ app_homepage:
22
path: /
33
controller: AppBundle:Homepage:show
44

5+
app_homepage_no_slash:
6+
path: ~
7+
controller: AppBundle:Homepage:show
8+
59
app_blog:
610
path: /blog
711
defaults:

src/Symfony/Component/Routing/Tests/Loader/XmlFileLoaderTest.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,10 @@ public function testLoadRouteWithControllerAttribute()
296296
$route = $routeCollection->get('app_homepage');
297297

298298
$this->assertSame('AppBundle:Homepage:show', $route->getDefault('_controller'));
299+
300+
$route = $routeCollection->get('app_homepage_no_slash');
301+
302+
$this->assertSame('/', $route->getPath());
299303
}
300304

301305
public function testLoadRouteWithoutControllerAttribute()
@@ -371,5 +375,11 @@ public function testImportRouteWithNamePrefix()
371375
$this->assertEquals('/blog', $routeCollection->get('app_blog')->getPath());
372376
$this->assertNotNull($routeCollection->get('api_app_blog'));
373377
$this->assertEquals('/api/blog', $routeCollection->get('api_app_blog')->getPath());
378+
379+
$route = $routeCollection->get('api_app_homepage');
380+
$this->assertSame('/api/', $route->getPath());
381+
382+
$route = $routeCollection->get('api_app_homepage_no_slash');
383+
$this->assertSame('/api', $route->getPath());
374384
}
375385
}

src/Symfony/Component/Routing/Tests/Loader/YamlFileLoaderTest.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,10 @@ public function testLoadRouteWithControllerAttribute()
117117
$route = $routeCollection->get('app_homepage');
118118

119119
$this->assertSame('AppBundle:Homepage:show', $route->getDefault('_controller'));
120+
121+
$route = $routeCollection->get('app_homepage_no_slash');
122+
123+
$this->assertSame('/', $route->getPath());
120124
}
121125

122126
public function testLoadRouteWithoutControllerAttribute()
@@ -192,5 +196,11 @@ public function testImportRouteWithNamePrefix()
192196
$this->assertEquals('/blog', $routeCollection->get('app_blog')->getPath());
193197
$this->assertNotNull($routeCollection->get('api_app_blog'));
194198
$this->assertEquals('/api/blog', $routeCollection->get('api_app_blog')->getPath());
199+
200+
$route = $routeCollection->get('api_app_homepage');
201+
$this->assertSame('/api/', $route->getPath());
202+
203+
$route = $routeCollection->get('api_app_homepage_no_slash');
204+
$this->assertSame('/api', $route->getPath());
195205
}
196206
}

0 commit comments

Comments
 (0)