feature #30249 [Routing] deprecate some router options (Tobion)

This PR was merged into the 4.3-dev branch.

Discussion
----------

[Routing] deprecate some router options

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | no <!-- don't forget to update src/**/CHANGELOG.md files -->
| BC breaks?    | no     <!-- see https://symfony.com/bc -->
| Deprecations? | yes <!-- don't forget to update UPGRADE-*.md and src/**/CHANGELOG.md files -->
| Tests pass?   | yes    <!-- please add some, will be required by reviewers -->
| Fixed tickets | https://github.com/symfony/symfony/pull/28865#issuecomment-463480970
| License       | MIT
| Doc PR        | symfony/symfony-docs#... <!-- required for new features -->

<!--
Write a short README entry for your feature/bugfix here (replace this comment block.)
This will help people understand your PR and can be used as a start of the Doc PR.
Additionally:
 - Bug fixes must be submitted against the lowest branch where they apply
   (lowest branches are regularly merged to upper ones so they get the fixes too).
 - Features and deprecations must be submitted against the master branch.
-->

Commits
-------

bf4cd6164d [Routing] deprecate some router options
This commit is contained in:
Fabien Potencier 2019-02-21 09:24:00 +01:00
commit 2e6d0698f5
5 changed files with 34 additions and 44 deletions

View File

@ -20,6 +20,7 @@ use Symfony\Bridge\Monolog\Processor\DebugProcessor;
use Symfony\Bridge\Twig\Extension\CsrfExtension; use Symfony\Bridge\Twig\Extension\CsrfExtension;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Bundle\FrameworkBundle\Routing\AnnotatedRouteControllerLoader; use Symfony\Bundle\FrameworkBundle\Routing\AnnotatedRouteControllerLoader;
use Symfony\Bundle\FrameworkBundle\Routing\RedirectableUrlMatcher;
use Symfony\Bundle\FullStack; use Symfony\Bundle\FullStack;
use Symfony\Component\BrowserKit\Client; use Symfony\Component\BrowserKit\Client;
use Symfony\Component\Cache\Adapter\AbstractAdapter; use Symfony\Component\Cache\Adapter\AbstractAdapter;
@ -83,6 +84,7 @@ use Symfony\Component\PropertyInfo\PropertyInitializableExtractorInterface;
use Symfony\Component\PropertyInfo\PropertyListExtractorInterface; use Symfony\Component\PropertyInfo\PropertyListExtractorInterface;
use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface; use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
use Symfony\Component\Routing\Generator\Dumper\PhpGeneratorDumper; use Symfony\Component\Routing\Generator\Dumper\PhpGeneratorDumper;
use Symfony\Component\Routing\Generator\UrlGenerator;
use Symfony\Component\Routing\Loader\AnnotationDirectoryLoader; use Symfony\Component\Routing\Loader\AnnotationDirectoryLoader;
use Symfony\Component\Routing\Loader\AnnotationFileLoader; use Symfony\Component\Routing\Loader\AnnotationFileLoader;
use Symfony\Component\Routing\Matcher\CompiledUrlMatcher; use Symfony\Component\Routing\Matcher\CompiledUrlMatcher;
@ -750,7 +752,7 @@ class FrameworkExtension extends Extension
} }
$container->setParameter('router.resource', $config['resource']); $container->setParameter('router.resource', $config['resource']);
$container->setParameter('router.cache_class_prefix', $container->getParameter('kernel.container_class')); $container->setParameter('router.cache_class_prefix', $container->getParameter('kernel.container_class')); // deprecated
$router = $container->findDefinition('router.default'); $router = $container->findDefinition('router.default');
$argument = $router->getArgument(2); $argument = $router->getArgument(2);
$argument['strict_requirements'] = $config['strict_requirements']; $argument['strict_requirements'] = $config['strict_requirements'];
@ -758,9 +760,9 @@ class FrameworkExtension extends Extension
$argument['resource_type'] = $config['type']; $argument['resource_type'] = $config['type'];
} }
if (!class_exists(CompiledUrlMatcher::class)) { if (!class_exists(CompiledUrlMatcher::class)) {
$argument['matcher_class'] = $argument['matcher_base_class']; $argument['matcher_class'] = $argument['matcher_base_class'] = $argument['matcher_base_class'] ?? RedirectableUrlMatcher::class;
$argument['matcher_dumper_class'] = PhpMatcherDumper::class; $argument['matcher_dumper_class'] = PhpMatcherDumper::class;
$argument['generator_class'] = $argument['generator_base_class']; $argument['generator_class'] = $argument['generator_base_class'] = $argument['generator_base_class'] ?? UrlGenerator::class;
$argument['generator_dumper_class'] = PhpGeneratorDumper::class; $argument['generator_dumper_class'] = PhpGeneratorDumper::class;
} }
$router->replaceArgument(2, $argument); $router->replaceArgument(2, $argument);

View File

@ -60,13 +60,9 @@
<argument key="cache_dir">%kernel.cache_dir%</argument> <argument key="cache_dir">%kernel.cache_dir%</argument>
<argument key="debug">%kernel.debug%</argument> <argument key="debug">%kernel.debug%</argument>
<argument key="generator_class">Symfony\Component\Routing\Generator\CompiledUrlGenerator</argument> <argument key="generator_class">Symfony\Component\Routing\Generator\CompiledUrlGenerator</argument>
<argument key="generator_base_class">Symfony\Component\Routing\Generator\UrlGenerator</argument>
<argument key="generator_dumper_class">Symfony\Component\Routing\Generator\Dumper\CompiledUrlGeneratorDumper</argument> <argument key="generator_dumper_class">Symfony\Component\Routing\Generator\Dumper\CompiledUrlGeneratorDumper</argument>
<argument key="generator_cache_class">%router.cache_class_prefix%UrlGenerator</argument>
<argument key="matcher_class">Symfony\Bundle\FrameworkBundle\Routing\RedirectableCompiledUrlMatcher</argument> <argument key="matcher_class">Symfony\Bundle\FrameworkBundle\Routing\RedirectableCompiledUrlMatcher</argument>
<argument key="matcher_base_class">Symfony\Bundle\FrameworkBundle\Routing\RedirectableUrlMatcher</argument>
<argument key="matcher_dumper_class">Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherDumper</argument> <argument key="matcher_dumper_class">Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherDumper</argument>
<argument key="matcher_cache_class">%router.cache_class_prefix%UrlMatcher</argument>
</argument> </argument>
<argument type="service" id="router.request_context" on-invalid="ignore" /> <argument type="service" id="router.request_context" on-invalid="ignore" />
<argument type="service" id="parameter_bag" on-invalid="ignore" /> <argument type="service" id="parameter_bag" on-invalid="ignore" />

View File

@ -7,6 +7,7 @@ CHANGELOG
* added `CompiledUrlMatcher` and `CompiledUrlMatcherDumper` * added `CompiledUrlMatcher` and `CompiledUrlMatcherDumper`
* added `CompiledUrlGenerator` and `CompiledUrlGeneratorDumper` * added `CompiledUrlGenerator` and `CompiledUrlGeneratorDumper`
* deprecated `PhpGeneratorDumper` and `PhpMatcherDumper` * deprecated `PhpGeneratorDumper` and `PhpMatcherDumper`
* deprecated `generator_base_class`, `generator_cache_class`, `matcher_base_class` and `matcher_cache_class` router options
4.2.0 4.2.0
----- -----

View File

@ -12,6 +12,7 @@
namespace Symfony\Component\Routing; namespace Symfony\Component\Routing;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Routing\RedirectableUrlMatcher;
use Symfony\Component\Config\ConfigCacheFactory; use Symfony\Component\Config\ConfigCacheFactory;
use Symfony\Component\Config\ConfigCacheFactoryInterface; use Symfony\Component\Config\ConfigCacheFactoryInterface;
use Symfony\Component\Config\ConfigCacheInterface; use Symfony\Component\Config\ConfigCacheInterface;
@ -113,13 +114,9 @@ class Router implements RouterInterface, RequestMatcherInterface
* * cache_dir: The cache directory (or null to disable caching) * * cache_dir: The cache directory (or null to disable caching)
* * debug: Whether to enable debugging or not (false by default) * * debug: Whether to enable debugging or not (false by default)
* * generator_class: The name of a UrlGeneratorInterface implementation * * generator_class: The name of a UrlGeneratorInterface implementation
* * generator_base_class: The base class for the dumped generator class
* * generator_cache_class: The class name for the dumped generator class
* * generator_dumper_class: The name of a GeneratorDumperInterface implementation * * generator_dumper_class: The name of a GeneratorDumperInterface implementation
* * matcher_class: The name of a UrlMatcherInterface implementation * * matcher_class: The name of a UrlMatcherInterface implementation
* * matcher_base_class: The base class for the dumped matcher class * * matcher_dumper_class: The name of a MatcherDumperInterface implementation
* * matcher_dumper_class: The class name for the dumped matcher class
* * matcher_cache_class: The name of a MatcherDumperInterface implementation
* * resource_type: Type hint for the main resource (optional) * * resource_type: Type hint for the main resource (optional)
* * strict_requirements: Configure strict requirement checking for generators * * strict_requirements: Configure strict requirement checking for generators
* implementing ConfigurableRequirementsInterface (default is true) * implementing ConfigurableRequirementsInterface (default is true)
@ -134,13 +131,13 @@ class Router implements RouterInterface, RequestMatcherInterface
'cache_dir' => null, 'cache_dir' => null,
'debug' => false, 'debug' => false,
'generator_class' => CompiledUrlGenerator::class, 'generator_class' => CompiledUrlGenerator::class,
'generator_base_class' => UrlGenerator::class, 'generator_base_class' => UrlGenerator::class, // deprecated
'generator_dumper_class' => CompiledUrlGeneratorDumper::class, 'generator_dumper_class' => CompiledUrlGeneratorDumper::class,
'generator_cache_class' => 'UrlGenerator', 'generator_cache_class' => 'UrlGenerator', // deprecated
'matcher_class' => CompiledUrlMatcher::class, 'matcher_class' => CompiledUrlMatcher::class,
'matcher_base_class' => UrlMatcher::class, 'matcher_base_class' => UrlMatcher::class, // deprecated
'matcher_dumper_class' => CompiledUrlMatcherDumper::class, 'matcher_dumper_class' => CompiledUrlMatcherDumper::class,
'matcher_cache_class' => 'UrlMatcher', 'matcher_cache_class' => 'UrlMatcher', // deprecated
'resource_type' => null, 'resource_type' => null,
'strict_requirements' => true, 'strict_requirements' => true,
]; ];
@ -148,6 +145,7 @@ class Router implements RouterInterface, RequestMatcherInterface
// check option names and live merge, if errors are encountered Exception will be thrown // check option names and live merge, if errors are encountered Exception will be thrown
$invalid = []; $invalid = [];
foreach ($options as $key => $value) { foreach ($options as $key => $value) {
$this->checkDeprecatedOption($key);
if (array_key_exists($key, $this->options)) { if (array_key_exists($key, $this->options)) {
$this->options[$key] = $value; $this->options[$key] = $value;
} else { } else {
@ -174,6 +172,8 @@ class Router implements RouterInterface, RequestMatcherInterface
throw new \InvalidArgumentException(sprintf('The Router does not support the "%s" option.', $key)); throw new \InvalidArgumentException(sprintf('The Router does not support the "%s" option.', $key));
} }
$this->checkDeprecatedOption($key);
$this->options[$key] = $value; $this->options[$key] = $value;
} }
@ -192,6 +192,8 @@ class Router implements RouterInterface, RequestMatcherInterface
throw new \InvalidArgumentException(sprintf('The Router does not support the "%s" option.', $key)); throw new \InvalidArgumentException(sprintf('The Router does not support the "%s" option.', $key));
} }
$this->checkDeprecatedOption($key);
return $this->options[$key]; return $this->options[$key];
} }
@ -279,7 +281,7 @@ class Router implements RouterInterface, RequestMatcherInterface
return $this->matcher; return $this->matcher;
} }
$compiled = is_a($this->options['matcher_class'], CompiledUrlMatcher::class, true); $compiled = is_a($this->options['matcher_class'], CompiledUrlMatcher::class, true) && (UrlMatcher::class === $this->options['matcher_base_class'] || RedirectableUrlMatcher::class === $this->options['matcher_base_class']);
if (null === $this->options['cache_dir'] || null === $this->options['matcher_cache_class']) { if (null === $this->options['cache_dir'] || null === $this->options['matcher_cache_class']) {
$routes = $this->getRouteCollection(); $routes = $this->getRouteCollection();
@ -336,7 +338,7 @@ class Router implements RouterInterface, RequestMatcherInterface
return $this->generator; return $this->generator;
} }
$compiled = is_a($this->options['generator_class'], CompiledUrlGenerator::class, true); $compiled = is_a($this->options['generator_class'], CompiledUrlGenerator::class, true) && UrlGenerator::class === $this->options['generator_base_class'];
if (null === $this->options['cache_dir'] || null === $this->options['generator_cache_class']) { if (null === $this->options['cache_dir'] || null === $this->options['generator_cache_class']) {
$routes = $this->getRouteCollection(); $routes = $this->getRouteCollection();
@ -411,4 +413,15 @@ class Router implements RouterInterface, RequestMatcherInterface
return $this->configCacheFactory; return $this->configCacheFactory;
} }
private function checkDeprecatedOption($key)
{
switch ($key) {
case 'generator_base_class':
case 'generator_cache_class':
case 'matcher_base_class':
case 'matcher_cache_class':
@trigger_error(sprintf('Option "%s" given to router %s is deprecated since Symfony 4.3.', $key, static::class), E_USER_DEPRECATED);
}
}
} }

View File

@ -93,12 +93,9 @@ class RouterTest extends TestCase
$this->assertSame($routeCollection, $this->router->getRouteCollection()); $this->assertSame($routeCollection, $this->router->getRouteCollection());
} }
/** public function testMatcherIsCreatedIfCacheIsNotConfigured()
* @dataProvider provideMatcherOptionsPreventingCaching
*/
public function testMatcherIsCreatedIfCacheIsNotConfigured($option)
{ {
$this->router->setOption($option, null); $this->router->setOption('cache_dir', null);
$this->loader->expects($this->once()) $this->loader->expects($this->once())
->method('load')->with('routing.yml', null) ->method('load')->with('routing.yml', null)
@ -107,20 +104,9 @@ class RouterTest extends TestCase
$this->assertInstanceOf('Symfony\\Component\\Routing\\Matcher\\UrlMatcher', $this->router->getMatcher()); $this->assertInstanceOf('Symfony\\Component\\Routing\\Matcher\\UrlMatcher', $this->router->getMatcher());
} }
public function provideMatcherOptionsPreventingCaching() public function testGeneratorIsCreatedIfCacheIsNotConfigured()
{ {
return [ $this->router->setOption('cache_dir', null);
['cache_dir'],
['matcher_cache_class'],
];
}
/**
* @dataProvider provideGeneratorOptionsPreventingCaching
*/
public function testGeneratorIsCreatedIfCacheIsNotConfigured($option)
{
$this->router->setOption($option, null);
$this->loader->expects($this->once()) $this->loader->expects($this->once())
->method('load')->with('routing.yml', null) ->method('load')->with('routing.yml', null)
@ -129,14 +115,6 @@ class RouterTest extends TestCase
$this->assertInstanceOf('Symfony\\Component\\Routing\\Generator\\UrlGenerator', $this->router->getGenerator()); $this->assertInstanceOf('Symfony\\Component\\Routing\\Generator\\UrlGenerator', $this->router->getGenerator());
} }
public function provideGeneratorOptionsPreventingCaching()
{
return [
['cache_dir'],
['generator_cache_class'],
];
}
public function testMatchRequestWithUrlMatcherInterface() public function testMatchRequestWithUrlMatcherInterface()
{ {
$matcher = $this->getMockBuilder('Symfony\Component\Routing\Matcher\UrlMatcherInterface')->getMock(); $matcher = $this->getMockBuilder('Symfony\Component\Routing\Matcher\UrlMatcherInterface')->getMock();