smarty_internal_runtime_tplfunction.php 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. <?php
  2. /**
  3. * Tplfunc Runtime Methods callTemplateFunction
  4. *
  5. * @package Smarty
  6. * @subpackage PluginsInternal
  7. * @author Uwe Tews
  8. *
  9. **/
  10. class Smarty_Internal_Runtime_TplFunction
  11. {
  12. /**
  13. * Array of source information for known template functions
  14. *
  15. * @var array
  16. */
  17. private $tplFunctions = array();
  18. /**
  19. * Call template function
  20. *
  21. * @param \Smarty_Internal_Template $tpl template object
  22. * @param string $name template function name
  23. * @param array $params parameter array
  24. * @param bool $nocache true if called nocache
  25. *
  26. * @throws \SmartyException
  27. */
  28. public function callTemplateFunction(Smarty_Internal_Template $tpl, $name, $params, $nocache)
  29. {
  30. if (isset($this->tplFunctions[ $name ])) {
  31. if (!$tpl->caching || ($tpl->caching && $nocache)) {
  32. $function = $this->tplFunctions[ $name ][ 'call_name' ];
  33. } else {
  34. if (isset($this->tplFunctions[ $name ][ 'call_name_caching' ])) {
  35. $function = $this->tplFunctions[ $name ][ 'call_name_caching' ];
  36. } else {
  37. $function = $this->tplFunctions[ $name ][ 'call_name' ];
  38. }
  39. }
  40. if (function_exists($function)) {
  41. $this->saveTemplateVariables($tpl, $name);
  42. $function ($tpl, $params);
  43. $this->restoreTemplateVariables($tpl, $name);
  44. return;
  45. }
  46. // try to load template function dynamically
  47. if ($this->addTplFuncToCache($tpl, $name, $function)) {
  48. $this->saveTemplateVariables($tpl, $name);
  49. $function ($tpl, $params);
  50. $this->restoreTemplateVariables($tpl, $name);
  51. return;
  52. }
  53. }
  54. throw new SmartyException("Unable to find template function '{$name}'");
  55. }
  56. /**
  57. * Register template functions defined by template
  58. *
  59. * @param \Smarty_Internal_Template $tpl
  60. * @param array $tplFunctions source information array of template functions defined in template
  61. */
  62. public function registerTplFunctions(Smarty_Internal_Template $tpl, $tplFunctions)
  63. {
  64. $this->tplFunctions = array_merge($this->tplFunctions, $tplFunctions);
  65. $ptr = $tpl;
  66. // make sure that the template functions are known in parent templates
  67. while (isset($ptr->parent) && $ptr->parent->_objType === 2 && !isset($ptr->ext->_tplFunction)) {
  68. $ptr->ext->_tplFunction = $this;
  69. $ptr = $ptr->parent;
  70. }
  71. }
  72. /**
  73. * Return source parameter array for single or all template functions
  74. *
  75. * @param null|string $name template function name
  76. *
  77. * @return array|bool|mixed
  78. */
  79. public function getTplFunction($name = null)
  80. {
  81. if (isset($name)) {
  82. return $this->tplFunctions[ $name ] ? $this->tplFunctions[ $name ] : false;
  83. } else {
  84. return $this->tplFunctions;
  85. }
  86. }
  87. /**
  88. *
  89. * Add template function to cache file for nocache calls
  90. *
  91. * @param Smarty_Internal_Template $tpl
  92. * @param string $_name template function name
  93. * @param string $_function PHP function name
  94. *
  95. * @return bool
  96. */
  97. public function addTplFuncToCache(Smarty_Internal_Template $tpl, $_name, $_function)
  98. {
  99. $funcParam = $this->tplFunctions[ $_name ];
  100. if (is_file($funcParam[ 'compiled_filepath' ])) {
  101. // read compiled file
  102. $code = file_get_contents($funcParam[ 'compiled_filepath' ]);
  103. // grab template function
  104. if (preg_match("/\/\* {$_function} \*\/([\S\s]*?)\/\*\/ {$_function} \*\//", $code, $match)) {
  105. // grab source info from file dependency
  106. preg_match("/\s*'{$funcParam['uid']}'([\S\s]*?)\),/", $code, $match1);
  107. unset($code);
  108. // make PHP function known
  109. eval($match[ 0 ]);
  110. if (function_exists($_function)) {
  111. // search cache file template
  112. $tplPtr = $tpl;
  113. while (!isset($tplPtr->cached) && isset($tplPtr->parent)) {
  114. $tplPtr = $tplPtr->parent;
  115. }
  116. // add template function code to cache file
  117. if (isset($tplPtr->cached)) {
  118. /* @var Smarty_CacheResource $cache */
  119. $cache = $tplPtr->cached;
  120. $content = $cache->read($tplPtr);
  121. if ($content) {
  122. // check if we must update file dependency
  123. if (!preg_match("/'{$funcParam['uid']}'(.*?)'nocache_hash'/", $content, $match2)) {
  124. $content = preg_replace("/('file_dependency'(.*?)\()/", "\\1{$match1[0]}", $content);
  125. }
  126. $tplPtr->smarty->ext->_updateCache->write($cache, $tplPtr,
  127. preg_replace('/\s*\?>\s*$/', "\n", $content) .
  128. "\n" . preg_replace(array('/^\s*<\?php\s+/',
  129. '/\s*\?>\s*$/',), "\n",
  130. $match[ 0 ]));
  131. }
  132. }
  133. return true;
  134. }
  135. }
  136. }
  137. return false;
  138. }
  139. /**
  140. * Save current template variables on stack
  141. *
  142. * @param \Smarty_Internal_Template $tpl
  143. * @param string $name stack name
  144. */
  145. public function saveTemplateVariables(Smarty_Internal_Template $tpl, $name)
  146. {
  147. $tpl->_cache[ 'varStack' ][] =
  148. array('tpl' => $tpl->tpl_vars, 'config' => $tpl->config_vars, 'name' => "_tplFunction_{$name}");
  149. }
  150. /**
  151. * Restore saved variables into template objects
  152. *
  153. * @param \Smarty_Internal_Template $tpl
  154. * @param string $name stack name
  155. */
  156. public function restoreTemplateVariables(Smarty_Internal_Template $tpl, $name)
  157. {
  158. if (isset($tpl->_cache[ 'varStack' ])) {
  159. $vars = array_pop($tpl->_cache[ 'varStack' ]);
  160. $tpl->tpl_vars = $vars[ 'tpl' ];
  161. $tpl->config_vars = $vars[ 'config' ];
  162. }
  163. }
  164. }