1: <?php
2:
3: /**
4: * TplFunction Runtime Methods callTemplateFunction
5: *
6: * @package Smarty
7: * @subpackage PluginsInternal
8: * @author Uwe Tews
9: **/
10: class 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: