D7net
Home
Console
Upload
information
Create File
Create Folder
About
Tools
:
/
opt
/
lampp
/
lib
/
php
/
HTML
/
Template
/
Xipe
/
Filename :
Cache.php
back
Copy
<?php // // +----------------------------------------------------------------------+ // | PHP Version 4 | // +----------------------------------------------------------------------+ // | Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002, 2003 The PHP Group | // +----------------------------------------------------------------------+ // | This source file is subject to version 2.02 of the PHP license, | // | that is bundled with this package in the file LICENSE, and is | // | available at through the world-wide-web at | // | http://www.php.net/license/2_02.txt. | // | If you did not receive a copy of the PHP license and are unable to | // | obtain it through the world-wide-web, please send a note to | // | license@php.net so we can mail you a copy immediately. | // +----------------------------------------------------------------------+ // | Authors: Wolfram Kriesing <wolfram@kriesing.de> | // +----------------------------------------------------------------------+ // $Id: Cache.php,v 1.8 2003/03/04 18:52:33 cain Exp $ // require_once 'HTML/Template/Xipe/XMLConfig.php'; /** * this class does the caching of final pages in pure html (or anything you use it for) * ok first an apology to the PEAR::Cache-team :-) i tried to * use the PEAR::Cache and it worked fine (was easy to implement) until i got to the * point that i wanted to include the cached content, * since the philosophy of this template engine is still based * on including either the template or the cached output. * the PEAR::Cache has a wonderful Cache implementation but * what i need here is the final file and there are 2 things that * make it impossible (or would need a change in the concept of this template engine) to * use the PEAR::Cache * 1. PEAR::Cache saves the file encoded and adds extra stuff in the file not only * the actual result, the html page in the normal case * it always has the expiration data and extra user data saved in the * cached file, and additionally the real data are encoded either bbase64 * or serialized, which means a simple include of the cached file is not possible * i would have to decode it first etc. * 2. PEAR::Cache doesnt provide a method to give back the full path and filename of the * cached file, it does always only return the content of it * which of course is right for the way PEAR::Cache works, since the * data have to be decoded * so i have to implement the caching my self :-/ * * to use the cache u have to set the option 'enable-Cache' to true * when making an instance of the template engine * and in the file that shall be cached do the following * (assuming $tpl is an instance of the template engine with the cache option on): * * // before calling '$tpl->isCached()' be sure that all the variables * // that the cache-file depends on (see your xml config) are set to the proper values * // so the cahe methods can properly determine if the file is already cached * // BE WARNED: letting a cache-file depend on i.e. $_REQUEST makes it possible to * // run a DOS-attack, since a new cache file has to be created everytime any * // request parameter changes, i.e. http://your.site.com/index.php?whatever * // this might flood your webservers diskspace * $myTplFile = 'your/template/file.tpl'; * if( !$tpl->isCached( $myTplFile ) ) * { * do all the stuff needed to be done to build a cacheable page * all the time consuming stuff, like db-requests, or getting data * using a webservice (which was my actual need for caching) * } * // simply include the file as usual * $tpl->compile( $myTplFile ); * include( $tpl->getCompiledTemplate() ); * * * @package HTML_Template_Xipe * @author Wolfram Kriesing <wolfram@kriesing.de> */ class HTML_Template_Xipe_Cache extends HTML_Template_Xipe_XMLConfig { /** * @var string the complete filename including path to the cached file */ var $_cachedFile = ''; /** * @var string the global object reference name */ var $_cacheObjReference = ''; /** * this can be set to true using forceRecache() * and it will rebuild the cached file, no matter if it is already cached * @see forceRecache() */ var $_forceRecache = false; /** * checks if the file is cached * * @access public * @version 02/05/26 * @author Wolfram Kriesing <wolfram@kriesing.de> * @return boolean returns true if the output is cached, false otherwise */ function isCached() { if ($this->getOption('cache','time')===false) { return false; } // lets make sure that we define the object reference globally, which is called // from within the template // if we wouldnt do this here we would have a problem if a compiled template // would be included but the reference to $this is not defined, which is needed to call _cacheEnd() // at the end of the template $this->_createCacheObjRef(); // check the forceRecache after creating the cacheObjRef, so the // template can access it if ($this->_forceRecache) { // if _forceRecache is true we say the file is not cached return false; } $cacheFile = $this->_getCacheFileName(); if (!file_exists($cacheFile)) { // if the cached file doesnt exist $this->_log('CACHE: cached file doenst exist: '.$cacheFile); return false; } // has the cached file expired? // the filetime is the time when it expires, this way we dont have to save the // caching time anywhere if (time()>filemtime($cacheFile)) { // if the caching time is 0 it shall be cached forever, so set the expire time to one year ahead // again if ($this->getOption('cache','time')===0) { touch( $cacheFile , time()+60*60*24*365 ); return true; } $this->_log('CACHE: cached file has expired: '.$cacheFile); return false; } // if the template needs a recompile we dont cache if ($this->_needsRecompile()) { $this->_log('CACHE: template needs recompile'); // remove the cached file so we know that we will recreate it // i am doing this because getCompiledTemplate() would return the old cached filename // also if the tpl was recompiled, because after compilation, needsRecompile is false and the cached file // does also exists, only that the expiration time might have changed, which getCompileTemplate, which calls // isCached, has no chance to notice @unlink($cacheFile); return false; } return true; } /** * tell the engine to rebuild the cached file * * @access public * @version 03/03/04 * @author Wolfram Kriesing <wolfram@kriesing.de> */ function forceRecache() { $this->_forceRecache = true; } /** * get the filename of the destination file * * @access public * @version 02/05/26 * @author Wolfram Kriesing <wolfram@kriesing.de> * @return string returns the complete filename */ function _getCacheFileName() { if ($this->_cachedFile) { return $this->_cachedFile; } // add the hash which is calculated over the dependency data, like $_REQUEST, to have a unique filename // for the different dependency data $extension = ''; if (($depends = $this->getOption('cache','depends'))) { //print $depends; $depends = explode(' ',$depends); // init $vars with the names that shall be cached, to be sure that if the values dont change but the names // we have to create a new name $vars = $depends; foreach ($depends as $aDepend) { // if the variable name is like $var['varName'] do only globalize '$var' // even though things like _REQUEST,_SESSION, etc. dont need to be globalized - but it does no harm either // and if it is a $class-> globalize only $class $globalize = preg_replace('/\[.*\]/','',$aDepend); $globalize = preg_replace('/->.*/','',$globalize); // serilaize the var since it might also be an array or object, or whatever //print("global $globalize;\$var = serialize($aDepend);<br>"); eval("global $globalize;\$var = serialize($aDepend);"); //print("$aDepend = $var<br>"); //print $this->_templateFile." ... $var<br>"; $vars = md5("$vars:$var"); } $extension = md5($vars).'.'; } //print "extension=$extension<br>depends = ";print_r($depends); $cacheFileName = $this->_compiledFilePrefix.$extension.$this->getOption('cacheFileExtension'); $this->_cachedFile = $cacheFileName; return $this->_cachedFile; } /** * this is called from within the template to write the content that shall be cached * * @access public * @version 02/05/26 * @author Wolfram Kriesing <wolfram@kriesing.de> */ function _cacheEnd() { $content = ob_get_contents(); // get the destination filename $file = $this->_getCacheFileName(); //print '_cacheEnd write into: '.$file.' <br><br>'; if (file_exists($file)) { unlink($file); } if (($cfp = fopen( $file , 'w' ))) { if ($this->getOption('debug')>0) { fwrite($cfp,'CACHED CONTENT<br>'.$content); } else { fwrite($cfp,$content); } fclose($cfp); chmod($file,0777); } // set file modification time to the time when it expires, // this saves us the checking of the config data, either in options array or the xml file $expires = time()+$this->getOption('cache','time'); if ($this->getOption('cache','time')===0) { // if the caching time is 0 set it to one year ahead $expires = time()+60*60*24*365; } touch($file,$expires); $this->_log('CACHE: caching file for '.$this->getOption('cache','time').' seconds (0 means forever), until: '. date( 'd.m.Y H:i:s' , $expires )); ob_end_flush(); } /** * this adds the calls to the template needed for caching this file * it is used as a filter by the parse method * * @see parse() * @access private * @version 02/05/26 * @author Wolfram Kriesing <wolfram@kriesing.de> * @param string the actual file content * @return string the modified file content */ function _makeCacheable( $input ) { $input = sprintf( '<'.'?php ob_start() ?'.'>%s<'.'?php $%s->_cacheEnd() ?'.'>' , $input , $this->_createCacheObjRef() ); return $input; } /** * * * @access private * @version 02/05/26 * @author Wolfram Kriesing <wolfram@kriesing.de> * @return string the name of the global object ref */ function _createCacheObjRef() { if ($this->_cacheObjReference) { return $this->_cacheObjReference; } // create global (!) object which can be called from within the template file // to call the cacheStart/cacheEnd-methods $this->_cacheObjReference = '_'.md5($this->_templateFile.'cache'); // has to start with a valid character for a varibale name, '_' // its a reference to this instance, so we can simply call the cache methods // we need to do it like this since we dont know the instance name of the template // engine and of this special instance neither, that's the easiest way to do it $GLOBALS[$this->_cacheObjReference] = &$this; //print "_createCacheObjRef = {$this->_cacheObjReference} for {$this->_templateFile}<br>"; return $this->_cacheObjReference; } // // overwritten methods // /** * return the cached file name if it is set, and it is only * set if the file is cached and valid, that means not expired etc. * * @access public * @version 02/05/26 * @author Wolfram Kriesing <wolfram@kriesing.de> * @return string the filename used to include */ function getCompiledTemplate() { if ($this->isCached()) { return $this->_cachedFile; } return parent::getCompiledTemplate(); } /** * do only really compile if the file is not cached * * @access public * @version 02/05/26 * @author Wolfram Kriesing <wolfram@kriesing.de> * @return boolean actually always true */ function compile() { if ($this->isCached()) { return true; } return parent::compile(); } } ?>