diff --git a/change_log.txt b/change_log.txt index 28b25161..b1196934 100644 --- a/change_log.txt +++ b/change_log.txt @@ -7,6 +7,7 @@ - use output buffers for better performance and less memory usage - optimize nocache hash processing - remove not really needed properties + - optimize rendering 06.08.2015 - avoid possible circular object references caused by parser/lexer objects diff --git a/libs/Smarty.class.php b/libs/Smarty.class.php index d73c5746..99cf5152 100644 --- a/libs/Smarty.class.php +++ b/libs/Smarty.class.php @@ -756,67 +756,6 @@ class Smarty extends Smarty_Internal_TemplateBase } } - /** - * fetches a rendered Smarty template - * - * @param string $template the resource handle of the template file or template object - * @param mixed $cache_id cache id to be used with this template - * @param mixed $compile_id compile id to be used with this template - * @param object $parent next higher level of Smarty variables - * @param bool $display true: display, false: fetch - * @param bool $merge_tpl_vars not used - left for BC - * @param bool $no_output_filter not used - left for BC - * - * @throws Exception - * @throws SmartyException - * @return string rendered template output - */ - public function fetch($template, $cache_id = null, $compile_id = null, $parent = null, $display = false, $merge_tpl_vars = true, $no_output_filter = false) - { - if ($cache_id !== null && is_object($cache_id)) { - $parent = $cache_id; - $cache_id = null; - } - if ($parent === null) { - $parent = $this; - } - // get template object - $_template = is_object($template) ? $template : $this->createTemplate($template, $cache_id, $compile_id, $parent, false); - // set caching in template object - $_template->caching = $this->caching; - // fetch template content - $level = ob_get_level(); - try { - $_smarty_old_error_level = isset($this->error_reporting) ? error_reporting($this->error_reporting) : null; - ob_start(); - $result = $_template->render(true, false, $display); - if (isset($_smarty_old_error_level)) { - error_reporting($_smarty_old_error_level); - } - return $result === null ? ob_get_clean() : $result; - } - catch (Exception $e) { - while (ob_get_level() > $level) { - ob_end_clean(); - } - throw $e; - } - } - - /** - * displays a Smarty template - * - * @param string $template the resource handle of the template file or template object - * @param mixed $cache_id cache id to be used with this template - * @param mixed $compile_id compile id to be used with this template - * @param object $parent next higher level of Smarty variables - */ - public function display($template, $cache_id = null, $compile_id = null, $parent = null) - { - // display template - $this->fetch($template, $cache_id, $compile_id, $parent, true); - } - /** * Check if a template resource exists * @@ -1180,10 +1119,20 @@ class Smarty extends Smarty_Internal_TemplateBase } else { $data = null; } - /* var Smarty $tpl */ - $tpl = new $this->template_class($template, $this, $parent, $cache_id, $compile_id); + $_templateId = $this->_getTemplateId($template, $cache_id, $compile_id); + if (isset($this->_cache['isCached'][$_templateId])) { + $tpl = $do_clone ? clone $this->_cache['isCached'][$_templateId] : $this->_cache['isCached'][$_templateId]; + $tpl->parent = $parent; + $tpl->tpl_vars = array(); + $tpl->config_vars = array(); + } else { + /* @var Smarty_Internal_Template $tpl */ + $tpl = new $this->template_class($template, $this, $parent, $cache_id, $compile_id, null, null, $_templateId); + } if ($do_clone) { $tpl->smarty = clone $tpl->smarty; + } elseif ($parent === null) { + $tpl->parent = $this; } // fill data if present if (!empty($data) && is_array($data)) { @@ -1214,6 +1163,31 @@ class Smarty extends Smarty_Internal_TemplateBase return Smarty_Internal_Extension_LoadPlugin::loadPlugin($this, $plugin_name, $check); } + /** + * Get unique template id + * + * @param string $template_name + * @param null|mixed $cache_id + * @param null|mixed $compile_id + * + * @return string + */ + public function _getTemplateId($template_name, $cache_id = null, $compile_id = null) + { + $cache_id = $cache_id === null ? $this->cache_id : $cache_id; + $compile_id = $compile_id === null ? $this->compile_id : $compile_id; + + if ($this->allow_ambiguous_resources) { + $_templateId = Smarty_Resource::getUniqueTemplateName($this, $template_name) . "#{$cache_id}#{$compile_id}"; + } else { + $_templateId = $this->_joined_template_dir . "#{$template_name}#{$cache_id}#{$compile_id}"; + } + if (isset($_templateId[150])) { + $_templateId = sha1($_templateId); + } + return $_templateId; + } + /** * Normalize path * - remove /./ and /../ diff --git a/libs/sysplugins/smarty_internal_method_configload.php b/libs/sysplugins/smarty_internal_method_configload.php index f3ddc170..2832bfe4 100644 --- a/libs/sysplugins/smarty_internal_method_configload.php +++ b/libs/sysplugins/smarty_internal_method_configload.php @@ -45,14 +45,8 @@ class Smarty_Internal_Method_ConfigLoad $confObj->source->config_sections = $sections; $confObj->source->scope = $scope; $confObj->compiled = Smarty_Template_Compiled::load($confObj); - if ($confObj->smarty->debugging) { - $confObj->smarty->_debug->start_render($confObj); - } $confObj->compiled->render($confObj); - if ($confObj->smarty->debugging) { - $confObj->smarty->_debug->end_render($confObj); - } - if ($data instanceof Smarty_Internal_Template) { + if ($data->_objType == 2) { $data->compiled->file_dependency[$confObj->source->uid] = array($confObj->source->filepath, $confObj->source->getTimeStamp(), $confObj->source->type); diff --git a/libs/sysplugins/smarty_internal_resource_php.php b/libs/sysplugins/smarty_internal_resource_php.php index 09229c4f..0bb99b4a 100644 --- a/libs/sysplugins/smarty_internal_resource_php.php +++ b/libs/sysplugins/smarty_internal_resource_php.php @@ -24,6 +24,14 @@ class Smarty_Internal_Resource_Php extends Smarty_Internal_Resource_File */ protected $short_open_tag; + /** + * Resource does implement populateCompiledFilepath() method + * + * @var bool + */ + public $hasCompiledHandler = true; + + /** * Create a new PHP Resource @@ -64,7 +72,7 @@ class Smarty_Internal_Resource_Php extends Smarty_Internal_Resource_File throw new SmartyException("PHP templates are disabled"); } if (!$source->exists) { - if ($_template->parent instanceof Smarty_Internal_Template) { + if ($_template->parent->_objType == 2) { $parent_resource = " in '{$_template->parent->template_resource}'"; } else { $parent_resource = ''; diff --git a/libs/sysplugins/smarty_internal_template.php b/libs/sysplugins/smarty_internal_template.php index 62c394dc..23b7aebd 100644 --- a/libs/sysplugins/smarty_internal_template.php +++ b/libs/sysplugins/smarty_internal_template.php @@ -137,65 +137,14 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase // Template resource $this->template_resource = $template_resource; $this->source = Smarty_Template_Source::load($this); - $this->templateId = isset($_templateId) ? $_templateId : $this->getTemplateId($template_resource, $this->cache_id, $this->compile_id); + $this->templateId = isset($_templateId) ? $_templateId : $this->smarty->_getTemplateId($template_resource, $this->cache_id, $this->compile_id); + // copy block data of template inheritance - if ($this->parent instanceof Smarty_Internal_Template) { + if (isset($this->parent) && $this->parent->_objType == 2) { $this->block_data = $this->parent->block_data; } } - /** - * fetches rendered template - * - * @param string $template the resource handle of the template file or template object - * @param mixed $cache_id cache id to be used with this template - * @param mixed $compile_id compile id to be used with this template - * @param object $parent next higher level of Smarty variables - * @param bool $_display true: display, false: fetch - * - * @return string - * @throws \Exception - */ - public function fetch($template = null, $cache_id = null, $compile_id = null, $parent = null, $_display = false) - { - if (isset($template)) { - return $this->smarty->fetch($template, $cache_id, $compile_id, $parent, $_display); - } else { - // fetch template content - $level = ob_get_level(); - try { - $_smarty_old_error_level = isset($this->smarty->error_reporting) ? error_reporting($this->smarty->error_reporting) : null; - ob_start(); - $result = $this->render(true, false, $_display); - if (isset($_smarty_old_error_level)) { - error_reporting($_smarty_old_error_level); - } - return $result === null ? ob_get_clean() : $result; - } - catch (Exception $e) { - while (ob_get_level() > $level) { - ob_end_clean(); - } - throw $e; - } - } - } - - /** - * displays a Smarty template - * - * @param string $template the resource handle of the template file or template object - * @param mixed $cache_id cache id to be used with this template - * @param mixed $compile_id compile id to be used with this template - * @param object $parent next higher level of Smarty variables - * - * @return string - */ - public function display($template = null, $cache_id = null, $compile_id = null, $parent = null) - { - $this->fetch($template, $cache_id, $compile_id, $parent, true); - } - /** * render template * @@ -209,7 +158,7 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase */ public function render($merge_tpl_vars = false, $no_output_filter = true, $display = null) { - $parentIsTpl = $this->parent instanceof Smarty_Internal_Template; + $parentIsTpl = isset($this->parent) && $this->parent->_objType == 2; if ($this->smarty->debugging) { $this->smarty->_debug->start_template($this, $display); } @@ -252,70 +201,30 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase $this->tpl_vars = $tpl_vars; $this->config_vars = $config_vars; } - // check URL debugging control + // check URL debugging control if (!$this->smarty->debugging && $this->smarty->debugging_ctrl == 'URL') { $this->smarty->_debug->debugUrl($this); } - // disable caching for evaluated code - if ($this->source->recompiled) { - $this->caching = false; - } - // read from cache or render - $isCacheTpl = $this->caching == Smarty::CACHING_LIFETIME_CURRENT || - $this->caching == Smarty::CACHING_LIFETIME_SAVED; - if ($isCacheTpl) { - if (!isset($this->cached)) { - $this->loadCached(); + if ($this->source->uncompiled) { + $this->source->render($this); + } else { + // disable caching for evaluated code + if ($this->source->recompiled) { + $this->caching = false; } - $this->cached->isCached($this); - } - if (!($isCacheTpl) || !$this->cached->valid) { - // render template (not loaded and not in cache) - if ($this->smarty->debugging) { - $this->smarty->_debug->start_render($this); - } - if (!$this->source->uncompiled) { - // render compiled code + // read from cache or render + $isCacheTpl = $this->caching == Smarty::CACHING_LIFETIME_CURRENT || + $this->caching == Smarty::CACHING_LIFETIME_SAVED; + if ($isCacheTpl) { + if (!isset($this->cached)) { + $this->loadCached(); + } + $this->cached->render($this, $no_output_filter); + } else { if (!isset($this->compiled)) { $this->loadCompiled(); } $this->compiled->render($this); - } else { - $this->source->renderUncompiled($this); - } - if ($parentIsTpl && !empty($this->tpl_function)) { - $this->parent->tpl_function = array_merge($this->parent->tpl_function, $this->tpl_function); - } - if ($this->smarty->debugging) { - $this->smarty->_debug->end_render($this); - } - // write to cache when necessary - if (!$this->source->recompiled && $isCacheTpl) { - if ($this->smarty->debugging) { - $this->smarty->_debug->start_cache($this); - } - $this->cached->updateCache($this, $no_output_filter); - $compile_check = $this->smarty->compile_check; - $this->smarty->compile_check = false; - if ($parentIsTpl) { - $this->compiled->unifunc = $this->parent->compiled->unifunc; - } - if (!$this->cached->processed) { - $this->cached->process($this, true); - } - $this->smarty->compile_check = $compile_check; - $this->getRenderedTemplateCode($this->cached->unifunc); - if ($this->smarty->debugging) { - $this->smarty->_debug->end_cache($this); - } - } - } else { - if ($this->smarty->debugging) { - $this->smarty->_debug->start_cache($this); - } - $this->cached->render($this); - if ($this->smarty->debugging) { - $this->smarty->_debug->end_cache($this); } } $content = null; @@ -359,7 +268,9 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase } } if ($parentIsTpl) { - $this->parent->tpl_function = array_merge($this->parent->tpl_function, $this->tpl_function); + if (!empty($this->tpl_function)) { + $this->parent->tpl_function = array_merge($this->parent->tpl_function, $this->tpl_function); + } foreach ($this->compiled->required_plugins as $code => $tmp1) { foreach ($tmp1 as $name => $tmp) { foreach ($tmp as $type => $data) { @@ -369,7 +280,7 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase } } // return cache content - return $content === null ? null: $content; + return $content === null ? null : $content; } } @@ -439,30 +350,6 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase return $this->cached->writeCachedContent($this, $content); } - /** - * Get unique template id - * - * @param string $template_name - * @param null|mixed $cache_id - * @param null|mixed $compile_id - * - * @return string - */ - public function getTemplateId($template_name, $cache_id = null, $compile_id = null) - { - $cache_id = isset($cache_id) ? $cache_id : $this->cache_id; - $compile_id = isset($compile_id) ? $compile_id : $this->compile_id; - if ($this->smarty->allow_ambiguous_resources) { - $_templateId = Smarty_Resource::getUniqueTemplateName($this, $template_name) . "#{$cache_id}#{$compile_id}"; - } else { - $_templateId = $this->smarty->_joined_template_dir . "#{$template_name}#{$cache_id}#{$compile_id}"; - } - if (isset($_templateId[150])) { - $_templateId = sha1($_templateId); - } - return $_templateId; - } - /** * Template code runtime function to get subtemplate content * @@ -500,7 +387,7 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase */ public function setupSubTemplate($template, $cache_id, $compile_id, $caching, $cache_lifetime, $data, $parent_scope, $cache_tpl_obj) { - $_templateId = $this->getTemplateId($template, $cache_id, $compile_id); + $_templateId = $this->smarty->_getTemplateId($template, $cache_id, $compile_id); // already in template cache? /* @var Smarty_Internal_Template $tpl */ if (isset($this->smarty->template_objects[$_templateId])) { @@ -510,41 +397,51 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase if ((bool) $tpl->caching !== (bool) $caching) { unset($tpl->compiled); } - $tpl->caching = $caching; - $tpl->cache_lifetime = $cache_lifetime; + if ($parent_scope = Smarty::SCOPE_LOCAL) { + $tpl->tpl_vars = $this->tpl_vars; + $tpl->config_vars = $this->config_vars; + } + $tpl->tpl_function = $this->tpl_function; } else { - $tpl = new $this->smarty->template_class($template, $this->smarty, $this, $cache_id, $compile_id, $caching, $cache_lifetime, $_templateId); - } - if (!$tpl->source->recompiled && !isset($this->smarty->template_objects[$_templateId]) && - (isset($this->smarty->template_objects[$this->templateId]) || - ($cache_tpl_obj && $this->smarty->resource_cache_mode & Smarty::RESOURCE_CACHE_AUTOMATIC) || - $this->smarty->resource_cache_mode & Smarty::RESOURCE_CACHE_ON) - ) { - $this->smarty->template_objects[$_templateId] = $tpl; + $tpl = clone $this; + $tpl->parent = $this; + if ($tpl->templateId !== $_templateId) { + $tpl->templateId = $_templateId; + $tpl->template_resource = $template; + $tpl->cache_id = $cache_id; + $tpl->compile_id = $compile_id; + $tpl->source = Smarty_Template_Source::load($tpl); + unset($tpl->compiled, $tpl->cached); + $tpl->cacheTpl($cache_tpl_obj); + } } + $tpl->caching = $caching; + $tpl->cache_lifetime = $cache_lifetime; if ($caching == 9999) { $tpl->cached = $this->cached; } // get variables from calling scope - if ($parent_scope == Smarty::SCOPE_LOCAL) { - $tpl->tpl_vars = $this->tpl_vars; - } elseif ($parent_scope == Smarty::SCOPE_PARENT) { - $tpl->tpl_vars = &$this->tpl_vars; - } elseif ($parent_scope == Smarty::SCOPE_GLOBAL) { - $tpl->tpl_vars = &Smarty::$global_tpl_vars; - } elseif (($scope_ptr = $this->getScopePointer($parent_scope)) == null) { - $tpl->tpl_vars = &$this->tpl_vars; - } else { - $tpl->tpl_vars = &$scope_ptr->tpl_vars; + if ($parent_scope != Smarty::SCOPE_LOCAL) { + if ($parent_scope == Smarty::SCOPE_PARENT) { + $tpl->tpl_vars = &$this->tpl_vars; + $tpl->config_vars = &$this->config_vars; + } elseif ($parent_scope == Smarty::SCOPE_GLOBAL) { + $tpl->tpl_vars = &Smarty::$global_tpl_vars; + $tpl->config_vars = $this->config_vars; + } elseif (($scope_ptr = $this->getScopePointer($parent_scope)) == null) { + $tpl->tpl_vars = &$this->tpl_vars; + $tpl->config_vars = &$this->config_vars; + } else { + $tpl->tpl_vars = &$scope_ptr->tpl_vars; + $tpl->config_vars = &$scope_ptr->$this->config_vars; + } } - $tpl->config_vars = $this->config_vars; if (!empty($data)) { // set up variable values foreach ($data as $_key => $_val) { $tpl->tpl_vars[$_key] = new Smarty_Variable($_val); } } - $tpl->tpl_function = $this->tpl_function; return $tpl; } @@ -570,7 +467,7 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase if (!isset($tpl->compiled)) { $tpl->compiled = $this->compiled; if ($tpl->compiled->includes[$tpl->source->type . ':' . $tpl->source->name] > 1) { - $tpl->smarty->template_objects[$tpl->templateId] = $tpl; + $tpl->cacheTpl(true); } } if ($this->smarty->debugging) { @@ -587,6 +484,21 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase } } + /** + * Cache resources for current template + * + * @param bool $cache_tpl_obj force caching + */ + public function cacheTpl($cache_tpl_obj) + { + if (!$this->source->handler->recompiled && (isset($this->smarty->template_objects[$this->parent->templateId]) || + ($cache_tpl_obj && $this->smarty->resource_cache_mode & Smarty::RESOURCE_CACHE_AUTOMATIC) || + $this->smarty->resource_cache_mode & Smarty::RESOURCE_CACHE_ON) + ) { + $this->smarty->->template_objects[$tpl->templateId] = $this; + } + } + /** * Call template function * diff --git a/libs/sysplugins/smarty_internal_templatebase.php b/libs/sysplugins/smarty_internal_templatebase.php index 9752b3ed..7e22efea 100644 --- a/libs/sysplugins/smarty_internal_templatebase.php +++ b/libs/sysplugins/smarty_internal_templatebase.php @@ -74,6 +74,128 @@ abstract class Smarty_Internal_TemplateBase extends Smarty_Internal_Data */ public $cache_lifetime = 3600; + /** + * fetches a rendered Smarty template + * + * @param string $template the resource handle of the template file or template object + * @param mixed $cache_id cache id to be used with this template + * @param mixed $compile_id compile id to be used with this template + * @param object $parent next higher level of Smarty variables + * @param bool $display not used - left for BC + * @param bool $merge_tpl_vars not used - left for BC + * @param bool $no_output_filter not used - left for BC + * + * @throws Exception + * @throws SmartyException + * @return string rendered template output + */ + public function fetch($template = null, $cache_id = null, $compile_id = null, $parent = null, $display = false, $merge_tpl_vars = true, $no_output_filter = false) + { + $result = $this->_execute($template, $cache_id, $compile_id, $parent, 'fetch'); + return $result === null ? ob_get_clean() : $result; + } + + /** + * displays a Smarty template + * + * @param string $template the resource handle of the template file or template object + * @param mixed $cache_id cache id to be used with this template + * @param mixed $compile_id compile id to be used with this template + * @param object $parent next higher level of Smarty variables + */ + public function display($template = null, $cache_id = null, $compile_id = null, $parent = null) + { + // display template + $this->_execute($template, $cache_id, $compile_id, $parent, 'display'); + } + + /** + * test if cache is valid + * + * @api Smarty::isCached() + * @link http://www.smarty.net/docs/en/api.is.cached.tpl + * + * @param null|string|\Smarty_Internal_Template $template the resource handle of the template file or template object + * @param mixed $cache_id cache id to be used with this template + * @param mixed $compile_id compile id to be used with this template + * @param object $parent next higher level of Smarty variables + * + * @return boolean cache status + */ + public function isCached($template = null, $cache_id = null, $compile_id = null, $parent = null) + { + return $this->_execute($template, $cache_id, $compile_id, $parent, 'isCached'); + } + + /** + * fetches a rendered Smarty template + * + * @param string $template the resource handle of the template file or template object + * @param mixed $cache_id cache id to be used with this template + * @param mixed $compile_id compile id to be used with this template + * @param object $parent next higher level of Smarty variables + * @param string $function function name + * + * @return mixed + * @throws \Exception + * @throws \SmartyException + */ + private function _execute($template, $cache_id, $compile_id, $parent, $function) + { + /* @var Smarty $smarty */ + $smarty = $this->_objType == 1 ? $this : $this->smarty; + if ($template === null) { + if ($this->_objType != 2) { + throw new SmartyException($function . '():Missing \'$template\' parameter'); + } else { + $template = $this; + } + } elseif (is_object($template)) { + if (!isset($template->_objType) || $template->_objType != 2) { + throw new SmartyException($function . '():Template object expected'); + } + } else { + // get template object + /* @var Smarty_Internal_Template $template */ + $template = $smarty->createTemplate($template, $cache_id, $compile_id, $parent, false); + if ($this->_objType == 1) { + // set caching in template object + $template->caching = $this->caching; + } + } + // fetch template content + $level = ob_get_level(); + try { + $_smarty_old_error_level = ($this->_objType == 1 && + isset($smarty->error_reporting)) ? error_reporting($smarty->error_reporting) : null; + if ($function == 'isCached') { + if ($template->caching) { + // return cache status of template + if (!isset($template->cached)) { + $template->loadCached(); + } + $result = $template->cached->isCached($template); + $template->smarty->_cache['isCached'][$template->templateId] = $template; + } else { + return false; + } + } else { + ob_start(); + $result = $template->render(true, false, $function == 'display'); + } + if (isset($_smarty_old_error_level)) { + error_reporting($_smarty_old_error_level); + } + return $result; + } + catch (Exception $e) { + while (ob_get_level() > $level) { + ob_end_clean(); + } + throw $e; + } + } + /** * Registers plugin to be used in templates * NOTE: this method can be safely removed for dynamic loading @@ -233,40 +355,6 @@ abstract class Smarty_Internal_TemplateBase extends Smarty_Internal_Data return $this; } - /** - * test if cache is valid - * - * @api Smarty::isCached() - * @link http://www.smarty.net/docs/en/api.is.cached.tpl - * - * @param string|\Smarty_Internal_Template $template the resource handle of the template file or template object - * @param mixed $cache_id cache id to be used with this template - * @param mixed $compile_id compile id to be used with this template - * @param object $parent next higher level of Smarty variables - * - * @return boolean cache status - */ - public function isCached($template = null, $cache_id = null, $compile_id = null, $parent = null) - { - if ($template === null && $this instanceof $this->template_class) { - $template = $this; - } else { - if (!($template instanceof $this->template_class)) { - if ($parent === null) { - $parent = $this; - } - /* @var Smarty $smarty */ - $smarty = isset($this->smarty) ? $this->smarty : $this; - $template = $smarty->createTemplate($template, $cache_id, $compile_id, $parent, false); - } - } - // return cache status of template - if (!isset($template->cached)) { - $template->loadCached(); - } - return $template->cached->isCached($template); - } - /** * @param boolean $caching */ diff --git a/libs/sysplugins/smarty_internal_templatecompilerbase.php b/libs/sysplugins/smarty_internal_templatecompilerbase.php index 7e1f9dc7..28aea607 100644 --- a/libs/sysplugins/smarty_internal_templatecompilerbase.php +++ b/libs/sysplugins/smarty_internal_templatecompilerbase.php @@ -997,7 +997,7 @@ abstract class Smarty_Internal_TemplateCompilerBase // If the template is not evaluated and we have a nocache section and or a nocache tag if ($is_code && !empty($content)) { // generate replacement code - if ((!($this->template->source->recompiled) || $this->forceNocache) && $this->template->caching && + if ((!($this->template->source->handler->recompiled) || $this->forceNocache) && $this->template->caching && !$this->suppressNocacheProcessing && ($this->nocache || $this->tag_nocache) ) { $this->template->compiled->has_nocache_code = true; diff --git a/libs/sysplugins/smarty_resource.php b/libs/sysplugins/smarty_resource.php index f11bb678..98764048 100644 --- a/libs/sysplugins/smarty_resource.php +++ b/libs/sysplugins/smarty_resource.php @@ -42,6 +42,13 @@ abstract class Smarty_Resource 'eval' => 'smarty_internal_resource_eval.php', 'php' => 'smarty_internal_resource_php.php'); + /** + * Flag if resource does implement populateCompiledFilepath() method + * + * @var bool + */ + public $hasCompiledHandler = false; + /** * Name of the Class to compile this resource's contents with * @@ -139,19 +146,14 @@ abstract class Smarty_Resource public static function load(Smarty $smarty, $type) { // try smarty's cache - if (isset($smarty->_resource_handlers[$type])) { - return $smarty->_resource_handlers[$type]; + if (isset($smarty->_cache['resource_handlers'][$type])) { + return $smarty->_cache['resource_handlers'][$type]; } // try registered resource if (isset($smarty->registered_resources[$type])) { - if ($smarty->registered_resources[$type] instanceof Smarty_Resource) { - $smarty->_resource_handlers[$type] = $smarty->registered_resources[$type]; - } else { - $smarty->_resource_handlers[$type] = new Smarty_Internal_Resource_Registered(); - } - - return $smarty->_resource_handlers[$type]; + return $smarty->_cache['resource_handlers'][$type] = $smarty->registered_resources[$type] instanceof + Smarty_Resource ? $smarty->registered_resources[$type] : new Smarty_Internal_Resource_Registered(); } // try sysplugins dir @@ -160,14 +162,14 @@ abstract class Smarty_Resource if (!class_exists($_resource_class, false)) { require SMARTY_SYSPLUGINS_DIR . self::$sysplugins[$type]; } - return $smarty->_resource_handlers[$type] = new $_resource_class(); + return $smarty->_cache['resource_handlers'][$type] = new $_resource_class(); } // try plugins dir $_resource_class = 'Smarty_Resource_' . ucfirst($type); if ($smarty->loadPlugin($_resource_class)) { if (class_exists($_resource_class, false)) { - return $smarty->_resource_handlers[$type] = new $_resource_class(); + return $smarty->_cache['resource_handlers'][$type] = new $_resource_class(); } else { $smarty->registerResource($type, array("smarty_resource_{$type}_source", "smarty_resource_{$type}_timestamp", @@ -185,7 +187,7 @@ abstract class Smarty_Resource if (is_object($smarty->security_policy)) { $smarty->security_policy->isTrustedStream($type); } - return $smarty->_resource_handlers[$type] = new Smarty_Internal_Resource_Stream(); + return $smarty->_cache['resource_handlers'][$type] = new Smarty_Internal_Resource_Stream(); } // TODO: try default_(template|config)_handler @@ -229,23 +231,23 @@ abstract class Smarty_Resource /** * modify template_resource according to resource handlers specifications * - * @param Smarty_Internal_template $template Smarty instance - * @param string $template_resource template_resource to extract resource handler and name of + * @param \Smarty_Internal_Template|\Smarty $obj Smarty instance + * @param string $template_resource template_resource to extract resource handler and name of * * @return string unique resource name */ - public static function getUniqueTemplateName($template, $template_resource) + public static function getUniqueTemplateName($obj, $template_resource) { - $smarty = isset($template->smarty) ? $template->smarty : $template; + $smarty = $obj->_objType == 2 ? $obj->smarty : $obj; list($name, $type) = self::parseResourceName($template_resource, $smarty->default_resource_type); // TODO: optimize for Smarty's internal resource types $resource = Smarty_Resource::load($smarty, $type); // go relative to a given template? $_file_is_dotted = $name[0] == '.' && ($name[1] == '.' || $name[1] == '/'); - if ($template instanceof Smarty_Internal_Template && $_file_is_dotted && - ($template->source->type == 'file' || $template->parent->source->type == 'extends') + if ($obj->_objType == 2 && $_file_is_dotted && + ($obj->source->type == 'file' || $obj->parent->source->type == 'extends') ) { - $name = dirname($template->source->filepath) . DS . $name; + $name = dirname($obj->source->filepath) . DS . $name; } return $resource->buildUniqueResourceName($smarty, $name); } diff --git a/libs/sysplugins/smarty_resource_recompiled.php b/libs/sysplugins/smarty_resource_recompiled.php index c823387b..cfd73401 100644 --- a/libs/sysplugins/smarty_resource_recompiled.php +++ b/libs/sysplugins/smarty_resource_recompiled.php @@ -23,6 +23,13 @@ abstract class Smarty_Resource_Recompiled extends Smarty_Resource */ public $recompiled = true; + /** + * Resource does implement populateCompiledFilepath() method + * + * @var bool + */ + public $hasCompiledHandler = true; + /** * populate Compiled Object with compiled filepath * diff --git a/libs/sysplugins/smarty_resource_uncompiled.php b/libs/sysplugins/smarty_resource_uncompiled.php index a52d86e8..88d2bba8 100644 --- a/libs/sysplugins/smarty_resource_uncompiled.php +++ b/libs/sysplugins/smarty_resource_uncompiled.php @@ -23,6 +23,13 @@ abstract class Smarty_Resource_Uncompiled extends Smarty_Resource */ public $uncompiled = true; + /** + * Resource does implement populateCompiledFilepath() method + * + * @var bool + */ + public $hasCompiledHandler = true; + /** * Render and output the template (without using the compiler) * diff --git a/libs/sysplugins/smarty_template_cached.php b/libs/sysplugins/smarty_template_cached.php index d2f54c36..38e30653 100644 --- a/libs/sysplugins/smarty_template_cached.php +++ b/libs/sysplugins/smarty_template_cached.php @@ -67,7 +67,7 @@ class Smarty_Template_Cached extends Smarty_Template_Resource_Base /** * Nocache hash codes of processed compiled templates - * + * * @var array */ public $hashes = array(); @@ -106,6 +106,59 @@ class Smarty_Template_Cached extends Smarty_Template_Resource_Base return $_template->cached; } + /** + * Render cache template + * + * @param \Smarty_Internal_Template $_template + * @param bool $no_output_filter + * + * @throws \Exception + */ + public function render(Smarty_Internal_Template $_template, $no_output_filter = true) + { + if ($this->isCached($_template)) { + if ($_template->smarty->debugging) { + $_template->smarty->_debug->start_cache($_template); + } + if (!$this->processed) { + $this->process($_template); + } + $this->getRenderedTemplateCode($_template); + if ($_template->smarty->debugging) { + $_template->smarty->_debug->end_cache($_template); + } + return; + } elseif ($_template->source->handler->uncompiled) { + $_template->source->render($_template); + } else { + if (!isset($_template->compiled)) { + $_template->loadCompiled(); + } + $_template->compiled->render($_template); + } + // write to cache when necessary + if ($_template->source->handler->recompiled) { + return; + } + if ($_template->smarty->debugging) { + $_template->smarty->_debug->start_cache($_template); + } + $_template->cached->updateCache($_template, $no_output_filter); + $compile_check = $_template->smarty->compile_check; + $_template->smarty->compile_check = false; + if (isset($this->parent) && $this->parent->_objType == 2) { + $_template->compiled->unifunc = $_template->parent->compiled->unifunc; + } + if (!$_template->cached->processed) { + $_template->cached->process($_template, true); + } + $_template->smarty->compile_check = $compile_check; + $this->getRenderedTemplateCode($_template); + if ($_template->smarty->debugging) { + $_template->smarty->_debug->end_cache($_template); + } + } + /** * Check if cache is valid, lock cache if required * @@ -202,22 +255,6 @@ class Smarty_Template_Cached extends Smarty_Template_Resource_Base } } - /** - * Render cached template - * - * @param Smarty_Internal_Template $_template - * - * @return string - * @throws Exception - */ - public function render(Smarty_Internal_Template $_template) - { - if (!$this->processed) { - $this->process($_template); - } - $_template->getRenderedTemplateCode($this->unifunc); - } - /** * Write this cache object to handler * diff --git a/libs/sysplugins/smarty_template_compiled.php b/libs/sysplugins/smarty_template_compiled.php index 8ecbeccc..69da4f0f 100644 --- a/libs/sysplugins/smarty_template_compiled.php +++ b/libs/sysplugins/smarty_template_compiled.php @@ -19,7 +19,6 @@ class Smarty_Template_Compiled extends Smarty_Template_Resource_Base */ public $nocache_hash = null; - /** * create Compiled Object container */ @@ -48,7 +47,7 @@ class Smarty_Template_Compiled extends Smarty_Template_Resource_Base } } $compiled = new Smarty_Template_Compiled(); - if (method_exists($_template->source->handler, 'populateCompiledFilepath')) { + if ($_template->source->handler->hasCompiledHandler) { $_template->source->handler->populateCompiledFilepath($compiled, $_template); } else { $compiled->populateCompiledFilepath($_template); @@ -199,17 +198,25 @@ class Smarty_Template_Compiled extends Smarty_Template_Resource_Base */ public function render(Smarty_Internal_Template $_template) { - + if ($_template->smarty->debugging) { + $_template->smarty->_debug->start_render($_template); + } if (!$this->processed) { $this->process($_template); } if (isset($_template->cached)) { $_template->cached->file_dependency = array_merge($_template->cached->file_dependency, $this->file_dependency); } - $_template->getRenderedTemplateCode($this->unifunc); + $this->getRenderedTemplateCode($_template); if ($_template->caching && $this->has_nocache_code) { $_template->cached->hashes[$this->nocache_hash] = true; } + if (isset($_template->parent) && $_template->parent->_objType == 2 && !empty($_template->tpl_function)) { + $_template->parent->tpl_function = array_merge($_template->parent->tpl_function, $_template->tpl_function); + } + if ($_template->smarty->debugging) { + $_template->smarty->_debug->end_render($_template); + } } /** diff --git a/libs/sysplugins/smarty_template_resource_base.php b/libs/sysplugins/smarty_template_resource_base.php index fa5d99ba..19d5d536 100644 --- a/libs/sysplugins/smarty_template_resource_base.php +++ b/libs/sysplugins/smarty_template_resource_base.php @@ -2,7 +2,6 @@ /** * Smarty Template Resource Base Object - * Meta Data Container for Template Resource Files * * @package Smarty * @subpackage TemplateResources @@ -101,64 +100,50 @@ abstract class Smarty_Template_Resource_Base */ abstract public function process(Smarty_Internal_Template $_template); - /** - * render template code + /** + * get rendered template content by calling compiled or cached template code * - * @param Smarty_Internal_Template $_template + * @param string $unifunc function with template code * * @return string - * @throws Exception + * @throws \Exception */ - public function render(Smarty_Internal_Template $_template) + public function getRenderedTemplateCode(Smarty_Internal_Template $_template, $unifunc = null) { - - if (!$this->processed) { - $this->process($_template); - } - return $_template->getRenderedTemplateCode($this->unifunc); - } - - /** - * Write compiled code by handler - * - * @param Smarty_Internal_Template $_template template object - * @param string $code compiled code - * - * @return boolean success - */ - public function write(Smarty_Internal_Template $_template, $code) - { - if (!$_template->source->recompiled) { - $obj = new Smarty_Internal_Write_File(); - if ($obj->writeFile($this->filepath, $code, $_template->smarty) === true) { - $this->timestamp = $this->exists = is_file($this->filepath); - if ($this->exists) { - $this->timestamp = filemtime($this->filepath); - return true; - } + $unifunc = isset($unifunc) ? $unifunc : $this->unifunc; + $level = ob_get_level(); + try { + if (empty($unifunc) || !is_callable($unifunc)) { + throw new SmartyException("Invalid compiled template for '{$_template->template_resource}'"); } - return false; - } else { - $this->content = $code; + if (isset($_template->smarty->security_policy)) { + $_template->smarty->security_policy->startTemplate($_template); + } + array_unshift($_template->_capture_stack, array()); + // + // render compiled or saved template code + // + $unifunc($_template); + // any unclosed {capture} tags ? + if (isset($_template->_capture_stack[0][0])) { + $_template->capture_error(); + } + array_shift($_template->_capture_stack); + if (isset($_template->smarty->security_policy)) { + $_template->smarty->security_policy->exitTemplate(); + } + return null; } - $this->timestamp = time(); - $this->exists = true; - return true; - } - - /** - * Read compiled content from handler - * - * @param Smarty_Internal_Template $_template template object - * - * @return string content - */ - public function read(Smarty_Internal_Template $_template) - { - if (!$_template->source->recompiled) { - return file_get_contents($this->filepath); + catch (Exception $e) { + while (ob_get_level() > $level) { + ob_end_clean(); + } + array_shift($_template->_capture_stack); + if (isset($_template->smarty->security_policy)) { + $_template->smarty->security_policy->exitTemplate(); + } + throw $e; } - return isset($this->content) ? $this->content : false; } /** diff --git a/libs/sysplugins/smarty_template_source.php b/libs/sysplugins/smarty_template_source.php index a1c88576..ac38e115 100644 --- a/libs/sysplugins/smarty_template_source.php +++ b/libs/sysplugins/smarty_template_source.php @@ -251,6 +251,27 @@ class Smarty_Template_Source $this->handler->renderUncompiled($_template->source, $_template); } + /** + * Render uncompiled source + * + * @param \Smarty_Internal_Template $_template + */ + public function render(Smarty_Internal_Template $_template) + { + if ($_template->source->handler->uncompiled) { + if ($_template->smarty->debugging) { + $_template->smarty->_debug->start_render($_template); + } + $this->handler->renderUncompiled($_template->source, $_template); + if (isset($_template->parent) && $_template->parent->_objType == 2 && !empty($_template->tpl_function)) { + $_template->parent->tpl_function = array_merge($_template->parent->tpl_function, $_template->tpl_function); + } + if ($_template->smarty->debugging) { + $_template->smarty->_debug->end_render($_template); + } + } + } + /** * Get source time stamp *