<?php
/**
 * Copyright 2007-2009 by picphp.cn itprato
 * 蓝梦专业图片管理系统模板引擎 ver 1.00
 * 开发人 lmpic
 */
/*----------------------------------------------

LMPIC Tag模板解析引挚 1.00 版
最后修改日期 2009-4-21 PHP版本要求：大于或等于php 5.1
---------------------------------------------*/
class Template_Core{
	//数据缓存目录
	public $cache_dir;
	//左边定界符
	public $left_delimiter	=	"{";
	//右边定界符
	public $right_delimiter	=	"}";
	public $specialTag		=	array(
	"conlist",		//内容列表
	"channel",		//频道列表
	"catlist",		//分类列表
	"hottags",		//热门标签
	"search",		//全站搜索
	"imgdemo",		//图片展示
	"flink",		//友情连接
	"lists",		//列表
	"pagelist",		//分页列表
	"catlist",		//分类列表
	"attachments",	//附件列表
	"navbar",		//导航栏
	"alonepage",	//页面列表
	);
	public $page			=	10;
	public $pagesize		=	false;
	public $content;
	public $cacheData;
	/**
	 * 始始化模板
	 */
	function __construct(){
		$this->cache_dir	=	DATADIR.'cache/';
		$this->html			=	new Html_Model();
	}
	/**
	 * 渲染模板
	 * path 模板路径
	 * outpath 输出页面路径
	 */
	function  render($path){
		$this->_path			=	$path;
		$this->cachePath();
		//模板数据
		$this->sourceHtml	=	$this->getSourceHtml();
		$this->compile();
		$this->exeTpl();
	}
	function save($tplpath,$savePath=false){
		$this->_path			=	$tplpath;
		$this->cachePath();
		//模板数据
		$this->sourceHtml	=	$this->getSourceHtml();
		ob_start();
		$this->compile();
		$this->exeTpl();
		$htmlcode			=	ob_get_contents();
		ob_end_clean();
		file::create_dir_path(dirname($savePath));
		file_put_contents($savePath,$htmlcode);
		unset($htmlcode);
		return true;
	}
	//载入编译数据
	function defineLoad($path){
		$this->_path			=	$path;
		//模板数据
		$this->cachePath();
		if(!file_exists($this->_cachedatapath)){
			$this->sourceHtml		=	$this->getSourceHtml();
			$this->compile();
		}
		$data		=	include $this->_cachedatapath;
		if(is_array(@$data))
		foreach ($data as $key=>$value) {
			$this->$key		=	$value;
		}
	}
	function cachePath(){
		$this->cachePath	=	$this->cache_dir.base64_encode(dirname($this->_path)).basename($this->_path);
		$this->_cachedatapath	=	$this->cache_dir.base64_encode(dirname($this->_path)).basename($this->_path).".inc";
	}
	function exeTpl(){
		include $this->cachePath;
	}
	/**
	 * 编译模板
	 */
	function compile(){
		$this->resetVar();
		//模板规则
		/*** 全局变量*/
		$find[]		=	'#{\s*global\s*:\s*([a-z0-9_]+)\s*}#ie';
		$replace[]	=	"'<?php echo '.strtoupper('\\1').';?>'";

		//PHP代码
		$find[] 	= 	'#{\s*php\s*}\s*(.+?)\s*{\s*/\s*php\s*}#is';
		$replace[] 	= 	'<?php $1 ?>';

		// 处理特殊方法标记
		$find[] 	= 	'#({\s*lm\s*:\s*)([a-z]+)\s*(.*?\s*)}#ie';
		$replace[]	=	'"$1$2 ".$this->trimArray(\'$3\')."}"';
		$find[] 	= 	'#{(\s*lm\s*:\s*)([a-z]+)\s*(.*?)(\s*)}#ie';
		$replace[] 	= 	'$this->compileTag( "$2" , \'$3\' );';
		$find[] 	= 	'#{\s*/lm:[a-z]+\s*}#i';
		$replace[] 	= 	'<?php }?>';
		$find[]		=	'#{\s*([a-z0-9_]+)\s*\.\s*([a-z0-9_]+)\s*}#i';
		$replace[]	=	"<?php echo \$\\1->\\2;?>";
		$find[]		=	'#{\s*(.+)\s*\[\s*([a-z_]+\s*)\s*\]\s*}#i';
		$replace[]	=	'<?php echo \$\\1["\\2"];?>';
		$find[]		=	'#{\s*(.+)\s*\[\s*([0-9]+)\s*\]\s*}#i';
		$replace[]	=	'<?php echo \$\\1[\\2];?>';

		/************if处理*****************/
		$find[] 	= 	'#{\s*if\s+([^}]+)\s*}#ie';
		$replace[] 	= 	"'<?php if ('.\$this->ifstring('$1').') {?>'";

		$find[] 	= 	'#{\s*else\s*}#i';
		$replace[] 	= 	'<?php }else{ ?>';

		$find[] 	= 	'#{\s*else\s*if\s+?([^}]+)\s*}#i';
		$replace[] 	= 	'<?php }elseif ($1){?>';

		$find[] 	= 	'#{\s*/if\s*}#i';
		$replace[] 	= 	'<?php } ?>';

		//处理直接变量
		$find[]		= 	'#{\s*([@]*)\s*\$([a-z0-9_]+)\s*}#i';
		$replace[]	=	'<?php echo \\1$this->\\2;?>';
		$find[]		= 	'#{\s*([@]*)\s*\$([a-z0-9_]+)\s*\.\s*([a-z0-9_]+)\s*}#i';
		$replace[]	=	'<?php echo \\1$this->\\2->\\3;?>';

		//处理自定义函数
		$find[]		=	"#{\s*function:\s*([a-z]+)\s*\((.*)\)\s*}#ie";
		$replace[]	=	'"{function:\\1(".$this->trimArray(\'\\2\').")}"';
		$find[]		=	"#{\s*function:\s*([a-z]+)\s*\((.*)\)\s*}#ie";
		$replace[]	=	'$this->funRun("$1",\'$2\');';

		//处理字段
		$find[]		=	"#{\s*([@]*)\s*field\s*:\s*([a-z0-9_]+)\s*}#i";
		$replace[]	=	"<?php echo \\1\$this->content->\\2;?>";
		$find[]		=	"#'field\s*:\s*([a-z0-9_]+)'#i";
		$replace[]	=	'$this->content->\\1';	
		//广告
		$find[]		=	"#{\s*myad\s*:\s*([0-9]*)\s*}#i";
		$replace[]	=	"<script language='javascript' src='".BASEURL."data/cache/ad$1.js'></script>";
		
//		替换样式表
		$find[]		=	"#(<\s*link\s+.*href\s*=\s*[\'\"])(.*\.css)\S*([\'\"])#ie";
		$replace[]	=	'"$1".$this->linkcss("$2")."$3"';
		
//		替换图片地址
		$find[]		=	"#(<\s*img\s+.*src=[\'\"])(.*\.[a-z]+)([\'\"])#ie";
		$replace[]	=	'"$1".$this->linkimg("$2")."$3"';

//		LOOP
		if($this->checkCompile()){
			//包含文件
			$this->sourceHtml	=	$this->includeTpl($this->sourceHtml);
			$this->compileHtml	=	preg_replace($find,$replace,$this->sourceHtml);
			//编译完成后，保存为PHP文件
			$cachefp	=	fopen($this->cachePath,"w");
			fwrite($cachefp,$this->compileHtml);
			fclose($cachefp);
			file_put_contents($this->_cachedatapath,"<?php \r\n return ".var_export($this->cacheData,true)."\r\n?>");
		}
	}
	/**
	 * 包含文件
	 */
	function includeTpl($html){
		$includeFind		=	"#{\s*include\s*file\s*=\s*[\'|\"]\s*(.+)\s*[\'|\"]\s*}#ie";
		$includeReplace		=	'$this->getExntedTpl("$1");';
		return preg_replace($includeFind,$includeReplace,$this->sourceHtml);
	}
	//获取扩展模板
	function getExntedTpl($path){
		$incPath			=	str_replace(" ","",dirname($this->_path)."/".$path);
		if(file_exists($incPath)){
			$this->cacheData['incpath'][]		=	$incPath;
			return file_get_contents($incPath);
		}
		else{
			die("包含文件：".$incPath." 不存在。");
		}
	}
	/**
	 * 检查是否需要编译
	 */
	function checkCompile(){
		if(file_exists($this->_cachedatapath)){
			$data	=	include $this->_cachedatapath;
			if(is_array(@$data['incpath']))
			foreach($data['incpath'] as $path){
			if(@filemtime( $this->cachePath ) < filemtime( $path )){
					return true;
				}
			}
		}
		if(@filemtime( $this->cachePath ) < filemtime( $this->_path )){
			return true;
		}
		
		return false;
	}
	function getSourceHtml(){
		if(!file_exists($this->_path)){
			if($this->_path==''){
				die("未指定模板文件");
			}
			else{
				die("找不到指定的模板文件-".$this->_path);
			}
		}
		return file_get_contents($this->_path);
	}
	function trimArray($strTag=""){
		$strTag	=	stripslashes($strTag);
		$strTag	=	preg_replace("#\s+#"," ",$strTag);
		$strTag	=	preg_replace("#=\s+#","=",$strTag);
		$strTag	=	preg_replace("#\s+#",",",$strTag);
		$strTag	=	preg_replace("#=#","=>",$strTag);
		$strTag	=	preg_replace("#['\"*]#","",$strTag);
		$strTag	=	preg_replace('/[^=!=<=>=<>,*]+/','\'$0\'',$strTag);
		$strTag	=	preg_replace('/\'([0-9]+)\'/','$1',$strTag);
		$strTag	=	preg_replace('/([0-9]+,[0-9]+)/','\'$1\'',$strTag);
		$strTag	=	preg_replace("#\s+#",",",$strTag);
		return "array(".$strTag.")";
	}
	function compileTag($tag,$argument){
		eval('$_argument='.$argument.";");
		if(!array_key_exists("name",$_argument)&&$tag!='pagelist'){
			die("标签<strong>【 $tag 】</strong>没有指定属性NAME");
		}
		$paginationTag	=	array('lists','attachments','search','loop');
		if(in_array($tag,$paginationTag)){
			if(@$_argument['pagesize']){
				$this->cacheData['pagesize']	=	$_argument['pagesize'];
			}
		}
		if($tag=='pagelist'){
			$_argument['is_html']	=	true;
			return $string			=	"<?php \$this->html->pagelist(".preg_replace("#\s*#i","",var_export($_argument,true))."); ?>";
		}
		if($tag=='loop'){
			return "<?php foreach($".$_argument['name']."s=\$this->".$_argument['name']." as $".$_argument['name']."){?>";
		}
		$string	=	"<?php $".$_argument['name']."s=\$this->runFunction('$tag',".preg_replace("#\s*#i","",var_export($_argument,true)).");\r\n";
		$string.=	"foreach( $".$_argument['name']."s as  $".$_argument['name']."){ ?>\r\n";
		$string	=	preg_replace('/\'([a-z0-9_]*)\.([a-z0-9_]*)\'/i',"\$\\1->\\2",$string);
		return $string;
	}
	function runFunction($tag,$argument=array()){
		if(in_array($tag,$this->specialTag)){
			return $this->html->$tag($argument);
		}
		else{
			die("特殊方法标签$tag不存在");
		}
	}
	function funRun($name,$arg){
		$names=array(
		"getdate",
		"position",
		"rawurldecode",
		);
		if(in_array($name,$names)){
			return "<?php echo \$this->html->".$name."(".preg_replace('/\'([a-z0-9_]*)\.([a-z0-9_]*)\'/i',"\$\\1->\\2",$arg)."); ?>";
		}
		else{
			@die("自定义函数$name不存在");
		}
	}
	function ifstring($string){
		$string	=	preg_replace("#\\$([a-z0-9_]+)\s*([^\.]+)#i","\$this->\\1\\2",$string);
		$string	=	preg_replace("#\\$\s*([a-z0-9_]+)\s*\.\s*([a-z0-9_]+)#i","\$this->\\1->\\2",$string);
		$string	=	preg_replace("#([a-z0-9_]+)\s*\.\s*([a-z0-9_]+)#i","$\\1->\\2",$string);
		$string	=	preg_replace("#\->\\$#i","->",$string);
		return $string;
	}
	function linkcss($path){
		return BASEURL.dirname($this->_path)."/css/".basename($path);
	}
	function linkimg($path){
		if(preg_match("#http://#i",$path)){
			return $path;
		}
		return BASEURL.dirname($this->_path)."/images/".basename($path);
	}
	function resetVar(){
		$this->cacheData	=	false;
		$this->pagesize		=	false;
	}
}