PageRenderTime 58ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/secured/phpDocumentor/phpDocumentor/Smarty-2.6.0/libs/Smarty_Compiler.class.php

http://oregon-caspages.googlecode.com/
PHP | 2123 lines | 1418 code | 257 blank | 448 comment | 303 complexity | 5f9c670144f8de36d406ab90227eddda MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, AGPL-3.0

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

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