diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddAnnotationsCachedReaderPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddAnnotationsCachedReaderPass.php index a0581ff21fb6f..d7db6ebf050a4 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddAnnotationsCachedReaderPass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddAnnotationsCachedReaderPass.php @@ -29,7 +29,6 @@ public function process(ContainerBuilder $container) // "annotation_reader" at build time don't get any cache foreach ($container->findTaggedServiceIds('annotations.cached_reader') as $id => $tags) { $reader = $container->getDefinition($id); - $reader->setPublic(false); $properties = $reader->getProperties(); if (isset($properties['cacheProviderBackup'])) { diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php index 888a5ea8d64c1..669d331c062f3 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php @@ -28,6 +28,7 @@ class UnusedTagsPass implements CompilerPassInterface 'cache.pool.clearer', 'config_cache.resource_checker', 'console.command', + 'container.do_not_inline', 'container.env_var_loader', 'container.env_var_processor', 'container.hot_path', diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 6f55ad6c38f39..ca338fc2054db 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -469,6 +469,8 @@ public function load(array $configs, ContainerBuilder $container) ->addTag('routing.route_loader'); $container->setParameter('container.behavior_describing_tags', [ + 'annotations.cached_reader', + 'container.do_not_inline', 'container.service_locator', 'container.service_subscriber', 'kernel.event_subscriber', @@ -1463,11 +1465,9 @@ private function registerAnnotationsConfiguration(array $config, ContainerBuilde $container ->getDefinition('annotations.cached_reader') - ->setPublic(true) // set to false in AddAnnotationsCachedReaderPass ->replaceArgument(2, $config['debug']) // reference the cache provider without using it until AddAnnotationsCachedReaderPass runs ->addArgument(new ServiceClosureArgument(new Reference($cacheService))) - ->addTag('annotations.cached_reader') ; $container->setAlias('annotation_reader', 'annotations.cached_reader')->setPrivate(true); diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/annotations.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/annotations.xml index 4420dfbf00db1..1fb375ea3c472 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/annotations.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/annotations.xml @@ -31,6 +31,8 @@ + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php index b66d0837c3a37..c2c7bc6b851cc 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php @@ -1699,6 +1699,8 @@ public function testRegisterParameterCollectingBehaviorDescribingTags() $this->assertTrue($container->hasParameter('container.behavior_describing_tags')); $this->assertEquals([ + 'annotations.cached_reader', + 'container.do_not_inline', 'container.service_locator', 'container.service_subscriber', 'kernel.event_subscriber', diff --git a/src/Symfony/Component/DependencyInjection/Compiler/DecoratorServicePass.php b/src/Symfony/Component/DependencyInjection/Compiler/DecoratorServicePass.php index af7c957a308a2..3b8086d0931e6 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/DecoratorServicePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/DecoratorServicePass.php @@ -40,6 +40,10 @@ public function process(ContainerBuilder $container) } $decoratingDefinitions = []; + $tagsToKeep = $container->hasParameter('container.behavior_describing_tags') + ? $container->getParameter('container.behavior_describing_tags') + : ['container.do_not_inline', 'container.service_locator', 'container.service_subscriber']; + foreach ($definitions as [$id, $definition]) { $decoratedService = $definition->getDecoratedService(); [$inner, $renamedId] = $decoratedService; @@ -89,8 +93,8 @@ public function process(ContainerBuilder $container) $decoratingTags = $decoratingDefinition->getTags(); $resetTags = []; - // container.service_locator and container.service_subscriber have special logic and they must not be transferred out to decorators - foreach (['container.service_locator', 'container.service_subscriber'] as $containerTag) { + // Behavior-describing tags must not be transferred out to decorators + foreach ($tagsToKeep as $containerTag) { if (isset($decoratingTags[$containerTag])) { $resetTags[$containerTag] = $decoratingTags[$containerTag]; unset($decoratingTags[$containerTag]); diff --git a/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php index 358b750f2a376..7935983ff5c2e 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php @@ -177,7 +177,7 @@ protected function processValue($value, $isRoot = false) */ private function isInlineableDefinition(string $id, Definition $definition): bool { - if ($definition->hasErrors() || $definition->isDeprecated() || $definition->isLazy() || $definition->isSynthetic()) { + if ($definition->hasErrors() || $definition->isDeprecated() || $definition->isLazy() || $definition->isSynthetic() || $definition->hasTag('container.do_not_inline')) { return false; } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/InlineServiceDefinitionsPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/InlineServiceDefinitionsPassTest.php index 4f01d33c4923d..ac4269753525c 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/InlineServiceDefinitionsPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/InlineServiceDefinitionsPassTest.php @@ -325,6 +325,34 @@ public function testProcessDoesNotSetLazyArgumentValuesAfterInlining() $this->assertSame('inline', (string) $values[0]); } + public function testDoNotInline() + { + $container = new ContainerBuilder(); + $container->register('decorated1', 'decorated1')->addTag('container.do_not_inline'); + $container->register('decorated2', 'decorated2')->addTag('container.do_not_inline'); + $container->setAlias('alias2', 'decorated2'); + + $container + ->register('s1', 's1') + ->setDecoratedService('decorated1') + ->setPublic(true) + ->setProperties(['inner' => new Reference('s1.inner')]); + + $container + ->register('s2', 's2') + ->setDecoratedService('alias2') + ->setPublic(true) + ->setProperties(['inner' => new Reference('s2.inner')]); + + $container->compile(); + + $this->assertFalse($container->hasAlias('alias2')); + $this->assertEquals(new Reference('decorated2'), $container->getDefinition('s2')->getProperties()['inner']); + $this->assertEquals(new Reference('s1.inner'), $container->getDefinition('s1')->getProperties()['inner']); + $this->assertSame('decorated2', $container->getDefinition('decorated2')->getClass()); + $this->assertSame('decorated1', $container->getDefinition('s1.inner')->getClass()); + } + protected function process(ContainerBuilder $container) { (new InlineServiceDefinitionsPass(new AnalyzeServiceReferencesPass()))->process($container);