diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php
new file mode 100644
index 0000000000000..395169caaca47
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php
@@ -0,0 +1,66 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;
+
+use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\DefinitionDecorator;
+
+/**
+ * @author Nicolas Grekas
+ */
+class CachePoolPass implements CompilerPassInterface
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function process(ContainerBuilder $container)
+ {
+ foreach ($container->findTaggedServiceIds('cache.pool') as $id => $tags) {
+ $pool = $container->getDefinition($id);
+
+ if (!$pool instanceof DefinitionDecorator) {
+ throw new \InvalidArgumentException(sprintf('Services tagged with "cache.pool" must have a parent service but "%s" has none.', $id));
+ }
+
+ $adapter = $pool;
+
+ do {
+ $adapterId = $adapter->getParent();
+ $adapter = $container->getDefinition($adapterId);
+ } while ($adapter instanceof DefinitionDecorator && !$adapter->hasTag('cache.adapter'));
+
+ if (!$adapter->hasTag('cache.adapter')) {
+ throw new \InvalidArgumentException(sprintf('Services tagged with "cache.pool" must have a parent service tagged with "cache.adapter" but "%s" has none.', $id));
+ }
+
+ $tags = $adapter->getTag('cache.adapter');
+
+ if (!isset($tags[0]['namespace_arg_index'])) {
+ throw new \InvalidArgumentException(sprintf('Invalid "cache.adapter" tag for service "%s": attribute "namespace_arg_index" is missing.', $adapterId));
+ }
+
+ if (!$adapter->isAbstract()) {
+ throw new \InvalidArgumentException(sprintf('Services tagged as "cache.adapter" must be abstract: "%s" is not.', $adapterId));
+ }
+
+ if (0 <= $namespaceArgIndex = $tags[0]['namespace_arg_index']) {
+ $pool->replaceArgument($namespaceArgIndex, $this->getNamespace($id));
+ }
+ }
+ }
+
+ private function getNamespace($id)
+ {
+ return substr(str_replace('/', '-', base64_encode(md5('symfony.'.$id, true))), 0, 10);
+ }
+}
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
index ab55275b20b2c..83981d8c76603 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
@@ -114,6 +114,7 @@ public function getConfigTreeBuilder()
$this->addSerializerSection($rootNode);
$this->addPropertyAccessSection($rootNode);
$this->addPropertyInfoSection($rootNode);
+ $this->addCacheSection($rootNode);
return $treeBuilder;
}
@@ -547,4 +548,33 @@ private function addPropertyInfoSection(ArrayNodeDefinition $rootNode)
->end()
;
}
+
+ private function addCacheSection(ArrayNodeDefinition $rootNode)
+ {
+ $rootNode
+ ->children()
+ ->arrayNode('cache')
+ ->info('Cache configuration')
+ ->fixXmlConfig('pool')
+ ->children()
+ ->arrayNode('pools')
+ ->useAttributeAsKey('name')
+ ->prototype('array')
+ ->children()
+ ->enumNode('type')
+ ->info('The cache pool type (one of "apcu", "doctrine", "psr6" or "filesystem")')
+ ->isRequired()
+ ->values(array('apcu', 'doctrine', 'psr6', 'filesystem'))
+ ->end()
+ ->integerNode('default_lifetime')->defaultValue(0)->end()
+ ->scalarNode('cache_provider_service')->defaultNull()->end()
+ ->scalarNode('directory')->defaultNull()->end()
+ ->end()
+ ->end()
+ ->end()
+ ->end()
+ ->end()
+ ->end()
+ ;
+ }
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
index 324915ecb211d..956610f410c85 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
@@ -138,6 +138,10 @@ public function load(array $configs, ContainerBuilder $container)
$this->registerPropertyInfoConfiguration($config['property_info'], $container, $loader);
}
+ if (isset($config['cache'])) {
+ $this->registerCacheConfiguration($config['cache'], $container, $loader);
+ }
+
$loader->load('debug_prod.xml');
$definition = $container->findDefinition('debug.debug_handlers_listener');
@@ -1017,6 +1021,27 @@ private function registerPropertyInfoConfiguration(array $config, ContainerBuild
}
}
+ private function registerCacheConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader)
+ {
+ if (!empty($config['pools'])) {
+ $loader->load('cache_adapters.xml');
+ }
+
+ foreach ($config['pools'] as $name => $poolConfig) {
+ $poolDefinition = new DefinitionDecorator('cache.adapter.'.$poolConfig['type']);
+ $poolDefinition->replaceArgument(1, $poolConfig['default_lifetime']);
+
+ if ('doctrine' === $poolConfig['type'] || 'psr6' === $poolConfig['type']) {
+ $poolDefinition->replaceArgument(0, new Reference($poolConfig['cache_provider_service']));
+ } elseif ('filesystem' === $poolConfig['type'] && isset($poolConfig['directory'][0])) {
+ $poolDefinition->replaceArgument(0, $poolConfig['directory']);
+ }
+
+ $poolDefinition->addTag('cache.pool');
+ $container->setDefinition('cache.pool.'.$name, $poolDefinition);
+ }
+ }
+
/**
* Gets a hash of the kernel root directory.
*
diff --git a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php
index 94062da0039f5..9c0c91eda6b1f 100644
--- a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php
+++ b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php
@@ -14,6 +14,7 @@
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddConstraintValidatorsPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddValidatorInitializersPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddConsoleCommandPass;
+use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\CachePoolPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\FormPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\PropertyInfoPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TemplatingPass;
@@ -87,6 +88,7 @@ public function build(ContainerBuilder $container)
$container->addCompilerPass(new FragmentRendererPass(), PassConfig::TYPE_AFTER_REMOVING);
$container->addCompilerPass(new SerializerPass());
$container->addCompilerPass(new PropertyInfoPass());
+ $container->addCompilerPass(new CachePoolPass());
if ($container->getParameter('kernel.debug')) {
$container->addCompilerPass(new UnusedTagsPass(), PassConfig::TYPE_AFTER_REMOVING);
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache_adapters.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache_adapters.xml
new file mode 100644
index 0000000000000..9c49c8672de8d
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache_adapters.xml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ %kernel.cache_dir%
+
+
+
+
+
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd
index cead2295ed1ac..cee9299e44e58 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd
@@ -25,6 +25,7 @@
+
@@ -202,4 +203,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/CachePoolPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/CachePoolPassTest.php
new file mode 100644
index 0000000000000..f07c04c7e0767
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/CachePoolPassTest.php
@@ -0,0 +1,108 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler;
+
+use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\CachePoolPass;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Definition;
+use Symfony\Component\DependencyInjection\DefinitionDecorator;
+
+class CachePoolPassTest extends \PHPUnit_Framework_TestCase
+{
+ private $cachePoolPass;
+
+ protected function setUp()
+ {
+ $this->cachePoolPass = new CachePoolPass();
+ }
+
+ public function testNamespaceArgumentIsReplaced()
+ {
+ $container = new ContainerBuilder();
+ $adapter = new Definition();
+ $adapter->setAbstract(true);
+ $adapter->addTag('cache.adapter', array('namespace_arg_index' => 0));
+ $container->setDefinition('app.cache_adapter', $adapter);
+ $cachePool = new DefinitionDecorator('app.cache_adapter');
+ $cachePool->addArgument(null);
+ $cachePool->addTag('cache.pool');
+ $container->setDefinition('app.cache_pool', $cachePool);
+
+ $this->cachePoolPass->process($container);
+
+ $this->assertSame('yRnzIIVLvL', $cachePool->getArgument(0));
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage Services tagged with "cache.pool" must have a parent service but "app.cache_pool" has none.
+ */
+ public function testThrowsExceptionWhenCachePoolHasNoParentDefinition()
+ {
+ $container = new ContainerBuilder();
+ $cachePool = new Definition();
+ $cachePool->addTag('cache.pool');
+ $container->setDefinition('app.cache_pool', $cachePool);
+
+ $this->cachePoolPass->process($container);
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage Services tagged with "cache.pool" must have a parent service tagged with "cache.adapter" but "app.cache_pool" has none.
+ */
+ public function testThrowsExceptionWhenCachePoolIsNotBasedOnAdapter()
+ {
+ $container = new ContainerBuilder();
+ $container->register('app.cache_adapter');
+ $cachePool = new DefinitionDecorator('app.cache_adapter');
+ $cachePool->addTag('cache.pool');
+ $container->setDefinition('app.cache_pool', $cachePool);
+
+ $this->cachePoolPass->process($container);
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage Invalid "cache.adapter" tag for service "app.cache_adapter": attribute "namespace_arg_index" is missing.
+ */
+ public function testThrowsExceptionWhenCacheAdapterDefinesNoNamespaceArgument()
+ {
+ $container = new ContainerBuilder();
+ $adapter = new Definition();
+ $adapter->setAbstract(true);
+ $adapter->addTag('cache.adapter');
+ $container->setDefinition('app.cache_adapter', $adapter);
+ $cachePool = new DefinitionDecorator('app.cache_adapter');
+ $cachePool->addTag('cache.pool');
+ $container->setDefinition('app.cache_pool', $cachePool);
+
+ $this->cachePoolPass->process($container);
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage Services tagged as "cache.adapter" must be abstract: "app.cache_adapter" is not.
+ */
+ public function testThrowsExceptionWhenCacheAdapterIsNotAbstract()
+ {
+ $container = new ContainerBuilder();
+ $adapter = new Definition();
+ $adapter->addTag('cache.adapter', array('namespace_arg_index' => 0));
+ $container->setDefinition('app.cache_adapter', $adapter);
+ $cachePool = new DefinitionDecorator('app.cache_adapter');
+ $cachePool->addTag('cache.pool');
+ $container->setDefinition('app.cache_pool', $cachePool);
+
+ $this->cachePoolPass->process($container);
+ }
+}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/cache.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/cache.php
new file mode 100644
index 0000000000000..63e5441293f60
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/cache.php
@@ -0,0 +1,27 @@
+loadFromExtension('framework', array(
+ 'cache' => array(
+ 'pools' => array(
+ 'foo' => array(
+ 'type' => 'apcu',
+ 'default_lifetime' => 30,
+ ),
+ 'bar' => array(
+ 'type' => 'doctrine',
+ 'default_lifetime' => 5,
+ 'cache_provider_service' => 'app.doctrine_cache_provider',
+ ),
+ 'baz' => array(
+ 'type' => 'filesystem',
+ 'default_lifetime' => 7,
+ 'directory' => 'app/cache/psr',
+ ),
+ 'foobar' => array(
+ 'type' => 'psr6',
+ 'default_lifetime' => 10,
+ 'cache_provider_service' => 'app.cache_pool',
+ ),
+ ),
+ ),
+));
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/cache.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/cache.xml
new file mode 100644
index 0000000000000..f3d26f7380290
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/cache.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/cache.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/cache.yml
new file mode 100644
index 0000000000000..0d45b13527161
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/cache.yml
@@ -0,0 +1,18 @@
+framework:
+ cache:
+ pools:
+ foo:
+ type: apcu
+ default_lifetime: 30
+ bar:
+ type: doctrine
+ default_lifetime: 5
+ cache_provider_service: app.doctrine_cache_provider
+ baz:
+ type: filesystem
+ default_lifetime: 7
+ directory: app/cache/psr
+ foobar:
+ type: psr6
+ default_lifetime: 10
+ cache_provider_service: app.cache_pool
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php
index 55d9a16e77e5c..93478df449b99 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php
@@ -13,6 +13,9 @@
use Symfony\Bundle\FrameworkBundle\Tests\TestCase;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\FrameworkExtension;
+use Symfony\Component\Cache\Adapter\ApcuAdapter;
+use Symfony\Component\Cache\Adapter\DoctrineAdapter;
+use Symfony\Component\Cache\Adapter\FilesystemAdapter;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\DefinitionDecorator;
use Symfony\Component\DependencyInjection\Loader\ClosureLoader;
@@ -568,6 +571,16 @@ public function testPropertyInfoEnabled()
$this->assertTrue($container->has('property_info'));
}
+ public function testCachePoolServices()
+ {
+ $container = $this->createContainerFromFile('cache');
+
+ $this->assertCachePoolServiceDefinitionIsCreated($container, 'foo', 'apcu', array('index_1' => 30), 0);
+ $this->assertCachePoolServiceDefinitionIsCreated($container, 'bar', 'doctrine', array('index_0' => new Reference('app.doctrine_cache_provider'), 'index_1' => 5));
+ $this->assertCachePoolServiceDefinitionIsCreated($container, 'baz', 'filesystem', array('index_0' => 'app/cache/psr', 'index_1' => 7));
+ $this->assertCachePoolServiceDefinitionIsCreated($container, 'foobar', 'psr6', array('index_0' => new Reference('app.cache_pool'), 'index_1' => 10));
+ }
+
protected function createContainer(array $data = array())
{
return new ContainerBuilder(new ParameterBag(array_merge(array(
@@ -636,4 +649,39 @@ private function assertVersionStrategy(ContainerBuilder $container, Reference $r
$this->assertEquals($format, $versionStrategy->getArgument(1));
}
}
+
+ private function assertCachePoolServiceDefinitionIsCreated(ContainerBuilder $container, $name, $type, array $arguments, $namespaceArgumentIndex = null)
+ {
+ $id = 'cache.pool.'.$name;
+
+ $this->assertTrue($container->has($id), sprintf('Service definition "%s" for cache pool of type "%s" is registered', $id, $type));
+
+ $poolDefinition = $container->getDefinition($id);
+
+ $this->assertInstanceOf(DefinitionDecorator::class, $poolDefinition, sprintf('Cache pool "%s" is based on an abstract cache adapter.', $name));
+ $this->assertEquals($arguments, $poolDefinition->getArguments());
+
+ $adapterDefinition = $container->getDefinition($poolDefinition->getParent());
+
+ switch ($type) {
+ case 'apcu':
+ $this->assertSame(ApcuAdapter::class, $adapterDefinition->getClass());
+ break;
+ case 'doctrine':
+ $this->assertSame(DoctrineAdapter::class, $adapterDefinition->getClass());
+ break;
+ case 'filesystem':
+ $this->assertSame(FilesystemAdapter::class, $adapterDefinition->getClass());
+ break;
+ }
+
+ $this->assertTrue($adapterDefinition->hasTag('cache.adapter'), sprintf('Service definition "%s" is tagged with the "cache.adapter" tag.', $id));
+
+ $tag = $adapterDefinition->getTag('cache.adapter');
+
+ if (null !== $namespaceArgumentIndex) {
+ $this->assertTrue(isset($tag[0]['namespace-arg-index']), 'The namespace argument index is given by the "namespace-arg-index" attribute of the "cache.adapter" tag.');
+ $this->assertSame($namespaceArgumentIndex, $tag[0]['namespace-arg-index'], 'The namespace argument index is given by the "namespace-arg-index" attribute of the "cache.adapter" tag.');
+ }
+ }
}
pFad - Phonifier reborn
Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies:
Alternative Proxy
pFad Proxy
pFad v3 Proxy
pFad v4 Proxy