Skip to content

[FrameworkBundle] fix wiring of annotations.cached_reader #46427

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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'])) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
</service>
</argument>
<argument /><!-- Debug-Flag -->
<tag name="annotations.cached_reader" />
<tag name="container.do_not_inline" />
</service>

<service id="annotations.filesystem_cache_adapter" class="Symfony\Component\Cache\Adapter\FilesystemAdapter">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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'];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should those be merged with the parameter instead ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so: giving full control to the parameter is more flexible to me.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but does it really make sense to disable core ones ? It would mean that if a project customizes the list, they would not benefit from new additions done in the core like this bugfix until they discover this internal change to the default value.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This tag is already used in ResolveInstanceofConditionalsPass where is has to contain container.service_locator and other core tags. This code doesn't introduce anything new to me, convention-wise (since this parameter works by convention).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok


foreach ($definitions as [$id, $definition]) {
$decoratedService = $definition->getDecoratedService();
[$inner, $renamedId] = $decoratedService;
Expand Down Expand Up @@ -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]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down