*/ /** * CacheHandler * * @author NAVER (developer@xpressengine.com) */ class CacheHandler extends Handler { /** * Instances are stored here. */ protected static $_instances = array(); /** * instance of cache handler * @var CacheBase */ protected $handler = null; /** * Version of key group * @var int */ protected $keyGroupVersions = null; /** * Get a instance of CacheHandler(for singleton) * * @param string $target type of cache (object|template) * @param object $info info. of DB * @param boolean $always_use_file If set true, use a file cache always * @return CacheHandler */ public static function getInstance($target = 'object', $info = null, $always_use_file = false) { $key = 'object' . ($always_use_file ? '_file' : ''); if (!isset(self::$_instances[$key])) { self::$_instances[$key] = new self($target, $info, $always_use_file); } return self::$_instances[$key]; } /** * Constructor. * * Do not use this directly. You can use getInstance() instead. * * @see CacheHandler::getInstance * @param string $target type of cache (object) * @param object $info info. of DB * @param boolean $always_use_file If set true, use a file cache always * @return CacheHandler */ protected function __construct($target, $info = null, $always_use_file = false) { // Allow using custom cache info for backward compatibility. if (is_object($info) && $info->use_object_cache) { $cache_config = $cache_config_array = $info->use_object_cache; } else { $cache_config = $cache_config_array = config('cache'); if (is_array($cache_config) && count($cache_config)) { $cache_config = array_first($cache_config); } } // Handle various types of cache backend. if (preg_match('/^(apc|memcache|redis|wincache|file)/', strval($cache_config), $matches)) { $type = $matches[1]; } elseif ($always_use_file) { $type = 'file'; } else { return; } // Create an instance of cache backend. $class = 'Cache' . ucfirst($type); include_once sprintf('%sclasses/cache/%s.class.php', _XE_PATH_, $class); $this->handler = $class::getInstance($cache_config_array); // Initialize key group versions. $this->keyGroupVersions = $this->handler->get('key_group_versions', 0); if(!$this->keyGroupVersions) { $this->keyGroupVersions = array(); $this->handler->put('key_group_versions', $this->keyGroupVersions, 0); } } /** * Return whether support or not support cache * * @return boolean */ public function isSupport($type = null, $cache_config = null) { if ($type === null) { return ($this->handler && $this->handler->isSupport()); } else { $class = 'Cache' . ucfirst(str_replace('memcached', 'memcache', $type)); include_once sprintf('%sclasses/cache/%s.class.php', _XE_PATH_, $class); $handler = $class::getInstance($cache_config, true); return $handler->isSupport(); } } /** * Get cache name by key * * @param string $key The key that will be associated with the item. * @return string Returns cache name */ public function getCacheKey($key) { return RX_VERSION . ':' . str_replace('/', ':', $key); } /** * Get cached data * * @param string $key Cache key * @param int $modified_time Unix time of data modified. * If stored time is older then modified time, return false. * @return false|mixed Return false on failure or older then modified time. Return the string associated with the $key on success. */ public function get($key, $modified_time = 0) { if (!$key) return false; return $this->handler ? $this->handler->get($this->getCacheKey($key), $modified_time) : false; } /** * Put data into cache * * @param string $key Cache key * @param mixed $obj Value of a variable to store. $value supports all data types except resources, such as file handlers. * @param int $valid_time Time for the variable to live in the cache in seconds. * After the value specified in ttl has passed the stored variable will be deleted from the cache. * If no ttl is supplied, use the default valid time. * @return bool|void Returns true on success or false on failure. If use CacheFile, returns void. */ public function put($key, $obj, $valid_time = 0) { if (!$key) return false; return $this->handler ? $this->handler->put($this->getCacheKey($key), $obj, $valid_time) : false; } /** * Delete Cache * * @param string $key Cache key * @return void */ public function delete($key) { if (!$key) return false; return $this->handler ? $this->handler->delete($this->getCacheKey($key)) : false; } /** * Return whether cache is valid or invalid * * @param string $key Cache key * @param int $modified_time Unix time of data modified. * If stored time is older then modified time, the data is invalid. * @return bool Return true on valid or false on invalid. */ public function isValid($key, $modified_time = 0) { if (!$key) return false; return $this->handler ? $this->handler->isValid($this->getCacheKey($key), $modified_time) : false; } /** * Truncate all cache * * @return bool|void Returns true on success or false on failure. If use CacheFile, returns void. */ public function truncate() { return $this->handler ? $this->handler->truncate() : false; } /** * Function used for generating keys for similar objects. * * Ex: 1:document:123 * 1:document:777 * * This allows easily removing all object of type "document" * from cache by simply invalidating the group key. * * The new key will be 2:document:123, thus forcing the document * to be reloaded from the database. * * @param string $keyGroupName Group name * @param string $key Cache key * @return string */ public function getGroupKey($keyGroupName, $key) { if(!$this->keyGroupVersions[$keyGroupName]) { $this->keyGroupVersions[$keyGroupName] = 1; $this->handler->put('key_group_versions', $this->keyGroupVersions, 0); } return 'cache_group_' . $this->keyGroupVersions[$keyGroupName] . ':' . $keyGroupName . ':' . $key; } /** * Make invalid group key (like delete group key) * * @param string $keyGroupName Group name * @return void */ public function invalidateGroupKey($keyGroupName) { $this->keyGroupVersions[$keyGroupName]++; $this->handler->put('key_group_versions', $this->keyGroupVersions, 0); } } /** * Base class of Cache * * @author NAVER (developer@xpressengine.com) */ class CacheBase { /** * Default valid time * @var int */ public $valid_time = 36000; /** * Get cached data * * @param string $key Cache key * @param int $modified_time Unix time of data modified. * If stored time is older then modified time, return false. * @return false|mixed Return false on failure or older then modified time. Return the string associated with the $key on success. */ public function get($key, $modified_time = 0) { return false; } /** * Put data into cache * * @param string $key Cache key * @param mixed $obj Value of a variable to store. $value supports all data types except resources, such as file handlers. * @param int $valid_time Time for the variable to live in the cache in seconds. * After the value specified in ttl has passed the stored variable will be deleted from the cache. * If no ttl is supplied, use the default valid time. * @return bool|void Returns true on success or false on failure. If use CacheFile, returns void. */ public function put($key, $obj, $valid_time = 0) { return false; } /** * Alias of put() */ public function set($key, $obj, $valid_time = 0) { return $this->put($key, $obj, $valid_time = 0); } /** * Return whether cache is valid or invalid * * @param string $key Cache key * @param int $modified_time Unix time of data modified. * If stored time is older then modified time, the data is invalid. * @return bool Return true on valid or false on invalid. */ public function isValid($key, $modified_time = 0) { return false; } /** * Return whether support or not support cache * * @return boolean */ public function isSupport() { return false; } /** * Truncate all cache * * @return bool|void Returns true on success or false on failure. If use CacheFile, returns void. */ public function truncate() { return false; } } /* End of file CacheHandler.class.php */ /* Location: ./classes/cache/CacheHandler.class.php */