<?php

// comment this line out if on windows 9x or any other os not supporting flock()
define("WITH_FLOCK"1);    

/*************************************************

morecache.php - a general-purpose script-output caching class

home page: www.samscripts.com/scripts/morecache
support: support.samscripts.com/index.php

licence: freeware / optionally giftware ( www.samscripts.com/donate.php )
author: Sam Yapp
date: 8th September 2002

documentation and examples at www.samscripts.com

*************************************************/

class morecache{

    var 
$expireafter;
    var 
$expiretype;
    var 
$filenames;
    var 
$searchvars;
    var 
$replacevars;
    var 
$activecaches = -1;
    var 
$cachepath "./cached";


    function 
setexpiry($expireafter 60){    
        
$this->expireafter $expireafter;
        if( 
is_int($expireafter) ){
            
$this->expiretype "sec";
        }else{
            
$this->expiretype "date";
        }
    }

    function 
morecache$cachepath ""$expireafter 3600){
        if( 
$cachepath != "" $this->cachepath $cachepath;
        
$this->setexpiry($expireafter);
        
$this->filenames = array();
        
$this->searchvars = array();
        
$this->replacevars = array();
        
$this->activecaches = -1;
    }


    function 
makecachename($id){
        return 
$this->cachepath."/".md5($id).".cache";
    }

    function 
expirecache($cachename){
        
$filename $this->makecachename($cachename);
        @
unlink($filename);
    }

    function 
cache($cachename$expireafter ""$search = array(), $replace=array()){
        if( !
is_array($search) ) $search = array($search);
        
$this->activecaches++;

        
$this->filenames[$this->activecaches] = $this->makecachename($cachename);
        
$this->searches[$this->activecaches] = &$search;
        
$this->replaces[$this->activecaches] = &$replace;

        if( 
$expireafter == "" $expireafter $this->expireafter;
        
$this->setexpiry($expireafter);

        
$update 0;
        if( !
file_exists($this->filenames[$this->activecaches]) ){
            
$update 1;
            
$exist 0;
        }else{
            
$exist 1;
            
$updated filemtime($this->filenames[$this->activecaches]);
        }

        if( 
$exist ==|| $updated < ($this->expiretype == "sec" time() - $this->expireafter strtotime($this->expireafter))){
            
$update 1;
        }

        if( 
$update){ 
            
ob_start();
            return 
true;
        }else{
            if( 
count($this->searches[$this->activecaches]) == ){
                
$fp $this->flock($this->filenames[$this->activecaches], "r");
                if(!@
readfile$this->filenames[$this->activecaches])) $this->error "readfile failed for ".$this->filenames[$this->activecaches];
                
$this->funlock($fp);
            }else{
                
$f join(""file($this->filenames[$this->activecaches]));
                echo 
str_replace($this->searches[$this->activecaches], $this->replaces[$this->activecaches], $f);
            }
            return 
false;
        }
    }

    function 
stop($returnbuffer false$showoutput true){        // if returnbuffer is true, returns the contents of the cache to the calling script
        
$this->cachecontents ob_get_contents();
        
$this->save();
        if( 
$showoutput == true && count$this->searches[$this->activecaches]) != ){
            
ob_end_clean();
            echo 
str_replace($this->searches[$this->activecaches], $this->replaces[$this->activecaches], $this->cachecontents);
        }elseif( 
$showoutput == true ){
            
ob_end_flush();
        }else{
            
ob_end_clean();
        }
        
$this->activecaches--;
        return (
$showoutput == true $this->cachecontents true);
    }

    function 
flock($filename$mode){
        
$fp = @fopen($filename$mode "r" "r" "wb");
        if( 
defined(WITH_FLOCK) ) flock($fp$mode="r" LOCK_SH LOCK_EX);
        
ignore_user_abort(true);
        return 
$fp;
    }

    function 
funlock($fp){
        if( 
$fp ){
            
flock($fpLOCK_UN);
            @
fclose($fp);
        }
    }

    function 
save(){
        
$fo $this->flock($this->filenames[$this->activecaches], "w");
        if( 
$fo ){
            if( !@
fwrite$fo$this->cachecontents)) $this->error "Error writing to file ".$this->filenames[$this->activecaches];
            
$this->funlock($fo);
        }else{
            
$this->error "Failed opening file ".$this->filenames[$this->activecaches]." for output.";
        }
    }

}

?>