1
0
Fork 0
mirror of https://github.com/Oreolek/ifhub.club.git synced 2024-07-16 21:34:25 +03:00
ifhub.club/classes/lib/external/DklabCache/Cache/Backend/TagEmuWrapper.php
2008-09-21 06:36:57 +00:00

148 lines
4.5 KiB
PHP

<?php
/**
* Dklab_Cache_Backend_TagEmuWrapper: tag wrapper for any Zend_Cache backend.
*
* Implements tags. Tags are emulated via keys: unfortunately this
* increases the data read cost (the more tags are assigned to a key,
* the more read cost becomes).
*
* $Id: MetaForm.php 238 2008-03-17 21:07:17Z dk $
*/
require_once "Zend/Cache/Backend/Interface.php";
class Dklab_Cache_Backend_TagEmuWrapper implements Zend_Cache_Backend_Interface
{
const VERSION = "01";
private $_backend = null;
public function __construct(Zend_Cache_Backend_Interface $backend)
{
$this->_backend = $backend;
}
public function setDirectives($directives)
{
return $this->_backend->setDirectives($directives);
}
public function load($id, $doNotTestCacheValidity = false)
{
return $this->_loadOrTest($id, $doNotTestCacheValidity, false);
}
public function save($data, $id, $tags = array(), $specificLifetime = false)
{
// Save/update tags as usual infinite keys with value of tag version.
// If the tag already exists, do not rewrite it.
$tagsWithVersion = array();
if (is_array($tags)) {
foreach ($tags as $tag) {
$mangledTag = $this->_mangleTag($tag);
$tagVersion = $this->_backend->load($mangledTag);
if ($tagVersion === false) {
$tagVersion = $this->_generateNewTagVersion();
$this->_backend->save($tagVersion, $mangledTag, array(), null);
}
$tagsWithVersion[$tag] = $tagVersion;
}
}
// Data is saved in form of: array(tagsWithVersionArray, anyData).
$combined = array($tagsWithVersion, $data);
$serialized = serialize($combined);
return $this->_backend->save($serialized, $id, array(), $specificLifetime);
}
public function clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array())
{
if ($mode == Zend_Cache::CLEANING_MODE_MATCHING_TAG) {
if (is_array($tags)) {
foreach ($tags as $tag) {
$this->_backend->remove($this->_mangleTag($tag));
}
}
} else {
return $this->_backend->clean($mode, $tags);
}
}
public function test($id)
{
return $this->_loadOrTest($id, false, true);
}
public function remove($id)
{
return $this->_backend->remove($id);
}
/**
* Mangles the name to deny intersection of tag keys & data keys.
* Mangled tag names are NOT saved in memcache $combined[0] value,
* mangling is always performed on-demand (to same some space).
*
* @param string $tag Tag name to mangle.
* @return string Mangled tag name.
*/
private function _mangleTag($tag)
{
return __CLASS__ . "_" . self::VERSION . "_" . $tag;
}
/**
* Common method called from load() and test().
*
* @param string $id
* @param bool $doNotTestCacheValidity
* @param bool $returnTrueIfValid If true, returns not the value contained
* in the slot, but "true".
* @return mixed
*/
private function _loadOrTest($id, $doNotTestCacheValidity = false, $returnTrueIfValid = false)
{
// Data is saved in form of: array(tagsWithVersionArray, anyData).
$serialized = $this->_backend->load($id, $doNotTestCacheValidity);
if ($serialized === false) {
return false;
}
$combined = unserialize($serialized);
if (!is_array($combined)) {
return false;
}
// Test if all tags has the same version as when the slot was created
// (i.e. still not removed and then recreated).
if (is_array($combined[0])) {
foreach ($combined[0] as $tag => $savedTagVersion) {
$actualTagVersion = $this->_backend->load($this->_mangleTag($tag));
if ($actualTagVersion !== $savedTagVersion) {
return false;
}
}
}
return $returnTrueIfValid? true : $combined[1];
}
/**
* Generates a new unique identifier for tag version.
*
* @return string Globally (hopefully) unique identifier.
*/
private function _generateNewTagVersion()
{
static $counter = 0;
$counter++;
return md5(microtime() . getmypid() . uniqid('') . $counter);
}
}