<?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 ==0 || $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]) == 0 ){
                
$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]) != 0 ){
            
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($fp, LOCK_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.";
        }
    }

}

?>