. ======================================================================*/ /** * FIXME: needs documentation */ class KjwCache { var $_cachePath = null; var $_cacheFile = null; var $_enabled = false; var $_expire = null; function KjwCache($cachePath = 'cache') { $this->_cachePath = $cachePath; } function expire($seconds) { $this->_expire = $seconds; } function start() { // Check if we're in a session by checking SESSID, // if we're in a session, do not cache anything.. // echo ""; if (!isset($_REQUEST[session_name()])) { $this->_cacheFile = $this->_cachePath . '/' . md5($_SERVER['REQUEST_URI']) . '.cache'; // We have a file that is recent enough, output it and die. if (@file_exists($this->_cacheFile) && ($this->_expire === null || filemtime($this->_cacheFile) + $this->_expire > time())) { // Send last-modified header('Last-Modified: ' . gmdate('D, d M Y H:i:s T', filemtime($this->_cacheFile))); if ($this->_expire !== null) header('Expires: ' . gmdate('D, d M Y H:i:s T', filemtime($this->_cacheFile) + $this->_expire)); // Enable 304 not modified. if (function_exists('apache_request_headers')) { $headers = apache_request_headers(); if (isset($headers['If-Modified-Since']) && filemtime($this->_cacheFile) <= strtotime($headers['If-Modified-Since'])) { header("HTTP/1.0 304 Not Modified"); exit; } } // Write file for those that didn't have it already. readfile($this->_cacheFile); exit; } // Send expires header if we have it set. if ($this->_expire !== null) header('Expires: ' . gmdate('D, d M Y H:i:s T', time() + $this->_expire)); // Start output buffering so we can store the page. ob_start(); $this->_enabled = true; } else { // When we use sessions, we're doing dynamic data, // and we won't be doing caching. header('Cache-Control: no-cache, must-revalidate'); // HTTP/1.1 header('Last-Modified: ' . gmdate('D, d M Y H:i:s T', time())); header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); // Date in the past } } /** * "delete" .cache files.. call saveCache first if you plan to undo.. * @return amount of files deleted */ function setDirty() { $n = 0; $dp = opendir($this->_cachePath); while (($entry = readdir($dp)) !== false) if (substr($entry, -6) == '.cache') if (unlink($this->_cachePath . '/' . $entry)) ++$n; closedir($dp); return $n; } /** * store cache files by copying the .cache to .cache.bak. * removes old .bak files first, so we know this cache contains only newly cached items. * @return amount of files stored/pushed */ function saveCache() { $n = 0; $dp = opendir($this->_cachePath); while (($entry = readdir($dp)) !== false) if (substr($entry, -10) == '.cache.bak') unlink($this->_cachePath . '/' . $entry); rewinddir($dp); while (($entry = readdir($dp)) !== false) if (substr($entry, -6) == '.cache') if (copy($this->_cachePath . '/' . $entry, $this->_cachePath . '/' . $entry . '.bak')) ++$n; closedir($dp); return $n; } /** * deletes current .cache files. copies .cache.bak to .cache. * @return amount of files "restored" */ function loadCache() { $n = 0; $dp = opendir($this->_cachePath); while (($entry = readdir($dp)) !== false) if (substr($entry, -6) == '.cache') unlink($this->_cachePath . '/' . $entry); rewinddir($dp); while (($entry = readdir($dp)) !== false) if (substr($entry, -10) == '.cache.bak') if (copy($this->_cachePath . '/' . $entry, $this->_cachePath . '/' . substr($entry, 0, -4))) ++$n; closedir($dp); return $n; } function destroy() { if ($this->_enabled) { echo ""; if (($fp = @fopen($this->_cacheFile, 'w')) !== false) { $success = @fwrite($fp, ($towrite = ob_get_contents())) === strlen($towrite); @fclose($fp); if ($success === false) unlink($this->_cacheFile); } ob_end_flush(); } } } ?>