| <?php
/***********************************
	gimmecache.php 
	@ 2002 Sam Yapp www.samscripts.com
	You are free to use modify and do whatever you like with this script.
	Usage:
	***	To cache a whole page, ***
	near the top of your script, 
	include_once("gimmecache.php");
	$cache = new gimmecache("path/to/store/cached/files/in", 60);	// refresh cache after 60 seconds
	$cache->cache("a_unique_name_identifying_this_cache");
	*** To cache part of a script, ie. big database query ***
	include_once("gimmecache.php");
	$cache = new gimmecache("path/to/store/cached/files/in", date("Y-m-d 00:00:00"));	// refresh cache once a day
	if( $cache->cache("a_unique_name_identifying_this_cache")){		// cache() returns true if the code needs to be refreshed
		// all the code you want to cache goes here, eg.
		$result = mysql_query($really_big_and_slow_query);
		while( list( $f1, $f2, $f3, $f4) = mysql_fetch_row($result)){
			echo "Field1 $f1, Field2 $f2, Field3 $f3, Field4 $f4<br>\n";
		}
		$cache->stop();	// finish caching this bit of code
	}
	
	// The sql query and output of the data will only occur the first time each day that the script is requested.
	// the output is stored in the cache and is output to the browser as html which for a big query will be faster.
	*** To remove a cached file - sometimes you may need to refresh a script the next time it is called, but not this time ***
	$cache->expirecache($cache_identifier);
	*** to replace one or more strings in the cached output before outputting it to the web browser
	$cache->cache($cachepath, $expirytime, $search = array("firstvalue", "secondvalue"), array("firstreplacement", "secondreplacement"));
	// error checking: the variable $_THE_CACHE_ERRORS is an array containing text descriptions of any errors. It will be empty if no errors occur
************************************/
// you can change these:
$_DEFAULT_CACHE_PATH = "./cached";	// path to store cached files in - must be php writable
$_USE_DATABASE = "";		// enter the database table name here to use db instead of files - see below
/*******************************
if you want to cache to a mysql database, enter the name of the table
in $_USE_DATABASE above.
the database should have the following structure:
CREATE TABLE cached (
  id varchar(32) NOT NULL default '',
  updated datetime NOT NULL default '0000-00-00 00:00:00',
  file text NOT NULL,
  PRIMARY KEY  (id)
)
at present, this class simply calls mysql_query($sql) - ie it assumes that you
have already opened a database connection with mysql_connect and mysql_select_db
elsewhere in the script.
if $_USE_DATABASE = "" then files will be used for caching. (quicker, in most cases ? )
******************************/
// do NOT change the names of these - unless you change them throughout the script
$_THE_CACHE_FILENAME = array();	// global variable holds filenames of cached files
$_THE_CACHE_ERRORS = array();		// store any error messages generated
$_THE_CACHE_EXISTS = array();
$_THE_CACHE_REPLACE = array();
class gimmecache{
	var $cachepath;
	var $expireafter;
	var $expiretype;
	var $filename;
	var $connection;
	var $usedb;
	function setexpiry($expireafter = 60){		// sets either the number of seconds before re-caching or a date-string after which to expire the cache
		$this->expireafter = $expireafter;
		if( is_int($expireafter) ){
			$this->expiretype = "sec";
		}else{
			$this->expiretype = "date";
		}
	}
	function gimmecache( $cachepath = "", $expireafter = 60, $connection = 0){	// cachepath is where cached files will be stored
		global $_DEFAULT_CACHE_PATH;
		global $_USE_DATABASE;
		if( $_USE_DATABASE != "" ){
			$this->usedb = $_USE_DATABASE;
			$this->connection = $connection;
		}else{
			$this->usedb = false;
		}
		$this->cachepath = ($cachepath == "" ? $_DEFAULT_CACHE_PATH : $cachepath);
		$this->setexpiry($expireafter);
		$this->filename = "";
	}
	function expirecache($cachename){
			$filename = $this->cachepath."/".md5($cachename).".cache";
			@unlink($filename);
	}
	function cache($cachename, $expireafter = "", $search = array(), $replace=array()){
		$this->cachename = $cachename;
		if( $expireafter == "" ) $expireafter = $this->expireafter;
		$this->setexpiry($expireafter);
		$update = 0;
		if( $this->usedb ){
			$filename = md5($cachename);
			$res = @mysql_query("SELECT updated, file FROM ".$this->usedb." WHERE id='".$filename."'")or die(mysql_error());
			if( mysql_num_rows($res) == 0 ){
				$update = 1;
				$exist = 0;
			}else{
				list( $updated, $f) = mysql_fetch_row($res);
				$updated = strtotime($updated);
				$exist = 1;
			}
		}else{
			$filename = $this->cachepath."/".md5($cachename).".cache";
			if( !file_exists($filename) ){
				$update = 1;
				$exist = 0;
			}else{
				$exist = 1;
				$updated = filemtime($filename);
			}
		}
		if( $exist ==0 || $updated < ($this->expiretype == "sec" ? time() - $this->expireafter : strtotime($this->expireafter))){
			$update = 1;
		}
		if( $update){ 
			ob_start( "_the_cache_capture");
			global $_THE_CACHE_FILENAME;
			global $_THE_CACHE_EXISTS;
			global $_THE_CACHE_REPLACE;
			$_THE_CACHE_FILENAME[] = $filename;
			$_THE_CACHE_EXISTS[] = $exist;
			$countcache = count( $_THE_CACHE_REPLACE);
			$_THE_CACHE_REPLACE[$countcache]["search"] = $search;
			$_THE_CACHE_REPLACE[$countcache]["replace"] = $replace;
			return true;
		}else{
			global $_THE_CACHED_ERRORS;
			if( $this->usedb ){
				echo str_replace($search, $replace, $f);
			}else{
				if( count($search) == 0 ){
					if( !@readfile( $filename)) $_THE_CACHE_ERRORS = "readfile failed for ".$this->filename;
				}else{
					$f = join("", file($filename));
					echo str_replace($search, $replace, $f);
				}
			}
			return false;
		}
	}
	function stop($returnbuffer = false){		// if returnbuffer is true, returns the contents of the cache to the calling script
		if( $returnbuffer ){
			$ret = ob_get_contents();
		}else{
			$ret = "";
		}
		ob_end_flush();
		return $ret;
	}
}
function _the_cache_capture(&$output){
	global $_THE_CACHE_FILENAME;
	global $_THE_CACHE_ERRORS;
	global $_THE_CACHE_EXISTS;
	global $_THE_CACHE_REPLACE;
	global $_USE_DATABASE;
	$numcaches = count($_THE_CACHE_FILENAME);
	if( $numcaches != 0 ){
		$filename = $_THE_CACHE_FILENAME[$numcaches-1];
		if( $_USE_DATABASE != "" ){
			if( $_THE_CACHE_EXISTS[$numcaches-1] == 1 ){
				$sql = "UPDATE cached SET updated=now(), file='".addslashes($output)."' WHERE id='".$filename."'";
			}else{
				$sql = "INSERT INTO cached (id, updated, file) VALUES ('".$filename."', now(), '".addslashes($output)."')";
			}
			@mysql_query($sql);
		}else{
			$fo = @fopen($filename, "w");
			if( $fo ){
				if( !@fwrite( $fo, $output)) $_THE_CACHE_ERRORS[] = "Error writing to file $filename.";
				@fclose( fo);
			}else{
				$_THE_CACHE_ERRORS[] = "Failed opening file $filename for output.";
			}
		}
		array_pop($_THE_CACHE_FILENAME);
	}else{
		$_THE_CACHE_ERRORS[] = "No active caches.";
	}
	if( count( $_THE_CACHE_REPLACE[$numcaches-1]["search"]) != 0 ){
		$result = str_replace($_THE_CACHE_REPLACE[$numcaches-1]["search"], $_THE_CACHE_REPLACE[$numcaches-1]["replace"], &$output);
	}else{
		$result = &$output;
	}
	return $result;
}
?>
 |