Skip to content

Commit 1bc4306

Browse files
committed
[FrameworkBundle] integrate the Cache component
1 parent 0813705 commit 1bc4306

File tree

10 files changed

+337
-0
lines changed

10 files changed

+337
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
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\Bundle\FrameworkBundle\DependencyInjection\Compiler;
13+
14+
use Symfony\Component\Cache\Adapter\ApcuAdapter;
15+
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
16+
use Symfony\Component\DependencyInjection\ContainerBuilder;
17+
use Symfony\Component\DependencyInjection\DefinitionDecorator;
18+
use Symfony\Component\DependencyInjection\Reference;
19+
20+
/**
21+
* @author Christian Flothmann <christian.flothmann@xabbuh.de>
22+
*/
23+
class CacheAdapterPass implements CompilerPassInterface
24+
{
25+
/**
26+
* {@inheritdoc}
27+
*/
28+
public function process(ContainerBuilder $container)
29+
{
30+
foreach ($container->getDefinitions() as $id => $definition) {
31+
foreach ($definition->getArguments() as $index => $argument) {
32+
$definition->replaceArgument($index, $this->createCacheAdapter($container, $id, $argument));
33+
}
34+
35+
$calls = $definition->getMethodCalls();
36+
37+
foreach ($calls as $c => $call) {
38+
$arguments = $call[1];
39+
40+
foreach ($arguments as $index => $argument) {
41+
$arguments[$index] = $this->createCacheAdapter($container, $id, $argument);
42+
}
43+
44+
$calls[$c] = array($call[0], $arguments);
45+
}
46+
47+
$definition->setMethodCalls($calls);
48+
49+
foreach ($definition->getProperties() as $name => $property) {
50+
$definition->setProperty($name, $this->createCacheAdapter($container, $id, $property));
51+
}
52+
}
53+
}
54+
55+
private function createCacheAdapter(ContainerBuilder $container, $serviceId, $argument)
56+
{
57+
if (!$argument instanceof Reference) {
58+
return $argument;
59+
}
60+
61+
$adapterId = (string) $argument;
62+
63+
if ('cache.adapter.' !== substr($adapterId, 0, 14)) {
64+
return $argument;
65+
}
66+
67+
$name = substr($adapterId, 14);
68+
69+
if (!$container->hasDefinition($adapterId)) {
70+
throw new \InvalidArgumentException(sprintf('The cache adapter "%s" is not configured.', $name));
71+
}
72+
73+
$abstractAdapter = $container->getDefinition($adapterId);
74+
$adapter = new DefinitionDecorator($adapterId);
75+
76+
switch ($abstractAdapter->getClass()) {
77+
case ApcuAdapter::class:
78+
$adapter->replaceArgument(0, sha1($serviceId));
79+
break;
80+
}
81+
82+
return $adapter;
83+
}
84+
}

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php

+27
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ public function getConfigTreeBuilder()
114114
$this->addSerializerSection($rootNode);
115115
$this->addPropertyAccessSection($rootNode);
116116
$this->addPropertyInfoSection($rootNode);
117+
$this->addCacheSection($rootNode);
117118

118119
return $treeBuilder;
119120
}
@@ -547,4 +548,30 @@ private function addPropertyInfoSection(ArrayNodeDefinition $rootNode)
547548
->end()
548549
;
549550
}
551+
552+
private function addCacheSection(ArrayNodeDefinition $rootNode)
553+
{
554+
$rootNode
555+
->children()
556+
->arrayNode('cache')
557+
->info('Cache configuration')
558+
->fixXmlConfig('adapter')
559+
->children()
560+
->arrayNode('adapters')
561+
->useAttributeAsKey('name')
562+
->prototype('array')
563+
->children()
564+
->enumNode('type')
565+
->info('The cache adapter type (one of "apcu", "doctrine", "filesystem")')
566+
->isRequired()
567+
->values(array('apcu', 'doctrine', 'filesystem'))
568+
->end()
569+
->end()
570+
->end()
571+
->end()
572+
->end()
573+
->end()
574+
->end()
575+
;
576+
}
550577
}

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

+30
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111

1212
namespace Symfony\Bundle\FrameworkBundle\DependencyInjection;
1313

14+
use Symfony\Component\Cache\Adapter\ApcuAdapter;
15+
use Symfony\Component\Cache\Adapter\DoctrineAdapter;
16+
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
1417
use Symfony\Component\DependencyInjection\ContainerBuilder;
1518
use Symfony\Component\DependencyInjection\ContainerInterface;
1619
use Symfony\Component\DependencyInjection\Definition;
@@ -134,6 +137,10 @@ public function load(array $configs, ContainerBuilder $container)
134137
$this->registerPropertyInfoConfiguration($config['property_info'], $container, $loader);
135138
}
136139

140+
if (isset($config['cache'])) {
141+
$this->registerCacheConfiguration($config['cache'], $container);
142+
}
143+
137144
$loader->load('debug_prod.xml');
138145
$definition = $container->findDefinition('debug.debug_handlers_listener');
139146

@@ -987,6 +994,29 @@ private function registerPropertyInfoConfiguration(array $config, ContainerBuild
987994
}
988995
}
989996

997+
private function registerCacheConfiguration(array $config, ContainerBuilder $container)
998+
{
999+
foreach ($config['adapters'] as $name => $adapter) {
1000+
$class = null;
1001+
1002+
switch ($adapter['type']) {
1003+
case 'apcu':
1004+
$class = ApcuAdapter::class;
1005+
break;
1006+
case 'doctrine':
1007+
$class = DoctrineAdapter::class;
1008+
break;
1009+
case 'filesystem':
1010+
$class = FilesystemAdapter::class;
1011+
break;
1012+
}
1013+
1014+
$adapterDefinition = new Definition($class);
1015+
$adapterDefinition->setAbstract(true);
1016+
$container->setDefinition('cache.adapter.'.$name, $adapterDefinition);
1017+
}
1018+
}
1019+
9901020
/**
9911021
* Gets a hash of the kernel root directory.
9921022
*

src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php

+2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddConstraintValidatorsPass;
1515
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddValidatorInitializersPass;
1616
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddConsoleCommandPass;
17+
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\CacheAdapterPass;
1718
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\FormPass;
1819
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\PropertyInfoPass;
1920
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TemplatingPass;
@@ -87,6 +88,7 @@ public function build(ContainerBuilder $container)
8788
$container->addCompilerPass(new FragmentRendererPass(), PassConfig::TYPE_AFTER_REMOVING);
8889
$container->addCompilerPass(new SerializerPass());
8990
$container->addCompilerPass(new PropertyInfoPass());
91+
$container->addCompilerPass(new CacheAdapterPass());
9092

9193
if ($container->getParameter('kernel.debug')) {
9294
$container->addCompilerPass(new UnusedTagsPass(), PassConfig::TYPE_AFTER_REMOVING);

src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd

+12
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
<xsd:element name="property-access" type="property_access" minOccurs="0" maxOccurs="1" />
2626
<xsd:element name="serializer" type="serializer" minOccurs="0" maxOccurs="1" />
2727
<xsd:element name="property-info" type="property_info" minOccurs="0" maxOccurs="1" />
28+
<xsd:element name="cache" type="cache" minOccurs="0" maxOccurs="1" />
2829
</xsd:all>
2930

3031
<xsd:attribute name="http-method-override" type="xsd:boolean" />
@@ -202,4 +203,15 @@
202203
<xsd:complexType name="property_info">
203204
<xsd:attribute name="enabled" type="xsd:boolean" />
204205
</xsd:complexType>
206+
207+
<xsd:complexType name="cache">
208+
<xsd:choice minOccurs="1" maxOccurs="unbounded">
209+
<xsd:element name="adapter" type="cache_adapter" />
210+
</xsd:choice>
211+
</xsd:complexType>
212+
213+
<xsd:complexType name="cache_adapter">
214+
<xsd:attribute name="name" type="xsd:string" use="required" />
215+
<xsd:attribute name="type" type="xsd:string" use="required" />
216+
</xsd:complexType>
205217
</xsd:schema>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
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\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler;
13+
14+
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\CacheAdapterPass;
15+
use Symfony\Component\DependencyInjection\ContainerBuilder;
16+
use Symfony\Component\DependencyInjection\Definition;
17+
use Symfony\Component\DependencyInjection\Reference;
18+
19+
class CacheAdapterPassTest extends \PHPUnit_Framework_TestCase
20+
{
21+
private $cacheAdapterPass;
22+
23+
protected function setUp()
24+
{
25+
$this->cacheAdapterPass = new CacheAdapterPass();
26+
}
27+
28+
public function testAdapterIsInjectedIntoConstructorArguments()
29+
{
30+
$container = $this->initializeContainer();
31+
$this->cacheAdapterPass->process($container);
32+
$adapter = $container->getDefinition('foo')->getArgument(0);
33+
34+
$this->assertInstanceOf('Symfony\Component\DependencyInjection\DefinitionDecorator', $adapter);
35+
$this->assertFalse($adapter->isAbstract());
36+
$this->assertSame('cache.adapter.apcu_adapter', $adapter->getParent());
37+
$this->assertSame('0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33', $adapter->getArgument(0));
38+
}
39+
40+
public function testAdapterIsInjectedIntoMethodArguments()
41+
{
42+
$container = $this->initializeContainer();
43+
$this->cacheAdapterPass->process($container);
44+
$methodCalls = $container->getDefinition('bar')->getMethodCalls();
45+
$arguments = $methodCalls[0][1];
46+
$adapter = $arguments[0];
47+
48+
$this->assertInstanceOf('Symfony\Component\DependencyInjection\DefinitionDecorator', $adapter);
49+
$this->assertFalse($adapter->isAbstract());
50+
$this->assertSame('cache.adapter.doctrine_adapter', $adapter->getParent());
51+
}
52+
53+
public function testAdapterIsInjectIntoProperties()
54+
{
55+
$container = $this->initializeContainer();
56+
$this->cacheAdapterPass->process($container);
57+
$properties = $container->getDefinition('baz')->getProperties();
58+
$adapter = $properties['cache'];
59+
60+
$this->assertInstanceOf('Symfony\Component\DependencyInjection\DefinitionDecorator', $adapter);
61+
$this->assertFalse($adapter->isAbstract());
62+
$this->assertSame('cache.adapter.fs_adapter', $adapter->getParent());
63+
}
64+
65+
/**
66+
* @expectedException \InvalidArgumentException
67+
* @expectedExceptionMessage The cache adapter "bar" is not configured
68+
*/
69+
public function testThrowsExceptionWhenReferencedAdapterIsNotConfigured()
70+
{
71+
$container = new ContainerBuilder();
72+
$container->setDefinition('foo', new Definition('Foo', array(new Reference('cache.adapter.bar'))));
73+
$this->cacheAdapterPass->process($container);
74+
}
75+
76+
private function initializeContainer()
77+
{
78+
$container = new ContainerBuilder();
79+
80+
$apcuAdapter = new Definition('Symfony\Component\Cache\Adapter\ApcuAdapter');
81+
$apcuAdapter->setAbstract(true);
82+
$container->setDefinition('cache.adapter.apcu_adapter', $apcuAdapter);
83+
84+
$doctrineAdapter = new Definition('Symfony\Component\Cache\Adapter\DoctrineAdapter');
85+
$doctrineAdapter->setAbstract(true);
86+
$container->setDefinition('cache.adapter.doctrine_adapter', $doctrineAdapter);
87+
88+
$filesystemAdapter = new Definition('Symfony\Component\Cache\Adapter\FilesystemAdapter');
89+
$filesystemAdapter->setAbstract(true);
90+
$container->setDefinition('cache.adapter.fs_adapter', $filesystemAdapter);
91+
92+
$foo = new Definition();
93+
$foo->setArguments(array(new Reference('cache.adapter.apcu_adapter')));
94+
$container->setDefinition('foo', $foo);
95+
96+
$bar = new Definition();
97+
$bar->addMethodCall('setCache', array(new Reference('cache.adapter.doctrine_adapter')));
98+
$container->setDefinition('bar', $bar);
99+
100+
$baz = new Definition();
101+
$baz->setProperty('cache', new Reference('cache.adapter.fs_adapter'));
102+
$container->setDefinition('baz', $baz);
103+
104+
return $container;
105+
}
106+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
$container->loadFromExtension('framework', array(
4+
'cache' => array(
5+
'adapters' => array(
6+
'foo' => array(
7+
'type' => 'apcu',
8+
),
9+
'bar' => array(
10+
'type' => 'doctrine',
11+
),
12+
'baz' => array(
13+
'type' => 'filesystem',
14+
),
15+
),
16+
),
17+
));
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?xml version="1.0" ?>
2+
<container xmlns="http://symfony.com/schema/dic/services"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xmlns:framework="http://symfony.com/schema/dic/symfony"
5+
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd
6+
http://symfony.com/schema/dic/symfony http://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
7+
8+
<framework:config>
9+
<framework:cache>
10+
<framework:adapter name="foo" type="apcu" />
11+
<framework:adapter name="bar" type="doctrine" />
12+
<framework:adapter name="baz" type="filesystem" />
13+
</framework:cache>
14+
</framework:config>
15+
</container>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
framework:
2+
cache:
3+
adapters:
4+
foo:
5+
type: apcu
6+
bar:
7+
type: doctrine
8+
baz:
9+
type: filesystem

0 commit comments

Comments
 (0)