Code

cde968d09a14c70c2d5c554a32f18a17599d203b
[gosa.git] / gosa-core / include / smarty / sysplugins / smarty_internal_templatecompilerbase.php
1 <?php\r
2 /**\r
3  * Smarty Internal Plugin Smarty Template Compiler Base\r
4  *\r
5  * This file contains the basic classes and methodes for compiling Smarty templates with lexer/parser\r
6  *\r
7  * @package Smarty\r
8  * @subpackage Compiler\r
9  * @author Uwe Tews\r
10  */\r
11 \r
12 /**\r
13  * Main abstract compiler class\r
14  *\r
15  * @package Smarty\r
16  * @subpackage Compiler\r
17  */\r
18 abstract class Smarty_Internal_TemplateCompilerBase {\r
19 \r
20     /**\r
21      * hash for nocache sections\r
22      *\r
23      * @var mixed\r
24      */\r
25     private $nocache_hash = null;\r
26     /**\r
27      * suppress generation of nocache code\r
28      *\r
29      * @var bool\r
30      */\r
31     public $suppressNocacheProcessing = false;\r
32     /**\r
33      * suppress generation of merged template code\r
34      *\r
35      * @var bool\r
36      */\r
37     public $suppressMergedTemplates = false;\r
38     /**\r
39      * compile tag objects\r
40      *\r
41      * @var array\r
42      */\r
43     public static $_tag_objects = array();\r
44     /**\r
45      * tag stack\r
46      *\r
47      * @var array\r
48      */\r
49     public $_tag_stack = array();\r
50     /**\r
51      * current template\r
52      *\r
53      * @var Smarty_Internal_Template\r
54      */\r
55     public $template = null;\r
56     /**\r
57      * merged templates\r
58      *\r
59      * @var array\r
60      */\r
61     public $merged_templates = array();\r
62     /**\r
63      * flag when compiling {block}\r
64      *\r
65      * @var bool\r
66      */\r
67     public $inheritance = false;\r
68     /**\r
69      * plugins loaded by default plugin handler\r
70      *\r
71      * @var array\r
72      */\r
73     public $default_handler_plugins = array();\r
74     /**\r
75      * saved preprocessed modifier list\r
76      *\r
77      * @var mixed\r
78      */\r
79     public $default_modifier_list = null;\r
80     /**\r
81      * force compilation of complete template as nocache\r
82      * @var boolean\r
83      */\r
84     public $forceNocache = false;\r
85     /**\r
86      * suppress Smarty header code in compiled template\r
87      * @var bool\r
88      */\r
89     public $suppressHeader = false;\r
90     /**\r
91      * suppress template property header code in compiled template\r
92      * @var bool\r
93      */\r
94     public $suppressTemplatePropertyHeader = false;\r
95     /**\r
96      * flag if compiled template file shall we written\r
97      * @var bool\r
98      */\r
99     public $write_compiled_code = true;\r
100     /**\r
101      * flag if currently a template function is compiled\r
102      * @var bool\r
103      */\r
104     public $compiles_template_function = false;\r
105     /**\r
106      * called subfuntions from template function\r
107      * @var array\r
108      */\r
109     public $called_functions = array();\r
110     /**\r
111      * flags for used modifier plugins\r
112      * @var array\r
113      */\r
114     public $modifier_plugins = array();\r
115 \r
116     /**\r
117      * Initialize compiler\r
118      */\r
119     public function __construct()\r
120     {\r
121         $this->nocache_hash = str_replace('.', '-', uniqid(rand(), true));\r
122     }\r
123 \r
124     /**\r
125      * Method to compile a Smarty template\r
126      *\r
127      * @param  Smarty_Internal_Template $template template object to compile\r
128      * @return bool true if compiling succeeded, false if it failed\r
129      */\r
130     public function compileTemplate(Smarty_Internal_Template $template)\r
131     {\r
132         if (empty($template->properties['nocache_hash'])) {\r
133             $template->properties['nocache_hash'] = $this->nocache_hash;\r
134         } else {\r
135             $this->nocache_hash = $template->properties['nocache_hash'];\r
136         }\r
137         // flag for nochache sections\r
138         $this->nocache = false;\r
139         $this->tag_nocache = false;\r
140         // save template object in compiler class\r
141         $this->template = $template;\r
142         // reset has noche code flag\r
143         $this->template->has_nocache_code = false; \r
144         $this->smarty->_current_file = $saved_filepath = $this->template->source->filepath;\r
145         // template header code\r
146         $template_header = '';\r
147         if (!$this->suppressHeader) {\r
148             $template_header .= "<?php /* Smarty version " . Smarty::SMARTY_VERSION . ", created on " . strftime("%Y-%m-%d %H:%M:%S") . "\n";\r
149             $template_header .= "         compiled from \"" . $this->template->source->filepath . "\" */ ?>\n";\r
150         }\r
151 \r
152         do {\r
153             // flag for aborting current and start recompile\r
154             $this->abort_and_recompile = false;\r
155             // get template source\r
156             $_content = $template->source->content;\r
157             // run prefilter if required\r
158             if (isset($this->smarty->autoload_filters['pre']) || isset($this->smarty->registered_filters['pre'])) {\r
159                 $template->source->content = $_content = Smarty_Internal_Filter_Handler::runFilter('pre', $_content, $template);\r
160             }\r
161             // on empty template just return header\r
162             if ($_content == '') {\r
163                 if ($this->suppressTemplatePropertyHeader) {\r
164                     $code = '';\r
165                 } else {\r
166                     $code = $template_header . $template->createTemplateCodeFrame();\r
167                 }\r
168                 return $code;\r
169             }\r
170             // call compiler\r
171             $_compiled_code = $this->doCompile($_content);\r
172         } while ($this->abort_and_recompile);\r
173         $this->template->source->filepath = $saved_filepath;\r
174         // free memory\r
175         unset($this->parser->root_buffer, $this->parser->current_buffer, $this->parser, $this->lex, $this->template);\r
176         self::$_tag_objects = array();\r
177         // return compiled code to template object\r
178         $merged_code = '';\r
179         if (!$this->suppressMergedTemplates) {\r
180             foreach ($this->merged_templates as $code) {\r
181                 $merged_code .= $code;\r
182             }\r
183         }\r
184         if ($this->suppressTemplatePropertyHeader) {\r
185             $code = $_compiled_code . $merged_code;\r
186         } else {\r
187             $code = $template_header . $template->createTemplateCodeFrame($_compiled_code) . $merged_code;\r
188         }\r
189         // run postfilter if required\r
190         if (isset($this->smarty->autoload_filters['post']) || isset($this->smarty->registered_filters['post'])) {\r
191             $code = Smarty_Internal_Filter_Handler::runFilter('post', $code, $template);\r
192         }\r
193         return $code;\r
194     }\r
195 \r
196     /**\r
197      * Compile Tag\r
198      *\r
199      * This is a call back from the lexer/parser\r
200      * It executes the required compile plugin for the Smarty tag\r
201      *\r
202      * @param string $tag       tag name\r
203      * @param array  $args      array with tag attributes\r
204      * @param array  $parameter array with compilation parameter\r
205      * @return string compiled code\r
206      */\r
207     public function compileTag($tag, $args, $parameter = array())\r
208     {\r
209         // $args contains the attributes parsed and compiled by the lexer/parser\r
210         // assume that tag does compile into code, but creates no HTML output\r
211         $this->has_code = true;\r
212         $this->has_output = false;\r
213         // log tag/attributes\r
214         if (isset($this->smarty->get_used_tags) && $this->smarty->get_used_tags) {\r
215             $this->template->used_tags[] = array($tag, $args);\r
216         }\r
217         // check nocache option flag\r
218         if (in_array("'nocache'",$args) || in_array(array('nocache'=>'true'),$args)\r
219         || in_array(array('nocache'=>'"true"'),$args) || in_array(array('nocache'=>"'true'"),$args)) {\r
220             $this->tag_nocache = true;\r
221         }\r
222         // compile the smarty tag (required compile classes to compile the tag are autoloaded)\r
223         if (($_output = $this->callTagCompiler($tag, $args, $parameter)) === false) {\r
224             if (isset($this->smarty->template_functions[$tag])) {\r
225                 // template defined by {template} tag\r
226                 $args['_attr']['name'] = "'" . $tag . "'";\r
227                 $_output = $this->callTagCompiler('call', $args, $parameter);\r
228             }\r
229         }\r
230         if ($_output !== false) {\r
231             if ($_output !== true) {\r
232                 // did we get compiled code\r
233                 if ($this->has_code) {\r
234                     // Does it create output?\r
235                     if ($this->has_output) {\r
236                         $_output .= "\n";\r
237                     }\r
238                     // return compiled code\r
239                     return $_output;\r
240                 }\r
241             }\r
242             // tag did not produce compiled code\r
243             return '';\r
244         } else {\r
245             // map_named attributes\r
246             if (isset($args['_attr'])) {\r
247                 foreach ($args['_attr'] as $key => $attribute) {\r
248                     if (is_array($attribute)) {\r
249                         $args = array_merge($args, $attribute);\r
250                     }\r
251                 }\r
252             }\r
253             // not an internal compiler tag\r
254             if (strlen($tag) < 6 || substr($tag, -5) != 'close') {\r
255                 // check if tag is a registered object\r
256                 if (isset($this->smarty->registered_objects[$tag]) && isset($parameter['object_methode'])) {\r
257                     $methode = $parameter['object_methode'];\r
258                     if (!in_array($methode, $this->smarty->registered_objects[$tag][3]) &&\r
259                     (empty($this->smarty->registered_objects[$tag][1]) || in_array($methode, $this->smarty->registered_objects[$tag][1]))) {\r
260                         return $this->callTagCompiler('private_object_function', $args, $parameter, $tag, $methode);\r
261                     } elseif (in_array($methode, $this->smarty->registered_objects[$tag][3])) {\r
262                         return $this->callTagCompiler('private_object_block_function', $args, $parameter, $tag, $methode);\r
263                     } else {\r
264                         return $this->trigger_template_error ('unallowed methode "' . $methode . '" in registered object "' . $tag . '"', $this->lex->taglineno);\r
265                     }\r
266                 }\r
267                 // check if tag is registered\r
268                 foreach (array(Smarty::PLUGIN_COMPILER, Smarty::PLUGIN_FUNCTION, Smarty::PLUGIN_BLOCK) as $plugin_type) {\r
269                     if (isset($this->smarty->registered_plugins[$plugin_type][$tag])) {\r
270                         // if compiler function plugin call it now\r
271                         if ($plugin_type == Smarty::PLUGIN_COMPILER) {\r
272                             $new_args = array();\r
273                             foreach ($args as $key => $mixed) {\r
274                                 if (is_array($mixed)) {\r
275                                         $new_args = array_merge($new_args, $mixed);\r
276                                 } else {\r
277                                         $new_args[$key] = $mixed;\r
278                                 }\r
279                             }\r
280                             if (!$this->smarty->registered_plugins[$plugin_type][$tag][1]) {\r
281                                 $this->tag_nocache = true;\r
282                             }\r
283                             $function = $this->smarty->registered_plugins[$plugin_type][$tag][0];\r
284                             if (!is_array($function)) {\r
285                                 return $function($new_args, $this);\r
286                             } else if (is_object($function[0])) {\r
287                                 return $this->smarty->registered_plugins[$plugin_type][$tag][0][0]->$function[1]($new_args, $this);\r
288                             } else {\r
289                                 return call_user_func_array($function, array($new_args, $this));\r
290                             }\r
291                         }\r
292                         // compile registered function or block function\r
293                         if ($plugin_type == Smarty::PLUGIN_FUNCTION || $plugin_type == Smarty::PLUGIN_BLOCK) {\r
294                             return $this->callTagCompiler('private_registered_' . $plugin_type, $args, $parameter, $tag);\r
295                         }\r
296 \r
297                     }\r
298                 }\r
299                 // check plugins from plugins folder\r
300                 foreach ($this->smarty->plugin_search_order as $plugin_type) {\r
301                     if ($plugin_type == Smarty::PLUGIN_BLOCK && $this->smarty->loadPlugin('smarty_compiler_' . $tag) && (!isset($this->smarty->security_policy) || $this->smarty->security_policy->isTrustedTag($tag, $this))) {\r
302                         $plugin = 'smarty_compiler_' . $tag;\r
303                         if (is_callable($plugin)) {\r
304                             // convert arguments format for old compiler plugins\r
305                             $new_args = array();\r
306                             foreach ($args as $key => $mixed) {\r
307                                 if (is_array($mixed)) {\r
308                                         $new_args = array_merge($new_args, $mixed);\r
309                                 } else {\r
310                                         $new_args[$key] = $mixed;\r
311                                 }\r
312                             }\r
313                             return $plugin($new_args, $this->smarty);\r
314                         }\r
315                         if (class_exists($plugin, false)) {\r
316                             $plugin_object = new $plugin;\r
317                             if (method_exists($plugin_object, 'compile')) {\r
318                                 return $plugin_object->compile($args, $this);\r
319                             }\r
320                         }\r
321                         throw new SmartyException("Plugin \"{$tag}\" not callable");\r
322                     } else {\r
323                         if ($function = $this->getPlugin($tag, $plugin_type)) {\r
324                             if(!isset($this->smarty->security_policy) || $this->smarty->security_policy->isTrustedTag($tag, $this)) {\r
325                                 return $this->callTagCompiler('private_' . $plugin_type . '_plugin', $args, $parameter, $tag, $function);\r
326                             }\r
327                         }\r
328                     }\r
329                 }\r
330                 if (is_callable($this->smarty->default_plugin_handler_func)) {\r
331                     $found = false;\r
332                     // look for already resolved tags\r
333                     foreach ($this->smarty->plugin_search_order as $plugin_type) {\r
334                         if (isset($this->default_handler_plugins[$plugin_type][$tag])) {\r
335                             $found = true;\r
336                             break;\r
337                         }\r
338                     }\r
339                     if (!$found) {\r
340                         // call default handler\r
341                         foreach ($this->smarty->plugin_search_order as $plugin_type) {\r
342                             if ($this->getPluginFromDefaultHandler($tag, $plugin_type)) {\r
343                                 $found = true;\r
344                                 break;\r
345                             }\r
346                         }\r
347                     }\r
348                     if ($found) {\r
349                         // if compiler function plugin call it now\r
350                         if ($plugin_type == Smarty::PLUGIN_COMPILER) {\r
351                             $new_args = array();\r
352                             foreach ($args as $mixed) {\r
353                                 $new_args = array_merge($new_args, $mixed);\r
354                             }\r
355                             $function = $this->default_handler_plugins[$plugin_type][$tag][0];\r
356                             if (!is_array($function)) {\r
357                                 return $function($new_args, $this);\r
358                             } else if (is_object($function[0])) {\r
359                                 return $this->default_handler_plugins[$plugin_type][$tag][0][0]->$function[1]($new_args, $this);\r
360                             } else {\r
361                                 return call_user_func_array($function, array($new_args, $this));\r
362                             }\r
363                         } else {\r
364                             return $this->callTagCompiler('private_registered_' . $plugin_type, $args, $parameter, $tag);\r
365                         }\r
366                     }\r
367                 }\r
368             } else {\r
369                 // compile closing tag of block function\r
370                 $base_tag = substr($tag, 0, -5);\r
371                 // check if closing tag is a registered object\r
372                 if (isset($this->smarty->registered_objects[$base_tag]) && isset($parameter['object_methode'])) {\r
373                     $methode = $parameter['object_methode'];\r
374                     if (in_array($methode, $this->smarty->registered_objects[$base_tag][3])) {\r
375                         return $this->callTagCompiler('private_object_block_function', $args, $parameter, $tag, $methode);\r
376                     } else {\r
377                         return $this->trigger_template_error ('unallowed closing tag methode "' . $methode . '" in registered object "' . $base_tag . '"', $this->lex->taglineno);\r
378                     }\r
379                 }\r
380                 // registered block tag ?\r
381                 if (isset($this->smarty->registered_plugins[Smarty::PLUGIN_BLOCK][$base_tag]) || isset($this->default_handler_plugins[Smarty::PLUGIN_BLOCK][$base_tag])) {\r
382                     return $this->callTagCompiler('private_registered_block', $args, $parameter, $tag);\r
383                 }\r
384                 // block plugin?\r
385                 if ($function = $this->getPlugin($base_tag, Smarty::PLUGIN_BLOCK)) {\r
386                     return $this->callTagCompiler('private_block_plugin', $args, $parameter, $tag, $function);\r
387                 }\r
388                 if ($this->smarty->loadPlugin('smarty_compiler_' . $tag)) {\r
389                     $plugin = 'smarty_compiler_' . $tag;\r
390                     if (is_callable($plugin)) {\r
391                         return $plugin($args, $this->smarty);\r
392                     }\r
393                     if (class_exists($plugin, false)) {\r
394                         $plugin_object = new $plugin;\r
395                         if (method_exists($plugin_object, 'compile')) {\r
396                             return $plugin_object->compile($args, $this);\r
397                         }\r
398                     }\r
399                     throw new SmartyException("Plugin \"{$tag}\" not callable");\r
400                 }\r
401             }\r
402             $this->trigger_template_error ("unknown tag \"" . $tag . "\"", $this->lex->taglineno);\r
403         }\r
404     }\r
405 \r
406     /**\r
407      * lazy loads internal compile plugin for tag and calls the compile methode\r
408      *\r
409      * compile objects cached for reuse.\r
410      * class name format:  Smarty_Internal_Compile_TagName\r
411      * plugin filename format: Smarty_Internal_Tagname.php\r
412      *\r
413      * @param string $tag   tag name\r
414      * @param array $args   list of tag attributes\r
415      * @param mixed $param1 optional parameter\r
416      * @param mixed $param2 optional parameter\r
417      * @param mixed $param3 optional parameter\r
418      * @return string compiled code\r
419      */\r
420     public function callTagCompiler($tag, $args, $param1 = null, $param2 = null, $param3 = null)\r
421     {\r
422         // re-use object if already exists\r
423         if (isset(self::$_tag_objects[$tag])) {\r
424             // compile this tag\r
425             return self::$_tag_objects[$tag]->compile($args, $this, $param1, $param2, $param3);\r
426         }\r
427         // lazy load internal compiler plugin\r
428         $class_name = 'Smarty_Internal_Compile_' . $tag;\r
429         if ($this->smarty->loadPlugin($class_name)) {\r
430             // check if tag allowed by security\r
431             if (!isset($this->smarty->security_policy) || $this->smarty->security_policy->isTrustedTag($tag, $this)) {\r
432             // use plugin if found\r
433             self::$_tag_objects[$tag] = new $class_name;\r
434             // compile this tag\r
435             return self::$_tag_objects[$tag]->compile($args, $this, $param1, $param2, $param3);\r
436             }\r
437         }\r
438         // no internal compile plugin for this tag\r
439         return false;\r
440     }\r
441 \r
442     /**\r
443      * Check for plugins and return function name\r
444      *\r
445      * @param string $pugin_name  name of plugin or function\r
446      * @param string $plugin_type type of plugin\r
447      * @return string call name of function\r
448      */\r
449     public function getPlugin($plugin_name, $plugin_type)\r
450     {\r
451         $function = null;\r
452         if ($this->template->caching && ($this->nocache || $this->tag_nocache)) {\r
453             if (isset($this->template->required_plugins['nocache'][$plugin_name][$plugin_type])) {\r
454                 $function = $this->template->required_plugins['nocache'][$plugin_name][$plugin_type]['function'];\r
455             } else if (isset($this->template->required_plugins['compiled'][$plugin_name][$plugin_type])) {\r
456                 $this->template->required_plugins['nocache'][$plugin_name][$plugin_type] = $this->template->required_plugins['compiled'][$plugin_name][$plugin_type];\r
457                 $function = $this->template->required_plugins['nocache'][$plugin_name][$plugin_type]['function'];\r
458             }\r
459         } else {\r
460             if (isset($this->template->required_plugins['compiled'][$plugin_name][$plugin_type])) {\r
461                 $function = $this->template->required_plugins['compiled'][$plugin_name][$plugin_type]['function'];\r
462             } else if (isset($this->template->required_plugins['nocache'][$plugin_name][$plugin_type])) {\r
463                 $this->template->required_plugins['compiled'][$plugin_name][$plugin_type] = $this->template->required_plugins['nocache'][$plugin_name][$plugin_type];\r
464                 $function = $this->template->required_plugins['compiled'][$plugin_name][$plugin_type]['function'];\r
465             }\r
466         }\r
467         if (isset($function)) {\r
468             if ($plugin_type == 'modifier') {\r
469                 $this->modifier_plugins[$plugin_name] = true;\r
470             }\r
471             return $function;\r
472         }\r
473         // loop through plugin dirs and find the plugin\r
474         $function = 'smarty_' . $plugin_type . '_' . $plugin_name;\r
475         $file = $this->smarty->loadPlugin($function, false);\r
476 \r
477         if (is_string($file)) {\r
478             if ($this->template->caching && ($this->nocache || $this->tag_nocache)) {\r
479                 $this->template->required_plugins['nocache'][$plugin_name][$plugin_type]['file'] = $file;\r
480                 $this->template->required_plugins['nocache'][$plugin_name][$plugin_type]['function'] = $function;\r
481             } else {\r
482                 $this->template->required_plugins['compiled'][$plugin_name][$plugin_type]['file'] = $file;\r
483                 $this->template->required_plugins['compiled'][$plugin_name][$plugin_type]['function'] = $function;\r
484             }\r
485             if ($plugin_type == 'modifier') {\r
486                 $this->modifier_plugins[$plugin_name] = true;\r
487             }\r
488             return $function;\r
489         }\r
490         if (is_callable($function)) {\r
491             // plugin function is defined in the script\r
492             return $function;\r
493         }\r
494         return false;\r
495     }\r
496 \r
497     /**\r
498      * Check for plugins by default plugin handler\r
499      *\r
500      * @param string $tag         name of tag\r
501      * @param string $plugin_type type of plugin\r
502      * @return boolean true if found\r
503      */\r
504     public function getPluginFromDefaultHandler($tag, $plugin_type)\r
505     {\r
506         $callback = null;\r
507         $script = null;\r
508         $result = call_user_func_array(\r
509             $this->smarty->default_plugin_handler_func,\r
510             array($tag, $plugin_type, $this->template, &$callback, &$script)\r
511         );\r
512         if ($result) {\r
513             if ($script !== null) {\r
514                 if (is_file($script)) {\r
515                     if ($this->template->caching && ($this->nocache || $this->tag_nocache)) {\r
516                         $this->template->required_plugins['nocache'][$tag][$plugin_type]['file'] = $script;\r
517                         $this->template->required_plugins['nocache'][$tag][$plugin_type]['function'] = $callback;\r
518                     } else {\r
519                         $this->template->required_plugins['compiled'][$tag][$plugin_type]['file'] = $script;\r
520                         $this->template->required_plugins['compiled'][$tag][$plugin_type]['function'] = $callback;\r
521                     }\r
522                     include_once $script;\r
523                 }  else {\r
524                     throw new SmartyCompilerException("Plugin or modifer script file $script not found");\r
525                 }\r
526             }\r
527             if (is_callable($callback)) {\r
528                 $this->default_handler_plugins[$plugin_type][$tag] = array($callback, true, array());\r
529                 return true;\r
530             } else {\r
531                 throw new SmartyCompilerException("Function for plugin or modifier $tag not callable");\r
532             }\r
533         }\r
534         return false;\r
535     }\r
536 \r
537     /**\r
538      * Inject inline code for nocache template sections\r
539      *\r
540      * This method gets the content of each template element from the parser.\r
541      * If the content is compiled code and it should be not cached the code is injected\r
542      * into the rendered output.\r
543      *\r
544      * @param string  $content content of template element\r
545      * @param boolean $is_code true if content is compiled code\r
546      * @return string content\r
547      */\r
548     public function processNocacheCode($content, $is_code)\r
549     {\r
550         // If the template is not evaluated and we have a nocache section and or a nocache tag\r
551         if ($is_code && !empty($content)) {\r
552             // generate replacement code\r
553             if ((!($this->template->source->recompiled) || $this->forceNocache) && $this->template->caching && !$this->suppressNocacheProcessing &&\r
554             ($this->nocache || $this->tag_nocache || $this->forceNocache == 2)) {\r
555                 $this->template->has_nocache_code = true;\r
556                 $_output = str_replace("'", "\'", $content);\r
557                 $_output = str_replace('\\\\', '\\\\\\\\', $_output);\r
558                 $_output = str_replace("^#^", "'", $_output);\r
559                 $_output = "<?php echo '/*%%SmartyNocache:{$this->nocache_hash}%%*/" . $_output . "/*/%%SmartyNocache:{$this->nocache_hash}%%*/';?>\n";\r
560                 // make sure we include modifer plugins for nocache code\r
561                 foreach ($this->modifier_plugins as $plugin_name => $dummy) {\r
562                     if (isset($this->template->required_plugins['compiled'][$plugin_name]['modifier'])) {\r
563                         $this->template->required_plugins['nocache'][$plugin_name]['modifier'] = $this->template->required_plugins['compiled'][$plugin_name]['modifier'];\r
564                     }\r
565                 }\r
566             } else {\r
567                 $_output = $content;\r
568             }\r
569         } else {\r
570             $_output = $content;\r
571         }\r
572         $this->suppressNocacheProcessing = false;\r
573         $this->tag_nocache = false;\r
574         return $_output;\r
575     }\r
576 \r
577     /**\r
578      * display compiler error messages without dying\r
579      *\r
580      * If parameter $args is empty it is a parser detected syntax error.\r
581      * In this case the parser is called to obtain information about expected tokens.\r
582      *\r
583      * If parameter $args contains a string this is used as error message\r
584      *\r
585      * @param string $args individual error message or null\r
586      * @param string $line line-number\r
587      * @throws SmartyCompilerException when an unexpected token is found\r
588      */\r
589     public function trigger_template_error($args = null, $line = null)\r
590     {\r
591         // get template source line which has error\r
592         if (!isset($line)) {\r
593             $line = $this->lex->line;\r
594         }\r
595         $match = preg_split("/\n/", $this->lex->data);\r
596         $error_text = 'Syntax Error in template "' . $this->template->source->filepath . '"  on line ' . $line . ' "' . htmlspecialchars(trim(preg_replace('![\t\r\n]+!',' ',$match[$line-1]))) . '" ';\r
597         if (isset($args)) {\r
598             // individual error message\r
599             $error_text .= $args;\r
600         } else {\r
601             // expected token from parser\r
602             $error_text .= ' - Unexpected "' . $this->lex->value.'"';\r
603             if (count($this->parser->yy_get_expected_tokens($this->parser->yymajor)) <= 4 ) {\r
604                 foreach ($this->parser->yy_get_expected_tokens($this->parser->yymajor) as $token) {\r
605                     $exp_token = $this->parser->yyTokenName[$token];\r
606                     if (isset($this->lex->smarty_token_names[$exp_token])) {\r
607                         // token type from lexer\r
608                         $expect[] = '"' . $this->lex->smarty_token_names[$exp_token] . '"';\r
609                     } else {\r
610                         // otherwise internal token name\r
611                         $expect[] = $this->parser->yyTokenName[$token];\r
612                     }\r
613                 }\r
614                 $error_text .= ', expected one of: ' . implode(' , ', $expect);\r
615             }\r
616         }\r
617         throw new SmartyCompilerException($error_text);\r
618     }\r
619 \r
620 }\r
621 \r
622 ?>