10000 [FrameworkBundle][DI] Resolve cache pool adapters in CachePoolPass · symfony/symfony@1db236e · GitHub
[go: up one dir, main page]

Skip to content

Commit 1db236e

Browse files
[FrameworkBundle][DI] Resolve cache pool adapters in CachePoolPass
1 parent 1d4d6e7 commit 1db236e

File tree

7 files changed

+65
-26
lines changed

7 files changed

+65
-26
lines changed

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use Symfony\Component\DependencyInjection\DefinitionDecorator;
1919
use Symfony\Component\DependencyInjection\Reference;
2020
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
21+
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
2122

2223
/**
2324
* @author Nicolas Grekas <p@tchwork.com>
@@ -37,22 +38,20 @@ public function process(ContainerBuilder $container)
3738
}
3839
}
3940

41+
$resolvedPools = array();
4042
$aliases = $container->getAliases();
4143
$attributes = array(
4244
'provider',
4345
'namespace',
4446
'default_lifetime',
4547
);
4648
foreach ($container->findTaggedServiceIds('cache.pool') as $id => $tags) {
47-
$adapter = $pool = $container->getDefinition($id);
49+
$pool = $container->getDefinition($id);
4850
if ($pool->isAbstract()) {
4951
continue;
5052
}
51-
while ($adapter instanceof DefinitionDecorator) {
52-
$adapter = $container->findDefinition($adapter->getParent());
53-
if ($t = $adapter->getTag('cache.pool')) {
54-
$tags[0] += $t[0];
55-
}
53+
if ($pool instanceof DefinitionDecorator) {
54+
$resolvedPools[$id] = $pool = $this->resolveAdapters($container, $pool, $id, $tags);
5655
}
5756
if (!isset($tags[0]['namespace'])) {
5857
$tags[0]['namespace'] = $this->getNamespace($namespaceSuffix, $id);
@@ -85,13 +84,32 @@ public function process(ContainerBuilder $container)
8584
$pool->addTag('cache.pool', array('clearer' => $clearer));
8685
}
8786
}
87+
foreach ($resolvedPools as $id => $pool) {
88+
$container->setDefinition($id, $pool);
89+
}
8890
}
8991

9092
private function getNamespace($namespaceSuffix, $id)
9193
{
9294
return substr(str_replace('/', '-', base64_encode(hash('sha256', $id.$namespaceSuffix, true))), 0, 10);
9395
}
9496

97+
private function resolveAdapters(ContainerBuilder $container, DefinitionDecorator $pool, $id, array &$tags)
98+
{
99+
if (!$container->has($parent = $pool->getParent())) {
100+
throw new RuntimeException(sprintf('Service "%s": Parent definition "%s" does not exist.', $id, $parent));
101+
}
102+
$adapter = $container->findDefinition($parent);
103+
if ($t = $adapter->getTag('cache.pool')) {
104+
$tags[0] += $t[0];
105+
}
106+
if ($adapter instanceof DefinitionDecorator) {
107+
$adapter = $this->resolveAdapters($container, $adapter, $parent, $tags);
108+
}
109+
110+
return $pool->resolveChanges($adapter);
111+
}
112+
95113
/**
96114
* @internal
97115
*/

src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ public function build(ContainerBuilder $container)
9393
$container->addCompilerPass(new SerializerPass());
9494
$container->addCompilerPass(new PropertyInfoPass());
9595
$container->addCompilerPass(new ControllerArgumentValueResolverPass());
96-
$container->addCompilerPass(new CachePoolPass());
96+
$container->addCompilerPass(new CachePoolPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, 1);
9797
$container->addCompilerPass(new ValidateWorkflowsPass());
9898
$container->addCompilerPass(new CachePoolClearerPass(), PassConfig::TYPE_AFTER_REMOVING);
9999

src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/CachePoolPassTest.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ public function testNamespaceArgumentIsReplaced()
4141

4242
$this->cachePoolPass->process($container);
4343

44-
$this->assertSame('kRFqMp5odS', $cachePool->getArgument(0));
44+
$this->assertSame(Definition::class, get_class($container->getDefinition('app.cache_pool')));
45+
$this->assertSame('kRFqMp5odS', $container->getDefinition('app.cache_pool')->getArgument(0));
4546
}
4647

4748
public function testArgsAreReplaced()
@@ -75,6 +76,7 @@ public function testThrowsExceptionWhenCachePoolTagHasUnknownAttributes()
7576
$adapter = new Definition();
7677
$adapter->setAbstract(true);
7778
$adapter->addTag('cache.pool');
79+
$adapter->addArgument(null);
7880
$container->setDefinition('app.cache_adapter', $adapter);
7981
$cachePool = new DefinitionDecorator('app.cache_adapter');
8082
$cachePool->addTag('cache.pool', array('foobar' => 123));

src/Symfony/Component/DependencyInjection/ContainerBuilder.php

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
2121
use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
2222
use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
23+
use Symfony\Component\DependencyInjection\Exception\UnresolvedServiceDefinitionException;
2324
use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
2425
use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag;
2526
use Symfony\Component\Config\Resource\FileResource;
@@ -424,7 +425,7 @@ public function get($id, $invalidBehavior = ContainerInterface::EXCEPTION_ON_INV
424425
}
425426

426427
if (!isset($this->definitions[$id]) && isset($this->aliasDefinitions[$id])) {
427-
return $this->get($this->aliasDefinitions[$id]);
428+
return $this->get($this->aliasDefinitions[$id], $invalidBehavior);
428429
}
429430

430431
try {
@@ -441,6 +442,12 @@ public function get($id, $invalidBehavior = ContainerInterface::EXCEPTION_ON_INV
441442

442443
try {
443444
$service = $this->createService($definition, $id);
445+
} catch (UnresolvedServiceDefinitionException $e) {
446+
if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $invalidBehavior) {
447+
return;
448+
}
449+
450+
throw $e;
444451
} finally {
445452
unset($this->loading[$id]);
446453
}
@@ -835,8 +842,8 @@ public function findDefinition($id)
835842
*/
836843
private function createService(Definition $definition, $id, $tryProxy = true)
837844
{
838-
if ($definition instanceof DefinitionDecorator) {
839-
$definition = $this->resolveDefinitionDecorator($definition, $id);
845+
if ('Symfony\Component\DependencyInjection\Definition' !== get_class($definition)) {
846+
throw new UnresolvedServiceDefinitionException(sprintf('Constructing service "%s" from a %s is not supported at build time.', $id, get_class($definition)));
840847
}
841848

842849
if ($definition->isSynthetic()) {
@@ -1124,19 +1131,6 @@ private function callMethod($service, $call)
11241131
call_user_func_array(array($service, $call[0]), $this->resolveServices($this->getParameterBag()->unescapeValue($this->getParameterBag()->resolveValue($call[1]))));
11251132
}
11261133

1127-
private function resolveDefinitionDecorator(DefinitionDecorator $definition, $id)
1128-
{
1129-
if (!$this->has($parent = $definition->getParent())) {
1130-
throw new RuntimeException(sprintf('Service "%s": Parent definition "%s" does not exist.', $id, $parent));
1131-
}
1132-
$parentDef = $this->findDefinition($parent);
1133-
if ($parentDef instanceof DefinitionDecorator) {
1134-
$parentDef = $this->resolveDefinitionDecorator($parentDef, $parent);
1135-
}
1136-
1137-
return $definition->resolveChanges($parentDef);
1138-
}
1139-
11401134
/**
11411135
* Shares a given service in the container.
11421136
*

src/Symfony/Component/DependencyInjection/DefinitionDecorator.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ public function resolveChanges(Definition $parentDef)
283283
}
284284

285285
// append method calls
286-
if (count($calls = $this->getMethodCalls()) > 0) {
286+
if ($calls = $this->getMethodCalls()) {
287287
$def->setMethodCalls(array_merge($def->getMethodCalls(), $calls));
288288
}
289289

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\DependencyInjection\Exception;
13+
14+
/**
15+
* This exception is thrown when an unresolved service definition is requested.
16+
*
17+
* @author Nicolas Grekas <p@tchwork.com>
18+
*/
19+
class UnresolvedServiceDefinitionException extends RuntimeException
20+
{
21+
}

src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -413,14 +413,18 @@ public function testResolveServices()
413413
$this->assertEquals($builder->get('foo'), $builder->resolveServices(new Expression('service("foo")')), '->resolveServices() resolves expressions');
414414
}
415415

416+
/**
417+
* @expectedException \Symfony\Component\DependencyInjection\Exception\UnresolvedServiceDefinitionException
418+
* @expectedExceptionMessage Constructing service "foo" from a Symfony\Component\DependencyInjection\DefinitionDecorator is not supported at build time.
419+
*/
416420
public function testResolveServicesWithDecoratedDefinition()
417421
{
418422
$builder = new ContainerBuilder();
419423
$builder->setDefinition('grandpa', new Definition('stdClass'));
420424
$builder->setDefinition('parent', new DefinitionDecorator('grandpa'));
421425
$builder->setDefinition('foo', new DefinitionDecorator('parent'));
422426

423-
$this->assertInstanceOf('stdClass', $builder->get('foo'));
427+
$builder->get('foo');
424428
}
425429

426430
public function testMerge()

0 commit comments

Comments
 (0)
0