Skip to content

Instantly share code, notes, and snippets.

@bramstroker
Created February 12, 2013 13:33
Show Gist options
  • Save bramstroker/4769914 to your computer and use it in GitHub Desktop.
Save bramstroker/4769914 to your computer and use it in GitHub Desktop.
TaggableMemcached storage adapter
<?php
/**
* Memcached storage adapter with tag support
*
* @category AcsiBase
* @package AcsiBase\Cache
* @copyright 2012 ACSI Holding bv (http://www.acsi.eu)
* @version SVN: $Id$
*/
namespace AcsiBase\Cache\Storage\Adapter;
use Zend\Cache\Storage\TaggableInterface;
use Zend\Cache\Exception;
class TaggableMemcached extends \Zend\Cache\Storage\Adapter\Memcached implements TaggableInterface
{
/**
* Prefix constants
*/
const TAGITEMS_PREFIX = 'tag_';
const ITEMTAGS_PREFIX = 'item_';
/**
* Constructor
*
* @param null|array|Traversable|MemcachedOptions $options
* @throws Exception\ExceptionInterface
*/
public function __construct($options = null)
{
parent::__construct($options);
$this->getOptions()->getResourceManager()->setLibOption($this->getOptions()->getResourceId(), 'compression', false);
}
/**
* Set tags to an item by given key.
* An empty array will remove all tags.
*
* @param string $key
* @param string[] $tags
* @return boolean
*/
public function setTags($key, array $tags)
{
if (!$this->hasItem($key)) {
return false;
}
foreach ($tags as $tag) {
$this->prepend(self::TAGITEMS_PREFIX . $tag, $key . ';');
}
$existingTags = $this->getTags($key);
if ($existingTags !== false) {
$tags = array_merge($existingTags, $tags);
}
$this->setItem(self::ITEMTAGS_PREFIX . $key, $tags);
return true;
}
/**
* Get tags of an item by given key
*
* @param string $key
* @return string[]|FALSE
*/
public function getTags($key)
{
$tags = $this->getItem(self::ITEMTAGS_PREFIX . $key);
if ($tags === false || !is_array($tags)) {
return false;
}
return array_unique($tags);
}
/**
* Remove items matching given tags.
*
* If $disjunction only one of the given tags must match
* else all given tags must match.
*
* @param string[] $tags
* @param boolean $disjunction
* @return boolean
*/
public function clearByTags(array $tags, $disjunction = false)
{
if (!$tags) {
return true;
}
$deleteItems = array();
foreach ($tags as $tag) {
$items = explode(';', $this->getItem(self::TAGITEMS_PREFIX . $tag));
array_pop($items);
if (!$disjunction) {
if (empty($deleteItems)) {
$deleteItems = $items;
} else {
$deleteItems = array_intersect($deleteItems, $items);
}
} else {
$deleteItems = array_merge($deleteItems, $items);
}
}
$deleteItems = array_unique($deleteItems);
foreach ($deleteItems as $item) {
if (!$this->removeItem($item)) {
return false;
}
}
return true;
}
/**
* Prepend
*
* @param string $key
* @param string $value
*/
protected function prepend($key, $value)
{
if (!$this->internalHasItem($key, $value)) {
$this->setItem($key, $value);
} else {
$this->normalizeKey($key);
$this->getMemcachedResource()->prepend($key, $value);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment