8000 feature #18371 [FrameworkBundle] integrate the Cache component (xabbu… · symfony/symfony@0b67fa3 · GitHub
[go: up one dir, main page]

Skip to content

Commit 0b67fa3

Browse files
committed
feature #18371 [FrameworkBundle] integrate the Cache component (xabbuh, nicolas-grekas)
This PR was merged into the 3.1-dev branch. Discussion ---------- [FrameworkBundle] integrate the Cache component | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #17537 | License | MIT | Doc PR | - Last commit is the diff with #17868. Commits ------- 4152634 [FrameworkBundle] Add default pool & system adapter 714b916 [FrameworkBundle] Add & use Psr6CacheClearer 4740c5c [FrameworkBundle] use abstract cache.pool decoration and aliases 92b1a20 [FrameworkBundle] Fix and add tests for cache pool wiring e44bfdc [FrameworkBundle] Add cache-pool tag and wiring 281eafa [FrameworkBundle] Integrate the Cache component bc51fde [Cache] Normalize constructor arguments order
2 parents eb40f16 + 4152634 commit 0b67fa3

28 files changed

+592
-13
lines changed
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
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\DependencyInjection\Compiler\CompilerPassInterface;
15+
use Symfony\Component\DependencyInjection\ContainerBuilder;
16+
use Symfony\Component\DependencyInjection\DefinitionDecorator;
17+
use Symfony\Component\DependencyInjection\Reference;
18+
19+
/**
20+
* @author Nicolas Grekas <p@tchwork.com>
21+
*/
22+
class CachePoolPass implements CompilerPassInterface
23+
{
24+
/**
25+
* {@inheritdoc}
26+
*/
27+
public function process(ContainerBuilder $container)
28+
{
29+
$attributes = array(
30+
'provider',
31+
'namespace',
32+
'default_lifetime',
33+
);
34+
foreach ($container->findTaggedServiceIds('cache.pool') as $id => $tags) {
35+
$adapter = $pool = $container->getDefinition($id);
36+
if ($pool->isAbstract()) {
37+
continue;
38+
}
39+
if (!isset($tags[0]['namespace'])) {
40+
$tags[0]['namespace'] = $this->getNamespace($id);
41+
}
42+
while ($adapter instanceof DefinitionDecorator) {
43+
$adapter = $container->findDefinition($adapter->getParent());
44+
if ($t = $adapter->getTag('cache.pool')) {
45+
$tags[0] += $t[0];
46+
}
47+
}
48+
if (isset($tags[0]['clearer'])) {
49+
$clearer = $container->getDefinition($tags[0]['clearer']);
50+
} else {
51+
$clearer = null;
52+
}
53+
unset($tags[0]['clearer']);
54+
55+
if (isset($tags[0]['provider']) && is_string($tags[0]['provider'])) {
56+
$tags[0]['provider'] = new Reference($tags[0]['provider']);
57+
}
58+
$i = 0;
59+
foreach ($attributes as $attr) {
60+
if (isset($tags[0][$attr])) {
61+
$pool->replaceArgument($i++, $tags[0][$attr]);
62+
}
63+
unset($tags[0][$attr]);
64+
}
65+
if (!empty($tags[0])) {
66+
throw new \InvalidArgumentException(sprintf('Invalid "cache.pool" tag for service "%s": accepted attributes are "clearer", "provider", "namespace" and "default_lifetime", found "%s".', $id, implode('", "', array_keys($tags[0]))));
67+
}
68+
69+
if (null !== $clearer) {
70+
$clearer->addMethodCall('addPool', array(new Reference($id)));
71+
}
72+
}
73+
}
74+
75+
private function getNamespace($id)
76+
{
77+
return substr(str_replace('/', '-', base64_encode(md5('symfony.'.$id, true))), 0, 10);
78+
}
79+
}

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

Lines changed: 36 additions & 0 deletions
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,39 @@ 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+
->addDefaultsIfNotSet()
559+
->fixXmlConfig('pool')
560+
->children()
561+
->arrayNode('pools')
562+
->useAttributeAsKey('name')
563+
->prototype('array')
564+
->children()
565+
->scalarNode('adapter')
566+
->info('The cache pool adapter service to use as template definition.')
567+
->defaultValue('cache.adapter.shared')
568+
->end()
569+
->booleanNode('public')->defaultFalse()->end()
570+
->integerNode('default_lifetime')->end()
571+
->scalarNode('provider')
572+
->info('The service name to use as provider when the specified adapter needs one.')
573+
->end()
574+
->scalarNode('namespace')
575+
->info('The namespace where cached items are stored. Auto-generated by default. Set to false to disable namespacing.')
576+
->end()
577+
->scalarNode('clearer')->defaultValue('cache.default_pools_clearer')->end()
578+
->end()
579+
->end()
580+
->end()
581+
->end()
582+
->end()
583+
->end()
584+
;
585+
}
550586
}

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

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ public function load(array $configs, ContainerBuilder $container)
122122
$this->registerFragmentsConfiguration($config['fragments'], $container, $loader);
123123
$this->registerTranslatorConfiguration($config['translator'], $container);
124124
$this->registerProfilerConfiguration($config['profiler'], $container, $loader);
125+
$this->registerCacheConfiguration($config['cache'], $container, $loader);
125126

126127
if ($this->isConfigEnabled($container, $config['router'])) {
127128
$this->registerRouterConfiguration($config['router'], $container, $loader);
@@ -1016,6 +1017,28 @@ private function registerPropertyInfoConfiguration(array $config, ContainerBuild
10161017
}
10171018
}
10181019

1020+
private function registerCacheConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader)
1021+
{
1022+
$loader->load('cache_pools.xml');
1023+
1024+
foreach ($config['pools'] as $name => $poolConfig) {
1025+
$poolDefinition = new DefinitionDecorator($poolConfig['adapter']);
1026+
$poolDefinition->setPublic($poolConfig['public']);
1027+
unset($poolConfig['adapter'], $poolConfig['public']);
1028+
1029+
$poolDefinition->addTag('cache.pool', $poolConfig);
1030+
$container->setDefinition('cache.pool.'.$name, $poolDefinition);
1031+
}
1032+
1033+
$this->addClassesToCompile(array(
1034+
'Psr\Cache\CacheItemInterface',
1035+
'Psr\Cache\CacheItemPoolInterface',
1036+
'Symfony\Component\Cache\Adapter\AdapterInterface',
1037+
'Symfony\Component\Cache\Adapter\AbstractAdapter',
1038+
'Symfony\Component\Cache\CacheItem',
1039+
));
1040+
}
1041+
10191042
/**
10201043
* Gets a hash of the kernel root directory.
10211044
*

src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php

Lines changed: 2 additions & 0 deletions
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\CachePoolPass;
1718
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ControllerArgumentValueResolverPass;
1819
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\FormPass;
1920
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\PropertyInfoPass;
@@ -89,6 +90,7 @@ public function build(ContainerBuilder $container)
8990
$container->addCompilerPass(new SerializerPass());
9091
$container->addCompilerPass(new PropertyInfoPass());
9192
$container->addCompilerPass(new ControllerArgumentValueResolverPass());
93+
$container->addCompilerPass(new CachePoolPass());
9294

9395
if ($container->getParameter('kernel.debug')) {
9496
$container->addCompilerPass(new UnusedTagsPass(), PassConfig::TYPE_AFTER_REMOVING);
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?xml version="1.0" ?>
2+
3+
<container xmlns="http://symfony.com/schema/dic/services"
4+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5+
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
6+
7+
<services>
8+
9+
<service id="cache.default_pools_clearer" class="Symfony\Component\HttpKernel\CacheClearer\Psr6CacheClearer" public="false">
10+
<tag name="kernel.cache_clearer" />
11+
</service>
12+
13+
<service id="cache.adapter.shared" alias="cache.adapter.filesystem" />
14+
<service id="cache.adapter.local" alias="cache.adapter.filesystem" />
15+
16+
<service id="cache.pool.shared" parent="cache.adapter.shared">
17+
<tag name="cache.pool" clearer="cache.default_pools_clearer" />
18+
</service>
19+
20+
<service id="cache.pool.local" parent="cache.adapter.local">
21+
<tag name="cache.pool" clearer="cache.default_pools_clearer" />
22+
</service>
23+
24+
<service id="cache.adapter.apcu" class="Symfony\Component\Cache\Adapter\ApcuAdapter" abstract="true">
25+
<argument /> <!-- namespace -->
26+
<argument /> <!-- default lifetime -->
27+
</service>
28+
29+
<service id="cache.adapter.doctrine" class="Symfony\Component\Cache\Adapter\DoctrineAdapter" abstract="true">
30+
<argument /> <!-- Doctrine provider service -->
31+
<argument /> <!-- namespace -->
32+
<argument /> <!-- default lifetime -->
33+
</service>
34+
35+
<service id="cache.adapter.filesystem" class="Symfony\Component\Cache\Adapter\FilesystemAdapter" abstract="true">
36+
<argument /> <!-- namespace -->
37+
<argument /> <!-- default lifetime -->
38+
<argument>%kernel.cache_dir%/pools</argument>
39+
</service>
40+
41+
<service id="cache.adapter.psr6" c 10000 lass="Symfony\Component\Cache\Adapter\ProxyAdapter" abstract="true">
42+
<argument /> <!-- PSR-6 provider service -->
43+
<argument /> <!-- namespace -->
44+
<argument /> <!-- default lifetime -->
45+
</service>
46+
47+
<service id="cache.adapter.redis" class="Symfony\Component\Cache\Adapter\RedisAdapter" abstract="true">
48+
<argument /> <!-- Redis connection object -->
49+
<argument /> <!-- namespace -->
50+
<argument /> <!-- default lifetime -->
51+
</service>
52+
53+
</services>
54+
</container>

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

Lines changed: 16 additions & 0 deletions
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,19 @@
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="pool" type="cache_pool" />
210+
</xsd:choice>
211+
</xsd:complexType>
212+
213+
<xsd:complexType name="cache_pool">
214+
<xsd:attribute name="name" type="xsd:string" use="required" />
215+
<xsd:attribute name="adapter" type="xsd:string" />
216+
<xsd:attribute name="public" type="xsd:boolean" />
217+
<xsd:attribute name="default-lifetime" type="xsd:integer" />
218+
<xsd:attribute name="provider" type="xsd:string" />
219+
<xsd:attribute name="clearer" type="xsd:string" />
220+
</xsd:complexType>
205221
</xsd:schema>
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
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\CachePoolPass;
15+
use Symfony\Component\DependencyInjection\ContainerBuilder;
16+
use Symfony\Component\DependencyInjection\Definition;
17+
use Symfony\Component\DependencyInjection\DefinitionDecorator;
18+
use Symfony\Component\DependencyInjection\Reference;
19+
20+
class CachePoolPassTest extends \PHPUnit_Framework_TestCase
21+
{
22+
private $cachePoolPass;
23+
24+
protected function setUp()
25+
{
26+
$this->cachePoolPass = new CachePoolPass();
27+
}
28+
29+
public function testNamespaceArgumentIsReplaced()
30+
{
31+
$container = new ContainerBuilder();
32+
$adapter = new Definition();
33+
$adapter->setAbstract(true);
34+
$adapter->addTag('cache.pool');
35+
$container->setDefinition('app.cache_adapter', $adapter);
36+
$container->setAlias('app.cache_adapter_alias', 'app.cache_adapter');
37+
$cachePool = new DefinitionDecorator('app.cache_adapter_alias');
38+
$cachePool->addArgument(null);
39+
$cachePool->addTag('cache.pool');
40+
$container->setDefinition('app.cache_pool', $cachePool);
41+
42+
$this->cachePoolPass->process($container);
43+
44+
$this->assertSame('yRnzIIVLvL', $cachePool->getArgument(0));
45+
}
46+
47+
public function testArgsAreReplaced()
48+
{
49+
$container = new ContainerBuilder();
50+
$cachePool = new Definition();
51+
$cachePool->addTag('cache.pool', array(
52+
'provider' => 'foobar',
53+
'default_lifetime' => 3,
54+
));
55+
$cachePool->addArgument(null);
56+
$cachePool->addArgument(null);
57+
$cachePool->addArgument(null);
58+
$container->setDefinition('app.cache_pool', $cachePool);
59+
60+
$this->cachePoolPass->process($container);
61+
62+
$this->assertInstanceOf(Reference::class, $cachePool->getArgument(0));
63+
$this->assertSame('foobar', (string) $cachePool->getArgument(0));
64+
$this->assertSame('yRnzIIVLvL', $cachePool->getArgument(1));
65+
$this->assertSame(3, $cachePool->getArgument(2));
66+
}
67+
68+
/**
69+
* @expectedException \InvalidArgumentException
70+
* @expectedExceptionMessage Invalid "cache.pool" tag for service "app.cache_pool": accepted attributes are
71+
*/
72+
public function testThrowsExceptionWhenCachePoolTagHasUnknownAttributes()
73+
{
74+
$container = new ContainerBuilder();
75+
$adapter = new Definition();
76+
$adapter->setAbstract(true);
77+
$adapter->addTag('cache.pool');
78+
$container->setDefinition('app.cache_adapter', $adapter);
79+
$cachePool = new DefinitionDecorator('app.cache_adapter');
80+
$cachePool->addTag('cache.pool', array('foobar' => 123));
81+
$container->setDefinition('app.cache_pool', $cachePool);
82+
83+
$this->cachePoolPass->process($container);
84+
}
85+
}

src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,9 @@ protected static function getBundleDefaultConfig()
265265
'base_urls' => array(),
266266
'packages' => array(),
267267
),
268+
'cache' => array(
269+
'pools' => array(),
270+
),
268271
);
269272
}
270273
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
$container->loadFromExtension('framework', array(
4+
'cache' => array(
5+
'pools' => array(
6+
'foo' => array(
7+
'adapter' => 'cache.adapter.apcu',
8+
'default_lifetime' => 30,
9+
),
10+
'bar' => array(
11+
'adapter' => 'cache.adapter.doctrine',
12+
'default_lifetime' => 5,
13+
'provider' => 'app.doctrine_cache_provider',
14+
),
15+
'baz' => array(
16+
'adapter' => 'cache.adapter.filesystem',
17+
'default_lifetime' => 7,
18+
),
19+
'foobar' => array(
20+
'adapter' => 'cache.adapter.psr6',
21+
'default_lifetime' => 10,
22+
'provider' => 'app.cache_pool',
23+
),
24+
'def' => array(
25+
'default_lifetime' => 11,
26+
),
27+
),
28+
),
29+
));

0 commit comments

Comments
 (0)
0