[Routing] added support for expression conditions in routes

This commit is contained in:
Fabien Potencier 2013-09-04 09:25:51 +02:00
parent 86ac8d7547
commit d477f157ce
28 changed files with 255 additions and 28 deletions

View File

@ -28,6 +28,7 @@ class Route
private $host;
private $methods;
private $schemes;
private $condition;
/**
* Constructor.
@ -153,4 +154,14 @@ class Route
{
return $this->methods;
}
public function setCondition($condition)
{
$this->condition = $condition;
}
public function getCondition()
{
return $this->condition;
}
}

View File

@ -116,6 +116,7 @@ abstract class AnnotationClassLoader implements LoaderInterface
'schemes' => array(),
'methods' => array(),
'host' => '',
'condition' => '',
);
$class = new \ReflectionClass($class);
@ -154,6 +155,10 @@ abstract class AnnotationClassLoader implements LoaderInterface
if (null !== $annot->getHost()) {
$globals['host'] = $annot->getHost();
}
if (null !== $annot->getCondition()) {
$globals['condition'] = $annot->getCondition();
}
}
$collection = new RouteCollection();
@ -194,7 +199,12 @@ abstract class AnnotationClassLoader implements LoaderInterface
$host = $globals['host'];
}
$route = new Route($globals['path'].$annot->getPath(), $defaults, $requirements, $options, $host, $schemes, $methods);
$condition = $annot->getCondition();
if (null === $condition) {
$condition = $globals['condition'];
}
$route = new Route($globals['path'].$annot->getPath(), $defaults, $requirements, $options, $host, $schemes, $methods, $condition);
$this->configureRoute($route, $class, $method, $annot);

View File

@ -129,9 +129,9 @@ class XmlFileLoader extends FileLoader
$schemes = preg_split('/[\s,\|]++/', $node->getAttribute('schemes'), -1, PREG_SPLIT_NO_EMPTY);
$methods = preg_split('/[\s,\|]++/', $node->getAttribute('methods'), -1, PREG_SPLIT_NO_EMPTY);
list($defaults, $requirements, $options) = $this->parseConfigs($node, $path);
list($defaults, $requirements, $options, $condition) = $this->parseConfigs($node, $path);
$route = new Route($node->getAttribute('path'), $defaults, $requirements, $options, $node->getAttribute('host'), $schemes, $methods);
$route = new Route($node->getAttribute('path'), $defaults, $requirements, $options, $node->getAttribute('host'), $schemes, $methods, $condition);
$collection->add($id, $route);
}
@ -157,7 +157,7 @@ class XmlFileLoader extends FileLoader
$schemes = $node->hasAttribute('schemes') ? preg_split('/[\s,\|]++/', $node->getAttribute('schemes'), -1, PREG_SPLIT_NO_EMPTY) : null;
$methods = $node->hasAttribute('methods') ? preg_split('/[\s,\|]++/', $node->getAttribute('methods'), -1, PREG_SPLIT_NO_EMPTY) : null;
list($defaults, $requirements, $options) = $this->parseConfigs($node, $path);
list($defaults, $requirements, $options, $condition) = $this->parseConfigs($node, $path);
$this->setCurrentDir(dirname($path));
@ -211,6 +211,7 @@ class XmlFileLoader extends FileLoader
$defaults = array();
$requirements = array();
$options = array();
$condition = null;
foreach ($node->getElementsByTagNameNS(self::NAMESPACE_URI, '*') as $n) {
switch ($n->localName) {
@ -228,11 +229,14 @@ class XmlFileLoader extends FileLoader
case 'option':
$options[$n->getAttribute('key')] = trim($n->textContent);
break;
case 'condition':
$condition = trim($n->textContent);
break;
default:
throw new \InvalidArgumentException(sprintf('Unknown tag "%s" used in file "%s". Expected "default", "requirement" or "option".', $n->localName, $path));
}
}
return array($defaults, $requirements, $options);
return array($defaults, $requirements, $options, $condition);
}
}

View File

@ -28,7 +28,7 @@ use Symfony\Component\Config\Loader\FileLoader;
class YamlFileLoader extends FileLoader
{
private static $availableKeys = array(
'resource', 'type', 'prefix', 'pattern', 'path', 'host', 'schemes', 'methods', 'defaults', 'requirements', 'options',
'resource', 'type', 'prefix', 'pattern', 'path', 'host', 'schemes', 'methods', 'defaults', 'requirements', 'options', 'condition'
);
private $yamlParser;
@ -123,8 +123,9 @@ class YamlFileLoader extends FileLoader
$host = isset($config['host']) ? $config['host'] : '';
$schemes = isset($config['schemes']) ? $config['schemes'] : array();
$methods = isset($config['methods']) ? $config['methods'] : array();
$condition = isset($config['condition']) ? $config['condition'] : null;
$route = new Route($config['path'], $defaults, $requirements, $options, $host, $schemes, $methods);
$route = new Route($config['path'], $defaults, $requirements, $options, $host, $schemes, $methods, $condition);
$collection->add($name, $route);
}

View File

@ -29,6 +29,7 @@
<xsd:element name="default" nillable="true" type="element" />
<xsd:element name="requirement" type="element" />
<xsd:element name="option" type="element" />
<xsd:element name="condition" type="condition" />
</xsd:choice>
</xsd:group>
@ -61,4 +62,9 @@
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
<xsd:simpleType name="condition">
<xsd:restriction base="xsd:string">
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>

View File

@ -50,6 +50,9 @@ class ApacheMatcherDumper extends MatcherDumper
$prevHostRegex = '';
foreach ($this->getRoutes()->all() as $name => $route) {
if ($route->getCondition()) {
throw new \LogicException(sprintf('Unable to dump the routes for Apache as route "%s" has a condition.', $name));
}
$compiledRoute = $route->compile();
$hostRegex = $compiledRoute->getHostRegex();

View File

@ -13,6 +13,7 @@ namespace Symfony\Component\Routing\Matcher\Dumper;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
/**
* PhpMatcherDumper creates a PHP class able to match URLs for a given set of routes.
@ -23,6 +24,8 @@ use Symfony\Component\Routing\RouteCollection;
*/
class PhpMatcherDumper extends MatcherDumper
{
private $expressionLanguage;
/**
* Dumps a set of routes to a PHP class.
*
@ -91,6 +94,8 @@ EOF;
{
\$allow = array();
\$pathinfo = rawurldecode(\$pathinfo);
\$context = \$this->context;
\$request = \$this->request;
$code
@ -237,6 +242,10 @@ EOF;
$hostMatches = true;
}
if ($route->getCondition()) {
$conditions[] = $this->getExpressionLanguage()->compile($route->getCondition(), array('context', 'request'));
}
$conditions = implode(' && ', $conditions);
$code .= <<<EOF
@ -245,9 +254,8 @@ EOF;
EOF;
$gotoname = 'not_'.preg_replace('/[^A-Za-z0-9_]/', '', $name);
if ($methods) {
$gotoname = 'not_'.preg_replace('/[^A-Za-z0-9_]/', '', $name);
if (1 === count($methods)) {
$code .= <<<EOF
if (\$this->context->getMethod() != '$methods[0]') {
@ -375,4 +383,16 @@ EOF;
return $tree;
}
private function getExpressionLanguage()
{
if (null === $this->expressionLanguage) {
if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) {
throw new RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.');
}
$this->expressionLanguage = new ExpressionLanguage();
}
return $this->expressionLanguage;
}
}

View File

@ -50,6 +50,11 @@ abstract class RedirectableUrlMatcher extends UrlMatcher implements Redirectable
*/
protected function handleRouteRequirements($pathinfo, $name, Route $route)
{
// expression condition
if ($route->getCondition() && !$this->getExpressionLanguage()->evaluate($route->getCondition(), array('context' => $this->context, 'request' => $this->request))) {
return array(self::REQUIREMENT_MISMATCH, null);
}
// check HTTP scheme requirement
$scheme = $route->getRequirement('_scheme');
if ($scheme && $this->context->getScheme() !== $scheme) {

View File

@ -94,6 +94,15 @@ class TraceableUrlMatcher extends UrlMatcher
}
}
// check condition
if ($condition = $route->getCondition()) {
if (!$this->getExpressionLanguage()->evaluate($condition, array('context' => $this->context, 'request' => $this->request))) {
$this->addTrace(sprintf('Condition "%s" does not evaluate to "true"', $condition), self::ROUTE_ALMOST_MATCHES, $name, $route);
continue;
}
}
// check HTTP scheme requirement
if ($scheme = $route->getRequirement('_scheme')) {
if ($this->context->getScheme() !== $scheme) {

View File

@ -16,6 +16,8 @@ use Symfony\Component\Routing\Exception\ResourceNotFoundException;
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\Routing\Route;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
/**
* UrlMatcher matches URL based on a set of routes.
@ -24,7 +26,7 @@ use Symfony\Component\Routing\Route;
*
* @api
*/
class UrlMatcher implements UrlMatcherInterface
class UrlMatcher implements UrlMatcherInterface, RequestMatcherInterface
{
const REQUIREMENT_MATCH = 0;
const REQUIREMENT_MISMATCH = 1;
@ -45,6 +47,9 @@ class UrlMatcher implements UrlMatcherInterface
*/
protected $routes;
protected $request;
protected $expressionLanguage;
/**
* Constructor.
*
@ -91,6 +96,20 @@ class UrlMatcher implements UrlMatcherInterface
: new ResourceNotFoundException();
}
/**
* {@inheritdoc}
*/
public function matchRequest(Request $request)
{
$this->request = $request;
$ret = $this->match($request->getPathInfo());
$this->request = null;
return $ret;
}
/**
* Tries to match a URL with a set of routes.
*
@ -180,11 +199,18 @@ class UrlMatcher implements UrlMatcherInterface
*/
protected function handleRouteRequirements($pathinfo, $name, Route $route)
{
// expression condition
if ($route->getCondition() && !$this->getExpressionLanguage()->evaluate($route->getCondition(), array('context' => $this->context, 'request' => $this->request))) {
return array(self::REQUIREMENT_MISMATCH, null);
}
// check HTTP scheme requirement
$scheme = $route->getRequirement('_scheme');
$status = $scheme && $scheme !== $this->context->getScheme() ? self::REQUIREMENT_MISMATCH : self::REQUIREMENT_MATCH;
if ($scheme && $scheme !== $this->context->getScheme()) {
return array(self::REQUIREMENT_MISMATCH, null);
}
return array($status, null);
return array(self::REQUIREMENT_MATCH, null);
}
/**
@ -205,4 +231,16 @@ class UrlMatcher implements UrlMatcherInterface
return $defaults;
}
protected function getExpressionLanguage()
{
if (null === $this->expressionLanguage) {
if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) {
throw new RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.');
}
$this->expressionLanguage = new ExpressionLanguage();
}
return $this->expressionLanguage;
}
}

View File

@ -61,6 +61,8 @@ class Route implements \Serializable
*/
private $compiled;
private $condition;
/**
* Constructor.
*
@ -75,10 +77,11 @@ class Route implements \Serializable
* @param string $host The host 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
* @param string $condition A condition that should evaluate to true for the route to match
*
* @api
*/
public function __construct($path, array $defaults = array(), array $requirements = array(), array $options = array(), $host = '', $schemes = array(), $methods = array())
public function __construct($path, array $defaults = array(), array $requirements = array(), array $options = array(), $host = '', $schemes = array(), $methods = array(), $condition = null)
{
$this->setPath($path);
$this->setDefaults($defaults);
@ -93,6 +96,7 @@ class Route implements \Serializable
if ($methods) {
$this->setMethods($methods);
}
$this->setCondition($condition);
}
public function serialize()
@ -105,6 +109,7 @@ class Route implements \Serializable
'options' => $this->options,
'schemes' => $this->schemes,
'methods' => $this->methods,
'condition' => $this->condition,
));
}
@ -118,6 +123,7 @@ class Route implements \Serializable
$this->options = $data['options'];
$this->schemes = $data['schemes'];
$this->methods = $data['methods'];
$this->condition = $data['condition'];
}
/**
@ -543,6 +549,33 @@ class Route implements \Serializable
return $this;
}
/**
* Returns the condition.
*
* @return string The condition
*/
public function getCondition()
{
return $this->condition;
}
/**
* Sets the condition.
*
* This method implements a fluent interface.
*
* @param string $condition The condition
*
* @return Route The current Route instance
*/
public function setCondition($condition)
{
$this->condition = (string) $condition;
$this->compiled = null;
return $this;
}
/**
* Compiles the route.
*

View File

@ -177,6 +177,20 @@ class RouteCollection implements \IteratorAggregate, \Countable
}
}
/**
* Sets a condition on all routes.
*
* Existing conditions will be overridden.
*
* @param string $condition The condition
*/
public function setCondition($condition)
{
foreach ($this->routes as $route) {
$route->setCondition($condition);
}
}
/**
* Adds defaults to all routes.
*

View File

@ -35,15 +35,16 @@ class RouteTest extends \PHPUnit_Framework_TestCase
public function getValidParameters()
{
return array(
array('value', '/Blog', 'getPattern'),
array('value', '/Blog', 'getPath'),
array('requirements', array('_method' => 'GET'), 'getRequirements'),
array('options', array('compiler_class' => 'RouteCompiler'), 'getOptions'),
array('name', 'blog_index', 'getName'),
array('defaults', array('_controller' => 'MyBlogBundle:Blog:index'), 'getDefaults'),
array('schemes', array('https'), 'getSchemes'),
array('methods', array('GET', 'POST'), 'getMethods'),
array('host', array('{locale}.example.com'), 'getHost')
array('value', '/Blog', 'getPattern'),
array('value', '/Blog', 'getPath'),
array('requirements', array('_method' => 'GET'), 'getRequirements'),
array('options', array('compiler_class' => 'RouteCompiler'), 'getOptions'),
array('name', 'blog_index', 'getName'),
array('defaults', array('_controller' => 'MyBlogBundle:Blog:index'), 'getDefaults'),
array('schemes', array('https'), 'getSchemes'),
array('methods', array('GET', 'POST'), 'getMethods'),
array('host', array('{locale}.example.com'), 'getHost'),
array('condition', array('context.getMethod() == "GET"'), 'getCondition'),
);
}
}

View File

@ -24,6 +24,8 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
{
$allow = array();
$pathinfo = rawurldecode($pathinfo);
$context = $this->context;
$request = $this->request;
// foo
if (0 === strpos($pathinfo, '/foo') && preg_match('#^/foo/(?P<bar>baz|symfony)$#s', $pathinfo, $matches)) {

View File

@ -24,6 +24,8 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
{
$allow = array();
$pathinfo = rawurldecode($pathinfo);
$context = $this->context;
$request = $this->request;
// foo
if (0 === strpos($pathinfo, '/foo') && preg_match('#^/foo/(?P<bar>baz|symfony)$#s', $pathinfo, $matches)) {

View File

@ -24,6 +24,8 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
{
$allow = array();
$pathinfo = rawurldecode($pathinfo);
$context = $this->context;
$request = $this->request;
if (0 === strpos($pathinfo, '/rootprefix')) {
// static
@ -38,6 +40,11 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
}
// with-condition
if ($pathinfo === '/with-condition' && ($context->getMethod() == "GET")) {
return array('_route' => 'with-condition');
}
throw 0 < count($allow) ? new MethodNotAllowedException(array_unique($allow)) : new ResourceNotFoundException();
}
}

View File

@ -10,14 +10,18 @@ $collection->add('blog_show', new Route(
array('compiler_class' => 'RouteCompiler'),
'{locale}.example.com',
array('https'),
array('GET','POST','put','OpTiOnS')
array('GET','POST','put','OpTiOnS'),
'context.getMethod() == "GET"'
));
$collection->add('blog_show_legacy', new Route(
'/blog/{slug}',
array('_controller' => 'MyBlogBundle:Blog:show'),
array('_method' => 'GET|POST|put|OpTiOnS', '_scheme' => 'https', 'locale' => '\w+',),
array('compiler_class' => 'RouteCompiler'),
'{locale}.example.com'
'{locale}.example.com',
array(),
array(),
'context.getMethod() == "GET"'
));
return $collection;

View File

@ -8,6 +8,7 @@
<default key="_controller">MyBundle:Blog:show</default>
<requirement key="locale">\w+</requirement>
<option key="compiler_class">RouteCompiler</option>
<condition>context.getMethod() == "GET"</condition>
</route>
<route id="blog_show_legacy" pattern="/blog/{slug}" host="{locale}.example.com">
@ -17,5 +18,6 @@
<requirement key="_scheme">hTTps</requirement>
<requirement key="locale">\w+</requirement>
<option key="compiler_class">RouteCompiler</option>
<condition>context.getMethod() == "GET"</condition>
</route>
</routes>

View File

@ -5,6 +5,7 @@ blog_show:
requirements: { 'locale': '\w+' }
methods: ['GET','POST','put','OpTiOnS']
schemes: ['https']
condition: 'context.getMethod() == "GET"'
options:
compiler_class: RouteCompiler
@ -13,5 +14,6 @@ blog_show_legacy:
defaults: { _controller: "MyBundle:Blog:show" }
host: "{locale}.example.com"
requirements: { '_method': 'GET|POST|put|OpTiOnS', _scheme: https, 'locale': '\w+' }
condition: 'context.getMethod() == "GET"'
options:
compiler_class: RouteCompiler

View File

@ -84,7 +84,12 @@ class AnnotationClassLoaderTest extends AbstractAnnotationLoaderTest
array(
'Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\BarClass',
array('name' => 'route1', 'defaults' => array('arg2' => 'foobar')),
array('arg2' => false, 'arg3' => 'defaultValue3')
array('arg2' => 'defaultValue2', 'arg3' =>'defaultValue3')
),
array(
'Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\BarClass',
array('name' => 'route1', 'defaults' => array('arg2' => 'foo'), 'condition' => 'context.getMethod() == "GET"'),
array('arg2' => 'defaultValue2', 'arg3' =>'defaultValue3')
),
);
}
@ -102,6 +107,7 @@ class AnnotationClassLoaderTest extends AbstractAnnotationLoaderTest
'defaults' => array(),
'schemes' => array(),
'methods' => array(),
'condition' => null,
), $routeDatas);
$this->reader
@ -116,6 +122,7 @@ class AnnotationClassLoaderTest extends AbstractAnnotationLoaderTest
$this->assertSame($routeDatas['requirements'],$route->getRequirements(), '->load preserves requirements annotation');
$this->assertCount(0, array_intersect($route->getOptions(), $routeDatas['options']), '->load preserves options annotation');
$this->assertSame(array_replace($methodArgs, $routeDatas['defaults']), $route->getDefaults(), '->load preserves defaults annotation');
$this->assertEquals($routeDatas['condition'], $route->getCondition(), '->load preserves condition annotation');
}
private function getAnnotatedRoute($datas)

View File

@ -45,6 +45,7 @@ class XmlFileLoaderTest extends \PHPUnit_Framework_TestCase
$this->assertSame('RouteCompiler', $route->getOption('compiler_class'));
$this->assertEquals(array('GET', 'POST', 'PUT', 'OPTIONS'), $route->getMethods());
$this->assertEquals(array('https'), $route->getSchemes());
$this->assertEquals('context.getMethod() == "GET"', $route->getCondition());
}
}

View File

@ -79,6 +79,7 @@ class YamlFileLoaderTest extends \PHPUnit_Framework_TestCase
$this->assertSame('RouteCompiler', $route->getOption('compiler_class'));
$this->assertEquals(array('GET', 'POST', 'PUT', 'OPTIONS'), $route->getMethods());
$this->assertEquals(array('https'), $route->getSchemes());
$this->assertEquals('context.getMethod() == "GET"', $route->getCondition());
}
}

View File

@ -251,6 +251,9 @@ class PhpMatcherDumperTest extends \PHPUnit_Framework_TestCase
$rootprefixCollection->add('static', new Route('/test'));
$rootprefixCollection->add('dynamic', new Route('/{var}'));
$rootprefixCollection->addPrefix('rootprefix');
$route = new Route('/with-condition');
$route->setCondition('context.getMethod() == "GET"');
$rootprefixCollection->add('with-condition', $route);
return array(
array($collection, 'url_matcher1.php', array()),

View File

@ -26,13 +26,14 @@ class TraceableUrlMatcherTest extends \PHPUnit_Framework_TestCase
$coll->add('bar1', new Route('/bar/{name}', array(), array('id' => '\w+', '_method' => 'POST')));
$coll->add('bar2', new Route('/foo', array(), array(), array(), 'baz'));
$coll->add('bar3', new Route('/foo1', array(), array(), array(), 'baz'));
$coll->add('bar4', new Route('/foo2', array(), array(), array(), 'baz', array(), array(), 'context.getMethod() == "GET"'));
$context = new RequestContext();
$context->setHost('baz');
$matcher = new TraceableUrlMatcher($coll, $context);
$traces = $matcher->getTraces('/babar');
$this->assertEquals(array(0, 0, 0, 0, 0), $this->getLevels($traces));
$this->assertEquals(array(0, 0, 0, 0, 0, 0), $this->getLevels($traces));
$traces = $matcher->getTraces('/foo');
$this->assertEquals(array(1, 0, 0, 2), $this->getLevels($traces));
@ -41,7 +42,7 @@ class TraceableUrlMatcherTest extends \PHPUnit_Framework_TestCase
$this->assertEquals(array(0, 2), $this->getLevels($traces));
$traces = $matcher->getTraces('/bar/dd');
$this->assertEquals(array(0, 1, 1, 0, 0), $this->getLevels($traces));
$this->assertEquals(array(0, 1, 1, 0, 0, 0), $this->getLevels($traces));
$traces = $matcher->getTraces('/foo1');
$this->assertEquals(array(0, 0, 0, 0, 2), $this->getLevels($traces));
@ -52,6 +53,9 @@ class TraceableUrlMatcherTest extends \PHPUnit_Framework_TestCase
$traces = $matcher->getTraces('/bar/dd');
$this->assertEquals(array(0, 1, 2), $this->getLevels($traces));
$traces = $matcher->getTraces('/foo2');
$this->assertEquals(array(0, 0, 0, 0, 0, 1), $this->getLevels($traces));
}
public function getLevels($traces)

View File

@ -321,6 +321,19 @@ class UrlMatcherTest extends \PHPUnit_Framework_TestCase
$matcher->match('/foo');
}
/**
* @expectedException \Symfony\Component\Routing\Exception\ResourceNotFoundException
*/
public function testCondition()
{
$coll = new RouteCollection();
$route = new Route('/foo');
$route->setCondition('context.getMethod() == "POST"');
$coll->add('foo', $route);
$matcher = new UrlMatcher($coll, new RequestContext());
$matcher->match('/foo');
}
public function testDecodeOnce()
{
$coll = new RouteCollection();

View File

@ -244,4 +244,18 @@ class RouteCollectionTest extends \PHPUnit_Framework_TestCase
$this->assertEquals('{locale}.example.com', $routea->getHost());
$this->assertEquals('{locale}.example.com', $routeb->getHost());
}
public function testSetCondition()
{
$collection = new RouteCollection();
$routea = new Route('/a');
$routeb = new Route('/b', array(), array(), array(), '{locale}.example.net', array(), array(), 'context.getMethod() == "GET"');
$collection->add('a', $routea);
$collection->add('b', $routeb);
$collection->setCondition('context.getMethod() == "POST"');
$this->assertEquals('context.getMethod() == "POST"', $routea->getCondition());
$this->assertEquals('context.getMethod() == "POST"', $routeb->getCondition());
}
}

View File

@ -24,9 +24,10 @@ class RouteTest extends \PHPUnit_Framework_TestCase
$this->assertEquals('bar', $route->getOption('foo'), '__construct() takes options as its fourth argument');
$this->assertEquals('{locale}.example.com', $route->getHost(), '__construct() takes a host pattern as its fifth argument');
$route = new Route('/', array(), array(), array(), '', array('Https'), array('POST', 'put'));
$route = new Route('/', array(), array(), array(), '', array('Https'), array('POST', 'put'), 'context.getMethod() == "GET"');
$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');
$this->assertEquals('context.getMethod() == "GET"', $route->getCondition(), '__construct() takes a condition as its eight argument');
$route = new Route('/', array(), array(), array(), '', 'Https', 'Post');
$this->assertEquals(array('https'), $route->getSchemes(), '__construct() takes a single scheme as its sixth argument');
@ -181,6 +182,14 @@ class RouteTest extends \PHPUnit_Framework_TestCase
$this->assertNull($route->getRequirement('_method'));
}
public function testCondition()
{
$route = new Route('/');
$this->assertEquals(null, $route->getCondition());
$route->setCondition('context.getMethod() == "GET"');
$this->assertEquals('context.getMethod() == "GET"', $route->getCondition());
}
public function testCompile()
{
$route = new Route('/{foo}');

View File

@ -21,6 +21,7 @@
"require-dev": {
"symfony/config": "~2.2",
"symfony/yaml": "~2.0",
"symfony/expression-language": "~2.4",
"doctrine/common": "~2.2",
"psr/log": "~1.0"
},