/**********************************************
//DedeTagParse Dede织梦模板类
function c____DedeTagParse();
***********************************************/
class DedeTagParse
{
var $NameSpace = 'dede'; //标记的名字空间
var $TagStartWord = '{'; //标记起始
var $TagEndWord = '}'; //标记结束
var $TagMaxLen = 64; //标记名称的最大值
var $CharToLow = true; // true表示对属性和标记名称不区分大小写
var $IsCache = FALSE; //是否使用缓冲
var $TempMkTime = 0;
var $CacheFile = '';
var $SourceString = ''; //模板字符串
var $CTags = ''; //标记集合
var $Count = -1; //$Tags标记个数
var $refObj = ''; //引用当前模板类的对象
function __construct()
{
if(!isset($GLOBALS['cfg_tplcache']))
{
$GLOBALS['cfg_tplcache'] = 'N';
}
if($GLOBALS['cfg_tplcache']=='Y')
{
$this->IsCache = true;
}
else
{
$this->IsCache = FALSE;
}
$this->NameSpace = 'dede';
$this->TagStartWord = '{';
$this->TagEndWord = '}';
$this->TagMaxLen = 64;
$this->CharToLow = true;
$this->SourceString = '';
$this->CTags = Array();
$this->Count = -1;
$this->TempMkTime = 0;
$this->CacheFile = '';
}
function DedeTagParse()
{
$this->__construct();
}
//设置标记的命名空间,默认为dede
function SetNameSpace($str,$s="{",$e="}")
{
$this->NameSpace = strtolower($str);
$this->TagStartWord = $s;
$this->TagEndWord = $e;
}
//重置成员变量或Clear
function SetDefault()
{
$this->SourceString = '';
$this->CTags = '';
$this->Count=-1;
}
function GetCount()
{
return $this->Count+1;
}
function Clear()
{
$this->SetDefault();
}
//检测模板缓冲
function LoadCache($filename)
{
global $cfg_tplcache,$cfg_tplcache_dir;
if(!$this->IsCache)
{
return false;
}
$cdir = dirname($filename);
$cachedir = DEDEROOT.$cfg_tplcache_dir;
$ckfile = str_replace($cdir,'',$filename).substr(md5($filename),0,16).'.inc';
$ckfullfile = $cachedir.'/'.$ckfile;
$ckfullfile_t = $cachedir.'/'.$ckfile.'.txt';
$this->CacheFile = $ckfullfile;
$this->TempMkTime = filemtime($filename);
if(!file_exists($ckfullfile)||!file_exists($ckfullfile_t))
{
return false;
}
//检测模板最后更新时间
$fp = fopen($ckfullfile_t,'r');
$time_info = trim(fgets($fp,64));
fclose($fp);
if($time_info != $this->TempMkTime)
{
return false;
}
//引入缓冲数组
include($this->CacheFile);
//把缓冲数组内容读入类
if(isset($z) && is_array($z))
{
foreach($z as $k=>$v)
{
$this->Count++;
$ctag = new DedeTAg();
$ctag->CAttribute = new DedeAttribute();
$ctag->IsReplace = FALSE;
$ctag->TagName = $v[0];
$ctag->InnerText = $v[1];
$ctag->StartPos = $v[2];
$ctag->EndPos = $v[3];
$ctag->TagValue = '';
$ctag->TagID = $k;
if(isset($v[4]) && is_array($v[4]))
{
$i = 0;
foreach($v[4] as $k=>$v)
{
$ctag->CAttribute->Count++;
$ctag->CAttribute->Items[$k]=$v;
}
}
$this->CTags[$this->Count] = $ctag;
}
}
else
{
//模板没有缓冲数组
$this->CTags = '';
$this->Count = -1;
}
return true;
}
//写入缓冲
function SaveCache()
{
$fp = fopen($this->CacheFile.'.txt',"w");
fwrite($fp,$this->TempMkTime."/n");
fclose($fp);
$fp = fopen($this->CacheFile,"w");
flock($fp,3);
fwrite($fp,'<'.'?php'."/r/n");
if(is_array($this->CTags))
{
foreach($this->CTags as $tid=>$ctag)
{
$arrayValue = 'Array("'.$ctag->TagName.'",';
$arrayValue .= '"'.str_replace('$','/$',str_replace("/r","//r",str_replace("/n","//n",str_replace('"','/"',str_replace("//","////",$ctag->InnerText))))).'"';
$arrayValue .= ",{$ctag->StartPos},{$ctag->EndPos});";
fwrite($fp,"/$z[$tid]={$arrayValue}/n");
if(is_array($ctag->CAttribute->Items))
{
foreach($ctag->CAttribute->Items as $k=>$v)
{
$v = str_replace("//","////",$v);
$v = str_replace('"',"//".'"',$v);
$v = str_replace('$','/$',$v);
$k = trim(str_replace("'","",$k));
if($k=="")
{
continue;
}
if($k!='tagname')
{
fwrite($fp,"/$z[$tid][4]['$k']=/"$v/";/n");
}
}
}
}
}
fwrite($fp,"/n".'?'.'>');
fclose($fp);
}
//载入模板文件
function LoadTemplate($filename)
{
$this->SetDefault(); //重置成员变量或Clear
//打开模板文件进行读取
$fp = @fopen($filename,"r") or die(" Template Not Found! ".$filename."<br />");
while($line = fgets($fp,1024))
{
/*
* 赋值运算将原变量的值拷贝到新变量中(传值赋值),所以改变其中一个并不影响另一个。
* 这也适合于在很密集的循环中拷贝一些值例如大数组。也可以使用引用赋值,用 $var = &$othervar; 语法。
* 引用赋值意味着两个变量都指向同一个数据,没有任何数据的拷贝。
*
* .= 相当于 +=
*/
$this->SourceString .= $line;
}
fclose($fp); //关闭文件
//如果模板缓冲文件存在返回null,否则进行模板文件解析
if($this->LoadCache($filename))
{
return '';
}
else
{
$this->ParseTemplet(); //解析模板
}
}
function LoadTemplet($filename)
{
$this->LoadTemplate($filename);
}
function LoadFile($filename)
{
$this->LoadTemplate($filename);
}
//载入模板字符串
function LoadSource($str)
{
$this->SetDefault();
$this->SourceString = $str;
$this->IsCache = FALSE;
$this->ParseTemplet();
}
function LoadString($str)
{
$this->LoadSource($str);
}
//获得指定名称的Tag的ID(如果有多个同名的Tag,则取没有被取代为内容的第一个Tag)
function GetTagID($str)
{
if($this->Count==-1)
{
return -1;
}
if($this->CharToLow)
{
$str=strtolower($str);
}
foreach($this->CTags as $id=>$CTag)
{
if($CTag->TagName==$str && !$CTag->IsReplace)
{
return $id;
break;
}
}
return -1;
}
//获得指定名称的CTag数据类(如果有多个同名的Tag,则取没有被分配内容的第一个Tag)
function GetTag($str)
{
if($this->Count==-1)
{
return '';
}
if($this->CharToLow)
{
$str=strtolower($str);
}
foreach($this->CTags as $id=>$CTag)
{
if($CTag->TagName==$str && !$CTag->IsReplace)
{
return $CTag;
break;
}
}
return '';
}
function GetTagByName($str)
{
return $this->GetTag($str);
}
//获得指定ID的CTag数据类
function GetTagByID($id)
{
if(isset($this->CTags[$id]))
{
return $this->CTags[$id];
}
else
{
return '';
}
}
//给_vars数组传递一个元素
function AssignVar($vname,$vvalue)
{
if(!isset($_sys_globals['define']))
{
$_sys_globals['define'] = 'yes';
}
$_sys_globals[$vname] = $vvalue;
}
//分配指定ID的标记的值
function Assign($i,$str,$runfunc = true)
{
if(isset($this->CTags[$i]))
{
$this->CTags[$i]->IsReplace = true;
$this->CTags[$i]->TagValue = $str;
if( $this->CTags[$i]->GetAtt('function')!='' && $runfunc )
{
$this->CTags[$i]->TagValue = $this->EvalFunc( $str, $this->CTags[$i]->GetAtt('function'),$this->CTags[$i] );
}
}
}
//分配指定名称的标记的值,如果标记包含属性,请不要用此函数
function AssignName($tagname,$str)
{
foreach($this->CTags as $id=>$CTag)
{
if($CTag->TagName==$tagname)
{
$this->Assign($id,$str);
}
}
}
//处理特殊标记
function AssignSysTag()
{
global $_sys_globals;
for($i=0;$i<=$this->Count;$i++)
{
$CTag = $this->CTags[$i];
$str = '';
//获取一个外部变量
if( $CTag->TagName == 'global' )
{
$str = $this->GetGlobals($CTag->GetAtt('name'));
if( $this->CTags[$i]->GetAtt('function')!='' )
{
$str = $this->EvalFunc( $this->CTags[$i]->TagValue, $this->CTags[$i]->GetAtt('function'),$this->CTags[$i] );
}
$this->CTags[$i]->IsReplace = true;
$this->CTags[$i]->TagValue = $str;
}
//引入静态文件
else if( $CTag->TagName == 'include' )
{
$filename = ($CTag->GetAtt('file')=='' ? $CTag->GetAtt('filename') : $CTag->GetAtt('file') );
$str = $this->IncludeFile($filename,$CTag->GetAtt('ismake'));
$this->CTags[$i]->IsReplace = true;
$this->CTags[$i]->TagValue = $str;
}
//循环一个普通数组
else if( $CTag->TagName == 'foreach' )
{
$arr = $this->CTags[$i]->GetAtt('array');
if(isset($GLOBALS[$arr]))
{
foreach($GLOBALS[$arr] as $k=>$v)
{
$istr = '';
$istr .= preg_replace("//[field:key([/r/n/t/f ]+)///]/is",$k,$this->CTags[$i]->InnerText);
$str .= preg_replace("//[field:value([/r/n/t/f ]+)///]/is",$v,$istr);
}
}
$this->CTags[$i]->IsReplace = true;
$this->CTags[$i]->TagValue = $str;
}
//设置/获取变量值
else if( $CTag->TagName == 'var' )
{
$vname = $this->CTags[$i]->GetAtt('name');
if($vname=='')
{
$str = '';
}
else if($this->CTags[$i]->GetAtt('value')!='')
{
$_vars[$vname] = $this->CTags[$i]->GetAtt('value');
}
else
{
$str = (isset($_vars[$vname]) ? $_vars[$vname] : '');
}
$this->CTags[$i]->IsReplace = true;
$this->CTags[$i]->TagValue = $str;
}
//运行PHP接口
if( $CTag->GetAtt('runphp') == 'yes' )
{
$this->RunPHP($CTag,$i);
}
if(is_array($this->CTags[$i]->TagValue))
{
$this->CTags[$i]->TagValue = 'array';
}
}
}
//运行PHP代码
function RunPHP(&$refObj,$i)
{
$DedeMeValue = $phpcode = '';
if($refObj->GetAtt('source')=='value')
{
$phpcode = $this->CTags[$i]->TagValue;
}
else
{
$DedeMeValue = $this->CTags[$i]->TagValue;
$phpcode = $refObj->GetInnerText();
}
$phpcode = eregi_replace("'@me'|/"@me/"|@me",'$DedeMeValue',$phpcode);
@eval($phpcode); //or die("<xmp>$phpcode</xmp>");
$this->CTags[$i]->TagValue = $DedeMeValue;
$this->CTags[$i]->IsReplace = true;
}
//把分析模板输出到一个字符串中
//不替换没被处理的值
function GetResultNP()
{
$ResultString = '';
if($this->Count==-1)
{
return $this->SourceString;
}
$this->AssignSysTag();
$nextTagEnd = 0;
$strok = "";
for($i=0;$i<=$this->Count;$i++)
{
if($this->CTags[$i]->GetValue()!="")
{
if($this->CTags[$i]->GetValue()=='#@Delete@#')
{
$this->CTags[$i]->TagValue = "";
}
$ResultString .= substr($this->SourceString,$nextTagEnd,$this->CTags[$i]->StartPos-$nextTagEnd);
$ResultString .= $this->CTags[$i]->GetValue();
$nextTagEnd = $this->CTags[$i]->EndPos;
}
}
$slen = strlen($this->SourceString);
if($slen>$nextTagEnd)
{
$ResultString .= substr($this->SourceString,$nextTagEnd,$slen-$nextTagEnd);
}
return $ResultString;
}
//把分析模板输出到一个字符串中,并返回
function GetResult()
{
$ResultString = '';
if($this->Count==-1)
{
return $this->SourceString;
}
$this->AssignSysTag();
$nextTagEnd = 0;
$strok = "";
for($i=0;$i<=$this->Count;$i++)
{
$ResultString .= substr($this->SourceString,$nextTagEnd,$this->CTags[$i]->StartPos-$nextTagEnd);
$ResultString .= $this->CTags[$i]->GetValue();
$nextTagEnd = $this->CTags[$i]->EndPos;
}
$slen = strlen($this->SourceString);
if($slen>$nextTagEnd)
{
$ResultString .= substr($this->SourceString,$nextTagEnd,$slen-$nextTagEnd);
}
return $ResultString;
}
//直接输出分析模板
function Display()
{
echo $this->GetResult();
}
//把分析模板输出为文件
function SaveTo($filename)
{
$fp = @fopen($filename,"w") or die("DedeTag Engine Create File False");
fwrite($fp,$this->GetResult());
fclose($fp);
}
//解析模板
function ParseTemplet()
{
/*
* 说明:并置运算符 (.) 用于把两个字符串值连接起来。
*
* 参考:http://www.w3school.com.cn/php/php_string.asp
*/
$TagStartWord = $this->TagStartWord; //标签起始:{
$TagEndWord = $this->TagEndWord; //标签结束:}
$sPos = 0;
$ePos = 0;
$FullTagStartWord = $TagStartWord.$this->NameSpace.":"; //标签”命名空间“ 起始: '{' + 'dede' + ':'
$sTagEndWord = $TagStartWord."/".$this->NameSpace.":"; //标签”命名空间“结束: '{' + '/' + 'dede' + ':'
$eTagEndWord = "/".$TagEndWord; //标签""结束: '/' + '}'
$tsLen = strlen($FullTagStartWord); //标签“命名空间”长度 : 6
$sourceLen=strlen($this->SourceString); //模板字符串长度
/*
* 如果“模板字符串”小于或者等于 6 + 3,程序返回。
*/
if( $sourceLen <= ($tsLen + 3) )
{
return;
}
$cAtt = new DedeAttributeParse(); //属性解析器类
$cAtt->charToLow = $this->CharToLow; // true表示对属性和标记名称不区分大小写
//遍历模板字符串,请取标记及其属性信息
for($i=0; $i < $sourceLen; $i++)
{
$tTagName = '';
//如果不进行此判断,将无法识别相连的两个标记
if($i-1 >= 0)
{
$ss = $i-1;
}
else
{
$ss = 0;
}
/*
* strpos() 函数返回字符串在另一个字符串中第一次出现的位置。
*
* strpos(string,find,start)
*
* string 必需。规定被搜索的字符串。
* find 必需。规定要查找的字符。
* start 可选。规定开始搜索的位置。
*/
$sPos = strpos($this->SourceString,$FullTagStartWord,$ss); //从"模板字符串"0位置开始,查找 "{dede:" 第一个出现位置
$isTag = $sPos; //标签0 false 非零true
/*
* 第一次循环时,从“模板字符串”中截取字符 {dede: ,并判断是否与 标签{dede:相等。
*/
if($i==0)
{
$headerTag = substr($this->SourceString,0,strlen($FullTagStartWord));
if($headerTag==$FullTagStartWord)
{
$isTag=true; //设置为True 为结束次循环
$sPos=0; //模板标签出现位置 重置0;表示不是标签
}
}
//非{dede: 模板标签结束退出循环。
if($isTag===FALSE)
{
break;
}
//判断是否已经到倒数第三个字符(可能性机率极小,取消此逻辑)
/*
if($sPos > ($sourceLen-$tsLen-3) )
{
break;
}
*/
/*
* 标签起始位置 + 标签命名空间长度(6)。
* 标签起始位置 + 标签命名空间长度(6) + 标记名称最大值
*
* 匹配 {dede: + 【 /,空格,换行符,制表符】 部分。
*/
for($j=($sPos+$tsLen);$j<($sPos+$tsLen+$this->TagMaxLen);$j++)
{
//判断{标签起始位置 + 标签命名空间长度(6)} 大于 模板全部字符长度,则退出循环
if($j>($sourceLen-1))
{
break;
}
//当前字符串不是标签结束符号 And 正则表达式匹配当前字符满足【 匹配 /,空格,换行符,制表符】即 [/ /t/r/n]
else if( ereg("[/ /t/r/n]",$this->SourceString[$j]) || $this->SourceString[$j] == $this->TagEndWord )
{
break; //退出当前层循环嵌套,继续主循环嵌套
}
else
{
$tTagName .= $this->SourceString[$j]; //标签名称字符累加
}
}
//标签字符不等于 null
if($tTagName!='')
{
$i = $sPos+$tsLen;
$endPos = -1;
$fullTagEndWordThis = $sTagEndWord.$tTagName.$TagEndWord;
$e1 = strpos($this->SourceString,$eTagEndWord, $i);
$e2 = strpos($this->SourceString,$FullTagStartWord, $i);
$e3 = strpos($this->SourceString,$fullTagEndWordThis,$i);
//$eTagEndWord = /} $FullTagStartWord = {tag: $fullTagEndWordThis = {/tag:xxx]
$e1 = trim($e1); $e2 = trim($e2); $e3 = trim($e3);
$e1 = ($e1=='' ? '-1' : $e1);
$e2 = ($e2=='' ? '-1' : $e2);
$e3 = ($e3=='' ? '-1' : $e3);
//not found '{/tag:'
if($e3==-1)
{
$endPos = $e1;
$elen = $endPos + strlen($eTagEndWord);
}
//not found '/}'
else if($e1==-1)
{
$endPos = $e3;
$elen = $endPos + strlen($fullTagEndWordThis);
}
//found '/}' and found '{/dede:'
else
{
//if '/}' more near '{dede:'、'{/dede:' , end tag is '/}', else is '{/dede:'
if($e1 < $e2 && $e1 < $e3 )
{
$endPos = $e1;
$elen = $endPos + strlen($eTagEndWord);
}
else
{
$endPos = $e3;
$elen = $endPos + strlen($fullTagEndWordThis);
}
}
//not found end tag , error
if($endPos==-1)
{
echo "Character postion $sPos, '$tTagName' Error!<br />/r/n";
break;
}
$i = $elen;
$ePos = $endPos;
//分析所找到的标记位置等信息
$attStr = '';
$innerText = '';
$startInner = 0;
for($j=($sPos+$tsLen);$j < $ePos;$j++)
{
if($startInner==0 && ($this->SourceString[$j]==$TagEndWord && $this->SourceString[$j-1]!="//") )
{
$startInner=1;
continue;
}
if($startInner==0)
{
$attStr .= $this->SourceString[$j];
}
else
{
$innerText .= $this->SourceString[$j];
}
}
//echo "<xmp>$attStr</xmp>/r/n";
$cAtt->SetSource($attStr);
if($cAtt->cAttributes->GetTagName()!='')
{
$this->Count++;
$CDTag = new DedeTag();
$CDTag->TagName = $cAtt->cAttributes->GetTagName();
$CDTag->StartPos = $sPos;
$CDTag->EndPos = $i;
$CDTag->CAttribute = $cAtt->cAttributes;
$CDTag->IsReplace = FALSE;
$CDTag->TagID = $this->Count;
$CDTag->InnerText = $innerText;
$this->CTags[$this->Count] = $CDTag;
}
}
else //标签字符串等于null,退出循环
{
$i = $sPos+$tsLen;
break;
}
}//结束遍历模板字符串
//是否使用缓存
if($this->IsCache)
{
$this->SaveCache(); //写入缓存
}
}
//处理某字段的函数
function EvalFunc($fieldvalue,$functionname,&$refObj)
{
$DedeFieldValue = $fieldvalue;
$functionname = str_replace("{/"","[/"",$functionname);
$functionname = str_replace("/"}","/"]",$functionname);
$functionname = eregi_replace("'@me'|/"@me/"|@me",'$DedeFieldValue',$functionname);
$functionname = "/$DedeFieldValue = ".$functionname;
@eval($functionname.";"); //or die("<xmp>$functionname</xmp>");
if(empty($DedeFieldValue))
{
return '';
}
else
{
return $DedeFieldValue;
}
}
//获得一个外部变量
function GetGlobals($varname)
{
$varname = trim($varname);
//禁止在模板文件读取数据库密码
if($varname=="dbuserpwd"||$varname=="cfg_dbpwd")
{
return "";
}
//正常情况
if(isset($GLOBALS[$varname]))
{
return $GLOBALS[$varname];
}
else
{
return "";
}
}
//引入文件
function IncludeFile($filename,$ismake='no')
{
global $cfg_df_style;
$restr = '';
if($filename=='')
{
return '';
}
if( file_exists(DEDEROOT."/templets/".$filename) )
{
$okfile = DEDEROOT."/templets/".$filename;
}
else if(file_exists(DEDEROOT.'/templets/'.$cfg_df_style.'/'.$filename) )
{
$okfile = DEDEROOT.'/templets/'.$cfg_df_style.'/'.$filename;
}
else
{
return "无法在这个位置找到: $filename";
}
//编译
if($ismake!="no")
{
require_once(DEDEINC."/channelunit.func.php");
$dtp = new DedeTagParse();
$dtp->LoadTemplet($okfile);
MakeOneTag($dtp,$this->refObj);
$restr = $dtp->GetResult();
}
else
{
$fp = @fopen($okfile,"r");
while($line=fgets($fp,1024)) $restr.=$line;
fclose($fp);
}
return $restr;
}
}
/**********************************************
//class DedeAttribute Dede模板标记属性集合
function c____DedeAttribute();
**********************************************/
//属性的数据描述
class DedeAttribute
{
var $Count = -1;
var $Items = ""; //属性元素的集合
//获得某个属性
function GetAtt($str)
{
if($str=="")
{
return "";
}
if(isset($this->Items[$str]))
{
return $this->Items[$str];
}
else
{
return "";
}
}
//同上
function GetAttribute($str)
{
return $this->GetAtt($str);
}
//判断属性是否存在
function IsAttribute($str)
{
if(isset($this->Items[$str])) return true;
else return false;
}
//获得标记名称
function GetTagName()
{
return $this->GetAtt("tagname");
}
// 获得属性个数
function GetCount()
{
return $this->Count+1;
}
}
Dede织梦模板类
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.