[345] | 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 | ?> |
---|