Skip to content

Commit

Permalink
Add psr-6 decorator/wrapper
Browse files Browse the repository at this point in the history
  • Loading branch information
DerManoMann committed Dec 14, 2015
1 parent 9ea260f commit 53dfd8c
Show file tree
Hide file tree
Showing 16 changed files with 693 additions and 1 deletion.
21 changes: 21 additions & 0 deletions Readme.md
Expand Up @@ -125,6 +125,24 @@ the cache entry.
Both namespace and multi-level cache instances can be arbitrary nested.


### Psr/Cache

All cache instances can be used as `Psr\Cache\CacheItemPoolInterface` instances by wrapping them in decorator.

````
use Radebatz\ACache\ArrayCache;
use Radebatz\ACache\Decorators\Psr\CacheItemPool;
$cache = new ArrayCache();
$psrCache = new CacheItemPool($cache);
$cacheItem = $prsCache->getItem('foo');
...
````


## Testing

ACache comes with a pretty complete set of tests for a single cache instance and also
Expand All @@ -138,6 +156,9 @@ ACache is licensed under the MIT license.

## Changelog
All issues that break backwards compatibility are flagged [BC].
### v1.2.0
* Add psr-6 support

### v1.1.0
* [BC] make namespace last argument of `save()` method [#4]
* add changelog to provide upgrade details [#8]
Expand Down
7 changes: 6 additions & 1 deletion composer.json
Expand Up @@ -12,12 +12,16 @@
"email": "mano@radebatz.org"
}
],
"provide": {
"psr/cache-implementation": "1.0.0"
},
"support": {
"issues": "https://github.com/DerManoMann/acache/issues",
"source": "https://github.com/DerManoMann/acache.git"
},
"require": {
"php": ">=5.3.0",
"psr/cache": "^1.0",
"psr/log": "^1.0"
},
"require-dev": {
Expand All @@ -30,7 +34,8 @@
},
"autoload": {
"psr-4": {
"Radebatz\\ACache\\": "src/Radebatz/ACache"
"Radebatz\\ACache\\": "src/Radebatz/ACache",
"Psr\\Cache\\": "src/Psr/Cache"
}
},
"extra": {
Expand Down
Empty file modified src/Radebatz/ACache/ApcCache.php 100755 → 100644
Empty file.
Empty file modified src/Radebatz/ACache/ApcGC.php 100755 → 100644
Empty file.
149 changes: 149 additions & 0 deletions src/Radebatz/ACache/Decorators/Psr/CacheItem.php
@@ -0,0 +1,149 @@
<?php

/*
* This file is part of the ACache library.
*
* (c) Martin Rademacher <mano@radebatz.net>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Radebatz\ACache\Decorators\Psr;

use DateInterval;
use DateTime;
use DateTimeInterface;
use Psr\Cache\CacheItemInterface;

/**
* ACache Psr CacheItem implementation.
*/
class CacheItem implements CacheItemInterface
{
protected $key;
protected $value;
/** @var $cache CacheItemPool */
protected $cacheItemPool;
/** @var $expiresAt DateTimeInterface */
protected $expiresAt;

/**
* Create a new cache item.
*/
public function __construct($key, $value, CacheItemPool $cacheItemPool, $ttl = null)
{
if (strpbrk($key, CacheItemPool::BAD_KEY_CHARS)) {
throw new InvalidArgumentException(sprintf('Invalid key: %s', $key));
}

$this->key = $key;
$this->value = $value;
$this->cacheItemPool = $cacheItemPool;
$this->setExpiresAt($ttl);
}

/**
* {@inheritDoc}
*/
public function getKey()
{
return $this->key;
}

/**
* {@inheritDoc}
*/
public function get()
{
return $this->isHit() ? $this->value : null;
}

/**
* {@inheritDoc}
*/
public function set($value, $ttl = null)
{
$this->value = $value;
$this->setExpiresAt($ttl);

return $this;
}

/**
* {@inheritDoc}
*/
public function isHit()
{
return $this->cacheItemPool->getCache()->contains($this->key);
}

/**
* {@inheritDoc}
*/
public function expiresAt($expiration)
{
if (null === $expiration || ($expiration instanceof DateTimeInterface) || ($expiration instanceof DateTime)) {
$this->setExpiresAt($expiration);

return $this;
}

throw new InvalidArgumentException('Invalid expiration date');
}

/**
* {@inheritDoc}
*/
public function expiresAfter($time)
{
if (is_int($time)) {
$this->setExpiresAt($time);

return $this;
} elseif ($time instanceof DateInterval) {
$now = new DateTime();
$this->setExpiresAt($now->add($time));

return $this;
}

throw new InvalidArgumentException('Invalid expiration time');
}

/**
* Get the value irrespective of whether it is in cache or not.
*
* @return mixed The value.
*/
public function getValue()
{
return $this->value;
}

/**
* Get the expires at value.
*
* @return DateTimeInterface The expires at date/time.
*/
public function getExpiresAt()
{
return $this->expiresAt;
}

/**
* Set expires at value from given ttl.
*
* @param int|DateTimeInterface $ttl
*/
protected function setExpiresAt($ttl)
{
if (is_int($ttl)) {
$this->expiresAt = new DateTime('@'.(time() + $ttl));
} elseif (($ttl instanceof DateTimeInterface) || ($ttl instanceof DateTime)) {
$this->expiresAt = $ttl;
} else {
$this->expiresAt = null;
}
}
}
167 changes: 167 additions & 0 deletions src/Radebatz/ACache/Decorators/Psr/CacheItemPool.php
@@ -0,0 +1,167 @@
<?php

/*
* This file is part of the ACache library.
*
* (c) Martin Rademacher <mano@radebatz.net>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Radebatz\ACache\Decorators\Psr;

use Psr\Cache\CacheItemInterface;
use Psr\Cache\CacheItemPoolInterface;
use Radebatz\ACache\CacheInterface;

/**
* ACache Psr CacheItemPool implementation.
*/
class CacheItemPool implements CacheItemPoolInterface
{
const BAD_KEY_CHARS = '{}()/\@:';

/** @var $cache CacheInterface */
protected $cache;
protected $deferred;

/**
* Create a new cache item pool.
*
* @param $cache CacheInterface The underlying cache instance.
*/
public function __construct(CacheInterface $cache)
{
$this->cache = $cache;
$this->deferred = array();
}

/**
* {@inheritDoc}
*/
public function hasItem($key)
{
if (strpbrk($key, CacheItemPool::BAD_KEY_CHARS)) {
throw new InvalidArgumentException(sprintf('Invalid key: %s', $key));
}

if (array_key_exists($key, $this->deferred)) {
return true;
}

return $this->cache->contains($key);
}

/**
* {@inheritDoc}
*/
public function getItem($key)
{
if (strpbrk($key, CacheItemPool::BAD_KEY_CHARS)) {
throw new InvalidArgumentException(sprintf('Invalid key: %s', $key));
}

if (array_key_exists($key, $this->deferred)) {
return $this->deferred[$key];
}

$ttl = null;
$value = null;
if ($this->cache->contains($key)) {
$ttl = $this->cache->getTimeToLive($key);
$value = $this->cache->fetch($key);
}

return new CacheItem($key, $value, $this, 0 === $ttl ? null : $ttl);
}

/**
* {@inheritDoc}
*/
public function getItems(array $keys = array())
{
$items = array();
foreach ($keys as $key) {
$items[] = $this->getItem($key);
}

return $items;
}

/**
* {@inheritDoc}
*/
public function clear()
{
$this->cache->flush();

return true;
}

/**
* {@inheritDoc}
*/
public function deleteItem($key)
{
$this->cache->delete($key);

return $this;
}

/**
* {@inheritDoc}
*/
public function deleteItems(array $keys)
{
foreach ($keys as $key) {
$this->cache->delete($key);
}

return $this;
}

/**
* {@inheritDoc}
*/
public function save(CacheItemInterface $item)
{
$expiresAt = $item->getExpiresAt();
$this->cache->save($item->getKey(), $item->getValue(), null === $expiresAt ? 0 : $expiresAt->getTimestamp() - time());

return $this;
}

/**
* {@inheritDoc}
*/
public function saveDeferred(CacheItemInterface $item)
{
// TODO: improve $this->deferred[$item->getKey()] = $item;
$this->save($item);

return $this;
}

/**
* {@inheritDoc}
*/
public function commit()
{
foreach ($this->deferred as $item) {
$this->save($item);
}

return true;
}

/**
* Get the underlying cache instance.
*
* @return CacheInterface The cache.
*/
public function getCache()
{
return $this->cache;
}
}
16 changes: 16 additions & 0 deletions src/Radebatz/ACache/Decorators/Psr/InvalidArgumentException.php
@@ -0,0 +1,16 @@
<?php

/*
* This file is part of the ACache library.
*
* (c) Martin Rademacher <mano@radebatz.net>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Radebatz\ACache\Decorators\Psr;

class InvalidArgumentException extends \Exception implements \Psr\Cache\InvalidArgumentException
{
}
Empty file modified src/Radebatz/ACache/FilesystemCache.php 100755 → 100644
Empty file.
Empty file modified src/Radebatz/ACache/NullCache.php 100755 → 100644
Empty file.
Empty file modified tests/Radebatz/ACache/Tests/ApcGCTest.php 100755 → 100644
Empty file.
Empty file modified tests/Radebatz/ACache/Tests/CacheTest.php 100755 → 100644
Empty file.

0 comments on commit 53dfd8c

Please sign in to comment.