merged branch fabpot/routing-options (PR #6738)
This PR was merged into the master branch. Commits -------9fc7def
added the UPGRADE file for Symfony 3.0e84cad2
[Routing] updated CHANGELOG65eca8a
[Routing] added new schemes and methods options to the annotation loader5082994
[Routing] renamed pattern to pathb357caf
[Routing] renamed hostname pattern to just hostnamee803f46
made schemes and methods available in XmlFileLoaderd374e70
made schemes and methods available in YamlFileLoader2834e7e
added scheme and method setter in RouteCollection10183de
make scheme and method requirements first-class citizen in Route Discussion ---------- Routing options | Q | A | ------------- | --- | Bug fix? | no | New feature? | no | BC breaks? | no | Deprecations? | yes | Tests pass? | yes | Fixed tickets | #5989, #5990, #6049 | License | MIT In #5989, it has unanimously been decided to renamed `hostname_pattern` to `hostname` and `pattern` to `path`. That makes a lot of sense and I would like to do the renaming now as `hostname_pattern` is new in Symfony 2.2, so I'd like to avoid breaking BC just after the release. As we are modifying the route options, I've also included changes introduced by @Tobion in #6049 which were discussed in #5990. As everything is BC, I think it's wise to include that in 2.2. What do you think? --------------------------------------------------------------------------- by Tobion at 2013-01-14T18:25:53Z I agree it should be done in 2.2. Thanks for working on it. --------------------------------------------------------------------------- by vicb at 2013-01-14T23:11:12Z @fabpot "Everything is BC" until it breaks BC in 3.0, that's why I'd like to see [deprecations in PR summary](https://github.com/symfony/symfony-docs/pull/2116) what do you think ? --------------------------------------------------------------------------- by vicb at 2013-01-14T23:16:40Z it would also be great to update the CHANGELOG with deprecations (it could also help people answering your question) --------------------------------------------------------------------------- by fabpot at 2013-01-15T07:07:03Z @vicb: I've just updated the CHANGELOG and created the UPGRADE file for 3.0. --------------------------------------------------------------------------- by vicb at 2013-01-15T07:15:32Z @fabpot thanks.
This commit is contained in:
commit
89f9b24575
47
UPGRADE-3.0.md
Normal file
47
UPGRADE-3.0.md
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
UPGRADE FROM 2.x to 3.0
|
||||||
|
=======================
|
||||||
|
|
||||||
|
### Routing
|
||||||
|
|
||||||
|
* Some route settings have been renamed:
|
||||||
|
|
||||||
|
* The `pattern` setting for a route has been deprecated in favor of `path`
|
||||||
|
* The `_scheme` and `_method` requirements have been moved to the `schemes` and `methods` settings
|
||||||
|
|
||||||
|
Before:
|
||||||
|
|
||||||
|
```
|
||||||
|
article_edit:
|
||||||
|
pattern: /article/{id}
|
||||||
|
requirements: { '_method': 'POST|PUT', '_scheme': 'https', 'id': '\d+' }
|
||||||
|
|
||||||
|
<route id="article_edit" pattern="/article/{id}">
|
||||||
|
<requirement key="_method">POST|PUT</requirement>
|
||||||
|
<requirement key="_scheme">https</requirement>
|
||||||
|
<requirement key="id">\d+</requirement>
|
||||||
|
</route>
|
||||||
|
|
||||||
|
$route = new Route();
|
||||||
|
$route->setPattern('/article/{id}');
|
||||||
|
$route->setRequirement('_method', 'POST|PUT');
|
||||||
|
$route->setRequirement('_scheme', 'https');
|
||||||
|
```
|
||||||
|
|
||||||
|
After:
|
||||||
|
|
||||||
|
```
|
||||||
|
article_edit:
|
||||||
|
path: /article/{id}
|
||||||
|
methods: [POST, PUT]
|
||||||
|
schemes: https
|
||||||
|
requirements: { 'id': '\d+' }
|
||||||
|
|
||||||
|
<route id="article_edit" pattern="/article/{id}" methods="POST PUT" schemes="https">
|
||||||
|
<requirement key="id">\d+</requirement>
|
||||||
|
</route>
|
||||||
|
|
||||||
|
$route = new Route();
|
||||||
|
$route->setPath('/article/{id}');
|
||||||
|
$route->setMethods(array('POST', 'PUT'));
|
||||||
|
$route->setSchemes('https');
|
||||||
|
```
|
@ -92,7 +92,7 @@ EOF
|
|||||||
? implode(', ', $requirements['_method']) : $requirements['_method']
|
? implode(', ', $requirements['_method']) : $requirements['_method']
|
||||||
)
|
)
|
||||||
: 'ANY';
|
: 'ANY';
|
||||||
$hostname = '' !== $route->getHostnamePattern() ? $route->getHostnamePattern() : 'ANY';
|
$hostname = '' !== $route->getHostname() ? $route->getHostname() : 'ANY';
|
||||||
$maxName = max($maxName, strlen($name));
|
$maxName = max($maxName, strlen($name));
|
||||||
$maxMethod = max($maxMethod, strlen($method));
|
$maxMethod = max($maxMethod, strlen($method));
|
||||||
$maxHostname = max($maxHostname, strlen($hostname));
|
$maxHostname = max($maxHostname, strlen($hostname));
|
||||||
@ -109,7 +109,7 @@ EOF
|
|||||||
? implode(', ', $requirements['_method']) : $requirements['_method']
|
? implode(', ', $requirements['_method']) : $requirements['_method']
|
||||||
)
|
)
|
||||||
: 'ANY';
|
: 'ANY';
|
||||||
$hostname = '' !== $route->getHostnamePattern() ? $route->getHostnamePattern() : 'ANY';
|
$hostname = '' !== $route->getHostname() ? $route->getHostname() : 'ANY';
|
||||||
$output->writeln(sprintf($format, $name, $method, $hostname, $route->getPattern()));
|
$output->writeln(sprintf($format, $name, $method, $hostname, $route->getPattern()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -124,14 +124,14 @@ EOF
|
|||||||
throw new \InvalidArgumentException(sprintf('The route "%s" does not exist.', $name));
|
throw new \InvalidArgumentException(sprintf('The route "%s" does not exist.', $name));
|
||||||
}
|
}
|
||||||
|
|
||||||
$hostname = '' !== $route->getHostnamePattern() ? $route->getHostnamePattern() : 'ANY';
|
$hostname = '' !== $route->getHostname() ? $route->getHostname() : 'ANY';
|
||||||
|
|
||||||
$output->writeln($this->getHelper('formatter')->formatSection('router', sprintf('Route "%s"', $name)));
|
$output->writeln($this->getHelper('formatter')->formatSection('router', sprintf('Route "%s"', $name)));
|
||||||
|
|
||||||
$output->writeln(sprintf('<comment>Name</comment> %s', $name));
|
$output->writeln(sprintf('<comment>Name</comment> %s', $name));
|
||||||
$output->writeln(sprintf('<comment>Pattern</comment> %s', $route->getPattern()));
|
$output->writeln(sprintf('<comment>Pattern</comment> %s', $route->getPattern()));
|
||||||
$output->writeln(sprintf('<comment>HostnamePattern</comment> %s', $hostname));
|
$output->writeln(sprintf('<comment>Hostname</comment> %s', $hostname));
|
||||||
$output->writeln(sprintf('<comment>Class</comment> %s', get_class($route)));
|
$output->writeln(sprintf('<comment>Class</comment> %s', get_class($route)));
|
||||||
|
|
||||||
$defaults = '';
|
$defaults = '';
|
||||||
$d = $route->getDefaults();
|
$d = $route->getDefaults();
|
||||||
|
@ -78,7 +78,7 @@ class Router extends BaseRouter implements WarmableInterface
|
|||||||
* - the route defaults,
|
* - the route defaults,
|
||||||
* - the route requirements,
|
* - the route requirements,
|
||||||
* - the route pattern.
|
* - the route pattern.
|
||||||
* - the route hostnamePattern.
|
* - the route hostname.
|
||||||
*
|
*
|
||||||
* @param RouteCollection $collection
|
* @param RouteCollection $collection
|
||||||
*/
|
*/
|
||||||
@ -94,7 +94,7 @@ class Router extends BaseRouter implements WarmableInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
$route->setPattern($this->resolve($route->getPattern()));
|
$route->setPattern($this->resolve($route->getPattern()));
|
||||||
$route->setHostnamePattern($this->resolve($route->getHostnamePattern()));
|
$route->setHostname($this->resolve($route->getHostname()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,12 +117,12 @@ class RoutingTest extends \PHPUnit_Framework_TestCase
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testHostnamePatternPlaceholders()
|
public function testHostnamePlaceholders()
|
||||||
{
|
{
|
||||||
$routes = new RouteCollection();
|
$routes = new RouteCollection();
|
||||||
|
|
||||||
$route = new Route('foo');
|
$route = new Route('foo');
|
||||||
$route->setHostnamePattern('/before/%parameter.foo%/after/%%unescaped%%');
|
$route->setHostname('/before/%parameter.foo%/after/%%unescaped%%');
|
||||||
|
|
||||||
$routes->add('foo', $route);
|
$routes->add('foo', $route);
|
||||||
|
|
||||||
@ -136,7 +136,7 @@ class RoutingTest extends \PHPUnit_Framework_TestCase
|
|||||||
|
|
||||||
$this->assertEquals(
|
$this->assertEquals(
|
||||||
'/before/foo/after/%unescaped%',
|
'/before/foo/after/%unescaped%',
|
||||||
$route->getHostnamePattern()
|
$route->getHostname()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,12 +20,14 @@ namespace Symfony\Component\Routing\Annotation;
|
|||||||
*/
|
*/
|
||||||
class Route
|
class Route
|
||||||
{
|
{
|
||||||
private $pattern;
|
private $path;
|
||||||
private $name;
|
private $name;
|
||||||
private $requirements;
|
private $requirements;
|
||||||
private $options;
|
private $options;
|
||||||
private $defaults;
|
private $defaults;
|
||||||
private $hostnamePattern;
|
private $hostname;
|
||||||
|
private $methods;
|
||||||
|
private $schemes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
@ -39,9 +41,11 @@ class Route
|
|||||||
$this->requirements = array();
|
$this->requirements = array();
|
||||||
$this->options = array();
|
$this->options = array();
|
||||||
$this->defaults = array();
|
$this->defaults = array();
|
||||||
|
$this->methods = array();
|
||||||
|
$this->schemes = array();
|
||||||
|
|
||||||
if (isset($data['value'])) {
|
if (isset($data['value'])) {
|
||||||
$data['pattern'] = $data['value'];
|
$data['path'] = $data['value'];
|
||||||
unset($data['value']);
|
unset($data['value']);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,24 +58,40 @@ class Route
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Deprecated in 2.2, to be removed in 3.0. Use setPath instead.
|
||||||
|
*/
|
||||||
public function setPattern($pattern)
|
public function setPattern($pattern)
|
||||||
{
|
{
|
||||||
$this->pattern = $pattern;
|
$this->path = $pattern;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Deprecated in 2.2, to be removed in 3.0. Use getPath instead.
|
||||||
|
*/
|
||||||
public function getPattern()
|
public function getPattern()
|
||||||
{
|
{
|
||||||
return $this->pattern;
|
return $this->path;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setHostnamePattern($pattern)
|
public function setPath($path)
|
||||||
{
|
{
|
||||||
$this->hostnamePattern = $pattern;
|
$this->path = $path;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getHostnamePattern()
|
public function getPath()
|
||||||
{
|
{
|
||||||
return $this->hostnamePattern;
|
return $this->path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setHostname($pattern)
|
||||||
|
{
|
||||||
|
$this->hostname = $pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getHostname()
|
||||||
|
{
|
||||||
|
return $this->hostname;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setName($name)
|
public function setName($name)
|
||||||
@ -113,4 +133,24 @@ class Route
|
|||||||
{
|
{
|
||||||
return $this->defaults;
|
return $this->defaults;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setSchemes($schemes)
|
||||||
|
{
|
||||||
|
$this->schemes = is_array($schemes) ? $schemes : array($schemes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSchemes()
|
||||||
|
{
|
||||||
|
return $this->schemes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setMethods($methods)
|
||||||
|
{
|
||||||
|
$this->methods = is_array($methods) ? $methods : array($methods);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMethods()
|
||||||
|
{
|
||||||
|
return $this->methods;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,49 @@ CHANGELOG
|
|||||||
2.2.0
|
2.2.0
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
* [DEPRECATION] Several route settings have been renamed (the old ones will be removed in 3.0):
|
||||||
|
|
||||||
|
* The `pattern` setting for a route has been deprecated in favor of `path`
|
||||||
|
* The `_scheme` and `_method` requirements have been moved to the `schemes` and `methods` settings
|
||||||
|
|
||||||
|
Before:
|
||||||
|
|
||||||
|
```
|
||||||
|
article_edit:
|
||||||
|
pattern: /article/{id}
|
||||||
|
requirements: { '_method': 'POST|PUT', '_scheme': 'https', 'id': '\d+' }
|
||||||
|
|
||||||
|
<route id="article_edit" pattern="/article/{id}">
|
||||||
|
<requirement key="_method">POST|PUT</requirement>
|
||||||
|
<requirement key="_scheme">https</requirement>
|
||||||
|
<requirement key="id">\d+</requirement>
|
||||||
|
</route>
|
||||||
|
|
||||||
|
$route = new Route();
|
||||||
|
$route->setPattern('/article/{id}');
|
||||||
|
$route->setRequirement('_method', 'POST|PUT');
|
||||||
|
$route->setRequirement('_scheme', 'https');
|
||||||
|
```
|
||||||
|
|
||||||
|
After:
|
||||||
|
|
||||||
|
```
|
||||||
|
article_edit:
|
||||||
|
path: /article/{id}
|
||||||
|
methods: [POST, PUT]
|
||||||
|
schemes: https
|
||||||
|
requirements: { 'id': '\d+' }
|
||||||
|
|
||||||
|
<route id="article_edit" pattern="/article/{id}" methods="POST PUT" schemes="https">
|
||||||
|
<requirement key="id">\d+</requirement>
|
||||||
|
</route>
|
||||||
|
|
||||||
|
$route = new Route();
|
||||||
|
$route->setPath('/article/{id}');
|
||||||
|
$route->setMethods(array('POST', 'PUT'));
|
||||||
|
$route->setSchemes('https');
|
||||||
|
```
|
||||||
|
|
||||||
* [BC BREAK] RouteCollection does not behave like a tree structure anymore but as
|
* [BC BREAK] RouteCollection does not behave like a tree structure anymore but as
|
||||||
a flat array of Routes. So when using PHP to build the RouteCollection, you must
|
a flat array of Routes. So when using PHP to build the RouteCollection, you must
|
||||||
make sure to add routes to the sub-collection before adding it to the parent
|
make sure to add routes to the sub-collection before adding it to the parent
|
||||||
|
@ -28,9 +28,10 @@ use Symfony\Component\Config\Loader\LoaderResolverInterface;
|
|||||||
* The @Route annotation can be set on the class (for global parameters),
|
* The @Route annotation can be set on the class (for global parameters),
|
||||||
* and on each method.
|
* and on each method.
|
||||||
*
|
*
|
||||||
* The @Route annotation main value is the route pattern. The annotation also
|
* The @Route annotation main value is the route path. The annotation also
|
||||||
* recognizes three parameters: requirements, options, and name. The name parameter
|
* recognizes several parameters: requirements, options, defaults, schemes,
|
||||||
* is mandatory. Here is an example of how you should be able to use it:
|
* methods, hostname, and name. The name parameter is mandatory.
|
||||||
|
* Here is an example of how you should be able to use it:
|
||||||
*
|
*
|
||||||
* /**
|
* /**
|
||||||
* * @Route("/Blog")
|
* * @Route("/Blog")
|
||||||
@ -108,11 +109,13 @@ abstract class AnnotationClassLoader implements LoaderInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
$globals = array(
|
$globals = array(
|
||||||
'pattern' => '',
|
'path' => '',
|
||||||
'requirements' => array(),
|
'requirements' => array(),
|
||||||
'options' => array(),
|
'options' => array(),
|
||||||
'defaults' => array(),
|
'defaults' => array(),
|
||||||
'hostname_pattern' => '',
|
'schemes' => array(),
|
||||||
|
'methods' => array(),
|
||||||
|
'hostname' => '',
|
||||||
);
|
);
|
||||||
|
|
||||||
$class = new \ReflectionClass($class);
|
$class = new \ReflectionClass($class);
|
||||||
@ -121,8 +124,11 @@ abstract class AnnotationClassLoader implements LoaderInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($annot = $this->reader->getClassAnnotation($class, $this->routeAnnotationClass)) {
|
if ($annot = $this->reader->getClassAnnotation($class, $this->routeAnnotationClass)) {
|
||||||
if (null !== $annot->getPattern()) {
|
// for BC reasons
|
||||||
$globals['pattern'] = $annot->getPattern();
|
if (null !== $annot->getPath()) {
|
||||||
|
$globals['path'] = $annot->getPath();
|
||||||
|
} elseif (null !== $annot->getPattern()) {
|
||||||
|
$globals['path'] = $annot->getPattern();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (null !== $annot->getRequirements()) {
|
if (null !== $annot->getRequirements()) {
|
||||||
@ -137,8 +143,16 @@ abstract class AnnotationClassLoader implements LoaderInterface
|
|||||||
$globals['defaults'] = $annot->getDefaults();
|
$globals['defaults'] = $annot->getDefaults();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (null !== $annot->getHostnamePattern()) {
|
if (null !== $annot->getSchemes()) {
|
||||||
$globals['hostname_pattern'] = $annot->getHostnamePattern();
|
$globals['schemes'] = $annot->getSchemes();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null !== $annot->getMethods()) {
|
||||||
|
$globals['methods'] = $annot->getMethods();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null !== $annot->getHostname()) {
|
||||||
|
$globals['hostname'] = $annot->getHostname();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,13 +186,15 @@ abstract class AnnotationClassLoader implements LoaderInterface
|
|||||||
}
|
}
|
||||||
$requirements = array_replace($globals['requirements'], $annot->getRequirements());
|
$requirements = array_replace($globals['requirements'], $annot->getRequirements());
|
||||||
$options = array_replace($globals['options'], $annot->getOptions());
|
$options = array_replace($globals['options'], $annot->getOptions());
|
||||||
|
$schemes = array_replace($globals['schemes'], $annot->getSchemes());
|
||||||
|
$methods = array_replace($globals['methods'], $annot->getMethods());
|
||||||
|
|
||||||
$hostnamePattern = $annot->getHostnamePattern();
|
$hostname = $annot->getHostname();
|
||||||
if (null === $hostnamePattern) {
|
if (null === $hostname) {
|
||||||
$hostnamePattern = $globals['hostname_pattern'];
|
$hostname = $globals['hostname'];
|
||||||
}
|
}
|
||||||
|
|
||||||
$route = new Route($globals['pattern'].$annot->getPattern(), $defaults, $requirements, $options, $hostnamePattern);
|
$route = new Route($globals['path'].$annot->getPath(), $defaults, $requirements, $options, $hostname, $schemes, $methods);
|
||||||
|
|
||||||
$this->configureRoute($route, $class, $method, $annot);
|
$this->configureRoute($route, $class, $method, $annot);
|
||||||
|
|
||||||
|
@ -113,13 +113,25 @@ class XmlFileLoader extends FileLoader
|
|||||||
*/
|
*/
|
||||||
protected function parseRoute(RouteCollection $collection, \DOMElement $node, $path)
|
protected function parseRoute(RouteCollection $collection, \DOMElement $node, $path)
|
||||||
{
|
{
|
||||||
if ('' === ($id = $node->getAttribute('id')) || !$node->hasAttribute('pattern')) {
|
if ('' === ($id = $node->getAttribute('id')) || (!$node->hasAttribute('pattern') && !$node->hasAttribute('path'))) {
|
||||||
throw new \InvalidArgumentException(sprintf('The <route> element in file "%s" must have an "id" and a "pattern" attribute.', $path));
|
throw new \InvalidArgumentException(sprintf('The <route> element in file "%s" must have an "id" and a "path" attribute.', $path));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($node->hasAttribute('pattern')) {
|
||||||
|
if ($node->hasAttribute('path')) {
|
||||||
|
throw new \InvalidArgumentException(sprintf('The <route> element in file "%s" cannot define both a "path" and a "pattern" attribute. Use only "path".', $path));
|
||||||
|
}
|
||||||
|
|
||||||
|
$node->setAttribute('path', $node->getAttribute('pattern'));
|
||||||
|
$node->removeAttribute('pattern');
|
||||||
|
}
|
||||||
|
|
||||||
|
$schemes = array_filter(explode(' ', $node->getAttribute('schemes')));
|
||||||
|
$methods = array_filter(explode(' ', $node->getAttribute('methods')));
|
||||||
|
|
||||||
list($defaults, $requirements, $options) = $this->parseConfigs($node, $path);
|
list($defaults, $requirements, $options) = $this->parseConfigs($node, $path);
|
||||||
|
|
||||||
$route = new Route($node->getAttribute('pattern'), $defaults, $requirements, $options, $node->getAttribute('hostname-pattern'));
|
$route = new Route($node->getAttribute('path'), $defaults, $requirements, $options, $node->getAttribute('hostname'), $schemes, $methods);
|
||||||
$collection->add($id, $route);
|
$collection->add($id, $route);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,7 +153,9 @@ class XmlFileLoader extends FileLoader
|
|||||||
|
|
||||||
$type = $node->getAttribute('type');
|
$type = $node->getAttribute('type');
|
||||||
$prefix = $node->getAttribute('prefix');
|
$prefix = $node->getAttribute('prefix');
|
||||||
$hostnamePattern = $node->hasAttribute('hostname-pattern') ? $node->getAttribute('hostname-pattern') : null;
|
$hostname = $node->hasAttribute('hostname') ? $node->getAttribute('hostname') : null;
|
||||||
|
$schemes = $node->hasAttribute('schemes') ? array_filter(explode(' ', $node->getAttribute('schemes'))) : null;
|
||||||
|
$methods = $node->hasAttribute('methods') ? array_filter(explode(' ', $node->getAttribute('methods'))) : null;
|
||||||
|
|
||||||
list($defaults, $requirements, $options) = $this->parseConfigs($node, $path);
|
list($defaults, $requirements, $options) = $this->parseConfigs($node, $path);
|
||||||
|
|
||||||
@ -150,8 +164,14 @@ class XmlFileLoader extends FileLoader
|
|||||||
$subCollection = $this->import($resource, ('' !== $type ? $type : null), false, $file);
|
$subCollection = $this->import($resource, ('' !== $type ? $type : null), false, $file);
|
||||||
/* @var $subCollection RouteCollection */
|
/* @var $subCollection RouteCollection */
|
||||||
$subCollection->addPrefix($prefix);
|
$subCollection->addPrefix($prefix);
|
||||||
if (null !== $hostnamePattern) {
|
if (null !== $hostname) {
|
||||||
$subCollection->setHostnamePattern($hostnamePattern);
|
$subCollection->setHostname($hostname);
|
||||||
|
}
|
||||||
|
if (null !== $schemes) {
|
||||||
|
$subCollection->setSchemes($schemes);
|
||||||
|
}
|
||||||
|
if (null !== $methods) {
|
||||||
|
$subCollection->setMethods($methods);
|
||||||
}
|
}
|
||||||
$subCollection->addDefaults($defaults);
|
$subCollection->addDefaults($defaults);
|
||||||
$subCollection->addRequirements($requirements);
|
$subCollection->addRequirements($requirements);
|
||||||
|
@ -28,7 +28,7 @@ use Symfony\Component\Config\Loader\FileLoader;
|
|||||||
class YamlFileLoader extends FileLoader
|
class YamlFileLoader extends FileLoader
|
||||||
{
|
{
|
||||||
private static $availableKeys = array(
|
private static $availableKeys = array(
|
||||||
'resource', 'type', 'prefix', 'pattern', 'hostname_pattern', 'defaults', 'requirements', 'options',
|
'resource', 'type', 'prefix', 'pattern', 'path', 'hostname', 'schemes', 'methods', 'defaults', 'requirements', 'options',
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -63,6 +63,15 @@ class YamlFileLoader extends FileLoader
|
|||||||
}
|
}
|
||||||
|
|
||||||
foreach ($config as $name => $config) {
|
foreach ($config as $name => $config) {
|
||||||
|
if (isset($config['pattern'])) {
|
||||||
|
if (isset($config['path'])) {
|
||||||
|
throw new \InvalidArgumentException(sprintf('The file "%s" cannot define both a "path" and a "pattern" attribute. Use only "path".', $path));
|
||||||
|
}
|
||||||
|
|
||||||
|
$config['path'] = $config['pattern'];
|
||||||
|
unset($config['pattern']);
|
||||||
|
}
|
||||||
|
|
||||||
$this->validate($config, $name, $path);
|
$this->validate($config, $name, $path);
|
||||||
|
|
||||||
if (isset($config['resource'])) {
|
if (isset($config['resource'])) {
|
||||||
@ -98,9 +107,11 @@ class YamlFileLoader extends FileLoader
|
|||||||
$defaults = isset($config['defaults']) ? $config['defaults'] : array();
|
$defaults = isset($config['defaults']) ? $config['defaults'] : array();
|
||||||
$requirements = isset($config['requirements']) ? $config['requirements'] : array();
|
$requirements = isset($config['requirements']) ? $config['requirements'] : array();
|
||||||
$options = isset($config['options']) ? $config['options'] : array();
|
$options = isset($config['options']) ? $config['options'] : array();
|
||||||
$hostnamePattern = isset($config['hostname_pattern']) ? $config['hostname_pattern'] : null;
|
$hostname = isset($config['hostname']) ? $config['hostname'] : '';
|
||||||
|
$schemes = isset($config['schemes']) ? $config['schemes'] : array();
|
||||||
|
$methods = isset($config['methods']) ? $config['methods'] : array();
|
||||||
|
|
||||||
$route = new Route($config['pattern'], $defaults, $requirements, $options, $hostnamePattern);
|
$route = new Route($config['path'], $defaults, $requirements, $options, $hostname, $schemes, $methods);
|
||||||
|
|
||||||
$collection->add($name, $route);
|
$collection->add($name, $route);
|
||||||
}
|
}
|
||||||
@ -120,15 +131,23 @@ class YamlFileLoader extends FileLoader
|
|||||||
$defaults = isset($config['defaults']) ? $config['defaults'] : array();
|
$defaults = isset($config['defaults']) ? $config['defaults'] : array();
|
||||||
$requirements = isset($config['requirements']) ? $config['requirements'] : array();
|
$requirements = isset($config['requirements']) ? $config['requirements'] : array();
|
||||||
$options = isset($config['options']) ? $config['options'] : array();
|
$options = isset($config['options']) ? $config['options'] : array();
|
||||||
$hostnamePattern = isset($config['hostname_pattern']) ? $config['hostname_pattern'] : null;
|
$hostname = isset($config['hostname']) ? $config['hostname'] : null;
|
||||||
|
$schemes = isset($config['schemes']) ? $config['schemes'] : null;
|
||||||
|
$methods = isset($config['methods']) ? $config['methods'] : null;
|
||||||
|
|
||||||
$this->setCurrentDir(dirname($path));
|
$this->setCurrentDir(dirname($path));
|
||||||
|
|
||||||
$subCollection = $this->import($config['resource'], $type, false, $file);
|
$subCollection = $this->import($config['resource'], $type, false, $file);
|
||||||
/* @var $subCollection RouteCollection */
|
/* @var $subCollection RouteCollection */
|
||||||
$subCollection->addPrefix($prefix);
|
$subCollection->addPrefix($prefix);
|
||||||
if (null !== $hostnamePattern) {
|
if (null !== $hostname) {
|
||||||
$subCollection->setHostnamePattern($hostnamePattern);
|
$subCollection->setHostname($hostname);
|
||||||
|
}
|
||||||
|
if (null !== $schemes) {
|
||||||
|
$subCollection->setSchemes($schemes);
|
||||||
|
}
|
||||||
|
if (null !== $methods) {
|
||||||
|
$subCollection->setMethods($methods);
|
||||||
}
|
}
|
||||||
$subCollection->addDefaults($defaults);
|
$subCollection->addDefaults($defaults);
|
||||||
$subCollection->addRequirements($requirements);
|
$subCollection->addRequirements($requirements);
|
||||||
@ -158,9 +177,9 @@ class YamlFileLoader extends FileLoader
|
|||||||
$path, $name, implode('", "', $extraKeys), implode('", "', self::$availableKeys)
|
$path, $name, implode('", "', $extraKeys), implode('", "', self::$availableKeys)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
if (isset($config['resource']) && isset($config['pattern'])) {
|
if (isset($config['resource']) && isset($config['path'])) {
|
||||||
throw new \InvalidArgumentException(sprintf(
|
throw new \InvalidArgumentException(sprintf(
|
||||||
'The routing file "%s" must not specify both the "resource" key and the "pattern" key for "%s". Choose between an import and a route definition.',
|
'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.',
|
||||||
$path, $name
|
$path, $name
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@ -170,9 +189,9 @@ class YamlFileLoader extends FileLoader
|
|||||||
$name, $path
|
$name, $path
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
if (!isset($config['resource']) && !isset($config['pattern'])) {
|
if (!isset($config['resource']) && !isset($config['path'])) {
|
||||||
throw new \InvalidArgumentException(sprintf(
|
throw new \InvalidArgumentException(sprintf(
|
||||||
'You must define a "pattern" for the route "%s" in file "%s".',
|
'You must define a "path" for the route "%s" in file "%s".',
|
||||||
$name, $path
|
$name, $path
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,16 @@
|
|||||||
|
|
||||||
<xsd:element name="routes" type="routes" />
|
<xsd:element name="routes" type="routes" />
|
||||||
|
|
||||||
|
<xsd:simpleType name="word">
|
||||||
|
<xsd:restriction base="xsd:string">
|
||||||
|
<xsd:pattern value="([a-zA-Z]){3,}"/>
|
||||||
|
</xsd:restriction>
|
||||||
|
</xsd:simpleType>
|
||||||
|
|
||||||
|
<xsd:simpleType name="stringlist">
|
||||||
|
<xsd:list itemType="word"/>
|
||||||
|
</xsd:simpleType>
|
||||||
|
|
||||||
<xsd:complexType name="routes">
|
<xsd:complexType name="routes">
|
||||||
<xsd:choice minOccurs="0" maxOccurs="unbounded">
|
<xsd:choice minOccurs="0" maxOccurs="unbounded">
|
||||||
<xsd:element name="import" type="import" />
|
<xsd:element name="import" type="import" />
|
||||||
@ -36,8 +46,11 @@
|
|||||||
<xsd:group ref="configs" minOccurs="0" maxOccurs="unbounded" />
|
<xsd:group ref="configs" minOccurs="0" maxOccurs="unbounded" />
|
||||||
|
|
||||||
<xsd:attribute name="id" type="xsd:string" use="required" />
|
<xsd:attribute name="id" type="xsd:string" use="required" />
|
||||||
<xsd:attribute name="pattern" type="xsd:string" use="required" />
|
<xsd:attribute name="path" type="xsd:string" />
|
||||||
<xsd:attribute name="hostname-pattern" type="xsd:string" />
|
<xsd:attribute name="pattern" type="xsd:string" />
|
||||||
|
<xsd:attribute name="hostname" type="xsd:string" />
|
||||||
|
<xsd:attribute name="schemes" type="stringlist" />
|
||||||
|
<xsd:attribute name="methods" type="stringlist" />
|
||||||
</xsd:complexType>
|
</xsd:complexType>
|
||||||
|
|
||||||
<xsd:complexType name="import">
|
<xsd:complexType name="import">
|
||||||
@ -46,7 +59,9 @@
|
|||||||
<xsd:attribute name="resource" type="xsd:string" use="required" />
|
<xsd:attribute name="resource" type="xsd:string" use="required" />
|
||||||
<xsd:attribute name="type" type="xsd:string" />
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
<xsd:attribute name="prefix" type="xsd:string" />
|
<xsd:attribute name="prefix" type="xsd:string" />
|
||||||
<xsd:attribute name="hostname-pattern" type="xsd:string" />
|
<xsd:attribute name="hostname" type="xsd:string" />
|
||||||
|
<xsd:attribute name="schemes" type="stringlist" />
|
||||||
|
<xsd:attribute name="methods" type="stringlist" />
|
||||||
</xsd:complexType>
|
</xsd:complexType>
|
||||||
|
|
||||||
<xsd:complexType name="element">
|
<xsd:complexType name="element">
|
||||||
|
@ -48,16 +48,16 @@ class TraceableUrlMatcher extends UrlMatcher
|
|||||||
|
|
||||||
if (!preg_match($compiledRoute->getRegex(), $pathinfo, $matches)) {
|
if (!preg_match($compiledRoute->getRegex(), $pathinfo, $matches)) {
|
||||||
// does it match without any requirements?
|
// does it match without any requirements?
|
||||||
$r = new Route($route->getPattern(), $route->getDefaults(), array(), $route->getOptions());
|
$r = new Route($route->getPath(), $route->getDefaults(), array(), $route->getOptions());
|
||||||
$cr = $r->compile();
|
$cr = $r->compile();
|
||||||
if (!preg_match($cr->getRegex(), $pathinfo)) {
|
if (!preg_match($cr->getRegex(), $pathinfo)) {
|
||||||
$this->addTrace(sprintf('Pattern "%s" does not match', $route->getPattern()), self::ROUTE_DOES_NOT_MATCH, $name, $route);
|
$this->addTrace(sprintf('Path "%s" does not match', $route->getPath()), self::ROUTE_DOES_NOT_MATCH, $name, $route);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($route->getRequirements() as $n => $regex) {
|
foreach ($route->getRequirements() as $n => $regex) {
|
||||||
$r = new Route($route->getPattern(), $route->getDefaults(), array($n => $regex), $route->getOptions());
|
$r = new Route($route->getPath(), $route->getDefaults(), array($n => $regex), $route->getOptions());
|
||||||
$cr = $r->compile();
|
$cr = $r->compile();
|
||||||
|
|
||||||
if (in_array($n, $cr->getVariables()) && !preg_match($cr->getRegex(), $pathinfo)) {
|
if (in_array($n, $cr->getVariables()) && !preg_match($cr->getRegex(), $pathinfo)) {
|
||||||
@ -104,10 +104,10 @@ class TraceableUrlMatcher extends UrlMatcher
|
|||||||
private function addTrace($log, $level = self::ROUTE_DOES_NOT_MATCH, $name = null, $route = null)
|
private function addTrace($log, $level = self::ROUTE_DOES_NOT_MATCH, $name = null, $route = null)
|
||||||
{
|
{
|
||||||
$this->traces[] = array(
|
$this->traces[] = array(
|
||||||
'log' => $log,
|
'log' => $log,
|
||||||
'name' => $name,
|
'name' => $name,
|
||||||
'level' => $level,
|
'level' => $level,
|
||||||
'pattern' => null !== $route ? $route->getPattern() : null,
|
'path' => null !== $route ? $route->getPath() : null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@ namespace Symfony\Component\Routing;
|
|||||||
* A Route describes a route and its parameters.
|
* A Route describes a route and its parameters.
|
||||||
*
|
*
|
||||||
* @author Fabien Potencier <fabien@symfony.com>
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
* @author Tobias Schultze <http://tobion.de>
|
||||||
*
|
*
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
@ -23,14 +24,24 @@ class Route implements \Serializable
|
|||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
private $pattern = '/';
|
private $path = '/';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
private $hostnamePattern = '';
|
private $hostname = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $schemes = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $methods = array();
|
||||||
|
|
||||||
|
/**
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
private $defaults = array();
|
private $defaults = array();
|
||||||
@ -57,52 +68,68 @@ class Route implements \Serializable
|
|||||||
*
|
*
|
||||||
* * compiler_class: A class name able to compile this route instance (RouteCompiler by default)
|
* * compiler_class: A class name able to compile this route instance (RouteCompiler by default)
|
||||||
*
|
*
|
||||||
* @param string $pattern The path pattern to match
|
* @param string $path The path pattern to match
|
||||||
* @param array $defaults An array of default parameter values
|
* @param array $defaults An array of default parameter values
|
||||||
* @param array $requirements An array of requirements for parameters (regexes)
|
* @param array $requirements An array of requirements for parameters (regexes)
|
||||||
* @param array $options An array of options
|
* @param array $options An array of options
|
||||||
* @param string $hostnamePattern The hostname pattern to match
|
* @param string $hostname The hostname pattern to match
|
||||||
|
* @param string|array $schemes A required URI scheme or an array of restricted schemes
|
||||||
|
* @param string|array $methods A required HTTP method or an array of restricted methods
|
||||||
*
|
*
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
public function __construct($pattern, array $defaults = array(), array $requirements = array(), array $options = array(), $hostnamePattern = '')
|
public function __construct($path, array $defaults = array(), array $requirements = array(), array $options = array(), $hostname = '', $schemes = array(), $methods = array())
|
||||||
{
|
{
|
||||||
$this->setPattern($pattern);
|
$this->setPath($path);
|
||||||
$this->setDefaults($defaults);
|
$this->setDefaults($defaults);
|
||||||
$this->setRequirements($requirements);
|
$this->setRequirements($requirements);
|
||||||
$this->setOptions($options);
|
$this->setOptions($options);
|
||||||
$this->setHostnamePattern($hostnamePattern);
|
$this->setHostname($hostname);
|
||||||
|
// The conditions make sure that an initial empty $schemes/$methods does not override the corresponding requirement.
|
||||||
|
// They can be removed when the BC layer is removed.
|
||||||
|
if ($schemes) {
|
||||||
|
$this->setSchemes($schemes);
|
||||||
|
}
|
||||||
|
if ($methods) {
|
||||||
|
$this->setMethods($methods);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function serialize()
|
public function serialize()
|
||||||
{
|
{
|
||||||
return serialize(array(
|
return serialize(array(
|
||||||
'pattern' => $this->pattern,
|
'path' => $this->path,
|
||||||
'hostnamePattern' => $this->hostnamePattern,
|
'hostname' => $this->hostname,
|
||||||
'defaults' => $this->defaults,
|
'defaults' => $this->defaults,
|
||||||
'requirements' => $this->requirements,
|
'requirements' => $this->requirements,
|
||||||
'options' => $this->options,
|
'options' => $this->options,
|
||||||
|
'schemes' => $this->schemes,
|
||||||
|
'methods' => $this->methods,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function unserialize($data)
|
public function unserialize($data)
|
||||||
{
|
{
|
||||||
$data = unserialize($data);
|
$data = unserialize($data);
|
||||||
$this->pattern = $data['pattern'];
|
$this->path = $data['path'];
|
||||||
$this->hostnamePattern = $data['hostnamePattern'];
|
$this->hostname = $data['hostname'];
|
||||||
$this->defaults = $data['defaults'];
|
$this->defaults = $data['defaults'];
|
||||||
$this->requirements = $data['requirements'];
|
$this->requirements = $data['requirements'];
|
||||||
$this->options = $data['options'];
|
$this->options = $data['options'];
|
||||||
|
$this->schemes = $data['schemes'];
|
||||||
|
$this->methods = $data['methods'];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the pattern for the path.
|
* Returns the pattern for the path.
|
||||||
*
|
*
|
||||||
* @return string The pattern
|
* @return string The pattern
|
||||||
|
*
|
||||||
|
* @deprecated Deprecated in 2.2, to be removed in 3.0. Use setPath instead.
|
||||||
*/
|
*/
|
||||||
public function getPattern()
|
public function getPattern()
|
||||||
{
|
{
|
||||||
return $this->pattern;
|
return $this->path;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -113,12 +140,38 @@ class Route implements \Serializable
|
|||||||
* @param string $pattern The pattern
|
* @param string $pattern The pattern
|
||||||
*
|
*
|
||||||
* @return Route The current Route instance
|
* @return Route The current Route instance
|
||||||
|
*
|
||||||
|
* @deprecated Deprecated in 2.2, to be removed in 3.0. Use setPath instead.
|
||||||
*/
|
*/
|
||||||
public function setPattern($pattern)
|
public function setPattern($pattern)
|
||||||
|
{
|
||||||
|
return $this->setPath($pattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the pattern for the path.
|
||||||
|
*
|
||||||
|
* @return string The path pattern
|
||||||
|
*/
|
||||||
|
public function getPath()
|
||||||
|
{
|
||||||
|
return $this->path;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the pattern for the path.
|
||||||
|
*
|
||||||
|
* This method implements a fluent interface.
|
||||||
|
*
|
||||||
|
* @param string $path The path pattern
|
||||||
|
*
|
||||||
|
* @return Route The current Route instance
|
||||||
|
*/
|
||||||
|
public function setPath($path)
|
||||||
{
|
{
|
||||||
// A pattern must start with a slash and must not have multiple slashes at the beginning because the
|
// A pattern must start with a slash and must not have multiple slashes at the beginning because the
|
||||||
// generated path for this route would be confused with a network path, e.g. '//domain.com/path'.
|
// generated path for this route would be confused with a network path, e.g. '//domain.com/path'.
|
||||||
$this->pattern = '/' . ltrim(trim($pattern), '/');
|
$this->path = '/' . ltrim(trim($path), '/');
|
||||||
$this->compiled = null;
|
$this->compiled = null;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
@ -129,9 +182,9 @@ class Route implements \Serializable
|
|||||||
*
|
*
|
||||||
* @return string The pattern
|
* @return string The pattern
|
||||||
*/
|
*/
|
||||||
public function getHostnamePattern()
|
public function getHostname()
|
||||||
{
|
{
|
||||||
return $this->hostnamePattern;
|
return $this->hostname;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -141,9 +194,83 @@ class Route implements \Serializable
|
|||||||
*
|
*
|
||||||
* @return Route The current Route instance
|
* @return Route The current Route instance
|
||||||
*/
|
*/
|
||||||
public function setHostnamePattern($pattern)
|
public function setHostname($pattern)
|
||||||
{
|
{
|
||||||
$this->hostnamePattern = (string) $pattern;
|
$this->hostname = (string) $pattern;
|
||||||
|
$this->compiled = null;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the lowercased schemes this route is restricted to.
|
||||||
|
* So an empty array means that any scheme is allowed.
|
||||||
|
*
|
||||||
|
* @return array The schemes
|
||||||
|
*/
|
||||||
|
public function getSchemes()
|
||||||
|
{
|
||||||
|
return $this->schemes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the schemes (e.g. 'https') this route is restricted to.
|
||||||
|
* So an empty array means that any scheme is allowed.
|
||||||
|
*
|
||||||
|
* This method implements a fluent interface.
|
||||||
|
*
|
||||||
|
* @param string|array $schemes The scheme or an array of schemes
|
||||||
|
*
|
||||||
|
* @return Route The current Route instance
|
||||||
|
*/
|
||||||
|
public function setSchemes($schemes)
|
||||||
|
{
|
||||||
|
$this->schemes = array_map('strtolower', (array) $schemes);
|
||||||
|
|
||||||
|
// this is to keep BC and will be removed in a future version
|
||||||
|
if ($this->schemes) {
|
||||||
|
$this->requirements['_scheme'] = implode('|', $this->schemes);
|
||||||
|
} else {
|
||||||
|
unset($this->requirements['_scheme']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->compiled = null;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the uppercased HTTP methods this route is restricted to.
|
||||||
|
* So an empty array means that any method is allowed.
|
||||||
|
*
|
||||||
|
* @return array The schemes
|
||||||
|
*/
|
||||||
|
public function getMethods()
|
||||||
|
{
|
||||||
|
return $this->methods;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the HTTP methods (e.g. 'POST') this route is restricted to.
|
||||||
|
* So an empty array means that any method is allowed.
|
||||||
|
*
|
||||||
|
* This method implements a fluent interface.
|
||||||
|
*
|
||||||
|
* @param string|array $methods The method or an array of methods
|
||||||
|
*
|
||||||
|
* @return Route The current Route instance
|
||||||
|
*/
|
||||||
|
public function setMethods($methods)
|
||||||
|
{
|
||||||
|
$this->methods = array_map('strtoupper', (array) $methods);
|
||||||
|
|
||||||
|
// this is to keep BC and will be removed in a future version
|
||||||
|
if ($this->methods) {
|
||||||
|
$this->requirements['_method'] = implode('|', $this->methods);
|
||||||
|
} else {
|
||||||
|
unset($this->requirements['_method']);
|
||||||
|
}
|
||||||
|
|
||||||
$this->compiled = null;
|
$this->compiled = null;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
@ -453,6 +580,13 @@ class Route implements \Serializable
|
|||||||
throw new \InvalidArgumentException(sprintf('Routing requirement for "%s" cannot be empty.', $key));
|
throw new \InvalidArgumentException(sprintf('Routing requirement for "%s" cannot be empty.', $key));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this is to keep BC and will be removed in a future version
|
||||||
|
if ('_scheme' === $key) {
|
||||||
|
$this->setSchemes(explode('|', $regex));
|
||||||
|
} elseif ('_method' === $key) {
|
||||||
|
$this->setMethods(explode('|', $regex));
|
||||||
|
}
|
||||||
|
|
||||||
return $regex;
|
return $regex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -235,7 +235,7 @@ class RouteCollection implements \IteratorAggregate, \Countable
|
|||||||
$options = func_num_args() > 3 ? func_get_arg(3) : array();
|
$options = func_num_args() > 3 ? func_get_arg(3) : array();
|
||||||
|
|
||||||
foreach ($this->routes as $route) {
|
foreach ($this->routes as $route) {
|
||||||
$route->setPattern('/' . $prefix . $route->getPattern());
|
$route->setPath('/' . $prefix . $route->getPath());
|
||||||
$route->addDefaults($defaults);
|
$route->addDefaults($defaults);
|
||||||
$route->addRequirements($requirements);
|
$route->addRequirements($requirements);
|
||||||
$route->addOptions($options);
|
$route->addOptions($options);
|
||||||
@ -261,10 +261,10 @@ class RouteCollection implements \IteratorAggregate, \Countable
|
|||||||
* @param array $defaults An array of default values
|
* @param array $defaults An array of default values
|
||||||
* @param array $requirements An array of requirements
|
* @param array $requirements An array of requirements
|
||||||
*/
|
*/
|
||||||
public function setHostnamePattern($pattern, array $defaults = array(), array $requirements = array())
|
public function setHostname($pattern, array $defaults = array(), array $requirements = array())
|
||||||
{
|
{
|
||||||
foreach ($this->routes as $route) {
|
foreach ($this->routes as $route) {
|
||||||
$route->setHostnamePattern($pattern);
|
$route->setHostname($pattern);
|
||||||
$route->addDefaults($defaults);
|
$route->addDefaults($defaults);
|
||||||
$route->addRequirements($requirements);
|
$route->addRequirements($requirements);
|
||||||
}
|
}
|
||||||
@ -318,6 +318,30 @@ class RouteCollection implements \IteratorAggregate, \Countable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the schemes (e.g. 'https') all child routes are restricted to.
|
||||||
|
*
|
||||||
|
* @param string|array $schemes The scheme or an array of schemes
|
||||||
|
*/
|
||||||
|
public function setSchemes($schemes)
|
||||||
|
{
|
||||||
|
foreach ($this->routes as $route) {
|
||||||
|
$route->setSchemes($schemes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the HTTP methods (e.g. 'POST') all child routes are restricted to.
|
||||||
|
*
|
||||||
|
* @param string|array $methods The method or an array of methods
|
||||||
|
*/
|
||||||
|
public function setMethods($methods)
|
||||||
|
{
|
||||||
|
foreach ($this->routes as $route) {
|
||||||
|
$route->setMethods($methods);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an array of resources loaded to build this collection.
|
* Returns an array of resources loaded to build this collection.
|
||||||
*
|
*
|
||||||
|
@ -46,8 +46,8 @@ class RouteCompiler implements RouteCompilerInterface
|
|||||||
$hostnameRegex = null;
|
$hostnameRegex = null;
|
||||||
$hostnameTokens = array();
|
$hostnameTokens = array();
|
||||||
|
|
||||||
if ('' !== $hostnamePattern = $route->getHostnamePattern()) {
|
if ('' !== $hostname = $route->getHostname()) {
|
||||||
$result = self::compilePattern($route, $hostnamePattern, true);
|
$result = self::compilePattern($route, $hostname, true);
|
||||||
|
|
||||||
$hostnameVariables = $result['variables'];
|
$hostnameVariables = $result['variables'];
|
||||||
$variables = array_merge($variables, $hostnameVariables);
|
$variables = array_merge($variables, $hostnameVariables);
|
||||||
@ -56,9 +56,9 @@ class RouteCompiler implements RouteCompilerInterface
|
|||||||
$hostnameRegex = $result['regex'];
|
$hostnameRegex = $result['regex'];
|
||||||
}
|
}
|
||||||
|
|
||||||
$pattern = $route->getPattern();
|
$path = $route->getPath();
|
||||||
|
|
||||||
$result = self::compilePattern($route, $pattern, false);
|
$result = self::compilePattern($route, $path, false);
|
||||||
|
|
||||||
$staticPrefix = $result['staticPrefix'];
|
$staticPrefix = $result['staticPrefix'];
|
||||||
|
|
||||||
|
@ -36,11 +36,14 @@ class RouteTest extends \PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
return array(
|
return array(
|
||||||
array('value', '/Blog', 'getPattern'),
|
array('value', '/Blog', 'getPattern'),
|
||||||
|
array('value', '/Blog', 'getPath'),
|
||||||
array('requirements', array('_method' => 'GET'), 'getRequirements'),
|
array('requirements', array('_method' => 'GET'), 'getRequirements'),
|
||||||
array('options', array('compiler_class' => 'RouteCompiler'), 'getOptions'),
|
array('options', array('compiler_class' => 'RouteCompiler'), 'getOptions'),
|
||||||
array('name', 'blog_index', 'getName'),
|
array('name', 'blog_index', 'getName'),
|
||||||
array('defaults', array('_controller' => 'MyBlogBundle:Blog:index'), 'getDefaults'),
|
array('defaults', array('_controller' => 'MyBlogBundle:Blog:index'), 'getDefaults'),
|
||||||
array('hostname_pattern', array('{locale}.example.com'), 'getHostnamePattern')
|
array('schemes', array('https'), 'getSchemes'),
|
||||||
|
array('methods', array('GET', 'POST'), 'getMethods'),
|
||||||
|
array('hostname', array('{locale}.example.com'), 'getHostname')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">
|
xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">
|
||||||
|
|
||||||
<r:route id="blog_show" pattern="/blog/{slug}" hostname-pattern="{_locale}.example.com">
|
<r:route id="blog_show" pattern="/blog/{slug}" hostname="{_locale}.example.com">
|
||||||
<r:default key="_controller">MyBundle:Blog:show</r:default>
|
<r:default key="_controller">MyBundle:Blog:show</r:default>
|
||||||
<requirement xmlns="http://symfony.com/schema/routing" key="slug">\w+</requirement>
|
<requirement xmlns="http://symfony.com/schema/routing" key="slug">\w+</requirement>
|
||||||
<r2:requirement xmlns:r2="http://symfony.com/schema/routing" key="_locale">en|fr|de</r2:requirement>
|
<r2:requirement xmlns:r2="http://symfony.com/schema/routing" key="_locale">en|fr|de</r2:requirement>
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">
|
xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">
|
||||||
|
|
||||||
<route id="blog_show" pattern="/blog/{slug}" hostname-pattern="{locale}.example.com">
|
<route id="blog_show" pattern="/blog/{slug}" hostname="{locale}.example.com">
|
||||||
<default key="_controller">MyBundle:Blog:show</default>
|
<default key="_controller">MyBundle:Blog:show</default>
|
||||||
<requirement key="_method">GET</requirement>
|
<requirement key="_method">GET</requirement>
|
||||||
<requirement key="locale">\w+</requirement>
|
<requirement key="locale">\w+</requirement>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
blog_show:
|
blog_show:
|
||||||
pattern: /blog/{slug}
|
pattern: /blog/{slug}
|
||||||
defaults: { _controller: MyBlogBundle:Blog:show }
|
defaults: { _controller: MyBlogBundle:Blog:show }
|
||||||
hostname_pattern: "{locale}.example.com"
|
hostname : "{locale}.example.com"
|
||||||
requirements: { '_method': 'GET', 'locale': '\w+' }
|
requirements: { '_method': 'GET', 'locale': '\w+' }
|
||||||
options:
|
options:
|
||||||
compiler_class: RouteCompiler
|
compiler_class: RouteCompiler
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">
|
xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">
|
||||||
|
|
||||||
<import resource="validpattern.xml" prefix="/{foo}" hostname-pattern="{locale}.example.com">
|
<import resource="validpattern.xml" prefix="/{foo}" hostname="{locale}.example.com">
|
||||||
<default key="foo">123</default>
|
<default key="foo">123</default>
|
||||||
<requirement key="foo">\d+</requirement>
|
<requirement key="foo">\d+</requirement>
|
||||||
<option key="foo">bar</option>
|
<option key="foo">bar</option>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
blog_show:
|
blog_show:
|
||||||
resource: validpattern.yml
|
resource: validpattern.yml
|
||||||
prefix: /{foo}
|
prefix: /{foo}
|
||||||
defaults: { 'foo': '123' }
|
defaults: { 'foo': '123' }
|
||||||
requirements: { 'foo': '\d+' }
|
requirements: { 'foo': '\d+' }
|
||||||
options: { 'foo': 'bar' }
|
options: { 'foo': 'bar' }
|
||||||
hostname_pattern: "{locale}.example.com"
|
hostname: "{locale}.example.com"
|
||||||
|
@ -89,10 +89,12 @@ class AnnotationClassLoaderTest extends AbstractAnnotationLoaderTest
|
|||||||
{
|
{
|
||||||
$routeDatas = array_replace(array(
|
$routeDatas = array_replace(array(
|
||||||
'name' => 'route',
|
'name' => 'route',
|
||||||
'pattern' => '/',
|
'path' => '/',
|
||||||
'requirements' => array(),
|
'requirements' => array(),
|
||||||
'options' => array(),
|
'options' => array(),
|
||||||
'defaults' => array(),
|
'defaults' => array(),
|
||||||
|
'schemes' => array(),
|
||||||
|
'methods' => array(),
|
||||||
), $routeDatas);
|
), $routeDatas);
|
||||||
|
|
||||||
$this->reader
|
$this->reader
|
||||||
@ -103,7 +105,7 @@ class AnnotationClassLoaderTest extends AbstractAnnotationLoaderTest
|
|||||||
$routeCollection = $this->loader->load($className);
|
$routeCollection = $this->loader->load($className);
|
||||||
$route = $routeCollection->get($routeDatas['name']);
|
$route = $routeCollection->get($routeDatas['name']);
|
||||||
|
|
||||||
$this->assertSame($routeDatas['pattern'], $route->getPattern(), '->load preserves pattern annotation');
|
$this->assertSame($routeDatas['path'], $route->getPath(), '->load preserves path annotation');
|
||||||
$this->assertSame($routeDatas['requirements'],$route->getRequirements(), '->load preserves requirements annotation');
|
$this->assertSame($routeDatas['requirements'],$route->getRequirements(), '->load preserves requirements annotation');
|
||||||
$this->assertCount(0, array_intersect($route->getOptions(), $routeDatas['options']), '->load preserves options annotation');
|
$this->assertCount(0, array_intersect($route->getOptions(), $routeDatas['options']), '->load preserves options annotation');
|
||||||
$this->assertSame(array_replace($routeDatas['defaults'], $methodArgs), $route->getDefaults(), '->load preserves defaults annotation');
|
$this->assertSame(array_replace($routeDatas['defaults'], $methodArgs), $route->getDefaults(), '->load preserves defaults annotation');
|
||||||
|
@ -43,10 +43,10 @@ class PhpFileLoaderTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->assertEquals(1, count($routes), 'One route is loaded');
|
$this->assertEquals(1, count($routes), 'One route is loaded');
|
||||||
$this->assertContainsOnly('Symfony\Component\Routing\Route', $routes);
|
$this->assertContainsOnly('Symfony\Component\Routing\Route', $routes);
|
||||||
$route = $routes['blog_show'];
|
$route = $routes['blog_show'];
|
||||||
$this->assertEquals('/blog/{slug}', $route->getPattern());
|
$this->assertEquals('/blog/{slug}', $route->getPath());
|
||||||
$this->assertEquals('MyBlogBundle:Blog:show', $route->getDefault('_controller'));
|
$this->assertEquals('MyBlogBundle:Blog:show', $route->getDefault('_controller'));
|
||||||
$this->assertEquals('GET', $route->getRequirement('_method'));
|
$this->assertEquals('GET', $route->getRequirement('_method'));
|
||||||
$this->assertEquals('{locale}.example.com', $route->getHostnamePattern());
|
$this->assertEquals('{locale}.example.com', $route->getHostname());
|
||||||
$this->assertEquals('RouteCompiler', $route->getOption('compiler_class'));
|
$this->assertEquals('RouteCompiler', $route->getOption('compiler_class'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,11 +44,11 @@ class XmlFileLoaderTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->assertEquals(1, count($routes), 'One route is loaded');
|
$this->assertEquals(1, count($routes), 'One route is loaded');
|
||||||
$this->assertContainsOnly('Symfony\Component\Routing\Route', $routes);
|
$this->assertContainsOnly('Symfony\Component\Routing\Route', $routes);
|
||||||
$route = $routes['blog_show'];
|
$route = $routes['blog_show'];
|
||||||
$this->assertEquals('/blog/{slug}', $route->getPattern());
|
$this->assertEquals('/blog/{slug}', $route->getPath());
|
||||||
$this->assertEquals('MyBundle:Blog:show', $route->getDefault('_controller'));
|
$this->assertEquals('MyBundle:Blog:show', $route->getDefault('_controller'));
|
||||||
$this->assertEquals('GET', $route->getRequirement('_method'));
|
$this->assertEquals('GET', $route->getRequirement('_method'));
|
||||||
$this->assertEquals('\w+', $route->getRequirement('locale'));
|
$this->assertEquals('\w+', $route->getRequirement('locale'));
|
||||||
$this->assertEquals('{locale}.example.com', $route->getHostnamePattern());
|
$this->assertEquals('{locale}.example.com', $route->getHostname());
|
||||||
$this->assertEquals('RouteCompiler', $route->getOption('compiler_class'));
|
$this->assertEquals('RouteCompiler', $route->getOption('compiler_class'));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,11 +59,11 @@ class XmlFileLoaderTest extends \PHPUnit_Framework_TestCase
|
|||||||
|
|
||||||
$this->assertCount(1, $routeCollection, 'One route is loaded');
|
$this->assertCount(1, $routeCollection, 'One route is loaded');
|
||||||
$route = $routeCollection->get('blog_show');
|
$route = $routeCollection->get('blog_show');
|
||||||
$this->assertEquals('/blog/{slug}', $route->getPattern());
|
$this->assertEquals('/blog/{slug}', $route->getPath());
|
||||||
$this->assertEquals('MyBundle:Blog:show', $route->getDefault('_controller'));
|
$this->assertEquals('MyBundle:Blog:show', $route->getDefault('_controller'));
|
||||||
$this->assertEquals('\w+', $route->getRequirement('slug'));
|
$this->assertEquals('\w+', $route->getRequirement('slug'));
|
||||||
$this->assertEquals('en|fr|de', $route->getRequirement('_locale'));
|
$this->assertEquals('en|fr|de', $route->getRequirement('_locale'));
|
||||||
$this->assertEquals('{_locale}.example.com', $route->getHostnamePattern());
|
$this->assertEquals('{_locale}.example.com', $route->getHostname());
|
||||||
$this->assertEquals('RouteCompiler', $route->getOption('compiler_class'));
|
$this->assertEquals('RouteCompiler', $route->getOption('compiler_class'));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,12 +75,12 @@ class XmlFileLoaderTest extends \PHPUnit_Framework_TestCase
|
|||||||
|
|
||||||
$this->assertEquals(1, count($routes), 'One route is loaded');
|
$this->assertEquals(1, count($routes), 'One route is loaded');
|
||||||
$this->assertContainsOnly('Symfony\Component\Routing\Route', $routes);
|
$this->assertContainsOnly('Symfony\Component\Routing\Route', $routes);
|
||||||
$this->assertEquals('/{foo}/blog/{slug}', $routes['blog_show']->getPattern());
|
$this->assertEquals('/{foo}/blog/{slug}', $routes['blog_show']->getPath());
|
||||||
$this->assertEquals('MyBundle:Blog:show', $routes['blog_show']->getDefault('_controller'));
|
$this->assertEquals('MyBundle:Blog:show', $routes['blog_show']->getDefault('_controller'));
|
||||||
$this->assertEquals('123', $routes['blog_show']->getDefault('foo'));
|
$this->assertEquals('123', $routes['blog_show']->getDefault('foo'));
|
||||||
$this->assertEquals('\d+', $routes['blog_show']->getRequirement('foo'));
|
$this->assertEquals('\d+', $routes['blog_show']->getRequirement('foo'));
|
||||||
$this->assertEquals('bar', $routes['blog_show']->getOption('foo'));
|
$this->assertEquals('bar', $routes['blog_show']->getOption('foo'));
|
||||||
$this->assertEquals('{locale}.example.com', $routes['blog_show']->getHostnamePattern());
|
$this->assertEquals('{locale}.example.com', $routes['blog_show']->getHostname());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -70,7 +70,7 @@ class YamlFileLoaderTest extends \PHPUnit_Framework_TestCase
|
|||||||
$route = $routeCollection->get('#$péß^a|');
|
$route = $routeCollection->get('#$péß^a|');
|
||||||
|
|
||||||
$this->assertInstanceOf('Symfony\Component\Routing\Route', $route);
|
$this->assertInstanceOf('Symfony\Component\Routing\Route', $route);
|
||||||
$this->assertSame('/true', $route->getPattern());
|
$this->assertSame('/true', $route->getPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testLoadWithPattern()
|
public function testLoadWithPattern()
|
||||||
@ -82,11 +82,11 @@ class YamlFileLoaderTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->assertEquals(1, count($routes), 'One route is loaded');
|
$this->assertEquals(1, count($routes), 'One route is loaded');
|
||||||
$this->assertContainsOnly('Symfony\Component\Routing\Route', $routes);
|
$this->assertContainsOnly('Symfony\Component\Routing\Route', $routes);
|
||||||
$route = $routes['blog_show'];
|
$route = $routes['blog_show'];
|
||||||
$this->assertEquals('/blog/{slug}', $route->getPattern());
|
$this->assertEquals('/blog/{slug}', $route->getPath());
|
||||||
$this->assertEquals('MyBlogBundle:Blog:show', $route->getDefault('_controller'));
|
$this->assertEquals('MyBlogBundle:Blog:show', $route->getDefault('_controller'));
|
||||||
$this->assertEquals('GET', $route->getRequirement('_method'));
|
$this->assertEquals('GET', $route->getRequirement('_method'));
|
||||||
$this->assertEquals('\w+', $route->getRequirement('locale'));
|
$this->assertEquals('\w+', $route->getRequirement('locale'));
|
||||||
$this->assertEquals('{locale}.example.com', $route->getHostnamePattern());
|
$this->assertEquals('{locale}.example.com', $route->getHostname());
|
||||||
$this->assertEquals('RouteCompiler', $route->getOption('compiler_class'));
|
$this->assertEquals('RouteCompiler', $route->getOption('compiler_class'));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,11 +98,11 @@ class YamlFileLoaderTest extends \PHPUnit_Framework_TestCase
|
|||||||
|
|
||||||
$this->assertEquals(1, count($routes), 'One route is loaded');
|
$this->assertEquals(1, count($routes), 'One route is loaded');
|
||||||
$this->assertContainsOnly('Symfony\Component\Routing\Route', $routes);
|
$this->assertContainsOnly('Symfony\Component\Routing\Route', $routes);
|
||||||
$this->assertEquals('/{foo}/blog/{slug}', $routes['blog_show']->getPattern());
|
$this->assertEquals('/{foo}/blog/{slug}', $routes['blog_show']->getPath());
|
||||||
$this->assertEquals('MyBlogBundle:Blog:show', $routes['blog_show']->getDefault('_controller'));
|
$this->assertEquals('MyBlogBundle:Blog:show', $routes['blog_show']->getDefault('_controller'));
|
||||||
$this->assertEquals('123', $routes['blog_show']->getDefault('foo'));
|
$this->assertEquals('123', $routes['blog_show']->getDefault('foo'));
|
||||||
$this->assertEquals('\d+', $routes['blog_show']->getRequirement('foo'));
|
$this->assertEquals('\d+', $routes['blog_show']->getRequirement('foo'));
|
||||||
$this->assertEquals('bar', $routes['blog_show']->getOption('foo'));
|
$this->assertEquals('bar', $routes['blog_show']->getOption('foo'));
|
||||||
$this->assertEquals('{locale}.example.com', $routes['blog_show']->getHostnamePattern());
|
$this->assertEquals('{locale}.example.com', $routes['blog_show']->getHostname());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -105,7 +105,7 @@ EOF;
|
|||||||
$string .= sprintf("%s|-coll %s\n", $prefix, $route->getPrefix());
|
$string .= sprintf("%s|-coll %s\n", $prefix, $route->getPrefix());
|
||||||
$string .= $this->collectionToString($route, $prefix.'| ');
|
$string .= $this->collectionToString($route, $prefix.'| ');
|
||||||
} else {
|
} else {
|
||||||
$string .= sprintf("%s|-route %s %s\n", $prefix, $route->getName(), $route->getRoute()->getPattern());
|
$string .= sprintf("%s|-route %s %s\n", $prefix, $route->getName(), $route->getRoute()->getPath());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -368,7 +368,7 @@ class UrlMatcherTest extends \PHPUnit_Framework_TestCase
|
|||||||
$coll = new RouteCollection();
|
$coll = new RouteCollection();
|
||||||
$coll->add('foo', new Route('/foo/{foo}'));
|
$coll->add('foo', new Route('/foo/{foo}'));
|
||||||
$coll->add('bar', new Route('/bar/{foo}', array(), array(), array(), '{locale}.example.net'));
|
$coll->add('bar', new Route('/bar/{foo}', array(), array(), array(), '{locale}.example.net'));
|
||||||
$coll->setHostnamePattern('{locale}.example.com');
|
$coll->setHostname('{locale}.example.com');
|
||||||
|
|
||||||
$matcher = new UrlMatcher($coll, new RequestContext('', 'GET', 'en.example.com'));
|
$matcher = new UrlMatcher($coll, new RequestContext('', 'GET', 'en.example.com'));
|
||||||
$this->assertEquals(array('foo' => 'bar', '_route' => 'foo', 'locale' => 'en'), $matcher->match('/foo/bar'));
|
$this->assertEquals(array('foo' => 'bar', '_route' => 'foo', 'locale' => 'en'), $matcher->match('/foo/bar'));
|
||||||
|
@ -33,7 +33,7 @@ class RouteCollectionTest extends \PHPUnit_Framework_TestCase
|
|||||||
$collection->add('foo', new Route('/foo'));
|
$collection->add('foo', new Route('/foo'));
|
||||||
$collection->add('foo', new Route('/foo1'));
|
$collection->add('foo', new Route('/foo1'));
|
||||||
|
|
||||||
$this->assertEquals('/foo1', $collection->get('foo')->getPattern());
|
$this->assertEquals('/foo1', $collection->get('foo')->getPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testDeepOverriddenRoute()
|
public function testDeepOverriddenRoute()
|
||||||
@ -50,8 +50,8 @@ class RouteCollectionTest extends \PHPUnit_Framework_TestCase
|
|||||||
$collection1->addCollection($collection2);
|
$collection1->addCollection($collection2);
|
||||||
$collection->addCollection($collection1);
|
$collection->addCollection($collection1);
|
||||||
|
|
||||||
$this->assertEquals('/foo2', $collection1->get('foo')->getPattern());
|
$this->assertEquals('/foo2', $collection1->get('foo')->getPath());
|
||||||
$this->assertEquals('/foo2', $collection->get('foo')->getPattern());
|
$this->assertEquals('/foo2', $collection->get('foo')->getPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testIteratorWithOverriddenRoutes()
|
public function testIteratorWithOverriddenRoutes()
|
||||||
@ -63,7 +63,7 @@ class RouteCollectionTest extends \PHPUnit_Framework_TestCase
|
|||||||
$collection1->add('foo', new Route('/foo1'));
|
$collection1->add('foo', new Route('/foo1'));
|
||||||
$collection->addCollection($collection1);
|
$collection->addCollection($collection1);
|
||||||
|
|
||||||
$this->assertEquals('/foo1', $this->getFirstNamedRoute($collection, 'foo')->getPattern());
|
$this->assertEquals('/foo1', $this->getFirstNamedRoute($collection, 'foo')->getPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testCount()
|
public function testCount()
|
||||||
@ -110,7 +110,7 @@ class RouteCollectionTest extends \PHPUnit_Framework_TestCase
|
|||||||
$collection1 = new RouteCollection();
|
$collection1 = new RouteCollection();
|
||||||
$collection1->add('foo', $foo1 = new Route('/foo1'));
|
$collection1->add('foo', $foo1 = new Route('/foo1'));
|
||||||
$collection->addCollection($collection1, '/{foo}', array('foo' => 'foo'), array('foo' => '\d+'), array('foo' => 'bar'));
|
$collection->addCollection($collection1, '/{foo}', array('foo' => 'foo'), array('foo' => '\d+'), array('foo' => 'bar'));
|
||||||
$this->assertEquals('/{foo}/foo1', $collection->get('foo')->getPattern(), '->addCollection() can add a prefix to all merged routes');
|
$this->assertEquals('/{foo}/foo1', $collection->get('foo')->getPath(), '->addCollection() can add a prefix to all merged routes');
|
||||||
$this->assertEquals(array('foo' => 'foo'), $collection->get('foo')->getDefaults(), '->addCollection() can add a prefix to all merged routes');
|
$this->assertEquals(array('foo' => 'foo'), $collection->get('foo')->getDefaults(), '->addCollection() can add a prefix to all merged routes');
|
||||||
$this->assertEquals(array('foo' => '\d+'), $collection->get('foo')->getRequirements(), '->addCollection() can add a prefix to all merged routes');
|
$this->assertEquals(array('foo' => '\d+'), $collection->get('foo')->getRequirements(), '->addCollection() can add a prefix to all merged routes');
|
||||||
$this->assertEquals(
|
$this->assertEquals(
|
||||||
@ -137,8 +137,8 @@ class RouteCollectionTest extends \PHPUnit_Framework_TestCase
|
|||||||
$collection->addPrefix(' / ');
|
$collection->addPrefix(' / ');
|
||||||
$this->assertSame('', $collection->getPrefix(), '->addPrefix() trims the prefix and a single slash has no effect');
|
$this->assertSame('', $collection->getPrefix(), '->addPrefix() trims the prefix and a single slash has no effect');
|
||||||
$collection->addPrefix('/{admin}', array('admin' => 'admin'), array('admin' => '\d+'), array('foo' => 'bar'));
|
$collection->addPrefix('/{admin}', array('admin' => 'admin'), array('admin' => '\d+'), array('foo' => 'bar'));
|
||||||
$this->assertEquals('/{admin}/foo', $collection->get('foo')->getPattern(), '->addPrefix() adds a prefix to all routes');
|
$this->assertEquals('/{admin}/foo', $collection->get('foo')->getPath(), '->addPrefix() adds a prefix to all routes');
|
||||||
$this->assertEquals('/{admin}/bar', $collection->get('bar')->getPattern(), '->addPrefix() adds a prefix to all routes');
|
$this->assertEquals('/{admin}/bar', $collection->get('bar')->getPath(), '->addPrefix() adds a prefix to all routes');
|
||||||
$this->assertEquals(array('admin' => 'admin'), $collection->get('foo')->getDefaults(), '->addPrefix() adds defaults to all routes');
|
$this->assertEquals(array('admin' => 'admin'), $collection->get('foo')->getDefaults(), '->addPrefix() adds defaults to all routes');
|
||||||
$this->assertEquals(array('admin' => 'admin'), $collection->get('bar')->getDefaults(), '->addPrefix() adds defaults to all routes');
|
$this->assertEquals(array('admin' => 'admin'), $collection->get('bar')->getDefaults(), '->addPrefix() adds defaults to all routes');
|
||||||
$this->assertEquals(array('admin' => '\d+'), $collection->get('foo')->getRequirements(), '->addPrefix() adds requirements to all routes');
|
$this->assertEquals(array('admin' => '\d+'), $collection->get('foo')->getRequirements(), '->addPrefix() adds requirements to all routes');
|
||||||
@ -155,8 +155,8 @@ class RouteCollectionTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->assertEquals('/0/{admin}', $collection->getPrefix(), '->addPrefix() ensures a prefix must start with a slash and must not end with a slash');
|
$this->assertEquals('/0/{admin}', $collection->getPrefix(), '->addPrefix() ensures a prefix must start with a slash and must not end with a slash');
|
||||||
$collection->addPrefix('/ /');
|
$collection->addPrefix('/ /');
|
||||||
$this->assertSame('/ /0/{admin}', $collection->getPrefix(), '->addPrefix() can handle spaces if desired');
|
$this->assertSame('/ /0/{admin}', $collection->getPrefix(), '->addPrefix() can handle spaces if desired');
|
||||||
$this->assertSame('/ /0/{admin}/foo', $collection->get('foo')->getPattern(), 'the route pattern is in synch with the collection prefix');
|
$this->assertSame('/ /0/{admin}/foo', $collection->get('foo')->getPath(), 'the route path is in synch with the collection prefix');
|
||||||
$this->assertSame('/ /0/{admin}/bar', $collection->get('bar')->getPattern(), 'the route pattern in a sub-collection is in synch with the collection prefix');
|
$this->assertSame('/ /0/{admin}/bar', $collection->get('bar')->getPath(), 'the route path in a sub-collection is in synch with the collection prefix');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testAddPrefixOverridesDefaultsAndRequirements()
|
public function testAddPrefixOverridesDefaultsAndRequirements()
|
||||||
@ -224,7 +224,7 @@ class RouteCollectionTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->assertNull($collection1->get(0), '->get() does not disclose internal child RouteCollection');
|
$this->assertNull($collection1->get(0), '->get() does not disclose internal child RouteCollection');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSetHostnamePattern()
|
public function testSetHostname()
|
||||||
{
|
{
|
||||||
$collection = new RouteCollection();
|
$collection = new RouteCollection();
|
||||||
$routea = new Route('/a');
|
$routea = new Route('/a');
|
||||||
@ -232,9 +232,9 @@ class RouteCollectionTest extends \PHPUnit_Framework_TestCase
|
|||||||
$collection->add('a', $routea);
|
$collection->add('a', $routea);
|
||||||
$collection->add('b', $routeb);
|
$collection->add('b', $routeb);
|
||||||
|
|
||||||
$collection->setHostnamePattern('{locale}.example.com');
|
$collection->setHostname('{locale}.example.com');
|
||||||
|
|
||||||
$this->assertEquals('{locale}.example.com', $routea->getHostnamePattern());
|
$this->assertEquals('{locale}.example.com', $routea->getHostname());
|
||||||
$this->assertEquals('{locale}.example.com', $routeb->getHostnamePattern());
|
$this->assertEquals('{locale}.example.com', $routeb->getHostname());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,25 +18,33 @@ class RouteTest extends \PHPUnit_Framework_TestCase
|
|||||||
public function testConstructor()
|
public function testConstructor()
|
||||||
{
|
{
|
||||||
$route = new Route('/{foo}', array('foo' => 'bar'), array('foo' => '\d+'), array('foo' => 'bar'), '{locale}.example.com');
|
$route = new Route('/{foo}', array('foo' => 'bar'), array('foo' => '\d+'), array('foo' => 'bar'), '{locale}.example.com');
|
||||||
$this->assertEquals('/{foo}', $route->getPattern(), '__construct() takes a pattern as its first argument');
|
$this->assertEquals('/{foo}', $route->getPath(), '__construct() takes a path as its first argument');
|
||||||
$this->assertEquals(array('foo' => 'bar'), $route->getDefaults(), '__construct() takes defaults as its second argument');
|
$this->assertEquals(array('foo' => 'bar'), $route->getDefaults(), '__construct() takes defaults as its second argument');
|
||||||
$this->assertEquals(array('foo' => '\d+'), $route->getRequirements(), '__construct() takes requirements as its third argument');
|
$this->assertEquals(array('foo' => '\d+'), $route->getRequirements(), '__construct() takes requirements as its third argument');
|
||||||
$this->assertEquals('bar', $route->getOption('foo'), '__construct() takes options as its fourth argument');
|
$this->assertEquals('bar', $route->getOption('foo'), '__construct() takes options as its fourth argument');
|
||||||
$this->assertEquals('{locale}.example.com', $route->getHostnamePattern(), '__construct() takes a hostname pattern as its fifth argument');
|
$this->assertEquals('{locale}.example.com', $route->getHostname(), '__construct() takes a hostname pattern as its fifth argument');
|
||||||
|
|
||||||
|
$route = new Route('/', array(), array(), array(), '', array('Https'), array('POST', 'put'));
|
||||||
|
$this->assertEquals(array('https'), $route->getSchemes(), '__construct() takes schemes as its sixth argument and lowercases it');
|
||||||
|
$this->assertEquals(array('POST', 'PUT'), $route->getMethods(), '__construct() takes methods as its seventh argument and uppercases it');
|
||||||
|
|
||||||
|
$route = new Route('/', array(), array(), array(), '', 'Https', 'Post');
|
||||||
|
$this->assertEquals(array('https'), $route->getSchemes(), '__construct() takes a single scheme as its sixth argument');
|
||||||
|
$this->assertEquals(array('POST'), $route->getMethods(), '__construct() takes a single method as its seventh argument');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPattern()
|
public function testPath()
|
||||||
{
|
{
|
||||||
$route = new Route('/{foo}');
|
$route = new Route('/{foo}');
|
||||||
$route->setPattern('/{bar}');
|
$route->setPath('/{bar}');
|
||||||
$this->assertEquals('/{bar}', $route->getPattern(), '->setPattern() sets the pattern');
|
$this->assertEquals('/{bar}', $route->getPath(), '->setPath() sets the path');
|
||||||
$route->setPattern('');
|
$route->setPath('');
|
||||||
$this->assertEquals('/', $route->getPattern(), '->setPattern() adds a / at the beginning of the pattern if needed');
|
$this->assertEquals('/', $route->getPath(), '->setPath() adds a / at the beginning of the path if needed');
|
||||||
$route->setPattern('bar');
|
$route->setPath('bar');
|
||||||
$this->assertEquals('/bar', $route->getPattern(), '->setPattern() adds a / at the beginning of the pattern if needed');
|
$this->assertEquals('/bar', $route->getPath(), '->setPath() adds a / at the beginning of the path if needed');
|
||||||
$this->assertEquals($route, $route->setPattern(''), '->setPattern() implements a fluent interface');
|
$this->assertEquals($route, $route->setPath(''), '->setPath() implements a fluent interface');
|
||||||
$route->setPattern('//path');
|
$route->setPath('//path');
|
||||||
$this->assertEquals('/path', $route->getPattern(), '->setPattern() does not allow two slashes "//" at the beginning of the pattern as it would be confused with a network path when generating the path from the route');
|
$this->assertEquals('/path', $route->getPath(), '->setPath() does not allow two slahes "//" at the beginning of the path as it would be confused with a network path when generating the path from the route');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testOptions()
|
public function testOptions()
|
||||||
@ -85,7 +93,7 @@ class RouteTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->assertEquals('\d+', $route->getRequirement('foo'), '->getRequirement() returns a requirement');
|
$this->assertEquals('\d+', $route->getRequirement('foo'), '->getRequirement() returns a requirement');
|
||||||
$this->assertNull($route->getRequirement('bar'), '->getRequirement() returns null if a requirement is not defined');
|
$this->assertNull($route->getRequirement('bar'), '->getRequirement() returns null if a requirement is not defined');
|
||||||
$route->setRequirements(array('foo' => '^\d+$'));
|
$route->setRequirements(array('foo' => '^\d+$'));
|
||||||
$this->assertEquals('\d+', $route->getRequirement('foo'), '->getRequirement() removes ^ and $ from the pattern');
|
$this->assertEquals('\d+', $route->getRequirement('foo'), '->getRequirement() removes ^ and $ from the path');
|
||||||
$this->assertEquals($route, $route->setRequirements(array()), '->setRequirements() implements a fluent interface');
|
$this->assertEquals($route, $route->setRequirements(array()), '->setRequirements() implements a fluent interface');
|
||||||
|
|
||||||
$route->setRequirements(array('foo' => '\d+'));
|
$route->setRequirements(array('foo' => '\d+'));
|
||||||
@ -98,7 +106,7 @@ class RouteTest extends \PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
$route = new Route('/{foo}');
|
$route = new Route('/{foo}');
|
||||||
$route->setRequirement('foo', '^\d+$');
|
$route->setRequirement('foo', '^\d+$');
|
||||||
$this->assertEquals('\d+', $route->getRequirement('foo'), '->setRequirement() removes ^ and $ from the pattern');
|
$this->assertEquals('\d+', $route->getRequirement('foo'), '->setRequirement() removes ^ and $ from the path');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -122,11 +130,55 @@ class RouteTest extends \PHPUnit_Framework_TestCase
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testHostnamePattern()
|
public function testHostname()
|
||||||
{
|
{
|
||||||
$route = new Route('/');
|
$route = new Route('/');
|
||||||
$route->setHostnamePattern('{locale}.example.net');
|
$route->setHostname('{locale}.example.net');
|
||||||
$this->assertEquals('{locale}.example.net', $route->getHostnamePattern(), '->setHostnamePattern() sets the hostname pattern');
|
$this->assertEquals('{locale}.example.net', $route->getHostname(), '->setHostname() sets the hostname pattern');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testScheme()
|
||||||
|
{
|
||||||
|
$route = new Route('/');
|
||||||
|
$this->assertEquals(array(), $route->getSchemes(), 'schemes is initialized with array()');
|
||||||
|
$route->setSchemes('hTTp');
|
||||||
|
$this->assertEquals(array('http'), $route->getSchemes(), '->setSchemes() accepts a single scheme string and lowercases it');
|
||||||
|
$route->setSchemes(array('HttpS', 'hTTp'));
|
||||||
|
$this->assertEquals(array('https', 'http'), $route->getSchemes(), '->setSchemes() accepts an array of schemes and lowercases them');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSchemeIsBC()
|
||||||
|
{
|
||||||
|
$route = new Route('/');
|
||||||
|
$route->setRequirement('_scheme', 'http|https');
|
||||||
|
$this->assertEquals('http|https', $route->getRequirement('_scheme'));
|
||||||
|
$this->assertEquals(array('http', 'https'), $route->getSchemes());
|
||||||
|
$route->setSchemes(array('hTTp'));
|
||||||
|
$this->assertEquals('http', $route->getRequirement('_scheme'));
|
||||||
|
$route->setSchemes(array());
|
||||||
|
$this->assertNull($route->getRequirement('_scheme'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMethod()
|
||||||
|
{
|
||||||
|
$route = new Route('/');
|
||||||
|
$this->assertEquals(array(), $route->getMethods(), 'methods is initialized with array()');
|
||||||
|
$route->setMethods('gEt');
|
||||||
|
$this->assertEquals(array('GET'), $route->getMethods(), '->setMethods() accepts a single method string and uppercases it');
|
||||||
|
$route->setMethods(array('gEt', 'PosT'));
|
||||||
|
$this->assertEquals(array('GET', 'POST'), $route->getMethods(), '->setMethods() accepts an array of methods and uppercases them');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMethodIsBC()
|
||||||
|
{
|
||||||
|
$route = new Route('/');
|
||||||
|
$route->setRequirement('_method', 'GET|POST');
|
||||||
|
$this->assertEquals('GET|POST', $route->getRequirement('_method'));
|
||||||
|
$this->assertEquals(array('GET', 'POST'), $route->getMethods());
|
||||||
|
$route->setMethods(array('gEt'));
|
||||||
|
$this->assertEquals('GET', $route->getRequirement('_method'));
|
||||||
|
$route->setMethods(array());
|
||||||
|
$this->assertNull($route->getRequirement('_method'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testCompile()
|
public function testCompile()
|
||||||
|
Reference in New Issue
Block a user