Location: PHPKode > scripts > Gedar Template Engine > gedar-template-engine/GedarTemplate.inc.php
<?php
  /**
   * Project:         Gedar Template Engine: a PHP template engine
   * File:            GedarTemplate.inc.php
   * Copyright (C) 2005  Ali Masoudi<hide@address.com>
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; either version 2 of the License, or
   * (at your option) any later version.
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
   *
   * @link http://Gedar.alimasoudi.com
   * @authur Ali Masoudi <hide@address.com>
   * @version 1.0.1
   * @package Gedar
   */

  /**#@+
   * set main constant
   */
  
// DIR_SEP: is DIRECTORY_SPARATOR ,for diffrence in windows and unix style directory separator
if(!defined('DIR_SEP'))
  define('DIR_SEP', DIRECTORY_SEPARATOR);

// CURRENT_DIR: PHP Script directory,current file's directory that include and execute template engine
if(!defined('CURRENT_DIR'))
  define('CURRENT_DIR',dirname($_SERVER['SCRIPT_FILENAME']).DIRECTORY_SEPARATOR);

// GEDAR_MAINDIR: absolute path to gedar directory,absolute path to template engine directory
if(!defined('GEDAR_MAINDIR'))
  define('GEDAR_MAINDIR',dirname(__FILE__).DIRECTORY_SEPARATOR);


/**#@+
 * Template Compiling Class
 * @package Gedar
 */
class Template
{
  /**#@+
   * Internal Variable
   */
  
  /**
   * Determine the realase version of Gedar
   * Template Engien
   * @var string
   */
  var $_Gversion                           = "1.0.1";
  /**
   * Determine name of file must parsed
   *
   * @var string
   */
  var $_TplFileName                        = "";
  /**
   * Determine directory of template file
   *
   * @see $_TplFileName
   * @var string
   */
  var $_TplDirectory                       = "";
  /**
   * Determine That template directory path is relative
   * from php file ( the file includes template engine
   * class )
   *
   * @var bool
   */
  var $_TplTemplatePathRealtiveFromPhpFile = false;
  /**
   * Determine that need cache create or rebuild
   *
   * @var bool
   */
  var $_TplCache                           = true;
  /**
   * Directory of cache file relative from 
   * this class directory
   *
   * @var string
   */
  var $_TplCacheDirectory                  = "./cache/";
  /**
   * time in second for rebuilding cache file
   *
   * @var int
   */
  var $_TplCacheLifeTime                   = 300;
  /**
   * determine must write in cache now or not
   *
   * @var bool
   */
  var $_TplCacheWrite                      = true;
  /**
   * encrypted name of cache file
   *
   * @var string
   */
  var $_TplCacheFileName                   = "";
  /**
   * start prefix for regulare expression
   *
   * @var string
   */
  var $_TplStartPrefix                     = "\{";
  /**
   * end prefix for regulare expression
   *
   * @var string
   */
  var $_TplEndPrefix                       = "\}";
  /**
   * start prefix for template engine tag
   *
   * @var string
   */
  var $_TplStartTag                        = "{";
  /**
   * end prefix for template engine tag
   *
   * @var string
   */
  var $_TplEndTag                          = "}";
  /**
   * type of output; array("capture","show")
   * capture: return a variable of translated template
   * show: echo translated template
   *
   * @var string
   */
  var $_TplOutputType                      = "show";
  /**
   * array of directories that include plugin files
   *
   * @var array
   */
  var $_TplPluginDirectory               = array("./gPlugins");
  /**
   *
   * @var array
   */
  var $_TplPlugins                       = array();
  /**
   * template generation mode
   * '0': no cache
   * '1': default; when cache recreate that the source file change
   * '2': make cache per time
   *
   * @var string
   */
  var $_TplGenerationMode                = "1";
  /**
   * stores template variable
   *
   * @var array
   */
  var $_TplVars                          = array();
  /**
   * stores template special variable
   *
   * @var array
   */
  var $_TplSpecialVars                   = array();
  /**
   * current page information
   * ['query']: all url query in variable mode
   * ['directory']: main php file directory
   *
   * @var array
   */
  var $_page                             = array();
  /**
   * Predefiend variable
   * stores all predefiend variable
   * each element contains array['name','value']
   * @see setPredefiendVar()
   *
   * @var array
   */
  var $_gedarPredefiendVar               = array();
  /**
   * outputting tag
   *
   * @var array
   */
  var $_outputTag                        = array(
						 "header"=>array() ,
						 "content"
						 );
  /**
   * store all occured error
   *
   * @var array
   */
  var $_error                            = array();
  /**
   * timestamp that start engineing
   *
   * @var string
   */
  var $_startTimeStamp                   = "";
  /**
   * temporary variable
   *
   * @var mixed
   */
  var $_tmpVar                           = "";

  /**
   * set template values
   *
   * set the template essential variable<br/>
   * $pathAddressingMode define that templte directory is
   * relative from php file that load template engine
   * @param string $srcFileName
   * @param string $srcFileDir
   * @param bool   $pathAddressingMode
   * @return true
   */
  function Template($srcFileName,$srcFileDir,$pathAddressingMode=true,$cacheDir=false,$pluginDir=false)
  {
    $this->_TplFileName = $srcFileName;
    $this->_TplTemplatePathRealtiveFromPhpFile = $pathAddressingMode;
    $this->Initialize($srcFileDir,$cacheDir,$pluginDir);
  }

  /**
   * Initialize Template Requirement
   * Initialize source , cache and plugin directory
   * address and specefic, and set all regulare
   * expressions that will needed in class
   * @param string $srcFileDir
   * @param String $cacheDir
   * @param string pluginDir
   * @return true
   */
  function Initialize($srcFileDir,$cacheDir,$pluginDir)
  {
    $this->_startTimeStamp=microtime();
    $this->setDirectory($srcFileDir,$cacheDir);
    $this->setPluginDirectory($pluginDir);
    $this->setPredefiendVar();
    $this->regExpDefenition();
  }

  /**
   * Set template directory variable
   * set source directory and cache diretory
   * for current file
   * @param string $srcFileDir
   * @param string $cacheDir
   * @return true
   */
  function setDirectory($srcFileDir,$cacheDir)
  {
    if (@strlen($srcFileDir))
      {
	if(substr($srcFileDir,0,1)!="/" || substr($srcFileDir,0,1)!="\\")
	  {
	    $srcFileDir="/".$srcFileDir;
	  }
	$this->_TplDirectory=($this->_TplTemplatePathRealtiveFromPhpFile) 
	  ? 
	  $this->real_path($this->real_path(dirname($_SERVER['SCRIPT_FILENAME'])).$srcFileDir)
	  : 
	  $this->real_path(GEDAR_MAINDIR.$this->_TplDirectory.DIRECTORY_SEPARATOR.$srcFileDir);
      }
    else
      {
	$this->_TplDirectory = $this->real_path(GEDAR_MAINDIR.DIRECTORY_SEPARATOR.$this->_TplDirectory.DIRECTORY_SEPARATOR);
      }
    if ($cacheDir)
      $this->_TplCacheDirectory = $this->real_path($this->real_path(dirname($_SERVER['SCRIPT_FILENAME'])).DIR_SEP.$cacheDir);
    else
      $this->_TplCacheDirectory = $this->real_path(GEDAR_MAINDIR.DIR_SEP.$this->_TplCacheDirectory.DIR_SEP);
    return true;
  }

  /**
   * Set Plugin Directory
   * set directory that contains
   * plugins in itself
   * @param string $pluginDir
   * @return true
   */
  function setPluginDirectory($pluginDir)
  {
    if (@$pluginDir)
      $this->_TplPluginDirectory[] = $pluginDir;
    foreach($this->_TplPluginDirectory as $dir)
      {
	$this->_TplPluginDirectory[] = $this->real_path(GEDAR_MAINDIR.DIR_SEP.$dir);
      }
    return true;
  }

  /**
   * Set Predefined Variable
   * When class start working this method
   * set initial predefined variable
   * @return true
   */
  function setPredefiendVar()
  {
    $this->addPredefiendVar("ldel","{");
    $this->addPredefiendVar("rdel","}");
    $this->addPredefiendVar("date",date("Y-m-d"));
    $this->addPredefiendVar("time",date("H:i:s"));
  }

  /**
   * Regular Expression Defenition
   * Duty of this method is defining required 
   * regular expression in this class
   * @return true
   */
  function regExpDefenition()
  {
    // -Double qoute string-
    // "Gedar \"is a template engine"
    $this->_regExpDblQuoteStr = '"[^"\\\\]*(?:\\\\.[^"\\\\]*)*"';
    // -Single qoute string-
    // 'Gedar \'is simple to use'
    $this->_regExpSingleQuoteStr = '\'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\'';
    // -String-
    // 'ali'
    // "ali"
    $this->_regExpString = '(?:' . $this->_regExpDblQuoteStr . '|' . $this->_regExpSingleQuoteStr . ')';
    // -Bracket Element-
    // ['ali']
    // [$var]
    $this->_regExpBracket = '\[(?:(?:\$[a-zA-Z_]\w*)|(?:'.$this->_regExpString.'))\]';
    // -Numbers-
    // 9.2
    // -4
    $this->_regExpNumber = '\-?\d+(?:\.\d+)?';
    // -Mathematic Operator-
    // + - % * /
    $this->_regExpMathOp = '[\+\-\*\/\%]';
    $this->_regExpMathTogether = '[\$\w\+\-\*\/\%\d\>\[\]]';
    // -Variable minus initial dollar-
    // hassan['reza']['karim']
    // ahmad[$var]
    $this->_regExpVarAfterDollar = '\w+(?:' . $this->_regExpBracket
      . ')*(?:\.\$?\w+(?:' . $this->_regExpBracket . ')*)*(?:' . $this->_regExpMathOp 
      . '(?:' . $this->_regExpNumber . '|' . $this->_regExpMathTogether . ')*)?';
    // -Variable Defintion-
    // $hassan['reza']['lar']
    // $karim[$var]
    $this->_regExpVar = '\$' . $this->_regExpVarAfterDollar;
    $this->_regExpAssign = '(?:'. $this->_regExpString . '|'. $this->_regExpNumber .')';
    // -Var Name-
    // $hassan
    // $karim
    $this->_regExpVarName = '\$\w*';
    // -All Variable Type-
    // 12
    // $akbar['reza']
    // Karim
    $this->_regExpVariable = '(?:' . $this->_regExpVar . '|' . $this->_regExpNumber . '|' . $this->_regExpString . ')';
    // -Function-
    // --Function Name--
    // funcName
    $this->_regExpFuncName = '[a-zA-Z_]\w*';
    // --Function Calling--
    // funcname( param1 , param2 , ... )
    $this->_regExpFunction = '(?:' . $this->_regExpFuncName . '\s*\((?:\s*'.$this->_regExpVariable.'\s*,?\s*)*\))';
    $this->_regExpFunctionValue = '(?:'.$this->_regExpVar.')|(?:'.$this->_regExpAssign.')';
  }

  /**
   * Add Predefiend Variable
   * Add new predefiend variable to
   * current gedar template engine
   * @param string $name
   * @param string $value
   * @return true
   */
  function addPredefiendVar($name,$value)
  {
    $this->_gedarPredefiendVar[$name]=$value;
  }

  /*
   * Script Inormation
   * Set main Information about main script
   * such as queries , directory , filename ,
   * ... that will be needed in script
   * @return true
   */
  function _ScriptInfo()
  {
    parse_str($_SERVER['QUERY_STRING'], $query);
    $directory = substr($this->_TplVars['_GSCRIPT_NAME'] , 0 , strrpos( $this->_TplVars['_GSCRIPT_NAME'] , '/' ))."/";
    $this->_page['query']=$query;
    $this->_page['directory']=$directory;
    $this->assign("_GSERVER",$_SERVER);
    $this->assign("_GSCRIPT_NAME",$_SERVER['SCRIPT_NAME']);
    $this->assign("_GSELF",$_SERVER['PHP_SELF']);
    $this->assign("_GQUERY",$query);
    $this->assign( 'SCRIPT_DIRECTORY' , $directory);
    return true;
  }

  /**
   * Compile Template File
   * Check if translated resource
   * expired , make it from initial
   * @param string $fileName
   * @return true
   */
  function _compile($fileName)
  {
    /* Do not need to recompile */
    if(!$this->cacheFileIsExpired($fileName))
	return true;
    /* Need to recompile */
    $resource=$this->_compileResourceFile($fileName);
    $header=implode("\n",$this->_outputTag['header']);
    $content = $header."\n".$resource;
    $this->makeCacheFile($fileName,$content);
    return true;
  }

  /**
   * Compile Template
   * Gather source from a template and make
   * translated resource from it
   * $fileName is the name of file with the
   * complete path
   * @param string $fileName
   * @return true;
   */
  function _compileResourceFile($fileName)
  {
    $this->_templateComiplingHeaderInfo();
    $source=$this->_readFile($fileName);
    /* first change source section format to be specefied */
    $changedSource=preg_replace( '~'.$this->_TplStartPrefix.'([^'.$this->_TplEndPrefix.']+)'.$this->_TplEndPrefix.'~i',"\n"."^".
				 $this->_TplStartTag.$this->_TplEndTag."^"."\n"."$1$2$3"."\n"."~".$this->_TplStartTag.
				 $this->_TplEndTag."~"."\n"
			       ,$source
			       );
    $sourceLines = explode( "\n" , $changedSource );
    foreach( $sourceLines as $key=>$eachLine )
      {
	if (@$sourceLines[$key-1]=="^".$this->_TplStartTag.$this->_TplEndTag."^" && @$sourceLines[$key+1]=="~".$this->_TplStartTag.$this->_TplEndTag."~")
	  {
	    $transTag.=$this->_convertTag("{".$eachLine."}");
	  }
	elseif(@$sourceLines[$key-1]=="~".$this->_TplStartTag.$this->_TplEndTag."~")
	  {
	    $transTag.=$eachLine;
	  }
	elseif ($eachLine=="^".$this->_TplStartTag.$this->_TplEndTag."^" || $eachLine=="~".$this->_TplStartTag.$this->_TplEndTag."~" )
	  {
	    $transTag.= "";
	  }
	else
	  {
	    @$transTag.= "\n".$eachLine;
	  }
      }
    return $transTag;
  }

  /**
   * Convert Source Tag
   * Convert source tag to synonym php tag
   *
   * @param string $tag
   * @return string
   */
  function _convertTag($tag)
  {
    /* convert gedar predefined variable 
     every #name# translated to its value */
    foreach($this->_gedarPredefiendVar as $preVar)
      {
      if(preg_match('~'.$this->_TplStartPrefix.'\#'.$this->_gedarPredefiendVar.'\#'.$this->_TplEndPrefix.'~i',$tag ,$match))
	{
	  $translatedTag = $this->_TplStartTag;
	  return $translatedTag;
	}
      }
    /* Match {var} and convert them to 
     <start_php_tag print var; end_php_tag> */
    if(preg_match('~^\s*'.$this->_TplStartPrefix.'\s*('.$this->_regExpVariable.')\s*'.$this->_TplEndPrefix.'\s*$~i',$tag ,$match))
      {
	$ret="<?php print ".($match[1])."; ?>";
	return $this->_makeVariable($ret);
      }
    /* check for main function like if, else, for
     and other functions that defines in main dir*/
    $translatedTag=$this->_checkFunction($tag);
    /* check for end function tag like /if,/foreach
     and other functions */
    $translatedTag=$this->_checkEndFunction($translatedTag);
    /* make variable name as acceptable state
     in template */
    $translatedTag=$this->_makeVariable($translatedTag);
    return $translatedTag;
  }

  /**
   * Check Function
   * check if is it built-on function or 
   * external plugin and load it if it
   * is an external plugin and set
   * output displaying
   *
   * @param string $tag
   * @return string
   */
  function _checkFunction($tag)
  {
    $st = $this->_TplStartPrefix;
    $en = $this->_TplEndPrefix;
    $pattern = '~^'.$st.'\s*([a-z0-9_]+)(\s+.*)'.$en.'$~i';
    if(!preg_match($pattern,$tag,$match))
	return $tag;
    $function = $match[1];
    $params=$this->_getParams($match[2]);
    $wholeParams=$match[2];
    if($this->_isPredefiendFunction($function))
      eval('$output=$this->_compile'.$function.'Tag($params,$wholeParams);');
    else
      $output=$this->_setupPlugin($function,$params);
    return $output;
  }

  /**
   * Check End Function
   * check if is it built-on finish function or 
   * external plugin and load it if it
   * is an external plugin and set
   * output displaying
   * @param string $tag
   * @return string
   */
  function _checkEndFunction($tag)
  {
    $st = $this->_TplStartPrefix;
    $en = $this->_TplEndPrefix;
    $pattern = '~^'.$st.'\s*/([a-z0-9_]+)\s*'.$en.'$~i';
    if(!preg_match($pattern,$tag,$match))
	return $tag;
    $function = "end".$match[1];
    $params="array()";
    $wholeParams="";
    if($this->_isPredefiendFunction($function))
      eval('$output=$this->_compile'.$function.'Tag($params,$wholeParams);');
    else
      $output=$this->_setupPlugin($function,$param);
    return $output;
  }

  /**
   * Check Is Predefiend
   * Check that specefic function is predefiend
   * and built-on function or not
   * @param string $function
   * @return bool
   */
  function _isPredefiendFunction($function)
  {
    $methodeName = "_compile".$function."Tag";
    /*  gather all defined methode */
    $definedMethode = get_class_methods($this);
    /* get all of existing method and check
     is the method with '_compile{functionName}Tag'
     name is exist or not */
    foreach($definedMethode as $methode)
      if(strtolower($methode)==strtolower($methodeName))
	return true;
    return false;
  }

  /**
   * Get Parameters
   * Get parameters from an involved
   * parantheses tag source
   * @syntax ( paramName1= "param value1" , paramName2=$value2 , .... )
   * @param string $paramSrc
   * @return true;
   */
  function _getParams($paramSrc)
  {
    /* Check every paramName=Value between 
     parantheses */
    if(preg_match_all('~'."([a-zA-Z0-9_]*)\s*=\s*(".$this->_regExpVariable.")~i" , $paramSrc , $m))
      {
	$array = array();
	foreach( $m[1] as $key=>$v)
	  {
	    $array[$v]=$m[2][$key];
	  }
	$paramKey = 'array(';
	$i=1;
	foreach( $array as $key=>$v)
	  {
	    $paramKey .= (count($array)>$i)? "'".$key."'".'=>\''.addslashes($v).'\',' : "'".$key."'".'=>\''.addslashes($v).'\'';
	    $i++;
	  }
	$paramKey .= ')';
      }
    else
      $paramKey="array()";
    /* we make a expression like this array('ex'=>'nn' , ..)
     and assign it to $tmp_var with eval */
    eval('$tmp_var='.$paramKey.';');
    return $tmp_var;
  }

  /**
   * Setup Plugin
   * Setup a plugin for using in current
   * template and get output tag for it if 
   * needed
   * function name that give output tag is like
   * @returntag gedar_{plugin_name}_excute()
   * @param string $function
   * @param array $param
   * @return string
   */
  function _setupPlugin($function,$param)
  {
    $this->setPluginHeader($function);
    $functionName="gedar_".$function."_excute";
    include_once($this->pluginCompleteAddress($function));
    eval('$output='.$functionName.'($param,$this);');
    return $output;
  }

  /**
   * Set Plugin Header
   * set all header information like including
   * files and ... for this plugin in header
   * @param string $function
   * @return true
   */
  function setPluginHeader($function)
  {
    $pluginFile=$this->pluginCompleteAddress($function);
    if(!$pluginFile)
      $this->_error[]=$function.'(): Requested plugin doesn`t  exist!';
    $this->addHeaderIfNotExist('<?php include_once "'.$pluginFile.'"; ?>');
  }
  
  /**
   * Plugin Complete Address
   * give a plugin name and return its complete 
   * main file`s address
   * @param string $function
   * @return string
   */
  function pluginCompleteAddress( $function )
  {
    $function=strtolower($function);
    foreach ( $this->_TplPluginDirectory as $dir )
      {
	$completeAddress=$this->real_path(GEDAR_MAINDIR.$dir."/")."gPlugin.".$function.'.inc.php';
	if(file_exists($completeAddress))
	  return $completeAddress;
      }
    return false;
  }

  /**
   * Complete Template Address From Main Template Address
   * return complete address of a template from
   * main template address
   * @param string $address
   * @return string
   */
  function completeTemplateAddressFromMainTemplate($address)
  {
    if(substr($this->_TplDirectory,strlen($this->_TplDirectory),1)=="/")
      $ds="/";
    else
      $ds="";
    return $this->real_path($this->_TplDirectory.$ds.$address);
  }

  /**
   * If Callback Methode
   * compile if tags
   * @syntax {if (conditions)}
   * @param array $params
   * @param string wholeParamsPar
   * @return string
   */
  function _compileIfTag($params,$wholeParamsPar)
  {
    $output = "<?php if $wholeParamsPar { ?>";
    return $output;
  }

  /**
   * for Callback Methode
   * compile for tags
   * @syntax {for (from,to,step)}
   * @param array $params
   * @param string wholeParamsPar
   * @return string
   */
  function _compileForTag($params,$wholeParamsPar)
  {
    $output = "<?php for $wholeParamsPar { ?>";
    return $output;
  }

  /**
   * while Callback Methode
   * compile while tags
   * @syntax {while (condition)}
   * @param array $params
   * @param string wholeParamsPar
   * @return string
   */
  function _compileWhileTag($params,$wholeParamsPar)
  {
    $output = "<?php while $wholeParamsPar { ?>";
    return $output;
  }

  /**
   * Foreach Callback Methode
   * compile foreach tags
   * @syntax {for ($array as $key=>$element)}
   * @param array $params
   * @param string wholeParamsPar
   * @return string
   */
  function _compileForeachTag($params,$wholeParamsPar)
  {
    $output = "<?php foreach $wholeParamsPar { ?>";
    return $output;
  }

  /**
   * Endfor Callback Methode
   * compile Endfor tags
   * @syntax {/for}||{endfor}
   * @param array $params
   * @param string wholeParamsPar
   * @return string
   */
  function _compileEndForTag($params,$wholeParamsPar)
  {
    $output = "<?php } ?>";
    return $output;
  }

  /**
   * EndIF Callback Methode
   * compile EndIf tags
   * @syntax {/if}||{endif}
   * @param array $params
   * @param string wholeParamsPar
   * @return string
   */
  function _compileEndIfTag($params,$wholeParamsPar)
  {
    $output = "<?php } ?>";
    return $output;
  }

  /**
   * EndWhile Callback Methode
   * compile endWhile tags
   * @syntax {/while}||{endwhile}
   * @param array $params
   * @param string wholeParamsPar
   * @return string
   */
  function _compileEndWhileTag($params,$wholeParamsPar)
  {
    $output = "<?php } ?>";
    return $output;
  }

  /**
   * EndForeach Callback Methode
   * compile endforeach tags
   * @syntax {/foreach}||{endforeach}
   * @param array $params
   * @param string wholeParamsPar
   * @return string
   */
  function _compileEndForeachTag($params,$wholeParamsPar)
  {
    $output = "<?php } ?>";
    return $output;
  }

  /**
   * else Callback Methode
   * compile else tags
   * @syntax {else}
   * @param array $params
   * @param string wholeParamsPar
   * @return string
   */
  function _compileElseTag($params,$wholeParamsPar)
  {
    $output = "<?php } else { ?>";
    return $output;
  }

  /**
   * Elseif Callback Methode
   * compile elseif tags
   * @syntax {elseif(condition)}
   * @param array $params
   * @param string wholeParamsPar
   * @return string
   */
  function _compileElseIfTag($params,$wholeParamsPar)
  {
    $output = "<?php } elseif $wholeParamsPar { ?>";
    return $output;
  }

  /**
   * include Callback Methode
   * compile include tags
   * @syntax {include (file='filename')}
   * @param array $params
   * @param string wholeParamsPar
   * @return string
   */
  function _compileIncludeTag($params,$wholeParamsPar)
  {
    $file=$this->_getParamValue($params,"file");
    eval('$file='.$file.';');
    $fileAddress=$this->completeTemplateAddressFromMainTemplate($file);
    /* make cache file if not exist */
    $this->_compile($fileAddress);
    /* get its cache file name */
    $cacheName=$this->_makeCacheName($fileAddress);
    $output="<?php include '$cacheName'; ?>";
    return $output;
  }

  /**
   * Assign Callback Methode
   * compile assign tags
   * @syntax {assign (name="var_name" value="var_value")}
   * @param  array $params
   * @param  string wholeParamsPar
   * @return string
   */
  function _compileAssignTag($params,$wholeParamsPar)
  {
    $varName=$this->_getParamValue($params,"name");
    $varValue=$this->_getParamValue($params,"value");
    $pluginFile=$this->pluginCompleteAddress('assign');
    $this->addHeaderIfNotExist("<?php include_once '$pluginFile'; ?>");
    $output="<?php gedar_assign_do($varName,$varValue,\$this); ?>";
    return $output;
  }

  /**
   * Cycle Callback Methode
   * compile Cycle tags
   * @syntax {cycle (name="name" elements="elm1,elm2,...")}
   * @param  array $params
   * @param  string wholeParamsPar
   * @return string
   */
  function _compileCycleTag($params,$wholeParamsPar)
  {
    $name=$this->_getParamValue($params,"name")?
      $this->_getParamValue($params,"name"):
      "'___DEFAULT__'";
    $elements=stripslashes($this->_getParamValue($params,"elements"));
    $pluginFile=$this->pluginCompleteAddress('cycle');
    $this->addHeaderIfNotExist("<?php include_once '$pluginFile'; ?>");
    $this->addHeaderIfNotExist("<?php \$this->_TplSpecialVars['_cycle']['$name']['elements']='".$this->_checkString($elements)."'; ?>");
    $output="<?php echo gedar_cycle_do('$name',\$this); ?>";
    return $output;
  }
  
  /**
   * Get Parameter Value
   * give a parameter array and an element name
   * and return the value of it if exists
   * @param string $params
   * @param string $elem
   * @return var
   */
  function _getParamValue($params,$elem)
  {
    if(!$params[$elem])
      return false;
    $val=$params[$elem];
    if(!trim($val))
      $val='""';
    $ret=stripslashes($this->_makeVariable($val));
    return $ret;
  }

  /**
   * Make Variable
   * make variable as template variable for
   * examplae $var -> $_TplVars['var']
   * i use tokenizer in default if loaded
   * @param string $expr
   * @return string
   */
  function _makeVariable($expr)
  {
    $tokens = @token_get_all($expr);
    foreach ($tokens as $key=>$token)
      {
	if (is_array($token))
	  {
	    if ($token[0]==T_VARIABLE)
	      $trans= @$token[1]!='$this' ? '$this->_TplVars["'.(substr($token[1],1)).'"]' : '$this';
	    else
	      $trans=$token[1];
	  }
	else
	  $trans=$token;
	@$return.=$trans;
      }
    return $return;
  }

  /**
   * Header Compiling Information
   * insert information about template comiling
   * time and date ,...
   *
   * @return true
   */
  function _templateComiplingHeaderInfo()
  {
    $this->addHeaderIfNotExist('<?php /* Established by : <Gedar Template Engine>'.
			       ' version ('.$this->_Gversion.')'
			       .', Created on '.date("Y-m-d").'@ '.date("H:i:s")
			       .' Compiled from '.$this->_TplFileName.' */ ?>');
  }

  /**
   * Add Line To Header
   * Add new line to header if there is
   * not exist
   * @param string $htxt
   * @return true
   */
  function addHeaderIfNotExist($htxt)
  {
    if(!in_array($htxt,$this->_outputTag['header']))
      $this->_outputTag['header'][]=$htxt;
  }

  /**
   * Is Expired Cache File
   * Check that cache file is expired
   * or it is validate
   * @param string fileName
   * @return bool
   */
  function cacheFileIsExpired($fileName)
  {
    $cacheFileName=$this->_TplCacheDirectory.$this->_makeCacheName($fileName);
    if (!file_exists($cacheFileName))
	return $this->_TplCacheWrite=true;
    else
      {
	switch ($this->_TplGenerationMode)
	  {
	  case "0":
	    $this->_TplCacheWrite=false;
	    break;
	  case "1":
	    if (filemtime($fileName)<filemtime($cacheFileName))
		$this->_TplCacheWrite=false;
	    else
		return $this->_TplCacheWrite=true;
	    break;
	  case "2":
	    if ( (time()-filemtime($cacheFileName)) < $this->_TplCacheLifeTime )
	      $this->_TplCacheWrite = false;
	    else
	      return $this->_TplCacheWrite = true;
	    break;
	  }
      }
    return $this->_TplCacheWrite;
  }

  /**
   * Make Cache File
   * Make a cache file in cache directory
   * the directory of cache file is one
   * that specified with $_TplCacheDirectory
   * note: $filename is filename with it`s
   * complete address
   * @param string $fileName
   * @param string $content
   * return bool
   */
  function makeCacheFile($fileName,$content)
  {
    $this->makeDirIfNotExist($this->_TplCacheDirectory,"0775");
    $this->makeDirectorySecure($this->_TplCacheDirectory);
    $cacheName = $this->_makeCacheName($fileName);
    return $this->_writeToFile($this->_TplCacheDirectory.$cacheName,$content);
  }

  /**
   * Make Directory If Not Exist
   * check is a directory exist and
   * make it if it wasnt exist
   * @param string $directory
   * @param string $mode
   * @return bool
   */
  function makeDirIfNotExist($directory,$mode)
  {
    $directory=$this->real_path($directory);
    if(@file_exists($directory))
      return true;
    $return = mkdir($directory);
    if(!$return)
      return false;
    return $this->changeFileMode($directory , $mode);
  }

  /**
   * Make Directory Secure
   * put an empty index.html file and a 
   * .htaccess into specified directory
   * and maked it out of overriding
   * @param string directory
   * @return bool
   */
  function makeDirectorySecure($directory)
  {
    $ret=$this->_writeToFile( $directory.".htaccess" , '<FilesMatch ".">'."\n".'order allow,deny'."\n".'deny from all'."\n".'</FilesMatch>');
    if(!$ret)
      return false;
    $ret=$this->_writeToFile( $directory."index.html" , '');    
    if(!$ret)
      return false;
    return true;
  }

  /**
   * Write to File
   * writting or appending content to
   * specefied file
   * @param string $file
   * @param string $content
   * @param bool   $append
   * @return bool
   */
  function _writeToFile($file,$content,$append=false)
  {
    $mode = $append ? "a+" : "w";
    $fh=fopen($file,$mode);
    $ret=fwrite($fh,$content);
    fclose($fh);
    return $ret;
  }

  /**
   * Read File Content
   * read content of file
   * @param string filename
   * @return string
   */
  function _readFile($file)
  {
    $fh=fopen($file,"r");
    $content = @fread($fh ,filesize($file));
    @fclose($fh);
    return $content;
  }

  /**
   * Change File Mode
   * change mode of file
   * @see CHMOD
   * @param string $path
   * @param string $mode
   * @return true
   */
  function changeFileMode($path,$mode)
  {
    $cmd = "chmod ('$path',$mode);";
    eval($cmd);
    return true;
  }

  /**
   * Assign Variable
   * Assign a value to a variable name
   * @param string $tplVarNamr
   * @param string $tplVarValue
   * @return true
   */
  function assign( $tplVarName , $tplVarValue )
  {
    if (is_array($tplVarName)){
      foreach ($tplVarName as $key => $val) {
	if ($key != '') {
	  $this->_TplVars[$val] = $tplVarValue[$key];
	}
      }
    } else {
      if ($tplVarName != '')
	$this->_TplVars[$tplVarName] = $tplVarValue;
    }
  }
  
  /**
   * Append to Variable Value
   * merge append new value to old value
   * @param string $tplVarName
   * @param string $tplVarValue
   * $return true
   */
  function append( $tplVarName , $tplVarValue )
  {
    if ( isset( $this->_TplVars[$tplVarName] ) )
      {
	$this->_TplVars[$tplVarName] .= $tplVarValue;
      }
    else
      {
	$this->_TplVars[$tplVarName] = $tplVarValue;
      }
  }

  /**
   * Clear Template Varaible Value
   * clear value of a template variable
   * @param string $tplVarName
   * @return true
   */
  function clearTemplateVariable( $tplVarName )
  {
    if (is_array($tplVarName))
      foreach ($tplVarName as $curr_var)
	unset($this->_Tpl_Vars[$curr_var]);
    else
      unset($this->_Tpl_Vars[$tpl_var]);
  }

  /**
   * Make Name For Cached File
   * This method makeing a name from a file with
   * path of itself, that can used for name of 
   * it`s cached file
   * @param string $filename
   * @return string
   */
  function _makeCacheName($fileName)
  {
    $templateFilename = str_replace('/','%%',$fileName);	/* this changes / in path to %% */
    return '^^'.$templateFilename.'.php';
  }

  /**
   * Real Path
   * return real path with same slashes in windows and unix styles platform
   * special thanx to carlosreche at yahoo dot com 
   * see complete information about realpath function in Manual 
   * @link http://www.php.net/manual/en/function.realpath.php
   * @param string $path
   * return string
   */
  function real_path($path)
  {
    if ($path == "")
      {
	return false;
      }
    $path = trim(preg_replace("/\\\\/", "/", (string)$path));
    if (!preg_match("/(\.\w{1,4})$/", $path)  &&  
	!preg_match("/\?[^\\/]+$/", $path)  &&  
	!preg_match("/\\/$/", $path))
      {
	$path .= '/';
      }
    $pattern = "/^(\\/|\w:\\/|https?:\\/\\/[^\\/]+\\/)?(.*)$/i";
    preg_match_all($pattern, $path, $matches, PREG_SET_ORDER);
    $path_tok_1 = $matches[0][1];
    $path_tok_2 = $matches[0][2];
    $path_tok_2 = preg_replace(
			       array("/^\\/+/", "/\\/+/"), 
			       array("", "/"), 
			       $path_tok_2);
    $path_parts = explode("/", $path_tok_2);
    $real_path_parts = array();
    for ($i = 0, $real_path_parts = array(); $i < count($path_parts); $i++)
      {
	if ($path_parts[$i] == '.')
	  {
	    continue;
	  }
	else if ($path_parts[$i] == '..')
	  {
	    if (  (isset($real_path_parts[0])  &&  $real_path_parts[0] != '..')
		  || ($path_tok_1 != "")  )
	      {
		array_pop($real_path_parts);
		continue;
	      }
	  }
	array_push($real_path_parts, $path_parts[$i]);
      }
    return $path_tok_1 . implode('/', $real_path_parts);
  }

  /**
   * Eval Command
   * get an expression and do it with 
   * php interpreter
   * @param string $cmd
   * @return true;
   */
  function _evalExp($cmd)
  {
    eval($cmd);
  }

  /**
   * Check String
   *
   * @param string $str
   * @return string
   */
  function _checkString($str)
  {
    if (!get_magic_quotes_gpc())
      $str=addslashes($str);
    return $str;
  }

  /**
   * Add New Unacceppted Word
   * add new censor keyword , when $censorShipEnable is
   * true in $this->show ,swap these word with swap word
   * @param string $cWord
   * @param string $sWord
   * @return true
   */
  function _addCensorWord($cWord,$sWord)
  {
    $_TplSpecialVars["_censor"][]=array("censor"=>$cWord,"swap"=>$sWord);
  }

  /**
   * Add New Unicode Transferring
   *
   * @param string $from
   * @param string $to
   * @return true
   */
  function _addUnicodeConverting($from,$to)
  {
    $_TplSpecialVars["_unicode"][]=array("from"=>$from,"to"=>$to);
  }

  /**
   * Show Translated Template
   * return the translated template,
   * gzEnable send external as gz output buffer
   * captureFile send external print to file
   * $censorShip enable censoring output according
   * to $this->_censorWord
   * @param bool $gzEnable
   * @param string|bool $captureFile
   * @param bool $censorShipEnable
   * @param bool $unicodeConver
   * @return var
   */
  function show($gzEnable=false,$captureFile=false,$censorShipEnable=false,$unicodeConvert=false)
  {
    $srcFile = $this->_TplDirectory.$this->_TplFileName;
    $this->_compile($srcFile);
    $cacheName = $this->_TplCacheDirectory.$this->_makeCacheName( $this->_TplDirectory.$this->_TplFileName );
    if($captureFile && trim($captureFile)>"")
      {
	$this->_capture($captureFile,$censorShipEnable,$unicodeConvert);
	return true;
      }
    else
      {
	$content = $this->_fetch($gzEnable,$censorShipEnable,$unicodeConvert);
	print($content);
	return true;
      }
  }

  /**
   * Capture OutPut
   * Capture output of translated source to 
   * specefic file
   * @param string $file
   * @param bool $censorShipEnable
   * @param bool $unicodeConver
   * $return true
   */
  function _capture($file,$censorShipEnable,$unicodeConvert)
  {
    $content = $this->_fetch(false,$censorShipEnable,$unicodeConvert);
    $file=$this->real_path(GEDAR_MAINDIR.$file);
    $this->_writeToFile($file,$content);
    return true;
  }

  /**
   * Fetch Output
   * get output buffer
   * @param bool $gzEnable
   * @param bool $censorShipEnable
   * @param bool $unicodeConver
   * @return string
   */
  function _fetch($gzEnable=false,$censorShipEnable,$unicodeConvert)
  {
    $srcFile=$this->_TplDirectory.$this->_TplFileName;
    $cacheName = $this->_TplCacheDirectory.$this->_makeCacheName($srcFile);
    /* start buffering ... */    
    if($gzEnable)
      ob_start('ob_gzhandler');
    else
      ob_start();
    include $cacheName;
    $content = ob_get_contents();
    ob_end_clean(); /* finish buffering.   */
    /* censorshiping... */
    if($censorShipEnable)
      {
	foreach($_TplSpecialVars['_censor'] as $censor)
	  {
	    $content=str_replace($censor["censor"],$censor["swap"],$content);
	  }
      }
    if($unicodeConvert)
      {
	foreach($_TplSpecialVars['_unicode'] as $unicode)
	  {
	    $content=iconv($unicode['from'],$unicode['to'],$content);
	  }
      }
    return $content;
  }
}
?>
Return current item: Gedar Template Engine