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 */ 22class 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 157 return $this->mustCompile; 158 } 159 160 /** 161 * Compiles the template 162 * 163 * If the template is not evaluated the compiled template is saved on disk 164 */ 165 public function compileTemplateSource() 166 { 167 if (!$this->source->recompiled) { 168 $this->properties['file_dependency'] = array(); 169 if ($this->source->components) { 170 // for the extends resource the compiler will fill it 171 // uses real resource for file dependency 172 // $source = end($this->source->components); 173 // $this->properties['file_dependency'][$this->source->uid] = array($this->source->filepath, $this->source->timestamp, $source->type); 174 } else { 175 $this->properties['file_dependency'][$this->source->uid] = array($this->source->filepath, $this->source->timestamp, $this->source->type); 176 } 177 } 178 // compile locking 179 if ($this->smarty->compile_locking && !$this->source->recompiled) { 180 if ($saved_timestamp = $this->compiled->timestamp) { 181 touch($this->compiled->filepath); 182 } 183 } 184 // call compiler 185 try { 186 $code = $this->compiler->compileTemplate($this); 187 } catch (Exception $e) { 188 // restore old timestamp in case of error 189 if ($this->smarty->compile_locking && !$this->source->recompiled && $saved_timestamp) { 190 touch($this->compiled->filepath, $saved_timestamp); 191 } 192 throw $e; 193 } 194 // compiling succeded 195 if (!$this->source->recompiled && $this->compiler->write_compiled_code) { 196 // write compiled template 197 $_filepath = $this->compiled->filepath; 198 if ($_filepath === false) 199 throw new SmartyException('getCompiledFilepath() did not return a destination to save the compiled template to'); 200 Smarty_Internal_Write_File::writeFile($_filepath, $code, $this->smarty); 201 $this->compiled->exists = true; 202 $this->compiled->isCompiled = true; 203 } 204 // release compiler object to free memory 205 unset($this->compiler); 206 } 207 208 /** 209 * Writes the cached template output 210 * 211 * @return bool 212 */ 213 public function writeCachedContent($content) 214 { 215 if ($this->source->recompiled || !($this->caching == Smarty::CACHING_LIFETIME_CURRENT || $this->caching == Smarty::CACHING_LIFETIME_SAVED)) { 216 // don't write cache file 217 return false; 218 } 219 $this->properties['cache_lifetime'] = $this->cache_lifetime; 220 $this->properties['unifunc'] = 'content_' . str_replace('.', '_', uniqid('', true)); 221 $content = $this->createTemplateCodeFrame($content, true); 222 $_smarty_tpl = $this; 223 eval("?>" . $content); 224 $this->cached->valid = true; 225 $this->cached->processed = true; 226 227 return $this->cached->write($this, $content); 228 } 229 230 /** 231 * Template code runtime function to get subtemplate content 232 * 233 * @param string $template the resource handle of the template file 234 * @param mixed $cache_id cache id to be used with this template 235 * @param mixed $compile_id compile id to be used with this template 236 * @param integer $caching cache mode 237 * @param integer $cache_lifetime life time of cache data 238 * @param array $vars optional variables to assign 239 * @param int $parent_scope scope in which {include} should execute 240 * @returns string template content 241 */ 242 public function getSubTemplate($template, $cache_id, $compile_id, $caching, $cache_lifetime, $data, $parent_scope) 243 { 244 // already in template cache? 245 if ($this->smarty->allow_ambiguous_resources) { 246 $_templateId = Smarty_Resource::getUniqueTemplateName($this->smarty, $template) . $cache_id . $compile_id; 247 } else { 248 $_templateId = $this->smarty->joined_template_dir . '#' . $template . $cache_id . $compile_id; 249 } 250 251 if (isset($_templateId[150])) { 252 $_templateId = sha1($_templateId); 253 } 254 if (isset($this->smarty->template_objects[$_templateId])) { 255 // clone cached template object because of possible recursive call 256 $tpl = clone $this->smarty->template_objects[$_templateId]; 257 $tpl->parent = $this; 258 $tpl->caching = $caching; 259 $tpl->cache_lifetime = $cache_lifetime; 260 } else { 261 $tpl = new $this->smarty->template_class($template, $this->smarty, $this, $cache_id, $compile_id, $caching, $cache_lifetime); 262 } 263 // get variables from calling scope 264 if ($parent_scope == Smarty::SCOPE_LOCAL) { 265 $tpl->tpl_vars = $this->tpl_vars; 266 $tpl->tpl_vars['smarty'] = clone $this->tpl_vars['smarty']; 267 } elseif ($parent_scope == Smarty::SCOPE_PARENT) { 268 $tpl->tpl_vars = &$this->tpl_vars; 269 } elseif ($parent_scope == Smarty::SCOPE_GLOBAL) { 270 $tpl->tpl_vars = &Smarty::$global_tpl_vars; 271 } elseif (($scope_ptr = $this->getScopePointer($parent_scope)) == null) { 272 $tpl->tpl_vars = &$this->tpl_vars; 273 } else { 274 $tpl->tpl_vars = &$scope_ptr->tpl_vars; 275 } 276 $tpl->config_vars = $this->config_vars; 277 if (!empty($data)) { 278 // set up variable values 279 foreach ($data as $_key => $_val) { 280 $tpl->tpl_vars[$_key] = new Smarty_variable($_val); 281 } 282 } 283 284 return $tpl->fetch(null, null, null, null, false, false, true); 285 } 286 287 /** 288 * Template code runtime function to set up an inline subtemplate 289 * 290 * @param string $template the resource handle of the template file 291 * @param mixed $cache_id cache id to be used with this template 292 * @param mixed $compile_id compile id to be used with this template 293 * @param integer $caching cache mode 294 * @param integer $cache_lifetime life time of cache data 295 * @param array $vars optional variables to assign 296 * @param int $parent_scope scope in which {include} should execute 297 * @param string $hash nocache hash code 298 * @returns string template content 299 */ 300 public function setupInlineSubTemplate($template, $cache_id, $compile_id, $caching, $cache_lifetime, $data, $parent_scope, $hash) 301 { 302 $tpl = new $this->smarty->template_class($template, $this->smarty, $this, $cache_id, $compile_id, $caching, $cache_lifetime); 303 $tpl->properties['nocache_hash'] = $hash; 304 // get variables from calling scope 305 if ($parent_scope == Smarty::SCOPE_LOCAL) { 306 $tpl->tpl_vars = $this->tpl_vars; 307 $tpl->tpl_vars['smarty'] = clone $this->tpl_vars['smarty']; 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 325 return $tpl; 326 } 327 328 329 /** 330 * Create code frame for compiled and cached templates 331 * 332 * @param string $content optional template content 333 * @param bool $cache flag for cache file 334 * @return string 335 */ 336 public function createTemplateCodeFrame($content = '', $cache = false) 337 { 338 $plugins_string = ''; 339 // include code for plugins 340 if (!$cache) { 341 if (!empty($this->required_plugins['compiled'])) { 342 $plugins_string = '<?php '; 343 foreach ($this->required_plugins['compiled'] as $tmp) { 344 foreach ($tmp as $data) { 345 $file = addslashes($data['file']); 346 if (is_Array($data['function'])) { 347 $plugins_string .= "if (!is_callable(array('{$data['function'][0]}','{$data['function'][1]}'))) include '{$file}';\n"; 348 } else { 349 $plugins_string .= "if (!is_callable('{$data['function']}')) include '{$file}';\n"; 350 } 351 } 352 } 353 $plugins_string .= '?>'; 354 } 355 if (!empty($this->required_plugins['nocache'])) { 356 $this->has_nocache_code = true; 357 $plugins_string .= "<?php echo '/*%%SmartyNocache:{$this->properties['nocache_hash']}%%*/<?php \$_smarty = \$_smarty_tpl->smarty; "; 358 foreach ($this->required_plugins['nocache'] as $tmp) { 359 foreach ($tmp as $data) { 360 $file = addslashes($data['file']); 361 if (is_Array($data['function'])) { 362 $plugins_string .= addslashes("if (!is_callable(array('{$data['function'][0]}','{$data['function'][1]}'))) include '{$file}';\n"); 363 } else { 364 $plugins_string .= addslashes("if (!is_callable('{$data['function']}')) include '{$file}';\n"); 365 } 366 } 367 } 368 $plugins_string .= "?>/*/%%SmartyNocache:{$this->properties['nocache_hash']}%%*/';?>\n"; 369 } 370 } 371 // build property code 372 $this->properties['has_nocache_code'] = $this->has_nocache_code; 373 $output = ''; 374 if (!$this->source->recompiled) { 375 $output = "<?php /*%%SmartyHeaderCode:{$this->properties['nocache_hash']}%%*/"; 376 if ($this->smarty->direct_access_security) { 377 $output .= "if(!defined('SMARTY_DIR')) exit('no direct access allowed');\n"; 378 } 379 } 380 if ($cache) { 381 // remove compiled code of{function} definition 382 unset($this->properties['function']); 383 if (!empty($this->smarty->template_functions)) { 384 // copy code of {function} tags called in nocache mode 385 foreach ($this->smarty->template_functions as $name => $function_data) { 386 if (isset($function_data['called_nocache'])) { 387 foreach ($function_data['called_functions'] as $func_name) { 388 $this->smarty->template_functions[$func_name]['called_nocache'] = true; 389 } 390 } 391 } 392 foreach ($this->smarty->template_functions as $name => $function_data) { 393 if (isset($function_data['called_nocache'])) { 394 unset($function_data['called_nocache'], $function_data['called_functions'], $this->smarty->template_functions[$name]['called_nocache']); 395 $this->properties['function'][$name] = $function_data; 396 } 397 } 398 } 399 } 400 $this->properties['version'] = Smarty::SMARTY_VERSION; 401 if (!isset($this->properties['unifunc'])) { 402 $this->properties['unifunc'] = 'content_' . str_replace('.', '_', uniqid('', true)); 403 } 404 if (!$this->source->recompiled) { 405 $output .= "\$_valid = \$_smarty_tpl->decodeProperties(" . var_export($this->properties, true) . ',' . ($cache ? 'true' : 'false') . "); /*/%%SmartyHeaderCode%%*/?>\n"; 406 $output .= '<?php if ($_valid && !is_callable(\'' . $this->properties['unifunc'] . '\')) {function ' . $this->properties['unifunc'] . '($_smarty_tpl) {?>'; 407 } 408 $output .= $plugins_string; 409 $output .= $content; 410 if (!$this->source->recompiled) { 411 $output .= "<?php }} ?>\n"; 412 } 413 414 return $output; 415 } 416 417 /** 418 * This function is executed automatically when a compiled or cached template file is included 419 * 420 * - Decode saved properties from compiled template and cache files 421 * - Check if compiled or cache file is valid 422 * 423 * @param array $properties special template properties 424 * @param bool $cache flag if called from cache file 425 * @return bool flag if compiled or cache file is valid 426 */ 427 public function decodeProperties($properties, $cache = false) 428 { 429 $this->has_nocache_code = $properties['has_nocache_code']; 430 $this->properties['nocache_hash'] = $properties['nocache_hash']; 431 if (isset($properties['cache_lifetime'])) { 432 $this->properties['cache_lifetime'] = $properties['cache_lifetime']; 433 } 434 if (isset($properties['file_dependency'])) { 435 $this->properties['file_dependency'] = array_merge($this->properties['file_dependency'], $properties['file_dependency']); 436 } 437 if (!empty($properties['function'])) { 438 $this->properties['function'] = array_merge($this->properties['function'], $properties['function']); 439 $this->smarty->template_functions = array_merge($this->smarty->template_functions, $properties['function']); 440 } 441 $this->properties['version'] = (isset($properties['version'])) ? $properties['version'] : ''; 442 $this->properties['unifunc'] = $properties['unifunc']; 443 // check file dependencies at compiled code 444 $is_valid = true; 445 if ($this->properties['version'] != Smarty::SMARTY_VERSION) { 446 $is_valid = false; 447 } elseif (((!$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'])) { 448 foreach ($this->properties['file_dependency'] as $_file_to_check) { 449 if ($_file_to_check[2] == 'file' || $_file_to_check[2] == 'php') { 450 if ($this->source->filepath == $_file_to_check[0] && isset($this->source->timestamp)) { 451 // do not recheck current template 452 $mtime = $this->source->timestamp; 453 } else { 454 // file and php types can be checked without loading the respective resource handlers 455 $mtime = @filemtime($_file_to_check[0]); 456 } 457 } elseif ($_file_to_check[2] == 'string') { 458 continue; 459 } else { 460 $source = Smarty_Resource::source(null, $this->smarty, $_file_to_check[0]); 461 $mtime = $source->timestamp; 462 } 463 if (!$mtime || $mtime > $_file_to_check[1]) { 464 $is_valid = false; 465 break; 466 } 467 } 468 } 469 if ($cache) { 470 // CACHING_LIFETIME_SAVED cache expiry has to be validated here since otherwise we'd define the unifunc 471 if ($this->caching === Smarty::CACHING_LIFETIME_SAVED && 472 $this->properties['cache_lifetime'] >= 0 && 473 (time() > ($this->cached->timestamp + $this->properties['cache_lifetime']))) { 474 $is_valid = false; 475 } 476 $this->cached->valid = $is_valid; 477 } else { 478 $this->mustCompile = !$is_valid; } 479 // store data in reusable Smarty_Template_Compiled 480 if (!$cache) { 481 $this->compiled->_properties = $properties; 482 } 483 484 return $is_valid; 485 } 486 487 /** 488 * Template code runtime function to create a local Smarty variable for array assignments 489 * 490 * @param string $tpl_var tempate variable name 491 * @param bool $nocache cache mode of variable 492 * @param int $scope scope of variable 493 */ 494 public function createLocalArrayVariable($tpl_var, $nocache = false, $scope = Smarty::SCOPE_LOCAL) 495 { 496 if (!isset($this->tpl_vars[$tpl_var])) { 497 $this->tpl_vars[$tpl_var] = new Smarty_variable(array(), $nocache, $scope); 498 } else { 499 $this->tpl_vars[$tpl_var] = clone $this->tpl_vars[$tpl_var]; 500 if ($scope != Smarty::SCOPE_LOCAL) { 501 $this->tpl_vars[$tpl_var]->scope = $scope; 502 } 503 if (!(is_array($this->tpl_vars[$tpl_var]->value) || $this->tpl_vars[$tpl_var]->value instanceof ArrayAccess)) { 504 settype($this->tpl_vars[$tpl_var]->value, 'array'); 505 } 506 } 507 } 508 509 /** 510 * Template code runtime function to get pointer to template variable array of requested scope 511 * 512 * @param int $scope requested variable scope 513 * @return array array of template variables 514 */ 515 public function &getScope($scope) 516 { 517 if ($scope == Smarty::SCOPE_PARENT && !empty($this->parent)) { 518 return $this->parent->tpl_vars; 519 } elseif ($scope == Smarty::SCOPE_ROOT && !empty($this->parent)) { 520 $ptr = $this->parent; 521 while (!empty($ptr->parent)) { 522 $ptr = $ptr->parent; 523 } 524 525 return $ptr->tpl_vars; 526 } elseif ($scope == Smarty::SCOPE_GLOBAL) { 527 return Smarty::$global_tpl_vars; 528 } 529 $null = null; 530 531 return $null; 532 } 533 534 /** 535 * Get parent or root of template parent chain 536 * 537 * @param int $scope pqrent or root scope 538 * @return mixed object 539 */ 540 public function getScopePointer($scope) 541 { 542 if ($scope == Smarty::SCOPE_PARENT && !empty($this->parent)) { 543 return $this->parent; 544 } elseif ($scope == Smarty::SCOPE_ROOT && !empty($this->parent)) { 545 $ptr = $this->parent; 546 while (!empty($ptr->parent)) { 547 $ptr = $ptr->parent; 548 } 549 550 return $ptr; 551 } 552 553 return null; 554 } 555 556 /** 557 * [util function] counts an array, arrayaccess/traversable or PDOStatement object 558 * 559 * @param mixed $value 560 * @return int the count for arrays and objects that implement countable, 1 for other objects that don't, and 0 for empty elements 561 */ 562 public function _count($value) 563 { 564 if (is_array($value) === true || $value instanceof Countable) { 565 return count($value); 566 } elseif ($value instanceof IteratorAggregate) { 567 // Note: getIterator() returns a Traversable, not an Iterator 568 // thus rewind() and valid() methods may not be present 569 return iterator_count($value->getIterator()); 570 } elseif ($value instanceof Iterator) { 571 return iterator_count($value); 572 } elseif ($value instanceof PDOStatement) { 573 return $value->rowCount(); 574 } elseif ($value instanceof Traversable) { 575 return iterator_count($value); 576 } elseif ($value instanceof ArrayAccess) { 577 if ($value->offsetExists(0)) { 578 return 1; 579 } 580 } elseif (is_object($value)) { 581 return count($value); 582 } 583 584 return 0; 585 } 586 587 /** 588 * runtime error not matching capture tags 589 * 590 */ 591 public function capture_error() 592 { 593 throw new SmartyException("Not matching {capture} open/close in \"{$this->template_resource}\""); 594 } 595 596 /** 597 * Empty cache for this template 598 * 599 * @param integer $exp_time expiration time 600 * @return integer number of cache files deleted 601 */ 602 public function clearCache($exp_time=null) 603 { 604 Smarty_CacheResource::invalidLoadedCache($this->smarty); 605 606 return $this->cached->handler->clear($this->smarty, $this->template_name, $this->cache_id, $this->compile_id, $exp_time); 607 } 608 609 /** 610 * set Smarty property in template context 611 * 612 * @param string $property_name property name 613 * @param mixed $value value 614 */ 615 public function __set($property_name, $value) 616 { 617 switch ($property_name) { 618 case 'source': 619 case 'compiled': 620 case 'cached': 621 case 'compiler': 622 $this->$property_name = $value; 623 624 return; 625 626 // FIXME: routing of template -> smarty attributes 627 default: 628 if (property_exists($this->smarty, $property_name)) { 629 $this->smarty->$property_name = $value; 630 631 return; 632 } 633 } 634 635 throw new SmartyException("invalid template property '$property_name'."); 636 } 637 638 /** 639 * get Smarty property in template context 640 * 641 * @param string $property_name property name 642 */ 643 public function __get($property_name) 644 { 645 switch ($property_name) { 646 case 'source': 647 if (strlen($this->template_resource) == 0) { 648 throw new SmartyException('Missing template name'); 649 } 650 $this->source = Smarty_Resource::source($this); 651 // cache template object under a unique ID 652 // do not cache eval resources 653 if ($this->source->type != 'eval') { 654 if ($this->smarty->allow_ambiguous_resources) { 655 $_templateId = $this->source->unique_resource . $this->cache_id . $this->compile_id; 656 } else { 657 $_templateId = $this->smarty->joined_template_dir . '#' . $this->template_resource . $this->cache_id . $this->compile_id; 658 } 659 660 if (isset($_templateId[150])) { 661 $_templateId = sha1($_templateId); 662 } 663 $this->smarty->template_objects[$_templateId] = $this; 664 } 665 666 return $this->source; 667 668 case 'compiled': 669 $this->compiled = $this->source->getCompiled($this); 670 671 return $this->compiled; 672 673 case 'cached': 674 if (!class_exists('Smarty_Template_Cached')) { 675 include SMARTY_SYSPLUGINS_DIR . 'smarty_cacheresource.php'; 676 } 677 $this->cached = new Smarty_Template_Cached($this); 678 679 return $this->cached; 680 681 case 'compiler': 682 $this->smarty->loadPlugin($this->source->compiler_class); 683 $this->compiler = new $this->source->compiler_class($this->source->template_lexer_class, $this->source->template_parser_class, $this->smarty); 684 685 return $this->compiler; 686 687 // FIXME: routing of template -> smarty attributes 688 default: 689 if (property_exists($this->smarty, $property_name)) { 690 return $this->smarty->$property_name; 691 } 692 } 693 694 throw new SmartyException("template property '$property_name' does not exist."); 695 } 696 697 /** 698 * Template data object destrutor 699 * 700 */ 701 public function __destruct() 702 { 703 if ($this->smarty->cache_locking && isset($this->cached) && $this->cached->is_locked) { 704 $this->cached->handler->releaseLock($this->smarty, $this->cached); 705 } 706 } 707 708} 709