From bc51fdeec365fecf24b50c41598e64199de0d5df Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 1 Apr 2016 12:55:00 +0200 Subject: [PATCH 1/7] [Cache] Normalize constructor arguments order --- src/Symfony/Component/Cache/Adapter/DoctrineAdapter.php | 2 +- src/Symfony/Component/Cache/Adapter/FilesystemAdapter.php | 2 +- src/Symfony/Component/Cache/Adapter/ProxyAdapter.php | 2 +- src/Symfony/Component/Cache/Tests/Adapter/ChainAdapterTest.php | 2 +- .../Cache/Tests/Adapter/NamespacedProxyAdapterTest.php | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/Cache/Adapter/DoctrineAdapter.php b/src/Symfony/Component/Cache/Adapter/DoctrineAdapter.php index 26dd8e3a86d85..855ae290500ae 100644 --- a/src/Symfony/Component/Cache/Adapter/DoctrineAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/DoctrineAdapter.php @@ -20,7 +20,7 @@ class DoctrineAdapter extends AbstractAdapter { private $provider; - public function __construct(CacheProvider $provider, $defaultLifetime = 0, $namespace = '') + public function __construct(CacheProvider $provider, $namespace = '', $defaultLifetime = 0) { parent::__construct('', $defaultLifetime); $this->provider = $provider; diff --git a/src/Symfony/Component/Cache/Adapter/FilesystemAdapter.php b/src/Symfony/Component/Cache/Adapter/FilesystemAdapter.php index 22708584d8c3a..1fac6c3f65ecb 100644 --- a/src/Symfony/Component/Cache/Adapter/FilesystemAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/FilesystemAdapter.php @@ -20,7 +20,7 @@ class FilesystemAdapter extends AbstractAdapter { private $directory; - public function __construct($directory, $defaultLifetime = 0, $namespace = '') + public function __construct($namespace = '', $defaultLifetime = 0, $directory = null) { parent::__construct('', $defaultLifetime); diff --git a/src/Symfony/Component/Cache/Adapter/ProxyAdapter.php b/src/Symfony/Component/Cache/Adapter/ProxyAdapter.php index 83c3f1baea055..e8befafac91f5 100644 --- a/src/Symfony/Component/Cache/Adapter/ProxyAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/ProxyAdapter.php @@ -28,7 +28,7 @@ class ProxyAdapter implements AdapterInterface private $hits = 0; private $misses = 0; - public function __construct(CacheItemPoolInterface $pool, $defaultLifetime = 0, $namespace = '') + public function __construct(CacheItemPoolInterface $pool, $namespace = '', $defaultLifetime = 0) { $this->pool = $pool; $this->namespace = $this->getId($namespace, true); diff --git a/src/Symfony/Component/Cache/Tests/Adapter/ChainAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/ChainAdapterTest.php index 230a4500f8702..64fb83ce45adb 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/ChainAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/ChainAdapterTest.php @@ -28,7 +28,7 @@ public function createCachePool() $this->skippedTests['testDeferredSaveWithoutCommit'] = 'Fails on HHVM'; } - return new ChainAdapter(array(new ArrayAdapter(), new ExternalAdapter(), new FilesystemAdapter(null))); + return new ChainAdapter(array(new ArrayAdapter(), new ExternalAdapter(), new FilesystemAdapter())); } /** diff --git a/src/Symfony/Component/Cache/Tests/Adapter/NamespacedProxyAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/NamespacedProxyAdapterTest.php index 28898e780ed6f..9b82d91a1af7e 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/NamespacedProxyAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/NamespacedProxyAdapterTest.php @@ -21,6 +21,6 @@ class NamespacedProxyAdapterTest extends ProxyAdapterTest { public function createCachePool() { - return new ProxyAdapter(new ArrayAdapter(), 0, 'foo'); + return new ProxyAdapter(new ArrayAdapter(), 'foo'); } } From 281eafa5cbf6db25d2f48387f1a05530ae192fd7 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sun, 21 Feb 2016 00:25:19 +0100 Subject: [PATCH 2/7] [FrameworkBundle] Integrate the Cache component --- .../Compiler/CacheAdapterPass.php | 88 ++++++++++++++ .../DependencyInjection/Configuration.php | 50 ++++++++ .../FrameworkExtension.php | 47 ++++++++ .../FrameworkBundle/FrameworkBundle.php | 2 + .../Resources/config/schema/symfony-1.0.xsd | 15 +++ .../Compiler/CacheAdapterPassTest.php | 109 ++++++++++++++++++ .../Fixtures/php/cache.php | 28 +++++ .../Fixtures/xml/cache.xml | 15 +++ .../Fixtures/yml/cache.yml | 17 +++ .../FrameworkExtensionTest.php | 47 ++++++++ 10 files changed, 418 insertions(+) create mode 100644 src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CacheAdapterPass.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/CacheAdapterPassTest.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/cache.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/cache.xml create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/cache.yml diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CacheAdapterPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CacheAdapterPass.php new file mode 100644 index 0000000000000..d8453caa89fd4 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CacheAdapterPass.php @@ -0,0 +1,88 @@ + + * + * 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 + */ +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; + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index 69c310a9204a0..6dab7150c9a19 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,53 @@ private function addPropertyInfoSection(ArrayNodeDefinition $rootNode) ->end() ; } + + private function addCacheSection(ArrayNodeDefinition $rootNode) + { + $rootNode + ->children() + ->arrayNode('cache') + ->info('Cache configuration') + ->fixXmlConfig('adapter') + ->children() + ->arrayNode('adapters') + ->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")') + ->isRequired() + ->values(array('apcu', 'doctrine', 'filesystem')) + ->end() + ->arrayNode('options') + ->children() + ->integerNode('default_lifetime')->end() + ->scalarNode('cache_provider_service')->end() + ->scalarNode('directory')->end() + ->end() + ->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 22b8dde6b3d56..74196229905f0 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -12,6 +12,9 @@ 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; @@ -138,6 +141,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->load('debug_prod.xml'); $definition = $container->findDefinition('debug.debug_handlers_listener'); @@ -1016,6 +1023,46 @@ private function registerPropertyInfoConfiguration(array $config, ContainerBuild } } + private function registerCacheConfiguration(array $config, ContainerBuilder $container) + { + foreach ($config['adapters'] as $name => $adapter) { + $class = null; + $arguments = array(); + $namespaceArgumentIndex = null; + + 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; + } + + $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); + } + } + /** * 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 98002fb6b6a5d..8c0fddbdc7605 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\CacheAdapterPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ControllerArgumentValueResolverPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\FormPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\PropertyInfoPass; @@ -89,6 +90,7 @@ public function build(ContainerBuilder $container) $container->addCompilerPass(new SerializerPass()); $container->addCompilerPass(new PropertyInfoPass()); $container->addCompilerPass(new ControllerArgumentValueResolverPass()); + $container->addCompilerPass(new CacheAdapterPass()); if ($container->getParameter('kernel.debug')) { $container->addCompilerPass(new UnusedTagsPass(), PassConfig::TYPE_AFTER_REMOVING); 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..79f295205f5ad 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/CacheAdapterPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/CacheAdapterPassTest.php new file mode 100644 index 0000000000000..923189221f9e9 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/CacheAdapterPassTest.php @@ -0,0 +1,109 @@ + + * + * 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\CacheAdapterPass; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Reference; + +class CacheAdapterPassTest extends \PHPUnit_Framework_TestCase +{ + private $cacheAdapterPass; + + protected function setUp() + { + $this->cacheAdapterPass = new CacheAdapterPass(); + } + + public function testAdapterIsInjectedIntoConstructorArguments() + { + $container = $this->initializeContainer(); + $this->cacheAdapterPass->process($container); + $adapter = $container->getDefinition('foo')->getArgument(0); + + $this->assertInstanceOf('Symfony\Component\DependencyInjection\DefinitionDecorator', $adapter); + $this->assertFalse($adapter->isAbstract()); + $this->assertSame('cache.adapter.apcu_adapter', $adapter->getParent()); + $this->assertSame('0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33', $adapter->getArgument(0)); + } + + public function testAdapterIsInjectedIntoMethodArguments() + { + $container = $this->initializeContainer(); + $this->cacheAdapterPass->process($container); + $methodCalls = $container->getDefinition('bar')->getMethodCalls(); + $arguments = $methodCalls[0][1]; + $adapter = $arguments[0]; + + $this->assertInstanceOf('Symfony\Component\DependencyInjection\DefinitionDecorator', $adapter); + $this->assertFalse($adapter->isAbstract()); + $this->assertSame('cache.adapter.doctrine_adapter', $adapter->getParent()); + } + + public function testAdapterIsInjectIntoProperties() + { + $container = $this->initializeContainer(); + $this->cacheAdapterPass->process($container); + $properties = $container->getDefinition('baz')->getProperties(); + $adapter = $properties['cache']; + + $this->assertInstanceOf('Symfony\Component\DependencyInjection\DefinitionDecorator', $adapter); + $this->assertFalse($adapter->isAbstract()); + $this->assertSame('cache.adapter.fs_adapter', $adapter->getParent()); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage The cache adapter "bar" is not configured + */ + public function testThrowsExceptionWhenReferencedAdapterIsNotConfigured() + { + $container = new ContainerBuilder(); + $container->setDefinition('foo', new Definition('Foo', array(new Reference('cache.adapter.bar')))); + $this->cacheAdapterPass->process($container); + } + + private function initializeContainer() + { + $container = new ContainerBuilder(); + + $apcuAdapter = new Definition('Symfony\Component\Cache\Adapter\ApcuAdapter'); + $apcuAdapter->setAbstract(true); + $apcuAdapter->addTag('cache.adapter', array('id' => 'adapter1', 'namespace-arg-index' => 0)); + $container->setDefinition('cache.adapter.apcu_adapter', $apcuAdapter); + + $doctrineAdapter = new Definition('Symfony\Component\Cache\Adapter\DoctrineAdapter'); + $doctrineAdapter->setAbstract(true); + $doctrineAdapter->addTag('cache.adapter', array('id' => 'adapter2')); + $container->setDefinition('cache.adapter.doctrine_adapter', $doctrineAdapter); + + $filesystemAdapter = new Definition('Symfony\Component\Cache\Adapter\FilesystemAdapter'); + $filesystemAdapter->setAbstract(true); + $filesystemAdapter->addTag('cache.adapter', array('id' => 'adapter3')); + $container->setDefinition('cache.adapter.fs_adapter', $filesystemAdapter); + + $foo = new Definition(); + $foo->setArguments(array(new Reference('cache.adapter.adapter1'))); + $container->setDefinition('foo', $foo); + + $bar = new Definition(); + $bar->addMethodCall('setCache', array(new Reference('cache.adapter.adapter2'))); + $container->setDefinition('bar', $bar); + + $baz = new Definition(); + $baz->setProperty('cache', new Reference('cache.adapter.adapter3')); + $container->setDefinition('baz', $baz); + + return $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..a5c375ab3b740 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/cache.php @@ -0,0 +1,28 @@ +loadFromExtension('framework', array( + 'cache' => array( + 'adapters' => array( + 'foo' => array( + 'type' => 'apcu', + 'options' => array( + 'default_lifetime' => 30, + ), + ), + 'bar' => array( + 'type' => 'doctrine', + 'options' => array( + 'default_lifetime' => 5, + 'cache_provider_service' => 'app.doctrine_cache_provider', + ), + ), + 'baz' => array( + 'type' => 'filesystem', + 'options' => array( + 'default_lifetime' => 7, + 'directory' => 'app/cache/psr', + ), + ), + ), + ), +)); 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..086ea63a017af --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/cache.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + 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..9d0de6ad89ff1 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/cache.yml @@ -0,0 +1,17 @@ +framework: + cache: + adapters: + foo: + type: apcu + options: + default_lifetime: 30 + bar: + type: doctrine + options: + default_lifetime: 5 + cache_provider_service: app.doctrine_cache_provider + baz: + type: filesystem + options: + default_lifetime: 7 + directory: app/cache/psr diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php index 55d9a16e77e5c..6643e7f1f73c8 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,15 @@ public function testPropertyInfoEnabled() $this->assertTrue($container->has('property_info')); } + public function testCacheAdaptersAbstractServices() + { + $container = $this->createContainerFromFile('cache'); + + $this->assertCacheAdapterIsRegistered($container, 'foo', 'apcu', array(null, 30), 0); + $this->assertCacheAdapterIsRegistered($container, 'bar', 'doctrine', array(new Reference('app.doctrine_cache_provider'), 5)); + $this->assertCacheAdapterIsRegistered($container, 'baz', 'filesystem', array('app/cache/psr', 7)); + } + protected function createContainer(array $data = array()) { return new ContainerBuilder(new ParameterBag(array_merge(array( @@ -636,4 +648,39 @@ private function assertVersionStrategy(ContainerBuilder $container, Reference $r $this->assertEquals($format, $versionStrategy->getArgument(1)); } } + + private function assertCacheAdapterIsRegistered(ContainerBuilder $container, $name, $type, array $arguments, $namespaceArgumentIndex = null) + { + $id = 'cache.adapter.'.$name; + + $this->assertTrue($container->has($id), sprintf('Service definition "%s" for cache adapter of type "%s" is registered', $id, $type)); + + $adapterDefinition = $container->getDefinition($id); + + 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->isAbstract(), sprintf('Service definition "%s" for cache adapter "%s" is abstract', $id, $name)); + $this->assertEquals($arguments, $adapterDefinition->getArguments()); + $this->assertTrue($adapterDefinition->hasTag('cache.adapter'), sprintf('Service definition "%s" is tagged with the "cache.adapter" tag.', $id)); + + $tag = $adapterDefinition->getTag('cache.adapter'); + + $this->assertTrue(isset($tag[0]['id']), 'The adapter name is the "id" attribute of the "cache.adapter" tag.'); + $this->assertSame($name, $tag[0]['id'], 'The adapter name is the "id" attribute of the "cache.adapter" tag.'); + + 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.'); + } + } } From e44bfdcde90a592ff0aa7ff6ab1c340c32fa51d6 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 4 Mar 2016 18:43:16 +0100 Subject: [PATCH 3/7] [FrameworkBundle] Add cache-pool tag and wiring --- .../Compiler/CacheAdapterPass.php | 88 ------------------- .../Compiler/CachePoolPass.php | 64 ++++++++++++++ .../DependencyInjection/Configuration.php | 32 ++----- .../FrameworkExtension.php | 48 +++------- .../FrameworkBundle/FrameworkBundle.php | 4 +- .../Resources/config/cache_adapters.xml | 37 ++++++++ .../Resources/config/schema/symfony-1.0.xsd | 4 +- ...pterPassTest.php => CachePoolPassTest.php} | 16 ++-- 8 files changed, 133 insertions(+), 160 deletions(-) delete mode 100644 src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CacheAdapterPass.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Resources/config/cache_adapters.xml rename src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/{Compiler/CacheAdapterPassTest.php => CachePoolPassTest.php} (91%) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CacheAdapterPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CacheAdapterPass.php deleted file mode 100644 index d8453caa89fd4..0000000000000 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CacheAdapterPass.php +++ /dev/null @@ -1,88 +0,0 @@ - - * - * 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 - */ -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; - } -} 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..e4e6487209fe1 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php @@ -0,0 +1,64 @@ + + * + * 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 + */ +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)); + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index 6dab7150c9a19..d64d9faad446e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -555,40 +555,22 @@ private function addCacheSection(ArrayNodeDefinition $rootNode) ->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() diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 74196229905f0..f7431a6600287 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -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 @@ private function registerPropertyInfoConfiguration(array $config, ContainerBuild } } - 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; - - 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; - } + if (!empty($config['pool'])) { + $loader->load('cache_adapters.xml'); + } - $tagAttributes = array('id' => $name); + foreach ($config['pool'] as $name => $poolConfig) { + $poolDefinition = new DefinitionDecorator('cache.adapter.'.$poolConfig['type']); + $poolDefinition->replaceArgument(1, $poolConfig['default_lifetime']); - if (null !== $namespaceArgumentIndex) { - $tagAttributes['namespace-arg-index'] = $namespaceArgumentIndex; + 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']); } - $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); } } diff --git a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php index 8c0fddbdc7605..7ed44c5bb84d2 100644 --- a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php +++ b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php @@ -14,7 +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\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 @@ public function build(ContainerBuilder $container) $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); 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..13612a1d28612 --- /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 79f295205f5ad..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 @@ -206,11 +206,11 @@ - + - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/CacheAdapterPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/CachePoolPassTest.php similarity index 91% rename from src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/CacheAdapterPassTest.php rename to src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/CachePoolPassTest.php index 923189221f9e9..033809fcda76d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/CacheAdapterPassTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/CachePoolPassTest.php @@ -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 @@ public function testAdapterIsInjectedIntoConstructorArguments() 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 @@ public function testAdapterIsInjectedIntoMethodArguments() 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 @@ public function testThrowsExceptionWhenReferencedAdapterIsNotConfigured() { $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() From 92b1a206134d9c7c2fe1c7ffca07391a5058cb70 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 11 Mar 2016 09:48:42 +0100 Subject: [PATCH 4/7] [FrameworkBundle] Fix and add tests for cache pool wiring --- .../Compiler/CachePoolPass.php | 12 +- .../DependencyInjection/Configuration.php | 6 +- .../FrameworkExtension.php | 6 +- .../Resources/config/cache_adapters.xml | 8 +- .../DependencyInjection/CachePoolPassTest.php | 109 ------------------ .../Compiler/CachePoolPassTest.php | 108 +++++++++++++++++ .../Fixtures/php/cache.php | 23 ++-- .../Fixtures/xml/cache.xml | 7 +- .../Fixtures/yml/cache.yml | 19 +-- .../FrameworkExtensionTest.php | 27 ++--- 10 files changed, 163 insertions(+), 162 deletions(-) delete mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/CachePoolPassTest.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/CachePoolPassTest.php diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php index e4e6487209fe1..395169caaca47 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php @@ -14,7 +14,6 @@ use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\DefinitionDecorator; -use Symfony\Component\DependencyInjection\Reference; /** * @author Nicolas Grekas @@ -28,7 +27,6 @@ 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)); @@ -39,7 +37,11 @@ public function process(ContainerBuilder $container) do { $adapterId = $adapter->getParent(); $adapter = $container->getDefinition($adapterId); - } while ($adapter instanceof DefinitionDecorator && !$adapter->getTag('cache.adapter')); + } 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'); @@ -51,7 +53,7 @@ public function process(ContainerBuilder $container) throw new \InvalidArgumentException(sprintf('Services tagged as "cache.adapter" must be abstract: "%s" is not.', $adapterId)); } - if (0 <= $namespaceArgIndex) { + if (0 <= $namespaceArgIndex = $tags[0]['namespace_arg_index']) { $pool->replaceArgument($namespaceArgIndex, $this->getNamespace($id)); } } @@ -59,6 +61,6 @@ public function process(ContainerBuilder $container) private function getNamespace($id) { - return substr(str_replace('/', '-', base64_encode(md5('symfony.'.$id, true)), 0, 10)); + 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 d64d9faad446e..deb8d1e49e7e3 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -557,18 +557,16 @@ private function addCacheSection(ArrayNodeDefinition $rootNode) ->info('Cache configuration') ->fixXmlConfig('pool') ->children() - ->arrayNode('pool') + ->arrayNode('pools') ->useAttributeAsKey('name') ->prototype('array') - ->beforeNormalization() - ->end() ->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')->default(0)->end() + ->integerNode('default_lifetime')->defaultValue(0)->end() ->scalarNode('cache_provider_service')->defaultNull()->end() ->scalarNode('directory')->defaultNull()->end() ->end() diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index f7431a6600287..fd1ae70347e14 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -139,7 +139,7 @@ public function load(array $configs, ContainerBuilder $container) } if (isset($config['cache'])) { - $this->registerCacheConfiguration($config['cache'], $container); + $this->registerCacheConfiguration($config['cache'], $container, $loader); } $loader->load('debug_prod.xml'); @@ -1022,11 +1022,11 @@ private function registerPropertyInfoConfiguration(array $config, ContainerBuild private function registerCacheConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader) { - if (!empty($config['pool'])) { + if (!empty($config['pools'])) { $loader->load('cache_adapters.xml'); } - foreach ($config['pool'] as $name => $poolConfig) { + foreach ($config['pools'] as $name => $poolConfig) { $poolDefinition = new DefinitionDecorator('cache.adapter.'.$poolConfig['type']); $poolDefinition->replaceArgument(1, $poolConfig['default_lifetime']); diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache_adapters.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache_adapters.xml index 13612a1d28612..9c49c8672de8d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache_adapters.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache_adapters.xml @@ -7,27 +7,27 @@ - + - + - + - + %kernel.cache_dir% diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/CachePoolPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/CachePoolPassTest.php deleted file mode 100644 index 033809fcda76d..0000000000000 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/CachePoolPassTest.php +++ /dev/null @@ -1,109 +0,0 @@ - - * - * 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\Reference; - -class CachePoolPassTest extends \PHPUnit_Framework_TestCase -{ - private $cachePoolPass; - - protected function setUp() - { - $this->cachePoolPass = new CachePoolPass(); - } - - public function testAdapterIsInjectedIntoConstructorArguments() - { - $container = $this->initializeContainer(); - $this->cachePoolPass->process($container); - $adapter = $container->getDefinition('foo')->getArgument(0); - - $this->assertInstanceOf('Symfony\Component\DependencyInjection\DefinitionDecorator', $adapter); - $this->assertFalse($adapter->isAbstract()); - $this->assertSame('cache.adapter.apcu_adapter', $adapter->getParent()); - $this->assertSame('0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33', $adapter->getArgument(0)); - } - - public function testAdapterIsInjectedIntoMethodArguments() - { - $container = $this->initializeContainer(); - $this->cachePoolPass->process($container); - $methodCalls = $container->getDefinition('bar')->getMethodCalls(); - $arguments = $methodCalls[0][1]; - $adapter = $arguments[0]; - - $this->assertInstanceOf('Symfony\Component\DependencyInjection\DefinitionDecorator', $adapter); - $this->assertFalse($adapter->isAbstract()); - $this->assertSame('cache.adapter.doctrine_adapter', $adapter->getParent()); - } - - public function testAdapterIsInjectIntoProperties() - { - $container = $this->initializeContainer(); - $this->cachePoolPass->process($container); - $properties = $container->getDefinition('baz')->getProperties(); - $adapter = $properties['cache']; - - $this->assertInstanceOf('Symfony\Component\DependencyInjection\DefinitionDecorator', $adapter); - $this->assertFalse($adapter->isAbstract()); - $this->assertSame('cache.adapter.fs_adapter', $adapter->getParent()); - } - - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The cache adapter "bar" is not configured - */ - public function testThrowsExceptionWhenReferencedAdapterIsNotConfigured() - { - $container = new ContainerBuilder(); - $container->setDefinition('foo', new Definition('Foo', array(new Reference('cache.adapter.bar')))); - $this->cachePoolPass->process($container); - } - - private function initializeContainer() - { - $container = new ContainerBuilder(); - - $apcuAdapter = new Definition('Symfony\Component\Cache\Adapter\ApcuAdapter'); - $apcuAdapter->setAbstract(true); - $apcuAdapter->addTag('cache.adapter', array('id' => 'adapter1', 'namespace-arg-index' => 0)); - $container->setDefinition('cache.adapter.apcu_adapter', $apcuAdapter); - - $doctrineAdapter = new Definition('Symfony\Component\Cache\Adapter\DoctrineAdapter'); - $doctrineAdapter->setAbstract(true); - $doctrineAdapter->addTag('cache.adapter', array('id' => 'adapter2')); - $container->setDefinition('cache.adapter.doctrine_adapter', $doctrineAdapter); - - $filesystemAdapter = new Definition('Symfony\Component\Cache\Adapter\FilesystemAdapter'); - $filesystemAdapter->setAbstract(true); - $filesystemAdapter->addTag('cache.adapter', array('id' => 'adapter3')); - $container->setDefinition('cache.adapter.fs_adapter', $filesystemAdapter); - - $foo = new Definition(); - $foo->setArguments(array(new Reference('cache.adapter.adapter1'))); - $container->setDefinition('foo', $foo); - - $bar = new Definition(); - $bar->addMethodCall('setCache', array(new Reference('cache.adapter.adapter2'))); - $container->setDefinition('bar', $bar); - - $baz = new Definition(); - $baz->setProperty('cache', new Reference('cache.adapter.adapter3')); - $container->setDefinition('baz', $baz); - - return $container; - } -} 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 index a5c375ab3b740..63e5441293f60 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/cache.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/cache.php @@ -2,26 +2,25 @@ $container->loadFromExtension('framework', array( 'cache' => array( - 'adapters' => array( + 'pools' => array( 'foo' => array( 'type' => 'apcu', - 'options' => array( - 'default_lifetime' => 30, - ), + 'default_lifetime' => 30, ), 'bar' => array( 'type' => 'doctrine', - 'options' => array( - 'default_lifetime' => 5, - 'cache_provider_service' => 'app.doctrine_cache_provider', - ), + 'default_lifetime' => 5, + 'cache_provider_service' => 'app.doctrine_cache_provider', ), 'baz' => array( 'type' => 'filesystem', - 'options' => array( - 'default_lifetime' => 7, - 'directory' => 'app/cache/psr', - ), + '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 index 086ea63a017af..f3d26f7380290 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/cache.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/cache.xml @@ -7,9 +7,10 @@ - - - + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/cache.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/cache.yml index 9d0de6ad89ff1..0d45b13527161 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/cache.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/cache.yml @@ -1,17 +1,18 @@ framework: cache: - adapters: + pools: foo: type: apcu - options: - default_lifetime: 30 + default_lifetime: 30 bar: type: doctrine - options: - default_lifetime: 5 - cache_provider_service: app.doctrine_cache_provider + default_lifetime: 5 + cache_provider_service: app.doctrine_cache_provider baz: type: filesystem - options: - default_lifetime: 7 - directory: app/cache/psr + 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 6643e7f1f73c8..93478df449b99 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php @@ -571,13 +571,14 @@ public function testPropertyInfoEnabled() $this->assertTrue($container->has('property_info')); } - public function testCacheAdaptersAbstractServices() + public function testCachePoolServices() { $container = $this->createContainerFromFile('cache'); - $this->assertCacheAdapterIsRegistered($container, 'foo', 'apcu', array(null, 30), 0); - $this->assertCacheAdapterIsRegistered($container, 'bar', 'doctrine', array(new Reference('app.doctrine_cache_provider'), 5)); - $this->assertCacheAdapterIsRegistered($container, 'baz', 'filesystem', array('app/cache/psr', 7)); + $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()) @@ -649,13 +650,18 @@ private function assertVersionStrategy(ContainerBuilder $container, Reference $r } } - private function assertCacheAdapterIsRegistered(ContainerBuilder $container, $name, $type, array $arguments, $namespaceArgumentIndex = null) + private function assertCachePoolServiceDefinitionIsCreated(ContainerBuilder $container, $name, $type, array $arguments, $namespaceArgumentIndex = null) { - $id = 'cache.adapter.'.$name; + $id = 'cache.pool.'.$name; - $this->assertTrue($container->has($id), sprintf('Service definition "%s" for cache adapter of type "%s" is registered', $id, $type)); + $this->assertTrue($container->has($id), sprintf('Service definition "%s" for cache pool of type "%s" is registered', $id, $type)); - $adapterDefinition = $container->getDefinition($id); + $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': @@ -669,15 +675,10 @@ private function assertCacheAdapterIsRegistered(ContainerBuilder $container, $na break; } - $this->assertTrue($adapterDefinition->isAbstract(), sprintf('Service definition "%s" for cache adapter "%s" is abstract', $id, $name)); - $this->assertEquals($arguments, $adapterDefinition->getArguments()); $this->assertTrue($adapterDefinition->hasTag('cache.adapter'), sprintf('Service definition "%s" is tagged with the "cache.adapter" tag.', $id)); $tag = $adapterDefinition->getTag('cache.adapter'); - $this->assertTrue(isset($tag[0]['id']), 'The adapter name is the "id" attribute of the "cache.adapter" tag.'); - $this->assertSame($name, $tag[0]['id'], 'The adapter name is the "id" attribute of the "cache.adapter" tag.'); - 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.'); From 4740c5ccfb4f3264e974b166f0b02e6402317056 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 14 Mar 2016 10:01:08 +0100 Subject: [PATCH 5/7] [FrameworkBundle] use abstract cache.pool decoration and aliases --- .../Compiler/CachePoolPass.php | 50 ++++++++------- .../DependencyInjection/Configuration.php | 12 ++-- .../FrameworkExtension.php | 15 ++--- .../{cache_adapters.xml => cache_pools.xml} | 20 +++--- .../Resources/config/schema/symfony-1.0.xsd | 5 +- .../Compiler/CachePoolPassTest.php | 63 ++++++------------- .../Fixtures/php/cache.php | 15 +++-- .../Fixtures/xml/cache.xml | 9 +-- .../Fixtures/yml/cache.yml | 14 +++-- .../FrameworkExtensionTest.php | 44 ++++++------- 10 files changed, 116 insertions(+), 131 deletions(-) rename src/Symfony/Bundle/FrameworkBundle/Resources/config/{cache_adapters.xml => cache_pools.xml} (80%) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php index 395169caaca47..4c56a58781e15 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php @@ -14,6 +14,7 @@ use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\DefinitionDecorator; +use Symfony\Component\DependencyInjection\Reference; /** * @author Nicolas Grekas @@ -25,36 +26,37 @@ class CachePoolPass implements CompilerPassInterface */ public function process(ContainerBuilder $container) { + $attributes = array( + 'provider_service', + 'namespace', + 'default_lifetime', + 'directory', + ); foreach ($container->findTaggedServiceIds('cache.pool') as $id => $tags) { - $pool = $container->getDefinition($id); + $adapter = $pool = $container->getDefinition($id); + $tags[0] += array('namespace' => $this->getNamespace($id)); - if (!$pool instanceof DefinitionDecorator) { - throw new \InvalidArgumentException(sprintf('Services tagged with "cache.pool" must have a parent service but "%s" has none.', $id)); + while ($adapter instanceof DefinitionDecorator) { + $adapter = $container->findDefinition($adapter->getParent()); + if ($t = $adapter->getTag('cache.pool')) { + $tags[0] += $t[0]; + } } - - $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)); + if ($pool->isAbstract()) { + continue; } - - $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 (isset($tags[0]['provider_service']) && is_string($tags[0]['provider_service'])) { + $tags[0]['provider_service'] = new Reference($tags[0]['provider_service']); } - - if (!$adapter->isAbstract()) { - throw new \InvalidArgumentException(sprintf('Services tagged as "cache.adapter" must be abstract: "%s" is not.', $adapterId)); + $i = 0; + foreach ($attributes as $attr) { + if (isset($tags[0][$attr])) { + $pool->replaceArgument($i++, $tags[0][$attr]); + unset($tags[0][$attr]); + } } - - if (0 <= $namespaceArgIndex = $tags[0]['namespace_arg_index']) { - $pool->replaceArgument($namespaceArgIndex, $this->getNamespace($id)); + if (!empty($tags[0])) { + throw new \InvalidArgumentException(sprintf('Invalid "cache.pool" tag for service "%s": accepted attributes are "provider_service", "namespace", "default_lifetime" and "directory", found "%s".', $id, implode('", "', array_keys($tags[0])))); } } } diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index deb8d1e49e7e3..20a9e8b2998bd 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -561,13 +561,13 @@ private function addCacheSection(ArrayNodeDefinition $rootNode) ->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')) + ->scalarNode('adapter_service') + ->info('The cache pool service to use as template definition.') + ->defaultValue('cache.adapter.default') ->end() - ->integerNode('default_lifetime')->defaultValue(0)->end() - ->scalarNode('cache_provider_service')->defaultNull()->end() + ->booleanNode('public')->defaultFalse()->end() + ->integerNode('default_lifetime')->defaultNull()->end() + ->scalarNode('provider_service')->defaultNull()->end() ->scalarNode('directory')->defaultNull()->end() ->end() ->end() diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index fd1ae70347e14..f00c2a42ae3db 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -1023,20 +1023,15 @@ private function registerPropertyInfoConfiguration(array $config, ContainerBuild private function registerCacheConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader) { if (!empty($config['pools'])) { - $loader->load('cache_adapters.xml'); + $loader->load('cache_pools.xml'); } foreach ($config['pools'] as $name => $poolConfig) { - $poolDefinition = new DefinitionDecorator('cache.adapter.'.$poolConfig['type']); - $poolDefinition->replaceArgument(1, $poolConfig['default_lifetime']); + $poolDefinition = new DefinitionDecorator($poolConfig['adapter_service']); + $poolDefinition->setPublic($poolConfig['public']); + unset($poolConfig['adapter_service'], $poolConfig['public']); - 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'); + $poolDefinition->addTag('cache.pool', $poolConfig); $container->setDefinition('cache.pool.'.$name, $poolDefinition); } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache_adapters.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache_pools.xml similarity index 80% rename from src/Symfony/Bundle/FrameworkBundle/Resources/config/cache_adapters.xml rename to src/Symfony/Bundle/FrameworkBundle/Resources/config/cache_pools.xml index 9c49c8672de8d..bea42c651ebde 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache_adapters.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache_pools.xml @@ -6,31 +6,33 @@ + + - + - - - + + + - + - + - - %kernel.cache_dir% - + + + %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 cee9299e44e58..26fed333de769 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 @@ -212,9 +212,10 @@ - + + - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/CachePoolPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/CachePoolPassTest.php index f07c04c7e0767..f69c97ddc29c8 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/CachePoolPassTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/CachePoolPassTest.php @@ -15,6 +15,7 @@ use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\DefinitionDecorator; +use Symfony\Component\DependencyInjection\Reference; class CachePoolPassTest extends \PHPUnit_Framework_TestCase { @@ -30,9 +31,10 @@ public function testNamespaceArgumentIsReplaced() $container = new ContainerBuilder(); $adapter = new Definition(); $adapter->setAbstract(true); - $adapter->addTag('cache.adapter', array('namespace_arg_index' => 0)); + $adapter->addTag('cache.pool'); $container->setDefinition('app.cache_adapter', $adapter); - $cachePool = new DefinitionDecorator('app.cache_adapter'); + $container->setAlias('app.cache_adapter_alias', 'app.cache_adapter'); + $cachePool = new DefinitionDecorator('app.cache_adapter_alias'); $cachePool->addArgument(null); $cachePool->addTag('cache.pool'); $container->setDefinition('app.cache_pool', $cachePool); @@ -42,65 +44,40 @@ public function testNamespaceArgumentIsReplaced() $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() + public function testArgsAreReplaced() { $container = new ContainerBuilder(); $cachePool = new Definition(); - $cachePool->addTag('cache.pool'); + $cachePool->addTag('cache.pool', array( + 'provider_service' => 'foobar', + 'default_lifetime' => 3, + )); + $cachePool->addArgument(null); + $cachePool->addArgument(null); + $cachePool->addArgument(null); $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); + $this->assertInstanceOf(Reference::class, $cachePool->getArgument(0)); + $this->assertSame('foobar', (string) $cachePool->getArgument(0)); + $this->assertSame('yRnzIIVLvL', $cachePool->getArgument(1)); + $this->assertSame(3, $cachePool->getArgument(2)); } /** * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Invalid "cache.adapter" tag for service "app.cache_adapter": attribute "namespace_arg_index" is missing. + * @expectedExceptionMessage Invalid "cache.pool" tag for service "app.cache_pool": accepted attributes are */ - public function testThrowsExceptionWhenCacheAdapterDefinesNoNamespaceArgument() + public function testThrowsExceptionWhenCachePoolTagHasUnknownAttributes() { $container = new ContainerBuilder(); $adapter = new Definition(); $adapter->setAbstract(true); - $adapter->addTag('cache.adapter'); + $adapter->addTag('cache.pool'); $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'); + $cachePool->addTag('cache.pool', array('foobar' => 123)); $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 index 63e5441293f60..2cbd3b51eb419 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/cache.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/cache.php @@ -4,23 +4,26 @@ 'cache' => array( 'pools' => array( 'foo' => array( - 'type' => 'apcu', + 'adapter_service' => 'cache.adapter.apcu', 'default_lifetime' => 30, ), 'bar' => array( - 'type' => 'doctrine', + 'adapter_service' => 'cache.adapter.doctrine', 'default_lifetime' => 5, - 'cache_provider_service' => 'app.doctrine_cache_provider', + 'provider_service' => 'app.doctrine_cache_provider', ), 'baz' => array( - 'type' => 'filesystem', + 'adapter_service' => 'cache.adapter.filesystem', 'default_lifetime' => 7, 'directory' => 'app/cache/psr', ), 'foobar' => array( - 'type' => 'psr6', + 'adapter_service' => 'cache.adapter.psr6', 'default_lifetime' => 10, - 'cache_provider_service' => 'app.cache_pool', + 'provider_service' => 'app.cache_pool', + ), + 'def' => array( + 'default_lifetime' => 11, ), ), ), diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/cache.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/cache.xml index f3d26f7380290..13b05f6718581 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/cache.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/cache.xml @@ -7,10 +7,11 @@ - - - - + + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/cache.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/cache.yml index 0d45b13527161..f3c6048a7720c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/cache.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/cache.yml @@ -2,17 +2,19 @@ framework: cache: pools: foo: - type: apcu + adapter_service: cache.adapter.apcu default_lifetime: 30 bar: - type: doctrine + adapter_service: cache.adapter.doctrine default_lifetime: 5 - cache_provider_service: app.doctrine_cache_provider + provider_service: app.doctrine_cache_provider baz: - type: filesystem + adapter_service: cache.adapter.filesystem default_lifetime: 7 directory: app/cache/psr foobar: - type: psr6 + adapter_service: cache.adapter.psr6 default_lifetime: 10 - cache_provider_service: app.cache_pool + provider_service: app.cache_pool + def: + default_lifetime: 11 diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php index 93478df449b99..6508fe005e82e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php @@ -575,10 +575,11 @@ 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)); + $this->assertCachePoolServiceDefinitionIsCreated($container, 'foo', 'cache.adapter.apcu', 30); + $this->assertCachePoolServiceDefinitionIsCreated($container, 'bar', 'cache.adapter.doctrine', 5); + $this->assertCachePoolServiceDefinitionIsCreated($container, 'baz', 'cache.adapter.filesystem', 7); + $this->assertCachePoolServiceDefinitionIsCreated($container, 'foobar', 'cache.adapter.psr6', 10); + $this->assertCachePoolServiceDefinitionIsCreated($container, 'def', 'cache.adapter.filesystem', 11); } protected function createContainer(array $data = array()) @@ -650,38 +651,39 @@ private function assertVersionStrategy(ContainerBuilder $container, Reference $r } } - private function assertCachePoolServiceDefinitionIsCreated(ContainerBuilder $container, $name, $type, array $arguments, $namespaceArgumentIndex = null) + private function assertCachePoolServiceDefinitionIsCreated(ContainerBuilder $container, $name, $adapter, $defaultLifetime) { $id = 'cache.pool.'.$name; - $this->assertTrue($container->has($id), sprintf('Service definition "%s" for cache pool of type "%s" is registered', $id, $type)); + $this->assertTrue($container->has($id), sprintf('Service definition "%s" for cache pool of type "%s" is registered', $id, $adapter)); $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()); + $this->assertInstanceOf(DefinitionDecorator::class, $poolDefinition, sprintf('Cache pool "%s" is based on an abstract cache pool.', $name)); - $adapterDefinition = $container->getDefinition($poolDefinition->getParent()); + $this->assertTrue($poolDefinition->hasTag('cache.pool'), sprintf('Service definition "%s" is tagged with the "cache.pool" tag.', $id)); + $this->assertFalse($poolDefinition->isAbstract(), sprintf('Service definition "%s" is not abstract.', $id)); - switch ($type) { - case 'apcu': + $tag = $poolDefinition->getTag('cache.pool'); + $this->assertTrue(isset($tag[0]['default_lifetime']), 'The default lifetime is stored as an attribute of the "cache.pool" tag.'); + $this->assertSame($defaultLifetime, $tag[0]['default_lifetime'], 'The default lifetime is stored as an attribute of the "cache.pool" tag.'); + + $adapterId = $poolDefinition->getParent(); + $adapterDefinition = $container->findDefinition($adapterId); + + switch ($adapter) { + case 'cache.adapter.apcu': $this->assertSame(ApcuAdapter::class, $adapterDefinition->getClass()); break; - case 'doctrine': + case 'cache.adapter.doctrine': $this->assertSame(DoctrineAdapter::class, $adapterDefinition->getClass()); break; - case 'filesystem': + case 'cache.adapter.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.'); - } + $this->assertTrue($adapterDefinition->hasTag('cache.pool'), sprintf('Service definition "%s" is tagged with the "cache.pool" tag.', $adapterId)); + $this->assertTrue($adapterDefinition->isAbstract(), sprintf('Service definition "%s" is abstract.', $adapterId)); } } From 714b916d5d55c899a18f1bcc8462ba4dcb97c3a1 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 4 Apr 2016 09:11:03 +0200 Subject: [PATCH 6/7] [FrameworkBundle] Add & use Psr6CacheClearer --- .../Compiler/CachePoolPass.php | 31 ++++++--- .../DependencyInjection/Configuration.php | 15 +++-- .../FrameworkExtension.php | 4 +- .../Resources/config/cache_pools.xml | 18 +++-- .../Resources/config/schema/symfony-1.0.xsd | 5 +- .../Compiler/CachePoolPassTest.php | 2 +- .../Fixtures/php/cache.php | 13 ++-- .../Fixtures/xml/cache.xml | 8 +-- .../Fixtures/yml/cache.yml | 13 ++-- .../FrameworkExtensionTest.php | 1 - .../Tests/Functional/CachePoolsTest.php | 66 +++++++++++++++++++ .../Functional/app/CachePools/bundles.php | 18 +++++ .../Functional/app/CachePools/config.yml | 8 +++ .../app/CachePools/redis_config.yml | 22 +++++++ .../Bundle/FrameworkBundle/composer.json | 3 +- .../Cache/Adapter/FilesystemAdapter.php | 3 + .../Cache/Tests/Adapter/FilesystemTest.php | 2 +- .../Compiler/PassConfig.php | 5 +- .../ResolveDefinitionTemplatesPass.php | 6 +- .../CacheClearer/Psr6CacheClearer.php | 37 +++++++++++ 20 files changed, 228 insertions(+), 52 deletions(-) create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolsTest.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/bundles.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/config.yml create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/redis_config.yml create mode 100644 src/Symfony/Component/HttpKernel/CacheClearer/Psr6CacheClearer.php diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php index 4c56a58781e15..8e1e90cfaca58 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php @@ -27,36 +27,47 @@ class CachePoolPass implements CompilerPassInterface public function process(ContainerBuilder $container) { $attributes = array( - 'provider_service', + 'provider', 'namespace', 'default_lifetime', - 'directory', ); foreach ($container->findTaggedServiceIds('cache.pool') as $id => $tags) { $adapter = $pool = $container->getDefinition($id); - $tags[0] += array('namespace' => $this->getNamespace($id)); - + if ($pool->isAbstract()) { + continue; + } + if (!isset($tags[0]['namespace'])) { + $tags[0]['namespace'] = $this->getNamespace($id); + } while ($adapter instanceof DefinitionDecorator) { $adapter = $container->findDefinition($adapter->getParent()); if ($t = $adapter->getTag('cache.pool')) { $tags[0] += $t[0]; } } - if ($pool->isAbstract()) { - continue; + if (isset($tags[0]['clearer'])) { + $clearer = $container->getDefinition($tags[0]['clearer']); + } else { + $clearer = null; } - if (isset($tags[0]['provider_service']) && is_string($tags[0]['provider_service'])) { - $tags[0]['provider_service'] = new Reference($tags[0]['provider_service']); + unset($tags[0]['clearer']); + + if (isset($tags[0]['provider']) && is_string($tags[0]['provider'])) { + $tags[0]['provider'] = new Reference($tags[0]['provider']); } $i = 0; foreach ($attributes as $attr) { if (isset($tags[0][$attr])) { $pool->replaceArgument($i++, $tags[0][$attr]); - unset($tags[0][$attr]); } + unset($tags[0][$attr]); } if (!empty($tags[0])) { - throw new \InvalidArgumentException(sprintf('Invalid "cache.pool" tag for service "%s": accepted attributes are "provider_service", "namespace", "default_lifetime" and "directory", found "%s".', $id, implode('", "', array_keys($tags[0])))); + throw new \InvalidArgumentException(sprintf('Invalid "cache.pool" tag for service "%s": accepted attributes are "provider", "namespace" and "default_lifetime", found "%s".', $id, implode('", "', array_keys($tags[0])))); + } + + if (null !== $clearer) { + $clearer->addMethodCall('addPool', array(new Reference($id))); } } } diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index 20a9e8b2998bd..e125e3096a944 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -561,14 +561,19 @@ private function addCacheSection(ArrayNodeDefinition $rootNode) ->useAttributeAsKey('name') ->prototype('array') ->children() - ->scalarNode('adapter_service') - ->info('The cache pool service to use as template definition.') + ->scalarNode('adapter') + ->info('The cache pool adapter service to use as template definition.') ->defaultValue('cache.adapter.default') ->end() ->booleanNode('public')->defaultFalse()->end() - ->integerNode('default_lifetime')->defaultNull()->end() - ->scalarNode('provider_service')->defaultNull()->end() - ->scalarNode('directory')->defaultNull()->end() + ->integerNode('default_lifetime')->end() + ->scalarNode('provider') + ->info('The service name to use as provider when the specified adapter needs one.') + ->end() + ->scalarNode('namespace') + ->info('The namespace where cached items are stored. Auto-generated by default. Set to false to disable namespacing.') + ->end() + ->scalarNode('clearer')->defaultValue('cache.default_pools_clearer')->end() ->end() ->end() ->end() diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index f00c2a42ae3db..ae9d79c4142f1 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -1027,9 +1027,9 @@ private function registerCacheConfiguration(array $config, ContainerBuilder $con } foreach ($config['pools'] as $name => $poolConfig) { - $poolDefinition = new DefinitionDecorator($poolConfig['adapter_service']); + $poolDefinition = new DefinitionDecorator($poolConfig['adapter']); $poolDefinition->setPublic($poolConfig['public']); - unset($poolConfig['adapter_service'], $poolConfig['public']); + unset($poolConfig['adapter'], $poolConfig['public']); $poolDefinition->addTag('cache.pool', $poolConfig); $container->setDefinition('cache.pool.'.$name, $poolDefinition); diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache_pools.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache_pools.xml index bea42c651ebde..eef88060cfe60 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache_pools.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache_pools.xml @@ -6,33 +6,39 @@ + + + + - - + + + + %kernel.cache_dir%/pools + + - - - + + - %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 26fed333de769..d8fc67ae29dad 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 @@ -212,10 +212,11 @@ - + - + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/CachePoolPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/CachePoolPassTest.php index f69c97ddc29c8..3fc66cff09084 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/CachePoolPassTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/CachePoolPassTest.php @@ -49,7 +49,7 @@ public function testArgsAreReplaced() $container = new ContainerBuilder(); $cachePool = new Definition(); $cachePool->addTag('cache.pool', array( - 'provider_service' => 'foobar', + 'provider' => 'foobar', 'default_lifetime' => 3, )); $cachePool->addArgument(null); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/cache.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/cache.php index 2cbd3b51eb419..7cf634b92e394 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/cache.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/cache.php @@ -4,23 +4,22 @@ 'cache' => array( 'pools' => array( 'foo' => array( - 'adapter_service' => 'cache.adapter.apcu', + 'adapter' => 'cache.adapter.apcu', 'default_lifetime' => 30, ), 'bar' => array( - 'adapter_service' => 'cache.adapter.doctrine', + 'adapter' => 'cache.adapter.doctrine', 'default_lifetime' => 5, - 'provider_service' => 'app.doctrine_cache_provider', + 'provider' => 'app.doctrine_cache_provider', ), 'baz' => array( - 'adapter_service' => 'cache.adapter.filesystem', + 'adapter' => 'cache.adapter.filesystem', 'default_lifetime' => 7, - 'directory' => 'app/cache/psr', ), 'foobar' => array( - 'adapter_service' => 'cache.adapter.psr6', + 'adapter' => 'cache.adapter.psr6', 'default_lifetime' => 10, - 'provider_service' => 'app.cache_pool', + 'provider' => 'app.cache_pool', ), 'def' => array( 'default_lifetime' => 11, diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/cache.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/cache.xml index 13b05f6718581..d6f472716ff89 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/cache.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/cache.xml @@ -7,10 +7,10 @@ - - - - + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/cache.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/cache.yml index f3c6048a7720c..395009f18ad18 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/cache.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/cache.yml @@ -2,19 +2,18 @@ framework: cache: pools: foo: - adapter_service: cache.adapter.apcu + adapter: cache.adapter.apcu default_lifetime: 30 bar: - adapter_service: cache.adapter.doctrine + adapter: cache.adapter.doctrine default_lifetime: 5 - provider_service: app.doctrine_cache_provider + provider: app.doctrine_cache_provider baz: - adapter_service: cache.adapter.filesystem + adapter: cache.adapter.filesystem default_lifetime: 7 - directory: app/cache/psr foobar: - adapter_service: cache.adapter.psr6 + adapter: cache.adapter.psr6 default_lifetime: 10 - provider_service: app.cache_pool + provider: app.cache_pool def: default_lifetime: 11 diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php index 6508fe005e82e..000ec8e6ff385 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php @@ -683,7 +683,6 @@ private function assertCachePoolServiceDefinitionIsCreated(ContainerBuilder $con break; } - $this->assertTrue($adapterDefinition->hasTag('cache.pool'), sprintf('Service definition "%s" is tagged with the "cache.pool" tag.', $adapterId)); $this->assertTrue($adapterDefinition->isAbstract(), sprintf('Service definition "%s" is abstract.', $adapterId)); } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolsTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolsTest.php new file mode 100644 index 0000000000000..b35eebdb317f2 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolsTest.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\Tests\Functional; + +use Symfony\Component\Cache\Adapter\FilesystemAdapter; +use Symfony\Component\Cache\Adapter\RedisAdapter; + +class CachePoolsTest extends WebTestCase +{ + public function testCachePools() + { + $this->doTestCachePools(array(), FilesystemAdapter::class); + } + + /** + * @requires extension redis + */ + public function testRedisCachePools() + { + try { + $this->doTestCachePools(array('root_config' => 'redis_config.yml', 'environment' => 'redis_cache'), RedisAdapter::class); + } catch (\PHPUnit_Framework_Error_Warning $e) { + if (0 !== strpos($e->getMessage(), 'unable to connect to 127.0.0.1')) { + throw $e; + } + $this->markTestSkipped($e->getMessage()); + } + } + + public function doTestCachePools($options, $adapterClass) + { + static::bootKernel($options); + $container = static::$kernel->getContainer(); + + $pool = $container->get('cache.pool.test'); + $this->assertInstanceOf($adapterClass, $pool); + + $key = 'foobar'; + $pool->deleteItem($key); + $item = $pool->getItem($key); + $this->assertFalse($item->isHit()); + + $item->set('baz'); + $pool->save($item); + $item = $pool->getItem($key); + $this->assertTrue($item->isHit()); + + $container->get('cache_clearer')->clear($container->getParameter('kernel.cache_dir')); + $item = $pool->getItem($key); + $this->assertFalse($item->isHit()); + } + + protected static function createKernel(array $options = array()) + { + return parent::createKernel(array('test_case' => 'CachePools') + $options); + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/bundles.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/bundles.php new file mode 100644 index 0000000000000..a73987bcc986a --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/bundles.php @@ -0,0 +1,18 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestBundle; +use Symfony\Bundle\FrameworkBundle\FrameworkBundle; + +return array( + new FrameworkBundle(), + new TestBundle(), +); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/config.yml new file mode 100644 index 0000000000000..25aff9cbcbe15 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/config.yml @@ -0,0 +1,8 @@ +imports: + - { resource: ../config/default.yml } + +framework: + cache: + pools: + test: + public: true diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/redis_config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/redis_config.yml new file mode 100644 index 0000000000000..1bafa08c7c12f --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/redis_config.yml @@ -0,0 +1,22 @@ +imports: + - { resource: ../config/default.yml } + +services: + cache.adapter.redis.connection: + public: false + class: Redis + calls: + - [connect, [127.0.0.1]] + + cache.adapter.default: + abstract: true + parent: cache.adapter.redis + tags: + - name: cache.pool + provider: cache.adapter.redis.connection + +framework: + cache: + pools: + test: + public: true diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index 689aa7d6b65f9..ba60449cfc2f9 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -19,7 +19,7 @@ "php": ">=5.5.9", "symfony/asset": "~2.8|~3.0", "symfony/class-loader": "~2.8|~3.0", - "symfony/dependency-injection": "~2.8|~3.0", + "symfony/dependency-injection": "~3.1", "symfony/config": "~2.8|~3.0", "symfony/event-dispatcher": "~2.8|~3.0", "symfony/http-foundation": "~3.1", @@ -38,6 +38,7 @@ }, "require-dev": { "symfony/browser-kit": "~2.8|~3.0", + "symfony/cache": "~3.1", "symfony/console": "~2.8|~3.0", "symfony/css-selector": "~2.8|~3.0", "symfony/dom-crawler": "~2.8|~3.0", diff --git a/src/Symfony/Component/Cache/Adapter/FilesystemAdapter.php b/src/Symfony/Component/Cache/Adapter/FilesystemAdapter.php index 1fac6c3f65ecb..874dec0b87931 100644 --- a/src/Symfony/Component/Cache/Adapter/FilesystemAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/FilesystemAdapter.php @@ -28,6 +28,9 @@ public function __construct($namespace = '', $defaultLifetime = 0, $directory = $directory = sys_get_temp_dir().'/symfony-cache'; } if (isset($namespace[0])) { + if (preg_match('#[^-+_.A-Za-z0-9]#', $namespace, $match)) { + throw new InvalidArgumentException(sprintf('FilesystemAdapter namespace contains "%s" but only characters in [-+_.A-Za-z0-9] are allowed.', $match[0])); + } $directory .= '/'.$namespace; } if (!file_exists($dir = $directory.'/.')) { diff --git a/src/Symfony/Component/Cache/Tests/Adapter/FilesystemTest.php b/src/Symfony/Component/Cache/Tests/Adapter/FilesystemTest.php index 28786501a86ec..15956b424b3b6 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/FilesystemTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/FilesystemTest.php @@ -25,6 +25,6 @@ public function createCachePool() $this->skippedTests['testDeferredSaveWithoutCommit'] = 'Fails on HHVM'; } - return new FilesystemAdapter(sys_get_temp_dir().DIRECTORY_SEPARATOR.'sf-cache'); + return new FilesystemAdapter('sf-cache'); } } diff --git a/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php b/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php index 246529d865cd3..e201a56b8a93c 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php @@ -58,8 +58,8 @@ public function __construct() $this->removingPasses = array( new RemovePrivateAliasesPass(), - new RemoveAbstractDefinitionsPass(), new ReplaceAliasByActualDefinitionPass(), + new RemoveAbstractDefinitionsPass(), new RepeatedPass(array( new AnalyzeServiceReferencesPass(), new InlineServiceDefinitionsPass(), @@ -102,8 +102,7 @@ public function addPass(CompilerPassInterface $pass, $type = self::TYPE_BEFORE_O throw new InvalidArgumentException(sprintf('Invalid type "%s".', $type)); } - $passes = &$this->$property; - $passes[] = $pass; + $this->{$property}[] = $pass; } /** diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php index 2f94df971a1e0..82e29255729bb 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php @@ -15,6 +15,7 @@ use Symfony\Component\DependencyInjection\DefinitionDecorator; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Exception\RuntimeException; +use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; /** * This replaces all DefinitionDecorator instances with their equivalent fully @@ -96,11 +97,12 @@ private function resolveArguments(ContainerBuilder $container, array $arguments, */ private function resolveDefinition(ContainerBuilder $container, DefinitionDecorator $definition) { - if (!$container->hasDefinition($parent = $definition->getParent())) { + try { + $parentDef = $container->findDefinition($parent = $definition->getParent()); + } catch (ServiceNotFoundException $e) { throw new RuntimeException(sprintf('The parent definition "%s" defined for definition "%s" does not exist.', $parent, $this->currentId)); } - $parentDef = $container->getDefinition($parent); if ($parentDef instanceof DefinitionDecorator) { $id = $this->currentId; $this->currentId = $parent; diff --git a/src/Symfony/Component/HttpKernel/CacheClearer/Psr6CacheClearer.php b/src/Symfony/Component/HttpKernel/CacheClearer/Psr6CacheClearer.php new file mode 100644 index 0000000000000..30261b3f7c660 --- /dev/null +++ b/src/Symfony/Component/HttpKernel/CacheClearer/Psr6CacheClearer.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\CacheClearer; + +use Psr\Cache\CacheItemPoolInterface; + +/** + * @author Nicolas Grekas + */ +class Psr6CacheClearer implements CacheClearerInterface +{ + private $pools = array(); + + public function addPool(CacheItemPoolInterface $pool) + { + $this->pools[] = $pool; + } + + /** + * {@inheritdoc} + */ + public function clear($cacheDir) + { + foreach ($this->pools as $pool) { + $pool->clear(); + } + } +} From 41526342ea1bb1f8c071411c6b7c6255e7981c09 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 6 Apr 2016 19:53:33 +0200 Subject: [PATCH 7/7] [FrameworkBundle] Add default pool & system adapter --- .../Compiler/CachePoolPass.php | 2 +- .../DependencyInjection/Configuration.php | 3 ++- .../DependencyInjection/FrameworkExtension.php | 17 ++++++++++------- .../Resources/config/cache_pools.xml | 11 ++++++++++- .../Resources/config/schema/symfony-1.0.xsd | 1 - .../DependencyInjection/ConfigurationTest.php | 3 +++ .../Functional/app/CachePools/redis_config.yml | 2 +- .../Bundle/FrameworkBundle/composer.json | 2 +- .../Cache/Tests/Adapter/RedisAdapterTest.php | 1 - .../Compiler/ResolveDefinitionTemplatesPass.php | 6 ++---- .../ResolveDefinitionTemplatesPassTest.php | 14 ++++++++++++++ 11 files changed, 44 insertions(+), 18 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php index 8e1e90cfaca58..9598f537a0c62 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php @@ -63,7 +63,7 @@ public function process(ContainerBuilder $container) unset($tags[0][$attr]); } if (!empty($tags[0])) { - throw new \InvalidArgumentException(sprintf('Invalid "cache.pool" tag for service "%s": accepted attributes are "provider", "namespace" and "default_lifetime", found "%s".', $id, implode('", "', array_keys($tags[0])))); + 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])))); } if (null !== $clearer) { diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index e125e3096a944..e298b2609ce4d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -555,6 +555,7 @@ private function addCacheSection(ArrayNodeDefinition $rootNode) ->children() ->arrayNode('cache') ->info('Cache configuration') + ->addDefaultsIfNotSet() ->fixXmlConfig('pool') ->children() ->arrayNode('pools') @@ -563,7 +564,7 @@ private function addCacheSection(ArrayNodeDefinition $rootNode) ->children() ->scalarNode('adapter') ->info('The cache pool adapter service to use as template definition.') - ->defaultValue('cache.adapter.default') + ->defaultValue('cache.adapter.shared') ->end() ->booleanNode('public')->defaultFalse()->end() ->integerNode('default_lifetime')->end() diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index ae9d79c4142f1..014f447ba103a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -122,6 +122,7 @@ public function load(array $configs, ContainerBuilder $container) $this->registerFragmentsConfiguration($config['fragments'], $container, $loader); $this->registerTranslatorConfiguration($config['translator'], $container); $this->registerProfilerConfiguration($config['profiler'], $container, $loader); + $this->registerCacheConfiguration($config['cache'], $container, $loader); if ($this->isConfigEnabled($container, $config['router'])) { $this->registerRouterConfiguration($config['router'], $container, $loader); @@ -138,10 +139,6 @@ 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'); @@ -1022,9 +1019,7 @@ private function registerPropertyInfoConfiguration(array $config, ContainerBuild private function registerCacheConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader) { - if (!empty($config['pools'])) { - $loader->load('cache_pools.xml'); - } + $loader->load('cache_pools.xml'); foreach ($config['pools'] as $name => $poolConfig) { $poolDefinition = new DefinitionDecorator($poolConfig['adapter']); @@ -1034,6 +1029,14 @@ private function registerCacheConfiguration(array $config, ContainerBuilder $con $poolDefinition->addTag('cache.pool', $poolConfig); $container->setDefinition('cache.pool.'.$name, $poolDefinition); } + + $this->addClassesToCompile(array( + 'Psr\Cache\CacheItemInterface', + 'Psr\Cache\CacheItemPoolInterface', + 'Symfony\Component\Cache\Adapter\AdapterInterface', + 'Symfony\Component\Cache\Adapter\AbstractAdapter', + 'Symfony\Component\Cache\CacheItem', + )); } /** diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache_pools.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache_pools.xml index eef88060cfe60..2874f41bf9d26 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache_pools.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache_pools.xml @@ -10,7 +10,16 @@ - + + + + + + + + + + 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 d8fc67ae29dad..aa2c057d356ec 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 @@ -216,7 +216,6 @@ - diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php index 88be0616033ff..9bcadc68102c0 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php @@ -265,6 +265,9 @@ protected static function getBundleDefaultConfig() 'base_urls' => array(), 'packages' => array(), ), + 'cache' => array( + 'pools' => array(), + ), ); } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/redis_config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/redis_config.yml index 1bafa08c7c12f..fb2510b6fa0d2 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/redis_config.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/redis_config.yml @@ -8,7 +8,7 @@ services: calls: - [connect, [127.0.0.1]] - cache.adapter.default: + cache.adapter.shared: abstract: true parent: cache.adapter.redis tags: diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index ba60449cfc2f9..8016bc3ea47c1 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -18,6 +18,7 @@ "require": { "php": ">=5.5.9", "symfony/asset": "~2.8|~3.0", + "symfony/cache": "~3.1", "symfony/class-loader": "~2.8|~3.0", "symfony/dependency-injection": "~3.1", "symfony/config": "~2.8|~3.0", @@ -38,7 +39,6 @@ }, "require-dev": { "symfony/browser-kit": "~2.8|~3.0", - "symfony/cache": "~3.1", "symfony/console": "~2.8|~3.0", "symfony/css-selector": "~2.8|~3.0", "symfony/dom-crawler": "~2.8|~3.0", diff --git a/src/Symfony/Component/Cache/Tests/Adapter/RedisAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/RedisAdapterTest.php index a41514f37d4c4..fe3eaead39de3 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/RedisAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/RedisAdapterTest.php @@ -37,7 +37,6 @@ public static function setupBeforeClass() $e = error_get_last(); self::markTestSkipped($e['message']); } - self::$redis->select(1993); } public static function tearDownAfterClass() diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php index 82e29255729bb..4451e7c435f1a 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php @@ -15,7 +15,6 @@ use Symfony\Component\DependencyInjection\DefinitionDecorator; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Exception\RuntimeException; -use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; /** * This replaces all DefinitionDecorator instances with their equivalent fully @@ -97,12 +96,11 @@ private function resolveArguments(ContainerBuilder $container, array $arguments, */ private function resolveDefinition(ContainerBuilder $container, DefinitionDecorator $definition) { - try { - $parentDef = $container->findDefinition($parent = $definition->getParent()); - } catch (ServiceNotFoundException $e) { + if (!$container->has($parent = $definition->getParent())) { throw new RuntimeException(sprintf('The parent definition "%s" defined for definition "%s" does not exist.', $parent, $this->currentId)); } + $parentDef = $container->findDefinition($parent); if ($parentDef instanceof DefinitionDecorator) { $id = $this->currentId; $this->currentId = $parent; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveDefinitionTemplatesPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveDefinitionTemplatesPassTest.php index adb7ba3bdc2b9..31663713d3ba6 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveDefinitionTemplatesPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveDefinitionTemplatesPassTest.php @@ -309,6 +309,20 @@ public function testProcessMergeAutowiringTypes() $this->assertEquals(array('Foo', 'Bar'), $def->getAutowiringTypes()); } + public function testProcessResolvesAliases() + { + $container = new ContainerBuilder(); + + $container->register('parent', 'ParentClass'); + $container->setAlias('parent_alias', 'parent'); + $container->setDefinition('child', new DefinitionDecorator('parent_alias')); + + $this->process($container); + + $def = $container->getDefinition('child'); + $this->assertSame('ParentClass', $def->getClass()); + } + protected function process(ContainerBuilder $container) { $pass = new ResolveDefinitionTemplatesPass();