123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259 |
- <?php
- /**
- * Cache strategy using files
- *
- * @author Christopher Han <xiphux@gmail.com>
- * @copyright (c) 2012 Christopher Han
- * @package GitPHP
- * @subpackage Cache
- */
- class GitPHP_Cache_File implements GitPHP_CacheStrategy_Interface
- {
- /**
- * Gzipped cache
- *
- * @var int
- */
- const CacheTypeGzip = 1;
- /**
- * Igbinary cache
- *
- * @var int
- */
- const CacheTypeIgbinary = 2;
- /**
- * Cache file directory
- *
- * @var string
- */
- protected $cacheDir;
- /**
- * Compression threshold
- *
- * @var int
- */
- protected $compressThreshold = 0;
- /**
- * Enable igbinary
- *
- * @var boolean
- */
- protected $igbinary = false;
- /**
- * Constructor
- *
- * @param string $cacheDir cache dir
- * @param int $compressThreshold threshold to start compressing data at
- * @param boolean $igbinary whether to use igbinary, null to autodetect
- */
- public function __construct($cacheDir, $compressThreshold = 0, $igbinary = null)
- {
- if (file_exists($cacheDir)) {
- if (!is_dir($cacheDir)) {
- throw new Exception($cacheDir . ' exists but is not a directory');
- } else if (!is_writable($cacheDir)) {
- throw new Exception($cacheDir . ' is not writable');
- }
- } else {
- if (!mkdir($cacheDir, 0777))
- throw new Exception($cacheDir . ' could not be created');
- chmod($cacheDir, 0777);
- }
- $this->cacheDir = GitPHP_Util::AddSlash($cacheDir, true);
- if (!(is_int($compressThreshold) && ($compressThreshold >= 0))) {
- throw new Exception('Invalid compression threshold');
- }
- $this->compressThreshold = $compressThreshold;
- if ($igbinary === null) {
- $this->igbinary = function_exists('igbinary_serialize');
- } else if ($igbinary) {
- if (!function_exists('igbinary_serialize'))
- throw new Exception('Igbinary is not present');
- $this->igbinary = $igbinary;
- }
- }
- /**
- * Gets an item from the cache
- *
- * @param string $key cache key
- * @return mixed cached object or false if not found
- */
- public function Get($key)
- {
- if (empty($key))
- return false;
- $return = $this->Load($key);
- if ($return === false)
- return false;
- list($cachetype, $data) = $return;
- if ($cachetype == GitPHP_Cache_File::CacheTypeIgbinary) {
- $data = igbinary_unserialize($data);
- } else if ($cachetype == GitPHP_Cache_File::CacheTypeGzip) {
- $data = unserialize(gzuncompress($data));
- } else {
- $data = unserialize($data);
- }
- return $data;
- }
- /**
- * Sets an item into the cache
- *
- * @param string $key cache key
- * @param mixed $value object to cache
- * @param int $lifetime cached object lifetime
- */
- public function Set($key, $value, $lifetime)
- {
- if (empty($key) || empty($value))
- return;
- $expire = '';
- if ($lifetime >= 0)
- $expire = time() + $lifetime;
- $this->Save($key, $value, $expire);
- }
- /**
- * Check if an item exists
- *
- * @param string $key cache key
- * @return boolean true if exists
- */
- public function Exists($key)
- {
- return ($this->Load($key) !== false);
- }
- /**
- * Delete an item from the cache
- *
- * @param string $key cache key
- */
- public function Delete($key)
- {
- if (empty($key))
- return;
- $file = $this->cacheDir . $this->KeyToFile($key);
- if (file_exists($file))
- unlink($file);
- }
- /**
- * Clear the cache
- */
- public function Clear()
- {
- if ($dh = opendir($this->cacheDir)) {
- while (($file = readdir($dh)) !== false) {
- if (($file == '.') || ($file == '..'))
- continue;
- if (file_exists($this->cacheDir . $file))
- unlink($this->cacheDir . $file);
- }
- closedir($dh);
- }
- }
- /**
- * Load a key's serialized data
- *
- * @param string $key cache key
- */
- private function Load($key)
- {
- if (empty($key))
- return false;
- $file = $this->cacheDir . $this->KeyToFile($key);
- if (!is_readable($file))
- return false;
- $contents = file_get_contents($file);
- if (empty($contents)) {
- unlink($file);
- return false;
- }
- $flags = strtok($contents, "\n");
- $expire = strtok($flags, "|");
- $cachetype = strtok("|");
- if (!empty($expire) && ($expire < time())) {
- unlink($file);
- return false;
- }
- $data = substr($contents, strlen($flags) + 1);
- if (empty($data)) {
- unlink($file);
- return false;
- }
- if (($cachetype == GitPHP_Cache_File::CacheTypeIgbinary) && (!$this->igbinary)) {
- unlink($file);
- return false;
- }
- return array($cachetype, $data);
- }
- /**
- * Save a key's data
- *
- * @param string $key cache key
- * @param mixed $data data
- * @param int $expire expiration instant
- */
- private function Save($key, $data, $expire = '')
- {
- $flags = $expire;
- if ($this->igbinary) {
- $data = igbinary_serialize($data);
- $flags .= '|' . GitPHP_Cache_File::CacheTypeIgbinary;
- } else {
- $data = serialize($data);
- if (($this->compressThreshold > 0) && (strlen($data) > $this->compressThreshold)) {
- $data = gzcompress($data);
- $flags .= '|' . GitPHP_Cache_File::CacheTypeGzip;
- }
- }
- file_put_contents($this->cacheDir . $this->KeyToFile($key), $flags . "\n" . $data);
- }
- /**
- * Converts a key to a filename
- *
- * @param string $key key
- * @return string filename
- */
- private function KeyToFile($key)
- {
- if (empty($key))
- return '';
- $key = preg_replace('/[^\w\|]+/', '_', $key);
- $key = preg_replace('/\|/', '^', $key);
- return $key . '.dat';
- }
- }
|