From 5cbedc87f050d4f1e33e8f5d5e5f2c710d6f0bba Mon Sep 17 00:00:00 2001 From: uwetews Date: Mon, 14 Sep 2015 23:16:13 +0200 Subject: [PATCH] - optimize internal subtemplate handling --- libs/sysplugins/smarty_internal_template.php | 157 +++++++++++++++++- .../smarty_internal_templatecompilerbase.php | 76 ++++++--- libs/sysplugins/smarty_template_compiled.php | 9 +- 3 files changed, 208 insertions(+), 34 deletions(-) diff --git a/libs/sysplugins/smarty_internal_template.php b/libs/sysplugins/smarty_internal_template.php index ff0fcfae..8f3966fe 100644 --- a/libs/sysplugins/smarty_internal_template.php +++ b/libs/sysplugins/smarty_internal_template.php @@ -283,6 +283,157 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase } /** + * Template code runtime function to set up an inline subtemplate + * + * @param string $template template name + * @param mixed $cache_id cache id + * @param mixed $compile_id compile id + * @param integer $caching cache mode + * @param integer $cache_lifetime life time of cache data + * @param array $data passed parameter template variables + * @param int $parent_scope scope in which {include} should execute + * @param bool $cache_tpl_obj cache template object + * @param string|null $uid source uid + * + * @return \Smarty_Internal_Template template object + * @throws \SmartyException + */ + public function setupSubtemplate($template, $cache_id, $compile_id, $caching, $cache_lifetime, $data, $parent_scope, + $cache_tpl_obj, $uid = null) + { + // if there are cached template objects calculate $templateID + $_templateId = isset($this->smarty->_cache['template_objects']) ? + $this->smarty->_getTemplateId($template, $cache_id, $compile_id) : null; + // already in template cache? + /* @var Smarty_Internal_Template $tpl */ + if (isset($this->smarty->_cache['template_objects'][$_templateId])) { + // clone cached template object because of possible recursive call + $tpl = clone $this->smarty->_cache['template_objects'][$_templateId]; + $tpl->parent = $this; + // if $caching mode changed the compiled resource is invalid + if ((bool) $tpl->caching !== (bool) $caching) { + unset($tpl->compiled); + } + // get variables from calling scope + if ($parent_scope == Smarty::SCOPE_LOCAL) { + $tpl->tpl_vars = $this->tpl_vars; + $tpl->config_vars = $this->config_vars; + } + $tpl->tpl_function = $this->tpl_function; + // copy inheritance object? + if (isset($this->_Block)) { + $tpl->_Block = $this->_Block; + } else { + unset($tpl->_Block); + } + } else { + $tpl = clone $this; + $tpl->parent = $this; + if (!isset($tpl->templateId) || $tpl->templateId !== $_templateId) { + $tpl->templateId = $_templateId; + $tpl->template_resource = $template; + $tpl->cache_id = $cache_id; + $tpl->compile_id = $compile_id; + // $uid is set if template is inline + if (isset($uid)) { + // inline templates have same compiled resource + $tpl->compiled = $this->compiled; + // if template is called multiple times set flag to to cache template objects + if (isset($tpl->compiled->includes[$template]) && $tpl->compiled->includes[$template] > 1) { + $cache_tpl_obj = true; + } + if (isset($tpl->compiled->file_dependency[$uid])) { + $info = $tpl->compiled->file_dependency[$uid]; + $tpl->source = + new Smarty_Template_Source(isset($tpl->smarty->_cache['resource_handlers'][$info[2]]) ? + $tpl->smarty->_cache['resource_handlers'][$info[2]] : + Smarty_Resource::load($tpl->smarty, $info[2]), $tpl->smarty, + $info[0], $info[2], $info[0]); + $tpl->source->filepath = $info[0]; + $tpl->source->timestamp = $info[1]; + $tpl->source->exist = true; + $tpl->source->uid = $uid; + } else { + $tpl->source = null; + } + } else { + $tpl->source = null; + unset($tpl->compiled); + } + if (!isset($tpl->source)) { + $tpl->source = Smarty_Template_Source::load($tpl); + } + unset($tpl->cached); + // check if template object should be cached + if (!$tpl->source->handler->recompiled && (isset($tpl->parent->templateId) && + isset($tpl->smarty->_cache['template_objects'][$tpl->parent->templateId]) || + ($cache_tpl_obj && $tpl->smarty->resource_cache_mode & Smarty::RESOURCE_CACHE_AUTOMATIC) || + $tpl->smarty->resource_cache_mode & Smarty::RESOURCE_CACHE_ON) + ) { + $tpl->smarty->_cache['template_objects'][$tpl->_getTemplateId()] = $tpl; + } + } + } + $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) { + 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 ($parent_scope == Smarty::SCOPE_ROOT) { + $ptr = $tpl->parent; + while (!empty($ptr->parent)) { + $ptr = $ptr->parent; + } + $tpl->tpl_vars = &$ptr->tpl_vars; + $tpl->config_vars = &$ptr->config_vars; + } else { + $tpl->tpl_vars = $this->tpl_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); + } + } + return $tpl; + } + + /** + * Template code runtime function to render inline subtemplate + * + * @param Smarty_Internal_Template $tpl + * @param string $content_func name of content function + * + * @throws \Exception + */ + public function renderInline(Smarty_Internal_Template $tpl, $content_func) + { + if ($this->smarty->debugging) { + $this->smarty->_debug->start_template($tpl); + $this->smarty->_debug->start_render($tpl); + } + $tpl->compiled->getRenderedTemplateCode($tpl, $content_func); + if ($this->smarty->debugging) { + $this->smarty->_debug->end_template($tpl); + $this->smarty->_debug->end_render($tpl); + } + if ($tpl->caching == 9999 && $tpl->compiled->has_nocache_code) { + $this->cached->hashes[$tpl->compiled->nocache_hash] = true; + } + } + + /** * This function is executed automatically when a compiled or cached template file is included * - Decode saved properties from compiled template and cache files * - Check if compiled or cache file is valid @@ -423,9 +574,6 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase public function loadCompiled() { if (!isset($this->compiled)) { - if (!class_exists('Smarty_Template_Compiled', false)) { - require SMARTY_SYSPLUGINS_DIR . 'smarty_template_compiled.php'; - } $this->compiled = Smarty_Template_Compiled::load($this); } } @@ -437,9 +585,6 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase public function loadCached() { if (!isset($this->cached)) { - if (!class_exists('Smarty_Template_Cached', false)) { - require SMARTY_SYSPLUGINS_DIR . 'smarty_template_cached.php'; - } $this->cached = Smarty_Template_Cached::load($this); } } diff --git a/libs/sysplugins/smarty_internal_templatecompilerbase.php b/libs/sysplugins/smarty_internal_templatecompilerbase.php index 267d5e21..7ff09152 100644 --- a/libs/sysplugins/smarty_internal_templatecompilerbase.php +++ b/libs/sysplugins/smarty_internal_templatecompilerbase.php @@ -28,7 +28,7 @@ abstract class Smarty_Internal_TemplateCompilerBase /** * Parser object * - * @var object + * @var Smarty_Internal_Templateparser */ public $parser = null; @@ -95,12 +95,33 @@ abstract class Smarty_Internal_TemplateCompilerBase */ public $sources = array(); + /** + * flag when compiling inheritance template + * + * @var bool + */ + public $inheritance = false; + /** * flag when compiling inheritance child template * * @var bool */ - public $inheritance_child = false; + public $inheritanceChild= false; + + /** + * Force all subtemplate calls to be inheritance childs + * + * @var bool + */ + public $inheritanceForceChild = false; + + /** + * Flag if compiled parent template is child of other parent + * + * @var bool + */ + public $inheritanceParentIsChild = false; /** * uid of templates called by {extends} for recursion check @@ -109,6 +130,13 @@ abstract class Smarty_Internal_TemplateCompilerBase */ public $extends_uid = array(); + /** + * Template name of {extends} tag + * + * @var null|string + */ + public $extendsFileName = null; + /** * source line offset for error messages * @@ -411,8 +439,6 @@ abstract class Smarty_Internal_TemplateCompilerBase strftime("%Y-%m-%d %H:%M:%S") . "\n"; $template_header .= " compiled from \"" . $this->template->source->filepath . "\" */ ?>\n"; } - - $_compiled_code = ''; $this->smarty->_current_file = $this->template->source->filepath; if ($this->smarty->debugging) { $this->smarty->_debug->start_compile($this->template); @@ -420,9 +446,7 @@ abstract class Smarty_Internal_TemplateCompilerBase $this->parent_compiler->template->compiled->file_dependency[$this->template->source->uid] = array($this->template->source->filepath, $this->template->source->getTimeStamp(), $this->template->source->type); - // compile for child template? - $this->inheritance_child = $this->template->isChild; - // flag for nochache sections + // flag for nocache sections $this->nocache = $nocache; $this->tag_nocache = false; // reset has nocache code flag @@ -513,7 +537,7 @@ abstract class Smarty_Internal_TemplateCompilerBase * * @param $parser * - * @throws \Smarty_Exception + * @throws \SmartyException */ public function processInheritance($parser) { @@ -521,42 +545,48 @@ abstract class Smarty_Internal_TemplateCompilerBase // child did use {extends} $name = $this->extendsFileName; $this->extendsFileName = null; - if (!$this->inheritance_child) { - // drop any output of child templates + if (!$this->inheritanceForceChild && !$this->inheritance) { + // drop any output of child templates array_unshift($parser->current_buffer->subtrees, - new Smarty_Internal_ParseTree_Tag($parser, "\n")); - $parser->current_buffer->append_subtree($parser, new Smarty_Internal_ParseTree_Tag($parser, - "\n")); + new Smarty_Internal_ParseTree_Tag($parser, "_Block = new Smarty_Internal_Runtime_Block();?>\n")); + $this->inheritance = true; } - $parser->current_buffer->append_subtree($parser, new Smarty_Internal_ParseTree_Tag($parser, - $this->compileTag('include', + $include = new Smarty_Internal_ParseTree_Tag($parser, $this->compileTag('include', array($name, array('scope' => 'parent'), - array('inline' => true)), - array('isChild' => $this->inheritance_child)))); + array('inline' => true)))); + if (!$this->inheritanceForceChild && !$this->inheritanceParentIsChild) { + $parser->current_buffer->append_subtree($parser, new Smarty_Internal_ParseTree_Tag($parser, + "\n")); + $this->inheritance = false; + } + $this->inheritanceParentIsChild = false; + $parser->current_buffer->append_subtree($parser, $include); return; } // template list of extends: resource ? if (!empty($this->sources)) { - if (!$this->inheritance_child) { + if (!$this->inheritanceForceChild) { // drop any output of child templates $parser->current_buffer->append_subtree($parser, new Smarty_Internal_ParseTree_Tag($parser, - "\n")); + "_Block = new Smarty_Internal_Runtime_Block();?>\n")); } while (!empty($this->sources)) { $source = array_shift($this->sources); - if (!$this->inheritance_child && empty($this->sources)) { + if (!$this->inheritanceForceChild && empty($this->sources)) { // drop any output of child templates $parser->current_buffer->append_subtree($parser, new Smarty_Internal_ParseTree_Tag($parser, "\n")); } + $forceChild = $this->inheritanceForceChild; + $this->inheritanceForceChild = $this->inheritanceForceChild || !empty($this->sources); $parser->current_buffer->append_subtree($parser, new Smarty_Internal_ParseTree_Tag($parser, $this->compileTag('include', array("'{$source->resource}'", array('scope' => 'parent'), - array('inline' => true)), - array('isChild' => $this->inheritance_child || - !empty($this->sources))))); + array('inline' => true))))); + // restore value + $this->inheritanceForceChild = $forceChild; } } } diff --git a/libs/sysplugins/smarty_template_compiled.php b/libs/sysplugins/smarty_template_compiled.php index ffa5f1f1..641cccd3 100644 --- a/libs/sysplugins/smarty_template_compiled.php +++ b/libs/sysplugins/smarty_template_compiled.php @@ -151,11 +151,11 @@ class Smarty_Template_Compiled extends Smarty_Template_Resource_Base $_template->smarty->compile_check = $compileCheck; } } - if ($_template->smarty->resource_cache_mode & Smarty::RESOURCE_CACHE_AUTOMATIC && isset($_template->parent) && - isset($_template->parent->compiled) && !$_template->source->isConfig && - !in_array($_template->source->type, array('eval', 'string')) && + if (isset($_template->parent) && isset($_template->parent->compiled) && !empty($_template->parent->compiled->includes) && - isset($_template->smarty->_cache['template_objects'][$_template->_getTemplateId()]) + $_template->smarty->resource_cache_mode & Smarty::RESOURCE_CACHE_AUTOMATIC && + !$_template->source->handler->recompiled && $_template->source->type != 'string' && + !isset($_template->smarty->_cache['template_objects'][$_template->_getTemplateId()]) ) { foreach ($_template->parent->compiled->includes as $key => $count) { $_template->compiled->includes[$key] = @@ -232,7 +232,6 @@ class Smarty_Template_Compiled extends Smarty_Template_Resource_Base public function compileTemplateSource(Smarty_Internal_Template $_template) { $_template->source->compileds = array(); - $_template->isChild = false; $this->file_dependency = array(); $this->tpl_function = array(); $this->includes = array();