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

Skip to content

Commit 10183de

Browse files
committed
make scheme and method requirements first-class citizen in Route
1 parent 18c520a commit 10183de

File tree

2 files changed

+166
-7
lines changed

2 files changed

+166
-7
lines changed

src/Symfony/Component/Routing/Route.php

Lines changed: 114 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
* A Route describes a route and its parameters.
1616
*
1717
* @author Fabien Potencier <[email protected]>
18+
* @author Tobias Schultze <http://tobion.de>
1819
*
1920
* @api
2021
*/
@@ -30,7 +31,17 @@ class Route implements \Serializable
3031
*/
3132
private $hostnamePattern = '';
3233

33-
/**
34+
/**
35+
* @var array
36+
*/
37+
private $schemes = array();
38+
39+
/**
40+
* @var array
41+
*/
42+
private $methods = array();
43+
44+
/**
3445
* @var array
3546
*/
3647
private $defaults = array();
@@ -59,21 +70,32 @@ class Route implements \Serializable
5970
*
6071
* * compiler_class: A class name able to compile this route instance (RouteCompiler by default)
6172
*
62-
* @param string $pattern The path pattern to match
63-
* @param array $defaults An array of default parameter values
64-
* @param array $requirements An array of requirements for parameters (regexes)
65-
* @param array $options An array of options
66-
* @param string $hostnamePattern The hostname pattern to match
73+
* @param string $pattern The path pattern to match
74+
* @param array $defaults An array of default parameter values
75+
* @param array $requirements An array of requirements for parameters (regexes)
76+
* @param array $options An array of options
77+
* @param string $hostnamePattern The hostname pattern to match
78+
* @param string|array $schemes A required URI scheme or an array of restricted schemes
79+
* @param string|array $methods A required HTTP method or an array of restricted methods
6780
*
6881
* @api
6982
*/
70-
public function __construct($pattern, array $defaults = array(), array $requirements = array(), array $options = array(), $hostnamePattern = '')
83+
public function __construct($pattern, array $defaults = array(), array $requirements = array(), array $options = array(),
84+
$hostnamePattern = '', $schemes = array(), $methods = array())
7185
{
7286
$this->setPattern($pattern);
7387
$this->setDefaults($defaults);
7488
$this->setRequirements($requirements);
7589
$this->setOptions($options);
7690
$this->setHostnamePattern($hostnamePattern);
91+
// The conditions make sure that an initial empty $schemes/$methods does not override the corresponding requirement.
92+
// They can be removed when the BC layer is removed.
93+
if ($schemes) {
94+
$this->setSchemes($schemes);
95+
}
96+
if ($methods) {
97+
$this->setMethods($methods);
98+
}
7799
}
78100

79101
public function serialize()
@@ -84,6 +106,8 @@ public function serialize()
84106
'defaults' => $this->defaults,
85107
'requirements' => $this->requirements,
86108
'options' => $this->options,
109+
'schemes' => $this->schemes,
110+
'methods' => $this->methods,
87111
));
88112
}
89113

@@ -95,6 +119,8 @@ public function unserialize($data)
95119
$this->defaults = $data['defaults'];
96120
$this->requirements = $data['requirements'];
97121
$this->options = $data['options'];
122+
$this->schemes = $data['schemes'];
123+
$this->methods = $data['methods'];
98124
}
99125

100126
/**
@@ -149,6 +175,80 @@ public function setHostnamePattern($pattern)
149175
return $this;
150176
}
151177

178+
/**
179+
* Returns the lowercased schemes this route is restricted to.
180+
* So an empty array means that any scheme is allowed.
181+
*
182+
* @return array The schemes
183+
*/
184+
public function getSchemes()
185+
{
186+
return $this->schemes;
187+
}
188+
189+
/**
190+
* Sets the schemes (e.g. 'https') this route is restricted to.
191+
* So an empty array means that any scheme is allowed.
192+
*
193+
* This method implements a fluent interface.
194+
*
195+
* @param string|array $schemes The scheme or an array of schemes
196+
*
197+
* @return Route The current Route instance
198+
*/
199+
public function setSchemes($schemes)
200+
{
201+
$this->schemes = array_map('strtolower', (array) $schemes);
202+
203+
// this is to keep BC and will be removed in a future version
204+
if ($this->schemes) {
205+
$this->requirements['_scheme'] = implode('|', $this->schemes);
206+
} else {
207+
unset($this->requirements['_scheme']);
208+
}
209+
210+
$this->compiled = null;
211+
212+
return $this;
213+
}
214+
215+
/**
216+
* Returns the uppercased HTTP methods this route is restricted to.
217+
* So an empty array means that any method is allowed.
218+
*
219+
* @return array The schemes
220+
*/
221+
public function getMethods()
222+
{
223+
return $this->methods;
224+
}
225+
226+
/**
227+
* Sets the HTTP methods (e.g. 'POST') this route is restricted to.
228+
* So an empty array means that any method is allowed.
229+
*
230+
* This method implements a fluent interface.
231+
*
232+
* @param string|array $methods The method or an array of methods
233+
*
234+
* @return Route The current Route instance
235+
*/
236+
public function setMethods($methods)
237+
{
238+
$this->methods = array_map('strtoupper', (array) $methods);
239+
240+
// this is to keep BC and will be removed in a future version
241+
if ($this->methods) {
242+
$this->requirements['_method'] = implode('|', $this->methods);
243+
} else {
244+
unset($this->requirements['_method']);
245+
}
246+
247+
$this->compiled = null;
248+
249+
return $this;
250+
}
251+
152252
/**
153253
* Returns the options.
154254
*
@@ -454,6 +554,13 @@ private function sanitizeRequirement($key, $regex)
454554
throw new \InvalidArgumentException(sprintf('Routing requirement for "%s" cannot be empty.', $key));
455555
}
456556

557+
// this is to keep BC and will be removed in a future version
558+
if ('_scheme' === $key) {
559+
$this->setSchemes(explode('|', $regex));
560+
} elseif ('_method' === $key) {
561+
$this->setMethods(explode('|', $regex));
562+
}
563+
457564
return $regex;
458565
}
459566
}

src/Symfony/Component/Routing/Tests/RouteTest.php

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,14 @@ public function testConstructor()
2323
$this->assertEquals(array('foo' => '\d+'), $route->getRequirements(), '__construct() takes requirements as its third argument');
2424
$this->assertEquals('bar', $route->getOption('foo'), '__construct() takes options as its fourth argument');
2525
$this->assertEquals('{locale}.example.com', $route->getHostnamePattern(), '__construct() takes a hostname pattern as its fifth argument');
26+
27+
$route = new Route('/', array(), array(), array(), '', array('Https'), array('POST', 'put'));
28+
$this->assertEquals(array('https'), $route->getSchemes(), '__construct() takes schemes as its sixth argument and lowercases it');
29+
$this->assertEquals(array('POST', 'PUT'), $route->getMethods(), '__construct() takes methods as its seventh argument and uppercases it');
30+
31+
$route = new Route('/', array(), array(), array(), '', 'Https', 'Post');
32+
$this->assertEquals(array('https'), $route->getSchemes(), '__construct() takes a single scheme as its sixth argument');
33+
$this->assertEquals(array('POST'), $route->getMethods(), '__construct() takes a single method as its seventh argument');
2634
}
2735

2836
public function testPattern()
@@ -129,6 +137,50 @@ public function testHostnamePattern()
129137
$this->assertEquals('{locale}.example.net', $route->getHostnamePattern(), '->setHostnamePattern() sets the hostname pattern');
130138
}
131139

140+
public function testScheme()
141+
{
142+
$route = new Route('/');
143+
$this->assertEquals(array(), $route->getSchemes(), 'schemes is initialized with array()');
144+
$route->setSchemes('hTTp');
145+
$this->assertEquals(array('http'), $route->getSchemes(), '->setSchemes() accepts a single scheme string and lowercases it');
146+
$route->setSchemes(array('HttpS', 'hTTp'));
147+
$this->assertEquals(array('https', 'http'), $route->getSchemes(), '->setSchemes() accepts an array of schemes and lowercases them');
148+
}
149+
150+
public function testSchemeIsBC()
151+
{
152+
$route = new Route('/');
153+
$route->setRequirement('_scheme', 'http|https');
154+
$this->assertEquals('http|https', $route->getRequirement('_scheme'));
155+
$this->assertEquals(array('http', 'https'), $route->getSchemes());
156+
$route->setSchemes(array('hTTp'));
157+
$this->assertEquals('http', $route->getRequirement('_scheme'));
158+
$route->setSchemes(array());
159+
$this->assertNull($route->getRequirement('_scheme'));
160+
}
161+
162+
public function testMethod()
163+
{
164+
$route = new Route('/');
165+
$this->assertEquals(array(), $route->getMethods(), 'methods is initialized with array()');
166+
$route->setMethods('gEt');
167+
$this->assertEquals(array('GET'), $route->getMethods(), '->setMethods() accepts a single method string and uppercases it');
168+
$route->setMethods(array('gEt', 'PosT'));
169+
$this->assertEquals(array('GET', 'POST'), $route->getMethods(), '->setMethods() accepts an array of methods and uppercases them');
170+
}
171+
172+
public function testMethodIsBC()
173+
{
174+
$route = new Route('/');
175+
$route->setRequirement('_method', 'GET|POST');
176+
$this->assertEquals('GET|POST', $route->getRequirement('_method'));
177+
$this->assertEquals(array('GET', 'POST'), $route->getMethods());
178+
$route->setMethods(array('gEt'));
179+
$this->assertEquals('GET', $route->getRequirement('_method'));
180+
$route->setMethods(array());
181+
$this->assertNull($route->getRequirement('_method'));
182+
}
183+
132184
public function testCompile()
133185
{
134186
$route = new Route('/{foo}');

0 commit comments

Comments
 (0)