diff --git a/change_log.txt b/change_log.txt index af215e85..27932136 100644 --- a/change_log.txt +++ b/change_log.txt @@ -1,8 +1,6 @@  ===== 3.1.28-dev===== (xx.xx.2015) 24.10.2015 - - new extension handler to load functions when called - - improve recovery from ivalid compiled template code - - improve autoloader speed + - more optimizations of template processing 21.10.2015 - move some code into runtime extensions diff --git a/libs/Smarty.class.php b/libs/Smarty.class.php index 9eac6ef8..3ad655ff 100644 --- a/libs/Smarty.class.php +++ b/libs/Smarty.class.php @@ -88,17 +88,20 @@ if (!class_exists('Smarty_Autoloader', false)) { * Load always needed external class files */ -if (!class_exists('Smarty_Internal_Data', false)) { - require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_data.php'; + +if (false) { + if (!class_exists('Smarty_Internal_Data', false)) { + require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_data.php'; + } + require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_extension_handler.php'; + require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_templatebase.php'; + require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_template.php'; + require_once SMARTY_SYSPLUGINS_DIR . 'smarty_resource.php'; + require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_resource_file.php'; + require_once SMARTY_SYSPLUGINS_DIR . 'smarty_variable.php'; + require_once SMARTY_SYSPLUGINS_DIR . 'smarty_template_source.php'; + require_once SMARTY_SYSPLUGINS_DIR . 'smarty_template_resource_base.php'; } -require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_extension_handler.php'; -require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_templatebase.php'; -require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_template.php'; -require_once SMARTY_SYSPLUGINS_DIR . 'smarty_resource.php'; -require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_resource_file.php'; -require_once SMARTY_SYSPLUGINS_DIR . 'smarty_variable.php'; -require_once SMARTY_SYSPLUGINS_DIR . 'smarty_template_source.php'; -require_once SMARTY_SYSPLUGINS_DIR . 'smarty_template_resource_base.php'; /** * This is the main Smarty class @@ -120,7 +123,7 @@ class Smarty extends Smarty_Internal_TemplateBase /** * smarty version */ - const SMARTY_VERSION = '3.1.28-dev/71'; + const SMARTY_VERSION = '3.1.28-dev/72'; /** * define variable scopes @@ -1119,15 +1122,16 @@ class Smarty extends Smarty_Internal_TemplateBase * * @return string */ - public function _getTemplateId($template_name, $cache_id = null, $compile_id = null) + public function _getTemplateId($template_name, $cache_id = null, $compile_id = null, $caching = null) { $cache_id = $cache_id === null ? $this->cache_id : $cache_id; $compile_id = $compile_id === null ? $this->compile_id : $compile_id; + $caching = (int) ($caching === null ? $this->caching : $caching); if ($this->allow_ambiguous_resources) { - $_templateId = Smarty_Resource::getUniqueTemplateName($this, $template_name) . "#{$cache_id}#{$compile_id}"; + $_templateId = Smarty_Resource::getUniqueTemplateName($this, $template_name) . "#{$cache_id}#{$compile_id}#{$caching}"; } else { - $_templateId = $this->_joined_template_dir . "#{$template_name}#{$cache_id}#{$compile_id}"; + $_templateId = $this->_joined_template_dir . "#{$template_name}#{$cache_id}#{$compile_id}#{$caching}"; } if (isset($_templateId[150])) { $_templateId = sha1($_templateId); diff --git a/libs/sysplugins/smarty_internal_data.php b/libs/sysplugins/smarty_internal_data.php index 303d8c1e..20d0b56c 100644 --- a/libs/sysplugins/smarty_internal_data.php +++ b/libs/sysplugins/smarty_internal_data.php @@ -174,6 +174,27 @@ class Smarty_Internal_Data return $this->ext->getTemplateVars->getTemplateVars($this, $varName, $_ptr, $searchParents); } + /** + * Follow the parent chain an merge template and config variables + * + * @param \Smarty_Internal_Data|null $data + */ + public function _mergeVars(Smarty_Internal_Data $data = null) { + if (isset($data)) { + if (!empty($this->tpl_vars)) { + $data->tpl_vars = array_merge($this->tpl_vars, $data->tpl_vars); + } + if (!empty($this->config_vars)) { + $data->config_vars = array_merge($this->config_vars, $data->config_vars); + } + } else { + $data = $this; + } + if (isset($this->parent)) { + $this->parent->_mergeVars($data); + } + } + /** * Handle unknown class methods * diff --git a/libs/sysplugins/smarty_internal_runtime_inline.php b/libs/sysplugins/smarty_internal_runtime_inline.php index 3b49acea..730e88d3 100644 --- a/libs/sysplugins/smarty_internal_runtime_inline.php +++ b/libs/sysplugins/smarty_internal_runtime_inline.php @@ -8,7 +8,7 @@ * @author Uwe Tews * **/ -class Smarty_Internal_Runtime_Inline extends Smarty_Internal_Runtime_SubTemplate +class Smarty_Internal_Runtime_Inline { /** @@ -31,8 +31,8 @@ class Smarty_Internal_Runtime_Inline extends Smarty_Internal_Runtime_SubTemplate public function render(\Smarty_Internal_Template $parent, $template, $cache_id, $compile_id, $caching, $cache_lifetime, $data, $scope, $forceTplCache, $uid, $content_func) { - $tpl = $this->setupSubTemplate($parent, $template, $cache_id, $compile_id, $caching, $cache_lifetime, $data, - $scope, $uid); + $tpl = $parent->smarty->ext->_subTemplate->setupSubTemplate($parent, $template, $cache_id, $compile_id, $caching, $cache_lifetime, $data, + $scope, $forceTplCache, $uid); if ($parent->smarty->debugging) { $parent->smarty->_debug->start_template($tpl); $parent->smarty->_debug->start_render($tpl); @@ -45,7 +45,6 @@ class Smarty_Internal_Runtime_Inline extends Smarty_Internal_Runtime_SubTemplate if ($tpl->caching == 9999 && $tpl->compiled->has_nocache_code) { $parent->cached->hashes[$tpl->compiled->nocache_hash] = true; } - $this->updateTemplateCache($tpl, $forceTplCache); } /** @@ -56,22 +55,31 @@ class Smarty_Internal_Runtime_Inline extends Smarty_Internal_Runtime_SubTemplate * * @throws \SmartyException */ - public function setSourceByUid(Smarty_Internal_Template $tpl, $uid) + public function setSource(Smarty_Internal_Template $tpl, $uid = null) { - // inline templates have same compiled resource - $tpl->compiled = $tpl->parent->compiled; - if (isset($tpl->compiled->file_dependency[$uid])) { - list($filepath, $timestamp, $resource) = $tpl->compiled->file_dependency[$uid]; - $tpl->source = new Smarty_Template_Source(isset($tpl->smarty->_cache['resource_handlers'][$resource]) ? - $tpl->smarty->_cache['resource_handlers'][$resource] : - Smarty_Resource::load($tpl->smarty, $resource), $tpl->smarty, - $filepath, $resource, $filepath); - $tpl->source->filepath = $filepath; - $tpl->source->timestamp = $timestamp; - $tpl->source->exists = true; - $tpl->source->uid = $uid; + // $uid is set if template is inline + if (isset($uid)) { + // inline templates have same compiled resource + $tpl->compiled = $tpl->parent->compiled; + if (isset($tpl->compiled->file_dependency[$uid])) { + list($filepath, $timestamp, $resource) = $tpl->compiled->file_dependency[$uid]; + $tpl->source = new Smarty_Template_Source(isset($tpl->smarty->_cache['resource_handlers'][$resource]) ? + $tpl->smarty->_cache['resource_handlers'][$resource] : + Smarty_Resource::load($tpl->smarty, $resource), + $tpl->smarty, $filepath, $resource, $filepath); + $tpl->source->filepath = $filepath; + $tpl->source->timestamp = $timestamp; + $tpl->source->exists = 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); } } } diff --git a/libs/sysplugins/smarty_internal_runtime_subtemplate.php b/libs/sysplugins/smarty_internal_runtime_subtemplate.php index f9df3324..995d390b 100644 --- a/libs/sysplugins/smarty_internal_runtime_subtemplate.php +++ b/libs/sysplugins/smarty_internal_runtime_subtemplate.php @@ -11,6 +11,8 @@ class Smarty_Internal_Runtime_SubTemplate { + public $tplObjects = array(); + public $subTplInfo = array(); /** * Runtime function to render subtemplate * @@ -27,11 +29,8 @@ class Smarty_Internal_Runtime_SubTemplate */ public function render(Smarty_Internal_Template $parent, $template, $cache_id, $compile_id, $caching, $cache_lifetime, $data, $scope, $forceTplCache) - { - $tpl = $this->setupSubTemplate($parent, $template, $cache_id, $compile_id, $caching, $cache_lifetime, $data, - $scope); - $tpl->render(); - $this->updateTemplateCache($tpl, $forceTplCache); + {$this->setupSubTemplate($parent, $template, $cache_id, $compile_id, $caching, $cache_lifetime, $data, + $scope, $forceTplCache)->render(); } /** @@ -45,38 +44,38 @@ class Smarty_Internal_Runtime_SubTemplate * @param integer $cache_lifetime life time of cache data * @param array $data passed parameter template variables * @param int $scope scope in which {include} should execute + * @param $forceTplCache * @param string|null $uid source uid * * @return \Smarty_Internal_Template template object - * @throws \SmartyException */ public function setupSubTemplate(Smarty_Internal_Template $parent, $template, $cache_id, $compile_id, $caching, - $cache_lifetime, $data, $scope, $uid = null) + $cache_lifetime, $data, $scope, $forceTplCache, $uid = null) { // if there are cached template objects calculate $templateID - $_templateId = isset($parent->smarty->_cache['template_objects']) ? - $parent->smarty->_getTemplateId($template, $cache_id, $compile_id) : null; + $_templateId = !empty($this->tplObjects) ? + $parent->smarty->_getTemplateId($template, $cache_id, $compile_id, $caching) : null; // already in template cache? /* @var Smarty_Internal_Template $tpl */ - if (isset($parent->smarty->_cache['template_objects'][$_templateId])) { + if (isset($this->tplObjects[$_templateId])) { // clone cached template object because of possible recursive call - $tpl = clone $parent->smarty->_cache['template_objects'][$_templateId]; + $tpl = clone $this->tplObjects[$_templateId]; $tpl->parent = $parent; // if $caching mode changed the compiled resource is invalid if ((bool) $tpl->caching !== (bool) $caching) { unset($tpl->compiled); } // get variables from calling scope - if ($scope == Smarty::SCOPE_LOCAL) { + if ($scope == Smarty::SCOPE_LOCAL && $tpl->scope == Smarty::SCOPE_LOCAL) { $tpl->tpl_vars = $parent->tpl_vars; $tpl->config_vars = $parent->config_vars; } $tpl->tpl_function = $parent->tpl_function; // copy inheritance object? - if (isset($parent->_inheritance)) { - $tpl->_inheritance = $parent->_inheritance; + if (isset($parent->ext->_inheritance)) { + $tpl->ext->_inheritance = $parent->ext->_inheritance; } else { - unset($tpl->_inheritance); + unset($tpl->ext->_inheritance); } } else { $tpl = clone $parent; @@ -86,15 +85,10 @@ class Smarty_Internal_Runtime_SubTemplate $tpl->template_resource = $template; $tpl->cache_id = $cache_id; $tpl->compile_id = $compile_id; - // $uid is set if template is inline if (isset($uid)) { - $this->setSourceByUid($tpl, $uid); + $tpl->ext->_inline->setSource($tpl, $uid); } else { - $tpl->source = null; - unset($tpl->compiled); - } - if (!isset($tpl->source)) { - $tpl->source = Smarty_Template_Source::load($tpl); + $this->setSource($tpl, $uid); } unset($tpl->cached); } @@ -107,6 +101,7 @@ class Smarty_Internal_Runtime_SubTemplate // get variables from calling scope if ($scope != $tpl->scope) { if ($tpl->scope != Smarty::SCOPE_LOCAL) { + //We must get rid of pointers unset($tpl->tpl_vars, $tpl->config_vars); $tpl->tpl_vars = array(); $tpl->config_vars = array(); @@ -131,6 +126,21 @@ class Smarty_Internal_Runtime_SubTemplate $tpl->scope = $scope; } + if (!isset($this->tplObjects[$tpl->_getTemplateId()]) && + !$tpl->source->handler->recompiled + ) { + // if template is called multiple times set flag to to cache template objects + $forceTplCache = $forceTplCache || + (isset($this->subTplInfo[$tpl->template_resource]) && $this->subTplInfo[$tpl->template_resource] > 1); + // check if template object should be cached + if ($tpl->parent->_objType == 2 && isset($this->tplObjects[$tpl->parent->templateId]) || + ($forceTplCache && $tpl->smarty->resource_cache_mode & Smarty::RESOURCE_CACHE_AUTOMATIC) || + ($tpl->smarty->resource_cache_mode & Smarty::RESOURCE_CACHE_ON) + ) { + $this->tplObjects[$tpl->_getTemplateId()] = $tpl; + } + } + if (!empty($data)) { // set up variable values foreach ($data as $_key => $_val) { @@ -140,30 +150,37 @@ class Smarty_Internal_Runtime_SubTemplate return $tpl; } - public function updateTemplateCache(Smarty_Internal_Template $tpl, $forceTplCache) + /** + * Set source object of inline template by $uid + * + * @param \Smarty_Internal_Template $tpl + * @param string $uid + * + * @throws \SmartyException + */ + public function setSource(Smarty_Internal_Template $tpl, $uid = null) { - if (isset($tpl->smarty->_cache['template_objects'][$tpl->_getTemplateId()]) || - $tpl->source->handler->recompiled - ) { - return; - } - // if template is called multiple times set flag to to cache template objects - $forceTplCache = $forceTplCache || (isset($tpl->compiled->includes[$tpl->template_resource]) && - $tpl->compiled->includes[$tpl->template_resource] > 1); - // check if template object should be cached - if ((isset($tpl->parent->templateId) && - isset($tpl->smarty->_cache['template_objects'][$tpl->parent->templateId]) || - ($forceTplCache && $tpl->smarty->resource_cache_mode & Smarty::RESOURCE_CACHE_AUTOMATIC) || - $tpl->smarty->resource_cache_mode & Smarty::RESOURCE_CACHE_ON) - ) { - $tpl->parent = null; - if ($tpl->scope != Smarty::SCOPE_LOCAL) { - unset($tpl->tpl_vars, $tpl->config_vars); - $tpl->scope = Smarty::SCOPE_LOCAL; - } - $tpl->tpl_vars = array(); - $tpl->config_vars = array(); - $tpl->smarty->_cache['template_objects'][$tpl->_getTemplateId()] = $tpl; + //load source + $tpl->source = null; + unset($tpl->compiled); + if (!isset($tpl->source)) { + $tpl->source = Smarty_Template_Source::load($tpl); } } + + /** + * Get called subtemplates and its call count from compiled template + * + * @param \Smarty_Internal_Template $tpl + */ + public function registerSubTemplates(Smarty_Internal_Template $tpl) { + foreach ($tpl->compiled->includes as $name => $count) { + if (isset($this->subTplInfo[$name])) { + $this->subTplInfo[$name] += $count; + } else { + $this->subTplInfo[$name] = $count; + } + } + +} } diff --git a/libs/sysplugins/smarty_internal_template.php b/libs/sysplugins/smarty_internal_template.php index 33939ad9..d1314058 100644 --- a/libs/sysplugins/smarty_internal_template.php +++ b/libs/sysplugins/smarty_internal_template.php @@ -123,7 +123,7 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase * @throws SmartyException * @return string rendered template output */ - public function render($merge_tpl_vars = false, $no_output_filter = true, $display = null) + public function render($no_output_filter = true, $display = null) { $parentIsTpl = isset($this->parent) && $this->parent->_objType == 2; if ($this->smarty->debugging) { @@ -138,36 +138,6 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase } throw new SmartyException("Unable to load template {$this->source->type} '{$this->source->name}'{$parent_resource}"); } - $save_tpl_vars = null; - $save_config_vars = null; - // merge all variable scopes into template - if ($merge_tpl_vars) { - // save local variables - $save_tpl_vars = $this->tpl_vars; - $save_config_vars = $this->config_vars; - $ptr_array = array($this); - $ptr = $this; - while (isset($ptr->parent)) { - $ptr_array[] = $ptr = $ptr->parent; - } - $ptr_array = array_reverse($ptr_array); - $parent_ptr = reset($ptr_array); - $tpl_vars = $parent_ptr->tpl_vars; - $config_vars = $parent_ptr->config_vars; - while ($parent_ptr = next($ptr_array)) { - if (!empty($parent_ptr->tpl_vars)) { - $tpl_vars = array_merge($tpl_vars, $parent_ptr->tpl_vars); - } - if (!empty($parent_ptr->config_vars)) { - $config_vars = array_merge($config_vars, $parent_ptr->config_vars); - } - } - if (!empty(Smarty::$global_tpl_vars)) { - $tpl_vars = array_merge(Smarty::$global_tpl_vars, $tpl_vars); - } - $this->tpl_vars = $tpl_vars; - $this->config_vars = $config_vars; - } // check URL debugging control if (!$this->smarty->debugging && $this->smarty->debugging_ctrl == 'URL') { $this->smarty->_debug->debugUrl($this); @@ -213,18 +183,8 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase // debug output $this->smarty->_debug->display_debug($this, true); } - if ($merge_tpl_vars) { - // restore local variables - $this->tpl_vars = $save_tpl_vars; - $this->config_vars = $save_config_vars; - } return ''; } else { - if ($merge_tpl_vars) { - // restore local variables - $this->tpl_vars = $save_tpl_vars; - $this->config_vars = $save_config_vars; - } if ($this->smarty->debugging) { $this->smarty->_debug->end_template($this); if ($this->smarty->debugging == 2 and $display === false) { diff --git a/libs/sysplugins/smarty_internal_templatebase.php b/libs/sysplugins/smarty_internal_templatebase.php index d6ef0f89..1ecba224 100644 --- a/libs/sysplugins/smarty_internal_templatebase.php +++ b/libs/sysplugins/smarty_internal_templatebase.php @@ -88,18 +88,14 @@ abstract class Smarty_Internal_TemplateBase extends Smarty_Internal_Data * @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) + public function fetch($template = null, $cache_id = null, $compile_id = null, $parent = null) { - $result = $this->_execute($template, $cache_id, $compile_id, $parent, 'fetch'); + $result = $this->_execute($template, $cache_id, $compile_id, $parent, 0); return $result === null ? ob_get_clean() : $result; } @@ -114,7 +110,7 @@ abstract class Smarty_Internal_TemplateBase extends Smarty_Internal_Data public function display($template = null, $cache_id = null, $compile_id = null, $parent = null) { // display template - $this->_execute($template, $cache_id, $compile_id, $parent, 'display'); + $this->_execute($template, $cache_id, $compile_id, $parent, 1); } /** @@ -132,7 +128,7 @@ abstract class Smarty_Internal_TemplateBase extends Smarty_Internal_Data */ public function isCached($template = null, $cache_id = null, $compile_id = null, $parent = null) { - return $this->_execute($template, $cache_id, $compile_id, $parent, 'isCached'); + return $this->_execute($template, $cache_id, $compile_id, $parent, 2); } /** @@ -142,7 +138,7 @@ abstract class Smarty_Internal_TemplateBase extends Smarty_Internal_Data * @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 + * @param string $function function type 0 = fetch, 1 = display, 2 = isCache * * @return mixed * @throws \Exception @@ -177,7 +173,7 @@ abstract class Smarty_Internal_TemplateBase extends Smarty_Internal_Data $_smarty_old_error_level = ($this->_objType == 1 && isset($smarty->error_reporting)) ? error_reporting($smarty->error_reporting) : null; - if ($function == 'isCached') { + if ($function == 2) { if ($template->caching) { // return cache status of template if (!isset($template->cached)) { @@ -190,7 +186,16 @@ abstract class Smarty_Internal_TemplateBase extends Smarty_Internal_Data } } else { ob_start(); - $result = $template->render(true, false, $function == 'display'); + $save_tpl_vars = $template->tpl_vars; + $save_config_vars = $template->config_vars; + $template->_mergeVars(); + if (!empty(Smarty::$global_tpl_vars)) { + $template->tpl_vars = array_merge(Smarty::$global_tpl_vars, $template->tpl_vars); + } + $result = $template->render(false, $function); + // restore local variables + $template->tpl_vars = $save_tpl_vars; + $template->config_vars = $save_config_vars; } if (isset($_smarty_old_error_level)) { error_reporting($_smarty_old_error_level); diff --git a/libs/sysplugins/smarty_template_compiled.php b/libs/sysplugins/smarty_template_compiled.php index 8cb29a64..1facc28f 100644 --- a/libs/sysplugins/smarty_template_compiled.php +++ b/libs/sysplugins/smarty_template_compiled.php @@ -152,24 +152,8 @@ class Smarty_Template_Compiled extends Smarty_Template_Resource_Base $_template->smarty->compile_check = $compileCheck; } } - if (isset($_template->parent) && isset($_template->parent->compiled) && - !empty($_template->parent->compiled->includes) && - $_template->smarty->resource_cache_mode & Smarty::RESOURCE_CACHE_AUTOMATIC && - !$_template->source->handler->recompiled && $_template->source->type != 'string' && - (!isset($_template->smarty->_cache['template_objects']) || - !isset($_template->smarty->_cache['template_objects'][$_template->_getTemplateId()])) - ) { - foreach ($_template->parent->compiled->includes as $key => $count) { - $_template->compiled->includes[$key] = - isset($_template->compiled->includes[$key]) ? $_template->compiled->includes[$key] + $count : - $count; - } - $key = $_template->source->type . ':' . $_template->source->name; - if (isset($_template->compiled->includes[$key]) && $_template->compiled->includes[$key] > 1) { - $_template->smarty->_cache['template_objects'][isset($_template->templateId) ? $_template->templateId : - $_template->_getTemplateId()] = $_template; - } - } + $_template->smarty->ext->_subTemplate->registerSubTemplates($_template); + $this->processed = true; }