Basic driver and test setup

This commit is contained in:
Timothy Warren 2016-09-05 16:43:37 -04:00
parent 86d649e9e8
commit f4b73ea313
18 changed files with 875 additions and 70 deletions

View File

@ -1,13 +1,14 @@
/**
* Cache
* Banker
*
* A Caching library implementing psr/cache
*
* PHP version 5.6
*
* @package Cache
* @package Banker
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2016 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.0
* @link https://git.timshomepage.net/timw4mail/banker
*/

View File

@ -1,11 +1,28 @@
{
"name": "aviat/banker",
"type": "library",
"description": "A caching library implementing PSR-6 (psr/cache)",
"keywords": [
"cache",
"redis",
"memcache",
"memcached",
"psr-6",
"psr6"
],
"provide": {
"psr/cache": "1.0.1"
},
"autoload": {
"psr-4": {
"Aviat\\Banker\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Aviat\\Banker\\Tests\\": "tests/"
}
},
"require": {
"psr/log": "^1.0",
"psr/cache": "^1.0"
@ -24,8 +41,10 @@
"squizlabs/php_codesniffer": "^3.0.0@alpha",
"theseer/phpdox": "^0.9.0"
},
"suggests": {
"monolog/monolog": "A good standard logging library"
"suggest": {
"monolog/monolog": "A good standard logging library",
"ext-memcache": "Required for Memcache backend",
"ext-memcached": "Required for Memcached backend"
},
"license": "MIT",
"authors": [

View File

@ -1,16 +1,17 @@
<?php
/**
* Cache
* Banker
*
* A Caching library implementing psr/cache
*
* PHP version 5.6
*
* @package Cache
* @author Timothy J. Warren <tim@timshomepage.net>
* @package Banker
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2016 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.0
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.0
* @link https://git.timshomepage.net/timw4mail/banker
*/
namespace Aviat\Banker\Driver;
@ -18,6 +19,26 @@ namespace Aviat\Banker\Driver;
/**
* Base class for cache backends
*/
class Driver implements DriverInterface {
abstract class Driver implements DriverInterface {
/**
* The object encapsulating the connection to the cache backend
*
* @var mixed
*/
protected $conn;
/**
* Data to be stored later
*
* @var array
*/
protected $deferred = [];
/**
* Common constructor interface for driver classes
*
* @param array $config - Connection parameters for the specified backend
*/
abstract public function __construct(array $config = []);
}

View File

@ -1,16 +1,17 @@
<?php
/**
* Cache
* Banker
*
* A Caching library implementing psr/cache
*
* PHP version 5.6
*
* @package Cache
* @package Banker
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2016 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.0
* @link https://git.timshomepage.net/timw4mail/banker
*/
namespace Aviat\Banker\Driver;
@ -19,24 +20,61 @@ namespace Aviat\Banker\Driver;
* Interface for different cache backends
*/
interface DriverInterface {
/**
* Returns a Cache Item representing the specified key.
* See if a key exists in the cache
*
* This method must always return a CacheItemInterface object, even in case of
* a cache miss. It MUST NOT return null.
* @param $key
* @return bool
*/
public function exists($key);
/**
* Set a cached value
*
* @param string $key
* The key for which to return the corresponding Cache Item.
*
* @throws InvalidArgumentException
* If the $key string is not a legal value a \Psr\Cache\InvalidArgumentException
* MUST be thrown.
*
* @return CacheItemInterface
* The corresponding Cache Item.
* @param mixed $value
* @param int $expires
* @return DriverInterface
*/
public function getItem($key);
public function set($key, $value, $expires = 0);
/**
* Get the value for the selected cache key
*
* @param string $key
* @return mixed
*/
public function get($key);
/**
* Retrieve a set of values by their cache key
*
* @param string[] $keys
* @return array
*/
public function getMultiple(array $keys = []);
/**
* Remove an item from the cache
*
* @param string $key
* @return boolean
*/
public function delete($key);
/**
* Remove multiple items from the cache
*
* @param string[] $keys
* @return boolean
*/
public function deleteMultiple(array $keys = []);
/**
* Empty the cache
*
* @return boolean
*/
public function flush();
}

View File

@ -0,0 +1,136 @@
<?php
/**
* Banker
*
* A Caching library implementing psr/cache
*
* PHP version 5.6
*
* @package Banker
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2016 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.0
* @link https://git.timshomepage.net/timw4mail/banker
*/
namespace Aviat\Banker\Driver;
use Aviat\Banker\Exception\CacheException;
/**
* Redis cache backend
*/
class MemcacheDriver extends Driver {
/**
* Driver for PHP Memcache extension
*
* @param array $config
* @throws CacheException
*/
public function __construct(array $config = [])
{
if ( ! class_exists('Memcache'))
{
throw new CacheException('Memcache driver requires the PHP memcache extension');
}
$this->conn = new \Memcache();
$method = ($config['persistent'] === TRUE) ? 'pconnect' : 'connect';
$this->conn->$method($config['host'], $config['port']);
}
/**
* Disconnect from memcached server
*/
public function __destruct()
{
$this->conn->close();
}
/**
* See if a key currently exists in the cache
*
* @param string $key
* @return bool
*/
public function exists($key)
{
return $this->conn->get($key) !== FALSE;
}
/**
* Get the value for the selected cache key
*
* @param string $key
* @return mixed
*/
public function get($key)
{
return $this->conn->get($key);
}
/**
* Retrieve a set of values by their cache key
*
* @param string[] $keys
* @return array
*/
public function getMultiple(array $keys = [])
{
return $this->conn->get($keys);
}
/**
* Set a cached value
*
* @param string $key
* @param mixed $value
* @param int $expires
* @return DriverInterface
*/
public function set($key, $value, $expires = 0)
{
$this->conn->set($key, $value, 0, $expires);
return $this;
}
/**
* Remove an item from the cache
*
* @param string $key
* @return boolean
*/
public function delete($key)
{
return $this->conn->delete($key);
}
/**
* Remove multiple items from the cache
*
* @param string[] $keys
* @return boolean
*/
public function deleteMultiple(array $keys = [])
{
// Iteratively delete each item, using a boolean
// 'and' operation to return false if any deletion fails
return \array_reduce($keys, function($prev, $key) {
return $prev && $this->conn->delete($key);
}, TRUE);
}
/**
* Empty the cache
*
* @return boolean
*/
public function flush()
{
return $this->conn->flush();
}
}

View File

@ -0,0 +1,132 @@
<?php
/**
* Banker
*
* A Caching library implementing psr/cache
*
* PHP version 5.6
*
* @package Banker
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2016 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.0
* @link https://git.timshomepage.net/timw4mail/banker
*/
namespace Aviat\Banker\Driver;
use Aviat\Banker\Exception\CacheException;
use Memcached;
use MemcachedException;
/**
* Memcached cache backend
*/
class MemcachedDriver extends Driver {
/**
* Driver for PHP Memcache extension
*
* @param array $config
* @throws CacheException
*/
public function __construct(array $config = [])
{
if ( ! class_exists('Memcached'))
{
throw new CacheException("Memcached driver requires memcached extensions");
}
$this->conn = new Memcached();
$this->conn->addServer($config['host'], $config['port']);
}
/**
* Disconnect from memcached server
*/
public function __destruct()
{
$this->conn->quit();
}
/**
* See if a key currently exists in the cache
*
* @param string $key
* @return bool
*/
public function exists($key)
{
return $this->conn->get($key) !== FALSE;
}
/**
* Get the value for the selected cache key
*
* @param string $key
* @return mixed
*/
public function get($key)
{
return $this->conn->get($key);
}
/**
* Retrieve a set of values by their cache key
*
* @param string[] $keys
* @return array
*/
public function getMultiple(array $keys = [])
{
return $this->conn->getMulti($keys);
}
/**
* Set a cached value
*
* @param string $key
* @param mixed $value
* @return DriverInterface
*/
public function set($key, $value)
{
$this->conn->set($key, $value);
return $this;
}
/**
* Remove an item from the cache
*
* @param string $key
* @return boolean
*/
public function delete($key)
{
return $this->conn->delete($key);
}
/**
* Remove multiple items from the cache
*
* @param string[] $keys
* @return boolean
*/
public function deleteMultiple(array $keys = [])
{
return $this->conn->deleteMulti($keys);
}
/**
* Empty the cache
*
* @return boolean
*/
public function flush()
{
return $this->conn->flush();
}
}

137
src/Driver/NullDriver.php Normal file
View File

@ -0,0 +1,137 @@
<?php
/**
* Banker
*
* A Caching library implementing psr/cache
*
* PHP version 5.6
*
* @package Banker
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2016 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.0
* @link https://git.timshomepage.net/timw4mail/banker
*/
namespace Aviat\Banker\Driver;
/**
* Cache backend for use without a cache server. Only does transient
* in-memory caching
*/
class NullDriver extends Driver {
/**
* In memory store
*
* @var array
*/
protected $store = [];
/**
* NullDriver constructor.
*
* @param array $config
*/
public function __construct(array $config = [])
{
$this->store = [];
}
/**
* See if a key currently exists in the cache
*
* @param string $key
* @return bool
*/
public function exists($key)
{
return \array_key_exists($key, $this->store);
}
/**
* Get the value for the selected cache key
*
* @param string $key
* @return mixed
*/
public function get($key)
{
return $this->store[$key];
}
/**
* Retrieve a set of values by their cache key
*
* @param string[] $keys
* @return array
*/
public function getMultiple(array $keys = [])
{
$output = [];
foreach($keys as $key)
{
$output[$key] = $this->get($key);
}
return $output;
}
/**
* Set a cached value
*
* @param string $key
* @param mixed $value
* @param int $expires
* @return DriverInterface
*/
public function set($key, $value, $expires = 0)
{
$this->store[$key] = $value;
return $this;
}
/**
* Remove an item from the cache
*
* @param string $key
* @return boolean
*/
public function delete($key)
{
unset($this->store[$key]);
return ( ! array_key_exists($key, $this->store));
}
/**
* Remove multiple items from the cache
*
* @param string[] $keys
* @return boolean
*/
public function deleteMultiple(array $keys = [])
{
$res = TRUE;
foreach($keys as $key)
{
$res = $res && $this->delete($key);
}
return $res;
}
/**
* Empty the cache
*
* @return boolean
*/
public function flush()
{
$this->store = [];
return TRUE;
}
}

View File

@ -1,23 +1,159 @@
<?php
/**
* Cache
* Banker
*
* A Caching library implementing psr/cache
*
* PHP version 5.6
*
* @package Cache
* @package Banker
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2016 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.0
* @link https://git.timshomepage.net/timw4mail/banker
*/
namespace Aviat\Banker\Driver;
use Aviat\Banker\Exception\CacheException;
use Predis\Client;
/**
* Redis cache backend
*/
class RedisDriver extends Driver {
/**
* The object encapsulating the connection to the Redis server
*
* @var Predis\Client
*/
protected $conn;
/**
* RedisDriver constructor.
*
* @param array $config
* @throws CacheException
*/
public function __construct(array $config = [])
{
if ( ! class_exists('Predis\\Client'))
{
throw new CacheException("The redis driver requires the predis/predis composer package to be installed.");
}
$this->conn = new Client($config);
}
/**
* Disconnect from memcached server
*/
public function __destruct()
{
$this->conn->quit();
}
/**
* See if a key currently exists in the cache
*
* @param string $key
* @return bool
*/
public function exists($key)
{
return (bool) $this->conn->exists($key);
}
/**
* Get the value for the selected cache key
*
* @param string $key
* @return mixed
*/
public function get($key)
{
$raw = $this->conn->get($key);
return \unserialize($raw);
}
/**
* Retrieve a set of values by their cache key
*
* @param string[] $keys
* @return array
*/
public function getMultiple(array $keys = [])
{
$output = [];
foreach($keys as $key)
{
$output[$key] = $this->get($key);
}
return $output;
}
/**
* Set a cached value
*
* @param string $key
* @param mixed $value
* @param int $expires
* @return DriverInterface
*/
public function set($key, $value, $expires = 0)
{
$value = \serialize($value);
$this->conn->set($key, $value, "EX {$expires}");
return $this;
}
/**
* Remove an item from the cache
*
* @param string $key
* @return boolean
*/
public function delete($key)
{
return (bool) $this->conn->del($key);
}
/**
* Remove multiple items from the cache
*
* @param string[] $keys
* @return boolean
*/
public function deleteMultiple(array $keys = [])
{
$res = \call_user_func_array([$this->conn, 'del'], $keys);
return $res === count($keys);
}
/**
* Empty the cache
*
* @return boolean
*/
public function flush()
{
return $this->conn->flushdb();
}
/**
* Set the expiration timestamp of a key
*
* @param string $key
* @param int $expires
* @return boolean
*/
public function expiresAt($key, $expires)
{
return (bool) $this->conn->expireat($key, $expires);
}
}

View File

@ -1,16 +1,17 @@
<?php
/**
* Cache
* Banker
*
* A Caching library implementing psr/cache
*
* PHP version 5.6
*
* @package Cache
* @package Banker
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2016 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.0
* @link https://git.timshomepage.net/timw4mail/banker
*/
namespace Aviat\Banker\Driver;

View File

@ -1,16 +1,17 @@
<?php
/**
* Cache
* Banker
*
* A Caching library implementing psr/cache
*
* PHP version 5.6
*
* @package Cache
* @package Banker
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2016 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.0
* @link https://git.timshomepage.net/timw4mail/banker
*/
namespace Aviat\Banker\Exception;

View File

@ -1,16 +1,17 @@
<?php
/**
* Cache
* Banker
*
* A Caching library implementing psr/cache
*
* PHP version 5.6
*
* @package Cache
* @package Banker
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2016 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.0
* @link https://git.timshomepage.net/timw4mail/banker
*/
namespace Aviat\Banker\Exception;

View File

@ -1,26 +1,77 @@
<?php
/**
* Cache
* Banker
*
* A Caching library implementing psr/cache
*
* PHP version 5.6
*
* @package Cache
* @package Banker
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2016 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.0
* @link https://git.timshomepage.net/timw4mail/banker
*/
namespace Aviat\Banker\Driver;
namespace Aviat\Banker;
use Psr\Cache\CacheItemInterface;
use Aviat\Banker\Driver\DriverInterface;
/**
* Base class for Cache items
*/
class DriverCacheItem implements CacheItemInterface {
class Item implements CacheItemInterface {
/**
* The driver for the current cache backend
*
* @var DriverInterface
*/
protected $driver;
/**
* The key of the cache item
*
* @var string
*/
protected $key;
/**
* The expiration time
*
* @var int | null
*/
protected $expiresAt = NULL;
/**
* The time to live
*
* @var int | null
*/
protected $ttl = NULL;
/**
* The value to save in the cache
*
* @var mixed
*/
protected $value;
/**
* Create a Cache Item object
*
* @param DriverInterface $driver
* @param string $key
*/
public function __construct(DriverInterface $driver, $key)
{
$this->driver = $driver;
$this->key = $key;
}
/**
* Returns the key for the current cache item.
*
@ -32,7 +83,7 @@ class DriverCacheItem implements CacheItemInterface {
*/
public function getKey()
{
return $this->key;
}
/**
@ -49,7 +100,7 @@ class DriverCacheItem implements CacheItemInterface {
*/
public function get()
{
return $this->driver->get($this->key);
}
/**
@ -63,7 +114,7 @@ class DriverCacheItem implements CacheItemInterface {
*/
public function isHit()
{
return $this->driver->exists($this->key);
}
/**
@ -81,7 +132,8 @@ class DriverCacheItem implements CacheItemInterface {
*/
public function set($value)
{
$this->value = $value;
return $this;
}
/**
@ -96,9 +148,9 @@ class DriverCacheItem implements CacheItemInterface {
* @return static
* The called object.
*/
public function expiresAt($expiration)
public function expiresAt($expiration = NULL)
{
return $this;
}
/**
@ -114,8 +166,9 @@ class DriverCacheItem implements CacheItemInterface {
* @return static
* The called object.
*/
public function expiresAfter($time)
public function expiresAfter($time = 0)
{
$this->ttl = $time;
return $this;
}
}

View File

@ -1,16 +1,17 @@
<?php
/**
* Cache
* Banker
*
* A Caching library implementing psr/cache
*
* PHP version 5.6
*
* @package Cache
* @package Banker
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2016 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.0
* @link https://git.timshomepage.net/timw4mail/banker
*/
namespace Aviat\Banker;
@ -30,20 +31,20 @@ class ItemCollection extends \ArrayIterator implements \JsonSerializable {
* @var CacheItemInterface[]
*/
protected $items = [];
/**
* Create the collection object from the raw
* CacheitemInterface array
* CacheItemInterface array
*
* @param array $items - array of CacheItemInterface objects
* @param int $flags - flags
* @param int $flags - flags
*/
public function __construct(array $items = [], int $flags = 0)
public function __construct(array $items = [], $flags = 0)
{
parent::__construct($items, $flags);
$this->items = $items;
}
/**
* Specify what data to serialize when using `json_encode`
*

View File

@ -1,16 +1,17 @@
<?php
/**
* Cache
* Banker
*
* A Caching library implementing psr/cache
*
* PHP version 5.6
*
* @package Cache
* @package Banker
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2016 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.0
* @link https://git.timshomepage.net/timw4mail/banker
*/
namespace Aviat\Banker;
@ -20,19 +21,28 @@ use Psr\Cache\CacheItemPoolInterface;
use Aviat\Banker\Driver;
use Aviat\Banker\Driver\DriverInterface;
use Aviat\Banker\Exception\InvalidArgumentException;
use Aviat\Banker\Item;
/**
* The main cache manager
*/
class CachePool implements CacheItemPoolInterface {
class Pool implements CacheItemPoolInterface {
/**
* Driver class for handling the chosen caching backend
*
* @var DriverInterface $driver
* @var DriverInterface
*/
protected $driver;
/**
* Cache Items to be saved
*
* @var array
*/
protected $deferred = [];
/**
* Set up the cache backend
*
@ -40,7 +50,7 @@ class CachePool implements CacheItemPoolInterface {
*/
public function __construct(array $config)
{
$this->driver = $this->loadDriver($config);
}
/**
@ -61,7 +71,13 @@ class CachePool implements CacheItemPoolInterface {
*/
public function getItem($key)
{
if ( ! is_string($key))
{
throw new InvalidArgumentException("Cache key must be a string.");
}
$item = new Item($this->driver, $key);
return $item;
}
/**
@ -82,7 +98,14 @@ class CachePool implements CacheItemPoolInterface {
*/
public function getItems(array $keys = [])
{
// Get the set of items selected
$items = [];
foreach($keys as $key)
{
$items[$key] = $this->getItem($key);
}
return new ItemCollection($items);
}
/**
@ -104,7 +127,12 @@ class CachePool implements CacheItemPoolInterface {
*/
public function hasItem($key)
{
if ( ! is_string($key))
{
throw new InvalidArgumentException("Cache item must be a string");
}
return $this->driver->exists($key);
}
/**
@ -115,7 +143,7 @@ class CachePool implements CacheItemPoolInterface {
*/
public function clear()
{
return $this->driver->flush();
}
/**
@ -133,7 +161,19 @@ class CachePool implements CacheItemPoolInterface {
*/
public function deleteItem($key)
{
if ( ! is_string($key))
{
throw new InvalidArgumentException("Cache item must be a string");
}
if ( ! $this->hasItem($key))
{
return FALSE;
}
else
{
return $this->driver->delete($key);
}
}
/**
@ -151,7 +191,15 @@ class CachePool implements CacheItemPoolInterface {
*/
public function deleteItems(array $keys)
{
foreach ($keys as $key)
{
if ( ! is_string($key))
{
throw new InvalidArgumentException("Cache item must be a string");
}
}
return $this->driver->deleteMultiple($keys);
}
/**
@ -165,7 +213,7 @@ class CachePool implements CacheItemPoolInterface {
*/
public function save(CacheItemInterface $item)
{
}
/**
@ -179,7 +227,7 @@ class CachePool implements CacheItemPoolInterface {
*/
public function saveDeferred(CacheItemInterface $item)
{
$this->deferred[] = $item;
}
/**
@ -190,9 +238,21 @@ class CachePool implements CacheItemPoolInterface {
*/
public function commit()
{
if (empty($this->deferred))
{
return TRUE;
}
$result = TRUE;
foreach($this->deferred as $item)
{
$result = $result && $this->save($item);
}
return $result;
}
/**
* Instantiate the appropriate cache backend based on the config
*
@ -203,6 +263,7 @@ class CachePool implements CacheItemPoolInterface {
{
$driver = ucfirst(strtolower($driverConfig['driver']));
$class = "Driver\\${driver}Driver";
return new $class($driverConfig['connection']);
}
}

View File

@ -0,0 +1,26 @@
<?php
namespace Aviat\Banker\Tests\Driver;
use PHPUnit\Framework\TestCase;
class DriverTestBase extends TestCase {
protected $driver;
public function testGetSet()
{
$this->driver->set('foo', 'bar');
$this->assertEquals('bar', $this->driver->get('foo'));
$bar = [
'foo' => [
'apple' => 'orange'
],
'bar' => 'baz'
];
$this->driver->set('bar', $bar);
$this->assertEquals($bar, $this->driver->get('bar'));
}
}

View File

@ -0,0 +1,17 @@
<?php
namespace Aviat\Banker\Tests\Driver;
use Aviat\Banker\Driver\MemcacheDriver;
class MemcacheDriverTest extends DriverTestBase {
public function setup()
{
$this->driver = new MemcacheDriver([
'host' => 'localhost',
'port' => '11211'
]);
$this->driver->flush();
}
}

View File

@ -0,0 +1,17 @@
<?php
namespace Aviat\Banker\Tests\Driver;
use Aviat\Banker\Driver\MemcachedDriver;
class MemcachedDriverTest extends DriverTestBase {
public function setUp()
{
$this->driver = new MemcachedDriver([
'host' => 'localhost',
'port' => '11211',
]);
$this->driver->flush();
}
}

View File

@ -0,0 +1,7 @@
<?php
namespace Aviat\Banker\Tests\Driver;
class RedisDriverTest extends DriverTestBase {
}