PageRenderTime 52ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 1ms

/libs/module/smarty/Smarty_Compiler.class.php

https://github.com/monkeycraps/swoole_framework
PHP | 2461 lines | 1811 code | 220 blank | 430 comment | 313 complexity | 643a70fe7f650e0236fefc8014932330 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /**
  3. * Project: Smarty: the PHP compiling template engine
  4. * File: Smarty_Compiler.class.php
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, write to the Free Software
  18. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19. *
  20. * @link http://smarty.php.net/
  21. * @author Monte Ohrt <monte at ohrt dot com>
  22. * @author Andrei Zmievski <andrei@php.net>
  23. * @version 2.6.16
  24. * @copyright 2001-2005 New Digital Group, Inc.
  25. * @package Smarty
  26. */
  27. /* $Id: Smarty_Compiler.class.php,v 1.386 2006/11/30 17:01:28 mohrt Exp $ */
  28. /**
  29. * Template compiling class
  30. * @package Smarty
  31. */
  32. class Smarty_Compiler extends Smarty {
  33. // internal vars
  34. /**#@+
  35. * @access private
  36. */
  37. public $_folded_blocks = array(); // keeps folded template blocks
  38. public $_current_file = null; // the current template being compiled
  39. public $_current_line_no = 1; // line number for error messages
  40. public $_capture_stack = array(); // keeps track of nested capture buffers
  41. public $_plugin_info = array(); // keeps track of plugins to load
  42. public $_init_smarty_vars = false;
  43. public $_permitted_tokens = array('true','false','yes','no','on','off','null');
  44. public $_db_qstr_regexp = null; // regexps are setup in the constructor
  45. public $_si_qstr_regexp = null;
  46. public $_qstr_regexp = null;
  47. public $_func_regexp = null;
  48. public $_reg_obj_regexp = null;
  49. public $_var_bracket_regexp = null;
  50. public $_num_const_regexp = null;
  51. public $_dvar_guts_regexp = null;
  52. public $_dvar_regexp = null;
  53. public $_cvar_regexp = null;
  54. public $_svar_regexp = null;
  55. public $_avar_regexp = null;
  56. public $_mod_regexp = null;
  57. public $_var_regexp = null;
  58. public $_parenth_param_regexp = null;
  59. public $_func_call_regexp = null;
  60. public $_obj_ext_regexp = null;
  61. public $_obj_start_regexp = null;
  62. public $_obj_params_regexp = null;
  63. public $_obj_call_regexp = null;
  64. public $_cacheable_state = 0;
  65. public $_cache_attrs_count = 0;
  66. public $_nocache_count = 0;
  67. public $_cache_serial = null;
  68. public $_cache_include = null;
  69. public $_strip_depth = 0;
  70. public $_additional_newline = "\n";
  71. /**#@-*/
  72. /**
  73. * The class constructor.
  74. */
  75. function Smarty_Compiler()
  76. {
  77. // matches double quoted strings:
  78. // "foobar"
  79. // "foo\"bar"
  80. $this->_db_qstr_regexp = '"[^"\\\\]*(?:\\\\.[^"\\\\]*)*"';
  81. // matches single quoted strings:
  82. // 'foobar'
  83. // 'foo\'bar'
  84. $this->_si_qstr_regexp = '\'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\'';
  85. // matches single or double quoted strings
  86. $this->_qstr_regexp = '(?:' . $this->_db_qstr_regexp . '|' . $this->_si_qstr_regexp . ')';
  87. // matches bracket portion of vars
  88. // [0]
  89. // [foo]
  90. // [$bar]
  91. $this->_var_bracket_regexp = '\[\$?[\w\.]+\]';
  92. // matches numerical constants
  93. // 30
  94. // -12
  95. // 13.22
  96. $this->_num_const_regexp = '(?:\-?\d+(?:\.\d+)?)';
  97. // matches $ vars (not objects):
  98. // $foo
  99. // $foo.bar
  100. // $foo.bar.foobar
  101. // $foo[0]
  102. // $foo[$bar]
  103. // $foo[5][blah]
  104. // $foo[5].bar[$foobar][4]
  105. $this->_dvar_math_regexp = '(?:[\+\*\/\%]|(?:-(?!>)))';
  106. $this->_dvar_math_var_regexp = '[\$\w\.\+\-\*\/\%\d\>\[\]]';
  107. $this->_dvar_guts_regexp = '\w+(?:' . $this->_var_bracket_regexp
  108. . ')*(?:\.\$?\w+(?:' . $this->_var_bracket_regexp . ')*)*(?:' . $this->_dvar_math_regexp . '(?:' . $this->_num_const_regexp . '|' . $this->_dvar_math_var_regexp . ')*)?';
  109. $this->_dvar_regexp = '\$' . $this->_dvar_guts_regexp;
  110. // matches config vars:
  111. // #foo#
  112. // #foobar123_foo#
  113. $this->_cvar_regexp = '\#\w+\#';
  114. // matches section vars:
  115. // %foo.bar%
  116. $this->_svar_regexp = '\%\w+\.\w+\%';
  117. // matches all valid variables (no quotes, no modifiers)
  118. $this->_avar_regexp = '(?:' . $this->_dvar_regexp . '|'
  119. . $this->_cvar_regexp . '|' . $this->_svar_regexp . ')';
  120. // matches valid variable syntax:
  121. // $foo
  122. // $foo
  123. // #foo#
  124. // #foo#
  125. // "text"
  126. // "text"
  127. $this->_var_regexp = '(?:' . $this->_avar_regexp . '|' . $this->_qstr_regexp . ')';
  128. // matches valid object call (one level of object nesting allowed in parameters):
  129. // $foo->bar
  130. // $foo->bar()
  131. // $foo->bar("text")
  132. // $foo->bar($foo, $bar, "text")
  133. // $foo->bar($foo, "foo")
  134. // $foo->bar->foo()
  135. // $foo->bar->foo->bar()
  136. // $foo->bar($foo->bar)
  137. // $foo->bar($foo->bar())
  138. // $foo->bar($foo->bar($blah,$foo,44,"foo",$foo[0].bar))
  139. $this->_obj_ext_regexp = '\->(?:\$?' . $this->_dvar_guts_regexp . ')';
  140. $this->_obj_restricted_param_regexp = '(?:'
  141. . '(?:' . $this->_var_regexp . '|' . $this->_num_const_regexp . ')(?:' . $this->_obj_ext_regexp . '(?:\((?:(?:' . $this->_var_regexp . '|' . $this->_num_const_regexp . ')'
  142. . '(?:\s*,\s*(?:' . $this->_var_regexp . '|' . $this->_num_const_regexp . '))*)?\))?)*)';
  143. $this->_obj_single_param_regexp = '(?:\w+|' . $this->_obj_restricted_param_regexp . '(?:\s*,\s*(?:(?:\w+|'
  144. . $this->_var_regexp . $this->_obj_restricted_param_regexp . ')))*)';
  145. $this->_obj_params_regexp = '\((?:' . $this->_obj_single_param_regexp
  146. . '(?:\s*,\s*' . $this->_obj_single_param_regexp . ')*)?\)';
  147. $this->_obj_start_regexp = '(?:' . $this->_dvar_regexp . '(?:' . $this->_obj_ext_regexp . ')+)';
  148. $this->_obj_call_regexp = '(?:' . $this->_obj_start_regexp . '(?:' . $this->_obj_params_regexp . ')?(?:' . $this->_dvar_math_regexp . '(?:' . $this->_num_const_regexp . '|' . $this->_dvar_math_var_regexp . ')*)?)';
  149. // matches valid modifier syntax:
  150. // |foo
  151. // |@foo
  152. // |foo:"bar"
  153. // |foo:$bar
  154. // |foo:"bar":$foobar
  155. // |foo|bar
  156. // |foo:$foo->bar
  157. $this->_mod_regexp = '(?:\|@?\w+(?::(?:\w+|' . $this->_num_const_regexp . '|'
  158. . $this->_obj_call_regexp . '|' . $this->_avar_regexp . '|' . $this->_qstr_regexp .'))*)';
  159. // matches valid function name:
  160. // foo123
  161. // _foo_bar
  162. $this->_func_regexp = '[a-zA-Z_]\w*';
  163. // matches valid registered object:
  164. // foo->bar
  165. $this->_reg_obj_regexp = '[a-zA-Z_]\w*->[a-zA-Z_]\w*';
  166. // matches valid parameter values:
  167. // true
  168. // $foo
  169. // $foo|bar
  170. // #foo#
  171. // #foo#|bar
  172. // "text"
  173. // "text"|bar
  174. // $foo->bar
  175. $this->_param_regexp = '(?:\s*(?:' . $this->_obj_call_regexp . '|'
  176. . $this->_var_regexp . '|' . $this->_num_const_regexp . '|\w+)(?>' . $this->_mod_regexp . '*)\s*)';
  177. // matches valid parenthesised function parameters:
  178. //
  179. // "text"
  180. // $foo, $bar, "text"
  181. // $foo|bar, "foo"|bar, $foo->bar($foo)|bar
  182. $this->_parenth_param_regexp = '(?:\((?:\w+|'
  183. . $this->_param_regexp . '(?:\s*,\s*(?:(?:\w+|'
  184. . $this->_param_regexp . ')))*)?\))';
  185. // matches valid function call:
  186. // foo()
  187. // foo_bar($foo)
  188. // _foo_bar($foo,"bar")
  189. // foo123($foo,$foo->bar(),"foo")
  190. $this->_func_call_regexp = '(?:' . $this->_func_regexp . '\s*(?:'
  191. . $this->_parenth_param_regexp . '))';
  192. }
  193. /**
  194. * compile a resource
  195. *
  196. * sets $compiled_content to the compiled source
  197. * @param string $resource_name
  198. * @param string $source_content
  199. * @param string $compiled_content
  200. * @return true
  201. */
  202. function _compile_file($resource_name, $source_content, &$compiled_content)
  203. {
  204. if ($this->security) {
  205. // do not allow php syntax to be executed unless specified
  206. if ($this->php_handling == SMARTY_PHP_ALLOW &&
  207. !$this->security_settings['PHP_HANDLING']) {
  208. $this->php_handling = SMARTY_PHP_PASSTHRU;
  209. }
  210. }
  211. $this->_load_filters();
  212. $this->_current_file = $resource_name;
  213. $this->_current_line_no = 1;
  214. $ldq = preg_quote($this->left_delimiter, '~');
  215. $rdq = preg_quote($this->right_delimiter, '~');
  216. /* un-hide hidden xml open tags */
  217. $source_content = preg_replace("~<({$ldq}(.*?){$rdq})[?]~s", '< \\1', $source_content);
  218. // run template source through prefilter functions
  219. if (count($this->_plugins['prefilter']) > 0) {
  220. foreach ($this->_plugins['prefilter'] as $filter_name => $prefilter) {
  221. if ($prefilter === false) continue;
  222. if ($prefilter[3] || is_callable($prefilter[0])) {
  223. $source_content = call_user_func_array($prefilter[0],
  224. array($source_content, &$this));
  225. $this->_plugins['prefilter'][$filter_name][3] = true;
  226. } else {
  227. $this->_trigger_fatal_error("[plugin] prefilter '$filter_name' is not implemented");
  228. }
  229. }
  230. }
  231. /* fetch all special blocks */
  232. $search = "~{$ldq}\*(.*?)\*{$rdq}|{$ldq}\s*literal\s*{$rdq}(.*?){$ldq}\s*/literal\s*{$rdq}|{$ldq}\s*php\s*{$rdq}(.*?){$ldq}\s*/php\s*{$rdq}~s";
  233. preg_match_all($search, $source_content, $match, PREG_SET_ORDER);
  234. $this->_folded_blocks = $match;
  235. reset($this->_folded_blocks);
  236. /* replace special blocks by "{php}" */
  237. $source_content = preg_replace($search.'e', "'"
  238. . $this->_quote_replace($this->left_delimiter) . 'php'
  239. . "' . str_repeat(\"\n\", substr_count('\\0', \"\n\")) .'"
  240. . $this->_quote_replace($this->right_delimiter)
  241. . "'"
  242. , $source_content);
  243. /* Gather all template tags. */
  244. preg_match_all("~{$ldq}\s*(.*?)\s*{$rdq}~s", $source_content, $_match);
  245. $template_tags = $_match[1];
  246. /* Split content by template tags to obtain non-template content. */
  247. $text_blocks = preg_split("~{$ldq}.*?{$rdq}~s", $source_content);
  248. /* loop through text blocks */
  249. for ($curr_tb = 0, $for_max = count($text_blocks); $curr_tb < $for_max; $curr_tb++) {
  250. /* match anything resembling php tags */
  251. if (preg_match_all('~(<\?(?:\w+|=)?|\?>|language\s*=\s*[\"\']?php[\"\']?)~is', $text_blocks[$curr_tb], $sp_match)) {
  252. /* replace tags with placeholders to prevent recursive replacements */
  253. $sp_match[1] = array_unique($sp_match[1]);
  254. usort($sp_match[1], '_smarty_sort_length');
  255. for ($curr_sp = 0, $for_max2 = count($sp_match[1]); $curr_sp < $for_max2; $curr_sp++) {
  256. $text_blocks[$curr_tb] = str_replace($sp_match[1][$curr_sp],'%%%SMARTYSP'.$curr_sp.'%%%',$text_blocks[$curr_tb]);
  257. }
  258. /* process each one */
  259. for ($curr_sp = 0, $for_max2 = count($sp_match[1]); $curr_sp < $for_max2; $curr_sp++) {
  260. if ($this->php_handling == SMARTY_PHP_PASSTHRU) {
  261. /* echo php contents */
  262. $text_blocks[$curr_tb] = str_replace('%%%SMARTYSP'.$curr_sp.'%%%', '<?php echo \''.str_replace("'", "\'", $sp_match[1][$curr_sp]).'\'; ?>'."\n", $text_blocks[$curr_tb]);
  263. } else if ($this->php_handling == SMARTY_PHP_QUOTE) {
  264. /* quote php tags */
  265. $text_blocks[$curr_tb] = str_replace('%%%SMARTYSP'.$curr_sp.'%%%', htmlspecialchars($sp_match[1][$curr_sp]), $text_blocks[$curr_tb]);
  266. } else if ($this->php_handling == SMARTY_PHP_REMOVE) {
  267. /* remove php tags */
  268. $text_blocks[$curr_tb] = str_replace('%%%SMARTYSP'.$curr_sp.'%%%', '', $text_blocks[$curr_tb]);
  269. } else {
  270. /* SMARTY_PHP_ALLOW, but echo non php starting tags */
  271. $sp_match[1][$curr_sp] = preg_replace('~(<\?(?!php|=|$))~i', '<?php echo \'\\1\'?>'."\n", $sp_match[1][$curr_sp]);
  272. $text_blocks[$curr_tb] = str_replace('%%%SMARTYSP'.$curr_sp.'%%%', $sp_match[1][$curr_sp], $text_blocks[$curr_tb]);
  273. }
  274. }
  275. }
  276. }
  277. /* Compile the template tags into PHP code. */
  278. $compiled_tags = array();
  279. for ($i = 0, $for_max = count($template_tags); $i < $for_max; $i++) {
  280. $this->_current_line_no += substr_count($text_blocks[$i], "\n");
  281. $compiled_tags[] = $this->_compile_tag($template_tags[$i]);
  282. $this->_current_line_no += substr_count($template_tags[$i], "\n");
  283. }
  284. if (count($this->_tag_stack)>0) {
  285. list($_open_tag, $_line_no) = end($this->_tag_stack);
  286. $this->_syntax_error("unclosed tag \{$_open_tag} (opened line $_line_no).", E_USER_ERROR, __FILE__, __LINE__);
  287. return;
  288. }
  289. /* Reformat $text_blocks between 'strip' and '/strip' tags,
  290. removing spaces, tabs and newlines. */
  291. $strip = false;
  292. for ($i = 0, $for_max = count($compiled_tags); $i < $for_max; $i++) {
  293. if ($compiled_tags[$i] == '{strip}') {
  294. $compiled_tags[$i] = '';
  295. $strip = true;
  296. /* remove leading whitespaces */
  297. $text_blocks[$i + 1] = ltrim($text_blocks[$i + 1]);
  298. }
  299. if ($strip) {
  300. /* strip all $text_blocks before the next '/strip' */
  301. for ($j = $i + 1; $j < $for_max; $j++) {
  302. /* remove leading and trailing whitespaces of each line */
  303. $text_blocks[$j] = preg_replace('![\t ]*[\r\n]+[\t ]*!', '', $text_blocks[$j]);
  304. if ($compiled_tags[$j] == '{/strip}') {
  305. /* remove trailing whitespaces from the last text_block */
  306. $text_blocks[$j] = rtrim($text_blocks[$j]);
  307. }
  308. $text_blocks[$j] = "<?php echo '" . strtr($text_blocks[$j], array("'"=>"\'", "\\"=>"\\\\")) . "'; ?>";
  309. if ($compiled_tags[$j] == '{/strip}') {
  310. $compiled_tags[$j] = "\n"; /* slurped by php, but necessary
  311. if a newline is following the closing strip-tag */
  312. $strip = false;
  313. $i = $j;
  314. break;
  315. }
  316. }
  317. }
  318. }
  319. $compiled_content = '';
  320. /* Interleave the compiled contents and text blocks to get the final result. */
  321. for ($i = 0, $for_max = count($compiled_tags); $i < $for_max; $i++) {
  322. if ($compiled_tags[$i] == '') {
  323. // tag result empty, remove first newline from following text block
  324. $text_blocks[$i+1] = preg_replace('~^(\r\n|\r|\n)~', '', $text_blocks[$i+1]);
  325. }
  326. $compiled_content .= $text_blocks[$i].$compiled_tags[$i];
  327. }
  328. $compiled_content .= $text_blocks[$i];
  329. // remove \n from the end of the file, if any
  330. if (strlen($compiled_content) && (substr($compiled_content, -1) == "\n") ) {
  331. $compiled_content = substr($compiled_content, 0, -1);
  332. }
  333. if (!empty($this->_cache_serial)) {
  334. $compiled_content = "<?php \$this->_cache_serials['".$this->_cache_include."'] = '".$this->_cache_serial."'; ?>" . $compiled_content;
  335. }
  336. // remove unnecessary close/open tags
  337. $compiled_content = preg_replace('~\?>\n?<\?php~', '', $compiled_content);
  338. // run compiled template through postfilter functions
  339. if (count($this->_plugins['postfilter']) > 0) {
  340. foreach ($this->_plugins['postfilter'] as $filter_name => $postfilter) {
  341. if ($postfilter === false) continue;
  342. if ($postfilter[3] || is_callable($postfilter[0])) {
  343. $compiled_content = call_user_func_array($postfilter[0],
  344. array($compiled_content, &$this));
  345. $this->_plugins['postfilter'][$filter_name][3] = true;
  346. } else {
  347. $this->_trigger_fatal_error("Smarty plugin error: postfilter '$filter_name' is not implemented");
  348. }
  349. }
  350. }
  351. // put header at the top of the compiled template
  352. $template_header = "<?php /* Smarty version ".$this->_version.", created on ".strftime("%Y-%m-%d %H:%M:%S")."\n";
  353. $template_header .= " compiled from ".strtr(urlencode($resource_name), array('%2F'=>'/', '%3A'=>':'))." */ ?>\n";
  354. /* Emit code to load needed plugins. */
  355. $this->_plugins_code = '';
  356. if (count($this->_plugin_info)) {
  357. $_plugins_params = "array('plugins' => array(";
  358. foreach ($this->_plugin_info as $plugin_type => $plugins) {
  359. foreach ($plugins as $plugin_name => $plugin_info) {
  360. $_plugins_params .= "array('$plugin_type', '$plugin_name', '" . strtr($plugin_info[0], array("'" => "\\'", "\\" => "\\\\")) . "', $plugin_info[1], ";
  361. $_plugins_params .= $plugin_info[2] ? 'true),' : 'false),';
  362. }
  363. }
  364. $_plugins_params .= '))';
  365. $plugins_code = "<?php require_once(SMARTY_CORE_DIR . 'core.load_plugins.php');\nsmarty_core_load_plugins($_plugins_params, \$this); ?>\n";
  366. $template_header .= $plugins_code;
  367. $this->_plugin_info = array();
  368. $this->_plugins_code = $plugins_code;
  369. }
  370. if ($this->_init_smarty_vars) {
  371. $template_header .= "<?php require_once(SMARTY_CORE_DIR . 'core.assign_smarty_interface.php');\nsmarty_core_assign_smarty_interface(null, \$this); ?>\n";
  372. $this->_init_smarty_vars = false;
  373. }
  374. $compiled_content = $template_header . $compiled_content;
  375. return true;
  376. }
  377. /**
  378. * Compile a template tag
  379. *
  380. * @param string $template_tag
  381. * @return string
  382. */
  383. function _compile_tag($template_tag)
  384. {
  385. /* Matched comment. */
  386. if (substr($template_tag, 0, 1) == '*' && substr($template_tag, -1) == '*')
  387. return '';
  388. /* Split tag into two three parts: command, command modifiers and the arguments. */
  389. if(! preg_match('~^(?:(' . $this->_num_const_regexp . '|' . $this->_obj_call_regexp . '|' . $this->_var_regexp
  390. . '|\/?' . $this->_reg_obj_regexp . '|\/?' . $this->_func_regexp . ')(' . $this->_mod_regexp . '*))
  391. (?:\s+(.*))?$
  392. ~xs', $template_tag, $match)) {
  393. $this->_syntax_error("unrecognized tag: $template_tag", E_USER_ERROR, __FILE__, __LINE__);
  394. }
  395. $tag_command = $match[1];
  396. $tag_modifier = isset($match[2]) ? $match[2] : null;
  397. $tag_args = isset($match[3]) ? $match[3] : null;
  398. if (preg_match('~^' . $this->_num_const_regexp . '|' . $this->_obj_call_regexp . '|' . $this->_var_regexp . '$~', $tag_command)) {
  399. /* tag name is a variable or object */
  400. $_return = $this->_parse_var_props($tag_command . $tag_modifier);
  401. return "<?php echo $_return; ?>" . $this->_additional_newline;
  402. }
  403. /* If the tag name is a registered object, we process it. */
  404. if (preg_match('~^\/?' . $this->_reg_obj_regexp . '$~', $tag_command)) {
  405. return $this->_compile_registered_object_tag($tag_command, $this->_parse_attrs($tag_args), $tag_modifier);
  406. }
  407. switch ($tag_command) {
  408. case 'include':
  409. return $this->_compile_include_tag($tag_args);
  410. case 'include_php':
  411. return $this->_compile_include_php_tag($tag_args);
  412. case 'if':
  413. $this->_push_tag('if');
  414. return $this->_compile_if_tag($tag_args);
  415. case 'else':
  416. list($_open_tag) = end($this->_tag_stack);
  417. if ($_open_tag != 'if' && $_open_tag != 'elseif')
  418. $this->_syntax_error('unexpected {else}', E_USER_ERROR, __FILE__, __LINE__);
  419. else
  420. $this->_push_tag('else');
  421. return '<?php else: ?>';
  422. case 'elseif':
  423. list($_open_tag) = end($this->_tag_stack);
  424. if ($_open_tag != 'if' && $_open_tag != 'elseif')
  425. $this->_syntax_error('unexpected {elseif}', E_USER_ERROR, __FILE__, __LINE__);
  426. if ($_open_tag == 'if')
  427. $this->_push_tag('elseif');
  428. return $this->_compile_if_tag($tag_args, true);
  429. case '/if':
  430. $this->_pop_tag('if');
  431. return '<?php endif; ?>';
  432. case 'capture':
  433. return $this->_compile_capture_tag(true, $tag_args);
  434. case '/capture':
  435. return $this->_compile_capture_tag(false);
  436. case 'ldelim':
  437. return $this->left_delimiter;
  438. case 'rdelim':
  439. return $this->right_delimiter;
  440. case 'section':
  441. $this->_push_tag('section');
  442. return $this->_compile_section_start($tag_args);
  443. //htf
  444. case 'db':
  445. $this->_push_tag('db');
  446. return $this->_compile_db_start($tag_args);
  447. case 'cms':
  448. $this->_push_tag('cms');
  449. return $this->_compile_cms_start($tag_args);
  450. //end htf
  451. case 'sectionelse':
  452. $this->_push_tag('sectionelse');
  453. return "<?php endfor; else: ?>";
  454. break;
  455. case '/section':
  456. $_open_tag = $this->_pop_tag('section');
  457. if ($_open_tag == 'sectionelse')
  458. return "<?php endif; ?>";
  459. else
  460. return "<?php endfor; endif; ?>";
  461. //htf
  462. case '/db':
  463. $_open_tag = $this->_pop_tag('db');
  464. return "<?php endfor; ?>";
  465. case '/cms':
  466. $_open_tag = $this->_pop_tag('cms');
  467. return "<?php endforeach; ?>";
  468. //end htf
  469. case 'foreach':
  470. $this->_push_tag('foreach');
  471. return $this->_compile_foreach_start($tag_args);
  472. break;
  473. case 'foreachelse':
  474. $this->_push_tag('foreachelse');
  475. return "<?php endforeach; else: ?>";
  476. case '/foreach':
  477. $_open_tag = $this->_pop_tag('foreach');
  478. if ($_open_tag == 'foreachelse')
  479. return "<?php endif; unset(\$_from); ?>";
  480. else
  481. return "<?php endforeach; endif; unset(\$_from); ?>";
  482. break;
  483. case 'strip':
  484. case '/strip':
  485. if (substr($tag_command, 0, 1)=='/') {
  486. $this->_pop_tag('strip');
  487. if (--$this->_strip_depth==0) { /* outermost closing {/strip} */
  488. $this->_additional_newline = "\n";
  489. return '{' . $tag_command . '}';
  490. }
  491. } else {
  492. $this->_push_tag('strip');
  493. if ($this->_strip_depth++==0) { /* outermost opening {strip} */
  494. $this->_additional_newline = "";
  495. return '{' . $tag_command . '}';
  496. }
  497. }
  498. return '';
  499. case 'php':
  500. /* handle folded tags replaced by {php} */
  501. list(, $block) = each($this->_folded_blocks);
  502. $this->_current_line_no += substr_count($block[0], "\n");
  503. /* the number of matched elements in the regexp in _compile_file()
  504. determins the type of folded tag that was found */
  505. switch (count($block)) {
  506. case 2: /* comment */
  507. return '';
  508. case 3: /* literal */
  509. return "<?php echo '" . strtr($block[2], array("'"=>"\'", "\\"=>"\\\\")) . "'; ?>" . $this->_additional_newline;
  510. case 4: /* php */
  511. if ($this->security && !$this->security_settings['PHP_TAGS']) {
  512. $this->_syntax_error("(secure mode) php tags not permitted", E_USER_WARNING, __FILE__, __LINE__);
  513. return;
  514. }
  515. return '<?php ' . $block[3] .' ?>';
  516. }
  517. break;
  518. case 'insert':
  519. return $this->_compile_insert_tag($tag_args);
  520. default:
  521. if ($this->_compile_compiler_tag($tag_command, $tag_args, $output)) {
  522. return $output;
  523. } else if ($this->_compile_block_tag($tag_command, $tag_args, $tag_modifier, $output)) {
  524. return $output;
  525. } else if ($this->_compile_custom_tag($tag_command, $tag_args, $tag_modifier, $output)) {
  526. return $output;
  527. } else {
  528. $this->_syntax_error("unrecognized tag '$tag_command'", E_USER_ERROR, __FILE__, __LINE__);
  529. }
  530. }
  531. }
  532. /**
  533. * compile the custom compiler tag
  534. *
  535. * sets $output to the compiled custom compiler tag
  536. * @param string $tag_command
  537. * @param string $tag_args
  538. * @param string $output
  539. * @return boolean
  540. */
  541. function _compile_compiler_tag($tag_command, $tag_args, &$output)
  542. {
  543. $found = false;
  544. $have_function = true;
  545. /*
  546. * First we check if the compiler function has already been registered
  547. * or loaded from a plugin file.
  548. */
  549. if (isset($this->_plugins['compiler'][$tag_command])) {
  550. $found = true;
  551. $plugin_func = $this->_plugins['compiler'][$tag_command][0];
  552. if (!is_callable($plugin_func)) {
  553. $message = "compiler function '$tag_command' is not implemented";
  554. $have_function = false;
  555. }
  556. }
  557. /*
  558. * Otherwise we need to load plugin file and look for the function
  559. * inside it.
  560. */
  561. else if ($plugin_file = $this->_get_plugin_filepath('compiler', $tag_command)) {
  562. $found = true;
  563. include_once $plugin_file;
  564. $plugin_func = 'smarty_compiler_' . $tag_command;
  565. if (!is_callable($plugin_func)) {
  566. $message = "plugin function $plugin_func() not found in $plugin_file\n";
  567. $have_function = false;
  568. } else {
  569. $this->_plugins['compiler'][$tag_command] = array($plugin_func, null, null, null, true);
  570. }
  571. }
  572. /*
  573. * True return value means that we either found a plugin or a
  574. * dynamically registered function. False means that we didn't and the
  575. * compiler should now emit code to load custom function plugin for this
  576. * tag.
  577. */
  578. if ($found) {
  579. if ($have_function)
  580. {
  581. $output = call_user_func_array($plugin_func, array($tag_args, &$this));
  582. if($output != '') {
  583. $output = '<?php ' . $this->_push_cacheable_state('compiler', $tag_command)
  584. . $output
  585. . $this->_pop_cacheable_state('compiler', $tag_command) . ' ?>';
  586. }
  587. }
  588. else
  589. {
  590. $this->_syntax_error($message, E_USER_WARNING, __FILE__, __LINE__);
  591. }
  592. return true;
  593. } else {
  594. return false;
  595. }
  596. }
  597. /**
  598. * compile block function tag
  599. *
  600. * sets $output to compiled block function tag
  601. * @param string $tag_command
  602. * @param string $tag_args
  603. * @param string $tag_modifier
  604. * @param string $output
  605. * @return boolean
  606. */
  607. function _compile_block_tag($tag_command, $tag_args, $tag_modifier, &$output)
  608. {
  609. if (substr($tag_command, 0, 1) == '/') {
  610. $start_tag = false;
  611. $tag_command = substr($tag_command, 1);
  612. } else
  613. $start_tag = true;
  614. $found = false;
  615. $have_function = true;
  616. /*
  617. * First we check if the block function has already been registered
  618. * or loaded from a plugin file.
  619. */
  620. if (isset($this->_plugins['block'][$tag_command])) {
  621. $found = true;
  622. $plugin_func = $this->_plugins['block'][$tag_command][0];
  623. if (!is_callable($plugin_func)) {
  624. $message = "block function '$tag_command' is not implemented";
  625. $have_function = false;
  626. }
  627. }
  628. /*
  629. * Otherwise we need to load plugin file and look for the function
  630. * inside it.
  631. */
  632. else if ($plugin_file = $this->_get_plugin_filepath('block', $tag_command)) {
  633. $found = true;
  634. include_once $plugin_file;
  635. $plugin_func = 'smarty_block_' . $tag_command;
  636. if (!function_exists($plugin_func)) {
  637. $message = "plugin function $plugin_func() not found in $plugin_file\n";
  638. $have_function = false;
  639. } else {
  640. $this->_plugins['block'][$tag_command] = array($plugin_func, null, null, null, true);
  641. }
  642. }
  643. if (!$found) {
  644. return false;
  645. } else if (!$have_function) {
  646. $this->_syntax_error($message, E_USER_WARNING, __FILE__, __LINE__);
  647. return true;
  648. }
  649. /*
  650. * Even though we've located the plugin function, compilation
  651. * happens only once, so the plugin will still need to be loaded
  652. * at runtime for future requests.
  653. */
  654. $this->_add_plugin('block', $tag_command);
  655. if ($start_tag)
  656. $this->_push_tag($tag_command);
  657. else
  658. $this->_pop_tag($tag_command);
  659. if ($start_tag) {
  660. $output = '<?php ' . $this->_push_cacheable_state('block', $tag_command);
  661. $attrs = $this->_parse_attrs($tag_args);
  662. $_cache_attrs='';
  663. $arg_list = $this->_compile_arg_list('block', $tag_command, $attrs, $_cache_attrs);
  664. $output .= "$_cache_attrs\$this->_tag_stack[] = array('$tag_command', array(".implode(',', $arg_list).')); ';
  665. $output .= '$_block_repeat=true;' . $this->_compile_plugin_call('block', $tag_command).'($this->_tag_stack[count($this->_tag_stack)-1][1], null, $this, $_block_repeat);';
  666. $output .= 'while ($_block_repeat) { ob_start(); ?>';
  667. } else {
  668. $output = '<?php $_block_content = ob_get_contents(); ob_end_clean(); ';
  669. $_out_tag_text = $this->_compile_plugin_call('block', $tag_command).'($this->_tag_stack[count($this->_tag_stack)-1][1], $_block_content, $this, $_block_repeat)';
  670. if ($tag_modifier != '') {
  671. $this->_parse_modifiers($_out_tag_text, $tag_modifier);
  672. }
  673. $output .= '$_block_repeat=false;echo ' . $_out_tag_text . '; } ';
  674. $output .= " array_pop(\$this->_tag_stack); " . $this->_pop_cacheable_state('block', $tag_command) . '?>';
  675. }
  676. return true;
  677. }
  678. /**
  679. * compile custom function tag
  680. *
  681. * @param string $tag_command
  682. * @param string $tag_args
  683. * @param string $tag_modifier
  684. * @return string
  685. */
  686. function _compile_custom_tag($tag_command, $tag_args, $tag_modifier, &$output)
  687. {
  688. $found = false;
  689. $have_function = true;
  690. /*
  691. * First we check if the custom function has already been registered
  692. * or loaded from a plugin file.
  693. */
  694. if (isset($this->_plugins['function'][$tag_command])) {
  695. $found = true;
  696. $plugin_func = $this->_plugins['function'][$tag_command][0];
  697. if (!is_callable($plugin_func)) {
  698. $message = "custom function '$tag_command' is not implemented";
  699. $have_function = false;
  700. }
  701. }
  702. /*
  703. * Otherwise we need to load plugin file and look for the function
  704. * inside it.
  705. */
  706. else if ($plugin_file = $this->_get_plugin_filepath('function', $tag_command)) {
  707. $found = true;
  708. include_once $plugin_file;
  709. $plugin_func = 'smarty_function_' . $tag_command;
  710. if (!function_exists($plugin_func)) {
  711. $message = "plugin function $plugin_func() not found in $plugin_file\n";
  712. $have_function = false;
  713. } else {
  714. $this->_plugins['function'][$tag_command] = array($plugin_func, null, null, null, true);
  715. }
  716. }
  717. if (!$found) {
  718. return false;
  719. } else if (!$have_function) {
  720. $this->_syntax_error($message, E_USER_WARNING, __FILE__, __LINE__);
  721. return true;
  722. }
  723. /* declare plugin to be loaded on display of the template that
  724. we compile right now */
  725. $this->_add_plugin('function', $tag_command);
  726. $_cacheable_state = $this->_push_cacheable_state('function', $tag_command);
  727. $attrs = $this->_parse_attrs($tag_args);
  728. $_cache_attrs = '';
  729. $arg_list = $this->_compile_arg_list('function', $tag_command, $attrs, $_cache_attrs);
  730. $output = $this->_compile_plugin_call('function', $tag_command).'(array('.implode(',', $arg_list)."), \$this)";
  731. if($tag_modifier != '') {
  732. $this->_parse_modifiers($output, $tag_modifier);
  733. }
  734. if($output != '') {
  735. $output = '<?php ' . $_cacheable_state . $_cache_attrs . 'echo ' . $output . ';'
  736. . $this->_pop_cacheable_state('function', $tag_command) . "?>" . $this->_additional_newline;
  737. }
  738. return true;
  739. }
  740. /**
  741. * compile a registered object tag
  742. *
  743. * @param string $tag_command
  744. * @param array $attrs
  745. * @param string $tag_modifier
  746. * @return string
  747. */
  748. function _compile_registered_object_tag($tag_command, $attrs, $tag_modifier)
  749. {
  750. if (substr($tag_command, 0, 1) == '/') {
  751. $start_tag = false;
  752. $tag_command = substr($tag_command, 1);
  753. } else {
  754. $start_tag = true;
  755. }
  756. list($object, $obj_comp) = explode('->', $tag_command);
  757. $arg_list = array();
  758. if(count($attrs)) {
  759. $_assign_var = false;
  760. foreach ($attrs as $arg_name => $arg_value) {
  761. if($arg_name == 'assign') {
  762. $_assign_var = $arg_value;
  763. unset($attrs['assign']);
  764. continue;
  765. }
  766. if (is_bool($arg_value))
  767. $arg_value = $arg_value ? 'true' : 'false';
  768. $arg_list[] = "'$arg_name' => $arg_value";
  769. }
  770. }
  771. if($this->_reg_objects[$object][2]) {
  772. // smarty object argument format
  773. $args = "array(".implode(',', (array)$arg_list)."), \$this";
  774. } else {
  775. // traditional argument format
  776. $args = implode(',', array_values($attrs));
  777. if (empty($args)) {
  778. $args = 'null';
  779. }
  780. }
  781. $prefix = '';
  782. $postfix = '';
  783. $newline = '';
  784. if(!is_object($this->_reg_objects[$object][0])) {
  785. $this->_trigger_fatal_error("registered '$object' is not an object" , $this->_current_file, $this->_current_line_no, __FILE__, __LINE__);
  786. } elseif(!empty($this->_reg_objects[$object][1]) && !in_array($obj_comp, $this->_reg_objects[$object][1])) {
  787. $this->_trigger_fatal_error("'$obj_comp' is not a registered component of object '$object'", $this->_current_file, $this->_current_line_no, __FILE__, __LINE__);
  788. } elseif(method_exists($this->_reg_objects[$object][0], $obj_comp)) {
  789. // method
  790. if(in_array($obj_comp, $this->_reg_objects[$object][3])) {
  791. // block method
  792. if ($start_tag) {
  793. $prefix = "\$this->_tag_stack[] = array('$obj_comp', $args); ";
  794. $prefix .= "\$_block_repeat=true; \$this->_reg_objects['$object'][0]->$obj_comp(\$this->_tag_stack[count(\$this->_tag_stack)-1][1], null, \$this, \$_block_repeat); ";
  795. $prefix .= "while (\$_block_repeat) { ob_start();";
  796. $return = null;
  797. $postfix = '';
  798. } else {
  799. $prefix = "\$_obj_block_content = ob_get_contents(); ob_end_clean(); \$_block_repeat=false;";
  800. $return = "\$this->_reg_objects['$object'][0]->$obj_comp(\$this->_tag_stack[count(\$this->_tag_stack)-1][1], \$_obj_block_content, \$this, \$_block_repeat)";
  801. $postfix = "} array_pop(\$this->_tag_stack);";
  802. }
  803. } else {
  804. // non-block method
  805. $return = "\$this->_reg_objects['$object'][0]->$obj_comp($args)";
  806. }
  807. } else {
  808. // property
  809. $return = "\$this->_reg_objects['$object'][0]->$obj_comp";
  810. }
  811. if($return != null) {
  812. if($tag_modifier != '') {
  813. $this->_parse_modifiers($return, $tag_modifier);
  814. }
  815. if(!empty($_assign_var)) {
  816. $output = "\$this->assign('" . $this->_dequote($_assign_var) ."', $return);";
  817. } else {
  818. $output = 'echo ' . $return . ';';
  819. $newline = $this->_additional_newline;
  820. }
  821. } else {
  822. $output = '';
  823. }
  824. return '<?php ' . $prefix . $output . $postfix . "?>" . $newline;
  825. }
  826. /**
  827. * Compile {insert ...} tag
  828. *
  829. * @param string $tag_args
  830. * @return string
  831. */
  832. function _compile_insert_tag($tag_args)
  833. {
  834. $attrs = $this->_parse_attrs($tag_args);
  835. $name = $this->_dequote($attrs['name']);
  836. if (empty($name)) {
  837. return $this->_syntax_error("missing insert name", E_USER_ERROR, __FILE__, __LINE__);
  838. }
  839. if (!preg_match('~^\w+$~', $name)) {
  840. return $this->_syntax_error("'insert: 'name' must be an insert function name", E_USER_ERROR, __FILE__, __LINE__);
  841. }
  842. if (!empty($attrs['script'])) {
  843. $delayed_loading = true;
  844. } else {
  845. $delayed_loading = false;
  846. }
  847. foreach ($attrs as $arg_name => $arg_value) {
  848. if (is_bool($arg_value))
  849. $arg_value = $arg_value ? 'true' : 'false';
  850. $arg_list[] = "'$arg_name' => $arg_value";
  851. }
  852. $this->_add_plugin('insert', $name, $delayed_loading);
  853. $_params = "array('args' => array(".implode(', ', (array)$arg_list)."))";
  854. return "<?php require_once(SMARTY_CORE_DIR . 'core.run_insert_handler.php');\necho smarty_core_run_insert_handler($_params, \$this); ?>" . $this->_additional_newline;
  855. }
  856. /**
  857. * Compile {include ...} tag
  858. *
  859. * @param string $tag_args
  860. * @return string
  861. */
  862. function _compile_include_tag($tag_args)
  863. {
  864. $attrs = $this->_parse_attrs($tag_args);
  865. $arg_list = array();
  866. if (empty($attrs['file'])) {
  867. $this->_syntax_error("missing 'file' attribute in include tag", E_USER_ERROR, __FILE__, __LINE__);
  868. }
  869. foreach ($attrs as $arg_name => $arg_value) {
  870. if ($arg_name == 'file') {
  871. $include_file = $arg_value;
  872. continue;
  873. } else if ($arg_name == 'assign') {
  874. $assign_var = $arg_value;
  875. continue;
  876. }
  877. if (is_bool($arg_value))
  878. $arg_value = $arg_value ? 'true' : 'false';
  879. $arg_list[] = "'$arg_name' => $arg_value";
  880. }
  881. $output = '<?php ';
  882. if (isset($assign_var)) {
  883. $output .= "ob_start();\n";
  884. }
  885. $output .=
  886. "\$_smarty_tpl_vars = \$this->_tpl_vars;\n";
  887. $_params = "array('smarty_include_tpl_file' => " . $include_file . ", 'smarty_include_vars' => array(".implode(',', (array)$arg_list)."))";
  888. $output .= "\$this->_smarty_include($_params);\n" .
  889. "\$this->_tpl_vars = \$_smarty_tpl_vars;\n" .
  890. "unset(\$_smarty_tpl_vars);\n";
  891. if (isset($assign_var)) {
  892. $output .= "\$this->assign(" . $assign_var . ", ob_get_contents()); ob_end_clean();\n";
  893. }
  894. $output .= ' ?>';
  895. return $output;
  896. }
  897. /**
  898. * Compile {include ...} tag
  899. *
  900. * @param string $tag_args
  901. * @return string
  902. */
  903. function _compile_include_php_tag($tag_args)
  904. {
  905. $attrs = $this->_parse_attrs($tag_args);
  906. if (empty($attrs['file'])) {
  907. $this->_syntax_error("missing 'file' attribute in include_php tag", E_USER_ERROR, __FILE__, __LINE__);
  908. }
  909. $assign_var = (empty($attrs['assign'])) ? '' : $this->_dequote($attrs['assign']);
  910. $once_var = (empty($attrs['once']) || $attrs['once']=='false') ? 'false' : 'true';
  911. $arg_list = array();
  912. foreach($attrs as $arg_name => $arg_value) {
  913. if($arg_name != 'file' AND $arg_name != 'once' AND $arg_name != 'assign') {
  914. if(is_bool($arg_value))
  915. $arg_value = $arg_value ? 'true' : 'false';
  916. $arg_list[] = "'$arg_name' => $arg_value";
  917. }
  918. }
  919. $_params = "array('smarty_file' => " . $attrs['file'] . ", 'smarty_assign' => '$assign_var', 'smarty_once' => $once_var, 'smarty_include_vars' => array(".implode(',', $arg_list)."))";
  920. return "<?php require_once(SMARTY_CORE_DIR . 'core.smarty_include_php.php');\nsmarty_core_smarty_include_php($_params, \$this); ?>" . $this->_additional_newline;
  921. }
  922. /**
  923. * Compile {section ...} tag
  924. *
  925. * @param string $tag_args
  926. * @return string
  927. */
  928. function _compile_section_start($tag_args)
  929. {
  930. $attrs = $this->_parse_attrs($tag_args);
  931. $arg_list = array();
  932. $output = '<?php ';
  933. $section_name = $attrs['name'];
  934. if (empty($section_name)) {
  935. $this->_syntax_error("missing section name", E_USER_ERROR, __FILE__, __LINE__);
  936. }
  937. $output .= "unset(\$this->_sections[$section_name]);\n";
  938. $section_props = "\$this->_sections[$section_name]";
  939. foreach ($attrs as $attr_name => $attr_value) {
  940. switch ($attr_name) {
  941. case 'loop':
  942. $output .= "{$section_props}['loop'] = is_array(\$_loop=$attr_value) ? count(\$_loop) : max(0, (int)\$_loop); unset(\$_loop);\n";
  943. break;
  944. case 'show':
  945. if (is_bool($attr_value))
  946. $show_attr_value = $attr_value ? 'true' : 'false';
  947. else
  948. $show_attr_value = "(bool)$attr_value";
  949. $output .= "{$section_props}['show'] = $show_attr_value;\n";
  950. break;
  951. case 'name':
  952. $output .= "{$section_props}['$attr_name'] = $attr_value;\n";
  953. break;
  954. case 'max':
  955. case 'start':
  956. $output .= "{$section_props}['$attr_name'] = (int)$attr_value;\n";
  957. break;
  958. case 'step':
  959. $output .= "{$section_props}['$attr_name'] = ((int)$attr_value) == 0 ? 1 : (int)$attr_value;\n";
  960. break;
  961. default:
  962. $this->_syntax_error("unknown section attribute - '$attr_name'", E_USER_ERROR, __FILE__, __LINE__);
  963. break;
  964. }
  965. }
  966. if (!isset($attrs['show']))
  967. $output .= "{$section_props}['show'] = true;\n";
  968. if (!isset($attrs['loop']))
  969. $output .= "{$section_props}['loop'] = 1;\n";
  970. if (!isset($attrs['max']))
  971. $output .= "{$section_props}['max'] = {$section_props}['loop'];\n";
  972. else
  973. $output .= "if ({$section_props}['max'] < 0)\n" .
  974. " {$section_props}['max'] = {$section_props}['loop'];\n";
  975. if (!isset($attrs['step']))
  976. $output .= "{$section_props}['step'] = 1;\n";
  977. if (!isset($attrs['start']))
  978. $output .= "{$section_props}['start'] = {$section_props}['step'] > 0 ? 0 : {$section_props}['loop']-1;\n";
  979. else {
  980. $output .= "if ({$section_props}['start'] < 0)\n" .
  981. " {$section_props}['start'] = max({$section_props}['step'] > 0 ? 0 : -1, {$section_props}['loop'] + {$section_props}['start']);\n" .
  982. "else\n" .
  983. " {$section_props}['start'] = min({$section_props}['start'], {$section_props}['step'] > 0 ? {$section_props}['loop'] : {$section_props}['loop']-1);\n";
  984. }
  985. $output .= "if ({$section_props}['show']) {\n";
  986. if (!isset($attrs['start']) && !isset($attrs['step']) && !isset($attrs['max'])) {
  987. $output .= " {$section_props}['total'] = {$section_props}['loop'];\n";
  988. } else {
  989. $output .= " {$section_props}['total'] = min(ceil(({$section_props}['step'] > 0 ? {$section_props}['loop'] - {$section_props}['start'] : {$section_props}['start']+1)/abs({$section_props}['step'])), {$section_props}['max']);\n";
  990. }
  991. $output .= " if ({$section_props}['total'] == 0)\n" .
  992. " {$section_props}['show'] = false;\n" .
  993. "} else\n" .
  994. " {$section_props}['total'] = 0;\n";
  995. $output .= "if ({$section_props}['show']):\n";
  996. $output .= "
  997. for ({$section_props}['index'] = {$section_props}['start'], {$section_props}['iteration'] = 1;
  998. {$section_props}['iteration'] <= {$section_props}['total'];
  999. {$section_props}['index'] += {$section_props}['step'], {$section_props}['iteration']++):\n";
  1000. $output .= "{$section_props}['rownum'] = {$section_props}['iteration'];\n";
  1001. $output .= "{$section_props}['index_prev'] = {$section_props}['index'] - {$section_props}['step'];\n";
  1002. $output .= "{$section_props}['index_next'] = {$section_props}['index'] + {$section_props}['step'];\n";
  1003. $output .= "{$section_props}['first'] = ({$section_props}['iteration'] == 1);\n";
  1004. $output .= "{$section_props}['last'] = ({$section_props}['iteration'] == {$section_props}['total']);\n";
  1005. $output .= "?>";
  1006. return $output;
  1007. }
  1008. //htf here
  1009. /**
  1010. * Compile {db ...} tag
  1011. * it htf write
  1012. *
  1013. * @param string $tag_args
  1014. * @return string
  1015. */
  1016. function _compile_db_start($tag_args)
  1017. {
  1018. $attrs = $this->_parse_attrs($tag_args);
  1019. foreach($attrs as &$attr):
  1020. $attr = str_replace("'",'',$attr);
  1021. endforeach;
  1022. if (empty($attrs['from'])) {
  1023. $this->_syntax_error("missing db_select table name", E_USER_ERROR, __FILE__, __LINE__);
  1024. }
  1025. if(!array_key_exists('_name',$attrs)) $attrs['_name']='records';
  1026. $output = "<?php \n";
  1027. if($this->db=='')
  1028. {
  1029. global $php;
  1030. $php->autoload('db');
  1031. $this->db = $php->db;
  1032. $output.= "global \$php;\n";
  1033. }
  1034. $select = new SelectDB($this->db);
  1035. $select->call_by = 'smarty';
  1036. // if(!array_key_exists('limit',$attrs) and !array_key_exists('page',$attrs)) $attrs['limit']=10;
  1037. $attrs['select'] = str_replace('"','',$attrs['select']);
  1038. $attrs['select'] = str_replace("'",'',$attrs['select']);
  1039. $select->put($attrs);
  1040. $output .= "\$sql=\"".$select->getsql()."\";\n";
  1041. $output .= "\$this->_tpl_vars['{$attrs['_name']}']=\$php->db->query(\$sql)->fetchall();\n";
  1042. $output .= '$'.$attrs['_name'].'_count = count($this->_tpl_vars["'.$attrs['_name'].'"]);'."\n";
  1043. $output .= 'for($'.$attrs['_name'].'_i=0;$'.$attrs['_name'].'_i<$'.$attrs['_name'].'_count;$'.$attrs['_name'].'_i++):'."\n";
  1044. $output .= '$this->_records["'.$attrs['_name'].'"]["index"]=$'.$attrs['_name'].'_i;'."\n";
  1045. $output .= '$this->_records["'.$attrs['_name'].'"]["first"]= $'.$attrs['_name'].'_i==0;'."\n";
  1046. $output .= '$this->_records["'.$attrs['_name'].'"]["last"]= $'.$attrs['_name'].'_i==($'.$attrs['_name'].'_count-1);'."\n";
  1047. $output .= '$this->_sections["'.$attrs['_name'].'"]["index"]=$'.$attrs['_name'].'_i;'."\n";
  1048. $output .= "?>\n";
  1049. return $output;
  1050. }
  1051. //end htf
  1052. //htf here
  1053. /**
  1054. * Compile {db ...} tag
  1055. * it htf write
  1056. *
  1057. * @param string $tag_args
  1058. * @return string
  1059. */
  1060. function _compile_cms_start($tag_args)
  1061. {
  1062. $attrs = $this->_parse_attrs($tag_args);
  1063. foreach($attrs as &$attr):
  1064. $attr = str_replace("'",'',$attr);
  1065. endforeach;
  1066. if(empty($attrs['get'])) $attrs['get'] = 'category';
  1067. if(empty($attrs['name'])) $result_name = 'result';
  1068. else $result_name = $attrs['name'];
  1069. if(empty($attrs['key'])) $key_name = 'index';
  1070. else $key_name = $attrs['key'];
  1071. if(empty($attrs['func'])) $attrs['func'] = "get";
  1072. if(!($this->swoole instanceof Swoole))
  1073. {
  1074. global $php;
  1075. $this->swoole = $php;
  1076. }
  1077. $output = "<?php \n";
  1078. if($this->db=='')
  1079. {
  1080. $this->swoole->autoload('db');
  1081. $this->db = $this->swoole->db;
  1082. $output.= "global \$php;\n";
  1083. }
  1084. if(!is_object($this->cms))
  1085. {
  1086. $this->cms = $this->swoole->createModel('CMS');
  1087. $this->cms->smarty = $this;
  1088. $this->cms->swoole = $this->swoole;
  1089. }
  1090. $sql = $this->cms->get($attrs);
  1091. $output .= "\$$result_name = \$php->db->query(\"$sql\")->fetchall();\n";
  1092. $output .= "foreach(\$$result_name as \${$result_name}_key=>\${$result_name}_value): \n";
  1093. $output .= "\$this->_tpl_vars['{$result_name}'] = \${$result_name}_value;\n";
  1094. $output .= "\$this->_tpl_vars['{$key_name}'] = \${$result_name}_key;\n";
  1095. $output .= "?>\n";
  1096. return $output;
  1097. }
  1098. //end htf
  1099. /**
  1100. * Compile {foreach ...} tag.
  1101. *
  1102. * @param string $tag_args
  1103. * @return string
  1104. */
  1105. function _compile_foreach_start($tag_args)
  1106. {
  1107. $attrs = $this->_parse_attrs($tag_args);
  1108. $arg_list = array();
  1109. if (empty($attrs['from'])) {
  1110. return $this->_syntax_error("foreach: missing 'from' attribute", E_USER_ERROR, __FILE__, __LINE__);
  1111. }
  1112. $from = $attrs['from'];
  1113. if (empty($attrs['item'])) {
  1114. return $this->_syntax_error("foreach: missing 'item' attribute", E_USER_ERROR, __FILE__, __LINE__);
  1115. }
  1116. $item = $this->_dequote($attrs['item']);
  1117. if (!preg_match('~^\w+$~', $item)) {
  1118. return $this->_syntax_error("'foreach: 'item' must be a variable name (literal string)", E_USER_ERROR, __FILE__, __LINE__);
  1119. }
  1120. if (isset($attrs['key'])) {
  1121. $key = $this->_dequote($attrs['key']);
  1122. if (!preg_match('~^\w+$~', $key)) {
  1123. return $this->_syntax_error("foreach: 'key' must to be a variable name (literal string)", E_USER_ERROR, __FILE__, __LINE__);
  1124. }
  1125. $key_part = "\$this->_tpl_vars['$key'] => ";
  1126. } else {
  1127. $key = null;
  1128. $key_part = '';
  1129. }
  1130. if (isset($attrs['name'])) {
  1131. $name = $attrs['name'];
  1132. } else {
  1133. $name = null;
  1134. }
  1135. $output = '<?php ';
  1136. $output .= "\$_from = $from; if (!is_array(\$_from) && !is_object(\$_from)) { settype(\$_from, 'array'); }";
  1137. if (isset($name)) {
  1138. $foreach_props = "\$this->_foreach[$name]";
  1139. $output .= "{$foreach_props} = array('total' => count(\$_from), 'iteration' => 0);\n";
  1140. $output .= "if ({$foreach_props}['total'] > 0):\n";
  1141. $output .= " foreach (\$_from as $key_part\$this->_tpl_vars['$item']):\n";
  1142. $output .= " {$foreach_props}['iteration']++;\n";
  1143. } else {
  1144. $output .= "if (count(\$_from)):\n";
  1145. $output .= " foreach (\$_from as $key_part\$this->_tpl_vars['$item']):\n";
  1146. }
  1147. $output .= '?>';
  1148. return $output;
  1149. }
  1150. /**
  1151. * Compile {capture} .. {/capture} tags
  1152. *
  1153. * @param boolean $start true if this is the {capture} tag
  1154. * @param string $tag_args
  1155. * @return string
  1156. */
  1157. function _compile_capture_tag($start, $tag_args = '')
  1158. {
  1159. $attrs = $this->_parse_attrs($tag_args);
  1160. if ($start) {
  1161. if (isset($attrs['name']))
  1162. $buffer = $attrs['name'];
  1163. else
  1164. $buffer = "'default'";
  1165. if (isset($attrs['assign']))
  1166. $assign = $attrs['assign'];
  1167. else
  1168. $assign = null;
  1169. $output = "<?php ob_start(); ?>";
  1170. $this->_capture_stack[] = array($buffer, $assign);
  1171. } else {
  1172. list($buffer, $assign) = array_pop($this->_capture_stack);
  1173. $output = "<?php \$this->_smarty_vars['capture'][$buffer] = ob_get_contents(); ";
  1174. if (isset($assign)) {
  1175. $output .= " \$this->assign($assign, ob_get_contents());";
  1176. }
  1177. $output .= "ob_end_clean(); ?>";
  1178. }
  1179. return $output;
  1180. }
  1181. /**
  1182. * Compile {if ...} tag
  1183. *
  1184. * @param string $tag_args
  1185. * @param boolean $elseif if true, uses elseif instead of if
  1186. * @return string
  1187. */
  1188. function _compile_if_tag($tag_arg

Large files files are truncated, but you can click here to view the full file