Add hash prefix to key of the cache

Change file cache adapter
This commit is contained in:
Vasily Komrakov 2016-05-22 01:09:22 +03:00
commit ed691c8149
6 changed files with 194 additions and 20 deletions

View file

@ -24,6 +24,7 @@ $config = [
'adapter' => \TorrentPier\Cache\FileAdapter::class, 'adapter' => \TorrentPier\Cache\FileAdapter::class,
'options' => [ 'options' => [
'directory' => __DIR__ . '/../internal_data/cache', 'directory' => __DIR__ . '/../internal_data/cache',
'prefix' => 'hash string'
], ],
], ],
/*'cache' => [ /*'cache' => [

View file

@ -17,6 +17,11 @@ abstract class Adapter
*/ */
protected $provider; protected $provider;
/**
* @var string
*/
protected $prefix = '';
/** /**
* Set options for setting cache provider. * Set options for setting cache provider.
* *
@ -48,6 +53,18 @@ abstract class Adapter
*/ */
abstract protected function getType(); abstract protected function getType();
/**
* Add prefix to the namespace for security of key.
*
* @param string $prefix
* @return $this
*/
protected function setPrefix($prefix)
{
$this->prefix = $prefix;
return $this;
}
/** /**
* Prepare key. * Prepare key.
* *
@ -68,7 +85,7 @@ abstract class Adapter
list($namespace, $id) = $result; list($namespace, $id) = $result;
} }
$this->getProvider()->setNamespace($namespace); $this->getProvider()->setNamespace($this->prefix . $namespace);
return $id; return $id;
} }
@ -89,7 +106,7 @@ abstract class Adapter
* Fetches an entry from the cache. * Fetches an entry from the cache.
* *
* @param string $key * @param string $key
* @param mixed|null $defaultValue * @param mixed|\Closure|null $defaultValue
* @return mixed|null * @return mixed|null
*/ */
public function get($key, $defaultValue = null) public function get($key, $defaultValue = null)
@ -98,6 +115,10 @@ abstract class Adapter
$result = $this->getProvider()->fetch($id); $result = $this->getProvider()->fetch($id);
if ($result === false) { if ($result === false) {
if ($defaultValue instanceof \Closure) {
return call_user_func($defaultValue, $this, $key);
}
return $defaultValue; return $defaultValue;
} }
@ -108,12 +129,13 @@ abstract class Adapter
* Returns an associative array of values for keys is found in cache. * Returns an associative array of values for keys is found in cache.
* *
* @param array $keys * @param array $keys
* @param string $namespace
* @return array|\string[] * @return array|\string[]
*/ */
public function gets(array $keys) public function gets(array $keys, $namespace = self::DEFAULT_NAMESPACE)
{ {
$keys = array_map([$this, 'prepareKey'], $keys); $this->getProvider()->setNamespace($this->prefix . $namespace);
return $this->getProvider()->fetchMultiple([$keys]); return $this->getProvider()->fetchMultiple($keys);
} }
/** /**
@ -134,16 +156,13 @@ abstract class Adapter
* Returns a boolean value indicating if the operation succeeded. * Returns a boolean value indicating if the operation succeeded.
* *
* @param array $keysAndValues * @param array $keysAndValues
* @param string $namespace
* @param int $timeLeft * @param int $timeLeft
* @return bool * @return bool
*/ */
public function sets(array $keysAndValues, $timeLeft) public function sets(array $keysAndValues, $namespace = self::DEFAULT_NAMESPACE, $timeLeft = 0)
{ {
foreach ($keysAndValues as $key => $value) { $this->getProvider()->setNamespace($this->prefix . $namespace);
$id = $this->prepareKey($key);
$keysAndValues[$id] = $value;
unset($keysAndValues[$key]);
}
return $this->getProvider()->saveMultiple($keysAndValues, $timeLeft); return $this->getProvider()->saveMultiple($keysAndValues, $timeLeft);
} }
@ -167,7 +186,7 @@ abstract class Adapter
*/ */
public function deleteAll($namespace = '') public function deleteAll($namespace = '')
{ {
$this->getProvider()->setNamespace($namespace); $this->getProvider()->setNamespace($this->prefix . $namespace);
return $this->getProvider()->deleteAll(); return $this->getProvider()->deleteAll();
} }

View file

@ -2,7 +2,7 @@
namespace TorrentPier\Cache; namespace TorrentPier\Cache;
use Doctrine\Common\Cache\PhpFileCache; use Doctrine\Common\Cache\FilesystemCache;
/** /**
* Class FileAdapter * Class FileAdapter
@ -18,7 +18,7 @@ class FileAdapter extends Adapter
/** /**
* @var string The cache file extension. * @var string The cache file extension.
*/ */
protected $extension = PhpFileCache::EXTENSION; protected $extension = FilesystemCache::EXTENSION;
/** /**
* @var int The cache file umask. * @var int The cache file umask.
@ -31,7 +31,7 @@ class FileAdapter extends Adapter
public function getProvider() public function getProvider()
{ {
if (!$this->provider) { if (!$this->provider) {
$this->provider = new PhpFileCache($this->directory, $this->extension, $this->umask); $this->provider = new FilesystemCache($this->directory, $this->extension, $this->umask);
} }
return $this->provider; return $this->provider;
@ -42,7 +42,7 @@ class FileAdapter extends Adapter
*/ */
protected function getType() protected function getType()
{ {
return 'Cache in php file'; return 'Filesystem Cache';
} }
/** /**

View file

@ -98,6 +98,6 @@ class MemoryAdapter extends Adapter
*/ */
protected function getType() protected function getType()
{ {
return $this->isMemcached ? 'Cache in memcached' : 'Cache in memcache'; return sprintf('Memory Cache (Driver: %s)', $this->isMemcached ? 'memcached' : 'memcache');
} }
} }

View file

@ -0,0 +1,154 @@
<?php
namespace TorrentPier\Cache;
use Doctrine\Common\Cache\CacheProvider;
class AdapterTest extends \PHPUnit_Framework_TestCase
{
/** @var Adapter|\PHPUnit_Framework_MockObject_MockObject */
private $adapter;
/** @var CacheProvider|\PHPUnit_Framework_MockObject_MockObject */
private $cacheProvider;
/**
* {@inheritdoc}
*/
public function setUp()
{
$this->cacheProvider = $this->getMock(CacheProvider::class,
['doFetch', 'doContains', 'doSave', 'doDelete', 'doFlush', 'doGetStats']);
$this->adapter = $this->getMock(Adapter::class, ['getProvider', 'getType']);
$this->adapter->method('getProvider')->willReturn($this->cacheProvider);
$this->adapter->method('getType')->willReturn('Void Cache for tests');
}
/**
* @covers TorrentPier\Cache\Adapter::has
*/
public function testHas()
{
$this->cacheProvider->expects(self::once())->method('doContains')
->with('namespaceTest[keyTest][1]')->willReturn(false);
self::assertEquals(false, $this->adapter->has('namespaceTest::keyTest'));
}
/**
* @covers TorrentPier\Cache\Adapter::get
*/
public function testGet()
{
$this->cacheProvider->expects(self::at(0))->method('doFetch')
->with('DoctrineNamespaceCacheKey[namespaceTest]')->willReturn(false);
$this->cacheProvider->expects(self::at(1))->method('doFetch')
->with('namespaceTest[keyTest][1]')->willReturn(false);
self::assertEquals(false, $this->adapter->get('namespaceTest::keyTest'));
}
/**
* @covers TorrentPier\Cache\Adapter::get
*/
public function testGetCallback()
{
$this->cacheProvider->expects(self::at(0))->method('doFetch')
->with('DoctrineNamespaceCacheKey[namespaceTest]')->willReturn(false);
$this->cacheProvider->expects(self::at(1))->method('doFetch')
->with('namespaceTest[keyTest][1]')->willReturn(false);
$callback = function($cache, $key) {
return [$cache instanceof Adapter, $key];
};
self::assertEquals([true, 'namespaceTest::keyTest'], $this->adapter->get('namespaceTest::keyTest', $callback));
}
/**
* @covers TorrentPier\Cache\Adapter::set
*/
public function testSet()
{
$this->cacheProvider->expects(self::at(0))->method('doFetch')
->with('DoctrineNamespaceCacheKey[namespaceTest]')->willReturn(false);
$this->cacheProvider->expects(self::at(1))->method('doSave')
->with('namespaceTest[keyTest][1]', [1,2,3,4], 10)->willReturn(true);
self::assertEquals(true, $this->adapter->set('namespaceTest::keyTest', [1,2,3,4], 10));
}
public function testGets()
{
$this->cacheProvider->expects(self::at(0))->method('doFetch')
->with('DoctrineNamespaceCacheKey[namespaceTest]')->willReturn(false);
$this->cacheProvider->expects(self::at(1))->method('doFetch')
->with('namespaceTest[keyTest][1]')->willReturn('testValue');
self::assertEquals(['keyTest' => 'testValue'], $this->adapter->gets(['keyTest'], 'namespaceTest'));
}
public function testSets()
{
$this->cacheProvider->expects(self::at(0))->method('doFetch')
->with('DoctrineNamespaceCacheKey[namespaceTest]')->willReturn(false);
$this->cacheProvider->expects(self::at(1))->method('doSave')
->with('namespaceTest[keyTest][1]', [1,2,3,4], 10)->willReturn(true);
self::assertEquals(true, $this->adapter->sets(['keyTest' => [1,2,3,4]], 'namespaceTest', 10));
}
/**
* @covers TorrentPier\Cache\Adapter::delete
*/
public function testDelete()
{
$this->cacheProvider->expects(self::at(0))->method('doFetch')
->with('DoctrineNamespaceCacheKey[namespaceTest]')->willReturn(false);
$this->cacheProvider->expects(self::at(1))->method('doDelete')
->with('namespaceTest[keyTest][1]')->willReturn(true);
self::assertEquals(true, $this->adapter->delete('namespaceTest::keyTest'));
}
/**
* @covers TorrentPier\Cache\Adapter::deleteAll
*/
public function testDeleteAll()
{
$this->cacheProvider->expects(self::at(0))->method('doFetch')
->with('DoctrineNamespaceCacheKey[namespaceTest]')->willReturn(false);
$this->cacheProvider->expects(self::at(1))->method('doSave')
->with('DoctrineNamespaceCacheKey[namespaceTest]', 2)->willReturn(true);
self::assertEquals(true, $this->adapter->deleteAll('namespaceTest'));
}
/**
* @covers TorrentPier\Cache\Adapter::flush
*/
public function testFlush()
{
$this->cacheProvider->expects(self::at(0))->method('doFlush')->willReturn(true);
self::assertEquals(true, $this->adapter->flush());
}
/**
* @covers TorrentPier\Cache\Adapter::stats
*/
public function testStats()
{
$this->cacheProvider->expects(self::at(0))->method('doGetStats')->willReturn(null);
self::assertEquals(['type' => 'Void Cache for tests'], $this->adapter->stats());
}
}

View file

@ -2,7 +2,7 @@
namespace TorrentPier\Cache; namespace TorrentPier\Cache;
use Doctrine\Common\Cache\PhpFileCache; use Doctrine\Common\Cache\FilesystemCache;
/** /**
* Class FileAdapterTest * Class FileAdapterTest
@ -31,7 +31,7 @@ class FileAdapterTest extends \PHPUnit_Framework_TestCase
*/ */
public function testAdapterCache() public function testAdapterCache()
{ {
self::assertInstanceOf(PhpFileCache::class, $this->adapter->getProvider()); self::assertInstanceOf(FilesystemCache::class, $this->adapter->getProvider());
} }
/** /**
@ -39,7 +39,7 @@ class FileAdapterTest extends \PHPUnit_Framework_TestCase
*/ */
public function testStatsType() public function testStatsType()
{ {
self::assertEquals('Cache in php file', $this->adapter->stats()['type']); self::assertEquals('Filesystem Cache', $this->adapter->stats()['type']);
} }
/** /**