1 package net.sourceforge.phpeclipse.tests.parser;
3 /*******************************************************************************
4 * Copyright (c) 2002 www.phpeclipse.de All rights
5 * reserved. This program and the accompanying materials are made available
6 * under the terms of the Common Public License v1.0 which accompanies this
7 * distribution, and is available at http://www.eclipse.org/legal/cpl-v10.html
8 ******************************************************************************/
9 import net.sourceforge.phpdt.core.tests.util.AbstractCompilerTest;
12 * Tests the php parser
14 public class SmartyCompilerTestCase extends AbstractCompilerTest {
16 public SmartyCompilerTestCase(String name) {
21 * Test the PHP Parser with different PHP snippets
23 public void testPHPParser() {
27 + " * Project: Smarty: the PHP compiling template engine\n"
28 + " * File: Smarty_Compiler.class.php\n"
29 + " * Author: Monte Ohrt <monte@ispi.net>\n"
30 + " * Andrei Zmievski <andrei@php.net>\n"
32 + " * Version: 2.4.2\n"
33 + " * Copyright: 2001,2002 ispi of Lincoln, Inc.\n"
35 + " * This library is free software; you can redistribute it and/or\n"
36 + " * modify it under the terms of the GNU Lesser General Public\n"
37 + " * License as published by the Free Software Foundation; either\n"
38 + " * version 2.1 of the License, or (at your option) any later version.\n"
40 + " * This library is distributed in the hope that it will be useful,\n"
41 + " * but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
42 + " * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n"
43 + " * Lesser General Public License for more details.\n"
45 + " * You should have received a copy of the GNU Lesser General Public\n"
46 + " * License along with this library; if not, write to the Free Software\n"
47 + " * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n"
49 + " * You may contact the authors of Smarty by e-mail at:\n"
50 + " * monte@ispi.net\n"
51 + " * andrei@php.net\n"
53 + " * Or, write to:\n"
55 + " * Director of Technology, ispi\n"
56 + " * 237 S. 70th suite 220\n"
57 + " * Lincoln, NE 68510\n"
59 + " * The latest version of Smarty can be obtained from:\n"
60 + " * http://www.phpinsider.com/\n"
64 + "class Smarty_Compiler extends Smarty {\n"
66 + " // internal vars\n"
67 + " public $_sectionelse_stack = array(); // keeps track of whether section had \'else\' part\n"
68 + " public $_foreachelse_stack = array(); // keeps track of whether foreach had \'else\' part\n"
69 + " public $_literal_blocks = array(); // keeps literal template blocks\n"
70 + " public $_php_blocks = array(); // keeps php code blocks\n"
71 + " public $_current_file = null; // the current template being compiled\n"
72 + " public $_current_line_no = 1; // line number for error messages\n"
73 + " public $_capture_stack = array(); // keeps track of nested capture buffers\n"
74 + " public $_plugin_info = array(); // keeps track of plugins to load\n"
75 + " public $_init_smarty_vars = false;\n"
76 + " public $_permitted_tokens = array(\'true\',\'false\',\'yes\',\'no\',\'on\',\'off\');\n"
77 + " public $_db_qstr_regexp = null; // regexps are setup in the constructor\n"
78 + " public $_si_qstr_regexp = null;\n"
79 + " public $_qstr_regexp = null;\n"
80 + " public $_func_regexp = null;\n"
81 + " public $_var_bracket_regexp = null;\n"
82 + " public $_dvar_guts_regexp = null;\n"
83 + " public $_dvar_regexp = null;\n"
84 + " public $_cvar_regexp = null;\n"
85 + " public $_svar_regexp = null;\n"
86 + " public $_avar_regexp = null;\n"
87 + " public $_mod_regexp = null;\n"
88 + " public $_var_regexp = null;\n"
89 + " public $_parenth_param_regexp = null;\n"
90 + " public $_func_call_regexp = null;\n"
91 + " public $_obj_ext_regexp = null;\n"
92 + " public $_obj_start_regexp = null;\n"
93 + " public $_obj_params_regexp = null;\n"
94 + " public $_obj_call_regexp = null;\n"
97 + " * The class constructor.\n"
99 + " * @access public\n"
101 + " function Smarty_Compiler()\n"
103 + " // matches double quoted strings:\n"
105 + " // \"foo\\\"bar\"\n"
106 + " $this->_db_qstr_regexp = \'\"[^\"\\\\\\\\]*(?:\\\\\\\\.[^\"\\\\\\\\]*)*\"\';\n"
108 + " // matches single quoted strings:\n"
110 + " // \'foo\\\'bar\'\n"
111 + " $this->_si_qstr_regexp = \'\\\'[^\\\'\\\\\\\\]*(?:\\\\\\\\.[^\\\'\\\\\\\\]*)*\\\'\';\n"
113 + " // matches single or double quoted strings\n"
114 + " $this->_qstr_regexp = \'(?:\' . $this->_db_qstr_regexp . \'|\' . $this->_si_qstr_regexp . \')\';\n"
116 + " // matches bracket portion of vars\n"
120 + " $this->_var_bracket_regexp = \'\\[\\$?[\\w\\.]+\\]\';\n"
122 + " // matches $ vars (not objects):\n"
125 + " // $foo.bar.foobar\n"
128 + " // $foo[5][blah]\n"
129 + " // $foo[5].bar[$foobar][4]\n"
130 + " $this->_dvar_guts_regexp = \'\\w+(?:\' . $this->_var_bracket_regexp\n"
131 + " . \')*(?:\\.\\$?\\w+(?:\' . $this->_var_bracket_regexp . \')*)*\';\n"
132 + " $this->_dvar_regexp = \'\\$\' . $this->_dvar_guts_regexp;\n"
134 + " // matches config vars:\n"
136 + " // #foobar123_foo#\n"
137 + " $this->_cvar_regexp = \'\\#\\w+\\#\';\n"
139 + " // matches section vars:\n"
141 + " $this->_svar_regexp = \'\\%\\w+\\.\\w+\\%\';\n"
143 + " // matches all valid variables (no quotes, no modifiers)\n"
144 + " $this->_avar_regexp = \'(?:\' . $this->_dvar_regexp . \'|\'\n"
145 + " . $this->_cvar_regexp . \'|\' . $this->_svar_regexp . \')\';\n"
147 + " // matches valid modifier syntax:\n"
150 + " // |foo:\"bar\"\n"
152 + " // |foo:\"bar\":$foobar\n"
155 + " $this->_mod_regexp = \'(?:\\|@?\\w+(?::(?>\\w+|\'\n"
156 + " . $this->_avar_regexp . \'|\' . $this->_qstr_regexp .\'))*)\';\n"
158 + " // matches valid variable syntax:\n"
165 + " $this->_var_regexp = \'(?:\' . $this->_avar_regexp . \'|\' . $this->_qstr_regexp . \')\';\n"
167 + " // matches valid object call (no objects allowed in parameters):\n"
169 + " // $foo->bar()\n"
170 + " // $foo->bar(\"text\")\n"
171 + " // $foo->bar($foo, $bar, \"text\")\n"
172 + " // $foo->bar($foo|bar, \"foo\"|bar)\n"
173 + " // $foo->bar->foo()\n"
174 + " // $foo->bar->foo->bar()\n"
175 + " $this->_obj_ext_regexp = \'\\->(?:\\w+|\' . $this->_dvar_regexp . \')\';\n"
176 + " $this->_obj_params_regexp = \'\\((?:\\w+|\'\n"
177 + " . $this->_var_regexp . \'(?>\' . $this->_mod_regexp . \'*)(?:\\s*,\\s*(?:(?:\\w+|\'\n"
178 + " . $this->_var_regexp . \'(?>\' . $this->_mod_regexp . \'*))))*)?\\)\'; \n"
179 + " $this->_obj_start_regexp = \'(?:\' . $this->_dvar_regexp . \'(?:\' . $this->_obj_ext_regexp . \')+)\';\n"
180 + " $this->_obj_call_regexp = \'(?:\' . $this->_obj_start_regexp . \'(?:\' . $this->_obj_params_regexp . \')?)\';\n"
182 + " // matches valid function name:\n"
185 + " $this->_func_regexp = \'[a-zA-Z_]\\w*\';\n"
187 + " // matches valid registered object:\n"
189 + " $this->_reg_obj_regexp = \'[a-zA-Z_]\\w*->[a-zA-Z_]\\w*\';\n"
191 + " // matches valid parameter values:\n"
198 + " // \"text\"|bar\n"
200 + " $this->_param_regexp = \'(?:\\s*(?:\' . $this->_obj_call_regexp . \'|\'\n"
201 + " . $this->_var_regexp . \'|\\w+)(?>\' . $this->_mod_regexp . \'*)\\s*)\'; \n"
203 + " // matches valid parenthesised function parameters:\n"
206 + " // $foo, $bar, \"text\"\n"
207 + " // $foo|bar, \"foo\"|bar, $foo->bar($foo)|bar\n"
208 + " $this->_parenth_param_regexp = \'(?:\\((?:\\w+|\'\n"
209 + " . $this->_param_regexp . \'(?:\\s*,\\s*(?:(?:\\w+|\'\n"
210 + " . $this->_param_regexp . \')))*)?\\))\';\n"
212 + " // matches valid function call:\n"
214 + " // foo_bar($foo)\n"
215 + " // _foo_bar($foo,\"bar\")\n"
216 + " // foo123($foo,$foo->bar(),\"foo\")\n"
217 + " $this->_func_call_regexp = \'(?:\' . $this->_func_regexp . \'\\s*(?:\'\n"
218 + " . $this->_parenth_param_regexp . \'))\'; \n"
223 + " * compile a template file\n"
225 + " * @access public\n"
226 + " * @param $tpl_file\n"
227 + " * @param $template_source\n"
228 + " * @param $template_compiled\n"
230 + " function _compile_file($tpl_file, $template_source, &$template_compiled)\n"
232 + " if ($this->security) {\n"
233 + " // do not allow php syntax to be executed unless specified\n"
234 + " if ($this->php_handling == SMARTY_PHP_ALLOW &&\n"
235 + " !$this->security_settings[\'PHP_HANDLING\']) {\n"
236 + " $this->php_handling = SMARTY_PHP_PASSTHRU;\n"
240 + " $this->_load_filters();\n"
242 + " $this->_current_file = $tpl_file;\n"
243 + " $this->_current_line_no = 1;\n"
244 + " $ldq = preg_quote($this->left_delimiter, \'!\');\n"
245 + " $rdq = preg_quote($this->right_delimiter, \'!\');\n"
247 + " // run template source through prefilter functions\n"
248 + " if (count($this->_plugins[\'prefilter\']) > 0) {\n"
249 + " foreach ($this->_plugins[\'prefilter\'] as $filter_name => $prefilter) {\n"
250 + " if ($prefilter === false) continue; \n"
251 + " if ($prefilter[3] || function_exists($prefilter[0])) {\n"
252 + " $template_source = $prefilter[0]($template_source, $this);\n"
253 + " $this->_plugins[\'prefilter\'][$filter_name][3] = true;\n"
255 + " $this->_trigger_fatal_error(\"[plugin] prefilter \'$filter_name\' is not implemented\");\n"
260 + " /* Annihilate the comments. */\n"
261 + " $template_source = preg_replace(\"!({$ldq})\\*(.*?)\\*({$rdq})!se\",\n"
262 + " \"\'\\\\1*\'.str_repeat(\\\"\\n\\\", substr_count(\'\\\\2\', \\\"\\n\\\")) .\'*\\\\3\'\",\n"
263 + " $template_source);\n"
265 + " /* Pull out the literal blocks. */\n"
266 + " preg_match_all(\"!{$ldq}literal{$rdq}(.*?){$ldq}/literal{$rdq}!s\", $template_source, $match);\n"
267 + " $this->_literal_blocks = $match[1];\n"
268 + " $template_source = preg_replace(\"!{$ldq}literal{$rdq}(.*?){$ldq}/literal{$rdq}!s\",\n"
269 + " $this->quote_replace($this->left_delimiter.\'literal\'.$this->right_delimiter), $template_source);\n"
271 + " /* Pull out the php code blocks. */\n"
272 + " preg_match_all(\"!{$ldq}php{$rdq}(.*?){$ldq}/php{$rdq}!s\", $template_source, $match);\n"
273 + " $this->_php_blocks = $match[1];\n"
274 + " $template_source = preg_replace(\"!{$ldq}php{$rdq}(.*?){$ldq}/php{$rdq}!s\",\n"
275 + " $this->quote_replace($this->left_delimiter.\'php\'.$this->right_delimiter), $template_source);\n"
277 + " /* Gather all template tags. */\n"
278 + " preg_match_all(\"!{$ldq}\\s*(.*?)\\s*{$rdq}!s\", $template_source, $match);\n"
279 + " $template_tags = $match[1];\n"
280 + " /* Split content by template tags to obtain non-template content. */\n"
281 + " $text_blocks = preg_split(\"!{$ldq}.*?{$rdq}!s\", $template_source);\n"
283 + " /* loop through text blocks */\n"
284 + " for ($curr_tb = 0, $for_max = count($text_blocks); $curr_tb < $for_max; $curr_tb++) {\n"
285 + " /* match anything resembling php tags */\n"
286 + " if (preg_match_all(\'!(<\\?(?:\\w+|=)?|\\?>|language\\s*=\\s*[\\\"\\\']?php[\\\"\\\']?)!is\', $text_blocks[$curr_tb], $sp_match)) {\n"
287 + " /* replace tags with placeholders to prevent recursive replacements */\n"
288 + " $sp_match[1] = array_unique($sp_match[1]);\n"
289 + " usort($sp_match[1], \'_smarty_sort_length\');\n"
290 + " for ($curr_sp = 0, $for_max2 = count($sp_match[1]); $curr_sp < $for_max2; $curr_sp++) {\n"
291 + " $text_blocks[$curr_tb] = str_replace($sp_match[1][$curr_sp],\'%%%SMARTYSP\'.$curr_sp.\'%%%\',$text_blocks[$curr_tb]);\n"
293 + " /* process each one */\n"
294 + " for ($curr_sp = 0, $for_max2 = count($sp_match[0]); $curr_sp < $for_max2; $curr_sp++) {\n"
295 + " if ($this->php_handling == SMARTY_PHP_PASSTHRU) {\n"
296 + " /* echo php contents */\n"
297 + " $text_blocks[$curr_tb] = str_replace(\'%%%SMARTYSP\'.$curr_sp.\'%%%\', \'<?php echo \\\'\'.str_replace(\"\'\", \"\\\'\", $sp_match[1][$curr_sp]).\'\\\'; ?>\'.\"\\n\", $text_blocks[$curr_tb]);\n"
298 + " } else if ($this->php_handling == SMARTY_PHP_QUOTE) {\n"
299 + " /* quote php tags */\n"
300 + " $text_blocks[$curr_tb] = str_replace(\'%%%SMARTYSP\'.$curr_sp.\'%%%\', htmlspecialchars($sp_match[1][$curr_sp]), $text_blocks[$curr_tb]);\n"
301 + " } else if ($this->php_handling == SMARTY_PHP_REMOVE) {\n"
302 + " /* remove php tags */\n"
303 + " $text_blocks[$curr_tb] = str_replace(\'%%%SMARTYSP\'.$curr_sp.\'%%%\', \'\', $text_blocks[$curr_tb]);\n"
305 + " /* SMARTY_PHP_ALLOW, but echo non php starting tags */\n"
306 + " $sp_match[1][$curr_sp] = preg_replace(\'%(<\\?(?!php|=|$))%i\', \'<?php echo \\\'\\\\1\\\'?>\'.\"\\n\", $sp_match[1][$curr_sp]);\n"
307 + " $text_blocks[$curr_tb] = str_replace(\'%%%SMARTYSP\'.$curr_sp.\'%%%\', $sp_match[1][$curr_sp], $text_blocks[$curr_tb]);\n"
313 + " /* Compile the template tags into PHP code. */\n"
314 + " $compiled_tags = array();\n"
315 + " for ($i = 0, $for_max = count($template_tags); $i < $for_max; $i++) {\n"
316 + " $this->_current_line_no += substr_count($text_blocks[$i], \"\\n\");\n"
317 + " $compiled_tags[] = $this->_compile_tag($template_tags[$i]);\n"
318 + " $this->_current_line_no += substr_count($template_tags[$i], \"\\n\");\n"
321 + " $template_compiled = \'\';\n"
323 + " /* Interleave the compiled contents and text blocks to get the final result. */\n"
324 + " for ($i = 0, $for_max = count($compiled_tags); $i < $for_max; $i++) {\n"
325 + " $template_compiled .= $text_blocks[$i].$compiled_tags[$i];\n"
327 + " $template_compiled .= $text_blocks[$i];\n"
329 + " /* Reformat data between \'strip\' and \'/strip\' tags, removing spaces, tabs and newlines. */\n"
330 + " if (preg_match_all(\"!{$ldq}strip{$rdq}.*?{$ldq}/strip{$rdq}!s\", $template_compiled, $match)) {\n"
331 + " $strip_tags = $match[0];\n"
332 + " $strip_tags_modified = preg_replace(\"!{$ldq}/?strip{$rdq}|[\\t ]+$|^[\\t ]+!m\", \'\', $strip_tags);\n"
333 + " $strip_tags_modified = preg_replace(\'![\\r\\n]+!m\', \'\', $strip_tags_modified);\n"
334 + " for ($i = 0, $for_max = count($strip_tags); $i < $for_max; $i++)\n"
335 + " $template_compiled = preg_replace(\"!{$ldq}strip{$rdq}.*?{$ldq}/strip{$rdq}!s\",\n"
336 + " $this->quote_replace($strip_tags_modified[$i]),\n"
337 + " $template_compiled, 1);\n"
340 + " // remove \\n from the end of the file, if any\n"
341 + " if ($template_compiled{strlen($template_compiled) - 1} == \"\\n\" ) {\n"
342 + " $template_compiled = substr($template_compiled, 0, -1);\n"
345 + " // run compiled template through postfilter functions\n"
346 + " if (count($this->_plugins[\'postfilter\']) > 0) {\n"
347 + " foreach ($this->_plugins[\'postfilter\'] as $filter_name => $postfilter) {\n"
348 + " if ($postfilter === false) continue;\n"
349 + " if ($postfilter[3] || function_exists($postfilter[0])) {\n"
350 + " $template_compiled = $postfilter[0]($template_compiled, $this);\n"
351 + " $this->_plugins[\'postfilter\'][$filter_name][3] = true;\n"
353 + " $this->_trigger_plugin_error(\"Smarty plugin error: postfilter \'$filter_name\' is not implemented\");\n"
358 + " // put header at the top of the compiled template\n"
359 + " $template_header = \"<?php /* Smarty version \".$this->_version.\", created on \".strftime(\"%Y-%m-%d %H:%M:%S\").\"\\n\";\n"
360 + " $template_header .= \" compiled from \".$tpl_file.\" */ ?>\\n\";\n"
362 + " /* Emit code to load needed plugins. */\n"
363 + " if (count($this->_plugin_info)) {\n"
364 + " $plugins_code = \'<?php $this->_load_plugins(array(\';\n"
365 + " foreach ($this->_plugin_info as $plugin_type => $plugins) {\n"
366 + " foreach ($plugins as $plugin_name => $plugin_info) {\n"
367 + " $plugins_code .= \"\\narray(\'$plugin_type\', \'$plugin_name\', \'$plugin_info[0]\', $plugin_info[1], \";\n"
368 + " $plugins_code .= $plugin_info[2] ? \'true),\' : \'false),\';\n"
371 + " $plugins_code .= \")); ?>\";\n"
372 + " $template_header .= $plugins_code;\n"
373 + " $this->_plugin_info = array();\n"
376 + " if ($this->_init_smarty_vars) {\n"
377 + " $template_header .= \"<?php \\$this->_assign_smarty_interface(); ?>\\n\";\n"
378 + " $this->_init_smarty_vars = false;\n"
381 + " $template_compiled = $template_header . $template_compiled;\n"
387 + " * Compile a template tag\n"
389 + " * @access public\n"
390 + " * @param $template_tag\n"
392 + " function _compile_tag($template_tag)\n"
395 + " /* Matched comment. */\n"
396 + " if ($template_tag{0} == \'*\' && $template_tag{strlen($template_tag) - 1} == \'*\')\n"
399 + " /* Split tag into two three parts: command, command modifiers and the arguments. */\n"
400 + " if(! preg_match(\'/^(?:(\' . $this->_obj_call_regexp . \'|\' . $this->_var_regexp\n"
401 + " . \'|\' . $this->_reg_obj_regexp . \'|\\/?\' . $this->_func_regexp . \')(\' . $this->_mod_regexp . \'*))\n"
402 + " (?:\\s+(.*))?$\n"
403 + " /xs\', $template_tag, $match)) {\n"
404 + " $this->_syntax_error(\"unrecognized tag: $template_tag\", E_USER_ERROR, __FILE__, __LINE__);\n"
407 + " $tag_command = $match[1];\n"
408 + " $tag_modifier = isset($match[2]) ? $match[2] : null;\n"
409 + " $tag_args = isset($match[3]) ? $match[3] : null;\n"
412 + " /* If the tag name is a variable or object, we process it. */\n"
413 + " if (preg_match(\'!^\' . $this->_obj_call_regexp . \'|\' . $this->_var_regexp . \'$!\', $tag_command)) {\n"
414 + " $return = $this->_parse_var_props($tag_command . $tag_modifier, $this->_parse_attrs($tag_args));\n"
415 + " if(isset($_tag_attrs[\'assign\'])) {\n"
416 + " return \"<?php \\$this->assign(\'\" . $this->_dequote($_tag_attrs[\'assign\']) . \"\', $return ); ?>\\n\"; \n"
418 + " return \"<?php echo $return; ?>\\n\";\n"
422 + " /* If the tag name is a registered object, we process it. */\n"
423 + " if (preg_match(\'!^\' . $this->_reg_obj_regexp . \'$!\', $tag_command)) {\n"
424 + " return $this->_compile_registered_object_tag($tag_command, $this->_parse_attrs($tag_args), $tag_modifier);\n"
427 + " switch ($tag_command) {\n"
428 + " case \'include\':\n"
429 + " return $this->_compile_include_tag($tag_args);\n"
431 + " case \'include_php\':\n"
432 + " return $this->_compile_include_php_tag($tag_args);\n"
435 + " return $this->_compile_if_tag($tag_args);\n"
437 + " case \'else\':\n"
438 + " return \'<?php else: ?>\';\n"
440 + " case \'elseif\':\n"
441 + " return $this->_compile_if_tag($tag_args, true);\n"
444 + " return \'<?php endif; ?>\';\n"
446 + " case \'capture\':\n"
447 + " return $this->_compile_capture_tag(true, $tag_args);\n"
449 + " case \'/capture\':\n"
450 + " return $this->_compile_capture_tag(false);\n"
452 + " case \'ldelim\':\n"
453 + " return $this->left_delimiter;\n"
455 + " case \'rdelim\':\n"
456 + " return $this->right_delimiter;\n"
458 + " case \'section\':\n"
459 + " array_push($this->_sectionelse_stack, false);\n"
460 + " return $this->_compile_section_start($tag_args);\n"
462 + " case \'sectionelse\':\n"
463 + " $this->_sectionelse_stack[count($this->_sectionelse_stack)-1] = true;\n"
464 + " return \"<?php endfor; else: ?>\";\n"
466 + " case \'/section\':\n"
467 + " if (array_pop($this->_sectionelse_stack))\n"
468 + " return \"<?php endif; ?>\";\n"
470 + " return \"<?php endfor; endif; ?>\";\n"
472 + " case \'foreach\':\n"
473 + " array_push($this->_foreachelse_stack, false);\n"
474 + " return $this->_compile_foreach_start($tag_args);\n"
477 + " case \'foreachelse\':\n"
478 + " $this->_foreachelse_stack[count($this->_foreachelse_stack)-1] = true;\n"
479 + " return \"<?php endforeach; else: ?>\";\n"
481 + " case \'/foreach\':\n"
482 + " if (array_pop($this->_foreachelse_stack))\n"
483 + " return \"<?php endif; ?>\";\n"
485 + " return \"<?php endforeach; endif; ?>\";\n"
487 + " case \'config_load\':\n"
488 + " return $this->_compile_config_load_tag($tag_args);\n"
490 + " case \'strip\':\n"
491 + " case \'/strip\':\n"
492 + " return $this->left_delimiter.$tag_command.$this->right_delimiter;\n"
494 + " case \'literal\':\n"
495 + " list (,$literal_block) = each($this->_literal_blocks);\n"
496 + " $this->_current_line_no += substr_count($literal_block, \"\\n\");\n"
497 + " return \"<?php echo \'\".str_replace(\"\'\", \"\\\'\", str_replace(\"\\\\\", \"\\\\\\\\\", $literal_block)).\"\'; ?>\\n\";\n"
500 + " if ($this->security && !$this->security_settings[\'PHP_TAGS\']) {\n"
501 + " $this->_syntax_error(\"(secure mode) php tags not permitted\", E_USER_WARNING, __FILE__, __LINE__);\n"
504 + " list (,$php_block) = each($this->_php_blocks);\n"
505 + " $this->_current_line_no += substr_count($php_block, \"\\n\");\n"
506 + " return \'<?php \'.$php_block.\' ?>\';\n"
508 + " case \'insert\':\n"
509 + " return $this->_compile_insert_tag($tag_args);\n"
512 + " if ($this->_compile_compiler_tag($tag_command, $tag_args, $output)) {\n"
513 + " return $output;\n"
514 + " } else if ($this->_compile_block_tag($tag_command, $tag_args, $tag_modifier, $output)) {\n"
515 + " return $output;\n"
517 + " return $this->_compile_custom_tag($tag_command, $tag_args, $tag_modifier);\n"
524 + " * compile the custom compiler tag\n"
526 + " * @access public\n"
527 + " * @param $tag_command\n"
528 + " * @param $tag_args\n"
529 + " * @param $output\n"
531 + " function _compile_compiler_tag($tag_command, $tag_args, &$output)\n"
533 + " $found = false;\n"
534 + " $have_function = true;\n"
537 + " * First we check if the compiler function has already been registered\n"
538 + " * or loaded from a plugin file.\n"
540 + " if (isset($this->_plugins[\'compiler\'][$tag_command])) {\n"
541 + " $found = true;\n"
542 + " $plugin_func = $this->_plugins[\'compiler\'][$tag_command][0];\n"
543 + " if (!function_exists($plugin_func)) {\n"
544 + " $message = \"compiler function \'$tag_command\' is not implemented\";\n"
545 + " $have_function = false;\n"
549 + " * Otherwise we need to load plugin file and look for the function\n"
552 + " else if ($plugin_file = $this->_get_plugin_filepath(\'compiler\', $tag_command)) {\n"
553 + " $found = true;\n"
555 + " include_once $plugin_file;\n"
557 + " $plugin_func = \'smarty_compiler_\' . $tag_command;\n"
558 + " if (!function_exists($plugin_func)) {\n"
559 + " $message = \"plugin function $plugin_func() not found in $plugin_file\\n\";\n"
560 + " $have_function = false;\n"
562 + " $this->_plugins[\'compiler\'][$tag_command] = array($plugin_func, null, null);\n"
567 + " * True return value means that we either found a plugin or a\n"
568 + " * dynamically registered function. False means that we didn\'t and the\n"
569 + " * compiler should now emit code to load custom function plugin for this\n"
573 + " if ($have_function) {\n"
574 + " $output = \'<?php \' . $plugin_func($tag_args, $this) . \' ?>\';\n"
576 + " $this->_syntax_error($message, E_USER_WARNING, __FILE__, __LINE__);\n"
586 + " * compile block function tag\n"
588 + " * @access public\n"
589 + " * @param $tag_command\n"
590 + " * @param $tag_args\n"
591 + " * @param $tag_modifier\n"
592 + " * @param $output\n"
594 + " function _compile_block_tag($tag_command, $tag_args, $tag_modifier, &$output)\n"
596 + " if ($tag_command{0} == \'/\') {\n"
597 + " $start_tag = false;\n"
598 + " $tag_command = substr($tag_command, 1);\n"
600 + " $start_tag = true;\n"
602 + " $found = false;\n"
603 + " $have_function = true;\n"
606 + " * First we check if the block function has already been registered\n"
607 + " * or loaded from a plugin file.\n"
609 + " if (isset($this->_plugins[\'block\'][$tag_command])) {\n"
610 + " $found = true;\n"
611 + " $plugin_func = $this->_plugins[\'block\'][$tag_command][0];\n"
612 + " if (!function_exists($plugin_func)) {\n"
613 + " $message = \"block function \'$tag_command\' is not implemented\";\n"
614 + " $have_function = false;\n"
618 + " * Otherwise we need to load plugin file and look for the function\n"
621 + " else if ($plugin_file = $this->_get_plugin_filepath(\'block\', $tag_command)) {\n"
622 + " $found = true;\n"
624 + " include_once $plugin_file;\n"
626 + " $plugin_func = \'smarty_block_\' . $tag_command;\n"
627 + " if (!function_exists($plugin_func)) {\n"
628 + " $message = \"plugin function $plugin_func() not found in $plugin_file\\n\";\n"
629 + " $have_function = false;\n"
631 + " $this->_plugins[\'block\'][$tag_command] = array($plugin_func, null, null);\n"
635 + " if (!$found) {\n"
637 + " } else if (!$have_function) {\n"
638 + " $this->_syntax_error($message, E_USER_WARNING, __FILE__, __LINE__);\n"
643 + " * Even though we\'ve located the plugin function, compilation\n"
644 + " * happens only once, so the plugin will still need to be loaded\n"
645 + " * at runtime for future requests.\n"
647 + " $this->_add_plugin(\'block\', $tag_command);\n"
649 + " if ($start_tag) {\n"
650 + " $arg_list = array();\n"
651 + " $attrs = $this->_parse_attrs($tag_args);\n"
652 + " foreach ($attrs as $arg_name => $arg_value) {\n"
653 + " if (is_bool($arg_value))\n"
654 + " $arg_value = $arg_value ? \'true\' : \'false\';\n"
655 + " $arg_list[] = \"\'$arg_name\' => $arg_value\";\n"
658 + " $output = \"<?php \\$this->_tag_stack[] = array(\'$tag_command\', array(\".implode(\',\', (array)$arg_list).\")); \\$this->_plugins[\'block\'][\'$tag_command\'][0](array(\".implode(\',\', (array)$arg_list).\"), null, \\$this); ob_start(); ?>\";\n"
660 + " $output = \"<?php \\$this->_block_content = ob_get_contents(); ob_end_clean(); \";\n"
661 + " $out_tag_text = \"\\$this->_plugins[\'block\'][\'$tag_command\'][0](\\$this->_tag_stack[count(\\$this->_tag_stack)-1][1], \\$this->_block_content, \\$this)\";\n"
662 + " if($tag_modifier != \'\') {\n"
663 + " $this->_parse_modifiers($out_tag_text, $tag_modifier);\n"
665 + " $output .= \'echo \' . $out_tag_text . \';\';\n"
666 + " $output .= \" array_pop(\\$this->_tag_stack); ?>\";\n"
674 + " * compile custom function tag\n"
676 + " * @access public\n"
677 + " * @param $tag_command\n"
678 + " * @param $tag_args\n"
679 + " * @param $tag_modifier\n"
681 + " function _compile_custom_tag($tag_command, $tag_args, $tag_modifier)\n"
683 + " $this->_add_plugin(\'function\', $tag_command);\n"
685 + " $arg_list = array();\n"
686 + " $attrs = $this->_parse_attrs($tag_args);\n"
687 + " foreach ($attrs as $arg_name => $arg_value) {\n"
688 + " if (is_bool($arg_value))\n"
689 + " $arg_value = $arg_value ? \'true\' : \'false\';\n"
690 + " $arg_list[] = \"\'$arg_name\' => $arg_value\";\n"
693 + " $return = \"\\$this->_plugins[\'function\'][\'$tag_command\'][0](array(\".implode(\',\', (array)$arg_list).\"), \\$this)\";\n"
695 + " if($tag_modifier != \'\') {\n"
696 + " $this->_parse_modifiers($return, $tag_modifier);\n"
699 + " return \'<?php echo \' . $return . \" ; ?>\\n\";\n"
703 + " * compile a registered object tag\n"
705 + " * @access public\n"
706 + " * @param $tag_command\n"
707 + " * @param $attrs\n"
708 + " * @param $tag_modifier\n"
710 + " function _compile_registered_object_tag($tag_command, $attrs, $tag_modifier)\n"
712 + " list($object, $obj_comp) = explode(\'->\', $tag_command);\n"
714 + " $arg_list = array();\n"
715 + " if(count($attrs)) {\n"
716 + " $_assign_var = false;\n"
717 + " foreach ($attrs as $arg_name => $arg_value) {\n"
718 + " if($arg_name == \'assign\') {\n"
719 + " $_assign_var = $arg_value;\n"
720 + " unset($attrs[\'assign\']);\n"
723 + " if (is_bool($arg_value))\n"
724 + " $arg_value = $arg_value ? \'true\' : \'false\';\n"
725 + " $arg_list[] = \"\'$arg_name\' => $arg_value\";\n"
729 + " if(!is_object($this->_reg_objects[$object][0])) {\n"
730 + " $this->_trigger_fatal_error(\"registered \'$object\' is not an object\");\n"
731 + " } elseif(!empty($this->_reg_objects[$object][1]) && !in_array($obj_comp, $this->_reg_objects[$object][1])) {\n"
732 + " $this->_trigger_fatal_error(\"\'$obj_comp\' is not a registered component of object \'$object\'\");\n"
733 + " } elseif(method_exists($this->_reg_objects[$object][0], $obj_comp)) {\n"
735 + " if($this->_reg_objects[$object][2]) {\n"
736 + " // smarty object argument format\n"
737 + " $return = \"\\$this->_reg_objects[\'$object\'][0]->$obj_comp(array(\".implode(\',\', (array)$arg_list).\"), \\$this)\";\n"
739 + " // traditional argument format\n"
740 + " $return = \"\\$this->_reg_objects[\'$object\'][0]->$obj_comp(\".implode(\',\', array_values($attrs)).\")\";\n"
744 + " $return = \"\\$this->_reg_objects[\'$object\'][0]->$obj_comp\";\n"
747 + " if($tag_modifier != \'\') {\n"
748 + " $this->_parse_modifiers($return, $tag_modifier);\n"
751 + " if($_assign_var) {\n"
752 + " return \"<?php \\$this->assign(\'\" . $this->_dequote($_assign_var) .\"\', $return); ?>\\n\";\n"
754 + " return \'<?php echo \' . $return . \"; ?>\\n\";\n"
761 + " * Compile {insert ...} tag\n"
763 + " * @access public\n"
764 + " * @param $tag_args\n"
766 + " function _compile_insert_tag($tag_args)\n"
768 + " $attrs = $this->_parse_attrs($tag_args);\n"
769 + " $name = $this->_dequote($attrs[\'name\']);\n"
771 + " if (empty($name)) {\n"
772 + " $this->_syntax_error(\"missing insert name\", E_USER_ERROR, __FILE__, __LINE__);\n"
775 + " if (!empty($attrs[\'script\'])) {\n"
776 + " $delayed_loading = true;\n"
778 + " $delayed_loading = false; \n"
781 + " foreach ($attrs as $arg_name => $arg_value) {\n"
782 + " if (is_bool($arg_value))\n"
783 + " $arg_value = $arg_value ? \'true\' : \'false\';\n"
784 + " $arg_list[] = \"\'$arg_name\' => $arg_value\";\n"
787 + " $this->_add_plugin(\'insert\', $name, $delayed_loading);\n"
789 + " return \"<?php echo \\$this->_run_insert_handler(array(\".implode(\', \', (array)$arg_list).\")); ?>\\n\";\n"
794 + " * Compile {config_load ...} tag\n"
796 + " * @access public\n"
797 + " * @param $tag_args\n"
799 + " function _compile_config_load_tag($tag_args)\n"
801 + " $attrs = $this->_parse_attrs($tag_args);\n"
803 + " if (empty($attrs[\'file\'])) {\n"
804 + " $this->_syntax_error(\"missing \'file\' attribute in config_load tag\", E_USER_ERROR, __FILE__, __LINE__);\n"
807 + " if (empty($attrs[\'section\'])) {\n"
808 + " $attrs[\'section\'] = \'null\';\n"
811 + " if (isset($attrs[\'scope\'])) {\n"
812 + " $scope = @$this->_dequote($attrs[\'scope\']);\r\n"
813 + " if ($scope != \'local\' &&\r\n"
814 + " $scope != \'parent\' &&\r\n"
815 + " $scope != \'global\') {\r\n"
816 + " $this->_syntax_error(\"invalid \'scope\' attribute value\", E_USER_ERROR, __FILE__, __LINE__);\r\n"
819 + " if (isset($attrs[\'global\']) && $attrs[\'global\'])\r\n"
820 + " $scope = \'parent\';\r\n"
822 + " $scope = \'local\';\r\n"
825 + " return \'<?php $this->config_load(\' . $attrs[\'file\'] . \', \' . $attrs[\'section\'] . \", \'$scope\'); ?>\";\r\n"
830 + " * Compile {include ...} tag\r\n"
832 + " * @access public\r\n"
833 + " * $param $tag_args\r\n"
835 + " function _compile_include_tag($tag_args)\r\n"
837 + " $attrs = $this->_parse_attrs($tag_args);\r\n"
838 + " $arg_list = array();\r\n"
840 + " if (empty($attrs[\'file\'])) {\r\n"
841 + " $this->_syntax_error(\"missing \'file\' attribute in include tag\", E_USER_ERROR, __FILE__, __LINE__);\r\n"
844 + " foreach ($attrs as $arg_name => $arg_value) {\r\n"
845 + " if ($arg_name == \'file\') {\r\n"
846 + " $include_file = $arg_value;\r\n"
848 + " } else if ($arg_name == \'assign\') {\r\n"
849 + " $assign_var = $arg_value;\r\n"
852 + " if (is_bool($arg_value))\r\n"
853 + " $arg_value = $arg_value ? \'true\' : \'false\';\r\n"
854 + " $arg_list[] = \"\'$arg_name\' => $arg_value\";\r\n"
857 + " $output = \'<?php \';\r\n"
859 + " if (isset($assign_var)) {\r\n"
860 + " $output .= \"ob_start();\\n\";\r\n"
864 + " \"\\$_smarty_tpl_vars = \\$this->_tpl_vars;\\n\" .\r\n"
865 + " \"\\$this->_smarty_include(\".$include_file.\", array(\".implode(\',\', (array)$arg_list).\"));\\n\" .\r\n"
866 + " \"\\$this->_tpl_vars = \\$_smarty_tpl_vars;\\n\" .\r\n"
867 + " \"unset(\\$_smarty_tpl_vars);\\n\";\r\n"
869 + " if (isset($assign_var)) {\r\n"
870 + " $output .= \"\\$this->assign(\" . $assign_var . \", ob_get_contents()); ob_end_clean();\\n\";\r\n"
873 + " $output .= \' ?>\';\r\n"
875 + " return $output;\r\n"
880 + " * Compile {include ...} tag\r\n"
882 + " * @access public\r\n"
883 + " * @param $tag_args\r\n"
885 + " function _compile_include_php_tag($tag_args)\r\n"
887 + " $attrs = $this->_parse_attrs($tag_args);\r\n"
889 + " if (empty($attrs[\'file\'])) {\r\n"
890 + " $this->_syntax_error(\"missing \'file\' attribute in include_php tag\", E_USER_ERROR, __FILE__, __LINE__);\r\n"
893 + " $assign_var = $this->_dequote($attrs[\'assign\']);\r\n"
895 + " $once_var = ( $attrs[\'once\'] === false ) ? \'false\' : \'true\';\r\n"
897 + " foreach($attrs as $arg_name => $arg_value) {\r\n"
898 + " if($arg_name != \'file\' AND $arg_name != \'once\' AND $arg_name != \'assign\') {\r\n"
899 + " if(is_bool($arg_value))\r\n"
900 + " $arg_value = $arg_value ? \'true\' : \'false\';\r\n"
901 + " $arg_list[] = \"\'$arg_name\' => $arg_value\";\r\n"
906 + " \"<?php \\$this->_smarty_include_php($attrs[file], \'$assign_var\', $once_var, \" .\r\n"
907 + " \"array(\".implode(\',\', (array)$arg_list).\")); ?>\";\r\n"
909 + " return $output;\r\n"
914 + " * Compile {section ...} tag\r\n"
916 + " * @access public\r\n"
917 + " * @param $tag_args\r\n"
919 + " function _compile_section_start($tag_args)\r\n"
921 + " $attrs = $this->_parse_attrs($tag_args);\r\n"
922 + " $arg_list = array();\r\n"
924 + " $output = \'<?php \';\r\n"
925 + " $section_name = $attrs[\'name\']; \r\n"
926 + " if (empty($section_name)) {\r\n"
927 + " $this->_syntax_error(\"missing section name\", E_USER_ERROR, __FILE__, __LINE__);\r\n"
930 + " $output .= \"if (isset(\\$this->_sections[$section_name])) unset(\\$this->_sections[$section_name]);\\n\";\r\n"
931 + " $section_props = \"\\$this->_sections[$section_name]\";\r\n"
933 + " foreach ($attrs as $attr_name => $attr_value) {\r\n"
934 + " switch ($attr_name) {\r\n"
935 + " case \'loop\':\r\n"
936 + " $output .= \"{$section_props}[\'loop\'] = is_array($attr_value) ? count($attr_value) : max(0, (int)$attr_value);\\n\";\r\n"
939 + " case \'show\':\r\n"
940 + " if (is_bool($attr_value))\r\n"
941 + " $show_attr_value = $attr_value ? \'true\' : \'false\';\r\n"
943 + " $show_attr_value = \"(bool)$attr_value\";\r\n"
944 + " $output .= \"{$section_props}[\'show\'] = $show_attr_value;\\n\";\r\n"
947 + " case \'name\':\r\n"
948 + " $output .= \"{$section_props}[\'$attr_name\'] = $attr_value;\\n\";\r\n"
951 + " case \'max\':\r\n"
952 + " case \'start\':\r\n"
953 + " $output .= \"{$section_props}[\'$attr_name\'] = (int)$attr_value;\\n\";\r\n"
956 + " case \'step\':\r\n"
957 + " $output .= \"{$section_props}[\'$attr_name\'] = ((int)$attr_value) == 0 ? 1 : (int)$attr_value;\\n\";\r\n"
961 + " $this->_syntax_error(\"unknown section attribute - \'$attr_name\'\", E_USER_ERROR, __FILE__, __LINE__);\r\n"
966 + " if (!isset($attrs[\'show\']))\r\n"
967 + " $output .= \"{$section_props}[\'show\'] = true;\\n\";\r\n"
969 + " if (!isset($attrs[\'loop\']))\r\n"
970 + " $output .= \"{$section_props}[\'loop\'] = 1;\\n\";\r\n"
972 + " if (!isset($attrs[\'max\']))\r\n"
973 + " $output .= \"{$section_props}[\'max\'] = {$section_props}[\'loop\'];\\n\";\r\n"
975 + " $output .= \"if ({$section_props}[\'max\'] < 0)\\n\" .\r\n"
976 + " \" {$section_props}[\'max\'] = {$section_props}[\'loop\'];\\n\";\r\n"
978 + " if (!isset($attrs[\'step\']))\r\n"
979 + " $output .= \"{$section_props}[\'step\'] = 1;\\n\";\r\n"
981 + " if (!isset($attrs[\'start\']))\r\n"
982 + " $output .= \"{$section_props}[\'start\'] = {$section_props}[\'step\'] > 0 ? 0 : {$section_props}[\'loop\']-1;\\n\";\r\n"
984 + " $output .= \"if ({$section_props}[\'start\'] < 0)\\n\" .\r\n"
985 + " \" {$section_props}[\'start\'] = max({$section_props}[\'step\'] > 0 ? 0 : -1, {$section_props}[\'loop\'] + {$section_props}[\'start\']);\\n\" .\r\n"
986 + " \"else\\n\" .\r\n"
987 + " \" {$section_props}[\'start\'] = min({$section_props}[\'start\'], {$section_props}[\'step\'] > 0 ? {$section_props}[\'loop\'] : {$section_props}[\'loop\']-1);\\n\";\r\n"
990 + " $output .= \"if ({$section_props}[\'show\']) {\\n\";\r\n"
991 + " if (!isset($attrs[\'start\']) && !isset($attrs[\'step\']) && !isset($attrs[\'max\'])) {\r\n"
992 + " $output .= \" {$section_props}[\'total\'] = {$section_props}[\'loop\'];\\n\";\r\n"
994 + " $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\";\r\n"
996 + " $output .= \" if ({$section_props}[\'total\'] == 0)\\n\" .\r\n"
997 + " \" {$section_props}[\'show\'] = false;\\n\" .\r\n"
998 + " \"} else\\n\" .\r\n"
999 + " \" {$section_props}[\'total\'] = 0;\\n\";\r\n"
1001 + " $output .= \"if ({$section_props}[\'show\']):\\n\";\r\n"
1002 + " $output .= \"\r\n"
1003 + " for ({$section_props}[\'index\'] = {$section_props}[\'start\'], {$section_props}[\'iteration\'] = 1;\r\n"
1004 + " {$section_props}[\'iteration\'] <= {$section_props}[\'total\'];\r\n"
1005 + " {$section_props}[\'index\'] += {$section_props}[\'step\'], {$section_props}[\'iteration\']++):\\n\";\r\n"
1006 + " $output .= \"{$section_props}[\'rownum\'] = {$section_props}[\'iteration\'];\\n\";\r\n"
1007 + " $output .= \"{$section_props}[\'index_prev\'] = {$section_props}[\'index\'] - {$section_props}[\'step\'];\\n\";\r\n"
1008 + " $output .= \"{$section_props}[\'index_next\'] = {$section_props}[\'index\'] + {$section_props}[\'step\'];\\n\";\r\n"
1009 + " $output .= \"{$section_props}[\'first\'] = ({$section_props}[\'iteration\'] == 1);\\n\";\r\n"
1010 + " $output .= \"{$section_props}[\'last\'] = ({$section_props}[\'iteration\'] == {$section_props}[\'total\']);\\n\";\r\n"
1012 + " $output .= \"?>\";\r\n"
1014 + " return $output;\r\n"
1019 + " * Compile {foreach ...} tag.\r\n"
1021 + " * @access public\r\n"
1022 + " * @param $tag_args\r\n"
1024 + " function _compile_foreach_start($tag_args)\r\n"
1026 + " $attrs = $this->_parse_attrs($tag_args);\r\n"
1027 + " $arg_list = array();\r\n"
1029 + " if (empty($attrs[\'from\'])) {\r\n"
1030 + " $this->_syntax_error(\"missing \'from\' attribute\", E_USER_ERROR, __FILE__, __LINE__);\r\n"
1033 + " if (empty($attrs[\'item\'])) {\r\n"
1034 + " $this->_syntax_error(\"missing \'item\' attribute\", E_USER_ERROR, __FILE__, __LINE__);\r\n"
1037 + " $from = $attrs[\'from\'];\r\n"
1038 + " $item = $this->_dequote($attrs[\'item\']);\r\n"
1039 + " if (isset($attrs[\'name\']))\r\n"
1040 + " $name = $attrs[\'name\'];\r\n"
1042 + " $output = \'<?php \';\r\n"
1043 + " if (isset($name)) {\r\n"
1044 + " $output .= \"if (isset(\\$this->_foreach[$name])) unset(\\$this->_foreach[$name]);\\n\";\r\n"
1045 + " $foreach_props = \"\\$this->_foreach[$name]\";\r\n"
1048 + " $key_part = \'\';\r\n"
1050 + " foreach ($attrs as $attr_name => $attr_value) {\r\n"
1051 + " switch ($attr_name) {\r\n"
1052 + " case \'key\':\r\n"
1053 + " $key = $this->_dequote($attrs[\'key\']);\r\n"
1054 + " $key_part = \"\\$this->_tpl_vars[\'$key\'] => \";\r\n"
1057 + " case \'name\':\r\n"
1058 + " $output .= \"{$foreach_props}[\'$attr_name\'] = $attr_value;\\n\";\r\n"
1063 + " if (isset($name)) {\r\n"
1064 + " $output .= \"{$foreach_props}[\'total\'] = count((array)$from);\\n\";\r\n"
1065 + " $output .= \"{$foreach_props}[\'show\'] = {$foreach_props}[\'total\'] > 0;\\n\";\r\n"
1066 + " $output .= \"if ({$foreach_props}[\'show\']):\\n\";\r\n"
1067 + " $output .= \"{$foreach_props}[\'iteration\'] = 0;\\n\";\r\n"
1068 + " $output .= \" foreach ((array)$from as $key_part\\$this->_tpl_vars[\'$item\']):\\n\";\r\n"
1069 + " $output .= \" {$foreach_props}[\'iteration\']++;\\n\";\r\n"
1070 + " $output .= \" {$foreach_props}[\'first\'] = ({$foreach_props}[\'iteration\'] == 1);\\n\";\r\n"
1071 + " $output .= \" {$foreach_props}[\'last\'] = ({$foreach_props}[\'iteration\'] == {$foreach_props}[\'total\']);\\n\";\r\n"
1073 + " $output .= \"if (count((array)$from)):\\n\";\r\n"
1074 + " $output .= \" foreach ((array)$from as $key_part\\$this->_tpl_vars[\'$item\']):\\n\";\r\n"
1076 + " $output .= \'?>\';\r\n"
1078 + " return $output;\r\n"
1083 + " * Compile {capture} .. {/capture} tags\r\n"
1085 + " * @access public\r\n"
1086 + " * @param $start\r\n"
1087 + " * @param $tag_args\r\n"
1089 + " function _compile_capture_tag($start, $tag_args = \'\')\r\n"
1091 + " $attrs = $this->_parse_attrs($tag_args);\r\n"
1093 + " if ($start) {\r\n"
1094 + " if (isset($attrs[\'name\']))\r\n"
1095 + " $buffer = $attrs[\'name\'];\r\n"
1097 + " $buffer = \"\'default\'\";\r\n"
1099 + " $output = \"<?php ob_start(); ?>\";\r\n"
1100 + " $this->_capture_stack[] = $buffer;\r\n"
1102 + " $buffer = array_pop($this->_capture_stack);\r\n"
1103 + " $output = \"<?php \\$this->_smarty_vars[\'capture\'][$buffer] = ob_get_contents(); ob_end_clean(); ?>\";\r\n"
1106 + " return $output;\r\n"
1110 + " * Compile {if ...} tag\r\n"
1112 + " * @access public\r\n"
1113 + " * @param $tag_args\r\n"
1114 + " * @param $elseif\r\n"
1116 + " function _compile_if_tag($tag_args, $elseif = false)\r\n"
1119 + " /* Tokenize args for \'if\' tag. */\r\n"
1120 + " preg_match_all(\'/(?>\r\n"
1121 + " \' . $this->_obj_call_regexp . \'(?:\' . $this->_mod_regexp . \'*) | # valid object call\r\n"
1122 + " \' . $this->_var_regexp . \'(?:\' . $this->_mod_regexp . \'*) | # public or quoted string\r\n"
1123 + " \\-?\\d+|!==|<=>|==|!=|<=|>=|\\&\\&|\\|\\||\\(|\\)|,|\\!|\\^|=|<|>|\\||\\%|\\+|\\-|\\/|\\* | # valid non-word token\r\n"
1124 + " \\b\\w+\\b | # valid word token\r\n"
1125 + " \\S+ # anything else\r\n"
1126 + " )/x\', $tag_args, $match);\r\n"
1128 + " $tokens = $match[0];\r\n"
1130 + " // make sure we have balanced parenthesis\r\n"
1131 + " $token_count = array_count_values($tokens);\r\n"
1132 + " if(isset($token_count[\'(\']) && $token_count[\'(\'] != $token_count[\')\']) {\r\n"
1133 + " $this->_syntax_error(\"unbalanced parenthesis in if statement\", E_USER_ERROR, __FILE__, __LINE__);\r\n"
1136 + " $is_arg_stack = array();\r\n"
1138 + " for ($i = 0; $i < count($tokens); $i++) {\r\n"
1140 + " $token = &$tokens[$i];\r\n"
1142 + " switch (strtolower($token)) {\r\n"
1143 + " case \'!\':\r\n"
1144 + " case \'%\':\r\n"
1145 + " case \'!==\':\r\n"
1146 + " case \'==\':\r\n"
1147 + " case \'>\':\r\n"
1148 + " case \'<\':\r\n"
1149 + " case \'!=\':\r\n"
1150 + " case \'<=\':\r\n"
1151 + " case \'>=\':\r\n"
1152 + " case \'&&\':\r\n"
1153 + " case \'||\':\r\n"
1154 + " case \'|\':\r\n"
1155 + " case \'^\':\r\n"
1156 + " case \'&\':\r\n"
1157 + " case \'~\':\r\n"
1158 + " case \')\':\r\n"
1159 + " case \',\':\r\n"
1160 + " case \'+\':\r\n"
1161 + " case \'-\':\r\n"
1162 + " case \'*\':\r\n"
1163 + " case \'/\':\r\n"
1166 + " case \'eq\':\r\n"
1167 + " $token = \'==\';\r\n"
1170 + " case \'ne\':\r\n"
1171 + " case \'neq\':\r\n"
1172 + " $token = \'!=\';\r\n"
1175 + " case \'lt\':\r\n"
1176 + " $token = \'<\';\r\n"
1179 + " case \'le\':\r\n"
1180 + " case \'lte\':\r\n"
1181 + " $token = \'<=\';\r\n"
1184 + " case \'gt\':\r\n"
1185 + " $token = \'>\';\r\n"
1188 + " case \'ge\':\r\n"
1189 + " case \'gte\':\r\n"
1190 + " $token = \'>=\';\r\n"
1193 + " case \'and\':\r\n"
1194 + " $token = \'&&\';\r\n"
1197 + " case \'or\':\r\n"
1198 + " $token = \'||\';\r\n"
1201 + " case \'not\':\r\n"
1202 + " $token = \'!\';\r\n"
1205 + " case \'mod\':\r\n"
1206 + " $token = \'%\';\r\n"
1209 + " case \'(\':\r\n"
1210 + " array_push($is_arg_stack, $i);\r\n"
1213 + " case \'is\':\r\n"
1214 + " /* If last token was a \')\', we operate on the parenthesized\r\n"
1215 + " expression. The start of the expression is on the stack.\r\n"
1216 + " Otherwise, we operate on the last encountered token. */\r\n"
1217 + " if ($tokens[$i-1] == \')\')\r\n"
1218 + " $is_arg_start = array_pop($is_arg_stack);\r\n"
1220 + " $is_arg_start = $i-1;\r\n"
1221 + " /* Construct the argument for \'is\' expression, so it knows\r\n"
1222 + " what to operate on. */\r\n"
1223 + " $is_arg = implode(\' \', array_slice($tokens, $is_arg_start, $i - $is_arg_start));\r\n"
1225 + " /* Pass all tokens from next one until the end to the\r\n"
1226 + " \'is\' expression parsing function. The function will\r\n"
1227 + " return modified tokens, where the first one is the result\r\n"
1228 + " of the \'is\' expression and the rest are the tokens it\r\n"
1229 + " didn\'t touch. */ \r\n"
1230 + " $new_tokens = $this->_parse_is_expr($is_arg, array_slice($tokens, $i+1));\r\n"
1232 + " /* Replace the old tokens with the new ones. */\r\n"
1233 + " array_splice($tokens, $is_arg_start, count($tokens), $new_tokens);\r\n"
1235 + " /* Adjust argument start so that it won\'t change from the\r\n"
1236 + " current position for the next iteration. */\r\n"
1237 + " $i = $is_arg_start;\r\n"
1241 + " if(preg_match(\'!^\' . $this->_func_regexp . \'$!\', $token) ) {\r\n"
1242 + " // function call \r\n"
1243 + " if($this->security &&\r\n"
1244 + " !in_array($token, $this->security_settings[\'IF_FUNCS\'])) {\r\n"
1245 + " $this->_syntax_error(\"(secure mode) \'$token\' not allowed in if statement\", E_USER_ERROR, __FILE__, __LINE__);\r\n"
1247 + " } elseif(preg_match(\'!^\' . $this->_var_regexp . \'(?:\' . $this->_mod_regexp . \'*)$!\', $token)) {\r\n"
1248 + " // variable\r\n"
1249 + " $token = $this->_parse_var_props($token);\r\n"
1250 + " } elseif(preg_match(\'!^\' . $this->_obj_call_regexp . \'(?:\' . $this->_mod_regexp . \'*)$!\', $token)) {\r\n"
1252 + " $token = $this->_parse_var_props($token);\r\n"
1253 + " } elseif(is_numeric($token)) {\r\n"
1254 + " // number, skip it\r\n"
1256 + " $this->_syntax_error(\"unidentified token \'$token\'\", E_USER_ERROR, __FILE__, __LINE__);\r\n"
1262 + " if ($elseif)\r\n"
1263 + " return \'<?php elseif (\'.implode(\' \', $tokens).\'): ?>\';\r\n"
1265 + " return \'<?php if (\'.implode(\' \', $tokens).\'): ?>\';\r\n"
1270 + " * Parse is expression\r\n"
1272 + " * @access public\r\n"
1273 + " * @param $is_arg\r\n"
1274 + " * @param $tokens\r\n"
1276 + " function _parse_is_expr($is_arg, $tokens)\r\n"
1278 + " $expr_end = 0;\r\n"
1279 + " $negate_expr = false;\r\n"
1281 + " if (($first_token = array_shift($tokens)) == \'not\') {\r\n"
1282 + " $negate_expr = true;\r\n"
1283 + " $expr_type = array_shift($tokens);\r\n"
1285 + " $expr_type = $first_token;\r\n"
1287 + " switch ($expr_type) {\r\n"
1288 + " case \'even\':\r\n"
1289 + " if (@$tokens[$expr_end] == \'by\') {\r\n"
1290 + " $expr_end++;\r\n"
1291 + " $expr_arg = $tokens[$expr_end++];\r\n"
1292 + " $expr = \"!(($is_arg / $expr_arg) % \" . $this->_parse_var_props($expr_arg) . \")\";\r\n"
1294 + " $expr = \"!($is_arg % 2)\";\r\n"
1297 + " case \'odd\':\r\n"
1298 + " if (@$tokens[$expr_end] == \'by\') {\r\n"
1299 + " $expr_end++;\r\n"
1300 + " $expr_arg = $tokens[$expr_end++];\r\n"
1301 + " $expr = \"(($is_arg / $expr_arg) % \". $this->_parse_var_props($expr_arg) . \")\";\r\n"
1303 + " $expr = \"($is_arg % 2)\";\r\n"
1306 + " case \'div\':\r\n"
1307 + " if (@$tokens[$expr_end] == \'by\') {\r\n"
1308 + " $expr_end++;\r\n"
1309 + " $expr_arg = $tokens[$expr_end++];\r\n"
1310 + " $expr = \"!($is_arg % \" . $this->_parse_var_props($expr_arg) . \")\";\r\n"
1312 + " $this->_syntax_error(\"expecting \'by\' after \'div\'\", E_USER_ERROR, __FILE__, __LINE__);\r\n"
1317 + " $this->_syntax_error(\"unknown \'is\' expression - \'$expr_type\'\", E_USER_ERROR, __FILE__, __LINE__);\r\n"
1321 + " if ($negate_expr) {\r\n"
1322 + " $expr = \"!($expr)\";\r\n"
1325 + " array_splice($tokens, 0, $expr_end, $expr); \r\n"
1327 + " return $tokens;\r\n"
1332 + " * Parse attribute string\r\n"
1334 + " * @access public\r\n"
1335 + " * @param $tag_args\r\n"
1336 + " * @param $quote\r\n"
1338 + " function _parse_attrs($tag_args, $quote = true)\r\n"
1341 + " /* Tokenize tag attributes. */\r\n"
1342 + " preg_match_all(\'/(?:\' . $this->_obj_call_regexp . \'|\' . $this->_qstr_regexp . \' | (?>[^\"\\\'=\\s]+)\r\n"
1345 + " /x\', $tag_args, $match);\r\n"
1346 + " $tokens = $match[0]; \r\n"
1348 + " $attrs = array();\r\n"
1349 + " /* Parse state:\r\n"
1350 + " 0 - expecting attribute name\r\n"
1351 + " 1 - expecting \'=\'\r\n"
1352 + " 2 - expecting attribute value (not \'=\') */\r\n"
1353 + " $state = 0;\r\n"
1355 + " foreach ($tokens as $token) {\r\n"
1356 + " switch ($state) {\r\n"
1358 + " /* If the token is a valid identifier, we set attribute name\r\n"
1359 + " and go to state 1. */\r\n"
1360 + " if (preg_match(\'!^\\w+$!\', $token)) {\r\n"
1361 + " $attr_name = $token;\r\n"
1362 + " $state = 1;\r\n"
1364 + " $this->_syntax_error(\"invalid attribute name - \'$token\'\", E_USER_ERROR, __FILE__, __LINE__);\r\n"
1368 + " /* If the token is \'=\', then we go to state 2. */\r\n"
1369 + " if ($token == \'=\') {\r\n"
1370 + " $state = 2;\r\n"
1372 + " $this->_syntax_error(\"expecting \'=\' after attribute name \'$last_token\'\", E_USER_ERROR, __FILE__, __LINE__);\r\n"
1376 + " /* If token is not \'=\', we set the attribute value and go to\r\n"
1377 + " state 0. */\r\n"
1378 + " if ($token != \'=\') {\r\n"
1379 + " /* We booleanize the token if it\'s a non-quoted possible\r\n"
1380 + " boolean value. */\r\n"
1381 + " if (preg_match(\'!^(on|yes|true)$!\', $token))\r\n"
1382 + " $token = true;\r\n"
1383 + " else if (preg_match(\'!^(off|no|false)$!\', $token))\r\n"
1384 + " $token = false;\r\n"
1385 + " /* If the token is just a string,\r\n"
1386 + " we double-quote it. */\r\n"
1387 + " else if (preg_match(\'!^\\w+$!\', $token)) {\r\n"
1388 + " $token = \'\"\'.$token.\'\"\';\r\n"
1391 + " $attrs[$attr_name] = $token;\r\n"
1392 + " $state = 0;\r\n"
1394 + " $this->_syntax_error(\"\'=\' cannot be an attribute value\", E_USER_ERROR, __FILE__, __LINE__);\r\n"
1397 + " $last_token = $token;\r\n"
1400 + " if($state != 0) {\r\n"
1401 + " if($state == 1) {\r\n"
1402 + " $this->_syntax_error(\"expecting \'=\' after attribute name \'$last_token\'\", E_USER_ERROR, __FILE__, __LINE__); \r\n"
1404 + " $this->_syntax_error(\"missing attribute value\", E_USER_ERROR, __FILE__, __LINE__); \r\n"
1408 + " $this->_parse_vars_props($attrs);\r\n"
1410 + " return $attrs;\r\n"
1414 + " * compile multiple variables and section properties tokens into\r\n"
1417 + " * @access public\r\n"
1418 + " * @param $tokens\r\n"
1420 + " function _parse_vars_props(&$tokens)\r\n"
1422 + " foreach($tokens as $key => $val) { \r\n"
1423 + " $tokens[$key] = $this->_parse_var_props($val);\r\n"
1428 + " * compile single variable and section properties token into\r\n"
1431 + " * @access public\r\n"
1432 + " * @param $val\r\n"
1433 + " * @param $tag_attrs\r\n"
1435 + " function _parse_var_props($val, $tag_attrs = null)\r\n"
1438 + " $val = trim($val);\r\n"
1440 + " if(preg_match(\'!^(\' . $this->_obj_call_regexp . \'|\' . $this->_dvar_regexp . \')(?:\' . $this->_mod_regexp . \'*)$!\', $val)) {\r\n"
1441 + " // $ variable or object\r\n"
1442 + " return $this->_parse_var($val, $tag_attrs);\r\n"
1444 + " elseif(preg_match(\'!^\' . $this->_db_qstr_regexp . \'(?:\' . $this->_mod_regexp . \'*)$!\', $val)) {\r\n"
1445 + " // double quoted text\r\n"
1446 + " preg_match(\'!^(\' . $this->_db_qstr_regexp . \')(\'. $this->_mod_regexp . \'*)$!\', $val, $match);\r\n"
1447 + " $return = $this->_expand_quoted_text($match[1]);\r\n"
1448 + " if($match[2] != \'\') {\r\n"
1449 + " $this->_parse_modifiers($return, $match[2]);\r\n"
1451 + " return $return;\r\n"
1453 + " elseif(preg_match(\'!^\' . $this->_si_qstr_regexp . \'(?:\' . $this->_mod_regexp . \'*)$!\', $val)) {\r\n"
1454 + " // single quoted text\r\n"
1455 + " preg_match(\'!^(\' . $this->_si_qstr_regexp . \')(\'. $this->_mod_regexp . \'*)$!\', $val, $match);\r\n"
1456 + " if($match[2] != \'\') {\r\n"
1457 + " $this->_parse_modifiers($match[1], $match[2]);\r\n"
1458 + " return $match[1];\r\n"
1461 + " elseif(preg_match(\'!^\' . $this->_cvar_regexp . \'(?:\' . $this->_mod_regexp . \'*)$!\', $val)) {\r\n"
1462 + " // config var\r\n"
1463 + " return $this->_parse_conf_var($val);\r\n"
1465 + " elseif(preg_match(\'!^\' . $this->_svar_regexp . \'(?:\' . $this->_mod_regexp . \'*)$!\', $val)) {\r\n"
1466 + " // section var\r\n"
1467 + " return $this->_parse_section_prop($val);\r\n"
1469 + " elseif(!in_array($val, $this->_permitted_tokens) && !is_numeric($val)) {\r\n"
1470 + " // literal string\r\n"
1471 + " return $this->_expand_quoted_text(\'\"\' . $val .\'\"\');\r\n"
1473 + " return $val;\r\n"
1477 + " * expand quoted text with embedded variables\r\n"
1479 + " * @access public\r\n"
1480 + " * @param $var_expr\r\n"
1482 + " function _expand_quoted_text($var_expr)\r\n"
1484 + " // if contains unescaped $, expand it\r\n"
1485 + " if(preg_match_all(\'|(?<!\\\\\\\\)\\$\' . $this->_dvar_guts_regexp . \'|\', $var_expr, $match)) {\r\n"
1486 + " rsort($match[0]);\r\n"
1487 + " reset($match[0]);\r\n"
1488 + " foreach($match[0] as $var) {\r\n"
1489 + " $var_expr = str_replace ($var, \'\".\' . $this->_parse_var($var) . \'.\"\', $var_expr);\r\n"
1491 + " return preg_replace(\'!\\.\"\"|\"\"\\.!\', \'\', $var_expr);\r\n"
1493 + " return $var_expr;\r\n"
1498 + " * parse variable expression into PHP code\r\n"
1500 + " * @access public\r\n"
1501 + " * @param $var_expr\r\n"
1503 + " function _parse_var($var_expr)\r\n"
1506 + " preg_match(\'!(\' . $this->_obj_call_regexp . \'|\' . $this->_var_regexp . \')(\' . $this->_mod_regexp . \'*)$!\', $var_expr, $match);\r\n"
1508 + " $var_ref = substr($match[1],1);\r\n"
1509 + " $modifiers = $match[2];\r\n"
1511 + " if(!empty($this->default_modifiers) && !preg_match(\'!(^|\\|)smarty:nodefaults($|\\|)!\',$modifiers)) {\r\n"
1512 + " $_default_mod_string = implode(\'|\',(array)$this->default_modifiers);\r\n"
1513 + " $modifiers = empty($modifiers) ? $_default_mod_string : $_default_mod_string . \'|\' . $modifiers;\r\n"
1516 + " // get [foo] and .foo and ->foo() pieces \r\n"
1517 + " preg_match_all(\'!(?:^\\w+)|(?:\' . $this->_obj_ext_regexp . \')+(?:\' . $this->_obj_params_regexp . \')?|(?:\' . $this->_var_bracket_regexp . \')|\\.\\$?\\w+!\', $var_ref, $match); \r\n"
1519 + " $indexes = $match[0];\r\n"
1520 + " $var_name = array_shift($indexes);\r\n"
1522 + " /* Handle $smarty.* variable references as a special case. */\r\n"
1523 + " if ($var_name == \'smarty\') {\r\n"
1525 + " * If the reference could be compiled, use the compiled output;\r\n"
1526 + " * otherwise, fall back on the $smarty variable generated at\r\n"
1527 + " * run-time.\r\n"
1529 + " if (($smarty_ref = $this->_compile_smarty_ref($indexes)) !== null) {\r\n"
1530 + " $output = $smarty_ref;\r\n"
1532 + " $var_name = substr(array_shift($indexes), 1);\r\n"
1533 + " $output = \"\\$this->_smarty_vars[\'$var_name\']\";\r\n"
1536 + " $output = \"\\$this->_tpl_vars[\'$var_name\']\";\r\n"
1539 + " foreach ($indexes as $index) { \r\n"
1540 + " if ($index{0} == \'[\') {\r\n"
1541 + " $index = substr($index, 1, -1);\r\n"
1542 + " if (is_numeric($index)) {\r\n"
1543 + " $output .= \"[$index]\";\r\n"
1544 + " } elseif ($index{0} == \'$\') {\r\n"
1545 + " $output .= \"[\\$this->_tpl_vars[\'\" . substr($index, 1) . \"\']]\";\r\n"
1547 + " $parts = explode(\'.\', $index);\r\n"
1548 + " $section = $parts[0];\r\n"
1549 + " $section_prop = isset($parts[1]) ? $parts[1] : \'index\';\r\n"
1550 + " $output .= \"[\\$this->_sections[\'$section\'][\'$section_prop\']]\";\r\n"
1552 + " } else if ($index{0} == \'.\') {\r\n"
1553 + " if ($index{1} == \'$\')\r\n"
1554 + " $output .= \"[\\$this->_tpl_vars[\'\" . substr($index, 2) . \"\']]\";\r\n"
1556 + " $output .= \"[\'\" . substr($index, 1) . \"\']\";\r\n"
1557 + " } else if (substr($index,0,2) == \'->\') {\r\n"
1558 + " if(substr($index,2,2) == \'__\') {\r\n"
1559 + " $this->_syntax_error(\'call to internal object members is not allowed\', E_USER_ERROR, __FILE__, __LINE__);\r\n"
1560 + " } elseif($this->security && substr($index,2,1) == \'_\') {\r\n"
1561 + " $this->_syntax_error(\'(secure) call to private object member is not allowed\', E_USER_ERROR, __FILE__, __LINE__);\r\n"
1563 + " if(preg_match(\'!((?:\' . $this->_obj_ext_regexp . \')+)(\' . $this->_obj_params_regexp . \')?!\', $index, $match)) {\r\n"
1564 + " if(!empty($match[2])) {\r\n"
1565 + " // parse object parameters\r\n"
1566 + " $index = str_replace($match[2], $this->_parse_parenth_args($match[2]), $index);\r\n"
1568 + " if(preg_match_all(\'!\' . $this->_dvar_regexp . \'!\', $match[1], $_dvar_match)) {\r\n"
1569 + " // parse embedded variables\r\n"
1570 + " $_match_replace = $match[1];\r\n"
1571 + " foreach($_dvar_match[0] as $_curr_var) {\r\n"
1572 + " $_match_replace = str_replace($_curr_var, \'{\' . $this->_parse_var($_curr_var) . \'}\', $_match_replace);\r\n"
1574 + " $index = str_replace($match[1], $_match_replace, $index);\r\n"
1577 + " $output .= $index;\r\n"
1580 + " $output .= $index;\r\n"
1584 + " // look for variables imbedded in quoted strings, replace them\r\n"
1585 + " if(preg_match(\'!\' . $this->_qstr_regexp . \'!\', $output, $match)) {\r\n"
1586 + " $output = str_replace($match[0], $this->_expand_quoted_text($match[0]), $output);\r\n"
1589 + " $this->_parse_modifiers($output, $modifiers);\r\n"
1591 + " return $output;\r\n"
1595 + " * parse arguments in function call parenthesis\r\n"
1597 + " * @access public\r\n"
1598 + " * @param $parenth_args\r\n"
1600 + " function _parse_parenth_args($parenth_args)\r\n"
1602 + " preg_match_all(\'!\' . $this->_param_regexp . \'!\',$parenth_args, $match);\r\n"
1603 + " $match = $match[0];\r\n"
1604 + " rsort($match);\r\n"
1605 + " reset($match); \r\n"
1606 + " $orig_vals = $match;\r\n"
1607 + " $this->_parse_vars_props($match);\r\n"
1608 + " return str_replace($orig_vals, $match, $parenth_args);\r\n"
1612 + " * parse configuration variable expression into PHP code\r\n"
1614 + " * @access public\r\n"
1615 + " * @param $conf_var_expr\r\n"
1617 + " function _parse_conf_var($conf_var_expr)\r\n"
1619 + " $parts = explode(\'|\', $conf_var_expr, 2);\r\n"
1620 + " $var_ref = $parts[0];\r\n"
1621 + " $modifiers = isset($parts[1]) ? $parts[1] : \'\';\r\n"
1623 + " $var_name = substr($var_ref, 1, -1);\r\n"
1625 + " $output = \"\\$this->_config[0][\'vars\'][\'$var_name\']\";\r\n"
1627 + " $this->_parse_modifiers($output, $modifiers);\r\n"
1629 + " return $output;\r\n"
1634 + " * parse section property expression into PHP code\r\n"
1636 + " * @access public\r\n"
1637 + " * @param $section_prop_expr\r\n"
1639 + " function _parse_section_prop($section_prop_expr)\r\n"
1641 + " $parts = explode(\'|\', $section_prop_expr, 2);\r\n"
1642 + " $var_ref = $parts[0];\r\n"
1643 + " $modifiers = isset($parts[1]) ? $parts[1] : \'\';\r\n"
1645 + " preg_match(\'!%(\\w+)\\.(\\w+)%!\', $var_ref, $match);\r\n"
1646 + " $section_name = $match[1];\r\n"
1647 + " $prop_name = $match[2];\r\n"
1649 + " $output = \"\\$this->_sections[\'$section_name\'][\'$prop_name\']\";\r\n"
1651 + " $this->_parse_modifiers($output, $modifiers);\r\n"
1653 + " return $output;\r\n"
1658 + " * parse modifier chain into PHP code\r\n"
1660 + " * @access public\r\n"
1661 + " * @param $output\r\n"
1662 + " * @param $modifier_string\r\n"
1664 + " function _parse_modifiers(&$output, $modifier_string)\r\n"
1666 + " preg_match_all(\'!\\|(@?\\w+)((?>:(?:\'. $this->_qstr_regexp . \'|[^|]+))*)!\', \'|\' . $modifier_string, $match);\r\n"
1667 + " list(, $modifiers, $modifier_arg_strings) = $match;\r\n"
1669 + " for ($i = 0, $for_max = count($modifiers); $i < $for_max; $i++) {\r\n"
1670 + " $modifier_name = $modifiers[$i];\r\n"
1672 + " if($modifier_name == \'smarty\') {\r\n"
1673 + " // skip smarty modifier\r\n"
1677 + " preg_match_all(\'!:(\' . $this->_qstr_regexp . \'|[^:]+)!\', $modifier_arg_strings[$i], $match);\r\n"
1678 + " $modifier_args = $match[1];\r\n"
1680 + " if ($modifier_name{0} == \'@\') {\r\n"
1681 + " $map_array = \'false\';\r\n"
1682 + " $modifier_name = substr($modifier_name, 1);\r\n"
1684 + " $map_array = \'true\';\r\n"
1687 + " $this->_add_plugin(\'modifier\', $modifier_name);\r\n"
1689 + " $this->_parse_vars_props($modifier_args);\r\n"
1691 + " if (count($modifier_args) > 0)\r\n"
1692 + " $modifier_args = \', \'.implode(\', \', $modifier_args);\r\n"
1694 + " $modifier_args = \'\';\r\n"
1696 + " $output = \"\\$this->_run_mod_handler(\'$modifier_name\', $map_array, $output$modifier_args)\";\r\n"
1702 + " * add plugin\r\n"
1704 + " * @access public\r\n"
1705 + " * @param $type\r\n"
1706 + " * @param $name\r\n"
1707 + " * @param $delayed_loading\r\n"
1709 + " function _add_plugin($type, $name, $delayed_loading = null)\r\n"
1711 + " if (!isset($this->_plugin_info[$type])) {\r\n"
1712 + " $this->_plugin_info[$type] = array();\r\n"
1714 + " if (!isset($this->_plugin_info[$type][$name])) {\r\n"
1715 + " $this->_plugin_info[$type][$name] = array($this->_current_file,\r\n"
1716 + " $this->_current_line_no,\r\n"
1717 + " $delayed_loading);\r\n"
1723 + " * Compiles references of type $smarty.foo\r\n"
1725 + " * @access public\r\n"
1726 + " * @param $indexes\r\n"
1728 + " function _compile_smarty_ref(&$indexes)\r\n"
1730 + " /* Extract the reference name. */\r\n"
1731 + " $ref = substr($indexes[0], 1);\r\n"
1733 + " switch ($ref) {\r\n"
1734 + " case \'now\':\r\n"
1735 + " $compiled_ref = \'time()\';\r\n"
1736 + " if (count($indexes) > 1) {\r\n"
1737 + " $this->_syntax_error(\'$smarty\' . implode(\'\', $indexes) .\' is an invalid reference\', E_USER_ERROR, __FILE__, __LINE__);\r\n"
1741 + " case \'foreach\':\r\n"
1742 + " case \'section\':\r\n"
1743 + " if ($indexes[1]{0} != \'.\') {\r\n"
1744 + " $this->_syntax_error(\'$smarty\' . implode(\'\', array_slice($indexes, 0, 2)) . \' is an invalid reference\', E_USER_ERROR, __FILE__, __LINE__);\r\n"
1746 + " $name = substr($indexes[1], 1);\r\n"
1747 + " array_shift($indexes);\r\n"
1748 + " if ($ref == \'foreach\')\r\n"
1749 + " $compiled_ref = \"\\$this->_foreach[\'$name\']\";\r\n"
1751 + " $compiled_ref = \"\\$this->_sections[\'$name\']\";\r\n"
1754 + " case \'get\':\r\n"
1755 + " array_shift($indexes);\r\n"
1756 + " $compiled_ref = \"\\$_GET\";\r\n"
1757 + " if ($name = substr($indexes[0], 1))\r\n"
1758 + " $compiled_ref .= \"[\'$name\']\";\r\n"
1761 + " case \'post\':\r\n"
1762 + " array_shift($indexes);\r\n"
1763 + " $name = substr($indexes[0], 1);\r\n"
1764 + " $compiled_ref = \"\\$_POST\";\r\n"
1765 + " if ($name = substr($indexes[0], 1))\r\n"
1766 + " $compiled_ref .= \"[\'$name\']\";\r\n"
1769 + " case \'cookies\':\r\n"
1770 + " array_shift($indexes);\r\n"
1771 + " $name = substr($indexes[0], 1);\r\n"
1772 + " $compiled_ref = \"\\$_COOKIE\";\r\n"
1773 + " if ($name = substr($indexes[0], 1))\r\n"
1774 + " $compiled_ref .= \"[\'$name\']\";\r\n"
1777 + " case \'env\':\r\n"
1778 + " array_shift($indexes);\r\n"
1779 + " $compiled_ref = \"\\$_ENV\";\r\n"
1780 + " if ($name = substr($indexes[0], 1))\r\n"
1781 + " $compiled_ref .= \"[\'$name\']\";\r\n"
1784 + " case \'server\':\r\n"
1785 + " array_shift($indexes);\r\n"
1786 + " $name = substr($indexes[0], 1);\r\n"
1787 + " $compiled_ref = \"\\$_SERVER\";\r\n"
1788 + " if ($name = substr($indexes[0], 1))\r\n"
1789 + " $compiled_ref .= \"[\'$name\']\";\r\n"
1792 + " case \'session\':\r\n"
1793 + " array_shift($indexes);\r\n"
1794 + " $name = substr($indexes[0], 1);\r\n"
1795 + " $compiled_ref = \"\\$_SESSION\";\r\n"
1796 + " if ($name = substr($indexes[0], 1))\r\n"
1797 + " $compiled_ref .= \"[\'$name\']\";\r\n"
1801 + " * These cases are handled either at run-time or elsewhere in the\r\n"
1802 + " * compiler.\r\n"
1804 + " case \'request\':\r\n"
1805 + " $this->_init_smarty_vars = true;\r\n"
1806 + " return null;\r\n"
1808 + " case \'capture\':\r\n"
1809 + " return null;\r\n"
1811 + " case \'template\':\r\n"
1812 + " $compiled_ref = \"\'$this->_current_file\'\";\r\n"
1813 + " if (count($indexes) > 1) {\r\n"
1814 + " $this->_syntax_error(\'$smarty\' . implode(\'\', $indexes) .\' is an invalid reference\', E_USER_ERROR, __FILE__, __LINE__);\r\n"
1818 + " case \'version\':\r\n"
1819 + " $compiled_ref = \"\'$this->_version\'\";\r\n"
1822 + " case \'const\':\r\n"
1823 + " array_shift($indexes);\r\n"
1824 + " $compiled_ref = \'defined(\\\'\' . substr($indexes[0],1) . \'\\\') ? \' . substr($indexes[0],1) . \' : null\';\r\n"
1828 + " $this->_syntax_error(\'$smarty.\' . $ref . \' is an unknown reference\', E_USER_ERROR, __FILE__, __LINE__);\r\n"
1832 + " array_shift($indexes);\r\n"
1833 + " return $compiled_ref;\r\n"
1838 + " * load pre- and post-filters\r\n"
1840 + " * @access public\r\n"
1842 + " function _load_filters()\r\n"
1844 + " if (count($this->_plugins[\'prefilter\']) > 0) {\r\n"
1845 + " foreach ($this->_plugins[\'prefilter\'] as $filter_name => $prefilter) {\r\n"
1846 + " if ($prefilter === false) {\r\n"
1847 + " unset($this->_plugins[\'prefilter\'][$filter_name]);\r\n"
1848 + " $this->_load_plugins(array(array(\'prefilter\', $filter_name, null, null, false)));\r\n"
1852 + " if (count($this->_plugins[\'postfilter\']) > 0) {\r\n"
1853 + " foreach ($this->_plugins[\'postfilter\'] as $filter_name => $postfilter) {\r\n"
1854 + " if ($postfilter === false) {\r\n"
1855 + " unset($this->_plugins[\'postfilter\'][$filter_name]);\r\n"
1856 + " $this->_load_plugins(array(array(\'postfilter\', $filter_name, null, null, false)));\r\n"
1864 + " * display Smarty syntax error\r\n"
1866 + " * @access public\r\n"
1867 + " * @param $error_msg\r\n"
1868 + " * @param $error_type\r\n"
1869 + " * @param $file\r\n"
1870 + " * @param $line\r\n"
1872 + " function _syntax_error($error_msg, $error_type = E_USER_ERROR, $file=null, $line=null)\r\n"
1874 + " if(isset($file) && isset($line)) {\r\n"
1875 + " $info = \' (\'.basename($file).\", line $line)\";\r\n"
1877 + " $info = null;\r\n"
1879 + " trigger_error(\'Smarty: [in \' . $this->_current_file . \' line \' .\r\n"
1880 + " $this->_current_line_no . \"]: syntax error: $error_msg$info\", $error_type);\r\n"
1881 + " }\r\n" + "}\r\n" + "\r\n" + "/**\r\n"
1882 + " * compare to values by their string length\r\n" + " *\r\n"
1883 + " * @access private\r\n" + " * @param $a\r\n"
1884 + " * @param $b\r\n" + " */\r\n"
1885 + "function _smarty_sort_length($a, $b)\r\n" + "{\r\n"
1886 + " if($a == $b)\r\n" + " return 0;\r\n" + "\r\n"
1887 + " if(strlen($a) == strlen($b))\r\n"
1888 + " return ($a > $b) ? -1 : 1;\r\n" + "\r\n"
1889 + " return (strlen($a) > strlen($b)) ? -1 : 1;\r\n" + "}\r\n"
1890 + "\r\n" + "\r\n" + "/* vim: set et: */\r\n" + "\r\n"