Blame | Last modification | View Log | RSS feed
<?php if (!defined('BASEPATH')) exit('No direct script access allowed');class Cache{private $_ci;private $_path;private $_contents;private $_filename;private $_expires;private $_default_expires;private $_created;private $_dependencies;/*** Constructor - Initializes and references CI*/function __construct(){log_message('debug', "Cache Class Initialized.");$this->_ci =& get_instance();$this->_reset();$this->_ci->load->config('cache');$this->_path = $this->_ci->config->item('cache_dir');$this->_default_expires = $this->_ci->config->item('cache_default_expires');if ( ! is_dir($this->_path)){show_error("Cache Path not found: $this->_path");}}/*** Initialize Cache object to empty** @access private* @return void*/private function _reset(){$this->_contents = NULL;$this->_filename = NULL;$this->_expires = NULL;$this->_created = NULL;$this->_dependencies = array();}/*** Call a library's cached result or create new cache** @access public* @param string* @return array*/public function library($library, $method, $arguments = array(), $expires = NULL){if ( ! class_exists(ucfirst($library))){$this->_ci->load->library($library);}return $this->_call($library, $method, $arguments, $expires);}/*** Call a model's cached result or create new cache** @access public* @return array*/public function model($model, $method, $arguments = array(), $expires = NULL){if ( ! class_exists(ucfirst($model))){$this->_ci->load->model($model);}return $this->_call($model, $method, $arguments, $expires);}// Depreciated, use model() or library()private function _call($property, $method, $arguments = array(), $expires = NULL){$this->_ci->load->helper('security');if ( ! is_array($arguments)){$arguments = (array) $arguments;}// Clean given arguments to a 0-index array$arguments = array_values($arguments);$cache_file = $property.DIRECTORY_SEPARATOR.do_hash($method.serialize($arguments), 'sha1');// See if we have this cached or delete if $expires is negativeif($expires >= 0){$cached_response = $this->get($cache_file);}else{$this->delete($cache_file);return;}// Not FALSE? Return itif($cached_response !== FALSE && $cached_response !== NULL){return $cached_response;}else{// Call the model or library with the method provided and the same arguments$new_response = call_user_func_array(array($this->_ci->$property, $method), $arguments);$this->write($new_response, $cache_file, $expires);return $new_response;}}/*** Helper functions for the dependencies property*/function set_dependencies($dependencies){if (is_array($dependencies)){$this->_dependencies = $dependencies;}else{$this->_dependencies = array($dependencies);}return $this;}function add_dependencies($dependencies){if (is_array($dependencies)){$this->_dependencies = array_merge($this->_dependencies, $dependencies);}else{$this->_dependencies[] = $dependencies;}return $this;}function get_dependencies() { return $this->_dependencies; }/*** Helper function to get the cache creation date*/function get_created($created) { return $this->_created; }/*** Retrieve Cache File** @access public* @param string* @param boolean* @return mixed*/function get($filename = NULL, $use_expires = true){// Check if cache was requested with the function or uses this object//print_r($filename);if ($filename !== NULL){$this->_reset();$this->_filename = $filename;}// Check directory permissionsif ( ! is_dir($this->_path) OR ! is_really_writable($this->_path)){return FALSE;}// Build the file path.$filepath = $this->_path.$this->_filename.'.cache';// Check if the cache exists, if not return FALSEif ( ! @file_exists($filepath)){return FALSE;}// Check if the cache can be opened, if not return FALSEif ( ! $fp = @fopen($filepath, FOPEN_READ)){return FALSE;}// Lock the cacheflock($fp, LOCK_SH);// If the file contains data return it, otherwise return NULLif (filesize($filepath) > 0){//echo 'file size'.filesize($filepath);$this->_contents = unserialize(fread($fp, filesize($filepath)));//print_r($this->_contents);}else{//echo 'inside else';$this->_contents = NULL;}// Unlock the cache and close the fileflock($fp, LOCK_UN);fclose($fp);// Check cache expiration, delete and return FALSE when expiredif ($use_expires && ! empty($this->_contents['__cache_expires']) && $this->_contents['__cache_expires'] < time()){//echo 'inside if';//$this->delete($filename);return FALSE;}// Check Cache dependenciesif(isset($this->_contents['__cache_dependencies'])){//echo 'inside if';foreach ($this->_contents['__cache_dependencies'] as $dep){$cache_created = filemtime($this->_path.$this->_filename.'.cache');// If dependency doesn't exist or is newer than this cache, delete and return FALSEif (! file_exists($this->_path.$dep.'.cache') or filemtime($this->_path.$dep.'.cache') > $cache_created){//echo 'file deleted';$this->delete($filename);return FALSE;}}}// Instantiate the object variables$this->_expires = isset($this->_contents['__cache_expires']) ? $this->_contents['__cache_expires'] : NULL;$this->_dependencies = isset($this->_contents['__cache_dependencies']) ? $this->_contents['__cache_dependencies'] : NULL;$this->_created = isset($this->_contents['__cache_created']) ? $this->_contents['__cache_created'] : NULL;// Cleanup the meta variables from the contents$this->_contents = @$this->_contents['__cache_contents'];log_message('debug', "Cache retrieved: ".$filename);//print_r($this->_contents);//echo "<br/>----------------------------------------cache file ends--------------------------------------<br/>";// Return the cachelog_message('debug', "Cache retrieved: ".$filename);return $this->_contents;}/*** Write Cache File** @access public* @param mixed* @param string* @param int* @param array* @return void*/function write($contents = NULL, $filename = NULL, $expires = NULL, $dependencies = array()){// Check if cache was passed with the function or uses this objectif ($contents !== NULL){$this->_reset();$this->_contents = $contents;$this->_filename = $filename;$this->_expires = $expires;$this->_dependencies = $dependencies;}// Put the contents in an array so additional meta variables// can be easily removed from the output$this->_contents = array('__cache_contents' => $this->_contents);// Check directory permissionsif ( ! is_dir($this->_path) OR ! is_really_writable($this->_path)){return;}// check if filename contains dirs$subdirs = explode(DIRECTORY_SEPARATOR, $this->_filename);if (count($subdirs) > 1){array_pop($subdirs);$test_path = $this->_path.implode(DIRECTORY_SEPARATOR, $subdirs);// check if specified subdir existsif ( ! @file_exists($test_path)){// create non existing dirs, asumes PHP5if ( ! @mkdir($test_path, DIR_WRITE_MODE, TRUE)) return FALSE;}}// Set the path to the cachefile which is to be created$cache_path = $this->_path.$this->_filename.'.cache';// Open the file and log if an error occuresif ( ! $fp = @fopen($cache_path, FOPEN_WRITE_CREATE_DESTRUCTIVE)){log_message('error', "Unable to write Cache file: ".$cache_path);return;}// Meta variables$this->_contents['__cache_created'] = time();$this->_contents['__cache_dependencies'] = $this->_dependencies;// Add expires variable if its set...if (! empty($this->_expires)){$this->_contents['__cache_expires'] = $this->_expires + time();}// ...or add default expiration if its setelseif (! empty($this->_default_expires) ){$this->_contents['__cache_expires'] = $this->_default_expires + time();}// Lock the file before writing or log an error if it failesif (flock($fp, LOCK_EX)){fwrite($fp, serialize($this->_contents));flock($fp, LOCK_UN);}else{log_message('error', "Cache was unable to secure a file lock for file at: ".$cache_path);return;}fclose($fp);@chmod($cache_path, DIR_WRITE_MODE);// Log successlog_message('debug', "Cache file written: ".$cache_path);// Reset values$this->_reset();}/*** Delete Cache File** @access public* @param string* @return void*/function delete($filename = NULL){if ($filename !== NULL) $this->_filename = $filename;$file_path = $this->_path.$this->_filename.'.cache';if (file_exists($file_path)) unlink($file_path);// Reset values$this->_reset();}/*** Delete a group of cached files** Allows you to pass a group to delete cache. Example:** <code>* $this->cache->write($data, 'nav_title');* $this->cache->write($links, 'nav_links');* $this->cache->delete_group('nav_');* </code>** @param string $group* @return void*/public function delete_group($group = null){if ($group === null){return FALSE;}$this->_ci->load->helper('directory');$map = directory_map($this->_path, TRUE);foreach ($map AS $file){if (strpos($file, $group) !== FALSE){unlink($this->_path.$file);}}// Reset values$this->_reset();}/*** Delete Full Cache or Cache subdir** @access public* @param string* @return void*/function delete_all($dirname = ''){if (empty($this->_path)){return FALSE;}$this->_ci->load->helper('file');if (file_exists($this->_path.$dirname)) delete_files($this->_path.$dirname, TRUE);// Reset values$this->_reset();}}/* End of file Cache.php *//* Location: ./application/libraries/Cache.php */