1 | <?php |
---|
2 | /** |
---|
3 | * Smarty Internal Plugin Template |
---|
4 | * |
---|
5 | * This file contains the Smarty template engine |
---|
6 | * |
---|
7 | * @package Smarty |
---|
8 | * @subpackage Template |
---|
9 | * @author Uwe Tews |
---|
10 | */ |
---|
11 | |
---|
12 | /** |
---|
13 | * Main class with template data structures and methods |
---|
14 | * |
---|
15 | * @package Smarty |
---|
16 | * @subpackage Template |
---|
17 | * |
---|
18 | * @property Smarty_Template_Source $source |
---|
19 | * @property Smarty_Template_Compiled $compiled |
---|
20 | * @property Smarty_Template_Cached $cached |
---|
21 | */ |
---|
22 | class Smarty_Internal_Template extends Smarty_Internal_TemplateBase { |
---|
23 | |
---|
24 | /** |
---|
25 | * cache_id |
---|
26 | * @var string |
---|
27 | */ |
---|
28 | public $cache_id = null; |
---|
29 | /** |
---|
30 | * $compile_id |
---|
31 | * @var string |
---|
32 | */ |
---|
33 | public $compile_id = null; |
---|
34 | /** |
---|
35 | * caching enabled |
---|
36 | * @var boolean |
---|
37 | */ |
---|
38 | public $caching = null; |
---|
39 | /** |
---|
40 | * cache lifetime in seconds |
---|
41 | * @var integer |
---|
42 | */ |
---|
43 | public $cache_lifetime = null; |
---|
44 | /** |
---|
45 | * Template resource |
---|
46 | * @var string |
---|
47 | */ |
---|
48 | public $template_resource = null; |
---|
49 | /** |
---|
50 | * flag if compiled template is invalid and must be (re)compiled |
---|
51 | * @var bool |
---|
52 | */ |
---|
53 | public $mustCompile = null; |
---|
54 | /** |
---|
55 | * flag if template does contain nocache code sections |
---|
56 | * @var bool |
---|
57 | */ |
---|
58 | public $has_nocache_code = false; |
---|
59 | /** |
---|
60 | * special compiled and cached template properties |
---|
61 | * @var array |
---|
62 | */ |
---|
63 | public $properties = array('file_dependency' => array(), |
---|
64 | 'nocache_hash' => '', |
---|
65 | 'function' => array()); |
---|
66 | /** |
---|
67 | * required plugins |
---|
68 | * @var array |
---|
69 | */ |
---|
70 | public $required_plugins = array('compiled' => array(), 'nocache' => array()); |
---|
71 | /** |
---|
72 | * Global smarty instance |
---|
73 | * @var Smarty |
---|
74 | */ |
---|
75 | public $smarty = null; |
---|
76 | /** |
---|
77 | * blocks for template inheritance |
---|
78 | * @var array |
---|
79 | */ |
---|
80 | public $block_data = array(); |
---|
81 | /** |
---|
82 | * variable filters |
---|
83 | * @var array |
---|
84 | */ |
---|
85 | public $variable_filters = array(); |
---|
86 | /** |
---|
87 | * optional log of tag/attributes |
---|
88 | * @var array |
---|
89 | */ |
---|
90 | public $used_tags = array(); |
---|
91 | /** |
---|
92 | * internal flag to allow relative path in child template blocks |
---|
93 | * @var bool |
---|
94 | */ |
---|
95 | public $allow_relative_path = false; |
---|
96 | /** |
---|
97 | * internal capture runtime stack |
---|
98 | * @var array |
---|
99 | */ |
---|
100 | public $_capture_stack = array(0 => array()); |
---|
101 | |
---|
102 | /** |
---|
103 | * Create template data object |
---|
104 | * |
---|
105 | * Some of the global Smarty settings copied to template scope |
---|
106 | * It load the required template resources and cacher plugins |
---|
107 | * |
---|
108 | * @param string $template_resource template resource string |
---|
109 | * @param Smarty $smarty Smarty instance |
---|
110 | * @param Smarty_Internal_Template $_parent back pointer to parent object with variables or null |
---|
111 | * @param mixed $_cache_id cache id or null |
---|
112 | * @param mixed $_compile_id compile id or null |
---|
113 | * @param bool $_caching use caching? |
---|
114 | * @param int $_cache_lifetime cache life-time in seconds |
---|
115 | */ |
---|
116 | public function __construct($template_resource, $smarty, $_parent = null, $_cache_id = null, $_compile_id = null, $_caching = null, $_cache_lifetime = null) |
---|
117 | { |
---|
118 | $this->smarty = &$smarty; |
---|
119 | // Smarty parameter |
---|
120 | $this->cache_id = $_cache_id === null ? $this->smarty->cache_id : $_cache_id; |
---|
121 | $this->compile_id = $_compile_id === null ? $this->smarty->compile_id : $_compile_id; |
---|
122 | $this->caching = $_caching === null ? $this->smarty->caching : $_caching; |
---|
123 | if ($this->caching === true) |
---|
124 | $this->caching = Smarty::CACHING_LIFETIME_CURRENT; |
---|
125 | $this->cache_lifetime = $_cache_lifetime === null ? $this->smarty->cache_lifetime : $_cache_lifetime; |
---|
126 | $this->parent = $_parent; |
---|
127 | // Template resource |
---|
128 | $this->template_resource = $template_resource; |
---|
129 | // copy block data of template inheritance |
---|
130 | if ($this->parent instanceof Smarty_Internal_Template) { |
---|
131 | $this->block_data = $this->parent->block_data; |
---|
132 | } |
---|
133 | } |
---|
134 | |
---|
135 | /** |
---|
136 | * Returns if the current template must be compiled by the Smarty compiler |
---|
137 | * |
---|
138 | * It does compare the timestamps of template source and the compiled templates and checks the force compile configuration |
---|
139 | * |
---|
140 | * @return boolean true if the template must be compiled |
---|
141 | */ |
---|
142 | public function mustCompile() |
---|
143 | { |
---|
144 | if (!$this->source->exists) { |
---|
145 | if ($this->parent instanceof Smarty_Internal_Template) { |
---|
146 | $parent_resource = " in '$this->parent->template_resource}'"; |
---|
147 | } else { |
---|
148 | $parent_resource = ''; |
---|
149 | } |
---|
150 | throw new SmartyException("Unable to load template {$this->source->type} '{$this->source->name}'{$parent_resource}"); |
---|
151 | } |
---|
152 | if ($this->mustCompile === null) { |
---|
153 | $this->mustCompile = (!$this->source->uncompiled && ($this->smarty->force_compile || $this->source->recompiled || $this->compiled->timestamp === false || |
---|
154 | ($this->smarty->compile_check && $this->compiled->timestamp < $this->source->timestamp))); |
---|
155 | } |
---|
156 | return $this->mustCompile; |
---|
157 | } |
---|
158 | |
---|
159 | /** |
---|
160 | * Compiles the template |
---|
161 | * |
---|
162 | * If the template is not evaluated the compiled template is saved on disk |
---|
163 | */ |
---|
164 | public function compileTemplateSource() |
---|
165 | { |
---|
166 | if (!$this->source->recompiled) { |
---|
167 | $this->properties['file_dependency'] = array(); |
---|
168 | if ($this->source->components) { |
---|
169 | // uses real resource for file dependency |
---|
170 | $source = end($this->source->components); |
---|
171 | $this->properties['file_dependency'][$this->source->uid] = array($this->source->filepath, $this->source->timestamp, $source->type); |
---|
172 | } else { |
---|
173 | $this->properties['file_dependency'][$this->source->uid] = array($this->source->filepath, $this->source->timestamp, $this->source->type); |
---|
174 | } |
---|
175 | } |
---|
176 | if ($this->smarty->debugging) { |
---|
177 | Smarty_Internal_Debug::start_compile($this); |
---|
178 | } |
---|
179 | // compile locking |
---|
180 | if ($this->smarty->compile_locking && !$this->source->recompiled) { |
---|
181 | if ($saved_timestamp = $this->compiled->timestamp) { |
---|
182 | @touch($this->compiled->filepath); |
---|
183 | } |
---|
184 | } |
---|
185 | // call compiler |
---|
186 | try { |
---|
187 | $code = $this->compiler->compileTemplate($this); |
---|
188 | } catch (Exception $e) { |
---|
189 | // restore old timestamp in case of error |
---|
190 | if ($this->smarty->compile_locking && !$this->source->recompiled && $saved_timestamp) { |
---|
191 | touch($this->compiled->filepath, $saved_timestamp); |
---|
192 | } |
---|
193 | throw $e; |
---|
194 | } |
---|
195 | // compiling succeded |
---|
196 | if (!$this->source->recompiled && $this->compiler->write_compiled_code) { |
---|
197 | // write compiled template |
---|
198 | $_filepath = $this->compiled->filepath; |
---|
199 | if ($_filepath === false) |
---|
200 | throw new SmartyException('getCompiledFilepath() did not return a destination to save the compiled template to'); |
---|
201 | Smarty_Internal_Write_File::writeFile($_filepath, $code, $this->smarty); |
---|
202 | $this->compiled->exists = true; |
---|
203 | $this->compiled->isCompiled = true; |
---|
204 | } |
---|
205 | if ($this->smarty->debugging) { |
---|
206 | Smarty_Internal_Debug::end_compile($this); |
---|
207 | } |
---|
208 | // release compiler object to free memory |
---|
209 | unset($this->compiler); |
---|
210 | } |
---|
211 | |
---|
212 | /** |
---|
213 | * Writes the cached template output |
---|
214 | * |
---|
215 | * @return bool |
---|
216 | */ |
---|
217 | public function writeCachedContent($content) |
---|
218 | { |
---|
219 | if ($this->source->recompiled || !($this->caching == Smarty::CACHING_LIFETIME_CURRENT || $this->caching == Smarty::CACHING_LIFETIME_SAVED)) { |
---|
220 | // don't write cache file |
---|
221 | return false; |
---|
222 | } |
---|
223 | $this->properties['cache_lifetime'] = $this->cache_lifetime; |
---|
224 | $this->properties['unifunc'] = 'content_' . uniqid('', false); |
---|
225 | $content = $this->createTemplateCodeFrame($content, true); |
---|
226 | $_smarty_tpl = $this; |
---|
227 | eval("?>" . $content); |
---|
228 | $this->cached->valid = true; |
---|
229 | $this->cached->processed = true; |
---|
230 | return $this->cached->write($this, $content); |
---|
231 | } |
---|
232 | |
---|
233 | /** |
---|
234 | * Template code runtime function to get subtemplate content |
---|
235 | * |
---|
236 | * @param string $template the resource handle of the template file |
---|
237 | * @param mixed $cache_id cache id to be used with this template |
---|
238 | * @param mixed $compile_id compile id to be used with this template |
---|
239 | * @param integer $caching cache mode |
---|
240 | * @param integer $cache_lifetime life time of cache data |
---|
241 | * @param array $vars optional variables to assign |
---|
242 | * @param int $parent_scope scope in which {include} should execute |
---|
243 | * @returns string template content |
---|
244 | */ |
---|
245 | public function getSubTemplate($template, $cache_id, $compile_id, $caching, $cache_lifetime, $data, $parent_scope) |
---|
246 | { |
---|
247 | // already in template cache? |
---|
248 | if ($this->smarty->allow_ambiguous_resources) { |
---|
249 | $_templateId = Smarty_Resource::getUniqueTemplateName($this->smarty, $template) . $cache_id . $compile_id; |
---|
250 | } else { |
---|
251 | $_templateId = $this->smarty->joined_template_dir . '#' . $template . $cache_id . $compile_id; |
---|
252 | } |
---|
253 | |
---|
254 | if (isset($_templateId[150])) { |
---|
255 | $_templateId = sha1($_templateId); |
---|
256 | } |
---|
257 | if (isset($this->smarty->template_objects[$_templateId])) { |
---|
258 | // clone cached template object because of possible recursive call |
---|
259 | $tpl = clone $this->smarty->template_objects[$_templateId]; |
---|
260 | $tpl->parent = $this; |
---|
261 | $tpl->caching = $caching; |
---|
262 | $tpl->cache_lifetime = $cache_lifetime; |
---|
263 | } else { |
---|
264 | $tpl = new $this->smarty->template_class($template, $this->smarty, $this, $cache_id, $compile_id, $caching, $cache_lifetime); |
---|
265 | } |
---|
266 | // get variables from calling scope |
---|
267 | if ($parent_scope == Smarty::SCOPE_LOCAL) { |
---|
268 | $tpl->tpl_vars = $this->tpl_vars; |
---|
269 | } elseif ($parent_scope == Smarty::SCOPE_PARENT) { |
---|
270 | $tpl->tpl_vars = &$this->tpl_vars; |
---|
271 | } elseif ($parent_scope == Smarty::SCOPE_GLOBAL) { |
---|
272 | $tpl->tpl_vars = &Smarty::$global_tpl_vars; |
---|
273 | } elseif (($scope_ptr = $this->getScopePointer($parent_scope)) == null) { |
---|
274 | $tpl->tpl_vars = &$this->tpl_vars; |
---|
275 | } else { |
---|
276 | $tpl->tpl_vars = &$scope_ptr->tpl_vars; |
---|
277 | } |
---|
278 | $tpl->config_vars = $this->config_vars; |
---|
279 | if (!empty($data)) { |
---|
280 | // set up variable values |
---|
281 | foreach ($data as $_key => $_val) { |
---|
282 | $tpl->tpl_vars[$_key] = new Smarty_variable($_val); |
---|
283 | } |
---|
284 | } |
---|
285 | return $tpl->fetch(null, null, null, null, false, false, true); |
---|
286 | } |
---|
287 | |
---|
288 | /** |
---|
289 | * Template code runtime function to set up an inline subtemplate |
---|
290 | * |
---|
291 | * @param string $template the resource handle of the template file |
---|
292 | * @param mixed $cache_id cache id to be used with this template |
---|
293 | * @param mixed $compile_id compile id to be used with this template |
---|
294 | * @param integer $caching cache mode |
---|
295 | * @param integer $cache_lifetime life time of cache data |
---|
296 | * @param array $vars optional variables to assign |
---|
297 | * @param int $parent_scope scope in which {include} should execute |
---|
298 | * @param string $hash nocache hash code |
---|
299 | * @returns string template content |
---|
300 | */ |
---|
301 | public function setupInlineSubTemplate($template, $cache_id, $compile_id, $caching, $cache_lifetime, $data, $parent_scope, $hash) |
---|
302 | { |
---|
303 | $tpl = new $this->smarty->template_class($template, $this->smarty, $this, $cache_id, $compile_id, $caching, $cache_lifetime); |
---|
304 | $tpl->properties['nocache_hash'] = $hash; |
---|
305 | // get variables from calling scope |
---|
306 | if ($parent_scope == Smarty::SCOPE_LOCAL ) { |
---|
307 | $tpl->tpl_vars = $this->tpl_vars; |
---|
308 | } elseif ($parent_scope == Smarty::SCOPE_PARENT) { |
---|
309 | $tpl->tpl_vars = &$this->tpl_vars; |
---|
310 | } elseif ($parent_scope == Smarty::SCOPE_GLOBAL) { |
---|
311 | $tpl->tpl_vars = &Smarty::$global_tpl_vars; |
---|
312 | } elseif (($scope_ptr = $this->getScopePointer($parent_scope)) == null) { |
---|
313 | $tpl->tpl_vars = &$this->tpl_vars; |
---|
314 | } else { |
---|
315 | $tpl->tpl_vars = &$scope_ptr->tpl_vars; |
---|
316 | } |
---|
317 | $tpl->config_vars = $this->config_vars; |
---|
318 | if (!empty($data)) { |
---|
319 | // set up variable values |
---|
320 | foreach ($data as $_key => $_val) { |
---|
321 | $tpl->tpl_vars[$_key] = new Smarty_variable($_val); |
---|
322 | } |
---|
323 | } |
---|
324 | return $tpl; |
---|
325 | } |
---|
326 | |
---|
327 | |
---|
328 | /** |
---|
329 | * Create code frame for compiled and cached templates |
---|
330 | * |
---|
331 | * @param string $content optional template content |
---|
332 | * @param bool $cache flag for cache file |
---|
333 | * @return string |
---|
334 | */ |
---|
335 | public function createTemplateCodeFrame($content = '', $cache = false) |
---|
336 | { |
---|
337 | $plugins_string = ''; |
---|
338 | // include code for plugins |
---|
339 | if (!$cache) { |
---|
340 | if (!empty($this->required_plugins['compiled'])) { |
---|
341 | $plugins_string = '<?php '; |
---|
342 | foreach ($this->required_plugins['compiled'] as $tmp) { |
---|
343 | foreach ($tmp as $data) { |
---|
344 | $file = addslashes($data['file']); |
---|
345 | $plugins_string .= "if (!is_callable('{$data['function']}')) include '{$file}';\n"; |
---|
346 | } |
---|
347 | } |
---|
348 | $plugins_string .= '?>'; |
---|
349 | } |
---|
350 | if (!empty($this->required_plugins['nocache'])) { |
---|
351 | $this->has_nocache_code = true; |
---|
352 | $plugins_string .= "<?php echo '/*%%SmartyNocache:{$this->properties['nocache_hash']}%%*/<?php \$_smarty = \$_smarty_tpl->smarty; "; |
---|
353 | foreach ($this->required_plugins['nocache'] as $tmp) { |
---|
354 | foreach ($tmp as $data) { |
---|
355 | $file = addslashes($data['file']); |
---|
356 | $plugins_string .= addslashes("if (!is_callable('{$data['function']}')) include '{$file}';\n"); |
---|
357 | } |
---|
358 | } |
---|
359 | $plugins_string .= "?>/*/%%SmartyNocache:{$this->properties['nocache_hash']}%%*/';?>\n"; |
---|
360 | } |
---|
361 | } |
---|
362 | // build property code |
---|
363 | $this->properties['has_nocache_code'] = $this->has_nocache_code; |
---|
364 | $output = ''; |
---|
365 | if (!$this->source->recompiled) { |
---|
366 | $output = "<?php /*%%SmartyHeaderCode:{$this->properties['nocache_hash']}%%*/"; |
---|
367 | if ($this->smarty->direct_access_security) { |
---|
368 | $output .= "if(!defined('SMARTY_DIR')) exit('no direct access allowed');\n"; |
---|
369 | } |
---|
370 | } |
---|
371 | if ($cache) { |
---|
372 | // remove compiled code of{function} definition |
---|
373 | unset($this->properties['function']); |
---|
374 | if (!empty($this->smarty->template_functions)) { |
---|
375 | // copy code of {function} tags called in nocache mode |
---|
376 | foreach ($this->smarty->template_functions as $name => $function_data) { |
---|
377 | if (isset($function_data['called_nocache'])) { |
---|
378 | foreach ($function_data['called_functions'] as $func_name) { |
---|
379 | $this->smarty->template_functions[$func_name]['called_nocache'] = true; |
---|
380 | } |
---|
381 | } |
---|
382 | } |
---|
383 | foreach ($this->smarty->template_functions as $name => $function_data) { |
---|
384 | if (isset($function_data['called_nocache'])) { |
---|
385 | unset($function_data['called_nocache'], $function_data['called_functions'], $this->smarty->template_functions[$name]['called_nocache']); |
---|
386 | $this->properties['function'][$name] = $function_data; |
---|
387 | } |
---|
388 | } |
---|
389 | } |
---|
390 | } |
---|
391 | $this->properties['version'] = Smarty::SMARTY_VERSION; |
---|
392 | if (!isset($this->properties['unifunc'])) { |
---|
393 | $this->properties['unifunc'] = 'content_' . uniqid('', false); |
---|
394 | } |
---|
395 | if (!$this->source->recompiled) { |
---|
396 | $output .= "\$_valid = \$_smarty_tpl->decodeProperties(" . var_export($this->properties, true) . ',' . ($cache ? 'true' : 'false') . "); /*/%%SmartyHeaderCode%%*/?>\n"; |
---|
397 | } |
---|
398 | if (!$this->source->recompiled) { |
---|
399 | $output .= '<?php if ($_valid && !is_callable(\'' . $this->properties['unifunc'] . '\')) {function ' . $this->properties['unifunc'] . '($_smarty_tpl) {?>'; |
---|
400 | } |
---|
401 | $output .= $plugins_string; |
---|
402 | $output .= $content; |
---|
403 | if (!$this->source->recompiled) { |
---|
404 | $output .= '<?php }} ?>'; |
---|
405 | } |
---|
406 | return $output; |
---|
407 | } |
---|
408 | |
---|
409 | /** |
---|
410 | * This function is executed automatically when a compiled or cached template file is included |
---|
411 | * |
---|
412 | * - Decode saved properties from compiled template and cache files |
---|
413 | * - Check if compiled or cache file is valid |
---|
414 | * |
---|
415 | * @param array $properties special template properties |
---|
416 | * @param bool $cache flag if called from cache file |
---|
417 | * @return bool flag if compiled or cache file is valid |
---|
418 | */ |
---|
419 | public function decodeProperties($properties, $cache = false) |
---|
420 | { |
---|
421 | $this->has_nocache_code = $properties['has_nocache_code']; |
---|
422 | $this->properties['nocache_hash'] = $properties['nocache_hash']; |
---|
423 | if (isset($properties['cache_lifetime'])) { |
---|
424 | $this->properties['cache_lifetime'] = $properties['cache_lifetime']; |
---|
425 | } |
---|
426 | if (isset($properties['file_dependency'])) { |
---|
427 | $this->properties['file_dependency'] = array_merge($this->properties['file_dependency'], $properties['file_dependency']); |
---|
428 | } |
---|
429 | if (!empty($properties['function'])) { |
---|
430 | $this->properties['function'] = array_merge($this->properties['function'], $properties['function']); |
---|
431 | $this->smarty->template_functions = array_merge($this->smarty->template_functions, $properties['function']); |
---|
432 | } |
---|
433 | $this->properties['version'] = (isset($properties['version'])) ? $properties['version'] : ''; |
---|
434 | $this->properties['unifunc'] = $properties['unifunc']; |
---|
435 | // check file dependencies at compiled code |
---|
436 | $is_valid = true; |
---|
437 | if ($this->properties['version'] != Smarty::SMARTY_VERSION) { |
---|
438 | $is_valid = false; |
---|
439 | } else if (((!$cache && $this->smarty->compile_check && empty($this->compiled->_properties) && !$this->compiled->isCompiled) || $cache && ($this->smarty->compile_check === true || $this->smarty->compile_check === Smarty::COMPILECHECK_ON)) && !empty($this->properties['file_dependency'])) { |
---|
440 | foreach ($this->properties['file_dependency'] as $_file_to_check) { |
---|
441 | if ($_file_to_check[2] == 'file' || $_file_to_check[2] == 'php') { |
---|
442 | if ($this->source->filepath == $_file_to_check[0] && isset($this->source->timestamp)) { |
---|
443 | // do not recheck current template |
---|
444 | $mtime = $this->source->timestamp; |
---|
445 | } else { |
---|
446 | // file and php types can be checked without loading the respective resource handlers |
---|
447 | $mtime = filemtime($_file_to_check[0]); |
---|
448 | } |
---|
449 | } elseif ($_file_to_check[2] == 'string') { |
---|
450 | continue; |
---|
451 | } else { |
---|
452 | $source = Smarty_Resource::source(null, $this->smarty, $_file_to_check[0]); |
---|
453 | $mtime = $source->timestamp; |
---|
454 | } |
---|
455 | if ($mtime > $_file_to_check[1]) { |
---|
456 | $is_valid = false; |
---|
457 | break; |
---|
458 | } |
---|
459 | } |
---|
460 | } |
---|
461 | if ($cache) { |
---|
462 | $this->cached->valid = $is_valid; |
---|
463 | } else { |
---|
464 | $this->mustCompile = !$is_valid; |
---|
465 | } |
---|
466 | // store data in reusable Smarty_Template_Compiled |
---|
467 | if (!$cache) { |
---|
468 | $this->compiled->_properties = $properties; |
---|
469 | } |
---|
470 | return $is_valid; |
---|
471 | } |
---|
472 | |
---|
473 | /** |
---|
474 | * Template code runtime function to create a local Smarty variable for array assignments |
---|
475 | * |
---|
476 | * @param string $tpl_var tempate variable name |
---|
477 | * @param bool $nocache cache mode of variable |
---|
478 | * @param int $scope scope of variable |
---|
479 | */ |
---|
480 | public function createLocalArrayVariable($tpl_var, $nocache = false, $scope = Smarty::SCOPE_LOCAL) |
---|
481 | { |
---|
482 | if (!isset($this->tpl_vars[$tpl_var])) { |
---|
483 | $this->tpl_vars[$tpl_var] = new Smarty_variable(array(), $nocache, $scope); |
---|
484 | } else { |
---|
485 | $this->tpl_vars[$tpl_var] = clone $this->tpl_vars[$tpl_var]; |
---|
486 | if ($scope != Smarty::SCOPE_LOCAL) { |
---|
487 | $this->tpl_vars[$tpl_var]->scope = $scope; |
---|
488 | } |
---|
489 | if (!(is_array($this->tpl_vars[$tpl_var]->value) || $this->tpl_vars[$tpl_var]->value instanceof ArrayAccess)) { |
---|
490 | settype($this->tpl_vars[$tpl_var]->value, 'array'); |
---|
491 | } |
---|
492 | } |
---|
493 | } |
---|
494 | |
---|
495 | /** |
---|
496 | * Template code runtime function to get pointer to template variable array of requested scope |
---|
497 | * |
---|
498 | * @param int $scope requested variable scope |
---|
499 | * @return array array of template variables |
---|
500 | */ |
---|
501 | public function &getScope($scope) |
---|
502 | { |
---|
503 | if ($scope == Smarty::SCOPE_PARENT && !empty($this->parent)) { |
---|
504 | return $this->parent->tpl_vars; |
---|
505 | } elseif ($scope == Smarty::SCOPE_ROOT && !empty($this->parent)) { |
---|
506 | $ptr = $this->parent; |
---|
507 | while (!empty($ptr->parent)) { |
---|
508 | $ptr = $ptr->parent; |
---|
509 | } |
---|
510 | return $ptr->tpl_vars; |
---|
511 | } elseif ($scope == Smarty::SCOPE_GLOBAL) { |
---|
512 | return Smarty::$global_tpl_vars; |
---|
513 | } |
---|
514 | $null = null; |
---|
515 | return $null; |
---|
516 | } |
---|
517 | |
---|
518 | /** |
---|
519 | * Get parent or root of template parent chain |
---|
520 | * |
---|
521 | * @param int $scope pqrent or root scope |
---|
522 | * @return mixed object |
---|
523 | */ |
---|
524 | public function getScopePointer($scope) |
---|
525 | { |
---|
526 | if ($scope == Smarty::SCOPE_PARENT && !empty($this->parent)) { |
---|
527 | return $this->parent; |
---|
528 | } elseif ($scope == Smarty::SCOPE_ROOT && !empty($this->parent)) { |
---|
529 | $ptr = $this->parent; |
---|
530 | while (!empty($ptr->parent)) { |
---|
531 | $ptr = $ptr->parent; |
---|
532 | } |
---|
533 | return $ptr; |
---|
534 | } |
---|
535 | return null; |
---|
536 | } |
---|
537 | |
---|
538 | /** |
---|
539 | * [util function] counts an array, arrayaccess/traversable or PDOStatement object |
---|
540 | * |
---|
541 | * @param mixed $value |
---|
542 | * @return int the count for arrays and objects that implement countable, 1 for other objects that don't, and 0 for empty elements |
---|
543 | */ |
---|
544 | public function _count($value) |
---|
545 | { |
---|
546 | if (is_array($value) === true || $value instanceof Countable) { |
---|
547 | return count($value); |
---|
548 | } elseif ($value instanceof IteratorAggregate) { |
---|
549 | // Note: getIterator() returns a Traversable, not an Iterator |
---|
550 | // thus rewind() and valid() methods may not be present |
---|
551 | return iterator_count($value->getIterator()); |
---|
552 | } elseif ($value instanceof Iterator) { |
---|
553 | return iterator_count($value); |
---|
554 | } elseif ($value instanceof PDOStatement) { |
---|
555 | return $value->rowCount(); |
---|
556 | } elseif ($value instanceof Traversable) { |
---|
557 | return iterator_count($value); |
---|
558 | } elseif ($value instanceof ArrayAccess) { |
---|
559 | if ($value->offsetExists(0)) { |
---|
560 | return 1; |
---|
561 | } |
---|
562 | } elseif (is_object($value)) { |
---|
563 | return count($value); |
---|
564 | } |
---|
565 | return 0; |
---|
566 | } |
---|
567 | |
---|
568 | /** |
---|
569 | * runtime error not matching capture tags |
---|
570 | * |
---|
571 | */ |
---|
572 | public function capture_error() |
---|
573 | { |
---|
574 | throw new SmartyException("Not matching {capture} open/close in \"{$this->template_resource}\""); |
---|
575 | } |
---|
576 | |
---|
577 | /** |
---|
578 | * Empty cache for this template |
---|
579 | * |
---|
580 | * @param integer $exp_time expiration time |
---|
581 | * @return integer number of cache files deleted |
---|
582 | */ |
---|
583 | public function clearCache($exp_time=null) |
---|
584 | { |
---|
585 | Smarty_CacheResource::invalidLoadedCache($this->smarty); |
---|
586 | return $this->cached->handler->clear($this->smarty, $this->template_name, $this->cache_id, $this->compile_id, $exp_time); |
---|
587 | } |
---|
588 | |
---|
589 | /** |
---|
590 | * set Smarty property in template context |
---|
591 | * |
---|
592 | * @param string $property_name property name |
---|
593 | * @param mixed $value value |
---|
594 | */ |
---|
595 | public function __set($property_name, $value) |
---|
596 | { |
---|
597 | switch ($property_name) { |
---|
598 | case 'source': |
---|
599 | case 'compiled': |
---|
600 | case 'cached': |
---|
601 | case 'compiler': |
---|
602 | $this->$property_name = $value; |
---|
603 | return; |
---|
604 | |
---|
605 | // FIXME: routing of template -> smarty attributes |
---|
606 | default: |
---|
607 | if (property_exists($this->smarty, $property_name)) { |
---|
608 | $this->smarty->$property_name = $value; |
---|
609 | return; |
---|
610 | } |
---|
611 | } |
---|
612 | |
---|
613 | throw new SmartyException("invalid template property '$property_name'."); |
---|
614 | } |
---|
615 | |
---|
616 | /** |
---|
617 | * get Smarty property in template context |
---|
618 | * |
---|
619 | * @param string $property_name property name |
---|
620 | */ |
---|
621 | public function __get($property_name) |
---|
622 | { |
---|
623 | switch ($property_name) { |
---|
624 | case 'source': |
---|
625 | if (empty($this->template_resource)) { |
---|
626 | throw new SmartyException("Unable to parse resource name \"{$this->template_resource}\""); |
---|
627 | } |
---|
628 | $this->source = Smarty_Resource::source($this); |
---|
629 | // cache template object under a unique ID |
---|
630 | // do not cache eval resources |
---|
631 | if ($this->source->type != 'eval') { |
---|
632 | if ($this->smarty->allow_ambiguous_resources) { |
---|
633 | $_templateId = $this->source->unique_resource . $this->cache_id . $this->compile_id; |
---|
634 | } else { |
---|
635 | $_templateId = $this->smarty->joined_template_dir . '#' . $this->template_resource . $this->cache_id . $this->compile_id; |
---|
636 | } |
---|
637 | |
---|
638 | if (isset($_templateId[150])) { |
---|
639 | $_templateId = sha1($_templateId); |
---|
640 | } |
---|
641 | $this->smarty->template_objects[$_templateId] = $this; |
---|
642 | } |
---|
643 | return $this->source; |
---|
644 | |
---|
645 | case 'compiled': |
---|
646 | $this->compiled = $this->source->getCompiled($this); |
---|
647 | return $this->compiled; |
---|
648 | |
---|
649 | case 'cached': |
---|
650 | if (!class_exists('Smarty_Template_Cached')) { |
---|
651 | include SMARTY_SYSPLUGINS_DIR . 'smarty_cacheresource.php'; |
---|
652 | } |
---|
653 | $this->cached = new Smarty_Template_Cached($this); |
---|
654 | return $this->cached; |
---|
655 | |
---|
656 | case 'compiler': |
---|
657 | $this->smarty->loadPlugin($this->source->compiler_class); |
---|
658 | $this->compiler = new $this->source->compiler_class($this->source->template_lexer_class, $this->source->template_parser_class, $this->smarty); |
---|
659 | return $this->compiler; |
---|
660 | |
---|
661 | // FIXME: routing of template -> smarty attributes |
---|
662 | default: |
---|
663 | if (property_exists($this->smarty, $property_name)) { |
---|
664 | return $this->smarty->$property_name; |
---|
665 | } |
---|
666 | } |
---|
667 | |
---|
668 | throw new SmartyException("template property '$property_name' does not exist."); |
---|
669 | } |
---|
670 | |
---|
671 | /** |
---|
672 | * Template data object destrutor |
---|
673 | * |
---|
674 | */ |
---|
675 | public function __destruct() |
---|
676 | { |
---|
677 | if ($this->smarty->cache_locking && isset($this->cached) && $this->cached->is_locked) { |
---|
678 | $this->cached->handler->releaseLock($this->smarty, $this->cached); |
---|
679 | } |
---|
680 | } |
---|
681 | |
---|
682 | } |
---|
683 | |
---|
684 | ?> |
---|