[FrameworkBundle] Allow clearing private cache pools
This commit is contained in:
parent
635d77b32a
commit
b71df3f295
@ -18,3 +18,9 @@ SecurityBundle
|
||||
|
||||
* The `FirewallContext::getContext()` method has been deprecated and will be removed in 4.0.
|
||||
Use the `getListeners()` method instead.
|
||||
|
||||
HttpKernel
|
||||
-----------
|
||||
|
||||
* The `Psr6CacheClearer::addPool()` method has been deprecated. Pass an array of pools indexed
|
||||
by name to the constructor instead.
|
||||
|
@ -175,6 +175,9 @@ HttpKernel
|
||||
|
||||
* The `DataCollector::varToString()` method has been removed in favor of `cloneVar()`.
|
||||
|
||||
* The `Psr6CacheClearer::addPool()` method has been removed. Pass an array of pools indexed
|
||||
by name to the constructor instead.
|
||||
|
||||
Security
|
||||
--------
|
||||
|
||||
|
@ -55,16 +55,21 @@ EOF
|
||||
$clearers = array();
|
||||
$container = $this->getContainer();
|
||||
$cacheDir = $container->getParameter('kernel.cache_dir');
|
||||
$globalClearer = $container->get('cache.global_clearer');
|
||||
|
||||
foreach ($input->getArgument('pools') as $id) {
|
||||
$pool = $container->get($id);
|
||||
|
||||
if ($pool instanceof CacheItemPoolInterface) {
|
||||
$pools[$id] = $pool;
|
||||
} elseif ($pool instanceof Psr6CacheClearer) {
|
||||
$clearers[$id] = $pool;
|
||||
if ($globalClearer->hasPool($id)) {
|
||||
$pools[$id] = $id;
|
||||
} else {
|
||||
throw new \InvalidArgumentException(sprintf('"%s" is not a cache pool nor a cache clearer.', $id));
|
||||
$pool = $container->get($id);
|
||||
|
||||
if ($pool instanceof CacheItemPoolInterface) {
|
||||
$pools[$id] = $pool;
|
||||
} elseif ($pool instanceof Psr6CacheClearer) {
|
||||
$clearers[$id] = $pool;
|
||||
} else {
|
||||
throw new \InvalidArgumentException(sprintf('"%s" is not a cache pool nor a cache clearer.', $id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,7 +80,12 @@ EOF
|
||||
|
||||
foreach ($pools as $id => $pool) {
|
||||
$io->comment(sprintf('Clearing cache pool: <info>%s</info>', $id));
|
||||
$pool->clear();
|
||||
|
||||
if ($pool instanceof CacheItemPoolInterface) {
|
||||
$pool->clear();
|
||||
} else {
|
||||
$globalClearer->clearPool($id);
|
||||
}
|
||||
}
|
||||
|
||||
$io->success('Cache was successfully cleared.');
|
||||
|
@ -27,19 +27,31 @@ final class CachePoolClearerPass implements CompilerPassInterface
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
$container->getParameterBag()->remove('cache.prefix.seed');
|
||||
$poolsByClearer = array();
|
||||
$pools = array();
|
||||
|
||||
foreach ($container->findTaggedServiceIds('cache.pool') as $id => $attributes) {
|
||||
$pools[$id] = new Reference($id);
|
||||
foreach (array_reverse($attributes) as $attr) {
|
||||
if (isset($attr['clearer'])) {
|
||||
$clearer = $container->getDefinition($attr['clearer']);
|
||||
$clearer->addMethodCall('addPool', array(new Reference($id)));
|
||||
$poolsByClearer[$attr['clearer']][$id] = $pools[$id];
|
||||
}
|
||||
if (array_key_exists('clearer', $attr)) {
|
||||
if (!empty($attr['unlazy'])) {
|
||||
$container->getDefinition($id)->setLazy(false);
|
||||
}
|
||||
if (array_key_exists('clearer', $attr) || array_key_exists('unlazy', $attr)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$container->getDefinition('cache.global_clearer')->addArgument($pools);
|
||||
|
||||
foreach ($poolsByClearer as $clearer => $pools) {
|
||||
$clearer = $container->getDefinition($clearer);
|
||||
$clearer->addArgument($pools);
|
||||
}
|
||||
|
||||
if (!$container->has('cache.annotations')) {
|
||||
return;
|
||||
}
|
||||
|
@ -47,8 +47,10 @@ class CachePoolPass implements CompilerPassInterface
|
||||
if ($pool->isAbstract()) {
|
||||
continue;
|
||||
}
|
||||
$isLazy = $pool->isLazy();
|
||||
while ($adapter instanceof DefinitionDecorator) {
|
||||
$adapter = $container->findDefinition($adapter->getParent());
|
||||
$isLazy = $isLazy || $adapter->isLazy();
|
||||
if ($t = $adapter->getTag('cache.pool')) {
|
||||
$tags[0] += $t[0];
|
||||
}
|
||||
@ -80,8 +82,16 @@ class CachePoolPass implements CompilerPassInterface
|
||||
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]))));
|
||||
}
|
||||
|
||||
$attr = array();
|
||||
if (null !== $clearer) {
|
||||
$pool->addTag('cache.pool', array('clearer' => $clearer));
|
||||
$attr['clearer'] = $clearer;
|
||||
}
|
||||
if (!$isLazy) {
|
||||
$pool->setLazy(true);
|
||||
$attr['unlazy'] = true;
|
||||
}
|
||||
if ($attr) {
|
||||
$pool->addTag('cache.pool', $attr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -97,6 +97,7 @@
|
||||
<tag name="kernel.cache_clearer" />
|
||||
</service>
|
||||
|
||||
<service id="cache.global_clearer" parent="cache.default_clearer" />
|
||||
<service id="cache.app_clearer" alias="cache.default_clearer" />
|
||||
|
||||
</services>
|
||||
|
@ -18,6 +18,7 @@ use Symfony\Component\DependencyInjection\Compiler\RepeatedPass;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
use Symfony\Component\HttpKernel\CacheClearer\Psr6CacheClearer;
|
||||
|
||||
class CachePoolClearerPassTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
@ -29,6 +30,9 @@ class CachePoolClearerPassTest extends \PHPUnit_Framework_TestCase
|
||||
$container->setParameter('kernel.environment', 'prod');
|
||||
$container->setParameter('kernel.root_dir', 'foo');
|
||||
|
||||
$globalClearer = new Definition(Psr6CacheClearer::class);
|
||||
$container->setDefinition('cache.global_clearer', $globalClearer);
|
||||
|
||||
$publicPool = new Definition();
|
||||
$publicPool->addArgument('namespace');
|
||||
$publicPool->addTag('cache.pool', array('clearer' => 'clearer_alias'));
|
||||
@ -50,6 +54,7 @@ class CachePoolClearerPassTest extends \PHPUnit_Framework_TestCase
|
||||
$pass->process($container);
|
||||
}
|
||||
|
||||
$this->assertEquals(array(array('addPool', array(new Reference('public.pool')))), $clearer->getMethodCalls());
|
||||
$this->assertEquals(array(array('public.pool' => new Reference('public.pool'))), $clearer->getArguments());
|
||||
$this->assertEquals(array(array('public.pool' => new Reference('public.pool'))), $globalClearer->getArguments());
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Bundle\FrameworkBundle\Tests\Functional;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Command\CachePoolClearCommand;
|
||||
use Symfony\Component\Console\Tester\CommandTester;
|
||||
|
||||
/**
|
||||
* @group functional
|
||||
*/
|
||||
class CachePoolClearCommandTest extends WebTestCase
|
||||
{
|
||||
private $application;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
static::bootKernel(array('test_case' => 'CachePoolClear', 'root_config' => 'config.yml'));
|
||||
}
|
||||
|
||||
public function testClearPrivatePool()
|
||||
{
|
||||
$tester = $this->createCommandTester();
|
||||
$tester->execute(array('pools' => array('cache.private_pool')), array('decorated' => false));
|
||||
|
||||
$this->assertSame(0, $tester->getStatusCode(), 'cache:pool:clear exits with 0 in case of success');
|
||||
$this->assertContains('Clearing cache pool: cache.private_pool', $tester->getDisplay());
|
||||
$this->assertContains('[OK] Cache was successfully cleared.', $tester->getDisplay());
|
||||
}
|
||||
|
||||
public function testClearPublicPool()
|
||||
{
|
||||
$tester = $this->createCommandTester();
|
||||
$tester->execute(array('pools' => array('cache.public_pool')), array('decorated' => false));
|
||||
|
||||
$this->assertSame(0, $tester->getStatusCode(), 'cache:pool:clear exits with 0 in case of success');
|
||||
$this->assertContains('Clearing cache pool: cache.public_pool', $tester->getDisplay());
|
||||
$this->assertContains('[OK] Cache was successfully cleared.', $tester->getDisplay());
|
||||
}
|
||||
|
||||
public function testClearPoolWithCustomClearer()
|
||||
{
|
||||
$tester = $this->createCommandTester();
|
||||
$tester->execute(array('pools' => array('cache.pool_with_clearer')), array('decorated' => false));
|
||||
|
||||
$this->assertSame(0, $tester->getStatusCode(), 'cache:pool:clear exits with 0 in case of success');
|
||||
$this->assertContains('Clearing cache pool: cache.pool_with_clearer', $tester->getDisplay());
|
||||
$this->assertContains('[OK] Cache was successfully cleared.', $tester->getDisplay());
|
||||
}
|
||||
|
||||
public function testCallClearer()
|
||||
{
|
||||
$tester = $this->createCommandTester();
|
||||
$tester->execute(array('pools' => array('cache.default_clearer')), array('decorated' => false));
|
||||
|
||||
$this->assertSame(0, $tester->getStatusCode(), 'cache:pool:clear exits with 0 in case of success');
|
||||
$this->assertContains('Calling cache clearer: cache.default_clearer', $tester->getDisplay());
|
||||
$this->assertContains('[OK] Cache was successfully cleared.', $tester->getDisplay());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException
|
||||
* @expectedExceptionMessage You have requested a non-existent service "unknown_pool"
|
||||
*/
|
||||
public function testClearUnexistingPool()
|
||||
{
|
||||
$this->createCommandTester()
|
||||
->execute(array('pools' => array('unknown_pool')), array('decorated' => false));
|
||||
}
|
||||
|
||||
private function createCommandTester()
|
||||
{
|
||||
$command = new CachePoolClearCommand();
|
||||
$command->setContainer(static::$kernel->getContainer());
|
||||
|
||||
return new CommandTester($command);
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestBundle;
|
||||
use Symfony\Bundle\FrameworkBundle\FrameworkBundle;
|
||||
|
||||
return array(
|
||||
new FrameworkBundle(),
|
||||
new TestBundle(),
|
||||
);
|
@ -0,0 +1,21 @@
|
||||
imports:
|
||||
- { resource: ../config/default.yml }
|
||||
|
||||
services:
|
||||
dummy:
|
||||
class: Symfony\Bundle\FrameworkBundle\Tests\Fixtures\DeclaredClass
|
||||
arguments: ['@cache.private_pool']
|
||||
custom_clearer:
|
||||
parent: cache.default_clearer
|
||||
tags:
|
||||
- name: kernel.cache_clearer
|
||||
|
||||
framework:
|
||||
cache:
|
||||
pools:
|
||||
cache.private_pool: ~
|
||||
cache.public_pool:
|
||||
public: true
|
||||
cache.pool_with_clearer:
|
||||
public: true
|
||||
clearer: custom_clearer
|
@ -23,7 +23,7 @@
|
||||
"symfony/config": "~2.8|~3.0",
|
||||
"symfony/event-dispatcher": "~2.8|~3.0",
|
||||
"symfony/http-foundation": "~3.1",
|
||||
"symfony/http-kernel": "~3.2",
|
||||
"symfony/http-kernel": "~3.3",
|
||||
"symfony/polyfill-mbstring": "~1.0",
|
||||
"symfony/filesystem": "~2.8|~3.0",
|
||||
"symfony/finder": "~2.8|~3.0",
|
||||
|
@ -20,11 +20,32 @@ class Psr6CacheClearer implements CacheClearerInterface
|
||||
{
|
||||
private $pools = array();
|
||||
|
||||
public function __construct(array $pools = array())
|
||||
{
|
||||
$this->pools = $pools;
|
||||
}
|
||||
|
||||
public function addPool(CacheItemPoolInterface $pool)
|
||||
{
|
||||
@trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Pass an array of pools indexed by name to the constructor instead.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
$this->pools[] = $pool;
|
||||
}
|
||||
|
||||
public function hasPool($name)
|
||||
{
|
||||
return isset($this->pools[$name]);
|
||||
}
|
||||
|
||||
public function clearPool($name)
|
||||
{
|
||||
if (!isset($this->pools[$name])) {
|
||||
throw new \InvalidArgumentException(sprintf('Cache pool not found: %s.', $name));
|
||||
}
|
||||
|
||||
return $this->pools[$name]->clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpKernel\Tests\CacheClearer;
|
||||
|
||||
use Symfony\Component\HttpKernel\CacheClearer\Psr6CacheClearer;
|
||||
use Psr\Cache\CacheItemPoolInterface;
|
||||
|
||||
class Psr6CacheClearerTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testClearPoolsInjectedInConstructor()
|
||||
{
|
||||
$pool = $this->getMock(CacheItemPoolInterface::class);
|
||||
$pool
|
||||
->expects($this->once())
|
||||
->method('clear');
|
||||
|
||||
(new Psr6CacheClearer(array('pool' => $pool)))->clear('');
|
||||
}
|
||||
|
||||
public function testClearPool()
|
||||
{
|
||||
$pool = $this->getMock(CacheItemPoolInterface::class);
|
||||
$pool
|
||||
->expects($this->once())
|
||||
->method('clear');
|
||||
|
||||
(new Psr6CacheClearer(array('pool' => $pool)))->clearPool('pool');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
* @expectedExceptionMessage Cache pool not found: unknown
|
||||
*/
|
||||
public function testClearPoolThrowsExceptionOnUnreferencedPool()
|
||||
{
|
||||
(new Psr6CacheClearer())->clearPool('unknown');
|
||||
}
|
||||
|
||||
/**
|
||||
* @group legacy
|
||||
* @expectedDeprecation The Symfony\Component\HttpKernel\CacheClearer\Psr6CacheClearer::addPool() method is deprecated since version 3.3 and will be removed in 4.0. Pass an array of pools indexed by name to the constructor instead.
|
||||
*/
|
||||
public function testClearPoolsInjectedByAdder()
|
||||
{
|
||||
$pool1 = $this->getMock(CacheItemPoolInterface::class);
|
||||
$pool1
|
||||
->expects($this->once())
|
||||
->method('clear');
|
||||
|
||||
$pool2 = $this->getMock(CacheItemPoolInterface::class);
|
||||
$pool2
|
||||
->expects($this->once())
|
||||
->method('clear');
|
||||
|
||||
$clearer = new Psr6CacheClearer(array('pool1' => $pool1));
|
||||
$clearer->addPool($pool2);
|
||||
$clearer->clear('');
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user