8000 feature #20810 [FrameworkBundle] Allow clearing private cache pools i… · symfony/symfony@6751dc1 · GitHub
[go: up one dir, main page]

Skip to content

Commit 6751dc1

Browse files
committed
feature #20810 [FrameworkBundle] Allow clearing private cache pools in cache:pool:clear (chalasr)
This PR was merged into the 3.3-dev branch. Discussion ---------- [FrameworkBundle] Allow clearing private cache pools in cache:pool:clear | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | n/a | License | MIT | Doc PR | n/a In a2a567d cache pools have been passed to `public: false` by default. The problem is that in 3.2 the `cache:pool:clear` command has been introduced and uses `Container::get($pool);` for clearing them, but the service can't be found since it is private. So I propose to add a global clearer being able to clear any pool. Commits ------- b71df3f [FrameworkBundle] Allow clearing private cache pools
2 parents 635d77b + b71df3f commit 6751dc1

File tree

13 files changed

+275
-14
lines changed

13 files changed

+275
-14
lines changed

UPGRADE-3.3.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,9 @@ SecurityBundle
1818

1919
* The `FirewallContext::getContext()` method has been deprecated and will be removed in 4.0.
2020
Use the `getListeners()` method instead.
21+
22+
HttpKernel
23+
-----------
24+
25+
* The `Psr6CacheClearer::addPool()` method has been deprecated. Pass an array of pools indexed
26+
by name to the constructor instead.

UPGRADE-4.0.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,9 @@ HttpKernel
175175

176176
* The `DataCollector::varToString()` method has been removed in favor of `cloneVar()`.
177177

178+
* The `Psr6CacheClearer::addPool()` method has been removed. Pass an array of pools indexed
179+
by name to the constructor instead.
180+
178181
Security
179182
--------
180183

src/Symfony/Bundle/FrameworkBundle/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.');

src/Symfony/Bundle/FrameworkBundle/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
}

src/Symfony/Bundle/FrameworkBundle/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
}

src/Symfony/Bundle/FrameworkBundle/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+< 1241 div class="diff-text-inner"> <service id="cache.global_clearer" parent="cache.default_clearer" />
100101
<service id="cache.app_clearer" alias="cache.default_clearer" />
101102

102103
</services>

src/Symfony/Bundle/FrameworkBundle/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 <fabien@symfony.com>
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 <fabien@symfony.com>
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
< 10000 div data-testid="addition diffstat" class="DiffSquares-module__diffSquare--h5kjy DiffSquares-module__addition--jeNtt">
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

src/Symfony/Bundle/FrameworkBundle/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",

src/Symfony/Component/HttpKernel/CacheClearer/Psr6CacheClearer.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,32 @@ class Psr6CacheClearer implements CacheClearerInterface
2020
{
2121
private $pools = array();
2222

23+
public function __construct(array $pools = array())
24+
{
25+
$this->pools = $pools;
26+
}
27+
2328
public function addPool(CacheItemPoolInterface $pool)
2429
{
30+
@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);
31+
2532
$this->pools[] = $pool;
2633
}
2734

35+
public function hasPool($name)
36+
{
37+
return isset($this->pools[$name]);
38+
}
39+
40+
public function clearPool($name)
41+
{
42+
if (!isset($this->pools[$name])) {
43+
throw new \InvalidArgumentException(sprintf('Cache pool not found: %s.', $name));
44+
}
45+
46+
return $this->pools[$name]->clear();
47+
}
48+
2849
/**
2950
* {@inheritdoc}
3051
*/

0 commit comments

Comments
 (0)
0