[Routing] added support for expression conditions in routes
This commit is contained in:
parent
86ac8d7547
commit
d477f157ce
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -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)) {
|
||||
|
@ -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)) {
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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()),
|
||||
|
@ -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)
|
||||
|
@ -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();
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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}');
|
||||
|
@ -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"
|
||||
},
|
||||
|
Reference in New Issue
Block a user