国内流行的内容管理系统(CMS)多端全媒体解决方案 https://www.dedebiz.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1353 lines
45KB

  1. <?php
  2. if (!defined('DEDEINC')) exit('dedebiz');
  3. /**
  4. * 模板引擎文件
  5. *
  6. * @version $Id: dedetemplate.class.php 3 15:44 2010年7月6日Z tianya $
  7. * @package DedeBIZ.Libraries
  8. * @copyright Copyright (c) 2022, DedeBIZ.COM
  9. * @license https://www.dedebiz.com/license
  10. * @link https://www.dedebiz.com
  11. */
  12. /**
  13. * 这个函数用于定义任意名称的块使用的接口
  14. * 返回值应是一个二维数组
  15. * 块调用对应的文件为 include/taglib/plus_blockname.php
  16. * ----------------------------------------------------------------
  17. * 由于标记一般存在默认属性,在编写块函数时,应该在块函数中进行给属性赋省缺值处理,如:
  18. * $attlist = "titlelen=30,catalogid=0,modelid=0,flag=,addon=,row=8,ids=,orderby=id,orderway=desc,limit=,subday=0";
  19. * 给属性赋省缺值
  20. * FillAtts($atts,$attlist);
  21. * 处理属性中使用的系统变量 var、global、field 类型(不支持多维数组)
  22. * FillFields($atts,$fields,$refObj);
  23. *
  24. * @access public
  25. * @param array $atts 属性
  26. * @param object $refObj 所属对象
  27. * @param array $fields 字段
  28. * @return string
  29. */
  30. function MakePublicTag($atts = array(), $refObj = '', $fields = array())
  31. {
  32. $atts['tagname'] = preg_replace("/[0-9]{1,}$/", "", $atts['tagname']);
  33. $plusfile = DEDEINC.'/tpllib/plus_'.$atts['tagname'].'.php';
  34. if (!file_exists($plusfile)) {
  35. if (isset($atts['rstype']) && $atts['rstype'] == 'string') {
  36. return '';
  37. } else {
  38. return array();
  39. }
  40. } else {
  41. include_once($plusfile);
  42. $func = 'plus_'.$atts['tagname'];
  43. return $func($atts, $refObj, $fields);
  44. }
  45. }
  46. /**
  47. * 设定属性的默认值
  48. *
  49. * @access public
  50. * @param array $atts 属性
  51. * @param array $attlist 属性列表
  52. * @return void
  53. */
  54. function FillAtts(&$atts, $attlist)
  55. {
  56. $attlists = explode(',', $attlist);
  57. foreach ($attlists as $att) {
  58. list($k, $v) = explode('=', $att);
  59. if (!isset($atts[$k])) {
  60. $atts[$k] = $v;
  61. }
  62. }
  63. }
  64. /**
  65. * 把上级的fields传递给atts
  66. *
  67. * @access public
  68. * @param array $atts 属性
  69. * @param object $refObj 所属对象
  70. * @param array $fields 字段
  71. * @return string
  72. */
  73. function FillFields(&$atts, &$refObj, &$fields)
  74. {
  75. global $_vars;
  76. foreach ($atts as $k => $v) {
  77. if (preg_match('/^field\./i', $v)) {
  78. $key = preg_replace('/^field\./i', '', $v);
  79. if (isset($fields[$key])) {
  80. $atts[$k] = $fields[$key];
  81. }
  82. } else if (preg_match('/^var\./i', $v)) {
  83. $key = preg_replace('/^var\./i', '', $v);
  84. if (isset($_vars[$key])) {
  85. $atts[$k] = $_vars[$key];
  86. }
  87. } else if (preg_match('/^global\./i', $v)) {
  88. $key = preg_replace('/^global\./i', '', $v);
  89. if (isset($GLOBALS[$key])) {
  90. $atts[$k] = $GLOBALS[$key];
  91. }
  92. }
  93. }
  94. }
  95. /**
  96. * class Tag 标记的数据结构描述
  97. * function C__Tag();
  98. *
  99. * @package Tag
  100. * @subpackage DedeBIZ.Libraries
  101. * @link https://www.dedebiz.com
  102. */
  103. class Tag
  104. {
  105. var $isCompiler = FALSE; //标记是否已被替代,供解析器使用
  106. var $tagName = ""; //标记名称
  107. var $innerText = ""; //标记之间的文本
  108. var $startPos = 0; //标记起始位置
  109. var $endPos = 0; //标记结束位置
  110. var $cAtt; //标记属性描述,即是class TagAttribute
  111. var $tagValue = ""; //标记的值
  112. var $tagID = 0;
  113. /**
  114. * 获取标记的名称和值
  115. *
  116. * @access public
  117. * @return string
  118. */
  119. function GetName()
  120. {
  121. return strtolower($this->tagName);
  122. }
  123. function GetValue()
  124. {
  125. return $this->tagValue;
  126. }
  127. function IsAtt($str)
  128. {
  129. return $this->cAtt->IsAttribute($str);
  130. }
  131. function GetAtt($str)
  132. {
  133. return $this->cAtt->GetAtt($str);
  134. }
  135. /**
  136. * 获取底层模板
  137. *
  138. * @return string
  139. */
  140. function GetinnerText()
  141. {
  142. return $this->innerText;
  143. }
  144. }
  145. /**
  146. * 模板解析器
  147. * function C__DedeTemplate
  148. *
  149. * @package DedeTemplate
  150. * @subpackage DedeBIZ.Libraries
  151. * @link https://www.dedebiz.com
  152. */
  153. class DedeTemplate
  154. {
  155. var $tagMaxLen = 64;
  156. var $charToLow = TRUE;
  157. var $isCache = TRUE;
  158. var $isParse = FALSE;
  159. var $isCompiler = TRUE;
  160. var $templateDir = '';
  161. var $tempMkTime = 0;
  162. var $cacheFile = '';
  163. var $configFile = '';
  164. var $buildFile = '';
  165. var $refDir = '';
  166. var $cacheDir = '';
  167. var $templateFile = '';
  168. var $sourceString = '';
  169. var $cTags = array();
  170. //var $definedVars = array();
  171. var $count = -1;
  172. var $loopNum = 0;
  173. var $refObj = '';
  174. var $makeLoop = 0;
  175. var $tagStartWord = '{dede:';
  176. var $fullTagEndWord = '{/dede:';
  177. var $sTagEndWord = '/}';
  178. var $tagEndWord = '}';
  179. var $tpCfgs = array();
  180. /**
  181. * 析构函数
  182. *
  183. * @access public
  184. * @param string $templatedir 模板目录
  185. * @param string $refDir 所属目录
  186. * @return void
  187. */
  188. function __construct($templatedir = '', $refDir = '')
  189. {
  190. //$definedVars[] = 'var';
  191. //缓存目录
  192. if ($templatedir == '') {
  193. $this->templateDir = DEDEROOT.'/templates';
  194. } else {
  195. $this->templateDir = $templatedir;
  196. }
  197. //模板include目录
  198. if ($refDir == '') {
  199. if (isset($GLOBALS['cfg_df_style'])) {
  200. $this->refDir = $this->templateDir.'/'.$GLOBALS['cfg_df_style'].'/';
  201. } else {
  202. $this->refDir = $this->templateDir;
  203. }
  204. }
  205. $this->cacheDir = DEDEROOT.$GLOBALS['cfg_tplcache_dir'];
  206. }
  207. //构造函数,兼容PHP4
  208. function DedeTemplate($templatedir = '', $refDir = '')
  209. {
  210. $this->__construct($templatedir, $refDir);
  211. }
  212. /**
  213. * 设定本类自身实例的类引用和使用本类的类实例(如果在类中使用本模板引擎,后一参数一般为$this)
  214. *
  215. * @access public
  216. * @param object $refObj 实例对象
  217. * @return string
  218. */
  219. function SetObject(&$refObj)
  220. {
  221. $this->refObj = $refObj;
  222. }
  223. /**
  224. * 设定Var的键值对
  225. *
  226. * @access public
  227. * @param string $k 键
  228. * @param string $v 值
  229. * @return string
  230. */
  231. function SetVar($k, $v)
  232. {
  233. $GLOBALS['_vars'][$k] = $v;
  234. }
  235. /**
  236. * 设定Var的键值对
  237. *
  238. * @access public
  239. * @param string $k 键
  240. * @param string $v 值
  241. * @return string
  242. */
  243. function Assign($k, $v)
  244. {
  245. $GLOBALS['_vars'][$k] = $v;
  246. }
  247. /**
  248. * 设定数组
  249. *
  250. * @access public
  251. * @param string $k 键
  252. * @param string $v 值
  253. * @return string
  254. */
  255. function SetArray($k, $v)
  256. {
  257. $GLOBALS[$k] = $v;
  258. }
  259. /**
  260. * 设置标记风格
  261. *
  262. * @access public
  263. * @param string $ts 标签开始标记
  264. * @param string $ftend 标签结束标记
  265. * @param string $stend 标签尾部结束标记
  266. * @param string $tend 结束标记
  267. * @return void
  268. */
  269. function SetTagStyle($ts = '{dede:', $ftend = '{/dede:', $stend = '/}', $tend = '}')
  270. {
  271. $this->tagStartWord = $ts;
  272. $this->fullTagEndWord = $ftend;
  273. $this->sTagEndWord = $stend;
  274. $this->tagEndWord = $tend;
  275. }
  276. /**
  277. * 获得模板设定的config值
  278. *
  279. * @access public
  280. * @param string $k 键名
  281. * @return string
  282. */
  283. function GetConfig($k)
  284. {
  285. return (isset($this->tpCfgs[$k]) ? $this->tpCfgs[$k] : '');
  286. }
  287. /**
  288. * 设定模板文件
  289. *
  290. * @access public
  291. * @param string $tmpfile 模板文件
  292. * @return void
  293. */
  294. function LoadTemplate($tmpfile)
  295. {
  296. if (!file_exists($tmpfile)) {
  297. echo " Template Not Found! ";
  298. exit();
  299. }
  300. $tmpfile = preg_replace("/[\\/]{1,}/", "/", $tmpfile);
  301. $tmpfiles = explode('/', $tmpfile);
  302. $tmpfileOnlyName = preg_replace("/(.*)\//", "", $tmpfile);
  303. $this->templateFile = $tmpfile;
  304. $this->refDir = '';
  305. for ($i = 0; $i < count($tmpfiles) - 1; $i++) {
  306. $this->refDir .= $tmpfiles[$i].'/';
  307. }
  308. if (!is_dir($this->cacheDir)) {
  309. $this->cacheDir = $this->refDir;
  310. }
  311. if ($this->cacheDir != '') {
  312. $this->cacheDir = $this->cacheDir.'/';
  313. }
  314. if (isset($GLOBALS['_DEBUG_CACHE'])) {
  315. $this->cacheDir = $this->refDir;
  316. }
  317. $this->cacheFile = $this->cacheDir.preg_replace("/\.(wml|html|htm|php)$/", "_".$this->GetEncodeStr($tmpfile).'.inc', $tmpfileOnlyName);
  318. $this->configFile = $this->cacheDir.preg_replace("/\.(wml|html|htm|php)$/", "_".$this->GetEncodeStr($tmpfile).'_config.inc', $tmpfileOnlyName);
  319. //不开启缓存、当缓存文件不存在、及模板为更新的文件的时候才载入模板并进行解析
  320. if (
  321. $this->isCache == FALSE || !file_exists($this->cacheFile)
  322. || filemtime($this->templateFile) > filemtime($this->cacheFile)
  323. ) {
  324. $t1 = ExecTime(); //debug
  325. $fp = fopen($this->templateFile, 'r');
  326. $this->sourceString = fread($fp, filesize($this->templateFile));
  327. fclose($fp);
  328. $this->ParseTemplate();
  329. //模板解析时间
  330. //echo ExecTime() - $t1;
  331. } else {
  332. //如果存在config文件,则载入此文件,该文件用于保存 $this->tpCfgs的内容,以供扩展用途
  333. //模板中用{tag:config name='' value=''/}来设定该值
  334. if (file_exists($this->configFile)) {
  335. include($this->configFile);
  336. }
  337. }
  338. }
  339. /**
  340. * 载入模板字符串
  341. *
  342. * @access public
  343. * @param string $str 模板字符串
  344. * @return void
  345. */
  346. function LoadString($str = '')
  347. {
  348. $this->sourceString = $str;
  349. $hashcode = md5($this->sourceString);
  350. $this->cacheFile = $this->cacheDir."/string_".$hashcode.".inc";
  351. $this->configFile = $this->cacheDir."/string_".$hashcode."_config.inc";
  352. $this->ParseTemplate();
  353. }
  354. /**
  355. * 调用此函数include一个编译后的PHP文件,通常是在最后一个步骤才调用本文件
  356. *
  357. * @access public
  358. * @return string
  359. */
  360. function CacheFile()
  361. {
  362. global $gtmpfile;
  363. $this->WriteCache();
  364. return $this->cacheFile;
  365. }
  366. /**
  367. * 显示内容,由于函数中会重新解压一次$GLOBALS变量,所以在动态页中,应该尽量少用本方法,
  368. * 取代之是直接在程序中 include $tpl->CacheFile(),不过include $tpl->CacheFile()这种方式不能在类或函数内使用
  369. *
  370. * @access public
  371. * @param string
  372. * @return void
  373. */
  374. function Display()
  375. {
  376. global $gtmpfile;
  377. extract($GLOBALS, EXTR_SKIP);
  378. $this->WriteCache();
  379. include $this->cacheFile;
  380. }
  381. /**
  382. * 保存运行后的程序为文件
  383. *
  384. * @access public
  385. * @param string $savefile 保存到的文件目录
  386. * @return void
  387. */
  388. function SaveTo($savefile)
  389. {
  390. extract($GLOBALS, EXTR_SKIP);
  391. $this->WriteCache();
  392. ob_start();
  393. include $this->cacheFile;
  394. $okstr = ob_get_contents();
  395. ob_end_clean();
  396. $fp = @fopen($savefile, "w") or die(" Tag Engine Create File FALSE! ");
  397. fwrite($fp, $okstr);
  398. fclose($fp);
  399. }
  400. //------------------------------------------------------------------------
  401. /**
  402. * CheckDisabledFunctions
  403. *
  404. * COMMENT : CheckDisabledFunctions : 检查是否存在禁止的函数
  405. *
  406. * @access public
  407. * @param string
  408. * @return bool
  409. */
  410. function CheckDisabledFunctions($str, &$errmsg = '')
  411. {
  412. global $cfg_disable_funs;
  413. $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';
  414. //模板引擎增加disable_functions
  415. if (!defined('DEDEDISFUN')) {
  416. $tokens = token_get_all_nl($str);
  417. $disabled_functions = explode(',', $cfg_disable_funs);
  418. foreach ($tokens as $token) {
  419. if (is_array($token)) {
  420. if ($token[0] = '306' && in_array($token[1], $disabled_functions)) {
  421. $errmsg = 'DedeBIZ Error:function disabled "'.$token[1].'" <a href="https://www.dedebiz.com/help" target="_blank">more...</a>';
  422. return FALSE;
  423. }
  424. }
  425. }
  426. }
  427. return TRUE;
  428. }
  429. /**
  430. * 解析模板并写缓存文件
  431. *
  432. * @access public
  433. * @param string $ctype 缓存类型
  434. * @return void
  435. */
  436. function WriteCache($ctype = 'all')
  437. {
  438. if (
  439. !file_exists($this->cacheFile) || $this->isCache == FALSE
  440. || (file_exists($this->templateFile) && (filemtime($this->templateFile) > filemtime($this->cacheFile)))
  441. ) {
  442. if (!$this->isParse) {
  443. $this->ParseTemplate();
  444. }
  445. $fp = fopen($this->cacheFile, 'w') or dir("Write Cache File Error! ");
  446. flock($fp, 3);
  447. $result = trim($this->GetResult());
  448. $errmsg = '';
  449. //var_dump($result);exit();
  450. if (!$this->CheckDisabledFunctions($result, $errmsg)) {
  451. fclose($fp);
  452. @unlink($this->cacheFile);
  453. die($errmsg);
  454. }
  455. fwrite($fp, $result);
  456. fclose($fp);
  457. if (count($this->tpCfgs) > 0) {
  458. $fp = fopen($this->configFile, 'w') or dir("Write Config File Error! ");
  459. flock($fp, 3);
  460. fwrite($fp, '<'.'?php'."\r\n");
  461. foreach ($this->tpCfgs as $k => $v) {
  462. $v = str_replace("\"", "\\\"", $v);
  463. $v = str_replace("\$", "\\\$", $v);
  464. fwrite($fp, "\$this->tpCfgs['$k']=\"$v\";\r\n");
  465. }
  466. fwrite($fp, '?'.'>');
  467. fclose($fp);
  468. }
  469. }
  470. /*
  471. if(!file_exists($this->cacheFile) || $this->isCache==FALSE
  472. || ( file_exists($this->templateFile) && (filemtime($this->templateFile) > filemtime($this->cacheFile)) ) )
  473. {
  474. if($ctype!='config')
  475. {
  476. if(!$this->isParse)
  477. {
  478. $this->ParseTemplate();
  479. }
  480. $fp = fopen($this->cacheFile,'w') or dir("Write Cache File Error! ");
  481. flock($fp,3);
  482. fwrite($fp,trim($this->GetResult()));
  483. fclose($fp);
  484. }
  485. else
  486. {
  487. if(count($this->tpCfgs) > 0)
  488. {
  489. $fp = fopen($this->configFile,'w') or dir("Write Config File Error! ");
  490. flock($fp,3);
  491. fwrite($fp,'<'.'?php'."\r\n");
  492. foreach($this->tpCfgs as $k=>$v)
  493. {
  494. $v = str_replace("\"","\\\"",$v);
  495. $v = str_replace("\$","\\\$",$v);
  496. fwrite($fp,"\$this->tpCfgs['$k']=\"$v\";\r\n");
  497. }
  498. fwrite($fp,'?'.'>');
  499. fclose($fp);
  500. }
  501. }
  502. }
  503. else
  504. {
  505. if($ctype=='config' && count($this->tpCfgs) > 0 )
  506. {
  507. $fp = fopen($this->configFile,'w') or dir("Write Config File Error! ");
  508. flock($fp,3);
  509. fwrite($fp,'<'.'?php'."\r\n");
  510. foreach($this->tpCfgs as $k=>$v)
  511. {
  512. $v = str_replace("\"","\\\"",$v);
  513. $v = str_replace("\$","\\\$",$v);
  514. fwrite($fp,"\$this->tpCfgs['$k']=\"$v\";\r\n");
  515. }
  516. fwrite($fp,'?'.'>');
  517. fclose($fp);
  518. }
  519. }
  520. */
  521. }
  522. /**
  523. * 获得模板文件名的md5字符串
  524. *
  525. * @access public
  526. * @param string $tmpfile 模板文件
  527. * @return string
  528. */
  529. function GetEncodeStr($tmpfile)
  530. {
  531. //$tmpfiles = explode('/',$tmpfile);
  532. $encodeStr = substr(md5($tmpfile), 0, 24);
  533. return $encodeStr;
  534. }
  535. /**
  536. * 解析模板
  537. *
  538. * @access public
  539. * @return void
  540. */
  541. function ParseTemplate()
  542. {
  543. if ($this->makeLoop > 5) {
  544. return;
  545. }
  546. $this->count = -1;
  547. $this->cTags = array();
  548. $this->isParse = TRUE;
  549. $sPos = 0;
  550. $ePos = 0;
  551. $tagStartWord = $this->tagStartWord;
  552. $fullTagEndWord = $this->fullTagEndWord;
  553. $sTagEndWord = $this->sTagEndWord;
  554. $tagEndWord = $this->tagEndWord;
  555. $startWordLen = strlen($tagStartWord);
  556. $sourceLen = strlen($this->sourceString);
  557. if ($sourceLen <= ($startWordLen + 3)) {
  558. return;
  559. }
  560. $cAtt = new TagAttributeParse();
  561. $cAtt->CharToLow = TRUE;
  562. //遍历模板字符串,请取标记及其属性信息
  563. $t = 0;
  564. $preTag = '';
  565. $tswLen = strlen($tagStartWord);
  566. for ($i = 0; $i < $sourceLen; $i++) {
  567. $ttagName = '';
  568. //如果不进行此判断,将无法识别相连的两个标记
  569. if ($i - 1 >= 0) {
  570. $ss = $i - 1;
  571. } else {
  572. $ss = 0;
  573. }
  574. $tagPos = strpos($this->sourceString, $tagStartWord, $ss);
  575. //判断后面是否还有模板标记
  576. if ($tagPos == 0 && ($sourceLen - $i < $tswLen
  577. || substr($this->sourceString, $i, $tswLen) != $tagStartWord)) {
  578. $tagPos = -1;
  579. break;
  580. }
  581. //获取TAG基本信息
  582. for ($j = $tagPos + $startWordLen; $j < $tagPos + $startWordLen + $this->tagMaxLen; $j++) {
  583. if (preg_match("/[ >\/\r\n\t\}\.]/", $this->sourceString[$j])) {
  584. break;
  585. } else {
  586. $ttagName .= $this->sourceString[$j];
  587. }
  588. }
  589. if ($ttagName != '') {
  590. $i = $tagPos + $startWordLen;
  591. $endPos = -1;
  592. //判断 '/}' '{tag:下一标记开始' '{/tag:标记结束' 谁最靠近
  593. $fullTagEndWordThis = $fullTagEndWord.$ttagName.$tagEndWord;
  594. $e1 = strpos($this->sourceString, $sTagEndWord, $i);
  595. $e2 = strpos($this->sourceString, $tagStartWord, $i);
  596. $e3 = strpos($this->sourceString, $fullTagEndWordThis, $i);
  597. $e1 = trim($e1);
  598. $e2 = trim($e2);
  599. $e3 = trim($e3);
  600. $e1 = ($e1 == '' ? '-1' : $e1);
  601. $e2 = ($e2 == '' ? '-1' : $e2);
  602. $e3 = ($e3 == '' ? '-1' : $e3);
  603. if ($e3 == -1) {
  604. //不存在'{/tag:标记'
  605. $endPos = $e1;
  606. $elen = $endPos + strlen($sTagEndWord);
  607. } else if ($e1 == -1) {
  608. //不存在 '/}'
  609. $endPos = $e3;
  610. $elen = $endPos + strlen($fullTagEndWordThis);
  611. }
  612. //同时存在 '/}' 和 '{/tag:标记'
  613. else {
  614. //如果 '/}' 比 '{tag:'、'{/tag:标记' 都要靠近,则认为结束标志是 '/}',否则结束标志为 '{/tag:标记'
  615. if ($e1 < $e2 && $e1 < $e3) {
  616. $endPos = $e1;
  617. $elen = $endPos + strlen($sTagEndWord);
  618. } else {
  619. $endPos = $e3;
  620. $elen = $endPos + strlen($fullTagEndWordThis);
  621. }
  622. }
  623. //如果找不到结束标记,则认为这个标记存在错误
  624. if ($endPos == -1) {
  625. echo "Tpl Character postion $tagPos, '$ttagName' Error<br />\r\n";
  626. break;
  627. }
  628. $i = $elen;
  629. //分析所找到的标记位置等信息
  630. $attStr = '';
  631. $innerText = '';
  632. $startInner = 0;
  633. for ($j = $tagPos + $startWordLen; $j < $endPos; $j++) {
  634. if ($startInner == 0) {
  635. if ($this->sourceString[$j] == $tagEndWord) {
  636. $startInner = 1;
  637. continue;
  638. } else {
  639. $attStr .= $this->sourceString[$j];
  640. }
  641. } else {
  642. $innerText .= $this->sourceString[$j];
  643. }
  644. }
  645. $ttagName = strtolower($ttagName);
  646. //if、php标记,把整个属性串视为属性
  647. if (preg_match("/^if[0-9]{0,}$/", $ttagName)) {
  648. $cAtt->cAttributes = new TagAttribute();
  649. $cAtt->cAttributes->count = 2;
  650. $cAtt->cAttributes->items['tagname'] = $ttagName;
  651. $cAtt->cAttributes->items['condition'] = preg_replace("/^if[0-9]{0,}[\r\n\t ]/", "", $attStr);
  652. $innerText = preg_replace("/\{else\}/i", '<'."?php\r\n}\r\nelse{\r\n".'?'.'>', $innerText);
  653. } else if ($ttagName == 'php') {
  654. $cAtt->cAttributes = new TagAttribute();
  655. $cAtt->cAttributes->count = 2;
  656. $cAtt->cAttributes->items['tagname'] = $ttagName;
  657. $cAtt->cAttributes->items['code'] = '<'."?php\r\n".trim(preg_replace(
  658. "/^php[0-9]{0,}[\r\n\t ]/",
  659. "",
  660. $attStr
  661. ))."\r\n?".'>';
  662. } else {
  663. //普通标记,解释属性
  664. $cAtt->SetSource($attStr);
  665. }
  666. $this->count++;
  667. $cTag = new Tag();
  668. $cTag->tagName = $ttagName;
  669. $cTag->startPos = $tagPos;
  670. $cTag->endPos = $i;
  671. $cTag->cAtt = $cAtt->cAttributes;
  672. $cTag->isCompiler = FALSE;
  673. $cTag->tagID = $this->count;
  674. $cTag->innerText = $innerText;
  675. $this->cTags[$this->count] = $cTag;
  676. } else {
  677. $i = $tagPos + $startWordLen;
  678. break;
  679. }
  680. } //结束遍历模板字符串
  681. if ($this->count > -1 && $this->isCompiler) {
  682. $this->CompilerAll();
  683. }
  684. }
  685. /**
  686. * 把模板标记转换为PHP代码
  687. *
  688. * @access public
  689. * @return void
  690. */
  691. function CompilerAll()
  692. {
  693. $this->loopNum++;
  694. if ($this->loopNum > 10) {
  695. return; //限制最大递归深度为 10 以防止因标记出错等可能性导致死循环
  696. }
  697. $ResultString = '';
  698. $nextTagEnd = 0;
  699. for ($i = 0; isset($this->cTags[$i]); $i++) {
  700. $ResultString .= substr($this->sourceString, $nextTagEnd, $this->cTags[$i]->startPos - $nextTagEnd);
  701. $ResultString .= $this->CompilerOneTag($this->cTags[$i]);
  702. $nextTagEnd = $this->cTags[$i]->endPos;
  703. }
  704. $slen = strlen($this->sourceString);
  705. if ($slen > $nextTagEnd) {
  706. $ResultString .= substr($this->sourceString, $nextTagEnd, $slen - $nextTagEnd);
  707. }
  708. $this->sourceString = $ResultString;
  709. $this->ParseTemplate();
  710. }
  711. /**
  712. * 获得最终结果
  713. *
  714. * @access public
  715. * @return string
  716. */
  717. function GetResult()
  718. {
  719. if (!$this->isParse) {
  720. $this->ParseTemplate();
  721. }
  722. $addset = '';
  723. $addset .= '<'.'?php'."\r\n".'if(!isset($GLOBALS[\'_vars\'])) $GLOBALS[\'_vars\'] = array(); '."\r\n".'$fields = array();'."\r\n".'?'.'>';
  724. return preg_replace("/\?".">[ \r\n\t]{0,}<"."\?php/", "", $addset.$this->sourceString);
  725. }
  726. /**
  727. * 编译单个标记
  728. *
  729. * @access public
  730. * @param object $cTag 标签
  731. * @return string
  732. */
  733. function CompilerOneTag(&$cTag)
  734. {
  735. $cTag->isCompiler = TRUE;
  736. $tagname = $cTag->tagName;
  737. $varname = $cTag->GetAtt('name');
  738. $rsvalue = "";
  739. //用于在模板中设置一个变量以提供作扩展用途
  740. //此变量直接提交到 this->tpCfgs 中,并会生成与模板对应的缓存文件 ***_config.php 文件
  741. if ($tagname == 'config') {
  742. $this->tpCfgs[$varname] = $cTag->GetAtt('value');
  743. } else if ($tagname == 'global') {
  744. $cTag->tagValue = $this->CompilerArrayVar('global', $varname);
  745. if ($cTag->GetAtt('function') != '') {
  746. $cTag->tagValue = $this->CompilerFunction($cTag->GetAtt('function'), $cTag->tagValue);
  747. }
  748. $cTag->tagValue = '<'.'?php echo '.$cTag->tagValue.'; ?'.'>';
  749. } else if ($tagname == 'cfg') {
  750. $cTag->tagValue = '$GLOBALS[\'cfg_'.$varname.'\']'; //处理函数
  751. if ($cTag->GetAtt('function') != '') {
  752. $cTag->tagValue = $this->CompilerFunction($cTag->GetAtt('function'), $cTag->tagValue);
  753. }
  754. $cTag->tagValue = '<'.'?php echo '.$cTag->tagValue.'; ?'.'>';
  755. } else if ($tagname == 'name') {
  756. $cTag->tagValue = '$'.$varname; //处理函数
  757. if ($cTag->GetAtt('function') != '') {
  758. $cTag->tagValue = $this->CompilerFunction($cTag->GetAtt('function'), $cTag->tagValue);
  759. }
  760. $cTag->tagValue = '<'.'?php echo '.$cTag->tagValue.'; ?'.'>';
  761. } else if ($tagname == 'object') {
  762. list($_obs, $_em) = explode('->', $varname);
  763. $cTag->tagValue = "\$GLOBALS['{$_obs}']->{$_em}"; //处理函数
  764. if ($cTag->GetAtt('function') != '') {
  765. $cTag->tagValue = $this->CompilerFunction($cTag->GetAtt('function'), $cTag->tagValue);
  766. }
  767. $cTag->tagValue = '<'.'?php echo '.$cTag->tagValue.'; ?'.'>';
  768. } else if ($tagname == 'var') {
  769. $cTag->tagValue = $this->CompilerArrayVar('var', $varname);
  770. if ($cTag->GetAtt('function') != '') {
  771. $cTag->tagValue = $this->CompilerFunction($cTag->GetAtt('function'), $cTag->tagValue);
  772. }
  773. //增加默认空值处理
  774. if ($cTag->GetAtt('default') != '') {
  775. $cTag->tagValue = '<'.'?php echo empty('.$cTag->tagValue.')? \''.addslashes($cTag->GetAtt('default')).'\':'.$cTag->tagValue.'; ?'.'>';
  776. } else {
  777. $cTag->tagValue = '<'.'?php echo '.$cTag->tagValue.'; ?'.'>';
  778. }
  779. } else if ($tagname == 'field') {
  780. $cTag->tagValue = '$fields[\''.$varname.'\']';
  781. if ($cTag->GetAtt('function') != '') {
  782. $cTag->tagValue = $this->CompilerFunction($cTag->GetAtt('function'), $cTag->tagValue);
  783. }
  784. $cTag->tagValue = '<'.'?php echo '.$cTag->tagValue.'; ?'.'>';
  785. } else if (preg_match("/^key[0-9]{0,}/", $tagname) || preg_match("/^value[0-9]{0,}/", $tagname)) {
  786. if (preg_match("/^value[0-9]{0,}/", $tagname) && $varname != '') {
  787. $cTag->tagValue = '<'.'?php echo '.$this->CompilerArrayVar($tagname, $varname).'; ?'.'>';
  788. } else {
  789. $cTag->tagValue = '<'.'?php echo $'.$tagname.'; ?'.'>';
  790. }
  791. } else if (preg_match("/^if[0-9]{0,}$/", $tagname)) {
  792. $cTag->tagValue = $this->CompilerIf($cTag);
  793. } else if ($tagname == 'echo') {
  794. if (trim($cTag->GetInnerText()) == '') $cTag->tagValue = $cTag->GetAtt('code');
  795. else {
  796. $cTag->tagValue = '<'."?php echo $".trim($cTag->GetInnerText())." ;?".'>';
  797. }
  798. } else if ($tagname == 'php') {
  799. if (trim($cTag->GetInnerText()) == '') $cTag->tagValue = $cTag->GetAtt('code');
  800. else {
  801. $cTag->tagValue = '<'."?php\r\n".trim($cTag->GetInnerText())."\r\n?".'>';
  802. }
  803. }
  804. //遍历数组
  805. else if (preg_match("/^array[0-9]{0,}/", $tagname)) {
  806. $kk = '$key';
  807. $vv = '$value';
  808. if ($cTag->GetAtt('key') != '') {
  809. $kk = '$key'.$cTag->GetAtt('key');
  810. }
  811. if ($cTag->GetAtt('value') != '') {
  812. $vv = '$value'.$cTag->GetAtt('value');
  813. }
  814. $addvar = '';
  815. if (!preg_match("/\(/", $varname)) {
  816. $varname = '$GLOBALS[\''.$varname.'\']';
  817. } else {
  818. $addvar = "\r\n".'$myarrs = $pageClass->'.$varname.";\r\n";
  819. $varname = ' $myarrs ';
  820. }
  821. $rsvalue = '<'.'?php '.$addvar.' foreach('.$varname.' as '.$kk.'=>'.$vv.'){ ?'.">";
  822. $rsvalue .= $cTag->GetInnerText();
  823. $rsvalue .= '<'.'?php } ?'.">\r\n";
  824. $cTag->tagValue = $rsvalue;
  825. }
  826. //include 文件
  827. else if ($tagname == 'include') {
  828. $filename = $cTag->GetAtt('file');
  829. if ($filename == '') {
  830. $filename = $cTag->GetAtt('filename');
  831. }
  832. $cTag->tagValue = $this->CompilerInclude($filename, FALSE);
  833. if ($cTag->tagValue == 0) $cTag->tagValue = '';
  834. $cTag->tagValue = '<'.'?php include $this->CompilerInclude("'.$filename.'");'."\r\n".' ?'.'>';
  835. } else if ($tagname == 'label') {
  836. $bindFunc = $cTag->GetAtt('bind');
  837. $rsvalue = 'echo '.$bindFunc.";\r\n";
  838. $rsvalue = '<'.'?php '.$rsvalue.' ?'.">\r\n";
  839. $cTag->tagValue = $rsvalue;
  840. } else if ($tagname == 'datalist') {
  841. //生成属性数组
  842. foreach ($cTag->cAtt->items as $k => $v) {
  843. $v = $this->TrimAtts($v);
  844. $rsvalue .= '$atts[\''.$k.'\'] = \''.str_replace("'", "\\'", $v)."';\r\n";
  845. }
  846. $rsvalue = '<'.'?php'."\r\n".'$atts = array();'."\r\n".$rsvalue;
  847. $rsvalue .= '$blockValue = $this->refObj->GetArcList($atts,$this->refObj,$fields); '."\r\n";
  848. $rsvalue .= 'if(is_array($blockValue)){'."\r\n";
  849. $rsvalue .= 'foreach( $blockValue as $key=>$fields )'."\r\n{\r\n".'?'.">";
  850. $rsvalue .= $cTag->GetInnerText();
  851. $rsvalue .= '<'.'?php'."\r\n}\r\n}".'?'.'>';
  852. $cTag->tagValue = $rsvalue;
  853. } else if ($tagname == 'pagelist') {
  854. //生成属性数组
  855. foreach ($cTag->cAtt->items as $k => $v) {
  856. $v = $this->TrimAtts($v);
  857. $rsvalue .= '$atts[\''.$k.'\'] = \''.str_replace("'", "\\'", $v)."';\r\n";
  858. }
  859. $rsvalue = '<'.'?php'."\r\n".'$atts = array();'."\r\n".$rsvalue;
  860. $rsvalue .= ' echo $this->refObj->GetPageList($atts,$this->refObj,$fields); '."\r\n".'?'.">\r\n";
  861. $cTag->tagValue = $rsvalue;
  862. } else {
  863. $bindFunc = $cTag->GetAtt('bind');
  864. $bindType = $cTag->GetAtt('bindtype');
  865. $rstype = ($cTag->GetAtt('resulttype') == '' ? $cTag->GetAtt('rstype') : $cTag->GetAtt('resulttype'));
  866. $rstype = strtolower($rstype);
  867. //生成属性数组
  868. foreach ($cTag->cAtt->items as $k => $v) {
  869. if (preg_match("/(bind|bindtype)/i", $k)) {
  870. continue;
  871. }
  872. $v = $this->TrimAtts($v);
  873. $rsvalue .= '$atts[\''.$k.'\'] = \''.str_replace("'", "\\'", $v)."';\r\n";
  874. }
  875. $rsvalue = '<'.'?php'."\r\n".'$atts = array();'."\r\n".$rsvalue;
  876. //绑定到默认函数还是指定函数(datasource属性指定)
  877. if ($bindFunc == '') {
  878. $rsvalue .= '$blockValue = MakePublicTag($atts,$this->refObj,$fields); '."\r\n";
  879. } else {
  880. //自定义绑定函数如果不指定 bindtype,则指向$this->refObj->绑定函数名,即是默认指向被引用的类对象
  881. if ($bindType == '') $rsvalue .= '$blockValue = $this->refObj->'.$bindFunc.'($atts,$this->refObj,$fields); '."\r\n";
  882. else $rsvalue .= '$blockValue = '.$bindFunc.'($atts,$this->refObj,$fields); '."\r\n";
  883. }
  884. //返回结果类型:默认为 array 是一个二维数组,string 是字符串
  885. if ($rstype == 'string') {
  886. $rsvalue .= 'echo $blockValue;'."\r\n".'?'.">";
  887. } else {
  888. $rsvalue .= 'if(is_array($blockValue) && count($blockValue) > 0){'."\r\n";
  889. $rsvalue .= 'foreach( $blockValue as $key=>$fields )'."\r\n{\r\n".'?'.">";
  890. $rsvalue .= $cTag->GetInnerText();
  891. $rsvalue .= '<'.'?php'."\r\n}\r\n}\r\n".'?'.'>';
  892. }
  893. $cTag->tagValue = $rsvalue;
  894. }
  895. return $cTag->tagValue;
  896. }
  897. /**
  898. * 编译可能为数组的变量
  899. *
  900. * @access public
  901. * @param string $vartype 变量类型
  902. * @param string $varname 变量名称
  903. * @return string
  904. */
  905. function CompilerArrayVar($vartype, $varname)
  906. {
  907. $okvalue = '';
  908. if (!preg_match("/\[/", $varname)) {
  909. if (preg_match("/^value/", $vartype)) {
  910. $varname = $vartype.'.'.$varname;
  911. }
  912. $varnames = explode('.', $varname);
  913. if (isset($varnames[1])) {
  914. $varname = $varnames[0];
  915. for ($i = 1; isset($varnames[$i]); $i++) {
  916. $varname .= "['".$varnames[$i]."']";
  917. }
  918. }
  919. }
  920. if (preg_match("/\[/", $varname)) {
  921. $varnames = explode('[', $varname);
  922. $arrend = '';
  923. for ($i = 1; isset($varnames[$i]); $i++) {
  924. $arrend .= '['.$varnames[$i];
  925. }
  926. if (!preg_match("/[\"']/", $arrend)) {
  927. $arrend = str_replace('[', '', $arrend);
  928. $arrend = str_replace(']', '', $arrend);
  929. $arrend = "['{$arrend}']";
  930. }
  931. if ($vartype == 'var') {
  932. $okvalue = '$GLOBALS[\'_vars\'][\''.$varnames[0].'\']'.$arrend;
  933. } else if (preg_match("/^value/", $vartype)) {
  934. $okvalue = '$'.$varnames[0].$arrend;
  935. } else if ($vartype == 'field') {
  936. $okvalue = '$fields[\''.$varnames[0].'\']'.$arrend;
  937. } else {
  938. $okvalue = '$GLOBALS[\''.$varnames[0].'\']'.$arrend;
  939. }
  940. } else {
  941. if ($vartype == 'var') {
  942. $okvalue = '$GLOBALS[\'_vars\'][\''.$varname.'\']';
  943. } else if (preg_match("/^value/", $vartype)) {
  944. $okvalue = '$'.$vartype;
  945. } else if ($vartype == 'field') {
  946. $okvalue = '$'.str_replace($varname);
  947. } else {
  948. $okvalue = '$GLOBALS[\''.$varname.'\']';
  949. }
  950. }
  951. return $okvalue;
  952. }
  953. /**
  954. * 编译if标记
  955. *
  956. * @access public
  957. * @param string $cTag 标签
  958. * @return string
  959. */
  960. function CompilerIf($cTag)
  961. {
  962. $condition = trim($cTag->GetAtt('condition'));
  963. if ($condition == '') {
  964. $cTag->tagValue = '';
  965. return '';
  966. }
  967. if (version_compare(PHP_VERSION, '5.5.0', '>=')) {
  968. $condition = preg_replace_callback("/((var\.|field\.|cfg\.|global\.|key[0-9]{0,}\.|value[0-9]{0,}\.)[\._a-z0-9]+)/is", "private_rt", $condition);
  969. } else {
  970. $condition = preg_replace("/((var\.|field\.|cfg\.|global\.|key[0-9]{0,}\.|value[0-9]{0,}\.)[\._a-z0-9]+)/ies", "private_rt('\\1')", $condition);
  971. }
  972. $rsvalue = '<'.'?php if('.$condition.'){ ?'.'>';
  973. $rsvalue .= $cTag->GetInnerText();
  974. $rsvalue .= '<'.'?php } ?'.'>';
  975. return $rsvalue;
  976. }
  977. /**
  978. * 处理block区块传递的atts属性的值
  979. *
  980. * @access public
  981. * @param string $v 值
  982. * @return string
  983. */
  984. function TrimAtts($v)
  985. {
  986. $v = str_replace('<'.'?', '&lt;?', $v);
  987. $v = str_replace('?'.'>', '?&gt;', $v);
  988. return $v;
  989. }
  990. /**
  991. * 函数 function 语法处理
  992. *
  993. * @access public
  994. * @param string $funcstr 函数字符串
  995. * @param string $nvalue 函数值
  996. * @return string
  997. */
  998. function CompilerFunction($funcstr, $nvalue)
  999. {
  1000. $funcstr = str_replace('@quote', '"', $funcstr);
  1001. $funcstr = str_replace('@me', $nvalue, $funcstr);
  1002. return $funcstr;
  1003. }
  1004. /**
  1005. * 引入文件 include 语法处理
  1006. *
  1007. * @access public
  1008. * @param string $filename 文件名
  1009. * @param string $isload 是否载入
  1010. * @return string
  1011. */
  1012. function CompilerInclude($filename, $isload = TRUE)
  1013. {
  1014. $okfile = '';
  1015. if (@file_exists($filename)) {
  1016. $okfile = $filename;
  1017. } else if (@file_exists($this->refDir.$filename)) {
  1018. $okfile = $this->refDir.$filename;
  1019. } else if (@file_exists($this->refDir."../".$filename)) {
  1020. $okfile = $this->refDir."../".$filename;
  1021. }
  1022. if ($okfile == '') return 0;
  1023. if (!$isload) return 1;
  1024. $itpl = new DedeTemplate($this->templateDir);
  1025. $itpl->isCache = $this->isCache;
  1026. $itpl->SetObject($this->refObj);
  1027. $itpl->LoadTemplate($okfile);
  1028. return $itpl->CacheFile();
  1029. }
  1030. }
  1031. /**
  1032. * class TagAttribute Tag属性集合
  1033. * function C__TagAttribute();
  1034. * 属性的数据描述
  1035. *
  1036. * @package TagAttribute
  1037. * @subpackage DedeBIZ.Libraries
  1038. * @link https://www.dedebiz.com
  1039. */
  1040. class TagAttribute
  1041. {
  1042. var $count = -1;
  1043. var $items = array(); //属性元素的集合
  1044. /**
  1045. * 获得某个属性
  1046. *
  1047. * @access public
  1048. * @param string $str 预处理字符串
  1049. * @return string
  1050. */
  1051. function GetAtt($str)
  1052. {
  1053. if ($str == "") {
  1054. return "";
  1055. }
  1056. if (isset($this->items[$str])) {
  1057. return $this->items[$str];
  1058. } else {
  1059. return "";
  1060. }
  1061. }
  1062. /**
  1063. * 同上
  1064. *
  1065. * @access public
  1066. * @param string $str 预处理字符串
  1067. * @return string
  1068. */
  1069. function GetAttribute($str)
  1070. {
  1071. return $this->GetAtt($str);
  1072. }
  1073. /**
  1074. * 判断属性是否存在
  1075. *
  1076. * @access public
  1077. * @param string $str 预处理字符串
  1078. * @return bool
  1079. */
  1080. function IsAttribute($str)
  1081. {
  1082. if (isset($this->items[$str])) return TRUE;
  1083. else return FALSE;
  1084. }
  1085. /**
  1086. * 获得标记名称
  1087. *
  1088. * @access public
  1089. * @return string
  1090. */
  1091. function GettagName()
  1092. {
  1093. return $this->GetAtt("tagname");
  1094. }
  1095. /**
  1096. * 获得属性个数
  1097. *
  1098. * @access public
  1099. * @return int
  1100. */
  1101. function Getcount()
  1102. {
  1103. return $this->count + 1;
  1104. }
  1105. } //End Class
  1106. /**
  1107. * 属性解析器
  1108. * function C__TagAttributeParse();
  1109. *
  1110. * @package TagAttribute
  1111. * @subpackage DedeBIZ.Libraries
  1112. * @link https://www.dedebiz.com
  1113. */
  1114. class TagAttributeParse
  1115. {
  1116. var $sourceString = "";
  1117. var $sourceMaxSize = 1024;
  1118. var $cAttributes;
  1119. var $charToLow = TRUE;
  1120. function SetSource($str = "")
  1121. {
  1122. $this->cAttributes = new TagAttribute();
  1123. $strLen = 0;
  1124. $this->sourceString = trim(preg_replace("/[ \r\n\t\f]{1,}/", " ", $str));
  1125. $strLen = strlen($this->sourceString);
  1126. if ($strLen > 0 && $strLen <= $this->sourceMaxSize) {
  1127. $this->ParseAttribute();
  1128. }
  1129. }
  1130. /**
  1131. * 解析属性
  1132. *
  1133. * @access public
  1134. * @return void
  1135. */
  1136. function ParseAttribute()
  1137. {
  1138. $d = '';
  1139. $tmpatt = '';
  1140. $tmpvalue = '';
  1141. $startdd = -1;
  1142. $ddtag = '';
  1143. $hasAttribute = FALSE;
  1144. $strLen = strlen($this->sourceString);
  1145. $this->cAttributes->items = array();
  1146. //获得Tag的名称,解析到 cAtt->GetAtt('tagname') 中
  1147. for ($i = 0; $i < $strLen; $i++) {
  1148. if ($this->sourceString[$i] == ' ') {
  1149. $this->cAttributes->count++;
  1150. $tmpvalues = explode('.', $tmpvalue);
  1151. $this->cAttributes->items['tagname'] = ($this->charToLow ? strtolower($tmpvalues[0]) : $tmpvalues[0]);
  1152. if (isset($tmpvalues[2])) {
  1153. $okname = $tmpvalues[1];
  1154. for ($j = 2; isset($tmpvalues[$j]); $j++) {
  1155. $okname .= "['".$tmpvalues[$j]."']";
  1156. }
  1157. $this->cAttributes->items['name'] = $okname;
  1158. } else if (isset($tmpvalues[1]) && $tmpvalues[1] != '') {
  1159. $this->cAttributes->items['name'] = $tmpvalues[1];
  1160. }
  1161. $tmpvalue = '';
  1162. $hasAttribute = TRUE;
  1163. break;
  1164. } else {
  1165. $tmpvalue .= $this->sourceString[$i];
  1166. }
  1167. }
  1168. //不存在属性列表的情况
  1169. if (!$hasAttribute) {
  1170. $this->cAttributes->count++;
  1171. $tmpvalues = explode('.', $tmpvalue);
  1172. $this->cAttributes->items['tagname'] = ($this->charToLow ? strtolower($tmpvalues[0]) : $tmpvalues[0]);
  1173. if (isset($tmpvalues[2])) {
  1174. $okname = $tmpvalues[1];
  1175. for ($i = 2; isset($tmpvalues[$i]); $i++) {
  1176. $okname .= "['".$tmpvalues[$i]."']";
  1177. }
  1178. $this->cAttributes->items['name'] = $okname;
  1179. } else if (isset($tmpvalues[1]) && $tmpvalues[1] != '') {
  1180. $this->cAttributes->items['name'] = $tmpvalues[1];
  1181. }
  1182. return;
  1183. }
  1184. $tmpvalue = '';
  1185. //如果字符串含有属性值,遍历源字符串,并获得各属性
  1186. for ($i; $i < $strLen; $i++) {
  1187. $d = $this->sourceString[$i];
  1188. //查找属性名称
  1189. if ($startdd == -1) {
  1190. if ($d != '=') {
  1191. $tmpatt .= $d;
  1192. } else {
  1193. if ($this->charToLow) {
  1194. $tmpatt = strtolower(trim($tmpatt));
  1195. } else {
  1196. $tmpatt = trim($tmpatt);
  1197. }
  1198. $startdd = 0;
  1199. }
  1200. }
  1201. //查找属性的限定标志
  1202. else if ($startdd == 0) {
  1203. switch ($d) {
  1204. case ' ':
  1205. break;
  1206. case '\'':
  1207. $ddtag = '\'';
  1208. $startdd = 1;
  1209. break;
  1210. case '"':
  1211. $ddtag = '"';
  1212. $startdd = 1;
  1213. break;
  1214. default:
  1215. $tmpvalue .= $d;
  1216. $ddtag = ' ';
  1217. $startdd = 1;
  1218. break;
  1219. }
  1220. } else if ($startdd == 1) {
  1221. if ($d == $ddtag && (isset($this->sourceString[$i - 1]) && $this->sourceString[$i - 1] != "\\")) {
  1222. $this->cAttributes->count++;
  1223. $this->cAttributes->items[$tmpatt] = trim($tmpvalue);
  1224. $tmpatt = '';
  1225. $tmpvalue = '';
  1226. $startdd = -1;
  1227. } else {
  1228. $tmpvalue .= $d;
  1229. }
  1230. }
  1231. } //for
  1232. //最后一个属性的给值
  1233. if ($tmpatt != '') {
  1234. $this->cAttributes->count++;
  1235. $this->cAttributes->items[$tmpatt] = trim($tmpvalue);
  1236. } //print_r($this->cAttributes->items);
  1237. } //end func
  1238. } //End Class
  1239. /**
  1240. * 私有标签编译,主要用于if标签内的字符串解析
  1241. *
  1242. * @access public
  1243. * @param string $str 需要编译的字符串
  1244. * @return string
  1245. */
  1246. function private_rt($str)
  1247. {
  1248. if (is_array($str)) {
  1249. $arr = explode('.', $str[0]);
  1250. } else {
  1251. $arr = explode('.', $str);
  1252. }
  1253. $rs = '$GLOBALS[\'';
  1254. if ($arr[0] == 'cfg') {
  1255. return $rs.'cfg_'.$arr[1]."']";
  1256. } elseif ($arr[0] == 'var') {
  1257. $arr[0] = '_vars';
  1258. $rs .= implode('\'][\'', $arr);
  1259. $rs .= "']";
  1260. return $rs;
  1261. } elseif ($arr[0] == 'global') {
  1262. unset($arr[0]);
  1263. $rs .= implode('\'][\'', $arr);
  1264. $rs .= "']";
  1265. return $rs;
  1266. } else {
  1267. if ($arr[0] == 'field') $arr[0] = 'fields';
  1268. $rs = '$'.$arr[0]."['";
  1269. unset($arr[0]);
  1270. $rs .= implode('\'][\'', $arr);
  1271. $rs .= "']";
  1272. return $rs;
  1273. }
  1274. }