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