1 <?php defined('SYSPATH') OR die('No direct access allowed.');
3 * File-based Cache driver.
5 * $Id: File.php 4046 2009-03-05 19:23:29Z Shadowhand $
9 * @copyright (c) 2007-2008 Kohana Team
10 * @license http://kohanaphp.com/license.html
12 class Cache_File_Driver implements Cache_Driver {
14 protected $directory = '';
17 * Tests that the storage location is a directory and is writable.
19 public function __construct($directory)
21 // Find the real path to the directory
22 $directory = str_replace('\\', '/', realpath($directory)).'/';
24 // Make sure the cache directory is writable
25 if ( ! is_dir($directory) OR ! is_writable($directory))
26 throw new Kohana_Exception('cache.unwritable', $directory);
29 $this->directory = $directory;
33 * Finds an array of files matching the given id or tag.
35 * @param string cache id or tag
36 * @param bool search for tags
37 * @return array of filenames matching the id or tag
39 public function exists($id, $tag = FALSE)
44 return glob($this->directory.'*~*~*');
46 elseif ($tag === TRUE)
48 // Find all the files that have the tag name
49 $paths = glob($this->directory.'*~*'.$id.'*~*');
51 // Find all tags matching the given tag
53 foreach ($paths as $path)
56 $tags = explode('~', basename($path));
59 if (count($tags) !== 3 OR empty($tags[1]))
62 // Split the tags by plus signs, used to separate tags
63 $tags = explode('+', $tags[1]);
65 if (in_array($tag, $tags))
67 // Add the file to the array, it has the requested tag
76 // Find the file matching the given id
77 return glob($this->directory.$id.'~*');
82 * Sets a cache item to the given data, tags, and lifetime.
84 * @param string cache id to set
85 * @param string data in the cache
86 * @param array cache tags
87 * @param integer lifetime
90 public function set($id, $data, array $tags = NULL, $lifetime)
92 // Remove old cache files
95 // Cache File driver expects unix timestamp
103 // Convert the tags into a string list
104 $tags = implode('+', $tags);
107 // Write out a serialized cache
108 return (bool) file_put_contents($this->directory.$id.'~'.$tags.'~'.$lifetime, serialize($data));
112 * Finds an array of ids for a given tag.
114 * @param string tag name
115 * @return array of ids that match the tag
117 public function find($tag)
119 // An array will always be returned
122 if ($paths = $this->exists($tag, TRUE))
124 // Length of directory name
125 $offset = strlen($this->directory);
127 // Find all the files with the given tag
128 foreach ($paths as $path)
130 // Get the id from the filename
131 list($id, $junk) = explode('~', basename($path), 2);
133 if (($data = $this->get($id)) !== FALSE)
135 // Add the result to the array
136 $result[$id] = $data;
145 * Fetches a cache item. This will delete the item if it is expired or if
146 * the hash does not match the stored hash.
148 * @param string cache id
151 public function get($id)
153 if ($file = $this->exists($id))
155 // Use the first file
156 $file = current($file);
158 // Validate that the cache has not expired
159 if ($this->expired($file))
161 // Remove this cache, it has expired
166 // Turn off errors while reading the file
167 $ER = error_reporting(0);
169 if (($data = file_get_contents($file)) !== FALSE)
171 // Unserialize the data
172 $data = unserialize($data);
180 // Turn errors back on
181 error_reporting($ER);
185 // Return NULL if there is no data
186 return isset($data) ? $data : NULL;
190 * Deletes a cache item by id or tag
192 * @param string cache id or tag, or TRUE for "all items"
193 * @param boolean use tags
196 public function delete($id, $tag = FALSE)
198 $files = $this->exists($id, $tag);
203 // Disable all error reporting while deleting
204 $ER = error_reporting(0);
206 foreach ($files as $file)
208 // Remove the cache file
209 if ( ! unlink($file))
210 Kohana::log('error', 'Cache: Unable to delete cache file: '.$file);
213 // Turn on error reporting again
214 error_reporting($ER);
220 * Deletes all cache files that are older than the current time.
224 public function delete_expired()
226 if ($files = $this->exists(TRUE))
228 // Disable all error reporting while deleting
229 $ER = error_reporting(0);
231 foreach ($files as $file)
233 if ($this->expired($file))
235 // The cache file has already expired, delete it
236 if ( ! unlink($file))
237 Kohana::log('error', 'Cache: Unable to delete cache file: '.$file);
241 // Turn on error reporting again
242 error_reporting($ER);
247 * Check if a cache file has expired by filename.
249 * @param string filename
252 protected function expired($file)
254 // Get the expiration time
255 $expires = (int) substr($file, strrpos($file, '~') + 1);
257 // Expirations of 0 are "never expire"
258 return ($expires !== 0 AND $expires <= time());
261 } // End Cache File Driver