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

Skip to content
Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit b35f940

Browse files
[FrameworkBundle][DI] Resolve cache pool adapters in CachePoolPass
1 parent 39c8309 commit b35f940

File tree

8 files changed

+163
-100
lines changed

8 files changed

+163
-100
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

10000 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/Compiler/ResolveDefinitionTemplatesPass.php

Lines changed: 1 addition & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -124,95 +124,7 @@ private function doResolveDefinition(ContainerBuilder $container, DefinitionDeco
124124
}
125125

126126
$this->compiler->addLogMessage($this->formatter->formatResolveInheritance($this, $this->currentId, $parent));
127-
$def = new Definition();
128-
129-
// merge in parent definition
130-
// purposely ignored attributes: abstract, tags
131-
$def->setClass($parentDef->getClass());
132-
$def->setArguments($parentDef->getArguments());
133-
$def->setMethodCalls($parentDef->getMethodCalls());
134-
$def->setProperties($parentDef->getProperties());
135-
$def->setAutowiringTypes($parentDef->getAutowiringTypes());
136-
if ($parentDef->isDeprecated()) {
137-
$def->setDeprecated(true, $parentDef->getDeprecationMessage('%service_id%'));
138-
}
139-
$def->setFactory($parentDef->getFactory());
140-
$def->setConfigurator($parentDef->getConfigurator());
141-
$def->setFile($parentDef->getFile());
142-
$def->setPublic($parentDef->isPublic());
143-
$def->setLazy($parentDef->isLazy());
144-
$def->setAutowired($parentDef->isAutowired());
145-
146-
// overwrite with values specified in the decorator
147-
$changes = $definition->getChanges();
148-
if (isset($changes['class'])) {
149-
$def->setClass($definition->getClass());
150-
}
151-
if (isset($changes['factory'])) {
152-
$def->setFactory($definition->getFactory());
153-
}
154-
if (isset($changes['configurator'])) {
155-
$def->setConfigurator($definition->getConfigurator());
156-
}
157-
if (isset($changes['file'])) {
158-
$def->setFile($definition->getFile());
159-
}
160-
if (isset($changes['public'])) {
161-
$def->setPublic($definition->isPublic());
162-
}
163-
if (isset($changes['lazy'])) {
164-
$def->setLazy($definition->isLazy());
165-
}
166-
if (isset($changes['deprecated'])) {
167-
$def->setDeprecated($definition->isDeprecated(), $definition->getDeprecationMessage('%service_id%'));
168-
}
169-
if (isset($changes['autowire'])) {
170-
$def->setAutowired($definition->isAutowired());
171-
}
172-
if (isset($changes['decorated_service'])) {
173-
$decoratedService = $definition->getDecoratedService();
174-
if (null === $decoratedService) {
175-
$def->setDecoratedService($decoratedService);
176-
} else {
177-
$def->setDecoratedService($decoratedService[0], $decoratedService[1], $decoratedService[2]);
178-
}
179-
}
180-
181-
// merge arguments
182-
foreach ($definition->getArguments() as $k => $v) {
183-
if (is_numeric($k)) {
184-
$def->addArgument($v);
185-
continue;
186-
}
187-
188-
if (0 !== strpos($k, 'index_')) {
189-
throw new RuntimeException(sprintf('Invalid argument key "%s" found.', $k));
190-
}
191-
192-
$index = (int) substr($k, strlen('index_'));
193-
$def->replaceArgument($index, $v);
194-
}
195-
196-
// merge properties
197-
foreach ($definition->getProperties() as $k => $v) {
198-
$def->setProperty($k, $v);
199-
}
200-
201-
// append method calls
202-
if (count($calls = $definition->getMethodCalls()) > 0) {
203-
$def->setMethodCalls(array_merge($def->getMethodCalls(), $calls));
204-
}
205-
206-
// merge autowiring types
207-
foreach ($definition->getAutowiringTypes() as $autowiringType) {
208-
$def->addAutowiringType($autowiringType);
209-
}
210-
211-
// these attributes are always taken from the child
212-
$def->setAbstract($definition->isAbstract());
213-
$def->setShared($definition->isShared());
214-
$def->setTags($definition->getTags());
215127

216-
return $def;
128+
return $definition->resolveChanges($parentDef);
217129
}
218130
}

src/Symfony/Component/DependencyInjection/ContainerBuilder.php

Lines changed: 9 additions & 2 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[ 10000 $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
}
@@ -836,7 +843,7 @@ public function findDefinition($id)
836843
private function createService(Definition $definition, $id, $tryProxy = true)
837844
{
838845
if ('Symfony\Component\DependencyInjection\Definition' !== get_class($definition)) {
839-
throw new RuntimeException(sprintf('Constructing service "%s" from a %s is not supported at build time.', $id, 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()) {

src/Symfony/Component/DependencyInjection/DefinitionDecorator.php

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
1515
use Symfony\Component\DependencyInjection\Exception\OutOfBoundsException;
16+
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
1617

1718
/**
1819
* This definition decorates another definition.
@@ -196,4 +197,106 @@ public function replaceArgument($index, $value)
196197

197198
return $this;
198199
}
200+
201+
/**
202+
* Creates a new Definition by merging the current decorator with the given parent definition.
203+
*
204+
* @return Definition
205+
*/
206+
public function resolveChanges(Definition $parentDef)
207+
{
208+
if ($parentDef instanceof self) {
209+
throw new InvalidArgumentException('$parenfDef must be a resolved Definition.');
210+
}
211+
$def = new Definition();
212+
213+
// merge in parent definition
214+
// purposely ignored attributes: abstract, tags
215+
$def->setClass($parentDef->getClass());
216+
$def->setArguments($parentDef->getArguments());
217+
$def->setMethodCalls($parentDef->getMethodCalls());
218+
$def->setProperties($parentDef->getProperties());
219+
$def->setAutowiringTypes($parentDef->getAutowiringTypes());
220+
if ($parentDef->isDeprecated()) {
221+
$def->setDeprecated(true, $parentDef->getDeprecationMessage('%service_id%'));
222+
}
223+
$def->setFactory($parentDef->getFactory());
224+
$def->setConfigurator($parentDef->getConfigurator());
225+
$def->setFile($parentDef->getFile());
226+
$def->setPublic($parentDef->isPublic());
227+
$def->setLazy($parentDef->isLazy());
228+
$def->setAutowired($parentDef->isAutowired());
229+
230+
// overwrite with values specified in the decorator
231+
$changes = $this->getChanges();
232+
if (isset($changes['class'])) {
233+
$def->setClass($this->getClass());
234+
}
235+
if (isset($changes['factory'])) {
236+
$def->setFactory($this->getFactory());
237+
}
238+
if (isset($changes['configurator'])) {
239+
$def->setConfigurator($this->getConfigurator());
240+
}
241+
if (isset($changes['file'])) {
242+
$def->setFile($this->getFile());
243+
} 10000
244+
if (isset($changes['public'])) {
245+
$def->setPublic($this->isPublic());
246+
}
247+
if (isset($changes['lazy'])) {
248+
$def->setLazy($this->isLazy());
249+
}
250+
if (isset($changes['deprecated'])) {
251+
$def->setDeprecated($this->isDeprecated(), $this->getDeprecationMessage('%service_id%'));
252+
}
253+
if (isset($changes['autowire'])) {
254+
$def->setAutowired($this->isAutowired());
255+
}
256+
if (isset($changes['decorated_service'])) {
257+
$decoratedService = $this->getDecoratedService();
258+
if (null === $decoratedService) {
259+
$def->setDecoratedService($decoratedService);
260+
} else {
261+
$def->setDecoratedService($decoratedService[0], $decoratedService[1], $decoratedService[2]);
262+
}
263+
}
264+
265+
// merge arguments
266+
foreach ($this->getArguments() as $k => $v) {
267+
if (is_numeric($k)) {
268+
$def->addArgument($v);
269+
continue;
270+
}
271+
272+
if (0 !== strpos($k, 'index_')) {
273+
throw new RuntimeException(sprintf('Invalid argument key "%s" found.', $k));
274+
}
275+
276+
$index = (int) substr($k, strlen('index_'));
277+
$def->replaceArgument($index, $v);
278+
}
279+
280+
// merge properties
281+
foreach ($this->getProperties() as $k => $v) {
282+
$def->setProperty($k, $v);
283+
}
284+
285+
// append method calls
286+
if ($calls = $this->getMethodCalls()) {
287+
$def->setMethodCalls(array_merge($def->getMethodCalls(), $calls));
288+
}
289+
290+
// merge autowiring types
291+
foreach ($this->getAutowiringTypes() as $autowiringType) {
292+
$def->addAutowiringType($autowiringType);
293+
}
294+
295+
// these attributes are always taken from the child
296+
$def->setAbstract($this->isAbstract());
297+
$def->setShared($this->isShared());
298+
$def->setTags($this->getTags());
299+
300+
return $def;
301+
}
199302
}
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: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,7 @@ public function testResolveServices()
414414
}
415415

416416
/**
417-
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
417+
* @expectedException \Symfony\Component\DependencyInjection\Exception\UnresolvedServiceDefinitionException
418418
* @expectedExceptionMessage Constructing service "foo" from a Symfony\Component\DependencyInjection\DefinitionDecorator is not supported at build time.
419419
*/
420420
public function testResolveServicesWithDecoratedDefinition()

0 commit comments

Comments
 (0)
0