]> git.mxchange.org Git - friendica.git/blob - library/Smarty/libs/sysplugins/smarty_internal_templatebase.php
add smarty engine, remove some obsolete zot1 stuff
[friendica.git] / library / Smarty / libs / sysplugins / smarty_internal_templatebase.php
1 <?php\r
2 /**\r
3  * Smarty Internal Plugin Smarty Template  Base\r
4  *\r
5  * This file contains the basic shared methodes for template handling\r
6  *\r
7  * @package Smarty\r
8  * @subpackage Template\r
9  * @author Uwe Tews\r
10  */\r
11 \r
12 /**\r
13  * Class with shared template methodes\r
14  *\r
15  * @package Smarty\r
16  * @subpackage Template\r
17  */\r
18 abstract class Smarty_Internal_TemplateBase extends Smarty_Internal_Data {\r
19 \r
20     /**\r
21      * fetches a rendered Smarty template\r
22      *\r
23      * @param string $template          the resource handle of the template file or template object\r
24      * @param mixed  $cache_id          cache id to be used with this template\r
25      * @param mixed  $compile_id        compile id to be used with this template\r
26      * @param object $parent            next higher level of Smarty variables\r
27      * @param bool   $display           true: display, false: fetch\r
28      * @param bool   $merge_tpl_vars    if true parent template variables merged in to local scope\r
29      * @param bool   $no_output_filter  if true do not run output filter\r
30      * @return string rendered template output\r
31      */\r
32     public function fetch($template = null, $cache_id = null, $compile_id = null, $parent = null, $display = false, $merge_tpl_vars = true, $no_output_filter = false)\r
33     {\r
34         if ($template === null && $this instanceof $this->template_class) {\r
35             $template = $this;\r
36         }\r
37         if (!empty($cache_id) && is_object($cache_id)) {\r
38             $parent = $cache_id;\r
39             $cache_id = null;\r
40         }\r
41         if ($parent === null && ($this instanceof Smarty || is_string($template))) {\r
42             $parent = $this;\r
43         }\r
44         // create template object if necessary\r
45         $_template = ($template instanceof $this->template_class)\r
46         ? $template\r
47         : $this->smarty->createTemplate($template, $cache_id, $compile_id, $parent, false);\r
48         // if called by Smarty object make sure we use current caching status\r
49         if ($this instanceof Smarty) {\r
50             $_template->caching = $this->caching;\r
51         }\r
52         // merge all variable scopes into template\r
53         if ($merge_tpl_vars) {\r
54             // save local variables\r
55             $save_tpl_vars = $_template->tpl_vars;\r
56             $save_config_vars = $_template->config_vars;\r
57             $ptr_array = array($_template);\r
58             $ptr = $_template;\r
59             while (isset($ptr->parent)) {\r
60                 $ptr_array[] = $ptr = $ptr->parent;\r
61             }\r
62             $ptr_array = array_reverse($ptr_array);\r
63             $parent_ptr = reset($ptr_array);\r
64             $tpl_vars = $parent_ptr->tpl_vars;\r
65             $config_vars = $parent_ptr->config_vars;\r
66             while ($parent_ptr = next($ptr_array)) {\r
67                 if (!empty($parent_ptr->tpl_vars)) {\r
68                     $tpl_vars = array_merge($tpl_vars, $parent_ptr->tpl_vars);\r
69                 }\r
70                 if (!empty($parent_ptr->config_vars)) {\r
71                     $config_vars = array_merge($config_vars, $parent_ptr->config_vars);\r
72                 }\r
73             }\r
74             if (!empty(Smarty::$global_tpl_vars)) {\r
75                 $tpl_vars = array_merge(Smarty::$global_tpl_vars, $tpl_vars);\r
76             }\r
77             $_template->tpl_vars = $tpl_vars;\r
78             $_template->config_vars = $config_vars;\r
79         }\r
80         // dummy local smarty variable\r
81         if (!isset($_template->tpl_vars['smarty'])) {\r
82             $_template->tpl_vars['smarty'] = new Smarty_Variable;\r
83         }\r
84         if (isset($this->smarty->error_reporting)) {\r
85             $_smarty_old_error_level = error_reporting($this->smarty->error_reporting);\r
86         }\r
87         // check URL debugging control\r
88         if (!$this->smarty->debugging && $this->smarty->debugging_ctrl == 'URL') {\r
89             if (isset($_SERVER['QUERY_STRING'])) {\r
90                 $_query_string = $_SERVER['QUERY_STRING'];\r
91             } else {\r
92                 $_query_string = '';\r
93             }\r
94             if (false !== strpos($_query_string, $this->smarty->smarty_debug_id)) {\r
95                 if (false !== strpos($_query_string, $this->smarty->smarty_debug_id . '=on')) {\r
96                     // enable debugging for this browser session\r
97                     setcookie('SMARTY_DEBUG', true);\r
98                     $this->smarty->debugging = true;\r
99                 } elseif (false !== strpos($_query_string, $this->smarty->smarty_debug_id . '=off')) {\r
100                     // disable debugging for this browser session\r
101                     setcookie('SMARTY_DEBUG', false);\r
102                     $this->smarty->debugging = false;\r
103                 } else {\r
104                     // enable debugging for this page\r
105                     $this->smarty->debugging = true;\r
106                 }\r
107             } else {\r
108                 if (isset($_COOKIE['SMARTY_DEBUG'])) {\r
109                     $this->smarty->debugging = true;\r
110                 }\r
111             }\r
112         }\r
113         // must reset merge template date\r
114         $_template->smarty->merged_templates_func = array();\r
115         // get rendered template\r
116         // disable caching for evaluated code\r
117         if ($_template->source->recompiled) {\r
118             $_template->caching = false;\r
119         }\r
120         // checks if template exists\r
121         if (!$_template->source->exists) {\r
122             if ($_template->parent instanceof Smarty_Internal_Template) {\r
123                 $parent_resource = " in '{$_template->parent->template_resource}'";\r
124             } else {\r
125                 $parent_resource = '';\r
126             }\r
127             throw new SmartyException("Unable to load template {$_template->source->type} '{$_template->source->name}'{$parent_resource}");\r
128         }\r
129         // read from cache or render\r
130         if (!($_template->caching == Smarty::CACHING_LIFETIME_CURRENT || $_template->caching == Smarty::CACHING_LIFETIME_SAVED) || !$_template->cached->valid) {\r
131             // render template (not loaded and not in cache)\r
132             if (!$_template->source->uncompiled) {\r
133                 $_smarty_tpl = $_template;\r
134                 if ($_template->source->recompiled) {\r
135                     if ($this->smarty->debugging) {\r
136                         Smarty_Internal_Debug::start_compile($_template);\r
137                     }\r
138                     $code = $_template->compiler->compileTemplate($_template);\r
139                     if ($this->smarty->debugging) {\r
140                         Smarty_Internal_Debug::end_compile($_template);\r
141                     }\r
142                     if ($this->smarty->debugging) {\r
143                         Smarty_Internal_Debug::start_render($_template);\r
144                     }\r
145                     try {\r
146                         ob_start();\r
147                         eval("?>" . $code);\r
148                         unset($code);\r
149                     } catch (Exception $e) {\r
150                         ob_get_clean();\r
151                         throw $e;\r
152                     }\r
153                 } else {\r
154                     if (!$_template->compiled->exists || ($_template->smarty->force_compile && !$_template->compiled->isCompiled)) {\r
155                         $_template->compileTemplateSource();\r
156                     }\r
157                     if ($this->smarty->debugging) {\r
158                         Smarty_Internal_Debug::start_render($_template);\r
159                     }\r
160                     if (!$_template->compiled->loaded) {\r
161                         include($_template->compiled->filepath);\r
162                         if ($_template->mustCompile) {\r
163                             // recompile and load again\r
164                             $_template->compileTemplateSource();\r
165                             include($_template->compiled->filepath);\r
166                         }\r
167                         $_template->compiled->loaded = true;\r
168                     } else {\r
169                         $_template->decodeProperties($_template->compiled->_properties, false);\r
170                     }\r
171                     try {\r
172                         ob_start();\r
173                         if (empty($_template->properties['unifunc']) || !is_callable($_template->properties['unifunc'])) {\r
174                             throw new SmartyException("Invalid compiled template for '{$_template->template_resource}'");\r
175                         }\r
176                         array_unshift($_template->_capture_stack,array());\r
177                         //\r
178                         // render compiled template\r
179                         //\r
180                         $_template->properties['unifunc']($_template);\r
181                         // any unclosed {capture} tags ?\r
182                         if (isset($_template->_capture_stack[0][0])) {\r
183                             $_template->capture_error();\r
184                         }\r
185                         array_shift($_template->_capture_stack);\r
186                     } catch (Exception $e) {\r
187                         ob_get_clean();\r
188                         throw $e;\r
189                     }\r
190                 }\r
191             } else {\r
192                 if ($_template->source->uncompiled) {\r
193                     if ($this->smarty->debugging) {\r
194                         Smarty_Internal_Debug::start_render($_template);\r
195                     }\r
196                     try {\r
197                         ob_start();\r
198                         $_template->source->renderUncompiled($_template);\r
199                     } catch (Exception $e) {\r
200                         ob_get_clean();\r
201                         throw $e;\r
202                     }\r
203                 } else {\r
204                     throw new SmartyException("Resource '$_template->source->type' must have 'renderUncompiled' method");\r
205                 }\r
206             }\r
207             $_output = ob_get_clean();\r
208             if (!$_template->source->recompiled && empty($_template->properties['file_dependency'][$_template->source->uid])) {\r
209                 $_template->properties['file_dependency'][$_template->source->uid] = array($_template->source->filepath, $_template->source->timestamp, $_template->source->type);\r
210             }\r
211             if ($_template->parent instanceof Smarty_Internal_Template) {\r
212                 $_template->parent->properties['file_dependency'] = array_merge($_template->parent->properties['file_dependency'], $_template->properties['file_dependency']);\r
213                 foreach ($_template->required_plugins as $code => $tmp1) {\r
214                     foreach ($tmp1 as $name => $tmp) {\r
215                         foreach ($tmp as $type => $data) {\r
216                             $_template->parent->required_plugins[$code][$name][$type] = $data;\r
217                         }\r
218                     }\r
219                 }\r
220             }\r
221             if ($this->smarty->debugging) {\r
222                 Smarty_Internal_Debug::end_render($_template);\r
223             }\r
224             // write to cache when nessecary\r
225             if (!$_template->source->recompiled && ($_template->caching == Smarty::CACHING_LIFETIME_SAVED || $_template->caching == Smarty::CACHING_LIFETIME_CURRENT)) {\r
226                 if ($this->smarty->debugging) {\r
227                     Smarty_Internal_Debug::start_cache($_template);\r
228                 }\r
229                 $_template->properties['has_nocache_code'] = false;\r
230                 // get text between non-cached items\r
231                 $cache_split = preg_split("!/\*%%SmartyNocache:{$_template->properties['nocache_hash']}%%\*\/(.+?)/\*/%%SmartyNocache:{$_template->properties['nocache_hash']}%%\*/!s", $_output);\r
232                 // get non-cached items\r
233                 preg_match_all("!/\*%%SmartyNocache:{$_template->properties['nocache_hash']}%%\*\/(.+?)/\*/%%SmartyNocache:{$_template->properties['nocache_hash']}%%\*/!s", $_output, $cache_parts);\r
234                 $output = '';\r
235                 // loop over items, stitch back together\r
236                 foreach ($cache_split as $curr_idx => $curr_split) {\r
237                     // escape PHP tags in template content\r
238                     $output .= preg_replace('/(<%|%>|<\?php|<\?|\?>)/', '<?php echo \'$1\'; ?>', $curr_split);\r
239                     if (isset($cache_parts[0][$curr_idx])) {\r
240                         $_template->properties['has_nocache_code'] = true;\r
241                         // remove nocache tags from cache output\r
242                         $output .= preg_replace("!/\*/?%%SmartyNocache:{$_template->properties['nocache_hash']}%%\*/!", '', $cache_parts[0][$curr_idx]);\r
243                     }\r
244                 }\r
245                 if (!$no_output_filter && !$_template->has_nocache_code && (isset($this->smarty->autoload_filters['output']) || isset($this->smarty->registered_filters['output']))) {\r
246                     $output = Smarty_Internal_Filter_Handler::runFilter('output', $output, $_template);\r
247                 }\r
248                 // rendering (must be done before writing cache file because of {function} nocache handling)\r
249                 $_smarty_tpl = $_template;\r
250                 try {\r
251                     ob_start();\r
252                     eval("?>" . $output);\r
253                     $_output = ob_get_clean();\r
254                 } catch (Exception $e) {\r
255                     ob_get_clean();\r
256                     throw $e;\r
257                 }\r
258                 // write cache file content\r
259                 $_template->writeCachedContent($output);\r
260                 if ($this->smarty->debugging) {\r
261                     Smarty_Internal_Debug::end_cache($_template);\r
262                 }\r
263             } else {\r
264                 // var_dump('renderTemplate', $_template->has_nocache_code, $_template->template_resource, $_template->properties['nocache_hash'], $_template->parent->properties['nocache_hash'], $_output);\r
265                 if (!empty($_template->properties['nocache_hash']) && !empty($_template->parent->properties['nocache_hash'])) {\r
266                     // replace nocache_hash\r
267                     $_output = str_replace("{$_template->properties['nocache_hash']}", $_template->parent->properties['nocache_hash'], $_output);\r
268                     $_template->parent->has_nocache_code = $_template->parent->has_nocache_code || $_template->has_nocache_code;\r
269                 }\r
270             }\r
271         } else {\r
272             if ($this->smarty->debugging) {\r
273                 Smarty_Internal_Debug::start_cache($_template);\r
274             }\r
275             try {\r
276                 ob_start();\r
277                 array_unshift($_template->_capture_stack,array());\r
278                 //\r
279                 // render cached template\r
280                 //\r
281                 $_template->properties['unifunc']($_template);\r
282                 // any unclosed {capture} tags ?\r
283                 if (isset($_template->_capture_stack[0][0])) {\r
284                     $_template->capture_error();\r
285                 }\r
286                 array_shift($_template->_capture_stack);\r
287                 $_output = ob_get_clean();\r
288             } catch (Exception $e) {\r
289                 ob_get_clean();\r
290                 throw $e;\r
291             }\r
292             if ($this->smarty->debugging) {\r
293                 Smarty_Internal_Debug::end_cache($_template);\r
294             }\r
295         }\r
296         if ((!$this->caching || $_template->has_nocache_code || $_template->source->recompiled) && !$no_output_filter && (isset($this->smarty->autoload_filters['output']) || isset($this->smarty->registered_filters['output']))) {\r
297             $_output = Smarty_Internal_Filter_Handler::runFilter('output', $_output, $_template);\r
298         }\r
299         if (isset($this->error_reporting)) {\r
300             error_reporting($_smarty_old_error_level);\r
301         }\r
302         // display or fetch\r
303         if ($display) {\r
304             if ($this->caching && $this->cache_modified_check) {\r
305                 $_isCached = $_template->isCached() && !$_template->has_nocache_code;\r
306                 $_last_modified_date = @substr($_SERVER['HTTP_IF_MODIFIED_SINCE'], 0, strpos($_SERVER['HTTP_IF_MODIFIED_SINCE'], 'GMT') + 3);\r
307                 if ($_isCached && $_template->cached->timestamp <= strtotime($_last_modified_date)) {\r
308                     switch (PHP_SAPI) {\r
309                         case 'cgi':         // php-cgi < 5.3\r
310                         case 'cgi-fcgi':    // php-cgi >= 5.3\r
311                         case 'fpm-fcgi':    // php-fpm >= 5.3.3\r
312                         header('Status: 304 Not Modified');\r
313                         break;\r
314 \r
315                         case 'cli':\r
316                         if (/* ^phpunit */!empty($_SERVER['SMARTY_PHPUNIT_DISABLE_HEADERS'])/* phpunit$ */) {\r
317                             $_SERVER['SMARTY_PHPUNIT_HEADERS'][] = '304 Not Modified';\r
318                         }\r
319                         break;\r
320 \r
321                         default:\r
322                         header($_SERVER['SERVER_PROTOCOL'].' 304 Not Modified');\r
323                         break;\r
324                     }\r
325                 } else {\r
326                     switch (PHP_SAPI) {\r
327                         case 'cli':\r
328                         if (/* ^phpunit */!empty($_SERVER['SMARTY_PHPUNIT_DISABLE_HEADERS'])/* phpunit$ */) {\r
329                             $_SERVER['SMARTY_PHPUNIT_HEADERS'][] = 'Last-Modified: ' . gmdate('D, d M Y H:i:s', $_template->cached->timestamp) . ' GMT';\r
330                         }\r
331                         break;\r
332 \r
333                         default:\r
334                         header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $_template->cached->timestamp) . ' GMT');\r
335                         break;\r
336                     }\r
337                     echo $_output;\r
338                 }\r
339             } else {\r
340                 echo $_output;\r
341             }\r
342             // debug output\r
343             if ($this->smarty->debugging) {\r
344                 Smarty_Internal_Debug::display_debug($this);\r
345             }\r
346             if ($merge_tpl_vars) {\r
347                 // restore local variables\r
348                 $_template->tpl_vars = $save_tpl_vars;\r
349                 $_template->config_vars =  $save_config_vars;\r
350             }\r
351             return;\r
352         } else {\r
353             if ($merge_tpl_vars) {\r
354                 // restore local variables\r
355                 $_template->tpl_vars = $save_tpl_vars;\r
356                 $_template->config_vars =  $save_config_vars;\r
357             }\r
358             // return fetched content\r
359             return $_output;\r
360         }\r
361     }\r
362 \r
363     /**\r
364      * displays a Smarty template\r
365      *\r
366      * @param string $template   the resource handle of the template file or template object\r
367      * @param mixed  $cache_id   cache id to be used with this template\r
368      * @param mixed  $compile_id compile id to be used with this template\r
369      * @param object $parent     next higher level of Smarty variables\r
370      */\r
371     public function display($template = null, $cache_id = null, $compile_id = null, $parent = null)\r
372     {\r
373         // display template\r
374         $this->fetch($template, $cache_id, $compile_id, $parent, true);\r
375     }\r
376 \r
377     /**\r
378      * test if cache is valid\r
379      *\r
380      * @param string|object $template   the resource handle of the template file or template object\r
381      * @param mixed         $cache_id   cache id to be used with this template\r
382      * @param mixed         $compile_id compile id to be used with this template\r
383      * @param object        $parent     next higher level of Smarty variables\r
384      * @return boolean cache status\r
385      */\r
386     public function isCached($template = null, $cache_id = null, $compile_id = null, $parent = null)\r
387     {\r
388         if ($template === null && $this instanceof $this->template_class) {\r
389             return $this->cached->valid;\r
390         }\r
391         if (!($template instanceof $this->template_class)) {\r
392             if ($parent === null) {\r
393                 $parent = $this;\r
394             }\r
395             $template = $this->smarty->createTemplate($template, $cache_id, $compile_id, $parent, false);\r
396         }\r
397         // return cache status of template\r
398         return $template->cached->valid;\r
399     }\r
400 \r
401     /**\r
402      * creates a data object\r
403      *\r
404      * @param object $parent next higher level of Smarty variables\r
405      * @returns Smarty_Data data object\r
406      */\r
407     public function createData($parent = null)\r
408     {\r
409         return new Smarty_Data($parent, $this);\r
410     }\r
411 \r
412     /**\r
413      * Registers plugin to be used in templates\r
414      *\r
415      * @param string   $type       plugin type\r
416      * @param string   $tag        name of template tag\r
417      * @param callback $callback   PHP callback to register\r
418      * @param boolean  $cacheable  if true (default) this fuction is cachable\r
419      * @param array    $cache_attr caching attributes if any\r
420      * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining\r
421      * @throws SmartyException when the plugin tag is invalid\r
422      */\r
423     public function registerPlugin($type, $tag, $callback, $cacheable = true, $cache_attr = null)\r
424     {\r
425         if (isset($this->smarty->registered_plugins[$type][$tag])) {\r
426             throw new SmartyException("Plugin tag \"{$tag}\" already registered");\r
427         } elseif (!is_callable($callback)) {\r
428             throw new SmartyException("Plugin \"{$tag}\" not callable");\r
429         } else {\r
430             $this->smarty->registered_plugins[$type][$tag] = array($callback, (bool) $cacheable, (array) $cache_attr);\r
431         }\r
432 \r
433         return $this;\r
434     }\r
435 \r
436     /**\r
437      * Unregister Plugin\r
438      *\r
439      * @param string $type of plugin\r
440      * @param string $tag name of plugin\r
441      * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining\r
442      */\r
443     public function unregisterPlugin($type, $tag)\r
444     {\r
445         if (isset($this->smarty->registered_plugins[$type][$tag])) {\r
446             unset($this->smarty->registered_plugins[$type][$tag]);\r
447         }\r
448 \r
449         return $this;\r
450     }\r
451 \r
452     /**\r
453      * Registers a resource to fetch a template\r
454      *\r
455      * @param string $type name of resource type\r
456      * @param Smarty_Resource|array $callback or instance of Smarty_Resource, or array of callbacks to handle resource (deprecated)\r
457      * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining\r
458      */\r
459     public function registerResource($type, $callback)\r
460     {\r
461         $this->smarty->registered_resources[$type] = $callback instanceof Smarty_Resource ? $callback : array($callback, false);\r
462         return $this;\r
463     }\r
464 \r
465     /**\r
466      * Unregisters a resource\r
467      *\r
468      * @param string $type name of resource type\r
469      * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining\r
470      */\r
471     public function unregisterResource($type)\r
472     {\r
473         if (isset($this->smarty->registered_resources[$type])) {\r
474             unset($this->smarty->registered_resources[$type]);\r
475         }\r
476 \r
477         return $this;\r
478     }\r
479 \r
480     /**\r
481      * Registers a cache resource to cache a template's output\r
482      *\r
483      * @param string               $type     name of cache resource type\r
484      * @param Smarty_CacheResource $callback instance of Smarty_CacheResource to handle output caching\r
485      * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining\r
486      */\r
487     public function registerCacheResource($type, Smarty_CacheResource $callback)\r
488     {\r
489         $this->smarty->registered_cache_resources[$type] = $callback;\r
490         return $this;\r
491     }\r
492 \r
493     /**\r
494      * Unregisters a cache resource\r
495      *\r
496      * @param string $type name of cache resource type\r
497      * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining\r
498      */\r
499     public function unregisterCacheResource($type)\r
500     {\r
501         if (isset($this->smarty->registered_cache_resources[$type])) {\r
502             unset($this->smarty->registered_cache_resources[$type]);\r
503         }\r
504 \r
505         return $this;\r
506     }\r
507 \r
508     /**\r
509      * Registers object to be used in templates\r
510      *\r
511      * @param string  $object        name of template object\r
512      * @param object  $object_impl   the referenced PHP object to register\r
513      * @param array   $allowed       list of allowed methods (empty = all)\r
514      * @param boolean $smarty_args   smarty argument format, else traditional\r
515      * @param array   $block_methods list of block-methods\r
516      * @param array $block_functs list of methods that are block format\r
517      * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining\r
518      * @throws SmartyException if any of the methods in $allowed or $block_methods are invalid\r
519      */\r
520     public function registerObject($object_name, $object_impl, $allowed = array(), $smarty_args = true, $block_methods = array())\r
521     {\r
522         // test if allowed methodes callable\r
523         if (!empty($allowed)) {\r
524             foreach ((array) $allowed as $method) {\r
525                 if (!is_callable(array($object_impl, $method))) {\r
526                     throw new SmartyException("Undefined method '$method' in registered object");\r
527                 }\r
528             }\r
529         }\r
530         // test if block methodes callable\r
531         if (!empty($block_methods)) {\r
532             foreach ((array) $block_methods as $method) {\r
533                 if (!is_callable(array($object_impl, $method))) {\r
534                     throw new SmartyException("Undefined method '$method' in registered object");\r
535                 }\r
536             }\r
537         }\r
538         // register the object\r
539         $this->smarty->registered_objects[$object_name] =\r
540         array($object_impl, (array) $allowed, (boolean) $smarty_args, (array) $block_methods);\r
541         return $this;\r
542     }\r
543 \r
544     /**\r
545      * return a reference to a registered object\r
546      *\r
547      * @param string $name object name\r
548      * @return object\r
549      * @throws SmartyException if no such object is found\r
550      */\r
551     public function getRegisteredObject($name)\r
552     {\r
553         if (!isset($this->smarty->registered_objects[$name])) {\r
554             throw new SmartyException("'$name' is not a registered object");\r
555         }\r
556         if (!is_object($this->smarty->registered_objects[$name][0])) {\r
557             throw new SmartyException("registered '$name' is not an object");\r
558         }\r
559         return $this->smarty->registered_objects[$name][0];\r
560     }\r
561 \r
562     /**\r
563      * unregister an object\r
564      *\r
565      * @param string $name object name\r
566      * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining\r
567      */\r
568     public function unregisterObject($name)\r
569     {\r
570         if (isset($this->smarty->registered_objects[$name])) {\r
571             unset($this->smarty->registered_objects[$name]);\r
572         }\r
573 \r
574         return $this;\r
575     }\r
576 \r
577     /**\r
578      * Registers static classes to be used in templates\r
579      *\r
580      * @param string $class name of template class\r
581      * @param string $class_impl the referenced PHP class to register\r
582      * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining\r
583      * @throws SmartyException if $class_impl does not refer to an existing class\r
584      */\r
585     public function registerClass($class_name, $class_impl)\r
586     {\r
587         // test if exists\r
588         if (!class_exists($class_impl)) {\r
589             throw new SmartyException("Undefined class '$class_impl' in register template class");\r
590         }\r
591         // register the class\r
592         $this->smarty->registered_classes[$class_name] = $class_impl;\r
593         return $this;\r
594     }\r
595 \r
596     /**\r
597      * Registers a default plugin handler\r
598      *\r
599      * @param callable $callback class/method name\r
600      * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining\r
601      * @throws SmartyException if $callback is not callable\r
602      */\r
603     public function registerDefaultPluginHandler($callback)\r
604     {\r
605         if (is_callable($callback)) {\r
606             $this->smarty->default_plugin_handler_func = $callback;\r
607         } else {\r
608             throw new SmartyException("Default plugin handler '$callback' not callable");\r
609         }\r
610 \r
611         return $this;\r
612     }\r
613 \r
614     /**\r
615      * Registers a default template handler\r
616      *\r
617      * @param callable $callback class/method name\r
618      * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining\r
619      * @throws SmartyException if $callback is not callable\r
620      */\r
621     public function registerDefaultTemplateHandler($callback)\r
622     {\r
623         if (is_callable($callback)) {\r
624             $this->smarty->default_template_handler_func = $callback;\r
625         } else {\r
626             throw new SmartyException("Default template handler '$callback' not callable");\r
627         }\r
628 \r
629         return $this;\r
630     }\r
631 \r
632     /**\r
633      * Registers a default template handler\r
634      *\r
635      * @param callable $callback class/method name\r
636      * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining\r
637      * @throws SmartyException if $callback is not callable\r
638      */\r
639     public function registerDefaultConfigHandler($callback)\r
640     {\r
641         if (is_callable($callback)) {\r
642             $this->smarty->default_config_handler_func = $callback;\r
643         } else {\r
644             throw new SmartyException("Default config handler '$callback' not callable");\r
645         }\r
646 \r
647         return $this;\r
648     }\r
649 \r
650     /**\r
651      * Registers a filter function\r
652      *\r
653      * @param string $type filter type\r
654      * @param callback $callback\r
655      * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining\r
656      */\r
657     public function registerFilter($type, $callback)\r
658     {\r
659         $this->smarty->registered_filters[$type][$this->_get_filter_name($callback)] = $callback;\r
660         return $this;\r
661     }\r
662 \r
663     /**\r
664      * Unregisters a filter function\r
665      *\r
666      * @param string $type filter type\r
667      * @param callback $callback\r
668      * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining\r
669      */\r
670     public function unregisterFilter($type, $callback)\r
671     {\r
672         $name = $this->_get_filter_name($callback);\r
673         if (isset($this->smarty->registered_filters[$type][$name])) {\r
674             unset($this->smarty->registered_filters[$type][$name]);\r
675         }\r
676 \r
677         return $this;\r
678     }\r
679 \r
680     /**\r
681      * Return internal filter name\r
682      *\r
683      * @param callback $function_name\r
684      * @return string internal filter name\r
685      */\r
686     public function _get_filter_name($function_name)\r
687     {\r
688         if (is_array($function_name)) {\r
689             $_class_name = (is_object($function_name[0]) ?\r
690             get_class($function_name[0]) : $function_name[0]);\r
691             return $_class_name . '_' . $function_name[1];\r
692         } else {\r
693             return $function_name;\r
694         }\r
695     }\r
696 \r
697     /**\r
698      * load a filter of specified type and name\r
699      *\r
700      * @param string $type filter type\r
701      * @param string $name filter name\r
702      * @throws SmartyException if filter could not be loaded\r
703      */\r
704     public function loadFilter($type, $name)\r
705     {\r
706         $_plugin = "smarty_{$type}filter_{$name}";\r
707         $_filter_name = $_plugin;\r
708         if ($this->smarty->loadPlugin($_plugin)) {\r
709             if (class_exists($_plugin, false)) {\r
710                 $_plugin = array($_plugin, 'execute');\r
711             }\r
712             if (is_callable($_plugin)) {\r
713                 $this->smarty->registered_filters[$type][$_filter_name] = $_plugin;\r
714                 return true;\r
715             }\r
716         }\r
717         throw new SmartyException("{$type}filter \"{$name}\" not callable");\r
718     }\r
719 \r
720     /**\r
721      * unload a filter of specified type and name\r
722      *\r
723      * @param string $type filter type\r
724      * @param string $name filter name\r
725      * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining\r
726      */\r
727     public function unloadFilter($type, $name)\r
728     {\r
729         $_filter_name = "smarty_{$type}filter_{$name}";\r
730         if (isset($this->smarty->registered_filters[$type][$_filter_name])) {\r
731             unset ($this->smarty->registered_filters[$type][$_filter_name]);\r
732         }\r
733 \r
734         return $this;\r
735     }\r
736 \r
737     /**\r
738      * preg_replace callback to convert camelcase getter/setter to underscore property names\r
739      *\r
740      * @param string $match match string\r
741      * @return string replacemant\r
742      */\r
743     private function replaceCamelcase($match) {\r
744         return "_" . strtolower($match[1]);\r
745     }\r
746 \r
747     /**\r
748      * Handle unknown class methods\r
749      *\r
750      * @param string $name unknown method-name\r
751      * @param array  $args argument array\r
752      */\r
753     public function __call($name, $args)\r
754     {\r
755         static $_prefixes = array('set' => true, 'get' => true);\r
756         static $_resolved_property_name = array();\r
757         static $_resolved_property_source = array();\r
758 \r
759         // method of Smarty object?\r
760         if (method_exists($this->smarty, $name)) {\r
761             return call_user_func_array(array($this->smarty, $name), $args);\r
762         }\r
763         // see if this is a set/get for a property\r
764         $first3 = strtolower(substr($name, 0, 3));\r
765         if (isset($_prefixes[$first3]) && isset($name[3]) && $name[3] !== '_') {\r
766             if (isset($_resolved_property_name[$name])) {\r
767                 $property_name = $_resolved_property_name[$name];\r
768             } else {\r
769                 // try to keep case correct for future PHP 6.0 case-sensitive class methods\r
770                 // lcfirst() not available < PHP 5.3.0, so improvise\r
771                 $property_name = strtolower(substr($name, 3, 1)) . substr($name, 4);\r
772                 // convert camel case to underscored name\r
773                 $property_name = preg_replace_callback('/([A-Z])/', array($this,'replaceCamelcase'), $property_name);\r
774                 $_resolved_property_name[$name] = $property_name;\r
775             }\r
776             if (isset($_resolved_property_source[$property_name])) {\r
777                 $_is_this = $_resolved_property_source[$property_name];\r
778             } else {\r
779                 $_is_this = null;\r
780                 if (property_exists($this, $property_name)) {\r
781                     $_is_this = true;\r
782                 } else if (property_exists($this->smarty, $property_name)) {\r
783                     $_is_this = false;\r
784                 }\r
785                 $_resolved_property_source[$property_name] = $_is_this;\r
786             }\r
787             if ($_is_this) {\r
788                 if ($first3 == 'get')\r
789                 return $this->$property_name;\r
790                 else\r
791                 return $this->$property_name = $args[0];\r
792             } else if ($_is_this === false) {\r
793                 if ($first3 == 'get')\r
794                 return $this->smarty->$property_name;\r
795                 else\r
796                 return $this->smarty->$property_name = $args[0];\r
797             } else {\r
798                 throw new SmartyException("property '$property_name' does not exist.");\r
799                 return false;\r
800             }\r
801         }\r
802         if ($name == 'Smarty') {\r
803             throw new SmartyException("PHP5 requires you to call __construct() instead of Smarty()");\r
804         }\r
805         // must be unknown\r
806         throw new SmartyException("Call of unknown method '$name'.");\r
807     }\r
808 \r
809 }\r
810 \r
811 ?>