4  * Smarty Internal Plugin Template
 
   6  * This file contains the Smarty template engine
 
   9  * @subpackage Templates
 
  14  * Main class with template data structures and methods
 
  16 class Smarty_Internal_Template extends Smarty_Internal_Data {
 
  18     public $compiler_object = null;
 
  19     public $cacher_object = null; 
 
  21     public $cache_id = null;
 
  22     public $compile_id = null;
 
  23     public $caching = null;
 
  24     public $cache_lifetime = null;
 
  25     public $cacher_class = null;
 
  26     public $caching_type = null;
 
  27     public $forceNocache = false; 
 
  29     public $template_resource = null;
 
  30     public $resource_type = null;
 
  31     public $resource_name = null;
 
  32 //    public $resource_object = null;
 
  33     private $isExisting = null;
 
  34     public $templateUid = ''; 
 
  36     public $template_filepath = null;
 
  37     public $template_source = null;
 
  38     private $template_timestamp = null; 
 
  40     private $compiled_filepath = null;
 
  41     public $compiled_template = null;
 
  42     private $compiled_timestamp = null;
 
  43     public $mustCompile = null;
 
  44     public $suppressHeader = false;
 
  45     public $suppressFileDependency = false;
 
  46     public $has_nocache_code = false; 
 
  47     public $write_compiled_code = true; 
 
  49     public $rendered_content = null; 
 
  51     private $cached_filepath = null;
 
  52     public $cached_timestamp = null;
 
  53     private $isCached = null;
 
  54 //    private $cache_resource_object = null;
 
  55     private $cacheFileChecked = false; 
 
  57     public $tpl_vars = array();
 
  58     public $parent = null;
 
  59     public $config_vars = array(); 
 
  61     public $plugin_data = array(); 
 
  63     public $properties = array ('file_dependency' => array(),
 
  65         'function' => array()); 
 
  67     public $required_plugins = array('compiled' => array(), 'nocache' => array());
 
  68     public $saved_modifier = null;
 
  69     public $smarty = null;
 
  70     // blocks for template inheritance
 
  71     public $block_data = array();
 
  72     public $wrapper = null;
 
  74      * Create template data object
 
  76      * Some of the global Smarty settings copied to template scope
 
  77      * It load the required template resources and cacher plugins
 
  79      * @param string $template_resource template resource string
 
  80      * @param object $_parent back pointer to parent object with variables or null
 
  81      * @param mixed $_cache_id cache id or null
 
  82      * @param mixed $_compile_id compile id or null
 
  84     public function __construct($template_resource, $smarty, $_parent = null, $_cache_id = null, $_compile_id = null, $_caching = null, $_cache_lifetime = null)
 
  86         $this->smarty = &$smarty; 
 
  88         $this->cache_id = $_cache_id === null ? $this->smarty->cache_id : $_cache_id;
 
  89         $this->compile_id = $_compile_id === null ? $this->smarty->compile_id : $_compile_id;
 
  90         $this->caching = $_caching === null ? $this->smarty->caching : $_caching;
 
  91         if ($this->caching === true) $this->caching =  Smarty::CACHING_LIFETIME_CURRENT;
 
  92         $this->cache_lifetime = $_cache_lifetime === null ?$this->smarty->cache_lifetime : $_cache_lifetime;
 
  93         $this->parent = $_parent; 
 
  94         // dummy local smarty variable
 
  95         $this->tpl_vars['smarty'] = new Smarty_Variable; 
 
  97         $this->template_resource = $template_resource; 
 
  98         // copy block data of template inheritance
 
  99         if ($this->parent instanceof Smarty_Internal_Template) {
 
 100                 $this->block_data = $this->parent->block_data;
 
 106      * Returns the template filepath
 
 108      * The template filepath is determined by the actual resource handler
 
 110      * @return string the template filepath
 
 112     public function getTemplateFilepath ()
 
 114         return $this->template_filepath === null ?
 
 115         $this->template_filepath = $this->resource_object->getTemplateFilepath($this) :
 
 116         $this->template_filepath;
 
 120      * Returns the timpestamp of the template source
 
 122      * The template timestamp is determined by the actual resource handler
 
 124      * @return integer the template timestamp
 
 126     public function getTemplateTimestamp ()
 
 128         return $this->template_timestamp === null ?
 
 129         $this->template_timestamp = $this->resource_object->getTemplateTimestamp($this) :
 
 130         $this->template_timestamp;
 
 134      * Returns the template source code
 
 136      * The template source is being read by the actual resource handler
 
 138      * @return string the template source
 
 140     public function getTemplateSource ()
 
 142         if ($this->template_source === null) {
 
 143             if (!$this->resource_object->getTemplateSource($this)) {
 
 144                 throw new SmartyException("Unable to read template {$this->resource_type} '{$this->resource_name}'");
 
 147         return $this->template_source;
 
 151      * Returns if the  template is existing
 
 153      * The status is determined by the actual resource handler
 
 155      * @return boolean true if the template exists
 
 157     public function isExisting ($error = false)
 
 159         if ($this->isExisting === null) {
 
 160             $this->isExisting = $this->resource_object->isExisting($this);
 
 162         if (!$this->isExisting && $error) {
 
 163             throw new SmartyException("Unable to load template {$this->resource_type} '{$this->resource_name}'");
 
 165         return $this->isExisting;
 
 169      * Returns if the current template must be compiled by the Smarty compiler
 
 171      * It does compare the timestamps of template source and the compiled templates and checks the force compile configuration
 
 173      * @return boolean true if the template must be compiled
 
 175     public function mustCompile ()
 
 177         $this->isExisting(true);
 
 178         if ($this->mustCompile === null) {
 
 179             $this->mustCompile = ($this->resource_object->usesCompiler && ($this->smarty->force_compile || $this->resource_object->isEvaluated || $this->getCompiledTimestamp () === false || 
 
 180                     // ($this->smarty->compile_check && $this->getCompiledTimestamp () !== $this->getTemplateTimestamp ())));
 
 181                     ($this->smarty->compile_check && $this->getCompiledTimestamp () < $this->getTemplateTimestamp ())));
 
 183         return $this->mustCompile;
 
 187      * Returns the compiled template filepath
 
 189      * @return string the template filepath
 
 191     public function getCompiledFilepath ()
 
 193         return $this->compiled_filepath === null ?
 
 194         ($this->compiled_filepath = !$this->resource_object->isEvaluated ? $this->resource_object->getCompiledFilepath($this) : false) :
 
 195         $this->compiled_filepath;
 
 199      * Returns the timpestamp of the compiled template
 
 201      * @return integer the template timestamp
 
 203     public function getCompiledTimestamp ()
 
 205         return $this->compiled_timestamp === null ?
 
 206         ($this->compiled_timestamp = (!$this->resource_object->isEvaluated && file_exists($this->getCompiledFilepath())) ? filemtime($this->getCompiledFilepath()) : false) :
 
 207         $this->compiled_timestamp;
 
 211      * Returns the compiled template 
 
 213      * It checks if the template must be compiled or just read from the template resource
 
 215      * @return string the compiled template
 
 217     public function getCompiledTemplate ()
 
 219         if ($this->compiled_template === null) {
 
 220             // see if template needs compiling.
 
 221             if ($this->mustCompile()) {
 
 222                 $this->compileTemplateSource();
 
 224                 if ($this->compiled_template === null) {
 
 225                     $this->compiled_template = !$this->resource_object->isEvaluated && $this->resource_object->usesCompiler ? file_get_contents($this->getCompiledFilepath()) : false;
 
 229         return $this->compiled_template;
 
 233      * Compiles the template
 
 235      * If the template is not evaluated the compiled template is saved on disk
 
 237     public function compileTemplateSource ()
 
 239         if (!$this->resource_object->isEvaluated) {
 
 240             $this->properties['file_dependency'] = array();
 
 241             $this->properties['file_dependency'][$this->templateUid] = array($this->getTemplateFilepath(), $this->getTemplateTimestamp(),$this->resource_type);
 
 243         if ($this->smarty->debugging) {
 
 244             Smarty_Internal_Debug::start_compile($this);
 
 247         if (!is_object($this->compiler_object)) {
 
 249             $this->smarty->loadPlugin($this->resource_object->compiler_class);
 
 250             $this->compiler_object = new $this->resource_object->compiler_class($this->resource_object->template_lexer_class, $this->resource_object->template_parser_class, $this->smarty);
 
 253         if ($this->smarty->compile_locking && !$this->resource_object->isEvaluated) {
 
 254             if ($saved_timestamp = $this->getCompiledTimestamp()) {
 
 255                 touch($this->getCompiledFilepath());
 
 260             $this->compiler_object->compileTemplate($this);
 
 262         catch (Exception $e) {
 
 263             // restore old timestamp in case of error
 
 264             if ($this->smarty->compile_locking && !$this->resource_object->isEvaluated && $saved_timestamp) {
 
 265                 touch($this->getCompiledFilepath(), $saved_timestamp);
 
 269         // compiling succeded
 
 270         if (!$this->resource_object->isEvaluated && $this->write_compiled_code) {
 
 271             // write compiled template
 
 272             Smarty_Internal_Write_File::writeFile($this->getCompiledFilepath(), $this->compiled_template, $this->smarty);
 
 274         if ($this->smarty->debugging) {
 
 275             Smarty_Internal_Debug::end_compile($this);
 
 277         // release objects to free memory
 
 278                 Smarty_Internal_TemplateCompilerBase::$_tag_objects = array();  
 
 279         unset($this->compiler_object->parser->root_buffer,
 
 280                 $this->compiler_object->parser->current_buffer,
 
 281                 $this->compiler_object->parser,
 
 282                 $this->compiler_object->lex,
 
 283                 $this->compiler_object->template,
 
 284                 $this->compiler_object
 
 289      * Returns the filepath of the cached template output
 
 291      * The filepath is determined by the actual cache resource
 
 293      * @return string the cache filepath
 
 295     public function getCachedFilepath ()
 
 297         return $this->cached_filepath === null ?
 
 298         $this->cached_filepath = ($this->resource_object->isEvaluated || !($this->caching == Smarty::CACHING_LIFETIME_CURRENT || $this->caching == Smarty::CACHING_LIFETIME_SAVED)) ? false : $this->cache_resource_object->getCachedFilepath($this) :
 
 299         $this->cached_filepath;
 
 303      * Returns the timpestamp of the cached template output
 
 305      * The timestamp is determined by the actual cache resource
 
 307      * @return integer the template timestamp
 
 309     public function getCachedTimestamp ()
 
 311         return $this->cached_timestamp === null ?
 
 312         $this->cached_timestamp = ($this->resource_object->isEvaluated || !($this->caching == Smarty::CACHING_LIFETIME_CURRENT || $this->caching == Smarty::CACHING_LIFETIME_SAVED)) ? false : $this->cache_resource_object->getCachedTimestamp($this) :
 
 313         $this->cached_timestamp;
 
 317      * Returns the cached template output
 
 319      * @return string |booelan the template content or false if the file does not exist
 
 321     public function getCachedContent ()
 
 323         return $this->rendered_content === null ?
 
 324         $this->rendered_content = ($this->resource_object->isEvaluated || !($this->caching == Smarty::CACHING_LIFETIME_CURRENT || $this->caching == Smarty::CACHING_LIFETIME_SAVED)) ? false : $this->cache_resource_object->getCachedContents($this) :
 
 325         $this->rendered_content;
 
 329      * Writes the cached template output
 
 331     public function writeCachedContent ($content)
 
 333         if ($this->resource_object->isEvaluated || !($this->caching == Smarty::CACHING_LIFETIME_CURRENT || $this->caching == Smarty::CACHING_LIFETIME_SAVED)) {
 
 334             // don't write cache file
 
 337         $this->properties['cache_lifetime'] = $this->cache_lifetime;
 
 338         return $this->cache_resource_object->writeCachedContent($this, $this->createPropertyHeader(true) .$content);
 
 342      * Checks of a valid version redered HTML output is in the cache
 
 344      * If the cache is valid the contents is stored in the template object
 
 346      * @return boolean true if cache is valid
 
 348     public function isCached ($template = null, $cache_id = null, $compile_id = null, $parent = null)
 
 350         if ($template === null) {               
 
 352                 } elseif ($template === false) {
 
 355                         if ($parent === null) {
 
 358                         $this->smarty->isCached ($template, $cache_id, $compile_id, $parent);
 
 360         if ($this->isCached === null) {
 
 361             $this->isCached = false;
 
 362             if (($this->caching == Smarty::CACHING_LIFETIME_CURRENT || $this->caching == Smarty::CACHING_LIFETIME_SAVED) && !$this->resource_object->isEvaluated) {
 
 363                 $cachedTimestamp = $this->getCachedTimestamp();
 
 364                 if ($cachedTimestamp === false || $this->smarty->force_compile || $this->smarty->force_cache) {
 
 365                     return $this->isCached;
 
 367                 if ($this->caching === Smarty::CACHING_LIFETIME_SAVED || ($this->caching == Smarty::CACHING_LIFETIME_CURRENT && (time() <= ($cachedTimestamp + $this->cache_lifetime) || $this->cache_lifetime < 0))) {
 
 368                     if ($this->smarty->debugging) {
 
 369                         Smarty_Internal_Debug::start_cache($this);
 
 371                     $this->rendered_content = $this->cache_resource_object->getCachedContents($this, $no_render);
 
 372                     if ($this->smarty->debugging) {
 
 373                         Smarty_Internal_Debug::end_cache($this);
 
 375                     if ($this->cacheFileChecked) {
 
 376                         $this->isCached = true;
 
 377                         return $this->isCached;
 
 379                     $this->cacheFileChecked = true;
 
 380                     if ($this->caching === Smarty::CACHING_LIFETIME_SAVED && $this->properties['cache_lifetime'] >= 0 && (time() > ($this->getCachedTimestamp() + $this->properties['cache_lifetime']))) {
 
 381                         $this->tpl_vars = array();
 
 382                         $this->rendered_content = null;
 
 383                         return $this->isCached;
 
 385                     if (!empty($this->properties['file_dependency']) && $this->smarty->compile_check) {
 
 386                         $resource_type = null;
 
 387                         $resource_name = null;
 
 388                         foreach ($this->properties['file_dependency'] as $_file_to_check) {
 
 389                             If ($_file_to_check[2] == 'file' || $_file_to_check[2] == 'extends' || $_file_to_check[2] == 'php') {
 
 390                                 $mtime = filemtime($_file_to_check[0]);
 
 392                                 $this->getResourceTypeName($_file_to_check[0], $resource_type, $resource_name);
 
 393                                 $resource_handler = $this->loadTemplateResourceHandler($resource_type);
 
 394                                 $mtime = $resource_handler->getTemplateTimestampTypeName($resource_type, $resource_name);
 
 396                             // If ($mtime > $this->getCachedTimestamp()) {
 
 397                             If ($mtime > $_file_to_check[1]) {
 
 398                                 $this->tpl_vars = array();
 
 399                                 $this->rendered_content = null;
 
 400                                 return $this->isCached;
 
 404                     $this->isCached = true;
 
 408         return $this->isCached;
 
 412      * Render the output using the compiled template or the PHP template source
 
 414      * The rendering process is accomplished by just including the PHP files.
 
 415      * The only exceptions are evaluated templates (string template). Their code has 
 
 418     public function renderTemplate ()
 
 420         if ($this->resource_object->usesCompiler) {
 
 421             if ($this->mustCompile() && $this->compiled_template === null) {
 
 422                 $this->compileTemplateSource();
 
 424             if ($this->smarty->debugging) {
 
 425                 Smarty_Internal_Debug::start_render($this);
 
 427             $_smarty_tpl = $this;
 
 429             if ($this->resource_object->isEvaluated) {
 
 430                 eval("?>" . $this->compiled_template);
 
 432                 include($this->getCompiledFilepath ()); 
 
 433                 // check file dependencies at compiled code
 
 434                 if ($this->smarty->compile_check) {
 
 435                     if (!empty($this->properties['file_dependency'])) {
 
 436                         $this->mustCompile = false;
 
 437                         $resource_type = null;
 
 438                         $resource_name = null;
 
 439                         foreach ($this->properties['file_dependency'] as $_file_to_check) {
 
 440                             If ($_file_to_check[2] == 'file' || $_file_to_check[2] == 'extends' || $_file_to_check[2] == 'php') {
 
 441                                 $mtime = filemtime($_file_to_check[0]);
 
 443                                 $this->getResourceTypeName($_file_to_check[0], $resource_type, $resource_name);
 
 444                                 $resource_handler = $this->loadTemplateResourceHandler($resource_type);
 
 445                                 $mtime = $resource_handler->getTemplateTimestampTypeName($resource_type, $resource_name);
 
 447                             // If ($mtime != $_file_to_check[1]) {
 
 448                             If ($mtime > $_file_to_check[1]) {
 
 449                                 $this->mustCompile = true;
 
 453                         if ($this->mustCompile) {
 
 454                             // recompile and render again
 
 456                             $this->compileTemplateSource();
 
 458                             include($this->getCompiledFilepath ());
 
 464             if (is_callable(array($this->resource_object, 'renderUncompiled'))) {
 
 465                 if ($this->smarty->debugging) {
 
 466                     Smarty_Internal_Debug::start_render($this);
 
 469                 $this->resource_object->renderUncompiled($this);
 
 471                 throw new SmartyException("Resource '$this->resource_type' must have 'renderUncompiled' methode");
 
 474         $this->rendered_content = ob_get_clean();
 
 475         if (!$this->resource_object->isEvaluated && empty($this->properties['file_dependency'][$this->templateUid])) {
 
 476             $this->properties['file_dependency'][$this->templateUid] = array($this->getTemplateFilepath(), $this->getTemplateTimestamp(),$this->resource_type);
 
 478         if ($this->parent instanceof Smarty_Internal_Template) {
 
 479             $this->parent->properties['file_dependency'] = array_merge($this->parent->properties['file_dependency'], $this->properties['file_dependency']);
 
 480             foreach($this->required_plugins as $code => $tmp1) {
 
 481                 foreach($tmp1 as $name => $tmp) {
 
 482                     foreach($tmp as $type => $data) {
 
 483                         $this->parent->required_plugins[$code][$name][$type] = $data;
 
 488         if ($this->smarty->debugging) {
 
 489             Smarty_Internal_Debug::end_render($this);
 
 491         // write to cache when nessecary
 
 492         if (!$this->resource_object->isEvaluated && ($this->caching == Smarty::CACHING_LIFETIME_SAVED || $this->caching == Smarty::CACHING_LIFETIME_CURRENT)) {
 
 493             if ($this->smarty->debugging) {
 
 494                 Smarty_Internal_Debug::start_cache($this);
 
 496             $this->properties['has_nocache_code'] = false; 
 
 497             // get text between non-cached items
 
 498             $cache_split = preg_split("!/\*%%SmartyNocache:{$this->properties['nocache_hash']}%%\*\/(.+?)/\*/%%SmartyNocache:{$this->properties['nocache_hash']}%%\*/!s", $this->rendered_content); 
 
 499             // get non-cached items
 
 500             preg_match_all("!/\*%%SmartyNocache:{$this->properties['nocache_hash']}%%\*\/(.+?)/\*/%%SmartyNocache:{$this->properties['nocache_hash']}%%\*/!s", $this->rendered_content, $cache_parts);
 
 502             // loop over items, stitch back together
 
 503             foreach($cache_split as $curr_idx => $curr_split) {
 
 504                 // escape PHP tags in template content
 
 505                 $output .= preg_replace('/(<%|%>|<\?php|<\?|\?>)/', '<?php echo \'$1\'; ?>', $curr_split);
 
 506                 if (isset($cache_parts[0][$curr_idx])) {
 
 507                     $this->properties['has_nocache_code'] = true; 
 
 508                     // remove nocache tags from cache output
 
 509                     $output .= preg_replace("!/\*/?%%SmartyNocache:{$this->properties['nocache_hash']}%%\*/!", '', $cache_parts[0][$curr_idx]);
 
 512             if (isset($this->smarty->autoload_filters['output']) || isset($this->smarty->registered_filters['output'])) {
 
 513                 $output = Smarty_Internal_Filter_Handler::runFilter('output', $output, $this);
 
 515             // rendering (must be done before writing cache file because of {function} nocache handling)
 
 516             $_smarty_tpl = $this;
 
 518             eval("?>" . $output);
 
 519             $this->rendered_content = ob_get_clean(); 
 
 520             // write cache file content
 
 521             $this->writeCachedContent('<?php if (!$no_render) {?>'. $output. '<?php } ?>');
 
 522             if ($this->smarty->debugging) {
 
 523                 Smarty_Internal_Debug::end_cache($this);
 
 526             // var_dump('renderTemplate', $this->has_nocache_code, $this->template_resource, $this->properties['nocache_hash'], $this->parent->properties['nocache_hash'], $this->rendered_content);
 
 527             if ($this->has_nocache_code && !empty($this->properties['nocache_hash']) && !empty($this->parent->properties['nocache_hash'])) {
 
 528                 // replace nocache_hash
 
 529                 $this->rendered_content = preg_replace("/{$this->properties['nocache_hash']}/", $this->parent->properties['nocache_hash'], $this->rendered_content);
 
 530                 $this->parent->has_nocache_code = $this->has_nocache_code;
 
 536      * Returns the rendered HTML output 
 
 538      * If the cache is valid the cached content is used, otherwise
 
 539      * the output is rendered from the compiled template or PHP template source
 
 541      * @return string rendered HTML output
 
 543     public function getRenderedTemplate ()
 
 545         // disable caching for evaluated code
 
 546         if ($this->resource_object->isEvaluated) {
 
 547             $this->caching = false;
 
 549         // checks if template exists
 
 550         $this->isExisting(true); 
 
 551         // read from cache or render
 
 552         if ($this->rendered_content === null) {
 
 553                 if ($this->isCached) {
 
 554                         if ($this->smarty->debugging) {
 
 555                 Smarty_Internal_Debug::start_cache($this);
 
 557             $this->rendered_content = $this->cache_resource_object->getCachedContents($this, false);
 
 558             if ($this->smarty->debugging) {
 
 559                 Smarty_Internal_Debug::end_cache($this);
 
 562           if ($this->isCached === null) { 
 
 563             $this->isCached(false); 
 
 565           if (!$this->isCached) {          
 
 566             // render template (not loaded and not in cache)
 
 567             $this->renderTemplate();
 
 570         $this->updateParentVariables();
 
 571         $this->isCached = null;
 
 572         return $this->rendered_content;
 
 576      * Parse a template resource in its name and type
 
 577      * Load required resource handler
 
 579      * @param string $template_resource template resource specification
 
 580      * @param string $resource_type return resource type
 
 581      * @param string $resource_name return resource name
 
 582      * @param object $resource_handler return resource handler object
 
 584     public function parseResourceName($template_resource, &$resource_type, &$resource_name, &$resource_handler)
 
 586         if (empty($template_resource))
 
 588         $this->getResourceTypeName($template_resource, $resource_type, $resource_name);
 
 589         $resource_handler = $this->loadTemplateResourceHandler($resource_type); 
 
 590         // cache template object under a unique ID
 
 591         // do not cache eval resources
 
 592         if ($resource_type != 'eval') {
 
 593             $this->smarty->template_objects[sha1($this->template_resource . $this->cache_id . $this->compile_id)] = $this;
 
 599      * get system filepath to template
 
 601     public function buildTemplateFilepath ($file = null)
 
 604             $file = $this->resource_name;
 
 606         // relative file name? 
 
 607         if (!preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $file)) {
 
 608                 foreach((array)$this->smarty->template_dir as $_template_dir) {
 
 609                         if (strpos('/\\', substr($_template_dir, -1)) === false) {
 
 610                         $_template_dir .= DS;
 
 612                 $_filepath = $_template_dir . $file;
 
 613                 if (file_exists($_filepath)) {
 
 616                         if (!preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $_template_dir)) {
 
 617                                 // try PHP include_path
 
 618                                 if (($_filepath = Smarty_Internal_Get_Include_Path::getIncludePath($_filepath)) !== false) {
 
 624         // try absolute filepath
 
 625         if (file_exists($file)) return $file;
 
 627         if (!empty($this->smarty->default_template_handler_func)) {
 
 628             if (!is_callable($this->smarty->default_template_handler_func)) {
 
 629                 throw new SmartyException("Default template handler not callable");
 
 631                 $_return = call_user_func_array($this->smarty->default_template_handler_func,
 
 632                     array($this->resource_type, $this->resource_name, &$this->template_source, &$this->template_timestamp, $this));
 
 633                 if (is_string($_return)) {
 
 635                 } elseif ($_return === true) {
 
 644      * Update Smarty variables in other scopes
 
 646     public function updateParentVariables ($scope = Smarty::SCOPE_LOCAL)
 
 649         foreach ($this->tpl_vars as $_key => $_variable) {
 
 650             $_variable_scope = $this->tpl_vars[$_key]->scope;
 
 651             if ($scope == Smarty::SCOPE_LOCAL && $_variable_scope == Smarty::SCOPE_LOCAL) {
 
 654             if (isset($this->parent) && ($scope == Smarty::SCOPE_PARENT || $_variable_scope == Smarty::SCOPE_PARENT)) {
 
 655                 if (isset($this->parent->tpl_vars[$_key])) {
 
 656                     // variable is already defined in parent, copy value
 
 657                     $this->parent->tpl_vars[$_key]->value = $this->tpl_vars[$_key]->value;
 
 659                     // create variable in parent
 
 660                     $this->parent->tpl_vars[$_key] = clone $_variable;
 
 661                     $this->parent->tpl_vars[$_key]->scope = Smarty::SCOPE_LOCAL;
 
 664             if ($scope == Smarty::SCOPE_ROOT || $_variable_scope == Smarty::SCOPE_ROOT) {
 
 665                 if ($this->parent == null) {
 
 671                     while ($root_ptr->parent != null) {
 
 672                         $root_ptr = $root_ptr->parent;
 
 676                 if (isset($root_ptr->tpl_vars[$_key])) {
 
 677                     // variable is already defined in root, copy value
 
 678                     $root_ptr->tpl_vars[$_key]->value = $this->tpl_vars[$_key]->value;
 
 680                     // create variable in root
 
 681                     $root_ptr->tpl_vars[$_key] = clone $_variable;
 
 682                     $root_ptr->tpl_vars[$_key]->scope = Smarty::SCOPE_LOCAL;
 
 685             if ($scope == Smarty::SCOPE_GLOBAL || $_variable_scope == Smarty::SCOPE_GLOBAL) {
 
 686                 if (isset(Smarty::$global_tpl_vars[$_key])) {
 
 687                     // variable is already defined in root, copy value
 
 688                     Smarty::$global_tpl_vars[$_key]->value = $this->tpl_vars[$_key]->value;
 
 690                     // create global variable
 
 691                    Smarty::$global_tpl_vars[$_key] = clone $_variable;
 
 693                Smarty::$global_tpl_vars[$_key]->scope = Smarty::SCOPE_LOCAL;
 
 699      * Split a template resource in its name and type
 
 701      * @param string $template_resource template resource specification
 
 702      * @param string $resource_type return resource type
 
 703      * @param string $resource_name return resource name
 
 705     protected function getResourceTypeName ($template_resource, &$resource_type, &$resource_name)
 
 707         if (strpos($template_resource, ':') === false) {
 
 708             // no resource given, use default
 
 709             $resource_type = $this->smarty->default_resource_type;
 
 710             $resource_name = $template_resource;
 
 712             // get type and name from path
 
 713             list($resource_type, $resource_name) = explode(':', $template_resource, 2);
 
 714             if (strlen($resource_type) == 1) {
 
 715                 // 1 char is not resource type, but part of filepath
 
 716                 $resource_type = 'file';
 
 717                 $resource_name = $template_resource;
 
 723      * Load template resource handler by type
 
 725      * @param string $resource_type template resource type
 
 726      * @return object resource handler object
 
 728     protected function loadTemplateResourceHandler ($resource_type)
 
 730         // try registered resource
 
 731         if (isset($this->smarty->registered_resources[$resource_type])) {
 
 732             return new Smarty_Internal_Resource_Registered($this);
 
 734             // try sysplugins dir
 
 735             if (in_array($resource_type, array('file', 'string', 'extends', 'php', 'stream', 'eval'))) {
 
 736                 $_resource_class = 'Smarty_Internal_Resource_' . ucfirst($resource_type);
 
 737                 return new $_resource_class($this->smarty);
 
 740                 $_resource_class = 'Smarty_Resource_' . ucfirst($resource_type);
 
 741                 if ($this->smarty->loadPlugin($_resource_class)) {
 
 742                     if (class_exists($_resource_class, false)) {
 
 743                         return new $_resource_class($this->smarty);
 
 745                         return new Smarty_Internal_Resource_Registered($this, $resource_type);
 
 749                     $_known_stream = stream_get_wrappers();
 
 750                     if (in_array($resource_type, $_known_stream)) {
 
 752                         if (is_object($this->smarty->security_policy)) {
 
 753                             $this->smarty->security_policy->isTrustedStream($resource_type);
 
 755                         return new Smarty_Internal_Resource_Stream($this->smarty);
 
 757                         throw new SmartyException('Unkown resource type \'' . $resource_type . '\'');
 
 765      * Create property header
 
 767     public function createPropertyHeader ($cache = false)
 
 769         $plugins_string = ''; 
 
 770         // include code for plugins
 
 772             if (!empty($this->required_plugins['compiled'])) {
 
 773                 $plugins_string = '<?php ';
 
 774                 foreach($this->required_plugins['compiled'] as $tmp) {
 
 775                     foreach($tmp as $data) {
 
 776                         $plugins_string .= "if (!is_callable('{$data['function']}')) include '{$data['file']}';\n";
 
 779                 $plugins_string .= '?>';
 
 781             if (!empty($this->required_plugins['nocache'])) {
 
 782                 $this->has_nocache_code = true;
 
 783                 $plugins_string .= "<?php echo '/*%%SmartyNocache:{$this->properties['nocache_hash']}%%*/<?php ";
 
 784                 foreach($this->required_plugins['nocache'] as $tmp) {
 
 785                     foreach($tmp as $data) {
 
 786                         $plugins_string .= "if (!is_callable(\'{$data['function']}\')) include \'{$data['file']}\';\n";
 
 789                 $plugins_string .= "?>/*/%%SmartyNocache:{$this->properties['nocache_hash']}%%*/';?>\n";
 
 792         // build property code
 
 793         $this->properties['has_nocache_code'] = $this->has_nocache_code;
 
 794         $properties_string = "<?php /*%%SmartyHeaderCode:{$this->properties['nocache_hash']}%%*/" ;
 
 795         if ($this->smarty->direct_access_security) {
 
 796             $properties_string .= "if(!defined('SMARTY_DIR')) exit('no direct access allowed');\n";
 
 799             // remove compiled code of{function} definition
 
 800             unset($this->properties['function']);
 
 801             if (!empty($this->smarty->template_functions)) {
 
 802                 // copy code of {function} tags called in nocache mode
 
 803                 foreach ($this->smarty->template_functions as $name => $function_data) {
 
 804                     if (isset($function_data['called_nocache'])) {
 
 805                         unset($function_data['called_nocache'], $this->smarty->template_functions[$name]['called_nocache']);
 
 806                         $this->properties['function'][$name] = $function_data;
 
 811         $properties_string .= "\$_smarty_tpl->decodeProperties(" . var_export($this->properties, true) . "); /*/%%SmartyHeaderCode%%*/?>\n";
 
 812         return $properties_string . $plugins_string;
 
 816      * Decode saved properties from compiled template and cache files
 
 818     public function decodeProperties ($properties)
 
 820         $this->has_nocache_code = $properties['has_nocache_code'];
 
 821         $this->properties['nocache_hash'] = $properties['nocache_hash'];
 
 822         if (isset($properties['cache_lifetime'])) {
 
 823             $this->properties['cache_lifetime'] = $properties['cache_lifetime'];
 
 825         if (isset($properties['file_dependency'])) {
 
 826             $this->properties['file_dependency'] = array_merge($this->properties['file_dependency'], $properties['file_dependency']);
 
 828         if (!empty($properties['function'])) {
 
 829             $this->properties['function'] = array_merge($this->properties['function'], $properties['function']);
 
 830             $this->smarty->template_functions = array_merge($this->smarty->template_functions, $properties['function']);
 
 835      * creates a local Smarty variable for array assignments
 
 837     public function createLocalArrayVariable($tpl_var, $nocache = false, $scope = Smarty::SCOPE_LOCAL)
 
 839         if (!isset($this->tpl_vars[$tpl_var])) {
 
 840             $tpl_var_inst = $this->getVariable($tpl_var, null, true, false);
 
 841             if ($tpl_var_inst instanceof Undefined_Smarty_Variable) {
 
 842                 $this->tpl_vars[$tpl_var] = new Smarty_variable(array(), $nocache, $scope);
 
 844                 $this->tpl_vars[$tpl_var] = clone $tpl_var_inst;
 
 845                 if ($scope != Smarty::SCOPE_LOCAL) {
 
 846                     $this->tpl_vars[$tpl_var]->scope = $scope;
 
 850         if (!(is_array($this->tpl_vars[$tpl_var]->value) || $this->tpl_vars[$tpl_var]->value instanceof ArrayAccess)) {
 
 851             settype($this->tpl_vars[$tpl_var]->value, 'array');
 
 856      * [util function] counts an array, arrayaccess/traversable or PDOStatement object
 
 857      * @param mixed $value
 
 858      * @return int the count for arrays and objects that implement countable, 1 for other objects that don't, and 0 for empty elements
 
 860     public function _count($value)
 
 862         if (is_array($value) === true || $value instanceof Countable) {
 
 863             return count($value);
 
 864         } elseif ($value instanceof Iterator) {
 
 866             if ($value->valid()) {
 
 867                 return iterator_count($value);
 
 869         } elseif ($value instanceof PDOStatement) {
 
 870             return $value->rowCount();
 
 871         } elseif ($value instanceof Traversable) {
 
 872             return iterator_count($value);
 
 873         } elseif ($value instanceof ArrayAccess) {
 
 874             if ($value->offsetExists(0)) {
 
 877        } elseif (is_object($value)) {
 
 878             return count($value);
 
 886     public function fetch ($template = null, $cache_id = null, $compile_id = null, $parent = null, $display = false)
 
 888                 if ($template == null) {
 
 889                 return $this->smarty->fetch($this);
 
 891                 if (!isset($parent)) {
 
 894                 return $this->smarty->fetch($template, $cache_id, $compile_id, $parent, $display);
 
 900      * wrapper for display
 
 902     public function display ($template = null, $cache_id = null, $compile_id = null, $parent = null)
 
 904                 if ($template == null) {
 
 905                 return $this->smarty->display($this);
 
 907                 if (!isset($parent)) {
 
 910                 return $this->smarty->display($template, $cache_id, $compile_id, $parent);
 
 916      * set Smarty property in template context      
 
 917      * @param string $property_name property name
 
 918      * @param mixed $value value
 
 920     public function __set($property_name, $value)
 
 922         if ($property_name == 'resource_object' || $property_name == 'cache_resource_object') {
 
 923                 $this->$property_name = $value;
 
 924         } elseif (property_exists($this->smarty, $property_name)) {
 
 925                 $this->smarty->$property_name = $value;
 
 927                 throw new SmartyException("invalid template property '$property_name'.");
 
 932      * get Smarty property in template context      
 
 933      * @param string $property_name property name
 
 935     public function __get($property_name)
 
 937         if ($property_name == 'resource_object') {
 
 938                 // load template resource
 
 939                 $this->resource_object = null;
 
 940                 if (!$this->parseResourceName ($this->template_resource, $this->resource_type, $this->resource_name, $this->resource_object)) {
 
 941                 throw new SmartyException ("Unable to parse resource name \"{$template_resource}\"");
 
 943                 return $this->resource_object;
 
 945         if ($property_name == 'cache_resource_object') { 
 
 946                 // load cache resource
 
 947             $this->cache_resource_object = $this->loadCacheResource();
 
 948             return $this->cache_resource_object;
 
 950         if (property_exists($this->smarty, $property_name)) {
 
 951                 return $this->smarty->$property_name;
 
 953                 throw new SmartyException("template property '$property_name' does not exist.");
 
 959      * Takes unknown class methods and lazy loads sysplugin files for them
 
 960      * class name format: Smarty_Method_MethodName
 
 961      * plugin filename format: method.methodname.php
 
 963      * @param string $name unknown methode name
 
 964      * @param array $args aurgument array
 
 966     public function __call($name, $args)
 
 969         if (!isset($camel_func))
 
 970             $camel_func = create_function('$c', 'return "_" . strtolower($c[1]);'); 
 
 971         // see if this is a set/get for a property
 
 972         $first3 = strtolower(substr($name, 0, 3));
 
 973         if (in_array($first3, array('set', 'get')) && substr($name, 3, 1) !== '_') {
 
 974             // try to keep case correct for future PHP 6.0 case-sensitive class methods
 
 975             // lcfirst() not available < PHP 5.3.0, so improvise
 
 976             $property_name = strtolower(substr($name, 3, 1)) . substr($name, 4); 
 
 977             // convert camel case to underscored name
 
 978             $property_name = preg_replace_callback('/([A-Z])/', $camel_func, $property_name);
 
 979                 if (property_exists($this, $property_name)) {
 
 980                 if ($first3 == 'get')
 
 981                         return $this->$property_name;
 
 983                         return $this->$property_name = $args[0];
 
 986         // Smarty Backward Compatible wrapper
 
 987                 if (strpos($name,'_') !== false) {
 
 988                 if (!isset($this->wrapper)) {
 
 989                  $this->wrapper = new Smarty_Internal_Wrapper($this);
 
 991                 return $this->wrapper->convert($name, $args);
 
 993         // pass call to Smarty object   
 
 994         return call_user_func_array(array($this->smarty,$name),$args);