Skip to content

Commit dc34b7e

Browse files
committed
(experimental) Move Cache instance to Adapter impl
see zendframework#9
1 parent 5ef2ea7 commit dc34b7e

File tree

5 files changed

+268
-31
lines changed

5 files changed

+268
-31
lines changed

src/Adapter/CacheAdapter.php

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
<?php
2+
/**
3+
* Zend Framework (http://framework.zend.com/)
4+
*
5+
* @link http://github.com/zendframework/zf2 for the canonical source repository
6+
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
7+
* @license http://framework.zend.com/license/new-bsd New BSD License
8+
*/
9+
10+
namespace Zend\Paginator\Adapter;
11+
12+
use Zend\Cache\Storage\StorageInterface as CacheStorage;
13+
14+
class CacheAdapter implements AdapterInterface
15+
{
16+
/**
17+
* The cache tag prefix used to namespace Paginator results in the cache
18+
*
19+
*/
20+
const CACHE_TAG_PREFIX = 'Zend_Paginator_';
21+
22+
/**
23+
* @var AdapterInterface
24+
*/
25+
private $adapter;
26+
27+
/**
28+
* @var CacheStorage;
29+
*/
30+
private $cache;
31+
32+
public function __construct(AdapterInterface $adapter, CacheStorage $cache)
33+
{
34+
$this->adapter = $adapter;
35+
$this->cache = $cache;
36+
}
37+
38+
public function getItems($offset, $itemCountPerPage)
39+
{
40+
$pageNumber = ($offset === 0 ) ? 1 : $offset / $itemCountPerPage + 1;
41+
42+
$cacheId = $this->getCacheId($pageNumber, $itemCountPerPage);
43+
44+
if ($this->cache->hasItem($cacheId)) {
45+
return $this->cache->getItem($cacheId);
46+
}
47+
48+
$items = $this->adapter->getItems($offset, $itemCountPerPage);
49+
50+
if (!$items instanceof \Traversable) {
51+
$items = new \ArrayIterator($items);
52+
}
53+
54+
$this->cache->setItem($cacheId, $items);
55+
56+
return $items;
57+
}
58+
59+
public function count()
60+
{
61+
return $this->adapter->count();
62+
}
63+
64+
public function clearCache($pageNumber, $itemCountPerPage)
65+
{
66+
$cacheId = $this->getCacheId($pageNumber, $itemCountPerPage);
67+
68+
if ($this->cache->hasItem($cacheId)) {
69+
return $this->cache->removeItem($cacheId);
70+
}
71+
}
72+
73+
protected function getCacheId($pageNumber, $itemCountPerPage)
74+
{
75+
return static::CACHE_TAG_PREFIX . $pageNumber . '_' . $this->getCacheInternalId($itemCountPerPage);
76+
}
77+
78+
/**
79+
* Get the internal cache id
80+
* Depends on the adapter and the item count per page
81+
*
82+
* Used to tag that unique Paginator instance in cache
83+
*
84+
* @return string
85+
*/
86+
protected function getCacheInternalId($itemCountPerPage)
87+
{
88+
return md5(serialize([
89+
spl_object_hash($this->adapter),
90+
$itemCountPerPage
91+
]));
92+
}
93+
}

src/Adapter/FilterAdapter.php

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
namespace Zend\Paginator\Adapter;
3+
4+
use Zend\Filter\FilterInterface;
5+
6+
class FilterAdapter implements AdapterInterface
7+
{
8+
/**
9+
* @var AdapterInterface
10+
*/
11+
private $adapter;
12+
13+
/**
14+
* @var FilterInterface;
15+
*/
16+
private $filter;
17+
18+
public function __construct(AdapterInterface $adapter, FilterInterface $filter)
19+
{
20+
$this->adapter = $adapter;
21+
$this->filter = $filter;
22+
}
23+
24+
public function getItems($offset, $itemCountPerPage)
25+
{
26+
$items = $this->adapter->getItems($offset, $itemCountPerPage);
27+
return $this->filter->filter($items);
28+
}
29+
30+
public function count()
31+
{
32+
return $this->adapter->count();
33+
}
34+
}

src/CacheTrait.php

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
<?php
2+
3+
/**
4+
* Zend Framework (http://framework.zend.com/)
5+
*
6+
* @link http://github.com/zendframework/zf2 for the canonical source repository
7+
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
8+
* @license http://framework.zend.com/license/new-bsd New BSD License
9+
*/
10+
11+
namespace Zend\Paginator;
12+
13+
use Zend\Cache\Storage\IteratorInterface as CacheIterator;
14+
use Zend\Cache\Storage\StorageInterface as CacheStorage;
15+
16+
use Zend\Paginator\Adapter\CacheAdapter;
17+
18+
trait CacheTrait
19+
{
20+
21+
/**
22+
* Enable or disable the cache by Zend\Paginator\Paginator instance
23+
*
24+
* @var bool
25+
*/
26+
protected $cacheEnabled = true;
27+
28+
/**
29+
* Cache object
30+
*
31+
* @var CacheStorage
32+
*/
33+
protected $cache;
34+
35+
/**
36+
* Sets a cache object
37+
*
38+
* @param CacheStorage $cache
39+
*/
40+
public function setCache(CacheStorage $cache)
41+
{
42+
$this->cache = $cache;
43+
}
44+
45+
/**
46+
* Enables/Disables the cache for this instance
47+
*
48+
* @param bool $enable
49+
* @return Paginator
50+
*/
51+
public function setCacheEnabled($enable)
52+
{
53+
$this->cacheEnabled = (bool) $enable;
54+
return $this;
55+
}
56+
57+
/**
58+
* Tells if there is an active cache object
59+
* and if the cache has not been disabled
60+
*
61+
* @return bool
62+
*/
63+
protected function cacheEnabled()
64+
{
65+
return (($this->cache instanceof CacheStorage) && $this->cacheEnabled);
66+
}
67+
68+
/**
69+
* Returns the page item cache.
70+
*
71+
* @return array
72+
*/
73+
public function getPageItemCache()
74+
{
75+
$data = [];
76+
if ($this->cacheEnabled()) {
77+
$prefixLength = strlen(CacheAdapter::CACHE_TAG_PREFIX);
78+
$cacheIterator = $this->cache->getIterator();
79+
$cacheIterator->setMode(CacheIterator::CURRENT_AS_VALUE);
80+
foreach ($cacheIterator as $key => $value) {
81+
if (substr($key, 0, $prefixLength) == CacheAdapter::CACHE_TAG_PREFIX) {
82+
$pageNumber = (int)substr($key, $prefixLength);
83+
$data[$pageNumber] = $value;
84+
}
85+
}
86+
}
87+
return $data;
88+
}
89+
90+
/**
91+
* Clear the page item cache.
92+
*
93+
* @param int $pageNumber
94+
* @return Paginator
95+
*/
96+
public function clearPageItemCache($pageNumber = null)
97+
{
98+
if (!$this->cacheEnabled()) {
99+
return $this;
100+
}
101+
102+
$cacheAdapter = new CacheAdapter($this->adapter, $this->cache);
103+
104+
if (null === $pageNumber) {
105+
$prefixLength = strlen(CacheAdapter::CACHE_TAG_PREFIX);
106+
$cacheIterator = $this->cache->getIterator();
107+
$cacheIterator->setMode(CacheIterator::CURRENT_AS_KEY);
108+
foreach ($cacheIterator as $key) {
109+
if (substr($key, 0, $prefixLength) == CacheAdapter::CACHE_TAG_PREFIX) {
110+
$pageNumber = (int)substr($key, $prefixLength);
111+
$cacheAdapter->clearCache($pageNumber, $this->getItemCountPerPage());
112+
}
113+
}
114+
} else {
115+
$pageNumber = $this->normalizePageNumber($pageNumber);
116+
117+
$cacheAdapter->clearCache($pageNumber, $this->getItemCountPerPage());
118+
}
119+
return $this;
120+
}
121+
}

src/Paginator.php

Lines changed: 13 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,17 @@
99

1010
namespace Zend\Paginator;
1111

12-
use ArrayIterator;
1312
use Traversable;
13+
use ArrayIterator;
14+
use Zend\Filter\FilterInterface;
15+
use Zend\Paginator\Adapter;
1416

1517
class Paginator extends GlobalPaginator
1618
{
1719
use JsonSerializeTrait,
1820
RenderTrait,
1921
FilterTrait,
20-
CachedTrait;
21-
22-
/**
23-
* The cache tag prefix used to namespace Paginator results in the cache
24-
*
25-
*/
26-
const CACHE_TAG_PREFIX = 'Zend_Paginator_';
27-
22+
CacheTrait;
2823

2924
/**
3025
* @inheritdoc
@@ -33,32 +28,25 @@ public function getItemsByPage($pageNumber)
3328
{
3429
$pageNumber = $this->normalizePageNumber($pageNumber);
3530

31+
$adapter = $this->adapter;
32+
33+
$filter = $this->getFilter();
34+
if ($filter instanceof FilterInterface) {
35+
$adapter = new Adapter\FilterAdapter($adapter, $filter);
36+
}
37+
3638
if ($this->cacheEnabled()) {
37-
$data = static::$cache->getItem($this->_getCacheId($pageNumber));
38-
if ($data) {
39-
return $data;
40-
}
39+
$adapter = new Adapter\CacheAdapter($adapter, $this->cache);
4140
}
4241

4342
$offset = ($pageNumber - 1) * $this->getItemCountPerPage();
4443

45-
$items = $this->adapter->getItems($offset, $this->getItemCountPerPage());
46-
47-
$filter = $this->getFilter();
48-
49-
if ($filter !== null) {
50-
$items = $filter->filter($items);
51-
}
44+
$items = $adapter->getItems($offset, $this->getItemCountPerPage());
5245

5346
if (!$items instanceof Traversable) {
5447
$items = new ArrayIterator($items);
5548
}
5649

57-
if ($this->cacheEnabled()) {
58-
$cacheId = $this->_getCacheId($pageNumber);
59-
static::$cache->setItem($cacheId, $items);
60-
}
61-
6250
return $items;
6351
}
6452
}

test/PaginatorTest.php

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ protected function setUp()
6868
$this->config = Config\Factory::fromFile(__DIR__ . '/_files/config.xml', true);
6969

7070
$this->cache = CacheFactory::adapterFactory('memory', ['memory_limit' => 0]);
71-
Paginator\Paginator::setCache($this->cache);
71+
// Paginator\Paginator::setCache($this->cache);
72+
$this->paginator->setCache($this->cache);
7273

7374
$this->_restorePaginatorDefaults();
7475
}
@@ -853,14 +854,14 @@ public function testLoadScrollingStyleWithObjectThrowsInvalidArgumentException()
853854
public function testGetCacheId()
854855
{
855856
$adapter = new TestAsset\TestAdapter;
856-
$paginator = new Paginator\Paginator($adapter);
857-
$reflectionGetCacheId = new ReflectionMethod($paginator, '_getCacheId');
857+
$adapter = new Paginator\Adapter\CacheAdapter($adapter, $this->cache);
858+
$reflectionGetCacheId = new ReflectionMethod($adapter, 'getCacheId');
858859
$reflectionGetCacheId->setAccessible(true);
859-
$outputGetCacheId = $reflectionGetCacheId->invoke($paginator, null);
860+
$outputGetCacheId = $reflectionGetCacheId->invoke($adapter, 1, 10);
860861

861-
$reflectionGetCacheInternalId = new ReflectionMethod($paginator, '_getCacheInternalId');
862+
$reflectionGetCacheInternalId = new ReflectionMethod($adapter, 'getCacheInternalId');
862863
$reflectionGetCacheInternalId->setAccessible(true);
863-
$outputGetCacheInternalId = $reflectionGetCacheInternalId->invoke($paginator);
864+
$outputGetCacheInternalId = $reflectionGetCacheInternalId->invoke($adapter, 10);
864865

865866
$this->assertEquals($outputGetCacheId, 'Zend_Paginator_1_' . $outputGetCacheInternalId);
866867
}

0 commit comments

Comments
 (0)