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..9598f537a0c62
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php
@@ -0,0 +1,79 @@
+
+ *
+ * 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)
+ {
+ $attributes = array(
+ 'provider',
+ 'namespace',
+ 'default_lifetime',
+ );
+ foreach ($container->findTaggedServiceIds('cache.pool') as $id => $tags) {
+ $adapter = $pool = $container->getDefinition($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 (isset($tags[0]['clearer'])) {
+ $clearer = $container->getDefinition($tags[0]['clearer']);
+ } else {
+ $clearer = null;
+ }
+ 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]);
+ }
+ if (!empty($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) {
+ $clearer->addMethodCall('addPool', array(new Reference($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 69c310a9204a0..e298b2609ce4d 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,39 @@ private function addPropertyInfoSection(ArrayNodeDefinition $rootNode)
->end()
;
}
+
+ private function addCacheSection(ArrayNodeDefinition $rootNode)
+ {
+ $rootNode
+ ->children()
+ ->arrayNode('cache')
+ ->info('Cache configuration')
+ ->addDefaultsIfNotSet()
+ ->fixXmlConfig('pool')
+ ->children()
+ ->arrayNode('pools')
+ ->useAttributeAsKey('name')
+ ->prototype('array')
+ ->children()
+ ->scalarNode('adapter')
+ ->info('The cache pool adapter service to use as template definition.')
+ ->defaultValue('cache.adapter.shared')
+ ->end()
+ ->booleanNode('public')->defaultFalse()->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()
+ ->end()
+ ->end()
+ ->end()
+ ;
+ }
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
index 22b8dde6b3d56..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);
@@ -1016,6 +1017,28 @@ private function registerPropertyInfoConfiguration(array $config, ContainerBuild
}
}
+ private function registerCacheConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader)
+ {
+ $loader->load('cache_pools.xml');
+
+ foreach ($config['pools'] as $name => $poolConfig) {
+ $poolDefinition = new DefinitionDecorator($poolConfig['adapter']);
+ $poolDefinition->setPublic($poolConfig['public']);
+ unset($poolConfig['adapter'], $poolConfig['public']);
+
+ $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',
+ ));
+ }
+
/**
* 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..7ed44c5bb84d2 100644
--- a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php
+++ b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php
@@ -14,6 +14,7 @@
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddConstraintValidatorsPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddValidatorInitializersPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddConsoleCommandPass;
+use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\CachePoolPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\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 CachePoolPass());
if ($container->getParameter('kernel.debug')) {
$container->addCompilerPass(new UnusedTagsPass(), PassConfig::TYPE_AFTER_REMOVING);
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache_pools.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache_pools.xml
new file mode 100644
index 0000000000000..2874f41bf9d26
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache_pools.xml
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ %kernel.cache_dir%/pools
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
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..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
@@ -25,6 +25,7 @@
+
@@ -202,4 +203,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
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..3fc66cff09084
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/CachePoolPassTest.php
@@ -0,0 +1,85 @@
+
+ *
+ * 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;
+use Symfony\Component\DependencyInjection\Reference;
+
+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.pool');
+ $container->setDefinition('app.cache_adapter', $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);
+
+ $this->cachePoolPass->process($container);
+
+ $this->assertSame('yRnzIIVLvL', $cachePool->getArgument(0));
+ }
+
+ public function testArgsAreReplaced()
+ {
+ $container = new ContainerBuilder();
+ $cachePool = new Definition();
+ $cachePool->addTag('cache.pool', array(
+ 'provider' => 'foobar',
+ 'default_lifetime' => 3,
+ ));
+ $cachePool->addArgument(null);
+ $cachePool->addArgument(null);
+ $cachePool->addArgument(null);
+ $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.pool" tag for service "app.cache_pool": accepted attributes are
+ */
+ public function testThrowsExceptionWhenCachePoolTagHasUnknownAttributes()
+ {
+ $container = new ContainerBuilder();
+ $adapter = new Definition();
+ $adapter->setAbstract(true);
+ $adapter->addTag('cache.pool');
+ $container->setDefinition('app.cache_adapter', $adapter);
+ $cachePool = new DefinitionDecorator('app.cache_adapter');
+ $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/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/DependencyInjection/Fixtures/php/cache.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/cache.php
new file mode 100644
index 0000000000000..7cf634b92e394
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/cache.php
@@ -0,0 +1,29 @@
+loadFromExtension('framework', array(
+ 'cache' => array(
+ 'pools' => array(
+ 'foo' => array(
+ 'adapter' => 'cache.adapter.apcu',
+ 'default_lifetime' => 30,
+ ),
+ 'bar' => array(
+ 'adapter' => 'cache.adapter.doctrine',
+ 'default_lifetime' => 5,
+ 'provider' => 'app.doctrine_cache_provider',
+ ),
+ 'baz' => array(
+ 'adapter' => 'cache.adapter.filesystem',
+ 'default_lifetime' => 7,
+ ),
+ 'foobar' => array(
+ 'adapter' => 'cache.adapter.psr6',
+ 'default_lifetime' => 10,
+ '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
new file mode 100644
index 0000000000000..d6f472716ff89
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/cache.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
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..395009f18ad18
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/cache.yml
@@ -0,0 +1,19 @@
+framework:
+ cache:
+ pools:
+ foo:
+ adapter: cache.adapter.apcu
+ default_lifetime: 30
+ bar:
+ adapter: cache.adapter.doctrine
+ default_lifetime: 5
+ provider: app.doctrine_cache_provider
+ baz:
+ adapter: cache.adapter.filesystem
+ default_lifetime: 7
+ foobar:
+ adapter: cache.adapter.psr6
+ default_lifetime: 10
+ 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 55d9a16e77e5c..000ec8e6ff385 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,17 @@ public function testPropertyInfoEnabled()
$this->assertTrue($container->has('property_info'));
}
+ public function testCachePoolServices()
+ {
+ $container = $this->createContainerFromFile('cache');
+
+ $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())
{
return new ContainerBuilder(new ParameterBag(array_merge(array(
@@ -636,4 +650,39 @@ private function assertVersionStrategy(ContainerBuilder $container, Reference $r
$this->assertEquals($format, $versionStrategy->getArgument(1));
}
}
+
+ 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, $adapter));
+
+ $poolDefinition = $container->getDefinition($id);
+
+ $this->assertInstanceOf(DefinitionDecorator::class, $poolDefinition, sprintf('Cache pool "%s" is based on an abstract cache pool.', $name));
+
+ $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));
+
+ $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 'cache.adapter.doctrine':
+ $this->assertSame(DoctrineAdapter::class, $adapterDefinition->getClass());
+ break;
+ case 'cache.adapter.filesystem':
+ $this->assertSame(FilesystemAdapter::class, $adapterDefinition->getClass());
+ break;
+ }
+
+ $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..fb2510b6fa0d2
--- /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.shared:
+ 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..8016bc3ea47c1 100644
--- a/src/Symfony/Bundle/FrameworkBundle/composer.json
+++ b/src/Symfony/Bundle/FrameworkBundle/composer.json
@@ -18,8 +18,9 @@
"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": "~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",
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..874dec0b87931 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);
@@ -28,6 +28,9 @@ public function __construct($directory, $defaultLifetime = 0, $namespace = '')
$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/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/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/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');
}
}
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/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..4451e7c435f1a 100644
--- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php
+++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php
@@ -96,11 +96,11 @@ private function resolveArguments(ContainerBuilder $container, array $arguments,
*/
private function resolveDefinition(ContainerBuilder $container, DefinitionDecorator $definition)
{
- if (!$container->hasDefinition($parent = $definition->getParent())) {
+ 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->getDefinition($parent);
+ $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();
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();
+ }
+ }
+}