[FrameworkBundle] Add cache-pool tag and wiring
This commit is contained in:
parent
281eafa5cb
commit
e44bfdcde9
@ -1,88 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* 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;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
|
||||
/**
|
||||
* @author Christian Flothmann <christian.flothmann@xabbuh.de>
|
||||
*/
|
||||
class CacheAdapterPass implements CompilerPassInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
$adapters = array();
|
||||
|
||||
foreach ($container->findTaggedServiceIds('cache.adapter') as $id => $tags) {
|
||||
foreach ($tags as $attributes) {
|
||||
$adapters[$attributes['id']] = array(
|
||||
'definition_id' => $id,
|
||||
'namespace_argument_index' => isset($attributes['namespace-arg-index']) ? $attributes['namespace-arg-index'] : null,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($container->getDefinitions() as $id => $definition) {
|
||||
$definition->setArguments($this->resolveArguments($adapters, $id, $definition->getArguments()));
|
||||
|
||||
$calls = $definition->getMethodCalls();
|
||||
|
||||
foreach ($calls as $index => $call) {
|
||||
$calls[$index] = array($call[0], $this->resolveArguments($adapters, $id, $call[1]));
|
||||
}
|
||||
|
||||
$definition->setMethodCalls($calls);
|
||||
|
||||
$definition->setProperties($this->resolveArguments($adapters, $id, $definition->getProperties()));
|
||||
}
|
||||
}
|
||||
|
||||
private function resolveArguments(array $adapters, $id, array $arguments)
|
||||
{
|
||||
foreach ($arguments as $index => $argument) {
|
||||
if ($argument instanceof Reference) {
|
||||
$arguments[$index] = $this->createCacheAdapter($adapters, $id, $argument);
|
||||
}
|
||||
}
|
||||
|
||||
return $arguments;
|
||||
}
|
||||
|
||||
private function createCacheAdapter(array $adapters, $serviceId, Reference $argument)
|
||||
{
|
||||
$adapterId = (string) $argument;
|
||||
|
||||
if (0 !== strpos($adapterId, 'cache.adapter.')) {
|
||||
return $argument;
|
||||
}
|
||||
|
||||
$name = substr($adapterId, 14);
|
||||
|
||||
if (!isset($adapters[$name])) {
|
||||
throw new \InvalidArgumentException(sprintf('The cache adapter "%s" is not configured.', $name));
|
||||
}
|
||||
|
||||
$adapter = new DefinitionDecorator($adapters[$name]['definition_id']);
|
||||
|
||||
if (null !== $adapters[$name]['namespace_argument_index']) {
|
||||
$adapter->replaceArgument($adapters[$name]['namespace_argument_index'], sha1($serviceId));
|
||||
}
|
||||
|
||||
return $adapter;
|
||||
}
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* 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;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
|
||||
/**
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*/
|
||||
class CachePoolPass implements CompilerPassInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
foreach ($container->findTaggedServiceIds('cache.pool') as $id => $tags) {
|
||||
$pool = $container->getDefinition($id);
|
||||
$namespaceArgIndex = isset($tags[0]['namespace_arg_index']) ? $tags[0]['namespace_arg_index'] : -1;
|
||||
|
||||
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->getTag('cache.adapter'));
|
||||
|
||||
$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) {
|
||||
$pool->replaceArgument($namespaceArgIndex, $this->getNamespace($id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function getNamespace($id)
|
||||
{
|
||||
return substr(str_replace('/', '-', base64_encode(md5('symfony.'.$id, true)), 0, 10));
|
||||
}
|
||||
}
|
@ -555,40 +555,22 @@ class Configuration implements ConfigurationInterface
|
||||
->children()
|
||||
->arrayNode('cache')
|
||||
->info('Cache configuration')
|
||||
->fixXmlConfig('adapter')
|
||||
->fixXmlConfig('pool')
|
||||
->children()
|
||||
->arrayNode('adapters')
|
||||
->arrayNode('pool')
|
||||
->useAttributeAsKey('name')
|
||||
->prototype('array')
|
||||
->beforeNormalization()
|
||||
->always(function ($v) {
|
||||
if (!isset($v['options'])) {
|
||||
$v['options'] = array();
|
||||
}
|
||||
|
||||
foreach ($v as $key => $value) {
|
||||
if (!in_array($key, array('type', 'name', 'options'))) {
|
||||
$v['options'][$key] = $value;
|
||||
unset($v[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
return $v;
|
||||
})
|
||||
->end()
|
||||
->children()
|
||||
->enumNode('type')
|
||||
->info('The cache adapter type (one of "apcu", "doctrine", "filesystem")')
|
||||
->info('The cache pool type (one of "apcu", "doctrine", "psr6" or "filesystem")')
|
||||
->isRequired()
|
||||
->values(array('apcu', 'doctrine', 'filesystem'))
|
||||
->end()
|
||||
->arrayNode('options')
|
||||
->children()
|
||||
->integerNode('default_lifetime')->end()
|
||||
->scalarNode('cache_provider_service')->end()
|
||||
->scalarNode('directory')->end()
|
||||
->end()
|
||||
->values(array('apcu', 'doctrine', 'psr6', 'filesystem'))
|
||||
->end()
|
||||
->integerNode('default_lifetime')->default(0)->end()
|
||||
->scalarNode('cache_provider_service')->defaultNull()->end()
|
||||
->scalarNode('directory')->defaultNull()->end()
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
|
@ -12,9 +12,6 @@
|
||||
namespace Symfony\Bundle\FrameworkBundle\DependencyInjection;
|
||||
|
||||
use Doctrine\Common\Annotations\Reader;
|
||||
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\ContainerInterface;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
@ -1023,43 +1020,24 @@ class FrameworkExtension extends Extension
|
||||
}
|
||||
}
|
||||
|
||||
private function registerCacheConfiguration(array $config, ContainerBuilder $container)
|
||||
private function registerCacheConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader)
|
||||
{
|
||||
foreach ($config['adapters'] as $name => $adapter) {
|
||||
$class = null;
|
||||
$arguments = array();
|
||||
$namespaceArgumentIndex = null;
|
||||
if (!empty($config['pool'])) {
|
||||
$loader->load('cache_adapters.xml');
|
||||
}
|
||||
|
||||
switch ($adapter['type']) {
|
||||
case 'apcu':
|
||||
$class = ApcuAdapter::class;
|
||||
$arguments[] = null;
|
||||
$arguments[] = isset($adapter['options']['default_lifetime']) ? $adapter['options']['default_lifetime'] : 0;
|
||||
$namespaceArgumentIndex = 0;
|
||||
break;
|
||||
case 'doctrine':
|
||||
$class = DoctrineAdapter::class;
|
||||
$arguments[] = isset($adapter['options']['cache_provider_service']) ? new Reference($adapter['options']['cache_provider_service']) : null;
|
||||
$arguments[] = isset($adapter['options']['default_lifetime']) ? $adapter['options']['default_lifetime'] : null;
|
||||
break;
|
||||
case 'filesystem':
|
||||
$class = FilesystemAdapter::class;
|
||||
$arguments[] = isset($adapter['options']['directory']) ? $adapter['options']['directory'] : null;
|
||||
$arguments[] = isset($adapter['options']['default_lifetime']) ? $adapter['options']['default_lifetime'] : null;
|
||||
break;
|
||||
foreach ($config['pool'] 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']);
|
||||
}
|
||||
|
||||
$tagAttributes = array('id' => $name);
|
||||
|
||||
if (null !== $namespaceArgumentIndex) {
|
||||
$tagAttributes['namespace-arg-index'] = $namespaceArgumentIndex;
|
||||
}
|
||||
|
||||
$adapterDefinition = new Definition($class);
|
||||
$adapterDefinition->setArguments($arguments);
|
||||
$adapterDefinition->setAbstract(true);
|
||||
$adapterDefinition->addTag('cache.adapter', $tagAttributes);
|
||||
$container->setDefinition('cache.adapter.'.$name, $adapterDefinition);
|
||||
$poolDefinition->addTag('cache.pool');
|
||||
$container->setDefinition('cache.pool.'.$name, $poolDefinition);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,7 @@ namespace Symfony\Bundle\FrameworkBundle;
|
||||
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\CacheAdapterPass;
|
||||
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\CachePoolPass;
|
||||
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ControllerArgumentValueResolverPass;
|
||||
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\FormPass;
|
||||
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\PropertyInfoPass;
|
||||
@ -90,7 +90,7 @@ class FrameworkBundle extends Bundle
|
||||
$container->addCompilerPass(new SerializerPass());
|
||||
$container->addCompilerPass(new PropertyInfoPass());
|
||||
$container->addCompilerPass(new ControllerArgumentValueResolverPass());
|
||||
$container->addCompilerPass(new CacheAdapterPass());
|
||||
$container->addCompilerPass(new CachePoolPass());
|
||||
|
||||
if ($container->getParameter('kernel.debug')) {
|
||||
$container->addCompilerPass(new UnusedTagsPass(), PassConfig::TYPE_AFTER_REMOVING);
|
||||
|
@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" ?>
|
||||
|
||||
<container xmlns="http://symfony.com/schema/dic/services"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
|
||||
|
||||
<services>
|
||||
|
||||
<service id="cache.adapter.apcu" class="Symfony\Component\Cache\Adapter\ApcuAdapter" abstract="true">
|
||||
<tag name="cache.adapter" namespace-arg-index="0"></tag>
|
||||
<argument /> <!-- namespace -->
|
||||
<argument /> <!-- default lifetime -->
|
||||
</service>
|
||||
|
||||
<service id="cache.adapter.doctrine" class="Symfony\Component\Cache\Adapter\DoctrineAdapter" abstract="true">
|
||||
<tag name="cache.adapter" namespace-arg-index="2"></tag>
|
||||
<argument /> <!-- doctrine provider service -->
|
||||
<argument /> <!-- default lifetime -->
|
||||
<argument /> <!-- namespace -->
|
||||
</service>
|
||||
|
||||
<service id="cache.adapter.psr6" class="Symfony\Component\Cache\Adapter\ProxyAdapter" abstract="true">
|
||||
<tag name="cache.adapter" namespace-arg-index="2"></tag>
|
||||
<argument /> <!-- PSR-6 provider service -->
|
||||
<argument /> <!-- default lifetime -->
|
||||
<argument /> <!-- namespace -->
|
||||
</service>
|
||||
|
||||
<service id="cache.adapter.filesystem" class="Symfony\Component\Cache\Adapter\FilesystemAdapter" abstract="true">
|
||||
<tag name="cache.adapter" namespace-arg-index="2"></tag>
|
||||
<argument>%kernel.cache_dir%</argument>
|
||||
<argument /> <!-- default lifetime -->
|
||||
<argument /> <!-- namespace -->
|
||||
</service>
|
||||
|
||||
</services>
|
||||
</container>
|
@ -206,11 +206,11 @@
|
||||
|
||||
<xsd:complexType name="cache">
|
||||
<xsd:choice minOccurs="1" maxOccurs="unbounded">
|
||||
<xsd:element name="adapter" type="cache_adapter" />
|
||||
<xsd:element name="pool" type="cache_pool" />
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="cache_adapter">
|
||||
<xsd:complexType name="cache_pool">
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
<xsd:attribute name="type" type="xsd:string" use="required" />
|
||||
<xsd:attribute name="default-lifetime" type="xsd:integer" />
|
||||
|
@ -11,24 +11,24 @@
|
||||
|
||||
namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\CacheAdapterPass;
|
||||
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\CachePoolPass;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
|
||||
class CacheAdapterPassTest extends \PHPUnit_Framework_TestCase
|
||||
class CachePoolPassTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
private $cacheAdapterPass;
|
||||
private $cachePoolPass;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->cacheAdapterPass = new CacheAdapterPass();
|
||||
$this->cachePoolPass = new CachePoolPass();
|
||||
}
|
||||
|
||||
public function testAdapterIsInjectedIntoConstructorArguments()
|
||||
{
|
||||
$container = $this->initializeContainer();
|
||||
$this->cacheAdapterPass->process($container);
|
||||
$this->cachePoolPass->process($container);
|
||||
$adapter = $container->getDefinition('foo')->getArgument(0);
|
||||
|
||||
$this->assertInstanceOf('Symfony\Component\DependencyInjection\DefinitionDecorator', $adapter);
|
||||
@ -40,7 +40,7 @@ class CacheAdapterPassTest extends \PHPUnit_Framework_TestCase
|
||||
public function testAdapterIsInjectedIntoMethodArguments()
|
||||
{
|
||||
$container = $this->initializeContainer();
|
||||
$this->cacheAdapterPass->process($container);
|
||||
$this->cachePoolPass->process($container);
|
||||
$methodCalls = $container->getDefinition('bar')->getMethodCalls();
|
||||
$arguments = $methodCalls[0][1];
|
||||
$adapter = $arguments[0];
|
||||
@ -53,7 +53,7 @@ class CacheAdapterPassTest extends \PHPUnit_Framework_TestCase
|
||||
public function testAdapterIsInjectIntoProperties()
|
||||
{
|
||||
$container = $this->initializeContainer();
|
||||
$this->cacheAdapterPass->process($container);
|
||||
$this->cachePoolPass->process($container);
|
||||
$properties = $container->getDefinition('baz')->getProperties();
|
||||
$adapter = $properties['cache'];
|
||||
|
||||
@ -70,7 +70,7 @@ class CacheAdapterPassTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
$container->setDefinition('foo', new Definition('Foo', array(new Reference('cache.adapter.bar'))));
|
||||
$this->cacheAdapterPass->process($container);
|
||||
$this->cachePoolPass->process($container);
|
||||
}
|
||||
|
||||
private function initializeContainer()
|
Reference in New Issue
Block a user