From c62c550e3f2619f2731fac98fe9974d8efb6f827 Mon Sep 17 00:00:00 2001 From: phpnut Date: Mon, 30 Apr 2007 06:01:54 +0000 Subject: [PATCH] Adding initial implementation of extended caching capabilities git-svn-id: https://svn.cakephp.org/repo/branches/1.2.x.x@4933 3807eeeb-6ff5-0310-8944-8be069107fe0 --- app/config/core.php | 82 ++++++-- cake/libs/cache.php | 302 +++++++++++++++++++++------- cake/libs/cache/apc_engine.php | 84 ++++++++ cake/libs/cache/file_engine.php | 249 +++++++++++++++++++++++ cake/libs/cache/memcache_engine.php | 111 ++++++++++ cake/libs/cache/model_engine.php | 121 +++++++++++ 6 files changed, 854 insertions(+), 95 deletions(-) create mode 100644 cake/libs/cache/apc_engine.php create mode 100644 cake/libs/cache/file_engine.php create mode 100644 cake/libs/cache/memcache_engine.php create mode 100644 cake/libs/cache/model_engine.php diff --git a/app/config/core.php b/app/config/core.php index 5968e9473..861ec4287 100644 --- a/app/config/core.php +++ b/app/config/core.php @@ -30,11 +30,11 @@ * To configure CakePHP *not* to use mod_rewrite and to * use CakePHP pretty URLs, remove these .htaccess * files: - * + * * /.htaccess * /app/.htaccess * /app/webroot/.htaccess - * + * * And uncomment the define below: */ @@ -42,10 +42,10 @@ /** * CakePHP Debug Level: - * + * * Production Mode: * 0: No error messages, errors, or warnings shown. Flash messages redirect. - * + * * Development Mode: * 1: Errors and warnings shown, model caches refreshed, flash messages halted. * 2: As in 1, but also with full debug messages and SQL output. @@ -57,37 +57,37 @@ define('DEBUG', 2); /** * Turn off or enable cache checking application-wide. - * - * If set to true, you must still use the controller var $cacheAction inside - * your controllers to define caching settings. You can either set it - * controller-wide by setting var $cacheAction = true, or in each action + * + * If set to true, you must still use the controller var $cacheAction inside + * your controllers to define caching settings. You can either set it + * controller-wide by setting var $cacheAction = true, or in each action * using $this->cacheAction = true. */ define('CACHE_CHECK', false); /** - * Defines the default error type when using the log() function. Used for + * Defines the default error type when using the log() function. Used for * differentiating error logging and debugging. Currently PHP supports LOG_DEBUG. */ define('LOG_ERROR', 2); /** * The preferred session handling method. Valid values: - * + * * 'php' Uses settings defined in your php.ini. * 'cake' Saves session files in CakePHP's /tmp directory. * 'database' Uses CakePHP's database sessions. - * + * * To define a custom session handler, save it at /app/config/.php. * Set the value of CAKE_SESSION_SAVE to to utilize it in CakePHP. - * + * * To use database sessions, execute the SQL file found at /app/config/sql/sessions.sql. * */ define('CAKE_SESSION_SAVE', 'php'); /** * The name of the table used to store CakePHP database sessions. - * + * * CAKE_SESSION_SAVE must be set to 'database' in order to utilize this constant. - * + * * The table name set here should *not* include any table prefix defined elsewhere. */ define('CAKE_SESSION_TABLE', 'cake_sessions'); @@ -103,12 +103,12 @@ * The level of CakePHP session security. The session timeout time defined * in CAKE_SESSION_TIMEOUT is multiplied according to the settings here. * Valid values: - * + * * 'high' Session timeout in CAKE_SESSION_TIMEOUT x 10 * 'medium' Session timeout in CAKE_SESSION_TIMEOUT x 100 * 'low' Session timeout in CAKE_SESSION_TIMEOUT x 300 - * - * CakePHP session IDs are also regenerated between requests if + * + * CakePHP session IDs are also regenerated between requests if * CAKE_SECURITY is set to 'high'. */ define('CAKE_SECURITY', 'high'); @@ -119,10 +119,10 @@ define('CAKE_SESSION_TIMEOUT', '120'); /** * Uncomment the define below to use CakePHP admin routes. - * + * * The value of the define determines the name of the route * and its associated controller actions: - * + * * 'admin' -> admin_index() and /admin/controller/index * 'superuser' -> superuser_index() and /superuser/controller/index */ @@ -134,7 +134,7 @@ /** * Compress CSS output by removing comments, whitespace, repeating tags, etc. * This requires a/var/cache directory to be writable by the web server for caching. - * + * * To use, prefix the CSS link URL with '/ccss/' instead of '/css/' or use Controller::cssTag(). */ define('COMPRESS_CSS', false); @@ -147,10 +147,50 @@ */ define('MAX_MD5SIZE', (5 * 1024) * 1024); /** - * The classname, filename, (and database) used in CakePHP's + * The classname, filename, (and database) used in CakePHP's * access control lists. */ define('ACL_CLASSNAME', 'DB_ACL'); define('ACL_FILENAME', 'dbacl' . DS . 'db_acl'); define('ACL_DATABASE', 'default'); +/** + * Use the file storage engine with default parameters. + * Cached data is kept in app/tmp/cache/ + * + * File storage + * Cache::engine('File', array( + * 'dir' => '/tmp/', // use system tmp directory - remember to use absolute path + * 'prefix' => 'cakecache_', // prefix every cache file with this string + * 'lock' => true, // use file locking + * )); + * + * APC (Alternative PHP Cache) + * Cache::engine('APC'); + * + * Memcache + * Cache::engine('Memcache', array( + * 'servers' => array( + * '127.0.0.1', // localhost, default port + * '10.0.0.1:12345', // port 12345 + * ), + * 'compress' => true, // compress data in Memcache (slower, but uses less memory) + * )); + * + * Cake Model + * Cache::engine('Model', array( + * 'modelName' => 'DbModel', + * 'dataField' => 'value', + * 'expiryField' => 'expires')); + */ + Cache::engine('File'); +/** + * How long to cache data if not defined + * 3600 = 1 hour + */ + define('CACHE_DEFAULT_DURATION', 3600); +/** + * How often to do garbage collection + * about once in every hundred page loads + */ + define('CACHE_GC_PROBABILITY', 100); ?> \ No newline at end of file diff --git a/cake/libs/cache.php b/cake/libs/cache.php index 687e21e73..8c5aff0ed 100644 --- a/cake/libs/cache.php +++ b/cake/libs/cache.php @@ -1,7 +1,7 @@ id = (md5($id)); - parent::__construct($this->id); + function __construct() { } /** - * Returns this object's id after setting it. If called without parameters the current object's id is returned. + * Returns a singleton instance * - * @param unknown_type $id - * @return unknown + * @return object */ - function id($id = null) { - if (!$id) { - return $this->id; + function &getInstance() { + static $instance = array(); + if(!isset($instance[0]) || !$instance[0]) { + $instance[0] =& new Cache(); } - return ($this->id = $id); + return $instance[0]; } /** - * Store given content in cache database. - * - * @param string $content Content to keep in cache. - * @param int $keep_for Number of seconds to keep data in cache. - * @return boolean Success + * Tries to find and include a file for a cache engine + * @param $name + * @return boolean */ - function remember($content, $keep_for = CACHE_PAGES_FOR) { - $data = addslashes($this->for_caching . $content); - $expire = date("Y-m-d H:i:s", time() + ($keep_for > 0 ? $keep_for : 999999999)); - return $this->query("REPLACE {$this->useTable} (id,data,expire) VALUES ('{$this->id}', '{$data}', '{$expire}')"); - } -/** - * Returns content from the Cache object itself, if the Cache object has a non-empty data property. - * Else from the database cache. - * - * @return unknown - */ - function restore() { - if (empty($this->data['data'])) { - return $this->find("id='{$this->id}' AND expire>NOW()"); + function _includeEngine($name) { + if (class_exists($name.'Engine')) { + return true; } - return $this->data['data']; - } + $fileName = strtolower($name).'_engine'; + + if(vendor('cache_engines/'.$fileName)) { + return true; + } + $fileName = dirname(__FILE__) . DS . 'cache' . DS . $fileName . '.php'; + + if(is_readable($fileName)) { + include $fileName; + return true; + } + return false; + } /** - * Returns true if the cache data property has current (non-stale) content for given id. + * Set the cache engine to use + * + * @param string $name Name of the engine (without 'Engine') + * @param array $parmas Optional associative array of parameters passed to the engine + * @return boolean True on success, false on failure + */ + function engine($name, &$params = array()) { + if(defined('DISABLE_CACHE')) { + return false; + } + $_this =& Cache::getInstance(); + $cacheClass= $name.'Engine'; + + if (!Cache::_includeEngine($name) || !class_exists($cacheClass)) { + return false; + } + $_this->_Engine =& new $cacheClass(); + + if ($_this->_Engine->init($params)) { + if(time() % CACHE_GC_PROBABILITY == 0) { + $_this->_Engine->gc(); + } + return true; + } + $this->_Engine = null; + return false; + } +/** + * Write a value in the cache + * + * @param string $key Identifier for the data + * @param mixed $value Data to be cached - anything except a resource + * @param mixed $duration Optional - how long to cache the data, either in seconds or a string that can be parsed by the strtotime() function + * @return boolean True if the data was succesfully cached, false on failure + */ + function write($key, $value, $duration = CACHE_DEFAULT_DURATION) { + if (defined('DISABLE_CACHE')) { + return false; + } + $key = strval($key); + + if(empty($key)) { + return false; + } + + if(is_resource($value)) { + return false; + } + $duration = ife(is_string($duration), strtotime($duration), intval($duration)); + + if($duration < 1) { + return false; + } + $_this =& Cache::getInstance(); + + if(!isset($_this->_Engine)) { + return false; + } + return $_this->_Engine->write($key, $value, $duration); + } +/** + * Read a value from the cache + * + * @param string $key Identifier for the data + * @return mixed The cached data, or false if the data doesn't exist, has expired, or if there was an error fetching it + */ + function &read($key) { + if(defined('DISABLE_CACHE')) { + $val = false; + return $val; + } + $key = strval($key); + + if(empty($key)) { + return false; + } + + $_this =& Cache::getInstance(); + + if(!isset($_this->_Engine)) { + return false; + } + return $val; + } +/** + * Delete a value from the cache + * + * @param string $key Identifier for the data + * @return boolean True if the value was succesfully deleted, false if it didn't exist or couldn't be removed + */ + function delete($key) { + if(defined('DISABLE_CACHE')) { + return false; + } + $key = strval($key); + + if(empty($key)) { + return false; + } + $_this =& Cache::getInstance(); + + if(!isset($_this->_Engine)) { + return false; + } + return $_this->_Engine->delete($key); + } +/** + * Delete all values from the cache + * + * @return boolean True if the cache was succesfully cleared, false otherwise + */ + function clear() { + if(defined('DISABLE_CACHE')) { + return false; + } + $_this =& Cache::getInstance(); + + if(!isset($_this->_Engine)) { + return false; + } + return $_this->_Engine->clear(); + } +/** + * Check if Cache has initialized a working storage engine * * @return boolean */ - function has() { - return is_array($this->data = $this->find("id='{$this->id}' AND expire>NOW()")); + function isInitialized() { + if(defined('DISABLE_CACHE')) { + return false; + } + $_this =& Cache::getInstance(); + return isset($_this->_Engine); } +} /** - * Appends $string to the for_caching property of the Cache object. + * Storage engine for CakePHP caching * - * @param string $string + * @package cake + * @subpackage cake.cake.libs */ - function append($string) { - $this->for_caching .= $string; +class CacheEngine extends Object { +/** + * Set up the cache engine + * + * Called automatically by the cache frontend + * + * @param array $params Associative array of parameters for the engine + * @return boolean True if the engine has been succesfully initialized, false if not + */ + function init($params) { } /** - * Clears the cache database table. + * Garbage collection * - * @return unknown + * Permanently remove all expired and deleted data + */ + function gc() { + } +/** + * Write a value in the cache + * + * @param string $key Identifier for the data + * @param mixed $value Data to be cached + * @param mixed $duration How long to cache the data, in seconds + * @return boolean True if the data was succesfully cached, false on failure + */ + function write($key, &$value, $duration = CACHE_DEFAULT_DURATION) { + trigger_error(sprintf(__('Method set() not implemented in %s', true), get_class($this)), E_USER_ERROR); + } +/** + * Read a value from the cache + * + * @param string $key Identifier for the data + * @return mixed The cached data, or false if the data doesn't exist, has expired, or if there was an error fetching it + */ + function read($key) { + trigger_error(sprintf(__('Method get() not implemented in %s', true), get_class($this)), E_USER_ERROR); + } +/** + * Delete a value from the cache + * + * @param string $key Identifier for the data + * @return boolean True if the value was succesfully deleted, false if it didn't exist or couldn't be removed + */ + function delete($key) { + } +/** + * Delete all values from the cache + * + * @return boolean True if the cache was succesfully cleared, false otherwise */ function clear() { - return $this->query("DELETE FROM {$this->useTable}"); } } ?> \ No newline at end of file diff --git a/cake/libs/cache/apc_engine.php b/cake/libs/cache/apc_engine.php new file mode 100644 index 000000000..12aa8361f --- /dev/null +++ b/cake/libs/cache/apc_engine.php @@ -0,0 +1,84 @@ + + * Copyright 2005-2007, Cake Software Foundation, Inc. + * 1785 E. Sahara Avenue, Suite 490-204 + * Las Vegas, Nevada 89104 + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @filesource + * @copyright Copyright 2005-2007, Cake Software Foundation, Inc. + * @link http://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project + * @package cake + * @subpackage cake.cake.libs.cache + * @since CakePHP(tm) v 1.2.0.4933 + * @version $Revision$ + * @modifiedby $LastChangedBy$ + * @lastmodified $Date$ + * @license http://www.opensource.org/licenses/mit-license.php The MIT License + */ +/** + * APC storage engine for cache + * + * @package cake + * @subpackage cake.cake.libs.cache + */ +class APCEngine extends CacheEngine { +/** + * Set up the cache engine + * + * Called automatically by the cache frontend + * + * @param array $params Associative array of parameters for the engine + * @return boolean True if the engine has been succesfully initialized, false if not + */ + function init(&$params) { + return function_exists('apc_cache_info'); + } +/** + * Write a value in the cache + * + * @param string $key Identifier for the data + * @param mixed $value Data to be cached + * @param int $duration How long to cache the data, in seconds + * @return boolean True if the data was succesfully cached, false on failure + */ + function write($key, &$value, $duration = CACHE_DEFAULT_DURATION) { + return apc_store($key, $value, $duration); + } +/** + * Read a value from the cache + * + * @param string $key Identifier for the data + * @return mixed The cached data, or false if the data doesn't exist, has expired, or if there was an error fetching it + */ + function read($key) { + return apc_fetch($key); + } +/** + * Delete a value from the cache + * + * @param string $key Identifier for the data + * @return boolean True if the value was succesfully deleted, false if it didn't exist or couldn't be removed + */ + function delete($key) { + return apc_delete($key); + } +/** + * Delete all values from the cache + * + * @return boolean True if the cache was succesfully cleared, false otherwise + */ + function clear() { + return apc_clear_cache('user'); + } +} +?> \ No newline at end of file diff --git a/cake/libs/cache/file_engine.php b/cake/libs/cache/file_engine.php new file mode 100644 index 000000000..61c0454ae --- /dev/null +++ b/cake/libs/cache/file_engine.php @@ -0,0 +1,249 @@ + + * Copyright 2005-2007, Cake Software Foundation, Inc. + * 1785 E. Sahara Avenue, Suite 490-204 + * Las Vegas, Nevada 89104 + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @filesource + * @copyright Copyright 2005-2007, Cake Software Foundation, Inc. + * @link http://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project + * @package cake + * @subpackage cake.cake.libs.cache + * @since CakePHP(tm) v 1.2.0.4933 + * @version $Revision$ + * @modifiedby $LastChangedBy$ + * @lastmodified $Date$ + * @license http://www.opensource.org/licenses/mit-license.php The MIT License + */ +/** + * File Storage engine for cache + * + * @todo use the File and Folder classes (if it's not a too big performance hit) + * @package cake + * @subpackage cake.cake.libs.cache + */ +class FileEngine extends CacheEngine { +/** + * Enter description here... + * + * @var unknown_type + */ + var $_dir = ''; +/** + * Enter description here... + * + * @var unknown_type + */ + var $_prefix = ''; +/** + * Enter description here... + * + * @var unknown_type + */ + var $_lock = false; +/** + * Set up the cache engine + * + * Called automatically by the cache frontend + * + * @param array $params Associative array of parameters for the engine + * @return boolean True if the engine has been succesfully initialized, false if not + */ + function init($params) { + $dir = CACHE; + $prefix = 'cake_'; + $lock = false; + extract($params); + $dir = trim($dir); + + if(strlen($dir) < 1) { + return false; + } + + if($dir{0} != DS) { + return false; + } + + if(!is_writable($dir)) { + return false; + } + + if($dir{strlen($dir)-1} != DS) { + $dir .= DS; + } + $this->_dir = $dir; + $this->_prefix = strval($prefix); + $this->_lock = $lock; + return true; + } +/** + * Garbage collection + * Permanently remove all expired and deleted data + * + * @return boolean + */ + function gc() { + return $this->clear(true); + } +/** + * Write a value in the cache + * + * @param string $key Identifier for the data + * @param mixed $value Data to be cached + * @param mixed $duration How long to cache the data, in seconds + * @return boolean True if the data was succesfully cached, false on failure + */ + function write($key, &$value, $duration = CACHE_DEFAULT_DURATION) { + $serialized = serialize($value); + + if(!$serialized) { + return false; + } + $expires = time() + $duration; + return $this->_writeCache($this->_getFilename($key), $serialized, $expires); + } +/** + * Get absolute filename for a key + * + * @param string $key The key + * @return string Absolute cache filename for the given key + */ + function _getFilename($key) { + return $this->_dir . $this->_prefix . $this->base64url_encode($key); + } +/** + * write serialized data to a file + * + * @param unknown_type $filename + * @param unknown_type $value + * @param unknown_type $expires + * @return unknown + */ + function _writeCache(&$filename, &$value, &$expires) { + $contents = $expires."\n".$value."\n"; + return ife(file_put_contents($filename, $contents, ife($this->_lock, LOCK_EX, 0)), true, false); + } +/** + * Read a value from the cache + * + * @param string $key Identifier for the data + * @return mixed The cached data, or false if the data doesn't exist, has expired, or if there was an error fetching it + */ + function read($key) { + $filename = $this->_getFilename($key); + + if(!is_file($filename) || !is_readable($filename)) { + return false; + } + $fp = fopen($filename, 'r'); + + if(!$fp) { + return false; + } + + if($this->_lock && !flock($fp, LOCK_SH)) { + return false; + } + $expires = fgets($fp, 11); + + if(intval($expires) < time()) { + fclose($fp); + unlink($filename); + return false; + } + $data = ''; + + while(!feof($fp)) { + $data .= fgets($fp, 4096); + } + $data = trim($data); + return unserialize($data); + } +/** + * Get the expiry time for a cache file + * + * @param unknown_type $filename + * @return unknown + */ + function _getExpiry($filename) { + $fp = fopen($filename, 'r'); + + if(!$fp) { + return false; + } + + if($this->_lock && !flock($fp, LOCK_SH)) { + return false; + } + $expires = intval(fgets($fp, 11)); + fclose($fp); + return $expires; + } +/** + * Delete a value from the cache + * + * @param string $key Identifier for the data + * @return boolean True if the value was succesfully deleted, false if it didn't exist or couldn't be removed + */ + function delete($key) { + $filename = $this->_getFilename($key); + return unlink($filename); + } +/** + * Delete all values from the cache + * + * @param boolean $checkExpiry Optional - only delete expired cache items + * @return boolean True if the cache was succesfully cleared, false otherwise + */ + function clear($checkExpiry = false) { + $dir = dir($this->_dir); + + if ($checkExpiry) { + $now = time(); + $threshold = $now - 86400; + } + + while(($entry = $dir->read()) !== false) { + if(strpos($entry, $this->_prefix) !== 0) { + continue; + } + $filename = $this->_dir.$entry; + + if($checkExpiry) { + $mtime = filemtime($filename); + + if($mtime === false || $mtime > $threshold) { + continue; + } + $expires = $this->_getExpiry($filename); + + if($expires > $now) { + continue; + } + } + unlink($filename); + } + $dir->close(); + return true; + } +/** + * Get a filename-safe version of a string + * + * @param string $str String to encode + * @return string Encoded version of the string + */ + function base64url_encode($str) { + return strtr(base64_encode($str), '+/', '-_'); + } +} +?> \ No newline at end of file diff --git a/cake/libs/cache/memcache_engine.php b/cake/libs/cache/memcache_engine.php new file mode 100644 index 000000000..eb5a2d477 --- /dev/null +++ b/cake/libs/cache/memcache_engine.php @@ -0,0 +1,111 @@ + + * Copyright 2005-2007, Cake Software Foundation, Inc. + * 1785 E. Sahara Avenue, Suite 490-204 + * Las Vegas, Nevada 89104 + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @filesource + * @copyright Copyright 2005-2007, Cake Software Foundation, Inc. + * @link http://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project + * @package cake + * @subpackage cake.cake.libs.cache + * @since CakePHP(tm) v 1.2.0.4933 + * @version $Revision$ + * @modifiedby $LastChangedBy$ + * @lastmodified $Date$ + * @license http://www.opensource.org/licenses/mit-license.php The MIT License + */ +/** + * Memcache storage engine for cache + * + * @package cake + * @subpackage cake.cake.libs.cache + */ +class MemcacheEngine extends CacheEngine { + var $__Memcache = null; + var $_compress = 0; +/** + * Set up the cache engine + * + * Called automatically by the cache frontend + * + * @param array $params Associative array of parameters for the engine + * @return boolean True if the engine has been succesfully initialized, false if not + */ + function init(&$params) { + $servers = array('127.0.0.1'); + $compress = false; + extract($params); + + if($compress) { + $this->_compress = MEMCACHE_COMPRESSED; + } else { + $this->_compress = 0; + } + + if(!is_array($servers)) { + $servers = array($servers); + } + $this->__Memcache =& new Memcache(); + $connected = false; + + foreach($servers as $server) { + $parts = explode(':', $server); + $host = $parts[0]; + $port = isset($parts[1]) ? $parts[1] : 11211; + + if($this->__Memcache->addServer($host, $port)) { + $connected = true; + } + } + return $connected; + } +/** + * Write a value in the cache + * + * @param string $key Identifier for the data + * @param mixed $value Data to be cached + * @param int $duration How long to cache the data, in seconds + * @return boolean True if the data was succesfully cached, false on failure + */ + function write($key, &$value, $duration = CACHE_DEFAULT_DURATION) { + return $this->__Memcache->set($key, $value, $this->_compress, $duration); + } +/** + * Read a value from the cache + * + * @param string $key Identifier for the data + * @return mixed The cached data, or false if the data doesn't exist, has expired, or if there was an error fetching it + */ + function read($key) { + return $this->__Memcache->get($key); + } +/** + * Delete a value from the cache + * + * @param string $key Identifier for the data + * @return boolean True if the value was succesfully deleted, false if it didn't exist or couldn't be removed + */ + function delete($key) { + return $this->__Memcache->delete($key); + } +/** + * Delete all values from the cache + * + * @return boolean True if the cache was succesfully cleared, false otherwise + */ + function clear() { + return $this->__Memcache->flush(); + } +} +?> \ No newline at end of file diff --git a/cake/libs/cache/model_engine.php b/cake/libs/cache/model_engine.php new file mode 100644 index 000000000..fe619349f --- /dev/null +++ b/cake/libs/cache/model_engine.php @@ -0,0 +1,121 @@ + + * Copyright 2005-2007, Cake Software Foundation, Inc. + * 1785 E. Sahara Avenue, Suite 490-204 + * Las Vegas, Nevada 89104 + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @filesource + * @copyright Copyright 2005-2007, Cake Software Foundation, Inc. + * @link http://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project + * @package cake + * @subpackage cake.cake.libs.cache + * @since CakePHP(tm) v 1.2.0.4933 + * @version $Revision$ + * @modifiedby $LastChangedBy$ + * @lastmodified $Date$ + * @license http://www.opensource.org/licenses/mit-license.php The MIT License + */ +/** + * Database Storage engine for cache + * + * @todo Not Implemented + * @package cake + * @subpackage cake.cake.libs.cache + */ +class ModelEngine extends CacheEngine { + var $_Model = null; + var $_dataField = ''; + var $_expiryField = ''; +/** + * Set up the cache engine + * + * Called automatically by the cache frontend + * + * @todo does not work will return false + * @param array $params Associative array of parameters for the engine + * @return boolean True if the engine has been succesfully initialized, false if not + */ + function init($params) { + return false; + + $modelName = 'DbCache'; + $dataField = 'value'; + $expiryField = 'expires'; + extract($params); + + if(!class_exists($modelName) && !loadModel($modelName)) { + return false; + } + $this->_Model = new $modelName; + } +/** + * Garbage collection + * + * Permanently remove all expired and deleted data + */ + function gc() { + return $this->_Model->deleteAll(array($this->_expiryField => '<= '.time())); + } +/** + * Write a value in the cache + * + * @param string $key Identifier for the data + * @param mixed $value Data to be cached + * @param mixed $duration How long to cache the data, in seconds + * @return boolean True if the data was succesfully cached, false on failure + */ + function write($key, &$value, $duration = CACHE_DEFAULT_DURATION) { + $serialized = serialize($value); + + if(!$serialized) { + return false; + } + $data = array($this->_Model->name => array( + $this->_dataField => $serialized, + $this->_expiryField => time() + $duration)); + + $oldId = $this->_Model->id; + $this->_Model->id = $key; + $res = $this->_Model->save($data); + $this->_Model->id = $oldId; + return $res; + } +/** + * Read a value from the cache + * + * @param string $key Identifier for the data + * @return mixed The cached data, or false if the data doesn't exist, has expired, or if there was an error fetching it + */ + function read($key) { + $val = $this->_Model->field($this->_expiryField, array($this->_Model->primaryKey => $key, $this->_expiryField => '> '.time())); + return ife($val, unserialize($val), false); + } +/** + * Delete a value from the cache + * + * @param string $key Identifier for the data + * @return boolean True if the value was succesfully deleted, false if it didn't exist or couldn't be removed + */ + function delete($key) { + return $this->_Model->del($key); + } +/** + * Delete all values from the cache + * + * @return boolean True if the cache was succesfully cleared, false otherwise + */ + function clear() { + return $this->_Model->deleteAll(null); + } +} +?> \ No newline at end of file