PageRenderTime 50ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/libs/sysplugins/smarty_internal_templatebase.php

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