Created
February 18, 2014 07:31
-
-
Save rbraband/9066162 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* php_XCache | |
* | |
* @package XCache | |
* @version $Id$ | |
* @copyright 2014 | |
* @author Roland Braband <rbraband@web.de> | |
* @license BSD {@link http://www.opensource.org/licenses/bsd-license.php} | |
*/ | |
/** | |
* HowTo | |
* | |
$cache = php_XCache::getInstance(); | |
$xc_key = $cache->generateKey('DomainKey', 'Identifier'); | |
// determine the current user_id | |
if (is_null($user_id = $cache->get($xc_key))) { | |
$user_id = 1; | |
$cache->set($xc_key, $user_id); | |
} | |
// flush the domain cache | |
php_XCache::getInstance()->flushKeys('DomainKey'); | |
*/ | |
if (!defined('XC_TYPE_PHP')) define('XC_TYPE_PHP', 0); | |
if (!defined('XC_TYPE_VAR')) define('XC_TYPE_VAR', 1); | |
/** | |
* @property mixed FORCE_HASH | |
* @property mixed FORCE_TTL | |
* @property mixed SKIP_EXISTING | |
* @property mixed XC_ENABLE | |
*/ | |
class php_XCache { | |
private static $xcobj; | |
private $enabled; | |
private $xcnamespace; | |
private $xcttl; | |
private $xccrypt; | |
const SKIP_EXISTING = 'skipExisting'; | |
const FORCE_HASH = 'forceHash'; | |
const FORCE_TTL = 'forceTTL'; | |
const CACHE_SUFFIX = '.cache'; | |
const KEY_PREFIX = 'XCK'; | |
const XC_KEYVALUE = 'XC_KeyValue'; | |
const XC_LIST = 'XC_List'; | |
const XC_HASH = 'XC_Hash'; | |
const XC_ENABLE = 'XC_Enable'; | |
private function __construct($container, $options = array()) { | |
if (!extension_loaded('Xcache')) throw new RuntimeException('Unable to use XcacheClassLoader as Xcache is not enabled.'); | |
if (defined('STDIN')) { | |
$this->enabled = false; | |
return; | |
} | |
switch ($container) { | |
case 'XCACHE_KEY': | |
if (!isset($_SERVER['XCACHE_KEY'])) { | |
$this->enabled = false; | |
return; | |
} | |
$this->xccrypt = (isset($option[$this->FORCE_HASH])) ? (bool) $option[$this->FORCE_HASH] : false; | |
$this->xcttl = (isset($option[$this->FORCE_TTL])) ? (int) $option[$this->FORCE_TTL] : 60 * 60 * 24; | |
$this->xcnamespace = $_SERVER['XCACHE_KEY']; | |
break; | |
case 'HTTP_HOST': | |
if (!isset($_SERVER['HTTP_HOST'])) { | |
$this->enabled = false; | |
return; | |
} | |
$this->xccrypt = (isset($option[$this->FORCE_HASH])) ? (bool) $option[$this->FORCE_HASH] : false; | |
$this->xcttl = (isset($option[$this->FORCE_TTL])) ? (int) $option[$this->FORCE_TTL] : 60 * 60 * 1; | |
$this->xcnamespace = $_SERVER['HTTP_HOST']; | |
break; | |
case 'SESSION': | |
$this->xccrypt = (isset($option[$this->FORCE_HASH])) ? (bool) $option[$this->FORCE_HASH] : true; | |
$this->xcttl = (isset($option[$this->FORCE_TTL])) ? (int) $option[$this->FORCE_TTL] : 60 * 60 * 2; | |
$this->xcnamespace = session_id(); | |
break; | |
case 'GLOBAL': | |
$this->xccrypt = (isset($option[$this->FORCE_HASH])) ? (bool) $option[$this->FORCE_HASH] : false; | |
$this->xcttl = (isset($option[$this->FORCE_TTL])) ? (int) $option[$this->FORCE_TTL] : 0; | |
$this->xcnamespace = 'GLOBAL'; | |
break; | |
default: | |
$this->xccrypt = (isset($option[$this->FORCE_HASH])) ? (bool) $option[$this->FORCE_HASH] : false; | |
$this->xcttl = (isset($option[$this->FORCE_TTL])) ? (int) $option[$this->FORCE_TTL] : 300; | |
$this->xcnamespace = $container; | |
} | |
$this->enabled = (isset($option[$this->XC_ENABLE])) ? (bool) $option[$this->XC_ENABLE] : true; | |
} | |
public final function __clone() { | |
throw new BadMethodCallException("Clone is not allowed"); | |
} | |
/** | |
* getInstance | |
* | |
* @static | |
* @access public | |
* | |
* @param string $container | |
* @param array $options | |
* | |
* @return object XCache instance | |
*/ | |
public static function getInstance($container = 'XCACHE_KEY', $options = array()) { | |
$container = str_replace(array('/', '\\', ' '), '_', trim(strtoupper($container))); | |
if (!(isset(self::$xcobj[$container]) || self::$xcobj[$container] instanceof php_XCache)) { | |
self::$xcobj[$container] = new php_XCache($container, $options); | |
} | |
return self::$xcobj[$container]; | |
} | |
/** | |
* set | |
* | |
* @param mixed $name | |
* @param mixed $value | |
* @param int $time | |
* @param mixed $option | |
* | |
* @throws InvalidArgumentException | |
* @access public | |
* @return bool | |
*/ | |
public function set($name, $value, $time = null, $option = array()) { | |
if (!$this->enabled) return false; | |
if (is_array($name)) $name = $this->generateKey($name); | |
if (is_resource($value) || is_object($value) || is_callable($value)) throw new InvalidArgumentException("At the moment, It is not possible to store resources, callbacks or objects!"); | |
$time = (is_null($time)) ? $this->xcttl : intval($time); | |
if (isset($option[$this->SKIP_EXISTING]) && $option[$this->SKIP_EXISTING] === true) { | |
if (!$this->isExisting($name)) { | |
return xcache_set($this->_sanitize_id($name, $this->xcnamespace), $value, $time); | |
} | |
} else { | |
return xcache_set($this->_sanitize_id($name, $this->xcnamespace), $value, $time); | |
} | |
return false; | |
} | |
/** | |
* __set | |
* | |
* @param mixed $name | |
* @param mixed $value | |
* | |
* @throws InvalidArgumentException | |
* @internal param int $time | |
* @internal param mixed $option | |
* @access public | |
* @return bool | |
*/ | |
public function __set($name, $value) { | |
if (!$this->enabled) return false; | |
if (is_array($name)) $name = $this->generateKey($name); | |
if (is_resource($value) || is_object($value) || is_callable($value)) throw new InvalidArgumentException("At the moment, It is not possible to store resources, callbacks or objects!"); | |
return xcache_set($this->_sanitize_id($name, $this->xcnamespace), $value, $this->xcttl); | |
} | |
/** | |
* touch | |
* | |
* @param mixed $name | |
* | |
* @internal param int $time | |
* @access public | |
* @return bool | |
*/ | |
public function touch($name) { | |
if (!$this->enabled) return false; | |
$data = $this->get($name); | |
if ($data == null) { | |
return false; | |
} else { | |
$this->set($name, $data); | |
return true; | |
} | |
} | |
/** | |
* get | |
* | |
* @param mixed $name | |
* | |
* @access public | |
* @return mixed | |
*/ | |
public function get($name) { | |
if (!$this->enabled) return null; | |
if (is_array($name)) $name = $this->generateKey($name); | |
$data = xcache_get($this->_sanitize_id($name, $this->xcnamespace)); | |
if ($data === false || $data == "") { | |
return null; | |
} | |
return $data; | |
} | |
/** | |
* __get | |
* | |
* @param mixed $name | |
* | |
* @access public | |
* @return mixed | |
*/ | |
public function __get($name) { | |
if (!$this->enabled) return null; | |
$data = xcache_get($this->_sanitize_id($name, $this->xcnamespace)); | |
if ($data === false || $data == "") { | |
return null; | |
} | |
return $data; | |
} | |
/** | |
* __isset | |
* | |
* @param mixed $name | |
* | |
* @access public | |
* @return bool | |
*/ | |
public function __isset($name) { | |
if (!$this->enabled) return false; | |
if (is_array($name)) $name = $this->generateKey($name); | |
return xcache_isset($this->_sanitize_id($name, $this->xcnamespace)); | |
} | |
/** | |
* isExisting | |
* | |
* @param mixed $name | |
* | |
* @access public | |
* @return bool | |
*/ | |
function isExisting($name) { | |
if (!$this->enabled) return false; | |
if (is_array($name)) $name = $this->generateKey($name); | |
if (xcache_isset($this->_sanitize_id($name, $this->xcnamespace))) { | |
return true; | |
} else { | |
return false; | |
} | |
} | |
/** | |
* __unset | |
* | |
* @param mixed $name | |
* | |
* @access public | |
* @return bool | |
*/ | |
public function __unset($name) { | |
if (!$this->enabled) return false; | |
if (is_array($name)) $name = $this->generateKey($name); | |
return xcache_unset($this->_sanitize_id($name, $this->xcnamespace)); | |
} | |
/** | |
* delete | |
* | |
* @param mixed $name | |
* | |
* @access public | |
* @return bool | |
*/ | |
public function delete($name) { | |
if (!$this->enabled) return false; | |
if (is_array($name)) $name = $this->generateKey($name); | |
return xcache_unset($this->_sanitize_id($name, $this->xcnamespace)); | |
} | |
/** | |
* clean | |
* | |
* @access public | |
* @return void | |
*/ | |
public function clean() { | |
$cnt = xcache_count(XC_TYPE_VAR); | |
for ($i = 0; $i < $cnt; $i++) { | |
xcache_clear_cache(XC_TYPE_VAR, $i); | |
} | |
} | |
/** | |
* info | |
* | |
* @access public | |
* | |
* @param $html | |
* | |
* @return array | |
*/ | |
public function info($html = false) { | |
$_bool = Array(false => 'false', true => 'true'); | |
if ($html === true) { | |
return "crypted: {$_bool[$this->xccrypt]}, ttl: {$this->xcttl}, namespace: {$this->xcnamespace}, enabled: {$_bool[$this->enabled]}"; | |
} else { | |
return array('crypted' => $this->xccrypt, | |
'ttl' => $this->xcttl, | |
'namespace' => $this->xcnamespace, | |
'enabled' => $this->enabled | |
); | |
} | |
} | |
/** | |
* flushKeys | |
* | |
* @access public | |
* | |
* @param $pattern | |
* | |
* @return void | |
*/ | |
public function flushKeys($pattern) { | |
if (!$this->enabled) return; | |
$varCacheCount = xcache_count(XC_TYPE_VAR); | |
for ($i = 0; $i < $varCacheCount; $i++) { | |
$items = xcache_list(XC_TYPE_VAR, $i); | |
foreach ($items['cache_list'] as $item) { | |
preg_match('/^(?P<prefix>' . $this->xcnamespace . '):(?P<key>' . self::KEY_PREFIX . '):(?P<id>' . trim($pattern) . '.{0,})(?P<suffix>' . self::CACHE_SUFFIX . ')$/i', $item['name'], $match); | |
if (!empty($match)) xcache_unset($match[0]); | |
} | |
} | |
} | |
/** | |
* getKeys | |
* | |
* @access public | |
* | |
* @param $pattern | |
* | |
* @return array | |
*/ | |
public function getKeys($pattern) { | |
if (!$this->enabled) return array(); | |
$_keys = array(); | |
$varCacheCount = xcache_count(XC_TYPE_VAR); | |
for ($i = 0; $i < $varCacheCount; $i++) { | |
$items = xcache_list(XC_TYPE_VAR, $i); | |
$_keys = array(); | |
foreach ($items['cache_list'] as $item) { | |
preg_match('/^(?P<prefix>' . $this->xcnamespace . '):(?P<key>' . self::KEY_PREFIX . '):(?P<id>' . trim($pattern) . ')(?P<suffix>' . self::CACHE_SUFFIX . ')$/i', $item['name'], $match); | |
if (!empty($match)) array_push($_keys, $match['key']); | |
} | |
} | |
return $_keys; | |
} | |
/** | |
* increment | |
* | |
* @param mixed $name | |
* @param int $step | |
* | |
* @access public | |
* @return int | |
*/ | |
public function increment($name, $step = 1) { | |
if (!$this->enabled) return 0; | |
if (is_array($name)) $name = $this->generateKey($name); | |
return xcache_inc($this->_sanitize_id($name, $this->xcnamespace), (int) $step); | |
} | |
/** | |
* decrement | |
* | |
* @param mixed $name | |
* @param int $step | |
* | |
* @access public | |
* @return int | |
*/ | |
public function decrement($name, $step = 1) { | |
if (!$this->enabled) return 0; | |
if (is_array($name)) $name = $this->generateKey($name); | |
return xcache_dec($this->_sanitize_id($name, $this->xcnamespace), (int) $step); | |
} | |
/** | |
* lock | |
* | |
* @param mixed $name | |
* | |
* @access public | |
* @return bool | |
*/ | |
public function lock($name) { | |
if (!$this->enabled) return false; | |
if (is_array($name)) $name = $this->generateKey($name); | |
return xcache_inc($this->_sanitize_id($name, 'LOCK')) === 1; | |
} | |
/** | |
* unlock | |
* | |
* @param mixed $name | |
* | |
* @access public | |
* @return bool | |
*/ | |
public function unlock($name) { | |
if (!$this->enabled) return false; | |
if (is_array($name)) $name = $this->generateKey($name); | |
return xcache_unset($this->_sanitize_id($name, 'LOCK')); | |
} | |
/** | |
* clear | |
* | |
* @access public | |
* @return void | |
*/ | |
public function clear() { | |
xcache_clear_cache(XC_TYPE_PHP, 0); | |
} | |
/** | |
* generateKey | |
* | |
* @access public | |
* | |
* @param $string | |
* | |
* @throws InvalidArgumentException | |
* @return string | |
*/ | |
public function generateKey($string) { | |
if (empty($string)) throw new InvalidArgumentException("It is not possible to generate empty keys!"); | |
if (func_num_args() > 1) { | |
$args = func_get_args(); | |
// http://php.net/manual/de/function.implode.php | |
$key = self::KEY_PREFIX . ':' . implode(':', $args); | |
} else $key = self::KEY_PREFIX . ':' . trim($string); | |
$key = preg_replace(array('/:{1,2}$/'), '', $key); | |
//echo "<!-- {$key} -->\n"; | |
return $key; | |
} | |
/** | |
* _sanitize_id | |
* | |
* @param mixed $id | |
* @param $prefix | |
* | |
* @access protected | |
* @return string | |
*/ | |
protected function _sanitize_id($id, $prefix) { | |
if ($this->xccrypt) { | |
return hash('md5', $prefix . ':' . str_replace(array('/', '\\', ' '), '_', trim($id)) . self::CACHE_SUFFIX); | |
} else { | |
return $prefix . ':' . str_replace(array('/', '\\', ' '), '_', trim($id)) . self::CACHE_SUFFIX; | |
} | |
} | |
} | |
?> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment