Skip to content

Commit 2e328b0

Browse files
committed
add (pdo|chain) cache (adapter|simple) prune method
1 parent f0d0c5f commit 2e328b0

14 files changed

+311
-8
lines changed

src/Symfony/Component/Cache/Adapter/ChainAdapter.php

+13-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
use Psr\Cache\CacheItemPoolInterface;
1616
use Symfony\Component\Cache\CacheItem;
1717
use Symfony\Component\Cache\Exception\InvalidArgumentException;
18+
use Symfony\Component\Cache\PruneableInterface;
19+
use Symfony\Component\Cache\Traits\ChainTrait;
1820

1921
/**
2022
* Chains several adapters together.
@@ -24,8 +26,10 @@
2426
*
2527
* @author Kévin Dunglas <dunglas@gmail.com>
2628
*/
27-
class ChainAdapter implements AdapterInterface
29+
class ChainAdapter implements AdapterInterface, PruneableInterface
2830
{
31+
use ChainTrait;
32+
2933
private $adapters = array();
3034
private $adapterCount;
3135
private $saveUp;
@@ -231,4 +235,12 @@ public function commit()
231235

232236
return $committed;
233237
}
238+
239+
/**
240+
* {@inheritdoc}
241+
*/
242+
public function prune()
243+
{
244+
return $this->doPrune($this->adapters);
245+
}
234246
}

src/Symfony/Component/Cache/Adapter/PdoAdapter.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@
1111

1212
namespace Symfony\Component\Cache\Adapter;
1313

14+
use Symfony\Component\Cache\PruneableInterface;
1415
use Symfony\Component\Cache\Traits\PdoTrait;
1516

16-
class PdoAdapter extends AbstractAdapter
17+
class PdoAdapter extends AbstractAdapter implements PruneableInterface
1718
{
1819
use PdoTrait;
1920

src/Symfony/Component/Cache/CHANGELOG.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ CHANGELOG
55
-----
66

77
* added PruneableInterface so PSR-6 or PSR-16 cache implementations can declare support for manual stale cache pruning
8-
* added FilesystemTrait::prune() and PhpFilesTrait::prune() implementations
9-
* now FilesystemAdapter, PhpFilesAdapter, FilesystemCache, and PhpFilesCache implement PruneableInterface and support
10-
manual stale cache pruning
8+
* added prune logic to FilesystemTrait, PhpFilesTrait, PdoTrait, and ChainTrait
9+
* now FilesystemAdapter, PhpFilesAdapter, FilesystemCache, PhpFilesCache, PdoAdapter, PdoCache, ChainAdapter, and
10+
ChainCache implement PruneableInterface and support manual stale cache pruning
1111

1212
3.3.0
1313
-----

src/Symfony/Component/Cache/Simple/ChainCache.php

+13-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313

1414
use Psr\SimpleCache\CacheInterface;
1515
use Symfony\Component\Cache\Exception\InvalidArgumentException;
16+
use Symfony\Component\Cache\PruneableInterface;
17+
use Symfony\Component\Cache\Traits\ChainTrait;
1618

1719
/**
1820
* Chains several caches together.
@@ -22,8 +24,10 @@
2224
*
2325
* @author Nicolas Grekas <p@tchwork.com>
2426
*/
25-
class ChainCache implements CacheInterface
27+
class ChainCache implements CacheInterface, PruneableInterface
2628
{
29+
use ChainTrait;
30+
2731
private $miss;
2832
private $caches = array();
2933
private $defaultLifetime;
@@ -219,4 +223,12 @@ public function setMultiple($values, $ttl = null)
219223

220224
return $saved;
221225
}
226+
227+
/**
228+
* {@inheritdoc}
229+
*/
230+
public function prune()
231+
{
232+
return $this->doPrune($this->caches);
233+
}
222234
}

src/Symfony/Component/Cache/Simple/PdoCache.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@
1111

1212
namespace Symfony\Component\Cache\Simple;
1313

14+
use Symfony\Component\Cache\PruneableInterface;
1415
use Symfony\Component\Cache\Traits\PdoTrait;
1516

16-
class PdoCache extends AbstractCache
17+
class PdoCache extends AbstractCache implements PruneableInterface
1718
{
1819
use PdoTrait;
1920

src/Symfony/Component/Cache/Tests/Adapter/ChainAdapterTest.php

+71
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,11 @@
1111

1212
namespace Symfony\Component\Cache\Tests\Adapter;
1313

14+
use Symfony\Component\Cache\Adapter\AdapterInterface;
1415
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
1516
use Symfony\Component\Cache\Adapter\ArrayAdapter;
1617
use Symfony\Component\Cache\Adapter\ChainAdapter;
18+
use Symfony\Component\Cache\PruneableInterface;
1719
use Symfony\Component\Cache\Tests\Fixtures\ExternalAdapter;
1820

1921
/**
@@ -44,4 +46,73 @@ public function testInvalidAdapterException()
4446
{
4547
new ChainAdapter(array(new \stdClass()));
4648
}
49+
50+
public function testPrune()
51+
{
52+
if (isset($this->skippedTests[__FUNCTION__])) {
53+
$this->markTestSkipped($this->skippedTests[__FUNCTION__]);
54+
}
55+
56+
$cache = new ChainAdapter(array(
57+
$this->getPruneableMock(),
58+
$this->getNonPruneableMock(),
59+
$this->getPruneableMock(),
60+
));
61+
$this->assertTrue($cache->prune());
62+
63+
$cache = new ChainAdapter(array(
64+
$this->getPruneableMock(),
65+
$this->getFailingPruneableMock(),
66+
$this->getPruneableMock(),
67+
));
68+
$this->assertFalse($cache->prune());
69+
}
70+
71+
/**
72+
* @return \PHPUnit_Framework_MockObject_MockObject|PruneableCacheInterface
73+
*/
74+
private function getPruneableMock()
75+
{
76+
$pruneable = $this
77+
->getMockBuilder(PruneableCacheInterface::class)
78+
->getMock();
79+
80+
$pruneable
81+
->expects($this->atLeastOnce())
82+
->method('prune')
83+
->will($this->returnValue(true));
84+
85+
return $pruneable;
86+
}
87+
88+
/**
89+
* @return \PHPUnit_Framework_MockObject_MockObject|PruneableCacheInterface
90+
*/
91+
private function getFailingPruneableMock()
92+
{
93+
$pruneable = $this
94+
->getMockBuilder(PruneableCacheInterface::class)
95+
->getMock();
96+
97+
$pruneable
98+
->expects($this->atLeastOnce())
99+
->method('prune')
100+
->will($this->returnValue(false));
101+
102+
return $pruneable;
103+
}
104+
105+
/**
106+
* @return \PHPUnit_Framework_MockObject_MockObject|AdapterInterface
107+
*/
108+
private function getNonPruneableMock()
109+
{
110+
return $this
111+
->getMockBuilder(AdapterInterface::class)
112+
->getMock();
113+
}
114+
}
115+
116+
interface PruneableCacheInterface extends PruneableInterface, AdapterInterface
117+
{
47118
}

src/Symfony/Component/Cache/Tests/Adapter/PdoAdapterTest.php

+3
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,15 @@
1212
namespace Symfony\Component\Cache\Tests\Adapter;
1313

1414
use Symfony\Component\Cache\Adapter\PdoAdapter;
15+
use Symfony\Component\Cache\Tests\Traits\PdoPruneableTrait;
1516

1617
/**
1718
* @group time-sensitive
1819
*/
1920
class PdoAdapterTest extends AdapterTestCase
2021
{
22+
use PdoPruneableTrait;
23+
2124
protected static $dbFile;
2225

2326
public static function setupBeforeClass()

src/Symfony/Component/Cache/Tests/Adapter/PdoDbalAdapterTest.php

+3
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,15 @@
1313

1414
use Doctrine\DBAL\DriverManager;
1515
use Symfony\Component\Cache\Adapter\PdoAdapter;
16+
use Symfony\Component\Cache\Tests\Traits\PdoPruneableTrait;
1617

1718
/**
1819
* @group time-sensitive
1920
*/
2021
class PdoDbalAdapterTest extends AdapterTestCase
2122
{
23+
use PdoPruneableTrait;
24+
2225
protected static $dbFile;
2326

2427
public static function setupBeforeClass()

src/Symfony/Component/Cache/Tests/Simple/ChainCacheTest.php

+72-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
namespace Symfony\Component\Cache\Tests\Simple;
1313

14+
use Psr\SimpleCache\CacheInterface;
15+
use Symfony\Component\Cache\PruneableInterface;
1416
use Symfony\Component\Cache\Simple\ArrayCache;
1517
use Symfony\Component\Cache\Simple\ChainCache;
1618
use Symfony\Component\Cache\Simple\FilesystemCache;
@@ -40,6 +42,75 @@ public function testEmptyCachesException()
4042
*/
4143
public function testInvalidCacheException()
4244
{
43-
new Chaincache(array(new \stdClass()));
45+
new ChainCache(array(new \stdClass()));
4446
}
47+
48+
public function testPrune()
49+
{
50+
if (isset($this->skippedTests[__FUNCTION__])) {
51+
$this->markTestSkipped($this->skippedTests[__FUNCTION__]);
52+
}
53+
54+
$cache = new ChainCache(array(
55+
$this->getPruneableMock(),
56+
$this->getNonPruneableMock(),
57+
$this->getPruneableMock(),
58+
));
59+
$this->assertTrue($cache->prune());
60+
61+
$cache = new ChainCache(array(
62+
$this->getPruneableMock(),
63+
$this->getFailingPruneableMock(),
64+
$this->getPruneableMock(),
65+
));
66+
$this->assertFalse($cache->prune());
67+
}
68+
69+
/**
70+
* @return \PHPUnit_Framework_MockObject_MockObject|PruneableCacheInterface
71+
*/
72+
private function getPruneableMock()
73+
{
74+
$pruneable = $this
75+
->getMockBuilder(PruneableCacheInterface::class)
76+
->getMock();
77+
78+
$pruneable
79+
->expects($this->atLeastOnce())
80+
->method('prune')
81+
->will($this->returnValue(true));
82+
83+
return $pruneable;
84+
}
85+
86+
/**
87+
* @return \PHPUnit_Framework_MockObject_MockObject|PruneableCacheInterface
88+
*/
89+
private function getFailingPruneableMock()
90+
{
91+
$pruneable = $this
92+
->getMockBuilder(PruneableCacheInterface::class)
93+
->getMock();
94+
95+
$pruneable
96+
->expects($this->atLeastOnce())
97+
->method('prune')
98+
->will($this->returnValue(false));
99+
100+
return $pruneable;
101+
}
102+
103+
/**
104+
* @return \PHPUnit_Framework_MockObject_MockObject|CacheInterface
105+
*/
106+
private function getNonPruneableMock()
107+
{
108+
return $this
109+
->getMockBuilder(CacheInterface::class)
110+
->getMock();
111+
}
112+
}
113+
114+
interface PruneableCacheInterface extends PruneableInterface, CacheInterface
115+
{
45116
}

src/Symfony/Component/Cache/Tests/Simple/PdoCacheTest.php

+3
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,15 @@
1212
namespace Symfony\Component\Cache\Tests\Simple;
1313

1414
use Symfony\Component\Cache\Simple\PdoCache;
15+
use Symfony\Component\Cache\Tests\Traits\PdoPruneableTrait;
1516

1617
/**
1718
* @group time-sensitive
1819
*/
1920
class PdoCacheTest extends CacheTestCase
2021
{
22+
use PdoPruneableTrait;
23+
2124
protected static $dbFile;
2225

2326
public static function setupBeforeClass()

src/Symfony/Component/Cache/Tests/Simple/PdoDbalCacheTest.php

+3
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,15 @@
1313

1414
use Doctrine\DBAL\DriverManager;
1515
use Symfony\Component\Cache\Simple\PdoCache;
16+
use Symfony\Component\Cache\Tests\Traits\PdoPruneableTrait;
1617

1718
/**
1819
* @group time-sensitive
1920
*/
2021
class PdoDbalCacheTest extends CacheTestCase
2122
{
23+
use PdoPruneableTrait;
24+
2225
protected static $dbFile;
2326

2427
public static function setupBeforeClass()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
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\Component\Cache\Tests\Traits;
13+
14+
use Symfony\Component\Cache\Traits\PdoTrait;
15+
16+
trait PdoPruneableTrait
17+
{
18+
protected function isPruned($cache, $name)
19+
{
20+
$ro = new \ReflectionObject($cache);
21+
22+
if (!in_array(PdoTrait::class, $ro->getTraitNames())) {
23+
self::fail(sprintf('Cache passed to %s() does not use required "%s" trait.', PdoTrait::class));
24+
}
25+
if (!$ro->hasMethod('getConnection') || !$ro->hasProperty('table') || !$ro->hasProperty('idCol')) {
26+
self::fail(sprintf('Cache passed to %s() missing "getConnection()", "table" or "idCol" methods/props.', __METHOD__));
27+
}
28+
29+
$pdoConnect = $ro->getMethod('getConnection');
30+
$pdoConnect->setAccessible(true);
31+
$getPropVal = function ($name) use ($cache, $ro) {
32+
$property = $ro->getProperty($name);
33+
$property->setAccessible(true);
34+
35+
return $property->getValue($cache);
36+
};
37+
38+
/** @var \Doctrine\DBAL\Statement $select */
39+
$select = $pdoConnect->invoke($cache)->prepare(vsprintf('SELECT 1 FROM %s WHERE %s LIKE :id', array(
40+
$getPropVal('table'),
41+
$getPropVal('idCol'),
42+
)));
43+
$select->bindValue(':id', sprintf('%%%s', $name));
44+
$select->execute();
45+
46+
return $select->rowCount() !== 0;
47+
}
48+
49+
abstract public static function fail($message = '');
50+
}

0 commit comments

Comments
 (0)