国内流行的内容管理系统(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.

1352 lines
45KB

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