Skip to content

Commit 6737ebe

Browse files
committed
[FrameworkBundle] Allow clearing private cache pools
1 parent 2810e72 commit 6737ebe

File tree

9 files changed

+177
-14
lines changed

9 files changed

+177
-14
lines changed

Command/CachePoolClearCommand.php

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -55,16 +55,21 @@ protected function execute(InputInterface $input, OutputInterface $output)
5555
$clearers = array();
5656
$container = $this->getContainer();
5757
$cacheDir = $container->getParameter('kernel.cache_dir');
58+
$globalClearer = $container->get('cache.global_clearer');
5859

5960
foreach ($input->getArgument('pools') as $id) {
60-
$pool = $container->get($id);
61-
62-
if ($pool instanceof CacheItemPoolInterface) {
63-
$pools[$id] = $pool;
64-
} elseif ($pool instanceof Psr6CacheClearer) {
65-
$clearers[$id] = $pool;
61+
if ($globalClearer->hasPool($id)) {
62+
$pools[$id] = $id;
6663
} else {
67-
throw new \InvalidArgumentException(sprintf('"%s" is not a cache pool nor a cache clearer.', $id));
64+
$pool = $container->get($id);
65+
66+
if ($pool instanceof CacheItemPoolInterface) {
67+
$pools[$id] = $pool;
68+
} elseif ($pool instanceof Psr6CacheClearer) {
69+
$clearers[$id] = $pool;
70+
} else {
71+
throw new \InvalidArgumentException(sprintf('"%s" is not a cache pool nor a cache clearer.', $id));
72+
}
6873
}
6974
}
7075

@@ -75,7 +80,12 @@ protected function execute(InputInterface $input, OutputInterface $output)
7580

7681
foreach ($pools as $id => $pool) {
7782
$io->comment(sprintf('Clearing cache pool: <info>%s</info>', $id));
78-
$pool->clear();
83+
84+
if ($pool instanceof CacheItemPoolInterface) {
85+
$pool->clear();
86+
} else {
87+
$globalClearer->clearPool($id);
88+
}
7989
}
8090

8191
$io->success('Cache was successfully cleared.');

DependencyInjection/Compiler/CachePoolClearerPass.php

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,31 @@ final class CachePoolClearerPass implements CompilerPassInterface
2727
public function process(ContainerBuilder $container)
2828
{
2929
$container->getParameterBag()->remove('cache.prefix.seed');
30+
$poolsByClearer = array();
31+
$pools = array();
3032

3133
foreach ($container->findTaggedServiceIds('cache.pool') as $id => $attributes) {
34+
$pools[$id] = new Reference($id);
3235
foreach (array_reverse($attributes) as $attr) {
3336
if (isset($attr['clearer'])) {
34-
$clearer = $container->getDefinition($attr['clearer']);
35-
$clearer->addMethodCall('addPool', array(new Reference($id)));
37+
$poolsByClearer[$attr['clearer']][$id] = $pools[$id];
3638
}
37-
if (array_key_exists('clearer', $attr)) {
39+
if (!empty($attr['unlazy'])) {
40+
$container->getDefinition($id)->setLazy(false);
41+
}
42+
if (array_key_exists('clearer', $attr) || array_key_exists('unlazy', $attr)) {
3843
break;
3944
}
4045
}
4146
}
4247

48+
$container->getDefinition('cache.global_clearer')->addArgument($pools);
49+
50+
foreach ($poolsByClearer as $clearer => $pools) {
51+
$clearer = $container->getDefinition($clearer);
52+
$clearer->addArgument($pools);
53+
}
54+
4355
if (!$container->has('cache.annotations')) {
4456
return;
4557
}

DependencyInjection/Compiler/CachePoolPass.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,10 @@ public function process(ContainerBuilder $container)
4747
if ($pool->isAbstract()) {
4848
continue;
4949
}
50+
$isLazy = $pool->isLazy();
5051
while ($adapter instanceof DefinitionDecorator) {
5152
$adapter = $container->findDefinition($adapter->getParent());
53+
$isLazy = $isLazy || $adapter->isLazy();
5254
if ($t = $adapter->getTag('cache.pool')) {
5355
$tags[0] += $t[0];
5456
}
@@ -80,8 +82,16 @@ public function process(ContainerBuilder $container)
8082
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]))));
8183
}
8284

85+
$attr = array();
8386
if (null !== $clearer) {
84-
$pool->addTag('cache.pool', array('clearer' => $clearer));
87+
$attr['clearer'] = $clearer;
88+
}
89+
if (!$isLazy) {
90+
$pool->setLazy(true);
91+
$attr['unlazy'] = true;
92+
}
93+
if ($attr) {
94+
$pool->addTag('cache.pool', $attr);
8595
}
8696
}
8797
}

Resources/config/cache.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@
9797
<tag name="kernel.cache_clearer" />
9898
</service>
9999

100+
<service id="cache.global_clearer" parent="cache.default_clearer" />
100101
<service id="cache.app_clearer" alias="cache.default_clearer" />
101102

102103
</services>

Tests/DependencyInjection/Compiler/CachePoolClearerPassTest.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use Symfony\Component\DependencyInjection\ContainerBuilder;
1919
use Symfony\Component\DependencyInjection\Definition;
2020
use Symfony\Component\DependencyInjection\Reference;
21+
use Symfony\Component\HttpKernel\CacheClearer\Psr6CacheClearer;
2122

2223
class CachePoolClearerPassTest extends \PHPUnit_Framework_TestCase
2324
{
@@ -29,6 +30,9 @@ public function testPoolRefsAreWeak()
2930
$container->setParameter('kernel.environment', 'prod');
3031
$container->setParameter('kernel.root_dir', 'foo');
3132

33+
$globalClearer = new Definition(Psr6CacheClearer::class);
34+
$container->setDefinition('cache.global_clearer', $globalClearer);
35+
3236
$publicPool = new Definition();
3337
$publicPool->addArgument('namespace');
3438
$publicPool->addTag('cache.pool', array('clearer' => 'clearer_alias'));
@@ -50,6 +54,7 @@ public function testPoolRefsAreWeak()
5054
$pass->process($container);
5155
}
5256

53-
$this->assertEquals(array(array('addPool', array(new Reference('public.pool')))), $clearer->getMethodCalls());
57+
$this->assertEquals(array(array('public.pool' => new Reference('public.pool'))), $clearer->getArguments());
58+
$this->assertEquals(array(array('public.pool' => new Reference('public.pool'))), $globalClearer->getArguments());
5459
}
5560
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bundle\FrameworkBundle\Tests\Functional;
13+
14+
use Symfony\Bundle\FrameworkBundle\Command\CachePoolClearCommand;
15+
use Symfony\Component\Console\Tester\CommandTester;
16+
17+
/**
18+
* @group functional
19+
*/
20+
class CachePoolClearCommandTest extends WebTestCase
21+
{
22+
private $application;
23+
24+
protected function setUp()
25+
{
26+
static::bootKernel(array('test_case' => 'CachePoolClear', 'root_config' => 'config.yml'));
27+
}
28+
29+
public function testClearPrivatePool()
30+
{
31+
$tester = $this->createCommandTester();
32+
$tester->execute(array('pools' => array('cache.private_pool')), array('decorated' => false));
33+
34+
$this->assertSame(0, $tester->getStatusCode(), 'cache:pool:clear exits with 0 in case of success');
35+
$this->assertContains('Clearing cache pool: cache.private_pool', $tester->getDisplay());
36+
$this->assertContains('[OK] Cache was successfully cleared.', $tester->getDisplay());
37+
}
38+
39+
public function testClearPublicPool()
40+
{
41+
$tester = $this->createCommandTester();
42+
$tester->execute(array('pools' => array('cache.public_pool')), array('decorated' => false));
43+
44+
$this->assertSame(0, $tester->getStatusCode(), 'cache:pool:clear exits with 0 in case of success');
45+
$this->assertContains('Clearing cache pool: cache.public_pool', $tester->getDisplay());
46+
$this->assertContains('[OK] Cache was successfully cleared.', $tester->getDisplay());
47+
}
48+
49+
public function testClearPoolWithCustomClearer()
50+
{
51+
$tester = $this->createCommandTester();
52+
$tester->execute(array('pools' => array('cache.pool_with_clearer')), array('decorated' => false));
53+
54+
$this->assertSame(0, $tester->getStatusCode(), 'cache:pool:clear exits with 0 in case of success');
55+
$this->assertContains('Clearing cache pool: cache.pool_with_clearer', $tester->getDisplay());
56+
$this->assertContains('[OK] Cache was successfully cleared.', $tester->getDisplay());
57+
}
58+
59+
public function testCallClearer()
60+
{
61+
$tester = $this->createCommandTester();
62+
$tester->execute(array('pools' => array('cache.default_clearer')), array('decorated' => false));
63+
64+
$this->assertSame(0, $tester->getStatusCode(), 'cache:pool:clear exits with 0 in case of success');
65+
$this->assertContains('Calling cache clearer: cache.default_clearer', $tester->getDisplay());
66+
$this->assertContains('[OK] Cache was successfully cleared.', $tester->getDisplay());
67+
}
68+
69+
/**
70+
* @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException
71+
* @expectedExceptionMessage You have requested a non-existent service "unknown_pool"
72+
*/
73+
public function testClearUnexistingPool()
74+
{
75+
$this->createCommandTester()
76+
->execute(array('pools' => array('unknown_pool')), array('decorated' => false));
77+
}
78+
79+
private function createCommandTester()
80+
{
81+
$command = new CachePoolClearCommand();
82+
$command->setContainer(static::$kernel->getContainer());
83+
84+
return new CommandTester($command);
85+
}
86+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestBundle;
13+
use Symfony\Bundle\FrameworkBundle\FrameworkBundle;
14+
15+
return array(
16+
new FrameworkBundle(),
17+
new TestBundle(),
18+
);
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
imports:
2+
- { resource: ../config/default.yml }
3+
4+
services:
5+
dummy:
6+
class: Symfony\Bundle\FrameworkBundle\Tests\Fixtures\DeclaredClass
7+
arguments: ['@cache.private_pool']
8+
custom_clearer:
9+
parent: cache.default_clearer
10+
tags:
11+
- name: kernel.cache_clearer
12+
13+
framework:
14+
cache:
15+
pools:
16+
cache.private_pool: ~
17+
cache.public_pool:
18+
public: true
19+
cache.pool_with_clearer:
20+
public: true
21+
clearer: custom_clearer

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"symfony/config": "~2.8|~3.0",
2424
"symfony/event-dispatcher": "~2.8|~3.0",
2525
"symfony/http-foundation": "~3.1",
26-
"symfony/http-kernel": "~3.2",
26+
"symfony/http-kernel": "~3.3",
2727
"symfony/polyfill-mbstring": "~1.0",
2828
"symfony/filesystem": "~2.8|~3.0",
2929
"symfony/finder": "~2.8|~3.0",

0 commit comments

Comments
 (0)