Permalink
Browse files

[Routing] Add strict_parameters option to disable exceptions when a r…

…oute generation fails due to an invalid parameter
  • Loading branch information...
1 parent 3bb7dc0 commit bbef65e657212d3fc1daa2f812e66aa2bbbcff64 @Seldaek committed Jun 9, 2012
@@ -155,6 +155,7 @@ private function addRouterSection(ArrayNodeDefinition $rootNode)
->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 @@ private function registerRouterConfiguration(array $config, ContainerBuilder $co
$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 @@ public function dump(array $options = array())
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\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 @@
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;
}
/**
@@ -72,6 +77,28 @@ public function getContext()
}
/**
+ * 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}
*
* @api
@@ -113,7 +140,16 @@ protected function doGenerate($variables, $defaults, $requirements, $tokens, $pa
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 @@
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 @@ public function setOptions(array $options)
'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 @@ public function getGenerator()
}
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());
+ }
- $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());
+ require_once $cache;
- $options = array(
- 'class' => $class,
- 'base_class' => $this->options['generator_base_class'],
- );
-
- $cache->write($dumper->dump($options), $this->getRouteCollection()->getResources());
+ $this->generator = new $class($this->context, $this->logger);
}
- require_once $cache;
+ if (false === $this->options['strict_parameters']) {
+ $this->generator->setStrictParameters(false);
+ }
- return $this->generator = new $class($this->context);
+ return $this->generator;
}
}
@@ -165,6 +165,25 @@ public function testGenerateForRouteWithInvalidOptionalParameter()
$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 @@ public function testWithAnIntegerAsADefaultValue()
$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": {

0 comments on commit bbef65e

Please sign in to comment.