Skip to content

Commit f4330b2

Browse files
magnusnordlanderNyholm
authored andcommitted
PSR-16 bridge implementation (#130)
* Started a PSR-16 bridge implementation * Updated in response to review * StyleCI fixes * Fixed getMultiple
0 parents  commit f4330b2

File tree

4 files changed

+318
-0
lines changed

4 files changed

+318
-0
lines changed

Exception/CacheException.php

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
/*
4+
* This file is part of php-cache organization.
5+
*
6+
* (c) 2015 Aaron Scherer <[email protected]>, Tobias Nyholm <[email protected]>
7+
*
8+
* This source file is subject to the MIT license that is bundled
9+
* with this source code in the file LICENSE.
10+
*/
11+
12+
namespace Cache\Bridge\SimpleCache\Exception;
13+
14+
class CacheException extends \RuntimeException implements \Psr\SimpleCache\CacheException
15+
{
16+
}
+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
/*
4+
* This file is part of php-cache organization.
5+
*
6+
* (c) 2015 Aaron Scherer <[email protected]>, Tobias Nyholm <[email protected]>
7+
*
8+
* This source file is subject to the MIT license that is bundled
9+
* with this source code in the file LICENSE.
10+
*/
11+
12+
namespace Cache\Bridge\SimpleCache\Exception;
13+
14+
class InvalidArgumentException extends CacheException implements \Psr\SimpleCache\InvalidArgumentException
15+
{
16+
}

SimpleCacheBridge.php

+188
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
<?php
2+
3+
/*
4+
* This file is part of php-cache organization.
5+
*
6+
* (c) 2015 Aaron Scherer <[email protected]>, Tobias Nyholm <[email protected]>
7+
*
8+
* This source file is subject to the MIT license that is bundled
9+
* with this source code in the file LICENSE.
10+
*/
11+
12+
namespace Cache\Bridge\SimpleCache;
13+
14+
use Cache\Bridge\SimpleCache\Exception\InvalidArgumentException;
15+
use Psr\Cache\CacheItemInterface;
16+
use Psr\Cache\CacheItemPoolInterface;
17+
use Psr\Cache\InvalidArgumentException as CacheInvalidArgumentException;
18+
use Psr\SimpleCache\CacheInterface;
19+
20+
class SimpleCacheBridge implements CacheInterface
21+
{
22+
/**
23+
* @type CacheItemPoolInterface
24+
*/
25+
protected $cacheItemPool;
26+
27+
/**
28+
* SimpleCacheBridge constructor.
29+
*/
30+
public function __construct(CacheItemPoolInterface $cacheItemPool)
31+
{
32+
$this->cacheItemPool = $cacheItemPool;
33+
}
34+
35+
/**
36+
* {@inheritdoc}
37+
*/
38+
public function get($key, $default = null)
39+
{
40+
try {
41+
$item = $this->cacheItemPool->getItem($key);
42+
} catch (CacheInvalidArgumentException $e) {
43+
throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e);
44+
}
45+
46+
if (!$item->isHit()) {
47+
return $default;
48+
}
49+
50+
return $item->get();
51+
}
52+
53+
/**
54+
* {@inheritdoc}
55+
*/
56+
public function set($key, $value, $ttl = null)
57+
{
58+
try {
59+
$item = $this->cacheItemPool->getItem($key);
60+
} catch (CacheInvalidArgumentException $e) {
61+
throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e);
62+
}
63+
64+
$item->set($value);
65+
$item->expiresAfter($ttl);
66+
67+
return $this->cacheItemPool->save($item);
68+
}
69+
70+
/**
71+
* {@inheritdoc}
72+
*/
73+
public function delete($key)
74+
{
75+
try {
76+
return $this->cacheItemPool->deleteItem($key);
77+
} catch (CacheInvalidArgumentException $e) {
78+
throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e);
79+
}
80+
}
81+
82+
/**
83+
* {@inheritdoc}
84+
*/
85+
public function clear()
86+
{
87+
return $this->cacheItemPool->clear();
88+
}
89+
90+
/**
91+
* {@inheritdoc}
92+
*/
93+
public function getMultiple($keys, $default = null)
94+
{
95+
if (!is_array($keys)) {
96+
if (!$keys instanceof \Traversable) {
97+
throw new InvalidArgumentException('$keys is neither an array nor Traversable');
98+
}
99+
100+
// Since we need to throw an exception if *any* key is invalid, it doesn't
101+
// make sense to wrap iterators or something like that.
102+
$keys = iterator_to_array($keys);
103+
}
104+
105+
try {
106+
$items = $this->cacheItemPool->getItems($keys);
107+
} catch (CacheInvalidArgumentException $e) {
108+
throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e);
109+
}
110+
111+
foreach ($items as $key => $item) {
112+
/** @type $item CacheItemInterface */
113+
if (!$item->isHit()) {
114+
yield $key => $default;
115+
} else {
116+
yield $key => $item->get();
117+
}
118+
}
119+
}
120+
121+
/**
122+
* {@inheritdoc}
123+
*/
124+
public function setMultiple($values, $ttl = null)
125+
{
126+
if (!is_array($values)) {
127+
if (!$values instanceof \Traversable) {
128+
throw new InvalidArgumentException('$values is neither an array nor Traversable');
129+
}
130+
131+
// Since we need to throw an exception if *any* key is invalid, it doesn't
132+
// make sense to wrap iterators or something like that.
133+
$values = iterator_to_array($values);
134+
}
135+
136+
try {
137+
$items = $this->cacheItemPool->getItems(array_keys($values));
138+
} catch (CacheInvalidArgumentException $e) {
139+
throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e);
140+
}
141+
142+
$itemSuccess = true;
143+
144+
foreach ($items as $key => $item) {
145+
/* @var $item CacheItemInterface */
146+
$item->set($values[$key]);
147+
$item->expiresAfter($ttl);
148+
149+
$itemSuccess = $itemSuccess && $this->cacheItemPool->saveDeferred($item);
150+
}
151+
152+
return $itemSuccess && $this->cacheItemPool->commit();
153+
}
154+
155+
/**
156+
* {@inheritdoc}
157+
*/
158+
public function deleteMultiple($keys)
159+
{
160+
if (!is_array($keys)) {
161+
if (!$keys instanceof \Traversable) {
162+
throw new InvalidArgumentException('$keys is neither an array nor Traversable');
163+
}
164+
165+
// Since we need to throw an exception if *any* key is invalid, it doesn't
166+
// make sense to wrap iterators or something like that.
167+
$keys = iterator_to_array($keys);
168+
}
169+
170+
try {
171+
return $this->cacheItemPool->deleteItems($keys);
172+
} catch (CacheInvalidArgumentException $e) {
173+
throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e);
174+
}
175+
}
176+
177+
/**
178+
* {@inheritdoc}
179+
*/
180+
public function has($key)
181+
{
182+
try {
183+
return $this->cacheItemPool->hasItem($key);
184+
} catch (CacheInvalidArgumentException $e) {
185+
throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e);
186+
}
187+
}
188+
}

Tests/SimpleCacheBridgeTest.php

+98
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
<?php
2+
3+
/*
4+
* This file is part of php-cache organization.
5+
*
6+
* (c) 2015 Aaron Scherer <[email protected]>, Tobias Nyholm <[email protected]>
7+
*
8+
* This source file is subject to the MIT license that is bundled
9+
* with this source code in the file LICENSE.
10+
*/
11+
12+
namespace Cache\Bridge\SimpleCache\Tests;
13+
14+
use Cache\Bridge\SimpleCache\SimpleCacheBridge;
15+
use Mockery as m;
16+
use Psr\Cache\CacheItemInterface;
17+
use Psr\Cache\CacheItemPoolInterface;
18+
19+
class SimpleCacheBridgeTest extends \PHPUnit_Framework_TestCase
20+
{
21+
/**
22+
* @type SimpleCacheBridge
23+
*/
24+
private $bridge;
25+
26+
/**
27+
* @type m\MockInterface|CacheItemPoolInterface
28+
*/
29+
private $mock;
30+
31+
/**
32+
* @type m\MockInterface|CacheItemInterface
33+
*/
34+
private $itemMock;
35+
36+
protected function setUp()
37+
{
38+
parent::setUp();
39+
40+
$this->mock = m::mock(CacheItemPoolInterface::class);
41+
42+
$this->bridge = new SimpleCacheBridge($this->mock);
43+
44+
$this->itemMock = m::mock(CacheItemInterface::class);
45+
}
46+
47+
public function testConstructor()
48+
{
49+
$this->assertInstanceOf(SimpleCacheBridge::class, $this->bridge);
50+
}
51+
52+
public function testFetch()
53+
{
54+
$this->itemMock->shouldReceive('isHit')->times(1)->andReturn(true);
55+
$this->itemMock->shouldReceive('get')->times(1)->andReturn('some_value');
56+
57+
$this->mock->shouldReceive('getItem')->withArgs(['some_item'])->andReturn($this->itemMock);
58+
59+
$this->assertEquals('some_value', $this->bridge->get('some_item'));
60+
}
61+
62+
public function testFetchMiss()
63+
{
64+
$this->itemMock->shouldReceive('isHit')->times(1)->andReturn(false);
65+
66+
$this->mock->shouldReceive('getItem')->withArgs(['no_item'])->andReturn($this->itemMock);
67+
68+
$this->assertFalse($this->bridge->get('no_item', false));
69+
}
70+
71+
public function testContains()
72+
{
73+
$this->mock->shouldReceive('hasItem')->withArgs(['no_item'])->andReturn(false);
74+
$this->mock->shouldReceive('hasItem')->withArgs(['some_item'])->andReturn(true);
75+
76+
$this->assertFalse($this->bridge->has('no_item'));
77+
$this->assertTrue($this->bridge->has('some_item'));
78+
}
79+
80+
public function testSave()
81+
{
82+
$this->itemMock->shouldReceive('set')->twice()->with('dummy_data');
83+
$this->itemMock->shouldReceive('expiresAfter')->once()->with(null);
84+
$this->itemMock->shouldReceive('expiresAfter')->once()->with(2);
85+
$this->mock->shouldReceive('getItem')->twice()->with('some_item')->andReturn($this->itemMock);
86+
$this->mock->shouldReceive('save')->twice()->with($this->itemMock)->andReturn(true);
87+
88+
$this->assertTrue($this->bridge->set('some_item', 'dummy_data'));
89+
$this->assertTrue($this->bridge->set('some_item', 'dummy_data', 2));
90+
}
91+
92+
public function testDelete()
93+
{
94+
$this->mock->shouldReceive('deleteItem')->once()->with('some_item')->andReturn(true);
95+
96+
$this->assertTrue($this->bridge->delete('some_item'));
97+
}
98+
}

0 commit comments

Comments
 (0)