[Routing] Add strict_parameters option to disable exceptions when a route generation fails due to an invalid parameter
This commit is contained in:
parent
3bb7dc0bfa
commit
bbef65e657
@ -155,6 +155,7 @@ class Configuration implements ConfigurationInterface
|
||||
->scalarNode('type')->end()
|
||||
->scalarNode('http_port')->defaultValue(80)->end()
|
||||
->scalarNode('https_port')->defaultValue(443)->end()
|
||||
->scalarNode('strict_parameters')->defaultTrue()->end()
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
|
@ -255,11 +255,12 @@ class FrameworkExtension extends Extension
|
||||
$container->setParameter('router.resource', $config['resource']);
|
||||
$router = $container->findDefinition('router.default');
|
||||
|
||||
$argument = $router->getArgument(2);
|
||||
$argument['strict_parameters'] = $config['strict_parameters'];
|
||||
if (isset($config['type'])) {
|
||||
$argument = $router->getArgument(2);
|
||||
$argument['resource_type'] = $config['type'];
|
||||
$router->replaceArgument(2, $argument);
|
||||
}
|
||||
$router->replaceArgument(2, $argument);
|
||||
|
||||
$container->setParameter('request_listener.http_port', $config['http_port']);
|
||||
$container->setParameter('request_listener.https_port', $config['https_port']);
|
||||
|
@ -50,6 +50,7 @@
|
||||
</service>
|
||||
|
||||
<service id="router.default" class="%router.class%" public="false">
|
||||
<tag name="monolog.logger" channel="router" />
|
||||
<argument type="service" id="service_container" />
|
||||
<argument>%router.resource%</argument>
|
||||
<argument type="collection">
|
||||
@ -65,6 +66,7 @@
|
||||
<argument key="matcher_cache_class">%router.options.matcher.cache_class%</argument>
|
||||
</argument>
|
||||
<argument type="service" id="router.request_context" on-invalid="ignore" />
|
||||
<argument type="service" id="logger" on-invalid="ignore" />
|
||||
</service>
|
||||
|
||||
<service id="router" alias="router.default" />
|
||||
|
@ -49,6 +49,7 @@ class PhpGeneratorDumper extends GeneratorDumper
|
||||
|
||||
use Symfony\Component\Routing\RequestContext;
|
||||
use Symfony\Component\Routing\Exception\RouteNotFoundException;
|
||||
use Symfony\Component\HttpKernel\Log\LoggerInterface;
|
||||
|
||||
/**
|
||||
* {$options['class']}
|
||||
@ -63,9 +64,10 @@ class {$options['class']} extends {$options['base_class']}
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct(RequestContext \$context)
|
||||
public function __construct(RequestContext \$context, LoggerInterface \$logger = null)
|
||||
{
|
||||
\$this->context = \$context;
|
||||
\$this->logger = \$logger;
|
||||
}
|
||||
|
||||
{$this->generateGenerateMethod()}
|
||||
|
@ -17,6 +17,7 @@ use Symfony\Component\Routing\RequestContext;
|
||||
use Symfony\Component\Routing\Exception\InvalidParameterException;
|
||||
use Symfony\Component\Routing\Exception\RouteNotFoundException;
|
||||
use Symfony\Component\Routing\Exception\MissingMandatoryParametersException;
|
||||
use Symfony\Component\HttpKernel\Log\LoggerInterface;
|
||||
|
||||
/**
|
||||
* UrlGenerator generates a URL based on a set of routes.
|
||||
@ -28,6 +29,8 @@ use Symfony\Component\Routing\Exception\MissingMandatoryParametersException;
|
||||
class UrlGenerator implements UrlGeneratorInterface
|
||||
{
|
||||
protected $context;
|
||||
protected $strictParameters = true;
|
||||
protected $logger;
|
||||
protected $decodedChars = array(
|
||||
// %2F is not valid in a URL, so we don't encode it (which is fine as the requirements explicitly allowed it)
|
||||
'%2F' => '/',
|
||||
@ -40,13 +43,15 @@ class UrlGenerator implements UrlGeneratorInterface
|
||||
*
|
||||
* @param RouteCollection $routes A RouteCollection instance
|
||||
* @param RequestContext $context The context
|
||||
* @param LoggerInterface $logger A logger instance
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function __construct(RouteCollection $routes, RequestContext $context)
|
||||
public function __construct(RouteCollection $routes, RequestContext $context, LoggerInterface $logger = null)
|
||||
{
|
||||
$this->routes = $routes;
|
||||
$this->context = $context;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -71,6 +76,28 @@ class UrlGenerator implements UrlGeneratorInterface
|
||||
return $this->context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables the exception on incorrect parameters.
|
||||
*
|
||||
* @param Boolean $enabled
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function setStrictParameters($enabled)
|
||||
{
|
||||
$this->strictParameters = $enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the strict check of incorrect parameters.
|
||||
*
|
||||
* @return Boolean
|
||||
*/
|
||||
public function getStrictParameters()
|
||||
{
|
||||
return $this->strictParameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
@ -113,7 +140,16 @@ class UrlGenerator implements UrlGeneratorInterface
|
||||
if (!$isEmpty = in_array($tparams[$token[3]], array(null, '', false), true)) {
|
||||
// check requirement
|
||||
if ($tparams[$token[3]] && !preg_match('#^'.$token[2].'$#', $tparams[$token[3]])) {
|
||||
throw new InvalidParameterException(sprintf('Parameter "%s" for route "%s" must match "%s" ("%s" given).', $token[3], $name, $token[2], $tparams[$token[3]]));
|
||||
$message = sprintf('Parameter "%s" for route "%s" must match "%s" ("%s" given).', $token[3], $name, $token[2], $tparams[$token[3]]);
|
||||
if ($this->strictParameters) {
|
||||
throw new InvalidParameterException($message);
|
||||
}
|
||||
|
||||
if ($this->logger) {
|
||||
$this->logger->err($message);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,7 @@ namespace Symfony\Component\Routing;
|
||||
|
||||
use Symfony\Component\Config\Loader\LoaderInterface;
|
||||
use Symfony\Component\Config\ConfigCache;
|
||||
use Symfony\Component\HttpKernel\Log\LoggerInterface;
|
||||
|
||||
/**
|
||||
* The Router class is an example of the integration of all pieces of the
|
||||
@ -29,6 +30,7 @@ class Router implements RouterInterface
|
||||
protected $collection;
|
||||
protected $resource;
|
||||
protected $options;
|
||||
protected $logger;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
@ -37,11 +39,13 @@ class Router implements RouterInterface
|
||||
* @param mixed $resource The main resource to load
|
||||
* @param array $options An array of options
|
||||
* @param RequestContext $context The context
|
||||
* @param LoggerInterface $logger A logger instance
|
||||
*/
|
||||
public function __construct(LoaderInterface $loader, $resource, array $options = array(), RequestContext $context = null)
|
||||
public function __construct(LoaderInterface $loader, $resource, array $options = array(), RequestContext $context = null, LoggerInterface $logger = null)
|
||||
{
|
||||
$this->loader = $loader;
|
||||
$this->resource = $resource;
|
||||
$this->logger = $logger;
|
||||
$this->context = null === $context ? new RequestContext() : $context;
|
||||
$this->setOptions($options);
|
||||
}
|
||||
@ -73,6 +77,7 @@ class Router implements RouterInterface
|
||||
'matcher_dumper_class' => 'Symfony\\Component\\Routing\\Matcher\\Dumper\\PhpMatcherDumper',
|
||||
'matcher_cache_class' => 'ProjectUrlMatcher',
|
||||
'resource_type' => null,
|
||||
'strict_parameters' => true,
|
||||
);
|
||||
|
||||
// check option names and live merge, if errors are encountered Exception will be thrown
|
||||
@ -225,24 +230,30 @@ class Router implements RouterInterface
|
||||
}
|
||||
|
||||
if (null === $this->options['cache_dir'] || null === $this->options['generator_cache_class']) {
|
||||
return $this->generator = new $this->options['generator_class']($this->getRouteCollection(), $this->context);
|
||||
$this->generator = new $this->options['generator_class']($this->getRouteCollection(), $this->context, $this->logger);
|
||||
} else {
|
||||
$class = $this->options['generator_cache_class'];
|
||||
$cache = new ConfigCache($this->options['cache_dir'].'/'.$class.'.php', $this->options['debug']);
|
||||
if (!$cache->isFresh($class)) {
|
||||
$dumper = new $this->options['generator_dumper_class']($this->getRouteCollection());
|
||||
|
||||
$options = array(
|
||||
'class' => $class,
|
||||
'base_class' => $this->options['generator_base_class'],
|
||||
);
|
||||
|
||||
$cache->write($dumper->dump($options), $this->getRouteCollection()->getResources());
|
||||
}
|
||||
|
||||
require_once $cache;
|
||||
|
||||
$this->generator = new $class($this->context, $this->logger);
|
||||
}
|
||||
|
||||
$class = $this->options['generator_cache_class'];
|
||||
$cache = new ConfigCache($this->options['cache_dir'].'/'.$class.'.php', $this->options['debug']);
|
||||
if (!$cache->isFresh($class)) {
|
||||
$dumper = new $this->options['generator_dumper_class']($this->getRouteCollection());
|
||||
|
||||
$options = array(
|
||||
'class' => $class,
|
||||
'base_class' => $this->options['generator_base_class'],
|
||||
);
|
||||
|
||||
$cache->write($dumper->dump($options), $this->getRouteCollection()->getResources());
|
||||
if (false === $this->options['strict_parameters']) {
|
||||
$this->generator->setStrictParameters(false);
|
||||
}
|
||||
|
||||
require_once $cache;
|
||||
|
||||
return $this->generator = new $class($this->context);
|
||||
return $this->generator;
|
||||
}
|
||||
}
|
||||
|
@ -165,6 +165,25 @@ class UrlGeneratorTest extends \PHPUnit_Framework_TestCase
|
||||
$this->getGenerator($routes)->generate('test', array('foo' => 'bar'), true);
|
||||
}
|
||||
|
||||
public function testGenerateForRouteWithInvalidOptionalParameterNonStrict()
|
||||
{
|
||||
$routes = $this->getRoutes('test', new Route('/testing/{foo}', array('foo' => '1'), array('foo' => 'd+')));
|
||||
$generator = $this->getGenerator($routes);
|
||||
$generator->setStrictParameters(false);
|
||||
$this->assertNull($generator->generate('test', array('foo' => 'bar'), true));
|
||||
}
|
||||
|
||||
public function testGenerateForRouteWithInvalidOptionalParameterNonStrictWithLogger()
|
||||
{
|
||||
$routes = $this->getRoutes('test', new Route('/testing/{foo}', array('foo' => '1'), array('foo' => 'd+')));
|
||||
$logger = $this->getMock('Symfony\Component\HttpKernel\Log\LoggerInterface');
|
||||
$logger->expects($this->once())
|
||||
->method('err');
|
||||
$generator = $this->getGenerator($routes, array(), $logger);
|
||||
$generator->setStrictParameters(false);
|
||||
$this->assertNull($generator->generate('test', array('foo' => 'bar'), true));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Symfony\Component\Routing\Exception\InvalidParameterException
|
||||
*/
|
||||
@ -206,14 +225,14 @@ class UrlGeneratorTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals('/app.php/foo', $this->getGenerator($routes)->generate('test', array('default' => 'foo')));
|
||||
}
|
||||
|
||||
protected function getGenerator(RouteCollection $routes, array $parameters = array())
|
||||
protected function getGenerator(RouteCollection $routes, array $parameters = array(), $logger = null)
|
||||
{
|
||||
$context = new RequestContext('/app.php');
|
||||
foreach ($parameters as $key => $value) {
|
||||
$method = 'set'.$key;
|
||||
$context->$method($value);
|
||||
}
|
||||
$generator = new UrlGenerator($routes, $context);
|
||||
$generator = new UrlGenerator($routes, $context, $logger);
|
||||
|
||||
return $generator;
|
||||
}
|
||||
|
@ -21,6 +21,7 @@
|
||||
"require-dev": {
|
||||
"symfony/config": "2.1.*",
|
||||
"symfony/yaml": "2.1.*",
|
||||
"symfony/http-kernel": "2.1.*",
|
||||
"doctrine/common": ">=2.2,<2.4-dev"
|
||||
},
|
||||
"suggest": {
|
||||
|
Reference in New Issue
Block a user