芝麻web文件管理V1.00
编辑当前文件:/home/strato/chroot/opt/RZphp80/includes/HTML/Template/Xipe/Main.php
| // +----------------------------------------------------------------------+ // $Id: Main.php,v 1.18 2003/12/01 21:54:39 cain Exp $ // require_once 'PEAR.php'; require_once 'HTML/Template/Xipe/Options.php'; require_once 'HTML/Template/Xipe/Filter/Internal.php'; require_once 'Log.php'; /** * the intention is to use normal php in the template without the need to write * 'tmp', // by default its always the same one as where the template lies in, this might not be desired * delimiter' => array('{','}'), * templateDir' => '', * autoBraces' => true, // see method 'autoBraces' for explaination * makePhpTags' => true, // set this to false if you dont want the delimiters to be translated to php tags automativally * forceCompile' => false, // only suggested for debugging * xmlConfigFile' => 'config.xml', // name of the xml config file which might be found anywhere in the directory structure * locale' => 'en', // default language * cache' => array( 'time' => false// set this to the number of seconds for which the final (html-)file shall be cached // false means the file is not cached at all // if you set it to 0 it is cached forever ,'depends' => 0 // what does it depend on if the cache file can be reused // i.e. could be $_REQUEST $_COOKIES ), * logLevel' => 1, // 1 - only logs new compiles, 0 - logs nothing, 2 - logs everything even only deliveries * filterLevel' => 10, // 0 is no filter, use this if u want to register each filter u need yourself // 1-7 can still be defined :-) // 8 comments stay in the code // 9 as 10 only that the resulting HTML-code stays readable // 10 use all default filters, uses the allPre/Postfilters methods of each filter class * enable-XMLConfig'=>false, * enable-Cache' => false, // if you only turn on the Cache XMLConfig will be turned on too, since it is needed * verbose' => true, // set this to true if the engine shall output errors on the screen // in addition to returning a PEAR_Error // this makes getting the engine running easier // on a production system you should turn this off * logFileExtension'=>'log', // the extension for the log file * cacheFileExtension'=>'html',// file extension for the cached file * compiledTemplateExtension'=>'php',// the extension the generated template shall have * * The templateExtension is currently used in the Filter/TagLib, for determining if * an included file is a template file or a macro file. Templates are handled a bit * differently, they are included as often as the {%include%} tag occurs. * Macro-files are surrounded by an if() clause, to prevent multiple declarations * of macros (which are simply php-functions) *
* 'templateExtension'=> 'tpl',
* 'macroExtension'=> 'mcr' * * @access private * @var array $options the options for initializing the template class */ var $options = array( 'compileDir' => 'tmp', 'delimiter' => array('{','}'), 'templateDir' => '', 'autoBraces' => true, 'makePhpTags' => true, 'forceCompile' => false, 'xmlConfigFile' => 'config.xml', 'locale' => 'en', 'cache' => array( 'time' => false ,'depends' => 0 ), 'logLevel' => 1, 'filterLevel' => 10, 'enable-XMLConfig'=>false, 'enable-Cache' => false, 'verbose' => true, 'logFileExtension'=>'log', 'cacheFileExtension'=>'html', 'compiledTemplateExtension'=>'php', 'debug' => 0, 'templateExtension'=> 'tpl', 'macroExtension'=> 'mcr' ); /** * the current template file for this instance */ var $_templateFile = ''; var $_compiledTemplate = ''; var $_didSetup = false; var $_logFileName = ''; var $_compiledFilePrefix = ''; /** * @var boolean will be set to true if a recompile is needed, * this is when any xml-config file that applies to the current template has changed * or the template itself, or if the compiled template was removed, etc... */ var $_needsRecompile = false; /** * saves the preFilters which will be applied before compilation * * @access private * @var array methods/functions that will be called as prefilter */ var $_preFilters = array(); /** * saves the postFilters which will be applied after compilation * * @access private * @var array methods/functions that will be called as postfilter */ var $_postFilters = array(); /** * @var float the time compiling/delivering took */ var $_compileTime = 0; /** * @var boolean if the template was compiled * @see compiled(), compile() */ var $_compiled = false; var $logObject = null; /** * the constructor, pass the options to it as needed * * @see $options * @version 01/12/03 * @access public * @author Wolfram Kriesing
*/ function HTML_Template_Xipe_Main( $options=array() ) { foreach( $options as $key=>$aOption ) $this->setOption( $key , $aOption ); // replace (multiple) backslashes with forward slashes and replace multiple slashes with single slashes // this way we can quitely sleep and use windows too :-) and only work with forward slashes // all over the template engine // the replacing of multiple slashes is doen because i realized that something like // $DOCUMENT_ROOT.'/libs/' might come out to be '/document/root//libs' depending on the apache configuration $this->setOption('compileDir' , preg_replace("/\\\+|\/+/" , DIRECTORY_SEPARATOR , $this->getOption('compileDir') )); $this->setOption('templateDir' , preg_replace("/\\\+|\/+/" , DIRECTORY_SEPARATOR , $this->getOption('templateDir') )); } /** * this method sets up an instance of the engine * since the philosophie has changed to manage a single object-instance for * each page we need a method here so we dont need to setup all the internal * vars many times * * @version 02/05/25 * @access public * @author Wolfram Kriesing
* @param string the template filename for which this instance shall be setup * @return boolean if setup was necessary or not */ function setup( $filename ) { if( $this->_didSetup == true ) return false; // // setup all the internal vars, like compiledTemplate, etc. // $this->_templateFile = $filename; /* $pathInfo = pathinfo($this->_templateFile); if( in_array($pathInfo['extension'],array('sxw','sxc','sxi','sxd')) ) { } */ // build the filename-prefix that will be used for the compiled file if( PEAR::isError( $ret = $this->_getCompiledFilePrefix() ) ) { return $ret; } $this->_compiledFilePrefix = $ret; //print "this->_templateFile = $this->_templateFile
this->_compiledFilePrefix = $this->_compiledFilePrefix
"; $this->_compiledTemplate = $this->_compiledFilePrefix.$this->getOption('compiledTemplateExtension'); //print ".........BEFORE SETUP METHOD..........
"; //print_r($this);print "
"; // // do all the xml config stuff // if( $this->getOption('enable-XMLConfig') ) { if( PEAR::isError($ret=$this->_applyXmlConfig()) ) return $ret; } if( $this->getOption('enable-Cache') ) { /* $this->_cachedFilename = $this->_getCacheFileName($templateFile); // set the internal values which are needed by the internal methods if( $this->_needsRecompile() || $this->_applyXmlConfigIfNeeded() ) $this->doCompile = ??? // shall the compile method do anything or return true right away? */ } //print ".........END OF SETUP METHOD..........
"; //print_r($this);print "
"; $this->_didSetup = true; return true; } /** * gets the destination file name prefix * i.e. * for a template in /path/to/tpl/file.tpl * it returns
/
/
/file.tpl.
* * @access private * @version 2002/03/11 * @author Wolfram Kriesing
* @return string the filename-prefix that will be used for the compiled file */ function _getCompiledFilePrefix() { // remove the 'tempalteDir' from the templateFile name if( strpos( $this->_templateFile , $this->getOption('templateDir') ) === 0 ) $this->_templateFile = str_replace( $this->getOption('templateDir') , '' , $this->_templateFile ); // replace multiple slashes $this->_templateFile = preg_replace( '/\/+/' , DIRECTORY_SEPARATOR , $this->_templateFile ); // set the template file property and remove leading slashes $this->_templateFile = preg_replace( '/^\/+/' , '' , $this->_templateFile ); // if the compileDir doesnt contain the document root then we figure it starts under the // template dir, i.e. the template dir is: '/usr/local/httpd/htdocs/myProject' // and the compile dir is simply: '/tmp' if( strpos( $this->getOption('compileDir') , $_SERVER['DOCUMENT_ROOT'] )!==0 ) { $compileDir = preg_replace('/^\//' , '' , $this->getOption('compileDir') ); // strip of a leading '/' to be sure not to have 2 slashes there :-) $this->setOption( 'compileDir' , $this->getOption('templateDir').DIRECTORY_SEPARATOR.$compileDir); } $compileDir = $this->getOption('compileDir'); if (!@is_dir($compileDir)) { // check if the compile dir has been created return $this->_error( "'compileDir' could not be accessed
". "1. please create the 'compileDir' which is:
'$compileDir'
2. give write-rights to it" , PEAR_ERROR_DIE ); } if (!@is_writeable($compileDir)) { // i dont know how to check if "enter" rights are given return $this->_error( "can not write to 'compileDir', which is
'$compileDir'
". "1. please give write and enter-rights to it" , PEAR_ERROR_DIE ); } //print "file=$file
"; $directory = dirname( $this->_templateFile ); $filename = basename( $this->_templateFile ); // extract dirname to create directorie(s) in compileDir in case they dont exist yet // we just keep the directory structure as the application uses it, so we dont get into conflict with names // i dont see no reason for hashing the directories or the filenames if ($directory!='.') { // $directory is '.' also if no dir is given $path = explode(DIRECTORY_SEPARATOR,$directory); foreach ($path as $aDir) { $compileDir = $compileDir.DIRECTORY_SEPARATOR.$aDir; if (!@is_dir($compileDir)) { umask(0000); // make that the users of this group (mostly 'nogroup') can erase the compiled templates too if (!@mkdir($compileDir,0777)) { return $this->_error( "couldn't make directory:
'$aDir'
under
'". $this->getOption('compileDir')."'
". "1. please give write permission to the 'compileDir', ". "so Xipe can create directories inside" , PEAR_ERROR_DIE ); } } } } // build the filename prefix, add locale only if given $ret = $this->getOption('compileDir').DIRECTORY_SEPARATOR. $this->_templateFile. ($this->getOption('locale') ? '.'.$this->getOption('locale') : '' ). '.'; $this->_templateFile = $this->getOption('templateDir').DIRECTORY_SEPARATOR.$this->_templateFile; return $ret; } /** * DONT USE YET, since i didnt find a way to make it workin, because no * variable in the template is known if i include it here * use: $ tpl->compile('index.tpl'); * include($ tpl->getCompiledTemplate()); * instead * * @version 01/12/03 * @access public * @author Wolfram Kriesing
*/ function show() { if( $this->compile($file) ) { include( $this->_compiledTemplate ); } else { return $this->_error( "ERROR: couldnt get compiled template!!!" , PEAR_ERROR_DIE ); } } /** * here all the replacing, filtering and writing of the compiled file is done * well this is not much work, but still its in here :-) * * @access private * @version 01/12/03 * @author Wolfram Kriesing
* @param * @return */ function parse() { // read the entire file into one variable if( $input = @file($this->_templateFile) ) $fileContent = implode( '' , $input ); else $fileContent = ''; // if the file doesnt exist, write a template anyway, an empty one but write one // pass option to know the delimiter in the filter, but parse the xml-config before!!!, see line above $defaultFilter = new HTML_Template_Xipe_Filter_Internal($this->options); // apply pre filter $fileContent = $this->applyFilters( $fileContent , $this->_preFilters ); // this filter does all the default replacement of the delimiters $internalFilters = array(); // empty them every time, in case this method is called multiple times in one script // if xml config is on, remove the xml-config tags now // do this first to reduce the file size and reduce later parsing times if( $this->getOption('enable-XMLConfig') == true ) $internalFilters[] = array(&$defaultFilter,'removeXmlConfigString' ); if( $this->getOption('makePhpTags') == true ) $internalFilters[] = array(&$defaultFilter,'makePhpTags'); // if the option autoBraces is on apply the _first_ postFilter right here // which does the autBracing if( $this->getOption('autoBraces') == true ) $internalFilters[] = array(&$defaultFilter,'autoBraces'); if( $this->getOption('enable-Cache') && $this->getOption('cache','time') !== false ) $internalFilters[] = array( &$this , '_makeCacheable' ); $fileContent = $this->applyFilters( $fileContent , $internalFilters ); // apply post filter $fileContent = $this->applyFilters( $fileContent , $this->_postFilters ); // write the compiled template into the compiledTemplate-File if( ($cfp = fopen( $this->_compiledTemplate , 'w' )) ) { fwrite($cfp,$fileContent); fclose($cfp); chmod($this->_compiledTemplate,0777); } return true; } /** * compile the template * * @access public * @version 01/12/03 * @author Wolfram Kriesing
* @param string $file relative to the 'templateDir' which you set when calling the constructor * @return */ function compile() { //print $this->_templateFile.'
'; // cant the log-class do that??? $startTime = split(" ",microtime()); $startTime = $startTime[1]+$startTime[0]; $this->_compiled = false; if( $this->_needsRecompile() ) { $this->_log( 'compile started' ); $this->_log('Locale:'.$this->options['locale'] ); $this->_log( 'needsRecompile is true' ); if( !$this->parse() ) return false; $endTime = split(" ",microtime()); $endTime = $endTime[1]+$endTime[0]; $itTook = ($endTime - $startTime)*100; $this->_log("(compilation and) deliverance took: $itTook ms" ); $this->_compiled = true; } return true; } /** * tells if the current template needed to be compiled * if 'compile()' was called before and the template didnt * need to be recompiled this method will return false too * * @see compile() * @access private * @version 2003/01/10 * @author Wolfram Kriesing
* @return boolean if the template was compiled */ function compiled() { return $this->_compiled; } /** * checks if the current template needs to be recompiled * this is the case for either case: * - if forceCompile option is on * - if the template has changed/was removed, etc. * * @access private * @version 2002/03/11 * @author Wolfram Kriesing
* @return true if the template should be recompiled, false otherwise */ function _needsRecompile() { if( $this->getOption('forceCompile') ) { $this->_log('recompile because option "forceCompile" is true'); return true; } if( !$this->_isUpToDate() ) // check if the template has changed { $this->_log('recompile because tpl has changed/was removed: '.$this->_templateFile); return true; } if( $this->_needsRecompile == true ) // this will be set to true i.e. by the xml-config check, if any of the xml-files has changed return true; return false; } /** * checks if the compiled template is still up to date * * @access private * @version 01/12/03 * @author Wolfram Kriesing
* @param string $fileToCheckAgainst if given this file is checked if it is newer than the compiled template * this is useful if for example only an xml-config file has changed but not the * template itself * @return boolean true if it is still up to date */ function _isUpToDate( $fileToCheckAgainst='' ) { if( $fileToCheckAgainst == '' ) $checkFile = $this->_templateFile; else $checkFile = $fileToCheckAgainst; if( !file_exists( $this->_compiledTemplate ) || !file_exists( $checkFile ) || filemtime( $checkFile ) > filemtime( $this->_compiledTemplate ) ) { return false; } return true; } function getCompiledTemplate() { return $this->_compiledTemplate; } // filter stuff /** * register a prefilter, which will be executed BEFORE the template * is being compiled * * @access public * @version 01/12/03 * @author Wolfram Kriesing
* @param mixed the funtion to call, or an array(&$object,'methodname') * @param mixed if given parameters are passed to the function/method */ function registerPrefilter( $functionName , $params=null ) { $this->_registerFilter( 'pre' , $functionName , $params ); } /** * register a postfilter, which will be executed AFTER the template * was compiled * * @access public * @version 01/12/07 * @author Wolfram Kriesing
* @param mixed the funtion to call, or an array(&$object,'methodname') * @param mixed if given parameters are passed to the function/method */ function registerPostfilter( $functionName , $params=null ) { $this->_registerFilter( 'post' , $functionName , $params ); } /** * put the filter either in the pre or postFilter array * check for language filters too! those have to go first * * @access public * @version 02/09/22 (day of the elections in germany :-) ) * @author Wolfram Kriesing
* @param mixed the funtion to call, or an array(&$object,'methodname') * @param mixed if given parameters are passed to the function/method */ function _registerFilter( $which , $functionName , $params ) { $langFilter = false; if( is_array($functionName) ) { if( method_exists($functionName[0],'isLanguageFilter') ) $langFilter = call_user_func( array($functionName[0],'isLanguageFilter') ); } if( $params != null ) { settype($params,'array'); $thisFilter = array($functionName,$params); // use reference here !!! see comment above in registerPrefilter } else $thisFilter = $functionName; $arrayName = &$this->{'_'.$which.'Filters'}; if( $langFilter ) // language filters have to be applied first, so all other filters also have effect on it array_unshift($arrayName,$thisFilter); else $arrayName[] = $thisFilter; } /** * unregister a filter * * @access public * @version 02/06/21 * @author Wolfram Kriesing
* @param string the filter name, if not given all filters are unregistered */ function unregisterFilter( $name=null ) { if( $name==null ) { $this->_postFilters = array(); $this->_preFilters = array(); } } /** * actually it will only be used to apply the pre and post filters * * @access public * @version 01/12/10 * @author Wolfram Kriesing
* @param string $input the string to filter * @param array $filters an array of filters to apply * @return string the filtered string */ function applyFilters( $input , $filters ) { if( sizeof($filters) ) foreach( $filters as $aFilter ) { // FIXXME use log class $startTime = split(" ",microtime()); $startTime = $startTime[1]+$startTime[0]; $sizeBefore = strlen($input); if( !is_array($aFilter) || // is it not an array so it is simply a function name ( is_array($aFilter) && is_object($aFilter[0]) ) // or is it an array(&$object,'methodname')? ) { $input = call_user_func_array( $aFilter , array($input) ); $appliedFilter = $aFilter; if( is_array($aFilter) ) $appliedFilter = $aFilter[1]; } else { array_unshift($aFilter[1],$input); $input = call_user_func_array( $aFilter[0] , $aFilter[1] ); $appliedFilter = $aFilter[0]; if( is_array($aFilter[0]) ) $appliedFilter = $aFilter[0][1]; } $sizeAfter = strlen($input); // FIXXME use log class $endTime = split(" ",microtime()); $endTime = $endTime[1]+$endTime[0]; $itTook = ($endTime - $startTime)*100; $this->_log("applying filter: '$appliedFilter' \ttook=$itTook ms, \tsize before: $sizeBefore Byte, \tafter: $sizeAfter Byte"); } return $input; } // private stuff /** * show an error on the html page, format it, so it is obvious * * @access private * @version 02/02/25 * @param string $message the error message * @author Wolfram Kriesing
*/ function _error( $message , $mode = PEAR_ERROR_RETURN ) { if( $this->getOption('verbose') == true ) { echo '
HTML_Template_Xipe ERROR
'; echo '
'; echo $message; echo '
'; } return new PEAR_Error( $message , null , $mode ); } /** * logs errors depending on the loglevel it does either write them * in a file or leaves it all the way * * @access private * @version 02/05/13 * @author Wolfram Kriesing
* @param string the log message * @param int the log level of the message */ function _log($message) { if ($this->getOption('logLevel') == 0) { return; } if ($this->getOption('debug') > 0) { print("LOG MESSAGE: $message.
"); } // dont log the same messages multiple times if (!empty($this->_loggedMessages[md5($message)])) { return; } $this->_loggedMessages[md5($message)] = true; if ($this->logObject==null || !is_object($this->logObject) || !$this->_logFileName) { $this->_logFileName = $this->_compiledFilePrefix.$this->getOption('logFileExtension'); $this->logObject =& Log::factory('file',$this->_logFileName); $this->_log('---------------------'); //FIXXME write the options in the log-file but nicer!!! than here $this->_log('options: '.serialize($this->options)); $this->_log( 'current logLevel is: '.$this->getOption('logLevel') ); } $this->logObject->log($message); } } ?>