From cbae12682f5ae5ee79466aca47a4a98d1954e16d Mon Sep 17 00:00:00 2001 From: Antanas Arvasevicius Date: Fri, 20 Jan 2017 16:51:47 +0200 Subject: [PATCH] bug #21339 [FrameworkBundle] CachePoolClearerPass fails if "cache.annotations" service is created --- .../CacheAnnotationsMonologInjectorPass.php | 43 +++++++++ .../Compiler/CachePoolClearerPass.php | 18 ---- .../FrameworkBundle/FrameworkBundle.php | 2 + .../Tests/Functional/ContainerDumpTest.php | 10 ++ .../SetupBundle.php | 95 +++++++++++++++++++ .../bundles.php | 20 ++++ .../config.yml | 21 ++++ 7 files changed, 191 insertions(+), 18 deletions(-) create mode 100644 src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CacheAnnotationsMonologInjectorPass.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ContainerDumpCacheAnnotationsBug/SetupBundle.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ContainerDumpCacheAnnotationsBug/bundles.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ContainerDumpCacheAnnotationsBug/config.yml diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CacheAnnotationsMonologInjectorPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CacheAnnotationsMonologInjectorPass.php new file mode 100644 index 0000000000000..e16f0c0debbdd --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CacheAnnotationsMonologInjectorPass.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; + +use Symfony\Component\Cache\Adapter\AbstractAdapter; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; + +final class CacheAnnotationsMonologInjectorPass implements CompilerPassInterface +{ + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + if (!$container->hasDefinition('cache.annotations') && !$container->hasAlias('cache.annotations')) { + return; + } + $factory = array(AbstractAdapter::class, 'createSystemCache'); + $annotationsPool = $container->findDefinition('cache.annotations'); + if ($factory !== $annotationsPool->getFactory() || 4 !== count($annotationsPool->getArguments())) { + return; + } + if ($container->has('monolog.logger.cache')) { + $annotationsPool->addArgument(new Reference('monolog.logger.cache')); + } elseif ($container->hasDefinition('cache.system')) { + $systemPool = $container->getDefinition('cache.system'); + if ($factory === $systemPool->getFactory() && 5 <= count($systemArgs = $systemPool->getArguments())) { + $annotationsPool->addArgument($systemArgs[4]); + } + } + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolClearerPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolClearerPass.php index c859a6ba900a4..901722756bd4a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolClearerPass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolClearerPass.php @@ -11,7 +11,6 @@ namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; -use Symfony\Component\Cache\Adapter\AbstractAdapter; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; @@ -39,22 +38,5 @@ public function process(ContainerBuilder $container) } } } - - if (!$container->has('cache.annotations')) { - return; - } - $factory = array(AbstractAdapter::class, 'createSystemCache'); - $annotationsPool = $container->getDefinition('cache.annotations'); - if ($factory !== $annotationsPool->getFactory() || 4 !== count($annotationsPool->getArguments())) { - return; - } - if ($container->has('monolog.logger.cache')) { - $annotationsPool->addArgument(new Reference('monolog.logger.cache')); - } elseif ($container->has('cache.system')) { - $systemPool = $container->getDefinition('cache.system'); - if ($factory === $systemPool->getFactory() && 5 <= count($systemArgs = $systemPool->getArguments())) { - $annotationsPool->addArgument($systemArgs[4]); - } - } } } diff --git a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php index 4c20d146cb4bf..df98cafbcb033 100644 --- a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php +++ b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php @@ -15,6 +15,7 @@ use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddDebugLogProcessorPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddValidatorInitializersPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddConsoleCommandPass; +use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\CacheAnnotationsMonologInjectorPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\CachePoolPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\CachePoolClearerPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ControllerArgumentValueResolverPass; @@ -96,6 +97,7 @@ public function build(ContainerBuilder $container) $container->addCompilerPass(new CachePoolPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, 32); $container->addCompilerPass(new ValidateWorkflowsPass()); $container->addCompilerPass(new CachePoolClearerPass(), PassConfig::TYPE_AFTER_REMOVING); + $container->addCompilerPass(new CacheAnnotationsMonologInjectorPass(), PassConfig::TYPE_BEFORE_REMOVING, 32); if ($container->getParameter('kernel.debug')) { $container->addCompilerPass(new AddDebugLogProcessorPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, -32); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ContainerDumpTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ContainerDumpTest.php index 423d673be2f96..fd18fa6eaa212 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ContainerDumpTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ContainerDumpTest.php @@ -29,4 +29,14 @@ public function testContainerCompilation() $this->assertTrue($client->getContainer()->has('serializer')); } + + /** + * @see https://github.com/symfony/symfony/issues/21339 + */ + public function testContainerCompilationErrorDueCachePoolClearerPassBug() + { + $client = $this->createClient(array('test_case' => 'ContainerDumpCacheAnnotationsBug', 'root_config' => 'config.yml', 'debug' => true)); + + $this->assertTrue($client->getContainer()->has('serializer')); + } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ContainerDumpCacheAnnotationsBug/SetupBundle.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ContainerDumpCacheAnnotationsBug/SetupBundle.php new file mode 100644 index 0000000000000..d84a145bbaafc --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ContainerDumpCacheAnnotationsBug/SetupBundle.php @@ -0,0 +1,95 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\Functional\app\ContainerDumpCacheAnnotationsBug; + +use Psr\Cache\CacheItemInterface; +use Psr\Cache\CacheItemPoolInterface; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\Compiler\PassConfig; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\HttpKernel\Bundle\Bundle; + +class BeforeOptimizationCompilerPass implements CompilerPassInterface +{ + public function process(ContainerBuilder $container) + { + // force to use service in compiler pass which does DiExtraBundle + $container->get('cache.annotations'); + } +} + +/** + * Emulate CacheCollectorPass which aliasias cache.annotations service (used in debug mode). + * + * @see src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CacheCollectorPass.php:24 + */ +class CacheCollectorEmulationPass implements CompilerPassInterface +{ + public function process(ContainerBuilder $container) + { + $id = 'cache.annotations'; + + $container->register($id.'.recorder', DummyDecorator::class) + ->setDecoratedService($id) + ->addArgument(new Reference($id.'.recorder.inner')) + ->setPublic(false); + } +} + +class DummyDecorator implements CacheItemPoolInterface +{ + public function getItem($key) + { + } + + public function getItems(array $keys = array()) + { + } + + public function hasItem($key) + { + } + + public function clear() + { + } + + public function deleteItem($key) + { + } + + public function deleteItems(array $keys) + { + } + + public function save(CacheItemInterface $item) + { + } + + public function saveDeferred(CacheItemInterface $item) + { + } + + public function commit() + { + } +} + +class SetupBundle extends Bundle +{ + public function build(ContainerBuilder $container) + { + $container->addCompilerPass(new BeforeOptimizationCompilerPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION); + $container->addCompilerPass(new CacheCollectorEmulationPass()); + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ContainerDumpCacheAnnotationsBug/bundles.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ContainerDumpCacheAnnotationsBug/bundles.php new file mode 100644 index 0000000000000..2bb0f1069dafb --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ContainerDumpCacheAnnotationsBug/bundles.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Bundle\FrameworkBundle\Tests\Functional\app\ContainerDumpCacheAnnotationsBug\SetupBundle; +use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestBundle; +use Symfony\Bundle\FrameworkBundle\FrameworkBundle; + +return array( + new FrameworkBundle(), + new TestBundle(), + new SetupBundle(), +); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ContainerDumpCacheAnnotationsBug/config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ContainerDumpCacheAnnotationsBug/config.yml new file mode 100644 index 0000000000000..29f1e32ff964f --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ContainerDumpCacheAnnotationsBug/config.yml @@ -0,0 +1,21 @@ +imports: + - { resource: ../config/default.yml } + +framework: + esi: true + ssi: true + fragments: true + profiler: true + router: true + session: true + request: true + templating: + enabled: true + engines: ['php'] + assets: true + translator: true + validation: true + serializer: true + property_info: true + csrf_protection: true + form: true