$v) {
if (preg_match('/^field\./i', $v)) {
$key = preg_replace('/^field\./i', '', $v);
if (isset($fields[$key])) {
$atts[$k] = $fields[$key];
}
} else if (preg_match('/^var\./i', $v)) {
$key = preg_replace('/^var\./i', '', $v);
if (isset($_vars[$key])) {
$atts[$k] = $_vars[$key];
}
} else if (preg_match('/^global\./i', $v)) {
$key = preg_replace('/^global\./i', '', $v);
if (isset($GLOBALS[$key])) {
$atts[$k] = $GLOBALS[$key];
}
}
}
}
/**
* class Tag 标记的数据结构描述
* function C__Tag();
*
* @package Tag
* @subpackage DedeBIZ.Libraries
* @link https://www.dedebiz.com
*/
class Tag
{
var $isCompiler = FALSE; //标记是否已被替代,供解析器使用
var $tagName = ""; //标记名称
var $innerText = ""; //标记之间的文本
var $startPos = 0; //标记起始位置
var $endPos = 0; //标记结束位置
var $cAtt; //标记属性描述,即是class TagAttribute
var $tagValue = ""; //标记的值
var $tagID = 0;
/**
* 获取标记的名称和值
*
* @access public
* @return string
*/
function GetName()
{
return strtolower($this->tagName);
}
function GetValue()
{
return $this->tagValue;
}
function IsAtt($str)
{
return $this->cAtt->IsAttribute($str);
}
function GetAtt($str)
{
return $this->cAtt->GetAtt($str);
}
/**
* 获取底层模板
*
* @return string
*/
function GetinnerText()
{
return $this->innerText;
}
}
/**
* 模板解析器
* function C__DedeTemplate
*
* @package DedeTemplate
* @subpackage DedeBIZ.Libraries
* @link https://www.dedebiz.com
*/
class DedeTemplate
{
var $tagMaxLen = 64;
var $charToLow = TRUE;
var $isCache = TRUE;
var $isParse = FALSE;
var $isCompiler = TRUE;
var $templateDir = '';
var $tempMkTime = 0;
var $cacheFile = '';
var $configFile = '';
var $buildFile = '';
var $refDir = '';
var $cacheDir = '';
var $templateFile = '';
var $sourceString = '';
var $cTags = array();
//var $definedVars = array();
var $count = -1;
var $loopNum = 0;
var $refObj = '';
var $makeLoop = 0;
var $tagStartWord = '{dede:';
var $fullTagEndWord = '{/dede:';
var $sTagEndWord = '/}';
var $tagEndWord = '}';
var $tpCfgs = array();
/**
* 析构函数
*
* @access public
* @param string $templatedir 模板目录
* @param string $refDir 所属目录
* @return void
*/
function __construct($templatedir = '', $refDir = '')
{
//$definedVars[] = 'var';
//缓存目录
if ($templatedir == '') {
$this->templateDir = DEDEROOT.'/templates';
} else {
$this->templateDir = $templatedir;
}
//模板include目录
if ($refDir == '') {
if (isset($GLOBALS['cfg_df_style'])) {
$this->refDir = $this->templateDir.'/'.$GLOBALS['cfg_df_style'].'/';
} else {
$this->refDir = $this->templateDir;
}
}
$this->cacheDir = DEDEROOT.$GLOBALS['cfg_tplcache_dir'];
}
//构造函数,兼容PHP4
function DedeTemplate($templatedir = '', $refDir = '')
{
$this->__construct($templatedir, $refDir);
}
/**
* 设定本类自身实例的类引用和使用本类的类实例(如果在类中使用本模板引擎,后一参数一般为$this)
*
* @access public
* @param object $refObj 实例对象
* @return string
*/
function SetObject(&$refObj)
{
$this->refObj = $refObj;
}
/**
* 设定Var的键值对
*
* @access public
* @param string $k 键
* @param string $v 值
* @return string
*/
function SetVar($k, $v)
{
$GLOBALS['_vars'][$k] = $v;
}
/**
* 设定Var的键值对
*
* @access public
* @param string $k 键
* @param string $v 值
* @return string
*/
function Assign($k, $v)
{
$GLOBALS['_vars'][$k] = $v;
}
/**
* 设定数组
*
* @access public
* @param string $k 键
* @param string $v 值
* @return string
*/
function SetArray($k, $v)
{
$GLOBALS[$k] = $v;
}
/**
* 设置标记风格
*
* @access public
* @param string $ts 标签开始标记
* @param string $ftend 标签结束标记
* @param string $stend 标签尾部结束标记
* @param string $tend 结束标记
* @return void
*/
function SetTagStyle($ts = '{dede:', $ftend = '{/dede:', $stend = '/}', $tend = '}')
{
$this->tagStartWord = $ts;
$this->fullTagEndWord = $ftend;
$this->sTagEndWord = $stend;
$this->tagEndWord = $tend;
}
/**
* 获得模板设定的config值
*
* @access public
* @param string $k 键名
* @return string
*/
function GetConfig($k)
{
return (isset($this->tpCfgs[$k]) ? $this->tpCfgs[$k] : '');
}
/**
* 设定模板文件
*
* @access public
* @param string $tmpfile 模板文件
* @return void
*/
function LoadTemplate($tmpfile)
{
if (!file_exists($tmpfile)) {
echo " Template Not Found! ";
exit();
}
$tmpfile = preg_replace("/[\\/]{1,}/", "/", $tmpfile);
$tmpfiles = explode('/', $tmpfile);
$tmpfileOnlyName = preg_replace("/(.*)\//", "", $tmpfile);
$this->templateFile = $tmpfile;
$this->refDir = '';
for ($i = 0; $i < count($tmpfiles) - 1; $i++) {
$this->refDir .= $tmpfiles[$i].'/';
}
if (!is_dir($this->cacheDir)) {
$this->cacheDir = $this->refDir;
}
if ($this->cacheDir != '') {
$this->cacheDir = $this->cacheDir.'/';
}
if (isset($GLOBALS['_DEBUG_CACHE'])) {
$this->cacheDir = $this->refDir;
}
$this->cacheFile = $this->cacheDir.preg_replace("/\.(wml|html|htm|php)$/", "_".$this->GetEncodeStr($tmpfile).'.inc', $tmpfileOnlyName);
$this->configFile = $this->cacheDir.preg_replace("/\.(wml|html|htm|php)$/", "_".$this->GetEncodeStr($tmpfile).'_config.inc', $tmpfileOnlyName);
//不开启缓存、当缓存文件不存在、及模板为更新的文件的时候才载入模板并进行解析
if (
$this->isCache == FALSE || !file_exists($this->cacheFile)
|| filemtime($this->templateFile) > filemtime($this->cacheFile)
) {
$t1 = ExecTime(); //debug
$fp = fopen($this->templateFile, 'r');
$this->sourceString = fread($fp, filesize($this->templateFile));
fclose($fp);
$this->ParseTemplate();
//模板解析时间
//echo ExecTime() - $t1;
} else {
//如果存在config文件,则载入此文件,该文件用于保存 $this->tpCfgs的内容,以供扩展用途
//模板中用{tag:config name='' value=''/}来设定该值
if (file_exists($this->configFile)) {
include($this->configFile);
}
}
}
/**
* 载入模板字符串
*
* @access public
* @param string $str 模板字符串
* @return void
*/
function LoadString($str = '')
{
$this->sourceString = $str;
$hashcode = md5($this->sourceString);
$this->cacheFile = $this->cacheDir."/string_".$hashcode.".inc";
$this->configFile = $this->cacheDir."/string_".$hashcode."_config.inc";
$this->ParseTemplate();
}
/**
* 调用此函数include一个编译后的PHP文件,通常是在最后一个步骤才调用本文件
*
* @access public
* @return string
*/
function CacheFile()
{
global $gtmpfile;
$this->WriteCache();
return $this->cacheFile;
}
/**
* 显示内容,由于函数中会重新解压一次$GLOBALS变量,所以在动态页中,应该尽量少用本方法,
* 取代之是直接在程序中 include $tpl->CacheFile(),不过include $tpl->CacheFile()这种方式不能在类或函数内使用
*
* @access public
* @param string
* @return void
*/
function Display()
{
global $gtmpfile;
extract($GLOBALS, EXTR_SKIP);
$this->WriteCache();
include $this->cacheFile;
}
/**
* 保存运行后的程序为文件
*
* @access public
* @param string $savefile 保存到的文件目录
* @return void
*/
function SaveTo($savefile)
{
extract($GLOBALS, EXTR_SKIP);
$this->WriteCache();
ob_start();
include $this->cacheFile;
$okstr = ob_get_contents();
ob_end_clean();
$fp = @fopen($savefile, "w") or die(" Tag Engine Create File FALSE! ");
fwrite($fp, $okstr);
fclose($fp);
}
//------------------------------------------------------------------------
/**
* CheckDisabledFunctions
*
* COMMENT : CheckDisabledFunctions : 检查是否存在禁止的函数
*
* @access public
* @param string
* @return bool
*/
function CheckDisabledFunctions($str, &$errmsg = '')
{
global $cfg_disable_funs;
$cfg_disable_funs = isset($cfg_disable_funs) ? $cfg_disable_funs : 'phpinfo,eval,exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source,file_put_contents,fsockopen,fopen,fwrite';
//模板引擎增加disable_functions
if (!defined('DEDEDISFUN')) {
$tokens = token_get_all_nl($str);
$disabled_functions = explode(',', $cfg_disable_funs);
foreach ($tokens as $token) {
if (is_array($token)) {
if ($token[0] = '306' && in_array($token[1], $disabled_functions)) {
$errmsg = 'DedeBIZ Error:function disabled "'.$token[1].'" more';
return FALSE;
}
}
}
}
return TRUE;
}
/**
* 解析模板并写缓存文件
*
* @access public
* @param string $ctype 缓存类型
* @return void
*/
function WriteCache($ctype = 'all')
{
if (
!file_exists($this->cacheFile) || $this->isCache == FALSE
|| (file_exists($this->templateFile) && (filemtime($this->templateFile) > filemtime($this->cacheFile)))
) {
if (!$this->isParse) {
$this->ParseTemplate();
}
$fp = fopen($this->cacheFile, 'w') or dir("Write Cache File Error! ");
flock($fp, 3);
$result = trim($this->GetResult());
$errmsg = '';
//var_dump($result);exit();
if (!$this->CheckDisabledFunctions($result, $errmsg)) {
fclose($fp);
@unlink($this->cacheFile);
die($errmsg);
}
fwrite($fp, $result);
fclose($fp);
if (count($this->tpCfgs) > 0) {
$fp = fopen($this->configFile, 'w') or dir("Write Config File Error! ");
flock($fp, 3);
fwrite($fp, '<'.'?php'."\r\n");
foreach ($this->tpCfgs as $k => $v) {
$v = str_replace("\"", "\\\"", $v);
$v = str_replace("\$", "\\\$", $v);
fwrite($fp, "\$this->tpCfgs['$k']=\"$v\";\r\n");
}
fwrite($fp, '?'.'>');
fclose($fp);
}
}
/*
if(!file_exists($this->cacheFile) || $this->isCache==FALSE
|| ( file_exists($this->templateFile) && (filemtime($this->templateFile) > filemtime($this->cacheFile)) ) )
{
if($ctype!='config')
{
if(!$this->isParse)
{
$this->ParseTemplate();
}
$fp = fopen($this->cacheFile,'w') or dir("Write Cache File Error! ");
flock($fp,3);
fwrite($fp,trim($this->GetResult()));
fclose($fp);
}
else
{
if(count($this->tpCfgs) > 0)
{
$fp = fopen($this->configFile,'w') or dir("Write Config File Error! ");
flock($fp,3);
fwrite($fp,'<'.'?php'."\r\n");
foreach($this->tpCfgs as $k=>$v)
{
$v = str_replace("\"","\\\"",$v);
$v = str_replace("\$","\\\$",$v);
fwrite($fp,"\$this->tpCfgs['$k']=\"$v\";\r\n");
}
fwrite($fp,'?'.'>');
fclose($fp);
}
}
} else {
if($ctype=='config' && count($this->tpCfgs) > 0 )
{
$fp = fopen($this->configFile,'w') or dir("Write Config File Error! ");
flock($fp,3);
fwrite($fp,'<'.'?php'."\r\n");
foreach($this->tpCfgs as $k=>$v)
{
$v = str_replace("\"","\\\"",$v);
$v = str_replace("\$","\\\$",$v);
fwrite($fp,"\$this->tpCfgs['$k']=\"$v\";\r\n");
}
fwrite($fp,'?'.'>');
fclose($fp);
}
}
*/
}
/**
* 获得模板文件名的md5字符串
*
* @access public
* @param string $tmpfile 模板文件
* @return string
*/
function GetEncodeStr($tmpfile)
{
//$tmpfiles = explode('/',$tmpfile);
$encodeStr = substr(md5($tmpfile), 0, 24);
return $encodeStr;
}
/**
* 解析模板
*
* @access public
* @return void
*/
function ParseTemplate()
{
if ($this->makeLoop > 5) {
return;
}
$this->count = -1;
$this->cTags = array();
$this->isParse = TRUE;
$sPos = 0;
$ePos = 0;
$tagStartWord = $this->tagStartWord;
$fullTagEndWord = $this->fullTagEndWord;
$sTagEndWord = $this->sTagEndWord;
$tagEndWord = $this->tagEndWord;
$startWordLen = strlen($tagStartWord);
$sourceLen = strlen($this->sourceString);
if ($sourceLen <= ($startWordLen + 3)) {
return;
}
$cAtt = new TagAttributeParse();
$cAtt->CharToLow = TRUE;
//遍历模板字符串,请取标记及其属性信息
$t = 0;
$preTag = '';
$tswLen = strlen($tagStartWord);
for ($i = 0; $i < $sourceLen; $i++) {
$ttagName = '';
//如果不进行此判断,将无法识别相连的两个标记
if ($i - 1 >= 0) {
$ss = $i - 1;
} else {
$ss = 0;
}
$tagPos = strpos($this->sourceString, $tagStartWord, $ss);
//判断后面是否还有模板标记
if ($tagPos == 0 && ($sourceLen - $i < $tswLen
|| substr($this->sourceString, $i, $tswLen) != $tagStartWord)) {
$tagPos = -1;
break;
}
//获取TAG基本信息
for ($j = $tagPos + $startWordLen; $j < $tagPos + $startWordLen + $this->tagMaxLen; $j++) {
if (preg_match("/[ >\/\r\n\t\}\.]/", $this->sourceString[$j])) {
break;
} else {
$ttagName .= $this->sourceString[$j];
}
}
if ($ttagName != '') {
$i = $tagPos + $startWordLen;
$endPos = -1;
//判断 '/}' '{tag:下一标记开始' '{/tag:标记结束' 谁最靠近
$fullTagEndWordThis = $fullTagEndWord.$ttagName.$tagEndWord;
$e1 = strpos($this->sourceString, $sTagEndWord, $i);
$e2 = strpos($this->sourceString, $tagStartWord, $i);
$e3 = strpos($this->sourceString, $fullTagEndWordThis, $i);
$e1 = trim($e1);
$e2 = trim($e2);
$e3 = trim($e3);
$e1 = ($e1 == '' ? '-1' : $e1);
$e2 = ($e2 == '' ? '-1' : $e2);
$e3 = ($e3 == '' ? '-1' : $e3);
if ($e3 == -1) {
//不存在'{/tag:标记'
$endPos = $e1;
$elen = $endPos + strlen($sTagEndWord);
} else if ($e1 == -1) {
//不存在 '/}'
$endPos = $e3;
$elen = $endPos + strlen($fullTagEndWordThis);
}
//同时存在 '/}' 和 '{/tag:标记'
else {
//如果 '/}' 比 '{tag:'、'{/tag:标记' 都要靠近,则认为结束标志是 '/}',否则结束标志为 '{/tag:标记'
if ($e1 < $e2 && $e1 < $e3) {
$endPos = $e1;
$elen = $endPos + strlen($sTagEndWord);
} else {
$endPos = $e3;
$elen = $endPos + strlen($fullTagEndWordThis);
}
}
//如果找不到结束标记,则认为这个标记存在错误
if ($endPos == -1) {
echo "Tpl Character postion $tagPos, '$ttagName' Error
\r\n";
break;
}
$i = $elen;
//分析所找到的标记位置等信息
$attStr = '';
$innerText = '';
$startInner = 0;
for ($j = $tagPos + $startWordLen; $j < $endPos; $j++) {
if ($startInner == 0) {
if ($this->sourceString[$j] == $tagEndWord) {
$startInner = 1;
continue;
} else {
$attStr .= $this->sourceString[$j];
}
} else {
$innerText .= $this->sourceString[$j];
}
}
$ttagName = strtolower($ttagName);
//if、php标记,把整个属性串视为属性
if (preg_match("/^if[0-9]{0,}$/", $ttagName)) {
$cAtt->cAttributes = new TagAttribute();
$cAtt->cAttributes->count = 2;
$cAtt->cAttributes->items['tagname'] = $ttagName;
$cAtt->cAttributes->items['condition'] = preg_replace("/^if[0-9]{0,}[\r\n\t ]/", "", $attStr);
$innerText = preg_replace("/\{else\}/i", '<'."?php\r\n}\r\nelse{\r\n".'?'.'>', $innerText);
} else if ($ttagName == 'php') {
$cAtt->cAttributes = new TagAttribute();
$cAtt->cAttributes->count = 2;
$cAtt->cAttributes->items['tagname'] = $ttagName;
$cAtt->cAttributes->items['code'] = '<'."?php\r\n".trim(preg_replace(
"/^php[0-9]{0,}[\r\n\t ]/",
"",
$attStr
))."\r\n?".'>';
} else {
//普通标记,解释属性
$cAtt->SetSource($attStr);
}
$this->count++;
$cTag = new Tag();
$cTag->tagName = $ttagName;
$cTag->startPos = $tagPos;
$cTag->endPos = $i;
$cTag->cAtt = $cAtt->cAttributes;
$cTag->isCompiler = FALSE;
$cTag->tagID = $this->count;
$cTag->innerText = $innerText;
$this->cTags[$this->count] = $cTag;
} else {
$i = $tagPos + $startWordLen;
break;
}
} //结束遍历模板字符串
if ($this->count > -1 && $this->isCompiler) {
$this->CompilerAll();
}
}
/**
* 把模板标记转换为PHP代码
*
* @access public
* @return void
*/
function CompilerAll()
{
$this->loopNum++;
if ($this->loopNum > 10) {
return; //限制最大递归深度为 10 以防止因标记出错等可能性导致死循环
}
$ResultString = '';
$nextTagEnd = 0;
for ($i = 0; isset($this->cTags[$i]); $i++) {
$ResultString .= substr($this->sourceString, $nextTagEnd, $this->cTags[$i]->startPos - $nextTagEnd);
$ResultString .= $this->CompilerOneTag($this->cTags[$i]);
$nextTagEnd = $this->cTags[$i]->endPos;
}
$slen = strlen($this->sourceString);
if ($slen > $nextTagEnd) {
$ResultString .= substr($this->sourceString, $nextTagEnd, $slen - $nextTagEnd);
}
$this->sourceString = $ResultString;
$this->ParseTemplate();
}
/**
* 获得最终结果
*
* @access public
* @return string
*/
function GetResult()
{
if (!$this->isParse) {
$this->ParseTemplate();
}
$addset = '';
$addset .= '<'.'?php'."\r\n".'if(!isset($GLOBALS[\'_vars\'])) $GLOBALS[\'_vars\'] = array(); '."\r\n".'$fields = array();'."\r\n".'?'.'>';
return preg_replace("/\?".">[ \r\n\t]{0,}<"."\?php/", "", $addset.$this->sourceString);
}
/**
* 编译单个标记
*
* @access public
* @param object $cTag 标签
* @return string
*/
function CompilerOneTag(&$cTag)
{
$cTag->isCompiler = TRUE;
$tagname = $cTag->tagName;
$varname = $cTag->GetAtt('name');
$rsvalue = "";
//用于在模板中设置一个变量以提供作扩展用途
//此变量直接提交到 this->tpCfgs 中,并会生成与模板对应的缓存文件 ***_config.php 文件
if ($tagname == 'config') {
$this->tpCfgs[$varname] = $cTag->GetAtt('value');
} else if ($tagname == 'global') {
$cTag->tagValue = $this->CompilerArrayVar('global', $varname);
if ($cTag->GetAtt('function') != '') {
$cTag->tagValue = $this->CompilerFunction($cTag->GetAtt('function'), $cTag->tagValue);
}
$cTag->tagValue = '<'.'?php echo '.$cTag->tagValue.'; ?'.'>';
} else if ($tagname == 'cfg') {
$cTag->tagValue = '$GLOBALS[\'cfg_'.$varname.'\']'; //处理函数
if ($cTag->GetAtt('function') != '') {
$cTag->tagValue = $this->CompilerFunction($cTag->GetAtt('function'), $cTag->tagValue);
}
$cTag->tagValue = '<'.'?php echo '.$cTag->tagValue.'; ?'.'>';
} else if ($tagname == 'name') {
$cTag->tagValue = '$'.$varname; //处理函数
if ($cTag->GetAtt('function') != '') {
$cTag->tagValue = $this->CompilerFunction($cTag->GetAtt('function'), $cTag->tagValue);
}
$cTag->tagValue = '<'.'?php echo '.$cTag->tagValue.'; ?'.'>';
} else if ($tagname == 'object') {
list($_obs, $_em) = explode('->', $varname);
$cTag->tagValue = "\$GLOBALS['{$_obs}']->{$_em}"; //处理函数
if ($cTag->GetAtt('function') != '') {
$cTag->tagValue = $this->CompilerFunction($cTag->GetAtt('function'), $cTag->tagValue);
}
$cTag->tagValue = '<'.'?php echo '.$cTag->tagValue.'; ?'.'>';
} else if ($tagname == 'var') {
$cTag->tagValue = $this->CompilerArrayVar('var', $varname);
if ($cTag->GetAtt('function') != '') {
$cTag->tagValue = $this->CompilerFunction($cTag->GetAtt('function'), $cTag->tagValue);
}
//增加默认空值处理
if ($cTag->GetAtt('default') != '') {
$cTag->tagValue = '<'.'?php echo empty('.$cTag->tagValue.')? \''.addslashes($cTag->GetAtt('default')).'\':'.$cTag->tagValue.'; ?'.'>';
} else {
$cTag->tagValue = '<'.'?php echo '.$cTag->tagValue.'; ?'.'>';
}
} else if ($tagname == 'field') {
$cTag->tagValue = '$fields[\''.$varname.'\']';
if ($cTag->GetAtt('function') != '') {
$cTag->tagValue = $this->CompilerFunction($cTag->GetAtt('function'), $cTag->tagValue);
}
$cTag->tagValue = '<'.'?php echo '.$cTag->tagValue.'; ?'.'>';
} else if (preg_match("/^key[0-9]{0,}/", $tagname) || preg_match("/^value[0-9]{0,}/", $tagname)) {
if (preg_match("/^value[0-9]{0,}/", $tagname) && $varname != '') {
$cTag->tagValue = '<'.'?php echo '.$this->CompilerArrayVar($tagname, $varname).'; ?'.'>';
} else {
$cTag->tagValue = '<'.'?php echo $'.$tagname.'; ?'.'>';
}
} else if (preg_match("/^if[0-9]{0,}$/", $tagname)) {
$cTag->tagValue = $this->CompilerIf($cTag);
} else if ($tagname == 'echo') {
if (trim($cTag->GetInnerText()) == '') $cTag->tagValue = $cTag->GetAtt('code');
else {
$cTag->tagValue = '<'."?php echo $".trim($cTag->GetInnerText())." ;?".'>';
}
} else if ($tagname == 'php') {
if (trim($cTag->GetInnerText()) == '') $cTag->tagValue = $cTag->GetAtt('code');
else {
$cTag->tagValue = '<'."?php\r\n".trim($cTag->GetInnerText())."\r\n?".'>';
}
}
//遍历数组
else if (preg_match("/^array[0-9]{0,}/", $tagname)) {
$kk = '$key';
$vv = '$value';
if ($cTag->GetAtt('key') != '') {
$kk = '$key'.$cTag->GetAtt('key');
}
if ($cTag->GetAtt('value') != '') {
$vv = '$value'.$cTag->GetAtt('value');
}
$addvar = '';
if (!preg_match("/\(/", $varname)) {
$varname = '$GLOBALS[\''.$varname.'\']';
} else {
$addvar = "\r\n".'$myarrs = $pageClass->'.$varname.";\r\n";
$varname = ' $myarrs ';
}
$rsvalue = '<'.'?php '.$addvar.' foreach('.$varname.' as '.$kk.'=>'.$vv.'){ ?'.">";
$rsvalue .= $cTag->GetInnerText();
$rsvalue .= '<'.'?php } ?'.">\r\n";
$cTag->tagValue = $rsvalue;
}
//include 文件
else if ($tagname == 'include') {
$filename = $cTag->GetAtt('file');
if ($filename == '') {
$filename = $cTag->GetAtt('filename');
}
$cTag->tagValue = $this->CompilerInclude($filename, FALSE);
if ($cTag->tagValue == 0) $cTag->tagValue = '';
$cTag->tagValue = '<'.'?php include $this->CompilerInclude("'.$filename.'");'."\r\n".' ?'.'>';
} else if ($tagname == 'label') {
$bindFunc = $cTag->GetAtt('bind');
$rsvalue = 'echo '.$bindFunc.";\r\n";
$rsvalue = '<'.'?php '.$rsvalue.' ?'.">\r\n";
$cTag->tagValue = $rsvalue;
} else if ($tagname == 'datalist') {
//生成属性数组
foreach ($cTag->cAtt->items as $k => $v) {
$v = $this->TrimAtts($v);
$rsvalue .= '$atts[\''.$k.'\'] = \''.str_replace("'", "\\'", $v)."';\r\n";
}
$rsvalue = '<'.'?php'."\r\n".'$atts = array();'."\r\n".$rsvalue;
$rsvalue .= '$blockValue = $this->refObj->GetArcList($atts,$this->refObj,$fields); '."\r\n";
$rsvalue .= 'if(is_array($blockValue)){'."\r\n";
$rsvalue .= 'foreach( $blockValue as $key=>$fields )'."\r\n{\r\n".'?'.">";
$rsvalue .= $cTag->GetInnerText();
$rsvalue .= '<'.'?php'."\r\n}\r\n}".'?'.'>';
$cTag->tagValue = $rsvalue;
} else if ($tagname == 'pagelist') {
//生成属性数组
foreach ($cTag->cAtt->items as $k => $v) {
$v = $this->TrimAtts($v);
$rsvalue .= '$atts[\''.$k.'\'] = \''.str_replace("'", "\\'", $v)."';\r\n";
}
$rsvalue = '<'.'?php'."\r\n".'$atts = array();'."\r\n".$rsvalue;
$rsvalue .= ' echo $this->refObj->GetPageList($atts,$this->refObj,$fields); '."\r\n".'?'.">\r\n";
$cTag->tagValue = $rsvalue;
} else {
$bindFunc = $cTag->GetAtt('bind');
$bindType = $cTag->GetAtt('bindtype');
$rstype = ($cTag->GetAtt('resulttype') == '' ? $cTag->GetAtt('rstype') : $cTag->GetAtt('resulttype'));
$rstype = strtolower($rstype);
//生成属性数组
foreach ($cTag->cAtt->items as $k => $v) {
if (preg_match("/(bind|bindtype)/i", $k)) {
continue;
}
$v = $this->TrimAtts($v);
$rsvalue .= '$atts[\''.$k.'\'] = \''.str_replace("'", "\\'", $v)."';\r\n";
}
$rsvalue = '<'.'?php'."\r\n".'$atts = array();'."\r\n".$rsvalue;
//绑定到默认函数还是指定函数(datasource属性指定)
if ($bindFunc == '') {
$rsvalue .= '$blockValue = MakePublicTag($atts,$this->refObj,$fields); '."\r\n";
} else {
//自定义绑定函数如果不指定 bindtype,则指向$this->refObj->绑定函数名,即是默认指向被引用的类对象
if ($bindType == '') $rsvalue .= '$blockValue = $this->refObj->'.$bindFunc.'($atts,$this->refObj,$fields); '."\r\n";
else $rsvalue .= '$blockValue = '.$bindFunc.'($atts,$this->refObj,$fields); '."\r\n";
}
//返回结果类型:默认为 array 是一个二维数组,string 是字符串
if ($rstype == 'string') {
$rsvalue .= 'echo $blockValue;'."\r\n".'?'.">";
} else {
$rsvalue .= 'if(is_array($blockValue) && count($blockValue) > 0){'."\r\n";
$rsvalue .= 'foreach( $blockValue as $key=>$fields )'."\r\n{\r\n".'?'.">";
$rsvalue .= $cTag->GetInnerText();
$rsvalue .= '<'.'?php'."\r\n}\r\n}\r\n".'?'.'>';
}
$cTag->tagValue = $rsvalue;
}
return $cTag->tagValue;
}
/**
* 编译可能为数组的变量
*
* @access public
* @param string $vartype 变量类型
* @param string $varname 变量名称
* @return string
*/
function CompilerArrayVar($vartype, $varname)
{
$okvalue = '';
if (!preg_match("/\[/", $varname)) {
if (preg_match("/^value/", $vartype)) {
$varname = $vartype.'.'.$varname;
}
$varnames = explode('.', $varname);
if (isset($varnames[1])) {
$varname = $varnames[0];
for ($i = 1; isset($varnames[$i]); $i++) {
$varname .= "['".$varnames[$i]."']";
}
}
}
if (preg_match("/\[/", $varname)) {
$varnames = explode('[', $varname);
$arrend = '';
for ($i = 1; isset($varnames[$i]); $i++) {
$arrend .= '['.$varnames[$i];
}
if (!preg_match("/[\"']/", $arrend)) {
$arrend = str_replace('[', '', $arrend);
$arrend = str_replace(']', '', $arrend);
$arrend = "['{$arrend}']";
}
if ($vartype == 'var') {
$okvalue = '$GLOBALS[\'_vars\'][\''.$varnames[0].'\']'.$arrend;
} else if (preg_match("/^value/", $vartype)) {
$okvalue = '$'.$varnames[0].$arrend;
} else if ($vartype == 'field') {
$okvalue = '$fields[\''.$varnames[0].'\']'.$arrend;
} else {
$okvalue = '$GLOBALS[\''.$varnames[0].'\']'.$arrend;
}
} else {
if ($vartype == 'var') {
$okvalue = '$GLOBALS[\'_vars\'][\''.$varname.'\']';
} else if (preg_match("/^value/", $vartype)) {
$okvalue = '$'.$vartype;
} else if ($vartype == 'field') {
$okvalue = '$'.str_replace($varname);
} else {
$okvalue = '$GLOBALS[\''.$varname.'\']';
}
}
return $okvalue;
}
/**
* 编译if标记
*
* @access public
* @param string $cTag 标签
* @return string
*/
function CompilerIf($cTag)
{
$condition = trim($cTag->GetAtt('condition'));
if ($condition == '') {
$cTag->tagValue = '';
return '';
}
if (version_compare(PHP_VERSION, '5.5.0', '>=')) {
$condition = preg_replace_callback("/((var\.|field\.|cfg\.|global\.|key[0-9]{0,}\.|value[0-9]{0,}\.)[\._a-z0-9]+)/is", "private_rt", $condition);
} else {
$condition = preg_replace("/((var\.|field\.|cfg\.|global\.|key[0-9]{0,}\.|value[0-9]{0,}\.)[\._a-z0-9]+)/ies", "private_rt('\\1')", $condition);
}
$rsvalue = '<'.'?php if('.$condition.'){ ?'.'>';
$rsvalue .= $cTag->GetInnerText();
$rsvalue .= '<'.'?php } ?'.'>';
return $rsvalue;
}
/**
* 处理block区块传递的atts属性的值
*
* @access public
* @param string $v 值
* @return string
*/
function TrimAtts($v)
{
$v = str_replace('<'.'?', '<?', $v);
$v = str_replace('?'.'>', '?>', $v);
return $v;
}
/**
* 函数 function 语法处理
*
* @access public
* @param string $funcstr 函数字符串
* @param string $nvalue 函数值
* @return string
*/
function CompilerFunction($funcstr, $nvalue)
{
$funcstr = str_replace('@quote', '"', $funcstr);
$funcstr = str_replace('@me', $nvalue, $funcstr);
return $funcstr;
}
/**
* 引入文件 include 语法处理
*
* @access public
* @param string $filename 文件名
* @param string $isload 是否载入
* @return string
*/
function CompilerInclude($filename, $isload = TRUE)
{
$okfile = '';
if (@file_exists($filename)) {
$okfile = $filename;
} else if (@file_exists($this->refDir.$filename)) {
$okfile = $this->refDir.$filename;
} else if (@file_exists($this->refDir."../".$filename)) {
$okfile = $this->refDir."../".$filename;
}
if ($okfile == '') return 0;
if (!$isload) return 1;
$itpl = new DedeTemplate($this->templateDir);
$itpl->isCache = $this->isCache;
$itpl->SetObject($this->refObj);
$itpl->LoadTemplate($okfile);
return $itpl->CacheFile();
}
}
/**
* class TagAttribute Tag属性集合
* function C__TagAttribute();
* 属性的数据描述
*
* @package TagAttribute
* @subpackage DedeBIZ.Libraries
* @link https://www.dedebiz.com
*/
class TagAttribute
{
var $count = -1;
var $items = array(); //属性元素的集合
/**
* 获得某个属性
*
* @access public
* @param string $str 预处理字符串
* @return string
*/
function GetAtt($str)
{
if ($str == "") {
return "";
}
if (isset($this->items[$str])) {
return $this->items[$str];
} else {
return "";
}
}
/**
* 同上
*
* @access public
* @param string $str 预处理字符串
* @return string
*/
function GetAttribute($str)
{
return $this->GetAtt($str);
}
/**
* 判断属性是否存在
*
* @access public
* @param string $str 预处理字符串
* @return bool
*/
function IsAttribute($str)
{
if (isset($this->items[$str])) return TRUE;
else return FALSE;
}
/**
* 获得标记名称
*
* @access public
* @return string
*/
function GettagName()
{
return $this->GetAtt("tagname");
}
/**
* 获得属性个数
*
* @access public
* @return int
*/
function Getcount()
{
return $this->count + 1;
}
} //End Class
/**
* 属性解析器
* function C__TagAttributeParse();
*
* @package TagAttribute
* @subpackage DedeBIZ.Libraries
* @link https://www.dedebiz.com
*/
class TagAttributeParse
{
var $sourceString = "";
var $sourceMaxSize = 1024;
var $cAttributes;
var $charToLow = TRUE;
function SetSource($str = "")
{
$this->cAttributes = new TagAttribute();
$strLen = 0;
$this->sourceString = trim(preg_replace("/[ \r\n\t\f]{1,}/", " ", $str));
$strLen = strlen($this->sourceString);
if ($strLen > 0 && $strLen <= $this->sourceMaxSize) {
$this->ParseAttribute();
}
}
/**
* 解析属性
*
* @access public
* @return void
*/
function ParseAttribute()
{
$d = '';
$tmpatt = '';
$tmpvalue = '';
$startdd = -1;
$ddtag = '';
$hasAttribute = FALSE;
$strLen = strlen($this->sourceString);
$this->cAttributes->items = array();
//获得Tag的名称,解析到 cAtt->GetAtt('tagname') 中
for ($i = 0; $i < $strLen; $i++) {
if ($this->sourceString[$i] == ' ') {
$this->cAttributes->count++;
$tmpvalues = explode('.', $tmpvalue);
$this->cAttributes->items['tagname'] = ($this->charToLow ? strtolower($tmpvalues[0]) : $tmpvalues[0]);
if (isset($tmpvalues[2])) {
$okname = $tmpvalues[1];
for ($j = 2; isset($tmpvalues[$j]); $j++) {
$okname .= "['".$tmpvalues[$j]."']";
}
$this->cAttributes->items['name'] = $okname;
} else if (isset($tmpvalues[1]) && $tmpvalues[1] != '') {
$this->cAttributes->items['name'] = $tmpvalues[1];
}
$tmpvalue = '';
$hasAttribute = TRUE;
break;
} else {
$tmpvalue .= $this->sourceString[$i];
}
}
//不存在属性列表的情况
if (!$hasAttribute) {
$this->cAttributes->count++;
$tmpvalues = explode('.', $tmpvalue);
$this->cAttributes->items['tagname'] = ($this->charToLow ? strtolower($tmpvalues[0]) : $tmpvalues[0]);
if (isset($tmpvalues[2])) {
$okname = $tmpvalues[1];
for ($i = 2; isset($tmpvalues[$i]); $i++) {
$okname .= "['".$tmpvalues[$i]."']";
}
$this->cAttributes->items['name'] = $okname;
} else if (isset($tmpvalues[1]) && $tmpvalues[1] != '') {
$this->cAttributes->items['name'] = $tmpvalues[1];
}
return;
}
$tmpvalue = '';
//如果字符串含有属性值,遍历源字符串,并获得各属性
for ($i; $i < $strLen; $i++) {
$d = $this->sourceString[$i];
//查找属性名称
if ($startdd == -1) {
if ($d != '=') {
$tmpatt .= $d;
} else {
if ($this->charToLow) {
$tmpatt = strtolower(trim($tmpatt));
} else {
$tmpatt = trim($tmpatt);
}
$startdd = 0;
}
}
//查找属性的限定标志
else if ($startdd == 0) {
switch ($d) {
case ' ':
break;
case '\'':
$ddtag = '\'';
$startdd = 1;
break;
case '"':
$ddtag = '"';
$startdd = 1;
break;
default:
$tmpvalue .= $d;
$ddtag = ' ';
$startdd = 1;
break;
}
} else if ($startdd == 1) {
if ($d == $ddtag && (isset($this->sourceString[$i - 1]) && $this->sourceString[$i - 1] != "\\")) {
$this->cAttributes->count++;
$this->cAttributes->items[$tmpatt] = trim($tmpvalue);
$tmpatt = '';
$tmpvalue = '';
$startdd = -1;
} else {
$tmpvalue .= $d;
}
}
} //for
//最后一个属性的给值
if ($tmpatt != '') {
$this->cAttributes->count++;
$this->cAttributes->items[$tmpatt] = trim($tmpvalue);
} //print_r($this->cAttributes->items);
} //end func
} //End Class
/**
* 私有标签编译,主要用于if标签内的字符串解析
*
* @access public
* @param string $str 需要编译的字符串
* @return string
*/
function private_rt($str)
{
if (is_array($str)) {
$arr = explode('.', $str[0]);
} else {
$arr = explode('.', $str);
}
$rs = '$GLOBALS[\'';
if ($arr[0] == 'cfg') {
return $rs.'cfg_'.$arr[1]."']";
} elseif ($arr[0] == 'var') {
$arr[0] = '_vars';
$rs .= implode('\'][\'', $arr);
$rs .= "']";
return $rs;
} elseif ($arr[0] == 'global') {
unset($arr[0]);
$rs .= implode('\'][\'', $arr);
$rs .= "']";
return $rs;
} else {
if ($arr[0] == 'field') $arr[0] = 'fields';
$rs = '$'.$arr[0]."['";
unset($arr[0]);
$rs .= implode('\'][\'', $arr);
$rs .= "']";
return $rs;
}
}