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