<?php

/**
	* File: iZzxTemplate.php 此文件为引擎入口.
	*
	* 提示 false == 0  // true == 1   (可以互写)
	*
	*
	* 感谢您使用本程序
	*
**/

class iZzxTemplate
{
		/* 定义模板 目录/后缀名 */
	var $iZzxTemplate_Dir = array();
	var $iZzxTemplate_End = '.html';
	
	/* 定义解析 标示 */
	var $iZzxTemplate_Left = '{';
	var $iZzxTemplate_Right = '}';
	
	/* 定义模板缓存目录  */
	var $Cache_Dir = 'Cache';
	var $Cache_End = '.iQQol_template_c';
	
	/* 定义模板输出缓存 是否输出/目录/后缀名/缓存时间  */
	var $iZzxTemplate_Output_Is = false;
	var $iZzxTemplate_Output_Dir = 'Output_Cache';
	var $iZzxTemplate_Output_End = '.phpx_o';
	var $iZzxTemplate_Output_Time = 0; // 单位 秒
	var $iZzxTemplate_CName = ''; // 缓存标示符 ( 有效防止无效缓存 )
	
	/* 定义是否运行模板内插入PHP代码  */
	var $iZzxTemplate_PHP_off = true;
	
	/* 是否持续编译模板 */
	var $iZzxTemplate_PHP_Conver = false;
	
	/* 类所在目录  (将自行读取)  */
	var $iZzxTemplate_Tdir = '';
	
	/* 所创建目录的权限  */
	var $iZzxTemplate_Dir_Mode = 0777;
	
	/* 限制模板文件的大小 */
	var $iZzxTemplate_File_Max = 3; // 单位 M
		
	/* 类变量调用  */
	var $iZzxTemplate_ClassName = '';

	/* 模板变量资源管理  */
	var $iZzxTemplate_Global_Var = array();
	
	/* 类运行时间  */
	var $iZzxTemplate_Runtime = 0; // 单位 微妙
	
	/* 类内部变量储存 */
	var $iZzxTemplate_array_var = array();
	
	/* 快捷语言包 */
	var $lang_array = array();

	/* 模板编译信息提示 默认中文 ( 如果特定语言包存在,将自动读取 ) */
	var $iZzxTemplate_Class_Lang = array(
																			' 模板文件不存在或读取失败',
																			' 模板文件大小超出限制',
																			' 模板文件没有正常加载',
																			'严重错误',
																			'程序警告',
																			'语法错误',
																			'文件名称',
																			'错误等级',
																			'错误所在',
																			'错误信息',
																			'缓存文件路径',
																			'错误源产生在',
																			'行'
																		);



	/* PHP5 初始化类  */
	
	function __construct($setArray = array())
	{
		$this->iZzxTemplate($setArray);
	}
	
	/*
		初始化
						类所在目录
						文件大小限制
						取得当前类名称
						自动读取语言包
						初始类运行时间
	*/
	/* 初始化类  */
	function iZzxTemplate($setArray = array())
	{
		/* 获取当前类所在目录  */  
		$this->iZzxTemplate_Tdir = dirname(str_replace('\\','/',__FILE__));
		
		/* 获取当前类名称 (防止类名称修改,导致报错机制失败) */  
		$this->iZzxTemplate_ClassName = __CLASS__;
		
		/* 类被初始化时 自动读取语言包 (并判断语言包是否有效)  */
		global $_iZzxTemplate_Class_Lang;
		if (is_array($_iZzxTemplate_Class_Lang)) 
		{
			$this->iZzxTemplate_Class_Lang += $_iZzxTemplate_Class_Lang;
		}
		
		/* Array 设置模板引擎参数 */
		$this->setArray($setArray);
			
	}
	
	/* 以数组形式设置模板引擎参数 */
	function setArray($setArray)
	{
		if (!is_array($setArray)) return false;
		
		foreach ($setArray as $key=>$val)
		{
			eval('$this->'.$key.' = $val;');
		}
		
		return true;
	}
	
	/* 向模板引擎中注入变量 */
	function assign($key,$val = null)
	{
		if (empty($key)) return '';
		if (is_array($key))
		{
			foreach ($key as $k=>$v)
			{
				$this->iZzxTemplate_array_var[$k] = $v;
			}
		}else{
			$this->iZzxTemplate_array_var[$key] = $val;	
		}

	}
	
	/* 取得变量值 */
	function & iZzxTemplate_getv($key)
	{
		if (isset($this->iZzxTemplate_array_var[$key]))
		{
			return $this->iZzxTemplate_array_var[$key];
		}else{
			global $$key;
				if ($$key)
				{
					$this->assign($key,$$key);
				}
				return $$key;
		}
	}
	
	/* 获取模板路径 */
	function get_iZzxTemplate_path($iZzxTemplate_Name)
	{
		if (!is_array($this->iZzxTemplate_Dir))
		{
			$this->iZzxTemplate_Dir = (array)$this->iZzxTemplate_Dir;
		}
		
		$count = count($this->iZzxTemplate_Dir);
		
		for ($i=0; $i< $count ; $i++)
		{
			$p = $this->iZzxTemplate_Dir[$i].'/'.$iZzxTemplate_Name.$this->iZzxTemplate_End;
			if (file_exists($p))
			{
				return $p;
			}
		}
	}
	
	/* 获取模板缓存路径 */
	function get_Cache_path($iZzxTemplate_Name)
	{
		$iZzxTemplate_Name = $this->get_iZzxTemplate_Name($iZzxTemplate_Name);
		
		return $this->iZzxTemplate_Tdir.'/'.$this->Cache_Dir.'/'.$iZzxTemplate_Name.$this->iZzxTemplate_End.$this->Cache_End;
	}
	
	function get_iZzxTemplate_output_path($iZzxTemplate_Name, $type = false)
	{
		$iZzxTemplate_Name = $this->get_iZzxTemplate_Name($iZzxTemplate_Name);
		
		return $this->iZzxTemplate_Tdir.'/'.$this->iZzxTemplate_Output_Dir.'/'.($type ? '' : $this->iZzxTemplate_CName).$iZzxTemplate_Name.$this->iZzxTemplate_End.$this->iZzxTemplate_Output_End;
	}
	
	/* 获取处理后的模板标签 */
	function get_iZzxTemplate_Name($iZzxTemplate_Name)
	{
		if (eregi('/',$iZzxTemplate_Name))
		{
			$iZzxTemplate_Name = str_replace('/','{(_iZzxTemplate_)}',$iZzxTemplate_Name);
		}
		
		return md5($this->get_iZzxTemplate_path($iZzxTemplate_Name)).$iZzxTemplate_Name;
	}
	
	/* 输出模板 */
	function display($iZzxTemplate_Name,$display = 'display',$Clean = 0)
	{
		return $this->iZzxTemplate_Display($iZzxTemplate_Name,$Clean,$display);
	}
	
	/* 输出模板 */
	function iZzxTemplate_Display($iZzxTemplate_Name,$Clean = 0,$display = '')
	{
		
		/* 引擎运行时间统计  */
		$this->iZzxTemplate_Runtime = $this->iZzxTemplate_microtime();
		
		if ($this->iZzxTemplate_Output_Is)
			$_PATH = $this->get_iZzxTemplate_output_path($iZzxTemplate_Name);
		
		if (!$this->Is_cache($iZzxTemplate_Name) || $Clean)
		{	
			/* 将错误载入特定函数处理  */
			if ($this->iZzxTemplate_Compatible)
			{
				ob_start();
			}else{
				ob_start(array(new $this->iZzxTemplate_ClassName,'iZzxTemplate_xError'));
			}
			/* 进行模板编译   */
					include $this->iZzxTemplate_Conver($iZzxTemplate_Name,$Clean);
							
					$iZzxTemplate_Content = ob_get_contents();
				ob_end_clean();

		}else{
			/* 读取缓存输出文件 */
			$iZzxTemplate_Content = $this->iZzxTemplate_read($_PATH);
		}

			 /* 判断是否可以写入缓存输出内容  */
			if ($this->iZzxTemplate_Output_Is)
			{
				/* 判断缓存输出是否有效 */
				if (!$this->Is_cache($iZzxTemplate_Name))
					$this->iZzxTemplate_write($_PATH,$iZzxTemplate_Content);
			}
			

			switch ($display)
			{
				case 'display':
						echo $iZzxTemplate_Content;
						
						$iZzxTemplate_Content = null;
				break;
			}

			/* 变量占用资源释放  */
			if (is_array($this->iZzxTemplate_array_var))
			foreach ($this->iZzxTemplate_array_var as $key=>$val)
			{
				if (isset($$key)) unset($$key);
			}
			
			$this->iZzxTemplate_array_var = null;
		
			/* 返回执行时间 */
		$this->iZzxTemplate_Runtime();
		
		return $iZzxTemplate_Content;
	}
	
	/* 读取文件 */
	function iZzxTemplate_read($PATH)
	{
		if (function_exists('file_get_contents'))
		{
			return file_get_contents($PATH);
		}else{
			$fopen = fopen($PATH,'r');
			$iZzxTemplate_content = '';
			do {
				$data = fread($fopen,1024);
				if (strlen($data)===0) break;
				$iZzxTemplate_content .= $data;
			}while(1);
			fclose($fopen);
			
			return $iZzxTemplate_content;
		}
	}
	
	/* 写入文件 */
	function iZzxTemplate_write($PATH,$String)
	{
		/* 调用递归创建目录  */
		$this->iZzxTemplate_createdir(dirname($PATH));

			/* 以写入方式打开文件句柄,开启 flock  */
			$fopen = fopen($PATH,'w');
				flock($fopen, LOCK_EX + LOCK_NB);
				$fwrite = fwrite($fopen,$String);
					/* 失败重新尝试写入  */
					if (!$fwrite) $fwrite = fwrite($fopen,$String);
				flock($fopen, LOCK_UN + LOCK_NB);
			fclose($fopen);

		return $fwrite;
	}
	
	/* 循环创建目录 */
	function iZzxTemplate_createdir($Dir)
	{
		if (is_dir($Dir))
		 return true;
		 
		if (mkdir($Dir, $this->iZzxTemplate_Dir_Mode))
			return true;
		
		if (!$this->iZzxTemplate_createdir(dirname($Dir)))
		 return false;
		
		return mkdir($Dir,$this->iZzxTemplate_Dir_Mode);
	}
	
	/* 转换标示符 */
	function iZzxTemplate_converTag($Tag)
	{
		$_count = strlen($Tag);
		$new_array = array('{','}','[',']','$','(',')','*','+','.','?','\\','^','|');
		$Tag_ = '';
		for ($i=0;$i<$_count;$i++)
		{
			$Tag_ .= (in_array($Tag[$i],$new_array)?'\\':'').$Tag[$i];
		}
		return $Tag_;
	}
	
	function iZzxTemplate_microtime()
	{
		list($microtime_1,$microtime_2) = explode(' ',microtime());
		return $microtime_1 + $microtime_2;
	}
	
	/* 判断缓存输出是否有效/是否开启缓存输出  */
	function Is_cache($iZzxTemplate_Name)
	{
		$_PATH = $this->get_iZzxTemplate_output_path($iZzxTemplate_Name);
		if (!file_exists($_PATH))
		{
			return false;
		}elseif (filemtime($_PATH) + $this->iZzxTemplate_Output_Time < time()){
			return false;
		}else{
			return true;
		}
	}
	
	/* 模板引擎编译 */
	function iZzxTemplate_conver($iZzxTemplate_Name,$Clean = 0)
	{
		$_PATH = array();

		/* 取得有效模板路径  */
		$_PATH['From'] =  $this->get_iZzxTemplate_path($iZzxTemplate_Name);
		$_PATH['Save'] =  $this->get_Cache_path($iZzxTemplate_Name);
		
		/* 判断模板文件是否存在 */
		if (!file_exists($_PATH['From'])) return $_PATH['From'].' {'.$iZzxTemplate_Name.$this->iZzxTemplate_Class_Lang[0].'}';

		/* 判断模板缓存文件是否需要更新  */
		if ($this->iZzxTemplate_PHP_Conver) $Clean = 1;
		
		if (!$Clean)
		{
			if (file_exists($_PATH['From']))
				$_fromt = filemtime($_PATH['From']);
			if (file_exists($_PATH['Save']))
				$_savet = filemtime($_PATH['Save']);

			if ($_fromt <= $_savet)
			{
				return $_PATH['Save'];
			}
		}
		
		/* 判断模板文件大小限制 */
		if (filesize($_PATH['From']) > $this->iZzxTemplate_File_Max * 1024 * 1024) return $this->iZzxTemplate_Error($iZzxTemplate_Name.$this->iZzxTemplate_Class_Lang[1].' ('.$this->iZzxTemplate_File_Max.' M)');
		
		/* 取得有效标示  */
		$_Left = '(?<!!)'.$this->iZzxTemplate_converTag($this->iZzxTemplate_Left);
		$_Right = '((?<![!]))'.$this->iZzxTemplate_converTag($this->iZzxTemplate_Right);
		
		/* 取得模板源 */
		$iZzxTemplate_Conver = $this->iZzxTemplate_read($_PATH['From']);

		/* 如果模板为空,不进行编译 */
		if (empty($iZzxTemplate_Conver))
		{
			$this->iZzxTemplate_write($_PATH['Save'],$iZzxTemplate_Conver);
			return $_PATH['Save'];
		}
		
		/* **************模板进行相关编译起始******************* */
			/*
				Start// write by xbantu 2009-06-06
			*/
		$iZzxTemplate_Conver = trim($iZzxTemplate_Conver);
		
		preg_match_all('/'.$_Left.'iZzxTemplate (([\w|-|\/]{1,})|(\$([_a-zA-Z][\w]+)))'.$_Right.'/',$iZzxTemplate_Conver,$Include_);
		$Include_count = count($Include_[0]);
		
			/* 模板文件嵌套调用处理  */
		for ($i=0;$i< $Include_count;$i++)
		{
			/* 编译相应调入模板文件 */
			$iZzxTemplate_Conver = str_replace($Include_[0][$i],$this->iZzxTemplate_Left.'eval include $this->iZzxTemplate_conver("'.$Include_[1][$i].'")'.$this->iZzxTemplate_Right,$iZzxTemplate_Conver);
			
			/* 2009-06-07 放弃使用模板状态提示 */
			/*
				// 提示模板文件加载状态  
				$Include_Tmp_Name = $this->get_iZzxTemplate_path($Include_[1][$i]);	
				$iZzxTemplate_Conver = str_replace($Include_[0][$i],$this->iZzxTemplate_Left.' '.$Include_[1][$i].$this->iZzxTemplate_Class_Lang[2].$this->iZzxTemplate_Right,$iZzxTemplate_Conver);				
			*/
		}
		unset($Include_);
			
		 /* 获取模板所使用变量 */
		preg_match_all('/\$([_a-zA-Z][\w]+)/',$iZzxTemplate_Conver,$Global_var);

		if (is_array($Global_var[1]))
		{	
			$Global_var[1] = array_unique($Global_var[1]);

			$Global_var_Im = array('this','_GET','_POST','_COOKIE','_SERVER','_SESSION','_FILES','_ENV');
			$Global_var_out = '';

			foreach ($Global_var[1] as $val)
			{
				if (!in_array($val,$Global_var_Im))
				{
					$Global_var_out .= '$'.$val.' =& $this->iZzxTemplate_getv(\''.$val.'\'); ';

				}
			}
		}

		 /* 相关标签转换 */
		$Template_preg = array();
		$Template_Replace = array();

		 /* 判断是否允许插入PHP  */
		if ($this->iZzxTemplate_PHP_off === false)
		{
			$iZzxTemplate_Preg[] = '/<\?(=|php|)(.+?)\?>/is';
			
			$iZzxTemplate_Replace[] = '&lt;?\\1\\2?&gt;';
		}

			/*
			此类编译的语法
			_if 
			_elseif
			_else
			_for
			_while
			_foreach
			_eval
			_echo
			_print_r
			_变量输出
			*/ 
			
		$iZzxTemplate_Preg[] = '/'.$_Left.'(else if|elseif) (.*?)'.$_Right.'/i'; 
		$iZzxTemplate_Preg[] = '/'.$_Left.'for (.*?)'.$_Right.'/i'; 
		$iZzxTemplate_Preg[] = '/'.$_Left.'while (.*?)'.$_Right.'/i'; 
		$iZzxTemplate_Preg[] = '/'.$_Left.'(loop|foreach) (.*?)'.$_Right.'/i'; 
		$iZzxTemplate_Preg[] = '/'.$_Left.'if (.*?)'.$_Right.'/i'; 
		$iZzxTemplate_Preg[] = '/'.$_Left.'else'.$_Right.'/i'; 
		$iZzxTemplate_Preg[] = '/'.$_Left."(eval|_)( |[\r\n])(.*?)".$_Right.'/is';
		$iZzxTemplate_Preg[] = '/'.$_Left.'_e (.*?)'.$_Right.'/is';
		$iZzxTemplate_Preg[] = '/'.$_Left.'_p (.*?)'.$_Right.'/i';
		$iZzxTemplate_Preg[] = '/'.$_Left.'\/(if|for|loop|foreach|eval|while)'.$_Right.'/i'; 
		$iZzxTemplate_Preg[] = '/'.$_Left.'(([_a-zA-Z][\w]*\(.*?\))|\$((\w+)(\[(\'|")?\$*\w*(\'|")?\])*(->)?(\w*)(\((\'|")?(.*?)(\'|")?\)|)))'.$_Right.'/i'; 
		$iZzxTemplate_Preg[] = "/(	| ){0,}(\r\n){1,}\";/"; 
		$iZzxTemplate_Preg[] = '/'.$_Left.'(\#|\*)(.*?)(\#|\*)'.$_Right.'/'; 
		$iZzxTemplate_Preg[] = '/'.$_Left.'\%([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)'.$_Right.'/';


			/* 编译为相应的PHP文件语法 _所产生错误在运行时提示  */
		$iZzxTemplate_Replace[] = '<?php }else if (\\2){ ?>';
		$iZzxTemplate_Replace[] = '<?php for (\\1) { ?>';
		$iZzxTemplate_Replace[] = '<?php while (\\1) { ?>';
		$iZzxTemplate_Replace[] = '<?php foreach (\\2) { ?>';
		$iZzxTemplate_Replace[] = '<?php if (\\1){ ?>';
		$iZzxTemplate_Replace[] = '<?php }else{ ?>';
		$iZzxTemplate_Replace[] = '<?php \\3; ?>';
		$iZzxTemplate_Replace[] = '<?php echo \\1; ?>';
		$iZzxTemplate_Replace[] = '<?php print_r(\\1); ?>';
		$iZzxTemplate_Replace[] = '<?php } ?>';
		$iZzxTemplate_Replace[] = '<?php echo \\1;?>';
		$iZzxTemplate_Replace[] = '';
		$iZzxTemplate_Replace[] = '';
		$iZzxTemplate_Replace[] = '<?php echo $this->lang_array[\'\\1\'];?>';

		
		  /* 在有必要时 开启 */  
		//ksort($iZzxTemplate_Preg);
		//ksort($iZzxTemplate_Replace);
				
			/* 执行正则分析编译 */
		$iZzxTemplate_Conver=preg_replace($iZzxTemplate_Preg,$iZzxTemplate_Replace,$iZzxTemplate_Conver);
		
			/* 过滤敏感字符 */ 
		$iZzxTemplate_Conver = str_replace(array('!'.$this->iZzxTemplate_Right,'!'.$this->iZzxTemplate_Left,'?><?php'),array($this->iZzxTemplate_Right,$this->iZzxTemplate_Left,''),$iZzxTemplate_Conver);

			/* 整理输出缓存内容  */
		if ($Global_var_out)
		{
			$iZzxTemplate_Conver = "<?php $Global_var_out ?>\r\n".$iZzxTemplate_Conver;
		}
		
		$this->iZzxTemplate_write($_PATH['Save'],$iZzxTemplate_Conver);
		
		/*
			End conver;
		*/
		/* ***************模板进行相关编译结束******************** */
		
		return $_PATH['Save'];

	}
	
	/* 类错误信息输出 */
	function iZzxTemplate_Error($Msg)
	{
		echo $Msg;
		
		/*exit;*/
	}
	
	/* 模板错误输出 */
	function iZzxTemplate_xError($_iZzxTemplate_error)
	{
		/* 获取最后一次错误记录 */
		$_iZzxTemplate_error_ = error_get_last();
    $_iZzxTemplate_error = array();
    
    /* 判断是否重要错误信息 */
    switch ($_iZzxTemplate_error_['type'])
    {
    	case 1: $_iZzxTemplate_error['type'] = $this->iZzxTemplate_Class_Lang[3];
    	case 2: $_iZzxTemplate_error['type'] = $this->iZzxTemplate_Class_Lang[4];
    	case 4: $_iZzxTemplate_error['type'] = $this->iZzxTemplate_Class_Lang[5];
    	default:
    		$_iZzxTemplate_error['type'] = '1';
    }
    
    /* 错误信息格式化 */
    if ($_iZzxTemplate_error['type'])
    {
    	$_iZzxTemplate_error['body'] = file($_iZzxTemplate_error_['file']);
    	
    	$_iZzxTemplate_error['err_'] = "<meta http-equiv=Content-Type content=\"text/html;charset=utf-8\"><font size=2 color=#333333>\r\n";
    	$_iZzxTemplate_error['err_'] .= "[iZzxTemplate] <br /><br />\r\n";
    	$_iZzxTemplate_error['err_'] .= $this->iZzxTemplate_Class_Lang[6].': '.str_replace($this->Cache_End,'',basename($_iZzxTemplate_error_['file']))."<br />\r\n";
    	$_iZzxTemplate_error['err_'] .= $this->iZzxTemplate_Class_Lang[7].': '.$_iZzxTemplate_error['type']."<br />\r\n";
    	$_iZzxTemplate_error['err_'] .= $this->iZzxTemplate_Class_Lang[8].': '.htmlspecialchars($_iZzxTemplate_error['body'][$_iZzxTemplate_error_['line']-1])."<br />\r\n";
    	$_iZzxTemplate_error['err_'] .= $this->iZzxTemplate_Class_Lang[9].': '.$_iZzxTemplate_error_['message']."<br /><br />\r\n";
    	$_iZzxTemplate_error['err_'] .= "</font><font size=2 color=#999999>\r\n";

    	$_iZzxTemplate_error['err_'] .= $this->iZzxTemplate_Class_Lang[10].': {SERVER_PATH}/'.$this->Cache_Dir.'/'.basename($_iZzxTemplate_error_['file'])."<br />\r\n";
    	$_iZzxTemplate_error['err_'] .= $this->iZzxTemplate_Class_Lang[11].': '.$_iZzxTemplate_error_['line']." {$this->iZzxTemplate_Class_Lang[12]}<br />\r\n";
    	$_iZzxTemplate_error['err_'] .= "</font>\r\n";
    }

    return $_iZzxTemplate_error['err_'];
	}
	
	/* 清理缓存输出 或缓存 */
	function iZzxTemplate_clean($type = 'output')
	{
		
		switch ($type)
		{
			/* 判断是否是缓存输出 */
			case 'output':
				$_PATH = dirname($this->get_iZzxTemplate_output_path('_'));
				$_END = $this->iZzxTemplate_Output_End;
			
				$_PATH_ = glob($_PATH.'/*'.$_END);
			break;
			
			/* 判断是否是模板缓存 */
			case 'cache':
				$_PATH = dirname($this->get_Cache_path('_'));
				$_END = $this->Cache_End;
			
				$_PATH_ = glob($_PATH.'/*'.$_END);
			break;
		}
		
		 /* 判断是否是模板缓存 */
		if (!empty($type) && empty($_PATH))
		{
			$_PATH = $this->get_iZzxTemplate_output_path($type, true);
			
			$_PATH_ = glob($_PATH);
		}
		
		if ($_PATH_)
		{
			
			if (is_array($_PATH_))
			{
				$j = 0;
				foreach ($_PATH_ as $val)
				{
					if (file_exists($val))
					{
						unlink($val);
						$j ++;
					}
				}
				return $j;
			}else{
				return false;
			}
		}
		
		return false;
	}
	
	/* 获取实时模板引擎运行时间 */
	function iZzxTemplate_Runtime()
	{
		/* 返回执行时间 */
		return $this->iZzxTemplate_Runtime = round($this->iZzxTemplate_microtime() - $this->iZzxTemplate_Runtime,5);
	}

	
	//类结束

}

?>