1 package net.sourceforge.phpeclipse.tests.parser;
2 /*******************************************************************************
3 * Copyright (c) 2002 www.phpeclipse.de All rights
4 * reserved. This program and the accompanying materials are made available
5 * under the terms of the Common Public License v1.0 which accompanies this
6 * distribution, and is available at http://www.eclipse.org/legal/cpl-v10.html
7 ******************************************************************************/
8 import net.sourceforge.phpdt.core.tests.util.AbstractCompilerTest;
9 import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
11 * Tests the php parser
13 public class SmartyCompilerTestCase extends AbstractCompilerTest {
15 public SmartyCompilerTestCase(String name) {
19 * Test the PHP Parser with different PHP snippets
21 public void testPHPParser() {
25 " * Project: Smarty: the PHP compiling template engine\n" +
26 " * File: Smarty_Compiler.class.php\n" +
27 " * Author: Monte Ohrt <monte@ispi.net>\n" +
28 " * Andrei Zmievski <andrei@php.net>\n" +
30 " * Version: 2.4.2\n" +
31 " * Copyright: 2001,2002 ispi of Lincoln, Inc.\n" +
33 " * This library is free software; you can redistribute it and/or\n" +
34 " * modify it under the terms of the GNU Lesser General Public\n" +
35 " * License as published by the Free Software Foundation; either\n" +
36 " * version 2.1 of the License, or (at your option) any later version.\n" +
38 " * This library is distributed in the hope that it will be useful,\n" +
39 " * but WITHOUT ANY WARRANTY; without even the implied warranty of\n" +
40 " * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" +
41 " * Lesser General Public License for more details.\n" +
43 " * You should have received a copy of the GNU Lesser General Public\n" +
44 " * License along with this library; if not, write to the Free Software\n" +
45 " * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n" +
47 " * You may contact the authors of Smarty by e-mail at:\n" +
48 " * monte@ispi.net\n" +
49 " * andrei@php.net\n" +
51 " * Or, write to:\n" +
53 " * Director of Technology, ispi\n" +
54 " * 237 S. 70th suite 220\n" +
55 " * Lincoln, NE 68510\n" +
57 " * The latest version of Smarty can be obtained from:\n" +
58 " * http://www.phpinsider.com/\n" +
62 "class Smarty_Compiler extends Smarty {\n" +
64 " // internal vars\n" +
65 " public $_sectionelse_stack = array(); // keeps track of whether section had \'else\' part\n" +
66 " public $_foreachelse_stack = array(); // keeps track of whether foreach had \'else\' part\n" +
67 " public $_literal_blocks = array(); // keeps literal template blocks\n" +
68 " public $_php_blocks = array(); // keeps php code blocks\n" +
69 " public $_current_file = null; // the current template being compiled\n" +
70 " public $_current_line_no = 1; // line number for error messages\n" +
71 " public $_capture_stack = array(); // keeps track of nested capture buffers\n" +
72 " public $_plugin_info = array(); // keeps track of plugins to load\n" +
73 " public $_init_smarty_vars = false;\n" +
74 " public $_permitted_tokens = array(\'true\',\'false\',\'yes\',\'no\',\'on\',\'off\');\n" +
75 " public $_db_qstr_regexp = null; // regexps are setup in the constructor\n" +
76 " public $_si_qstr_regexp = null;\n" +
77 " public $_qstr_regexp = null;\n" +
78 " public $_func_regexp = null;\n" +
79 " public $_var_bracket_regexp = null;\n" +
80 " public $_dvar_guts_regexp = null;\n" +
81 " public $_dvar_regexp = null;\n" +
82 " public $_cvar_regexp = null;\n" +
83 " public $_svar_regexp = null;\n" +
84 " public $_avar_regexp = null;\n" +
85 " public $_mod_regexp = null;\n" +
86 " public $_var_regexp = null;\n" +
87 " public $_parenth_param_regexp = null;\n" +
88 " public $_func_call_regexp = null;\n" +
89 " public $_obj_ext_regexp = null;\n" +
90 " public $_obj_start_regexp = null;\n" +
91 " public $_obj_params_regexp = null;\n" +
92 " public $_obj_call_regexp = null;\n" +
95 " * The class constructor.\n" +
97 " * @access public\n" +
99 " function Smarty_Compiler()\n" +
101 " // matches double quoted strings:\n" +
103 " // \"foo\\\"bar\"\n" +
104 " $this->_db_qstr_regexp = \'\"[^\"\\\\\\\\]*(?:\\\\\\\\.[^\"\\\\\\\\]*)*\"\';\n" +
106 " // matches single quoted strings:\n" +
108 " // \'foo\\\'bar\'\n" +
109 " $this->_si_qstr_regexp = \'\\\'[^\\\'\\\\\\\\]*(?:\\\\\\\\.[^\\\'\\\\\\\\]*)*\\\'\';\n" +
111 " // matches single or double quoted strings\n" +
112 " $this->_qstr_regexp = \'(?:\' . $this->_db_qstr_regexp . \'|\' . $this->_si_qstr_regexp . \')\';\n" +
114 " // matches bracket portion of vars\n" +
118 " $this->_var_bracket_regexp = \'\\[\\$?[\\w\\.]+\\]\';\n" +
120 " // matches $ vars (not objects):\n" +
123 " // $foo.bar.foobar\n" +
126 " // $foo[5][blah]\n" +
127 " // $foo[5].bar[$foobar][4]\n" +
128 " $this->_dvar_guts_regexp = \'\\w+(?:\' . $this->_var_bracket_regexp\n" +
129 " . \')*(?:\\.\\$?\\w+(?:\' . $this->_var_bracket_regexp . \')*)*\';\n" +
130 " $this->_dvar_regexp = \'\\$\' . $this->_dvar_guts_regexp;\n" +
132 " // matches config vars:\n" +
134 " // #foobar123_foo#\n" +
135 " $this->_cvar_regexp = \'\\#\\w+\\#\';\n" +
137 " // matches section vars:\n" +
139 " $this->_svar_regexp = \'\\%\\w+\\.\\w+\\%\';\n" +
141 " // matches all valid variables (no quotes, no modifiers)\n" +
142 " $this->_avar_regexp = \'(?:\' . $this->_dvar_regexp . \'|\'\n" +
143 " . $this->_cvar_regexp . \'|\' . $this->_svar_regexp . \')\';\n" +
145 " // matches valid modifier syntax:\n" +
148 " // |foo:\"bar\"\n" +
150 " // |foo:\"bar\":$foobar\n" +
153 " $this->_mod_regexp = \'(?:\\|@?\\w+(?::(?>\\w+|\'\n" +
154 " . $this->_avar_regexp . \'|\' . $this->_qstr_regexp .\'))*)\';\n" +
156 " // matches valid variable syntax:\n" +
163 " $this->_var_regexp = \'(?:\' . $this->_avar_regexp . \'|\' . $this->_qstr_regexp . \')\';\n" +
165 " // matches valid object call (no objects allowed in parameters):\n" +
167 " // $foo->bar()\n" +
168 " // $foo->bar(\"text\")\n" +
169 " // $foo->bar($foo, $bar, \"text\")\n" +
170 " // $foo->bar($foo|bar, \"foo\"|bar)\n" +
171 " // $foo->bar->foo()\n" +
172 " // $foo->bar->foo->bar()\n" +
173 " $this->_obj_ext_regexp = \'\\->(?:\\w+|\' . $this->_dvar_regexp . \')\';\n" +
174 " $this->_obj_params_regexp = \'\\((?:\\w+|\'\n" +
175 " . $this->_var_regexp . \'(?>\' . $this->_mod_regexp . \'*)(?:\\s*,\\s*(?:(?:\\w+|\'\n" +
176 " . $this->_var_regexp . \'(?>\' . $this->_mod_regexp . \'*))))*)?\\)\'; \n" +
177 " $this->_obj_start_regexp = \'(?:\' . $this->_dvar_regexp . \'(?:\' . $this->_obj_ext_regexp . \')+)\';\n" +
178 " $this->_obj_call_regexp = \'(?:\' . $this->_obj_start_regexp . \'(?:\' . $this->_obj_params_regexp . \')?)\';\n" +
180 " // matches valid function name:\n" +
183 " $this->_func_regexp = \'[a-zA-Z_]\\w*\';\n" +
185 " // matches valid registered object:\n" +
187 " $this->_reg_obj_regexp = \'[a-zA-Z_]\\w*->[a-zA-Z_]\\w*\';\n" +
189 " // matches valid parameter values:\n" +
196 " // \"text\"|bar\n" +
198 " $this->_param_regexp = \'(?:\\s*(?:\' . $this->_obj_call_regexp . \'|\'\n" +
199 " . $this->_var_regexp . \'|\\w+)(?>\' . $this->_mod_regexp . \'*)\\s*)\'; \n" +
201 " // matches valid parenthesised function parameters:\n" +
204 " // $foo, $bar, \"text\"\n" +
205 " // $foo|bar, \"foo\"|bar, $foo->bar($foo)|bar\n" +
206 " $this->_parenth_param_regexp = \'(?:\\((?:\\w+|\'\n" +
207 " . $this->_param_regexp . \'(?:\\s*,\\s*(?:(?:\\w+|\'\n" +
208 " . $this->_param_regexp . \')))*)?\\))\';\n" +
210 " // matches valid function call:\n" +
212 " // foo_bar($foo)\n" +
213 " // _foo_bar($foo,\"bar\")\n" +
214 " // foo123($foo,$foo->bar(),\"foo\")\n" +
215 " $this->_func_call_regexp = \'(?:\' . $this->_func_regexp . \'\\s*(?:\'\n" +
216 " . $this->_parenth_param_regexp . \'))\'; \n" +
221 " * compile a template file\n" +
223 " * @access public\n" +
224 " * @param $tpl_file\n" +
225 " * @param $template_source\n" +
226 " * @param $template_compiled\n" +
228 " function _compile_file($tpl_file, $template_source, &$template_compiled)\n" +
230 " if ($this->security) {\n" +
231 " // do not allow php syntax to be executed unless specified\n" +
232 " if ($this->php_handling == SMARTY_PHP_ALLOW &&\n" +
233 " !$this->security_settings[\'PHP_HANDLING\']) {\n" +
234 " $this->php_handling = SMARTY_PHP_PASSTHRU;\n" +
238 " $this->_load_filters();\n" +
240 " $this->_current_file = $tpl_file;\n" +
241 " $this->_current_line_no = 1;\n" +
242 " $ldq = preg_quote($this->left_delimiter, \'!\');\n" +
243 " $rdq = preg_quote($this->right_delimiter, \'!\');\n" +
245 " // run template source through prefilter functions\n" +
246 " if (count($this->_plugins[\'prefilter\']) > 0) {\n" +
247 " foreach ($this->_plugins[\'prefilter\'] as $filter_name => $prefilter) {\n" +
248 " if ($prefilter === false) continue; \n" +
249 " if ($prefilter[3] || function_exists($prefilter[0])) {\n" +
250 " $template_source = $prefilter[0]($template_source, $this);\n" +
251 " $this->_plugins[\'prefilter\'][$filter_name][3] = true;\n" +
253 " $this->_trigger_fatal_error(\"[plugin] prefilter \'$filter_name\' is not implemented\");\n" +
258 " /* Annihilate the comments. */\n" +
259 " $template_source = preg_replace(\"!({$ldq})\\*(.*?)\\*({$rdq})!se\",\n" +
260 " \"\'\\\\1*\'.str_repeat(\\\"\\n\\\", substr_count(\'\\\\2\', \\\"\\n\\\")) .\'*\\\\3\'\",\n" +
261 " $template_source);\n" +
263 " /* Pull out the literal blocks. */\n" +
264 " preg_match_all(\"!{$ldq}literal{$rdq}(.*?){$ldq}/literal{$rdq}!s\", $template_source, $match);\n" +
265 " $this->_literal_blocks = $match[1];\n" +
266 " $template_source = preg_replace(\"!{$ldq}literal{$rdq}(.*?){$ldq}/literal{$rdq}!s\",\n" +
267 " $this->quote_replace($this->left_delimiter.\'literal\'.$this->right_delimiter), $template_source);\n" +
269 " /* Pull out the php code blocks. */\n" +
270 " preg_match_all(\"!{$ldq}php{$rdq}(.*?){$ldq}/php{$rdq}!s\", $template_source, $match);\n" +
271 " $this->_php_blocks = $match[1];\n" +
272 " $template_source = preg_replace(\"!{$ldq}php{$rdq}(.*?){$ldq}/php{$rdq}!s\",\n" +
273 " $this->quote_replace($this->left_delimiter.\'php\'.$this->right_delimiter), $template_source);\n" +
275 " /* Gather all template tags. */\n" +
276 " preg_match_all(\"!{$ldq}\\s*(.*?)\\s*{$rdq}!s\", $template_source, $match);\n" +
277 " $template_tags = $match[1];\n" +
278 " /* Split content by template tags to obtain non-template content. */\n" +
279 " $text_blocks = preg_split(\"!{$ldq}.*?{$rdq}!s\", $template_source);\n" +
281 " /* loop through text blocks */\n" +
282 " for ($curr_tb = 0, $for_max = count($text_blocks); $curr_tb < $for_max; $curr_tb++) {\n" +
283 " /* match anything resembling php tags */\n" +
284 " if (preg_match_all(\'!(<\\?(?:\\w+|=)?|\\?>|language\\s*=\\s*[\\\"\\\']?php[\\\"\\\']?)!is\', $text_blocks[$curr_tb], $sp_match)) {\n" +
285 " /* replace tags with placeholders to prevent recursive replacements */\n" +
286 " $sp_match[1] = array_unique($sp_match[1]);\n" +
287 " usort($sp_match[1], \'_smarty_sort_length\');\n" +
288 " for ($curr_sp = 0, $for_max2 = count($sp_match[1]); $curr_sp < $for_max2; $curr_sp++) {\n" +
289 " $text_blocks[$curr_tb] = str_replace($sp_match[1][$curr_sp],\'%%%SMARTYSP\'.$curr_sp.\'%%%\',$text_blocks[$curr_tb]);\n" +
291 " /* process each one */\n" +
292 " for ($curr_sp = 0, $for_max2 = count($sp_match[0]); $curr_sp < $for_max2; $curr_sp++) {\n" +
293 " if ($this->php_handling == SMARTY_PHP_PASSTHRU) {\n" +
294 " /* echo php contents */\n" +
295 " $text_blocks[$curr_tb] = str_replace(\'%%%SMARTYSP\'.$curr_sp.\'%%%\', \'<?php echo \\\'\'.str_replace(\"\'\", \"\\\'\", $sp_match[1][$curr_sp]).\'\\\'; ?>\'.\"\\n\", $text_blocks[$curr_tb]);\n" +
296 " } else if ($this->php_handling == SMARTY_PHP_QUOTE) {\n" +
297 " /* quote php tags */\n" +
298 " $text_blocks[$curr_tb] = str_replace(\'%%%SMARTYSP\'.$curr_sp.\'%%%\', htmlspecialchars($sp_match[1][$curr_sp]), $text_blocks[$curr_tb]);\n" +
299 " } else if ($this->php_handling == SMARTY_PHP_REMOVE) {\n" +
300 " /* remove php tags */\n" +
301 " $text_blocks[$curr_tb] = str_replace(\'%%%SMARTYSP\'.$curr_sp.\'%%%\', \'\', $text_blocks[$curr_tb]);\n" +
303 " /* SMARTY_PHP_ALLOW, but echo non php starting tags */\n" +
304 " $sp_match[1][$curr_sp] = preg_replace(\'%(<\\?(?!php|=|$))%i\', \'<?php echo \\\'\\\\1\\\'?>\'.\"\\n\", $sp_match[1][$curr_sp]);\n" +
305 " $text_blocks[$curr_tb] = str_replace(\'%%%SMARTYSP\'.$curr_sp.\'%%%\', $sp_match[1][$curr_sp], $text_blocks[$curr_tb]);\n" +
311 " /* Compile the template tags into PHP code. */\n" +
312 " $compiled_tags = array();\n" +
313 " for ($i = 0, $for_max = count($template_tags); $i < $for_max; $i++) {\n" +
314 " $this->_current_line_no += substr_count($text_blocks[$i], \"\\n\");\n" +
315 " $compiled_tags[] = $this->_compile_tag($template_tags[$i]);\n" +
316 " $this->_current_line_no += substr_count($template_tags[$i], \"\\n\");\n" +
319 " $template_compiled = \'\';\n" +
321 " /* Interleave the compiled contents and text blocks to get the final result. */\n" +
322 " for ($i = 0, $for_max = count($compiled_tags); $i < $for_max; $i++) {\n" +
323 " $template_compiled .= $text_blocks[$i].$compiled_tags[$i];\n" +
325 " $template_compiled .= $text_blocks[$i];\n" +
327 " /* Reformat data between \'strip\' and \'/strip\' tags, removing spaces, tabs and newlines. */\n" +
328 " if (preg_match_all(\"!{$ldq}strip{$rdq}.*?{$ldq}/strip{$rdq}!s\", $template_compiled, $match)) {\n" +
329 " $strip_tags = $match[0];\n" +
330 " $strip_tags_modified = preg_replace(\"!{$ldq}/?strip{$rdq}|[\\t ]+$|^[\\t ]+!m\", \'\', $strip_tags);\n" +
331 " $strip_tags_modified = preg_replace(\'![\\r\\n]+!m\', \'\', $strip_tags_modified);\n" +
332 " for ($i = 0, $for_max = count($strip_tags); $i < $for_max; $i++)\n" +
333 " $template_compiled = preg_replace(\"!{$ldq}strip{$rdq}.*?{$ldq}/strip{$rdq}!s\",\n" +
334 " $this->quote_replace($strip_tags_modified[$i]),\n" +
335 " $template_compiled, 1);\n" +
338 " // remove \\n from the end of the file, if any\n" +
339 " if ($template_compiled{strlen($template_compiled) - 1} == \"\\n\" ) {\n" +
340 " $template_compiled = substr($template_compiled, 0, -1);\n" +
343 " // run compiled template through postfilter functions\n" +
344 " if (count($this->_plugins[\'postfilter\']) > 0) {\n" +
345 " foreach ($this->_plugins[\'postfilter\'] as $filter_name => $postfilter) {\n" +
346 " if ($postfilter === false) continue;\n" +
347 " if ($postfilter[3] || function_exists($postfilter[0])) {\n" +
348 " $template_compiled = $postfilter[0]($template_compiled, $this);\n" +
349 " $this->_plugins[\'postfilter\'][$filter_name][3] = true;\n" +
351 " $this->_trigger_plugin_error(\"Smarty plugin error: postfilter \'$filter_name\' is not implemented\");\n" +
356 " // put header at the top of the compiled template\n" +
357 " $template_header = \"<?php /* Smarty version \".$this->_version.\", created on \".strftime(\"%Y-%m-%d %H:%M:%S\").\"\\n\";\n" +
358 " $template_header .= \" compiled from \".$tpl_file.\" */ ?>\\n\";\n" +
360 " /* Emit code to load needed plugins. */\n" +
361 " if (count($this->_plugin_info)) {\n" +
362 " $plugins_code = \'<?php $this->_load_plugins(array(\';\n" +
363 " foreach ($this->_plugin_info as $plugin_type => $plugins) {\n" +
364 " foreach ($plugins as $plugin_name => $plugin_info) {\n" +
365 " $plugins_code .= \"\\narray(\'$plugin_type\', \'$plugin_name\', \'$plugin_info[0]\', $plugin_info[1], \";\n" +
366 " $plugins_code .= $plugin_info[2] ? \'true),\' : \'false),\';\n" +
369 " $plugins_code .= \")); ?>\";\n" +
370 " $template_header .= $plugins_code;\n" +
371 " $this->_plugin_info = array();\n" +
374 " if ($this->_init_smarty_vars) {\n" +
375 " $template_header .= \"<?php \\$this->_assign_smarty_interface(); ?>\\n\";\n" +
376 " $this->_init_smarty_vars = false;\n" +
379 " $template_compiled = $template_header . $template_compiled;\n" +
385 " * Compile a template tag\n" +
387 " * @access public\n" +
388 " * @param $template_tag\n" +
390 " function _compile_tag($template_tag)\n" +
393 " /* Matched comment. */\n" +
394 " if ($template_tag{0} == \'*\' && $template_tag{strlen($template_tag) - 1} == \'*\')\n" +
397 " /* Split tag into two three parts: command, command modifiers and the arguments. */\n" +
398 " if(! preg_match(\'/^(?:(\' . $this->_obj_call_regexp . \'|\' . $this->_var_regexp\n" +
399 " . \'|\' . $this->_reg_obj_regexp . \'|\\/?\' . $this->_func_regexp . \')(\' . $this->_mod_regexp . \'*))\n" +
400 " (?:\\s+(.*))?$\n" +
401 " /xs\', $template_tag, $match)) {\n" +
402 " $this->_syntax_error(\"unrecognized tag: $template_tag\", E_USER_ERROR, __FILE__, __LINE__);\n" +
405 " $tag_command = $match[1];\n" +
406 " $tag_modifier = isset($match[2]) ? $match[2] : null;\n" +
407 " $tag_args = isset($match[3]) ? $match[3] : null;\n" +
410 " /* If the tag name is a variable or object, we process it. */\n" +
411 " if (preg_match(\'!^\' . $this->_obj_call_regexp . \'|\' . $this->_var_regexp . \'$!\', $tag_command)) {\n" +
412 " $return = $this->_parse_var_props($tag_command . $tag_modifier, $this->_parse_attrs($tag_args));\n" +
413 " if(isset($_tag_attrs[\'assign\'])) {\n" +
414 " return \"<?php \\$this->assign(\'\" . $this->_dequote($_tag_attrs[\'assign\']) . \"\', $return ); ?>\\n\"; \n" +
416 " return \"<?php echo $return; ?>\\n\";\n" +
420 " /* If the tag name is a registered object, we process it. */\n" +
421 " if (preg_match(\'!^\' . $this->_reg_obj_regexp . \'$!\', $tag_command)) {\n" +
422 " return $this->_compile_registered_object_tag($tag_command, $this->_parse_attrs($tag_args), $tag_modifier);\n" +
425 " switch ($tag_command) {\n" +
426 " case \'include\':\n" +
427 " return $this->_compile_include_tag($tag_args);\n" +
429 " case \'include_php\':\n" +
430 " return $this->_compile_include_php_tag($tag_args);\n" +
433 " return $this->_compile_if_tag($tag_args);\n" +
435 " case \'else\':\n" +
436 " return \'<?php else: ?>\';\n" +
438 " case \'elseif\':\n" +
439 " return $this->_compile_if_tag($tag_args, true);\n" +
442 " return \'<?php endif; ?>\';\n" +
444 " case \'capture\':\n" +
445 " return $this->_compile_capture_tag(true, $tag_args);\n" +
447 " case \'/capture\':\n" +
448 " return $this->_compile_capture_tag(false);\n" +
450 " case \'ldelim\':\n" +
451 " return $this->left_delimiter;\n" +
453 " case \'rdelim\':\n" +
454 " return $this->right_delimiter;\n" +
456 " case \'section\':\n" +
457 " array_push($this->_sectionelse_stack, false);\n" +
458 " return $this->_compile_section_start($tag_args);\n" +
460 " case \'sectionelse\':\n" +
461 " $this->_sectionelse_stack[count($this->_sectionelse_stack)-1] = true;\n" +
462 " return \"<?php endfor; else: ?>\";\n" +
464 " case \'/section\':\n" +
465 " if (array_pop($this->_sectionelse_stack))\n" +
466 " return \"<?php endif; ?>\";\n" +
468 " return \"<?php endfor; endif; ?>\";\n" +
470 " case \'foreach\':\n" +
471 " array_push($this->_foreachelse_stack, false);\n" +
472 " return $this->_compile_foreach_start($tag_args);\n" +
475 " case \'foreachelse\':\n" +
476 " $this->_foreachelse_stack[count($this->_foreachelse_stack)-1] = true;\n" +
477 " return \"<?php endforeach; else: ?>\";\n" +
479 " case \'/foreach\':\n" +
480 " if (array_pop($this->_foreachelse_stack))\n" +
481 " return \"<?php endif; ?>\";\n" +
483 " return \"<?php endforeach; endif; ?>\";\n" +
485 " case \'config_load\':\n" +
486 " return $this->_compile_config_load_tag($tag_args);\n" +
488 " case \'strip\':\n" +
489 " case \'/strip\':\n" +
490 " return $this->left_delimiter.$tag_command.$this->right_delimiter;\n" +
492 " case \'literal\':\n" +
493 " list (,$literal_block) = each($this->_literal_blocks);\n" +
494 " $this->_current_line_no += substr_count($literal_block, \"\\n\");\n" +
495 " return \"<?php echo \'\".str_replace(\"\'\", \"\\\'\", str_replace(\"\\\\\", \"\\\\\\\\\", $literal_block)).\"\'; ?>\\n\";\n" +
498 " if ($this->security && !$this->security_settings[\'PHP_TAGS\']) {\n" +
499 " $this->_syntax_error(\"(secure mode) php tags not permitted\", E_USER_WARNING, __FILE__, __LINE__);\n" +
502 " list (,$php_block) = each($this->_php_blocks);\n" +
503 " $this->_current_line_no += substr_count($php_block, \"\\n\");\n" +
504 " return \'<?php \'.$php_block.\' ?>\';\n" +
506 " case \'insert\':\n" +
507 " return $this->_compile_insert_tag($tag_args);\n" +
510 " if ($this->_compile_compiler_tag($tag_command, $tag_args, $output)) {\n" +
511 " return $output;\n" +
512 " } else if ($this->_compile_block_tag($tag_command, $tag_args, $tag_modifier, $output)) {\n" +
513 " return $output;\n" +
515 " return $this->_compile_custom_tag($tag_command, $tag_args, $tag_modifier);\n" +
522 " * compile the custom compiler tag\n" +
524 " * @access public\n" +
525 " * @param $tag_command\n" +
526 " * @param $tag_args\n" +
527 " * @param $output\n" +
529 " function _compile_compiler_tag($tag_command, $tag_args, &$output)\n" +
531 " $found = false;\n" +
532 " $have_function = true;\n" +
535 " * First we check if the compiler function has already been registered\n" +
536 " * or loaded from a plugin file.\n" +
538 " if (isset($this->_plugins[\'compiler\'][$tag_command])) {\n" +
539 " $found = true;\n" +
540 " $plugin_func = $this->_plugins[\'compiler\'][$tag_command][0];\n" +
541 " if (!function_exists($plugin_func)) {\n" +
542 " $message = \"compiler function \'$tag_command\' is not implemented\";\n" +
543 " $have_function = false;\n" +
547 " * Otherwise we need to load plugin file and look for the function\n" +
550 " else if ($plugin_file = $this->_get_plugin_filepath(\'compiler\', $tag_command)) {\n" +
551 " $found = true;\n" +
553 " include_once $plugin_file;\n" +
555 " $plugin_func = \'smarty_compiler_\' . $tag_command;\n" +
556 " if (!function_exists($plugin_func)) {\n" +
557 " $message = \"plugin function $plugin_func() not found in $plugin_file\\n\";\n" +
558 " $have_function = false;\n" +
560 " $this->_plugins[\'compiler\'][$tag_command] = array($plugin_func, null, null);\n" +
565 " * True return value means that we either found a plugin or a\n" +
566 " * dynamically registered function. False means that we didn\'t and the\n" +
567 " * compiler should now emit code to load custom function plugin for this\n" +
571 " if ($have_function) {\n" +
572 " $output = \'<?php \' . $plugin_func($tag_args, $this) . \' ?>\';\n" +
574 " $this->_syntax_error($message, E_USER_WARNING, __FILE__, __LINE__);\n" +
584 " * compile block function tag\n" +
586 " * @access public\n" +
587 " * @param $tag_command\n" +
588 " * @param $tag_args\n" +
589 " * @param $tag_modifier\n" +
590 " * @param $output\n" +
592 " function _compile_block_tag($tag_command, $tag_args, $tag_modifier, &$output)\n" +
594 " if ($tag_command{0} == \'/\') {\n" +
595 " $start_tag = false;\n" +
596 " $tag_command = substr($tag_command, 1);\n" +
598 " $start_tag = true;\n" +
600 " $found = false;\n" +
601 " $have_function = true;\n" +
604 " * First we check if the block function has already been registered\n" +
605 " * or loaded from a plugin file.\n" +
607 " if (isset($this->_plugins[\'block\'][$tag_command])) {\n" +
608 " $found = true;\n" +
609 " $plugin_func = $this->_plugins[\'block\'][$tag_command][0];\n" +
610 " if (!function_exists($plugin_func)) {\n" +
611 " $message = \"block function \'$tag_command\' is not implemented\";\n" +
612 " $have_function = false;\n" +
616 " * Otherwise we need to load plugin file and look for the function\n" +
619 " else if ($plugin_file = $this->_get_plugin_filepath(\'block\', $tag_command)) {\n" +
620 " $found = true;\n" +
622 " include_once $plugin_file;\n" +
624 " $plugin_func = \'smarty_block_\' . $tag_command;\n" +
625 " if (!function_exists($plugin_func)) {\n" +
626 " $message = \"plugin function $plugin_func() not found in $plugin_file\\n\";\n" +
627 " $have_function = false;\n" +
629 " $this->_plugins[\'block\'][$tag_command] = array($plugin_func, null, null);\n" +
633 " if (!$found) {\n" +
635 " } else if (!$have_function) {\n" +
636 " $this->_syntax_error($message, E_USER_WARNING, __FILE__, __LINE__);\n" +
641 " * Even though we\'ve located the plugin function, compilation\n" +
642 " * happens only once, so the plugin will still need to be loaded\n" +
643 " * at runtime for future requests.\n" +
645 " $this->_add_plugin(\'block\', $tag_command);\n" +
647 " if ($start_tag) {\n" +
648 " $arg_list = array();\n" +
649 " $attrs = $this->_parse_attrs($tag_args);\n" +
650 " foreach ($attrs as $arg_name => $arg_value) {\n" +
651 " if (is_bool($arg_value))\n" +
652 " $arg_value = $arg_value ? \'true\' : \'false\';\n" +
653 " $arg_list[] = \"\'$arg_name\' => $arg_value\";\n" +
656 " $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" +
658 " $output = \"<?php \\$this->_block_content = ob_get_contents(); ob_end_clean(); \";\n" +
659 " $out_tag_text = \"\\$this->_plugins[\'block\'][\'$tag_command\'][0](\\$this->_tag_stack[count(\\$this->_tag_stack)-1][1], \\$this->_block_content, \\$this)\";\n" +
660 " if($tag_modifier != \'\') {\n" +
661 " $this->_parse_modifiers($out_tag_text, $tag_modifier);\n" +
663 " $output .= \'echo \' . $out_tag_text . \';\';\n" +
664 " $output .= \" array_pop(\\$this->_tag_stack); ?>\";\n" +
672 " * compile custom function tag\n" +
674 " * @access public\n" +
675 " * @param $tag_command\n" +
676 " * @param $tag_args\n" +
677 " * @param $tag_modifier\n" +
679 " function _compile_custom_tag($tag_command, $tag_args, $tag_modifier)\n" +
681 " $this->_add_plugin(\'function\', $tag_command);\n" +
683 " $arg_list = array();\n" +
684 " $attrs = $this->_parse_attrs($tag_args);\n" +
685 " foreach ($attrs as $arg_name => $arg_value) {\n" +
686 " if (is_bool($arg_value))\n" +
687 " $arg_value = $arg_value ? \'true\' : \'false\';\n" +
688 " $arg_list[] = \"\'$arg_name\' => $arg_value\";\n" +
691 " $return = \"\\$this->_plugins[\'function\'][\'$tag_command\'][0](array(\".implode(\',\', (array)$arg_list).\"), \\$this)\";\n" +
693 " if($tag_modifier != \'\') {\n" +
694 " $this->_parse_modifiers($return, $tag_modifier);\n" +
697 " return \'<?php echo \' . $return . \" ; ?>\\n\";\n" +
701 " * compile a registered object tag\n" +
703 " * @access public\n" +
704 " * @param $tag_command\n" +
705 " * @param $attrs\n" +
706 " * @param $tag_modifier\n" +
708 " function _compile_registered_object_tag($tag_command, $attrs, $tag_modifier)\n" +
710 " list($object, $obj_comp) = explode(\'->\', $tag_command);\n" +
712 " $arg_list = array();\n" +
713 " if(count($attrs)) {\n" +
714 " $_assign_var = false;\n" +
715 " foreach ($attrs as $arg_name => $arg_value) {\n" +
716 " if($arg_name == \'assign\') {\n" +
717 " $_assign_var = $arg_value;\n" +
718 " unset($attrs[\'assign\']);\n" +
721 " if (is_bool($arg_value))\n" +
722 " $arg_value = $arg_value ? \'true\' : \'false\';\n" +
723 " $arg_list[] = \"\'$arg_name\' => $arg_value\";\n" +
727 " if(!is_object($this->_reg_objects[$object][0])) {\n" +
728 " $this->_trigger_fatal_error(\"registered \'$object\' is not an object\");\n" +
729 " } elseif(!empty($this->_reg_objects[$object][1]) && !in_array($obj_comp, $this->_reg_objects[$object][1])) {\n" +
730 " $this->_trigger_fatal_error(\"\'$obj_comp\' is not a registered component of object \'$object\'\");\n" +
731 " } elseif(method_exists($this->_reg_objects[$object][0], $obj_comp)) {\n" +
733 " if($this->_reg_objects[$object][2]) {\n" +
734 " // smarty object argument format\n" +
735 " $return = \"\\$this->_reg_objects[\'$object\'][0]->$obj_comp(array(\".implode(\',\', (array)$arg_list).\"), \\$this)\";\n" +
737 " // traditional argument format\n" +
738 " $return = \"\\$this->_reg_objects[\'$object\'][0]->$obj_comp(\".implode(\',\', array_values($attrs)).\")\";\n" +
742 " $return = \"\\$this->_reg_objects[\'$object\'][0]->$obj_comp\";\n" +
745 " if($tag_modifier != \'\') {\n" +
746 " $this->_parse_modifiers($return, $tag_modifier);\n" +
749 " if($_assign_var) {\n" +
750 " return \"<?php \\$this->assign(\'\" . $this->_dequote($_assign_var) .\"\', $return); ?>\\n\";\n" +
752 " return \'<?php echo \' . $return . \"; ?>\\n\";\n" +
759 " * Compile {insert ...} tag\n" +
761 " * @access public\n" +
762 " * @param $tag_args\n" +
764 " function _compile_insert_tag($tag_args)\n" +
766 " $attrs = $this->_parse_attrs($tag_args);\n" +
767 " $name = $this->_dequote($attrs[\'name\']);\n" +
769 " if (empty($name)) {\n" +
770 " $this->_syntax_error(\"missing insert name\", E_USER_ERROR, __FILE__, __LINE__);\n" +
773 " if (!empty($attrs[\'script\'])) {\n" +
774 " $delayed_loading = true;\n" +
776 " $delayed_loading = false; \n" +
779 " foreach ($attrs as $arg_name => $arg_value) {\n" +
780 " if (is_bool($arg_value))\n" +
781 " $arg_value = $arg_value ? \'true\' : \'false\';\n" +
782 " $arg_list[] = \"\'$arg_name\' => $arg_value\";\n" +
785 " $this->_add_plugin(\'insert\', $name, $delayed_loading);\n" +
787 " return \"<?php echo \\$this->_run_insert_handler(array(\".implode(\', \', (array)$arg_list).\")); ?>\\n\";\n" +
792 " * Compile {config_load ...} tag\n" +
794 " * @access public\n" +
795 " * @param $tag_args\n" +
797 " function _compile_config_load_tag($tag_args)\n" +
799 " $attrs = $this->_parse_attrs($tag_args);\n" +
801 " if (empty($attrs[\'file\'])) {\n" +
802 " $this->_syntax_error(\"missing \'file\' attribute in config_load tag\", E_USER_ERROR, __FILE__, __LINE__);\n" +
805 " if (empty($attrs[\'section\'])) {\n" +
806 " $attrs[\'section\'] = \'null\';\n" +
809 " if (isset($attrs[\'scope\'])) {\n" +
810 " $scope = @$this->_dequote($attrs[\'scope\']);\r\n" +
811 " if ($scope != \'local\' &&\r\n" +
812 " $scope != \'parent\' &&\r\n" +
813 " $scope != \'global\') {\r\n" +
814 " $this->_syntax_error(\"invalid \'scope\' attribute value\", E_USER_ERROR, __FILE__, __LINE__);\r\n" +
817 " if (isset($attrs[\'global\']) && $attrs[\'global\'])\r\n" +
818 " $scope = \'parent\';\r\n" +
820 " $scope = \'local\';\r\n" +
823 " return \'<?php $this->config_load(\' . $attrs[\'file\'] . \', \' . $attrs[\'section\'] . \", \'$scope\'); ?>\";\r\n" +
828 " * Compile {include ...} tag\r\n" +
830 " * @access public\r\n" +
831 " * $param $tag_args\r\n" +
833 " function _compile_include_tag($tag_args)\r\n" +
835 " $attrs = $this->_parse_attrs($tag_args);\r\n" +
836 " $arg_list = array();\r\n" +
838 " if (empty($attrs[\'file\'])) {\r\n" +
839 " $this->_syntax_error(\"missing \'file\' attribute in include tag\", E_USER_ERROR, __FILE__, __LINE__);\r\n" +
842 " foreach ($attrs as $arg_name => $arg_value) {\r\n" +
843 " if ($arg_name == \'file\') {\r\n" +
844 " $include_file = $arg_value;\r\n" +
846 " } else if ($arg_name == \'assign\') {\r\n" +
847 " $assign_var = $arg_value;\r\n" +
850 " if (is_bool($arg_value))\r\n" +
851 " $arg_value = $arg_value ? \'true\' : \'false\';\r\n" +
852 " $arg_list[] = \"\'$arg_name\' => $arg_value\";\r\n" +
855 " $output = \'<?php \';\r\n" +
857 " if (isset($assign_var)) {\r\n" +
858 " $output .= \"ob_start();\\n\";\r\n" +
862 " \"\\$_smarty_tpl_vars = \\$this->_tpl_vars;\\n\" .\r\n" +
863 " \"\\$this->_smarty_include(\".$include_file.\", array(\".implode(\',\', (array)$arg_list).\"));\\n\" .\r\n" +
864 " \"\\$this->_tpl_vars = \\$_smarty_tpl_vars;\\n\" .\r\n" +
865 " \"unset(\\$_smarty_tpl_vars);\\n\";\r\n" +
867 " if (isset($assign_var)) {\r\n" +
868 " $output .= \"\\$this->assign(\" . $assign_var . \", ob_get_contents()); ob_end_clean();\\n\";\r\n" +
871 " $output .= \' ?>\';\r\n" +
873 " return $output;\r\n" +
878 " * Compile {include ...} tag\r\n" +
880 " * @access public\r\n" +
881 " * @param $tag_args\r\n" +
883 " function _compile_include_php_tag($tag_args)\r\n" +
885 " $attrs = $this->_parse_attrs($tag_args);\r\n" +
887 " if (empty($attrs[\'file\'])) {\r\n" +
888 " $this->_syntax_error(\"missing \'file\' attribute in include_php tag\", E_USER_ERROR, __FILE__, __LINE__);\r\n" +
891 " $assign_var = $this->_dequote($attrs[\'assign\']);\r\n" +
893 " $once_var = ( $attrs[\'once\'] === false ) ? \'false\' : \'true\';\r\n" +
895 " foreach($attrs as $arg_name => $arg_value) {\r\n" +
896 " if($arg_name != \'file\' AND $arg_name != \'once\' AND $arg_name != \'assign\') {\r\n" +
897 " if(is_bool($arg_value))\r\n" +
898 " $arg_value = $arg_value ? \'true\' : \'false\';\r\n" +
899 " $arg_list[] = \"\'$arg_name\' => $arg_value\";\r\n" +
904 " \"<?php \\$this->_smarty_include_php($attrs[file], \'$assign_var\', $once_var, \" .\r\n" +
905 " \"array(\".implode(\',\', (array)$arg_list).\")); ?>\";\r\n" +
907 " return $output;\r\n" +
912 " * Compile {section ...} tag\r\n" +
914 " * @access public\r\n" +
915 " * @param $tag_args\r\n" +
917 " function _compile_section_start($tag_args)\r\n" +
919 " $attrs = $this->_parse_attrs($tag_args);\r\n" +
920 " $arg_list = array();\r\n" +
922 " $output = \'<?php \';\r\n" +
923 " $section_name = $attrs[\'name\']; \r\n" +
924 " if (empty($section_name)) {\r\n" +
925 " $this->_syntax_error(\"missing section name\", E_USER_ERROR, __FILE__, __LINE__);\r\n" +
928 " $output .= \"if (isset(\\$this->_sections[$section_name])) unset(\\$this->_sections[$section_name]);\\n\";\r\n" +
929 " $section_props = \"\\$this->_sections[$section_name]\";\r\n" +
931 " foreach ($attrs as $attr_name => $attr_value) {\r\n" +
932 " switch ($attr_name) {\r\n" +
933 " case \'loop\':\r\n" +
934 " $output .= \"{$section_props}[\'loop\'] = is_array($attr_value) ? count($attr_value) : max(0, (int)$attr_value);\\n\";\r\n" +
937 " case \'show\':\r\n" +
938 " if (is_bool($attr_value))\r\n" +
939 " $show_attr_value = $attr_value ? \'true\' : \'false\';\r\n" +
941 " $show_attr_value = \"(bool)$attr_value\";\r\n" +
942 " $output .= \"{$section_props}[\'show\'] = $show_attr_value;\\n\";\r\n" +
945 " case \'name\':\r\n" +
946 " $output .= \"{$section_props}[\'$attr_name\'] = $attr_value;\\n\";\r\n" +
949 " case \'max\':\r\n" +
950 " case \'start\':\r\n" +
951 " $output .= \"{$section_props}[\'$attr_name\'] = (int)$attr_value;\\n\";\r\n" +
954 " case \'step\':\r\n" +
955 " $output .= \"{$section_props}[\'$attr_name\'] = ((int)$attr_value) == 0 ? 1 : (int)$attr_value;\\n\";\r\n" +
959 " $this->_syntax_error(\"unknown section attribute - \'$attr_name\'\", E_USER_ERROR, __FILE__, __LINE__);\r\n" +
964 " if (!isset($attrs[\'show\']))\r\n" +
965 " $output .= \"{$section_props}[\'show\'] = true;\\n\";\r\n" +
967 " if (!isset($attrs[\'loop\']))\r\n" +
968 " $output .= \"{$section_props}[\'loop\'] = 1;\\n\";\r\n" +
970 " if (!isset($attrs[\'max\']))\r\n" +
971 " $output .= \"{$section_props}[\'max\'] = {$section_props}[\'loop\'];\\n\";\r\n" +
973 " $output .= \"if ({$section_props}[\'max\'] < 0)\\n\" .\r\n" +
974 " \" {$section_props}[\'max\'] = {$section_props}[\'loop\'];\\n\";\r\n" +
976 " if (!isset($attrs[\'step\']))\r\n" +
977 " $output .= \"{$section_props}[\'step\'] = 1;\\n\";\r\n" +
979 " if (!isset($attrs[\'start\']))\r\n" +
980 " $output .= \"{$section_props}[\'start\'] = {$section_props}[\'step\'] > 0 ? 0 : {$section_props}[\'loop\']-1;\\n\";\r\n" +
982 " $output .= \"if ({$section_props}[\'start\'] < 0)\\n\" .\r\n" +
983 " \" {$section_props}[\'start\'] = max({$section_props}[\'step\'] > 0 ? 0 : -1, {$section_props}[\'loop\'] + {$section_props}[\'start\']);\\n\" .\r\n" +
984 " \"else\\n\" .\r\n" +
985 " \" {$section_props}[\'start\'] = min({$section_props}[\'start\'], {$section_props}[\'step\'] > 0 ? {$section_props}[\'loop\'] : {$section_props}[\'loop\']-1);\\n\";\r\n" +
988 " $output .= \"if ({$section_props}[\'show\']) {\\n\";\r\n" +
989 " if (!isset($attrs[\'start\']) && !isset($attrs[\'step\']) && !isset($attrs[\'max\'])) {\r\n" +
990 " $output .= \" {$section_props}[\'total\'] = {$section_props}[\'loop\'];\\n\";\r\n" +
992 " $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" +
994 " $output .= \" if ({$section_props}[\'total\'] == 0)\\n\" .\r\n" +
995 " \" {$section_props}[\'show\'] = false;\\n\" .\r\n" +
996 " \"} else\\n\" .\r\n" +
997 " \" {$section_props}[\'total\'] = 0;\\n\";\r\n" +
999 " $output .= \"if ({$section_props}[\'show\']):\\n\";\r\n" +
1000 " $output .= \"\r\n" +
1001 " for ({$section_props}[\'index\'] = {$section_props}[\'start\'], {$section_props}[\'iteration\'] = 1;\r\n" +
1002 " {$section_props}[\'iteration\'] <= {$section_props}[\'total\'];\r\n" +
1003 " {$section_props}[\'index\'] += {$section_props}[\'step\'], {$section_props}[\'iteration\']++):\\n\";\r\n" +
1004 " $output .= \"{$section_props}[\'rownum\'] = {$section_props}[\'iteration\'];\\n\";\r\n" +
1005 " $output .= \"{$section_props}[\'index_prev\'] = {$section_props}[\'index\'] - {$section_props}[\'step\'];\\n\";\r\n" +
1006 " $output .= \"{$section_props}[\'index_next\'] = {$section_props}[\'index\'] + {$section_props}[\'step\'];\\n\";\r\n" +
1007 " $output .= \"{$section_props}[\'first\'] = ({$section_props}[\'iteration\'] == 1);\\n\";\r\n" +
1008 " $output .= \"{$section_props}[\'last\'] = ({$section_props}[\'iteration\'] == {$section_props}[\'total\']);\\n\";\r\n" +
1010 " $output .= \"?>\";\r\n" +
1012 " return $output;\r\n" +
1017 " * Compile {foreach ...} tag.\r\n" +
1019 " * @access public\r\n" +
1020 " * @param $tag_args\r\n" +
1022 " function _compile_foreach_start($tag_args)\r\n" +
1024 " $attrs = $this->_parse_attrs($tag_args);\r\n" +
1025 " $arg_list = array();\r\n" +
1027 " if (empty($attrs[\'from\'])) {\r\n" +
1028 " $this->_syntax_error(\"missing \'from\' attribute\", E_USER_ERROR, __FILE__, __LINE__);\r\n" +
1031 " if (empty($attrs[\'item\'])) {\r\n" +
1032 " $this->_syntax_error(\"missing \'item\' attribute\", E_USER_ERROR, __FILE__, __LINE__);\r\n" +
1035 " $from = $attrs[\'from\'];\r\n" +
1036 " $item = $this->_dequote($attrs[\'item\']);\r\n" +
1037 " if (isset($attrs[\'name\']))\r\n" +
1038 " $name = $attrs[\'name\'];\r\n" +
1040 " $output = \'<?php \';\r\n" +
1041 " if (isset($name)) {\r\n" +
1042 " $output .= \"if (isset(\\$this->_foreach[$name])) unset(\\$this->_foreach[$name]);\\n\";\r\n" +
1043 " $foreach_props = \"\\$this->_foreach[$name]\";\r\n" +
1046 " $key_part = \'\';\r\n" +
1048 " foreach ($attrs as $attr_name => $attr_value) {\r\n" +
1049 " switch ($attr_name) {\r\n" +
1050 " case \'key\':\r\n" +
1051 " $key = $this->_dequote($attrs[\'key\']);\r\n" +
1052 " $key_part = \"\\$this->_tpl_vars[\'$key\'] => \";\r\n" +
1055 " case \'name\':\r\n" +
1056 " $output .= \"{$foreach_props}[\'$attr_name\'] = $attr_value;\\n\";\r\n" +
1061 " if (isset($name)) {\r\n" +
1062 " $output .= \"{$foreach_props}[\'total\'] = count((array)$from);\\n\";\r\n" +
1063 " $output .= \"{$foreach_props}[\'show\'] = {$foreach_props}[\'total\'] > 0;\\n\";\r\n" +
1064 " $output .= \"if ({$foreach_props}[\'show\']):\\n\";\r\n" +
1065 " $output .= \"{$foreach_props}[\'iteration\'] = 0;\\n\";\r\n" +
1066 " $output .= \" foreach ((array)$from as $key_part\\$this->_tpl_vars[\'$item\']):\\n\";\r\n" +
1067 " $output .= \" {$foreach_props}[\'iteration\']++;\\n\";\r\n" +
1068 " $output .= \" {$foreach_props}[\'first\'] = ({$foreach_props}[\'iteration\'] == 1);\\n\";\r\n" +
1069 " $output .= \" {$foreach_props}[\'last\'] = ({$foreach_props}[\'iteration\'] == {$foreach_props}[\'total\']);\\n\";\r\n" +
1071 " $output .= \"if (count((array)$from)):\\n\";\r\n" +
1072 " $output .= \" foreach ((array)$from as $key_part\\$this->_tpl_vars[\'$item\']):\\n\";\r\n" +
1074 " $output .= \'?>\';\r\n" +
1076 " return $output;\r\n" +
1081 " * Compile {capture} .. {/capture} tags\r\n" +
1083 " * @access public\r\n" +
1084 " * @param $start\r\n" +
1085 " * @param $tag_args\r\n" +
1087 " function _compile_capture_tag($start, $tag_args = \'\')\r\n" +
1089 " $attrs = $this->_parse_attrs($tag_args);\r\n" +
1091 " if ($start) {\r\n" +
1092 " if (isset($attrs[\'name\']))\r\n" +
1093 " $buffer = $attrs[\'name\'];\r\n" +
1095 " $buffer = \"\'default\'\";\r\n" +
1097 " $output = \"<?php ob_start(); ?>\";\r\n" +
1098 " $this->_capture_stack[] = $buffer;\r\n" +
1100 " $buffer = array_pop($this->_capture_stack);\r\n" +
1101 " $output = \"<?php \\$this->_smarty_vars[\'capture\'][$buffer] = ob_get_contents(); ob_end_clean(); ?>\";\r\n" +
1104 " return $output;\r\n" +
1108 " * Compile {if ...} tag\r\n" +
1110 " * @access public\r\n" +
1111 " * @param $tag_args\r\n" +
1112 " * @param $elseif\r\n" +
1114 " function _compile_if_tag($tag_args, $elseif = false)\r\n" +
1117 " /* Tokenize args for \'if\' tag. */\r\n" +
1118 " preg_match_all(\'/(?>\r\n" +
1119 " \' . $this->_obj_call_regexp . \'(?:\' . $this->_mod_regexp . \'*) | # valid object call\r\n" +
1120 " \' . $this->_var_regexp . \'(?:\' . $this->_mod_regexp . \'*) | # public or quoted string\r\n" +
1121 " \\-?\\d+|!==|<=>|==|!=|<=|>=|\\&\\&|\\|\\||\\(|\\)|,|\\!|\\^|=|<|>|\\||\\%|\\+|\\-|\\/|\\* | # valid non-word token\r\n" +
1122 " \\b\\w+\\b | # valid word token\r\n" +
1123 " \\S+ # anything else\r\n" +
1124 " )/x\', $tag_args, $match);\r\n" +
1126 " $tokens = $match[0];\r\n" +
1128 " // make sure we have balanced parenthesis\r\n" +
1129 " $token_count = array_count_values($tokens);\r\n" +
1130 " if(isset($token_count[\'(\']) && $token_count[\'(\'] != $token_count[\')\']) {\r\n" +
1131 " $this->_syntax_error(\"unbalanced parenthesis in if statement\", E_USER_ERROR, __FILE__, __LINE__);\r\n" +
1134 " $is_arg_stack = array();\r\n" +
1136 " for ($i = 0; $i < count($tokens); $i++) {\r\n" +
1138 " $token = &$tokens[$i];\r\n" +
1140 " switch (strtolower($token)) {\r\n" +
1141 " case \'!\':\r\n" +
1142 " case \'%\':\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" +
1164 " case \'eq\':\r\n" +
1165 " $token = \'==\';\r\n" +
1168 " case \'ne\':\r\n" +
1169 " case \'neq\':\r\n" +
1170 " $token = \'!=\';\r\n" +
1173 " case \'lt\':\r\n" +
1174 " $token = \'<\';\r\n" +
1177 " case \'le\':\r\n" +
1178 " case \'lte\':\r\n" +
1179 " $token = \'<=\';\r\n" +
1182 " case \'gt\':\r\n" +
1183 " $token = \'>\';\r\n" +
1186 " case \'ge\':\r\n" +
1187 " case \'gte\':\r\n" +
1188 " $token = \'>=\';\r\n" +
1191 " case \'and\':\r\n" +
1192 " $token = \'&&\';\r\n" +
1195 " case \'or\':\r\n" +
1196 " $token = \'||\';\r\n" +
1199 " case \'not\':\r\n" +
1200 " $token = \'!\';\r\n" +
1203 " case \'mod\':\r\n" +
1204 " $token = \'%\';\r\n" +
1207 " case \'(\':\r\n" +
1208 " array_push($is_arg_stack, $i);\r\n" +
1211 " case \'is\':\r\n" +
1212 " /* If last token was a \')\', we operate on the parenthesized\r\n" +
1213 " expression. The start of the expression is on the stack.\r\n" +
1214 " Otherwise, we operate on the last encountered token. */\r\n" +
1215 " if ($tokens[$i-1] == \')\')\r\n" +
1216 " $is_arg_start = array_pop($is_arg_stack);\r\n" +
1218 " $is_arg_start = $i-1;\r\n" +
1219 " /* Construct the argument for \'is\' expression, so it knows\r\n" +
1220 " what to operate on. */\r\n" +
1221 " $is_arg = implode(\' \', array_slice($tokens, $is_arg_start, $i - $is_arg_start));\r\n" +
1223 " /* Pass all tokens from next one until the end to the\r\n" +
1224 " \'is\' expression parsing function. The function will\r\n" +
1225 " return modified tokens, where the first one is the result\r\n" +
1226 " of the \'is\' expression and the rest are the tokens it\r\n" +
1227 " didn\'t touch. */ \r\n" +
1228 " $new_tokens = $this->_parse_is_expr($is_arg, array_slice($tokens, $i+1));\r\n" +
1230 " /* Replace the old tokens with the new ones. */\r\n" +
1231 " array_splice($tokens, $is_arg_start, count($tokens), $new_tokens);\r\n" +
1233 " /* Adjust argument start so that it won\'t change from the\r\n" +
1234 " current position for the next iteration. */\r\n" +
1235 " $i = $is_arg_start;\r\n" +
1239 " if(preg_match(\'!^\' . $this->_func_regexp . \'$!\', $token) ) {\r\n" +
1240 " // function call \r\n" +
1241 " if($this->security &&\r\n" +
1242 " !in_array($token, $this->security_settings[\'IF_FUNCS\'])) {\r\n" +
1243 " $this->_syntax_error(\"(secure mode) \'$token\' not allowed in if statement\", E_USER_ERROR, __FILE__, __LINE__);\r\n" +
1245 " } elseif(preg_match(\'!^\' . $this->_var_regexp . \'(?:\' . $this->_mod_regexp . \'*)$!\', $token)) {\r\n" +
1246 " // variable\r\n" +
1247 " $token = $this->_parse_var_props($token);\r\n" +
1248 " } elseif(preg_match(\'!^\' . $this->_obj_call_regexp . \'(?:\' . $this->_mod_regexp . \'*)$!\', $token)) {\r\n" +
1250 " $token = $this->_parse_var_props($token);\r\n" +
1251 " } elseif(is_numeric($token)) {\r\n" +
1252 " // number, skip it\r\n" +
1254 " $this->_syntax_error(\"unidentified token \'$token\'\", E_USER_ERROR, __FILE__, __LINE__);\r\n" +
1260 " if ($elseif)\r\n" +
1261 " return \'<?php elseif (\'.implode(\' \', $tokens).\'): ?>\';\r\n" +
1263 " return \'<?php if (\'.implode(\' \', $tokens).\'): ?>\';\r\n" +
1268 " * Parse is expression\r\n" +
1270 " * @access public\r\n" +
1271 " * @param $is_arg\r\n" +
1272 " * @param $tokens\r\n" +
1274 " function _parse_is_expr($is_arg, $tokens)\r\n" +
1276 " $expr_end = 0;\r\n" +
1277 " $negate_expr = false;\r\n" +
1279 " if (($first_token = array_shift($tokens)) == \'not\') {\r\n" +
1280 " $negate_expr = true;\r\n" +
1281 " $expr_type = array_shift($tokens);\r\n" +
1283 " $expr_type = $first_token;\r\n" +
1285 " switch ($expr_type) {\r\n" +
1286 " case \'even\':\r\n" +
1287 " if (@$tokens[$expr_end] == \'by\') {\r\n" +
1288 " $expr_end++;\r\n" +
1289 " $expr_arg = $tokens[$expr_end++];\r\n" +
1290 " $expr = \"!(($is_arg / $expr_arg) % \" . $this->_parse_var_props($expr_arg) . \")\";\r\n" +
1292 " $expr = \"!($is_arg % 2)\";\r\n" +
1295 " case \'odd\':\r\n" +
1296 " if (@$tokens[$expr_end] == \'by\') {\r\n" +
1297 " $expr_end++;\r\n" +
1298 " $expr_arg = $tokens[$expr_end++];\r\n" +
1299 " $expr = \"(($is_arg / $expr_arg) % \". $this->_parse_var_props($expr_arg) . \")\";\r\n" +
1301 " $expr = \"($is_arg % 2)\";\r\n" +
1304 " case \'div\':\r\n" +
1305 " if (@$tokens[$expr_end] == \'by\') {\r\n" +
1306 " $expr_end++;\r\n" +
1307 " $expr_arg = $tokens[$expr_end++];\r\n" +
1308 " $expr = \"!($is_arg % \" . $this->_parse_var_props($expr_arg) . \")\";\r\n" +
1310 " $this->_syntax_error(\"expecting \'by\' after \'div\'\", E_USER_ERROR, __FILE__, __LINE__);\r\n" +
1315 " $this->_syntax_error(\"unknown \'is\' expression - \'$expr_type\'\", E_USER_ERROR, __FILE__, __LINE__);\r\n" +
1319 " if ($negate_expr) {\r\n" +
1320 " $expr = \"!($expr)\";\r\n" +
1323 " array_splice($tokens, 0, $expr_end, $expr); \r\n" +
1325 " return $tokens;\r\n" +
1330 " * Parse attribute string\r\n" +
1332 " * @access public\r\n" +
1333 " * @param $tag_args\r\n" +
1334 " * @param $quote\r\n" +
1336 " function _parse_attrs($tag_args, $quote = true)\r\n" +
1339 " /* Tokenize tag attributes. */\r\n" +
1340 " preg_match_all(\'/(?:\' . $this->_obj_call_regexp . \'|\' . $this->_qstr_regexp . \' | (?>[^\"\\\'=\\s]+)\r\n" +
1343 " /x\', $tag_args, $match);\r\n" +
1344 " $tokens = $match[0]; \r\n" +
1346 " $attrs = array();\r\n" +
1347 " /* Parse state:\r\n" +
1348 " 0 - expecting attribute name\r\n" +
1349 " 1 - expecting \'=\'\r\n" +
1350 " 2 - expecting attribute value (not \'=\') */\r\n" +
1351 " $state = 0;\r\n" +
1353 " foreach ($tokens as $token) {\r\n" +
1354 " switch ($state) {\r\n" +
1356 " /* If the token is a valid identifier, we set attribute name\r\n" +
1357 " and go to state 1. */\r\n" +
1358 " if (preg_match(\'!^\\w+$!\', $token)) {\r\n" +
1359 " $attr_name = $token;\r\n" +
1360 " $state = 1;\r\n" +
1362 " $this->_syntax_error(\"invalid attribute name - \'$token\'\", E_USER_ERROR, __FILE__, __LINE__);\r\n" +
1366 " /* If the token is \'=\', then we go to state 2. */\r\n" +
1367 " if ($token == \'=\') {\r\n" +
1368 " $state = 2;\r\n" +
1370 " $this->_syntax_error(\"expecting \'=\' after attribute name \'$last_token\'\", E_USER_ERROR, __FILE__, __LINE__);\r\n" +
1374 " /* If token is not \'=\', we set the attribute value and go to\r\n" +
1375 " state 0. */\r\n" +
1376 " if ($token != \'=\') {\r\n" +
1377 " /* We booleanize the token if it\'s a non-quoted possible\r\n" +
1378 " boolean value. */\r\n" +
1379 " if (preg_match(\'!^(on|yes|true)$!\', $token))\r\n" +
1380 " $token = true;\r\n" +
1381 " else if (preg_match(\'!^(off|no|false)$!\', $token))\r\n" +
1382 " $token = false;\r\n" +
1383 " /* If the token is just a string,\r\n" +
1384 " we double-quote it. */\r\n" +
1385 " else if (preg_match(\'!^\\w+$!\', $token)) {\r\n" +
1386 " $token = \'\"\'.$token.\'\"\';\r\n" +
1389 " $attrs[$attr_name] = $token;\r\n" +
1390 " $state = 0;\r\n" +
1392 " $this->_syntax_error(\"\'=\' cannot be an attribute value\", E_USER_ERROR, __FILE__, __LINE__);\r\n" +
1395 " $last_token = $token;\r\n" +
1398 " if($state != 0) {\r\n" +
1399 " if($state == 1) {\r\n" +
1400 " $this->_syntax_error(\"expecting \'=\' after attribute name \'$last_token\'\", E_USER_ERROR, __FILE__, __LINE__); \r\n" +
1402 " $this->_syntax_error(\"missing attribute value\", E_USER_ERROR, __FILE__, __LINE__); \r\n" +
1406 " $this->_parse_vars_props($attrs);\r\n" +
1408 " return $attrs;\r\n" +
1412 " * compile multiple variables and section properties tokens into\r\n" +
1415 " * @access public\r\n" +
1416 " * @param $tokens\r\n" +
1418 " function _parse_vars_props(&$tokens)\r\n" +
1420 " foreach($tokens as $key => $val) { \r\n" +
1421 " $tokens[$key] = $this->_parse_var_props($val);\r\n" +
1426 " * compile single variable and section properties token into\r\n" +
1429 " * @access public\r\n" +
1430 " * @param $val\r\n" +
1431 " * @param $tag_attrs\r\n" +
1433 " function _parse_var_props($val, $tag_attrs = null)\r\n" +
1436 " $val = trim($val);\r\n" +
1438 " if(preg_match(\'!^(\' . $this->_obj_call_regexp . \'|\' . $this->_dvar_regexp . \')(?:\' . $this->_mod_regexp . \'*)$!\', $val)) {\r\n" +
1439 " // $ variable or object\r\n" +
1440 " return $this->_parse_var($val, $tag_attrs);\r\n" +
1442 " elseif(preg_match(\'!^\' . $this->_db_qstr_regexp . \'(?:\' . $this->_mod_regexp . \'*)$!\', $val)) {\r\n" +
1443 " // double quoted text\r\n" +
1444 " preg_match(\'!^(\' . $this->_db_qstr_regexp . \')(\'. $this->_mod_regexp . \'*)$!\', $val, $match);\r\n" +
1445 " $return = $this->_expand_quoted_text($match[1]);\r\n" +
1446 " if($match[2] != \'\') {\r\n" +
1447 " $this->_parse_modifiers($return, $match[2]);\r\n" +
1449 " return $return;\r\n" +
1451 " elseif(preg_match(\'!^\' . $this->_si_qstr_regexp . \'(?:\' . $this->_mod_regexp . \'*)$!\', $val)) {\r\n" +
1452 " // single quoted text\r\n" +
1453 " preg_match(\'!^(\' . $this->_si_qstr_regexp . \')(\'. $this->_mod_regexp . \'*)$!\', $val, $match);\r\n" +
1454 " if($match[2] != \'\') {\r\n" +
1455 " $this->_parse_modifiers($match[1], $match[2]);\r\n" +
1456 " return $match[1];\r\n" +
1459 " elseif(preg_match(\'!^\' . $this->_cvar_regexp . \'(?:\' . $this->_mod_regexp . \'*)$!\', $val)) {\r\n" +
1460 " // config var\r\n" +
1461 " return $this->_parse_conf_var($val);\r\n" +
1463 " elseif(preg_match(\'!^\' . $this->_svar_regexp . \'(?:\' . $this->_mod_regexp . \'*)$!\', $val)) {\r\n" +
1464 " // section var\r\n" +
1465 " return $this->_parse_section_prop($val);\r\n" +
1467 " elseif(!in_array($val, $this->_permitted_tokens) && !is_numeric($val)) {\r\n" +
1468 " // literal string\r\n" +
1469 " return $this->_expand_quoted_text(\'\"\' . $val .\'\"\');\r\n" +
1471 " return $val;\r\n" +
1475 " * expand quoted text with embedded variables\r\n" +
1477 " * @access public\r\n" +
1478 " * @param $var_expr\r\n" +
1480 " function _expand_quoted_text($var_expr)\r\n" +
1482 " // if contains unescaped $, expand it\r\n" +
1483 " if(preg_match_all(\'|(?<!\\\\\\\\)\\$\' . $this->_dvar_guts_regexp . \'|\', $var_expr, $match)) {\r\n" +
1484 " rsort($match[0]);\r\n" +
1485 " reset($match[0]);\r\n" +
1486 " foreach($match[0] as $var) {\r\n" +
1487 " $var_expr = str_replace ($var, \'\".\' . $this->_parse_var($var) . \'.\"\', $var_expr);\r\n" +
1489 " return preg_replace(\'!\\.\"\"|\"\"\\.!\', \'\', $var_expr);\r\n" +
1491 " return $var_expr;\r\n" +
1496 " * parse variable expression into PHP code\r\n" +
1498 " * @access public\r\n" +
1499 " * @param $var_expr\r\n" +
1501 " function _parse_var($var_expr)\r\n" +
1504 " preg_match(\'!(\' . $this->_obj_call_regexp . \'|\' . $this->_var_regexp . \')(\' . $this->_mod_regexp . \'*)$!\', $var_expr, $match);\r\n" +
1506 " $var_ref = substr($match[1],1);\r\n" +
1507 " $modifiers = $match[2];\r\n" +
1509 " if(!empty($this->default_modifiers) && !preg_match(\'!(^|\\|)smarty:nodefaults($|\\|)!\',$modifiers)) {\r\n" +
1510 " $_default_mod_string = implode(\'|\',(array)$this->default_modifiers);\r\n" +
1511 " $modifiers = empty($modifiers) ? $_default_mod_string : $_default_mod_string . \'|\' . $modifiers;\r\n" +
1514 " // get [foo] and .foo and ->foo() pieces \r\n" +
1515 " preg_match_all(\'!(?:^\\w+)|(?:\' . $this->_obj_ext_regexp . \')+(?:\' . $this->_obj_params_regexp . \')?|(?:\' . $this->_var_bracket_regexp . \')|\\.\\$?\\w+!\', $var_ref, $match); \r\n" +
1517 " $indexes = $match[0];\r\n" +
1518 " $var_name = array_shift($indexes);\r\n" +
1520 " /* Handle $smarty.* variable references as a special case. */\r\n" +
1521 " if ($var_name == \'smarty\') {\r\n" +
1523 " * If the reference could be compiled, use the compiled output;\r\n" +
1524 " * otherwise, fall back on the $smarty variable generated at\r\n" +
1525 " * run-time.\r\n" +
1527 " if (($smarty_ref = $this->_compile_smarty_ref($indexes)) !== null) {\r\n" +
1528 " $output = $smarty_ref;\r\n" +
1530 " $var_name = substr(array_shift($indexes), 1);\r\n" +
1531 " $output = \"\\$this->_smarty_vars[\'$var_name\']\";\r\n" +
1534 " $output = \"\\$this->_tpl_vars[\'$var_name\']\";\r\n" +
1537 " foreach ($indexes as $index) { \r\n" +
1538 " if ($index{0} == \'[\') {\r\n" +
1539 " $index = substr($index, 1, -1);\r\n" +
1540 " if (is_numeric($index)) {\r\n" +
1541 " $output .= \"[$index]\";\r\n" +
1542 " } elseif ($index{0} == \'$\') {\r\n" +
1543 " $output .= \"[\\$this->_tpl_vars[\'\" . substr($index, 1) . \"\']]\";\r\n" +
1545 " $parts = explode(\'.\', $index);\r\n" +
1546 " $section = $parts[0];\r\n" +
1547 " $section_prop = isset($parts[1]) ? $parts[1] : \'index\';\r\n" +
1548 " $output .= \"[\\$this->_sections[\'$section\'][\'$section_prop\']]\";\r\n" +
1550 " } else if ($index{0} == \'.\') {\r\n" +
1551 " if ($index{1} == \'$\')\r\n" +
1552 " $output .= \"[\\$this->_tpl_vars[\'\" . substr($index, 2) . \"\']]\";\r\n" +
1554 " $output .= \"[\'\" . substr($index, 1) . \"\']\";\r\n" +
1555 " } else if (substr($index,0,2) == \'->\') {\r\n" +
1556 " if(substr($index,2,2) == \'__\') {\r\n" +
1557 " $this->_syntax_error(\'call to internal object members is not allowed\', E_USER_ERROR, __FILE__, __LINE__);\r\n" +
1558 " } elseif($this->security && substr($index,2,1) == \'_\') {\r\n" +
1559 " $this->_syntax_error(\'(secure) call to private object member is not allowed\', E_USER_ERROR, __FILE__, __LINE__);\r\n" +
1561 " if(preg_match(\'!((?:\' . $this->_obj_ext_regexp . \')+)(\' . $this->_obj_params_regexp . \')?!\', $index, $match)) {\r\n" +
1562 " if(!empty($match[2])) {\r\n" +
1563 " // parse object parameters\r\n" +
1564 " $index = str_replace($match[2], $this->_parse_parenth_args($match[2]), $index);\r\n" +
1566 " if(preg_match_all(\'!\' . $this->_dvar_regexp . \'!\', $match[1], $_dvar_match)) {\r\n" +
1567 " // parse embedded variables\r\n" +
1568 " $_match_replace = $match[1];\r\n" +
1569 " foreach($_dvar_match[0] as $_curr_var) {\r\n" +
1570 " $_match_replace = str_replace($_curr_var, \'{\' . $this->_parse_var($_curr_var) . \'}\', $_match_replace);\r\n" +
1572 " $index = str_replace($match[1], $_match_replace, $index);\r\n" +
1575 " $output .= $index;\r\n" +
1578 " $output .= $index;\r\n" +
1582 " // look for variables imbedded in quoted strings, replace them\r\n" +
1583 " if(preg_match(\'!\' . $this->_qstr_regexp . \'!\', $output, $match)) {\r\n" +
1584 " $output = str_replace($match[0], $this->_expand_quoted_text($match[0]), $output);\r\n" +
1587 " $this->_parse_modifiers($output, $modifiers);\r\n" +
1589 " return $output;\r\n" +
1593 " * parse arguments in function call parenthesis\r\n" +
1595 " * @access public\r\n" +
1596 " * @param $parenth_args\r\n" +
1598 " function _parse_parenth_args($parenth_args)\r\n" +
1600 " preg_match_all(\'!\' . $this->_param_regexp . \'!\',$parenth_args, $match);\r\n" +
1601 " $match = $match[0];\r\n" +
1602 " rsort($match);\r\n" +
1603 " reset($match); \r\n" +
1604 " $orig_vals = $match;\r\n" +
1605 " $this->_parse_vars_props($match);\r\n" +
1606 " return str_replace($orig_vals, $match, $parenth_args);\r\n" +
1610 " * parse configuration variable expression into PHP code\r\n" +
1612 " * @access public\r\n" +
1613 " * @param $conf_var_expr\r\n" +
1615 " function _parse_conf_var($conf_var_expr)\r\n" +
1617 " $parts = explode(\'|\', $conf_var_expr, 2);\r\n" +
1618 " $var_ref = $parts[0];\r\n" +
1619 " $modifiers = isset($parts[1]) ? $parts[1] : \'\';\r\n" +
1621 " $var_name = substr($var_ref, 1, -1);\r\n" +
1623 " $output = \"\\$this->_config[0][\'vars\'][\'$var_name\']\";\r\n" +
1625 " $this->_parse_modifiers($output, $modifiers);\r\n" +
1627 " return $output;\r\n" +
1632 " * parse section property expression into PHP code\r\n" +
1634 " * @access public\r\n" +
1635 " * @param $section_prop_expr\r\n" +
1637 " function _parse_section_prop($section_prop_expr)\r\n" +
1639 " $parts = explode(\'|\', $section_prop_expr, 2);\r\n" +
1640 " $var_ref = $parts[0];\r\n" +
1641 " $modifiers = isset($parts[1]) ? $parts[1] : \'\';\r\n" +
1643 " preg_match(\'!%(\\w+)\\.(\\w+)%!\', $var_ref, $match);\r\n" +
1644 " $section_name = $match[1];\r\n" +
1645 " $prop_name = $match[2];\r\n" +
1647 " $output = \"\\$this->_sections[\'$section_name\'][\'$prop_name\']\";\r\n" +
1649 " $this->_parse_modifiers($output, $modifiers);\r\n" +
1651 " return $output;\r\n" +
1656 " * parse modifier chain into PHP code\r\n" +
1658 " * @access public\r\n" +
1659 " * @param $output\r\n" +
1660 " * @param $modifier_string\r\n" +
1662 " function _parse_modifiers(&$output, $modifier_string)\r\n" +
1664 " preg_match_all(\'!\\|(@?\\w+)((?>:(?:\'. $this->_qstr_regexp . \'|[^|]+))*)!\', \'|\' . $modifier_string, $match);\r\n" +
1665 " list(, $modifiers, $modifier_arg_strings) = $match;\r\n" +
1667 " for ($i = 0, $for_max = count($modifiers); $i < $for_max; $i++) {\r\n" +
1668 " $modifier_name = $modifiers[$i];\r\n" +
1670 " if($modifier_name == \'smarty\') {\r\n" +
1671 " // skip smarty modifier\r\n" +
1675 " preg_match_all(\'!:(\' . $this->_qstr_regexp . \'|[^:]+)!\', $modifier_arg_strings[$i], $match);\r\n" +
1676 " $modifier_args = $match[1];\r\n" +
1678 " if ($modifier_name{0} == \'@\') {\r\n" +
1679 " $map_array = \'false\';\r\n" +
1680 " $modifier_name = substr($modifier_name, 1);\r\n" +
1682 " $map_array = \'true\';\r\n" +
1685 " $this->_add_plugin(\'modifier\', $modifier_name);\r\n" +
1687 " $this->_parse_vars_props($modifier_args);\r\n" +
1689 " if (count($modifier_args) > 0)\r\n" +
1690 " $modifier_args = \', \'.implode(\', \', $modifier_args);\r\n" +
1692 " $modifier_args = \'\';\r\n" +
1694 " $output = \"\\$this->_run_mod_handler(\'$modifier_name\', $map_array, $output$modifier_args)\";\r\n" +
1700 " * add plugin\r\n" +
1702 " * @access public\r\n" +
1703 " * @param $type\r\n" +
1704 " * @param $name\r\n" +
1705 " * @param $delayed_loading\r\n" +
1707 " function _add_plugin($type, $name, $delayed_loading = null)\r\n" +
1709 " if (!isset($this->_plugin_info[$type])) {\r\n" +
1710 " $this->_plugin_info[$type] = array();\r\n" +
1712 " if (!isset($this->_plugin_info[$type][$name])) {\r\n" +
1713 " $this->_plugin_info[$type][$name] = array($this->_current_file,\r\n" +
1714 " $this->_current_line_no,\r\n" +
1715 " $delayed_loading);\r\n" +
1721 " * Compiles references of type $smarty.foo\r\n" +
1723 " * @access public\r\n" +
1724 " * @param $indexes\r\n" +
1726 " function _compile_smarty_ref(&$indexes)\r\n" +
1728 " /* Extract the reference name. */\r\n" +
1729 " $ref = substr($indexes[0], 1);\r\n" +
1731 " switch ($ref) {\r\n" +
1732 " case \'now\':\r\n" +
1733 " $compiled_ref = \'time()\';\r\n" +
1734 " if (count($indexes) > 1) {\r\n" +
1735 " $this->_syntax_error(\'$smarty\' . implode(\'\', $indexes) .\' is an invalid reference\', E_USER_ERROR, __FILE__, __LINE__);\r\n" +
1739 " case \'foreach\':\r\n" +
1740 " case \'section\':\r\n" +
1741 " if ($indexes[1]{0} != \'.\') {\r\n" +
1742 " $this->_syntax_error(\'$smarty\' . implode(\'\', array_slice($indexes, 0, 2)) . \' is an invalid reference\', E_USER_ERROR, __FILE__, __LINE__);\r\n" +
1744 " $name = substr($indexes[1], 1);\r\n" +
1745 " array_shift($indexes);\r\n" +
1746 " if ($ref == \'foreach\')\r\n" +
1747 " $compiled_ref = \"\\$this->_foreach[\'$name\']\";\r\n" +
1749 " $compiled_ref = \"\\$this->_sections[\'$name\']\";\r\n" +
1752 " case \'get\':\r\n" +
1753 " array_shift($indexes);\r\n" +
1754 " $compiled_ref = \"\\$_GET\";\r\n" +
1755 " if ($name = substr($indexes[0], 1))\r\n" +
1756 " $compiled_ref .= \"[\'$name\']\";\r\n" +
1759 " case \'post\':\r\n" +
1760 " array_shift($indexes);\r\n" +
1761 " $name = substr($indexes[0], 1);\r\n" +
1762 " $compiled_ref = \"\\$_POST\";\r\n" +
1763 " if ($name = substr($indexes[0], 1))\r\n" +
1764 " $compiled_ref .= \"[\'$name\']\";\r\n" +
1767 " case \'cookies\':\r\n" +
1768 " array_shift($indexes);\r\n" +
1769 " $name = substr($indexes[0], 1);\r\n" +
1770 " $compiled_ref = \"\\$_COOKIE\";\r\n" +
1771 " if ($name = substr($indexes[0], 1))\r\n" +
1772 " $compiled_ref .= \"[\'$name\']\";\r\n" +
1775 " case \'env\':\r\n" +
1776 " array_shift($indexes);\r\n" +
1777 " $compiled_ref = \"\\$_ENV\";\r\n" +
1778 " if ($name = substr($indexes[0], 1))\r\n" +
1779 " $compiled_ref .= \"[\'$name\']\";\r\n" +
1782 " case \'server\':\r\n" +
1783 " array_shift($indexes);\r\n" +
1784 " $name = substr($indexes[0], 1);\r\n" +
1785 " $compiled_ref = \"\\$_SERVER\";\r\n" +
1786 " if ($name = substr($indexes[0], 1))\r\n" +
1787 " $compiled_ref .= \"[\'$name\']\";\r\n" +
1790 " case \'session\':\r\n" +
1791 " array_shift($indexes);\r\n" +
1792 " $name = substr($indexes[0], 1);\r\n" +
1793 " $compiled_ref = \"\\$_SESSION\";\r\n" +
1794 " if ($name = substr($indexes[0], 1))\r\n" +
1795 " $compiled_ref .= \"[\'$name\']\";\r\n" +
1799 " * These cases are handled either at run-time or elsewhere in the\r\n" +
1800 " * compiler.\r\n" +
1802 " case \'request\':\r\n" +
1803 " $this->_init_smarty_vars = true;\r\n" +
1804 " return null;\r\n" +
1806 " case \'capture\':\r\n" +
1807 " return null;\r\n" +
1809 " case \'template\':\r\n" +
1810 " $compiled_ref = \"\'$this->_current_file\'\";\r\n" +
1811 " if (count($indexes) > 1) {\r\n" +
1812 " $this->_syntax_error(\'$smarty\' . implode(\'\', $indexes) .\' is an invalid reference\', E_USER_ERROR, __FILE__, __LINE__);\r\n" +
1816 " case \'version\':\r\n" +
1817 " $compiled_ref = \"\'$this->_version\'\";\r\n" +
1820 " case \'const\':\r\n" +
1821 " array_shift($indexes);\r\n" +
1822 " $compiled_ref = \'defined(\\\'\' . substr($indexes[0],1) . \'\\\') ? \' . substr($indexes[0],1) . \' : null\';\r\n" +
1826 " $this->_syntax_error(\'$smarty.\' . $ref . \' is an unknown reference\', E_USER_ERROR, __FILE__, __LINE__);\r\n" +
1830 " array_shift($indexes);\r\n" +
1831 " return $compiled_ref;\r\n" +
1836 " * load pre- and post-filters\r\n" +
1838 " * @access public\r\n" +
1840 " function _load_filters()\r\n" +
1842 " if (count($this->_plugins[\'prefilter\']) > 0) {\r\n" +
1843 " foreach ($this->_plugins[\'prefilter\'] as $filter_name => $prefilter) {\r\n" +
1844 " if ($prefilter === false) {\r\n" +
1845 " unset($this->_plugins[\'prefilter\'][$filter_name]);\r\n" +
1846 " $this->_load_plugins(array(array(\'prefilter\', $filter_name, null, null, false)));\r\n" +
1850 " if (count($this->_plugins[\'postfilter\']) > 0) {\r\n" +
1851 " foreach ($this->_plugins[\'postfilter\'] as $filter_name => $postfilter) {\r\n" +
1852 " if ($postfilter === false) {\r\n" +
1853 " unset($this->_plugins[\'postfilter\'][$filter_name]);\r\n" +
1854 " $this->_load_plugins(array(array(\'postfilter\', $filter_name, null, null, false)));\r\n" +
1862 " * display Smarty syntax error\r\n" +
1864 " * @access public\r\n" +
1865 " * @param $error_msg\r\n" +
1866 " * @param $error_type\r\n" +
1867 " * @param $file\r\n" +
1868 " * @param $line\r\n" +
1870 " function _syntax_error($error_msg, $error_type = E_USER_ERROR, $file=null, $line=null)\r\n" +
1872 " if(isset($file) && isset($line)) {\r\n" +
1873 " $info = \' (\'.basename($file).\", line $line)\";\r\n" +
1875 " $info = null;\r\n" +
1877 " trigger_error(\'Smarty: [in \' . $this->_current_file . \' line \' .\r\n" +
1878 " $this->_current_line_no . \"]: syntax error: $error_msg$info\", $error_type);\r\n" +
1883 " * compare to values by their string length\r\n" +
1885 " * @access private\r\n" +
1886 " * @param $a\r\n" +
1887 " * @param $b\r\n" +
1889 "function _smarty_sort_length($a, $b)\r\n" +
1891 " if($a == $b)\r\n" +
1894 " if(strlen($a) == strlen($b))\r\n" +
1895 " return ($a > $b) ? -1 : 1;\r\n" +
1897 " return (strlen($a) > strlen($b)) ? -1 : 1;\r\n" +
1901 "/* vim: set et: */\r\n" +