diff --git a/change_log.txt b/change_log.txt index 6935e1cf..5352df0c 100644 --- a/change_log.txt +++ b/change_log.txt @@ -1,4 +1,7 @@  ===== 3.1.30-dev ===== (xx.xx.xx) + 10.05.2016 + - optimization of inheritance processing + 07.05.2016 -bugfix Only variables should be assigned by reference https://github.com/smarty-php/smarty/issues/227 diff --git a/libs/Smarty.class.php b/libs/Smarty.class.php index 03768cb2..d29fe841 100644 --- a/libs/Smarty.class.php +++ b/libs/Smarty.class.php @@ -121,7 +121,7 @@ class Smarty extends Smarty_Internal_TemplateBase /** * smarty version */ - const SMARTY_VERSION = '3.1.30-dev/67'; + const SMARTY_VERSION = '3.1.30-dev/68'; /** * define variable scopes diff --git a/libs/sysplugins/smarty_internal_block.php b/libs/sysplugins/smarty_internal_block.php index 20ca3d02..476befc2 100644 --- a/libs/sysplugins/smarty_internal_block.php +++ b/libs/sysplugins/smarty_internal_block.php @@ -77,69 +77,13 @@ class Smarty_Internal_Block * - if outer level {block} of child template ($state == 1) save it as child root block * - otherwise process inheritance and render * - * @param \Smarty_Internal_Template $tpl - * @param int|null $tplIndex index of outer level {block} if nested + * @param string $name block name + * @param int|null $tplIndex index of outer level {block} if nested */ - public function __construct(Smarty_Internal_Template $tpl, $name, $tplIndex = null) + public function __construct($name, $tplIndex) { $this->name = $name; - $inheritance = &$tpl->ext->_inheritance; - $this->tplIndex = $tplIndex ? $tplIndex : $inheritance->tplIndex; - if (isset($inheritance->childRoot[ $this->name ])) { - $this->child = $inheritance->childRoot[ $this->name ]; - } - if ($inheritance->state == 1) { - $inheritance->childRoot[ $this->name ] = $this; - return; - } - // make sure we got child block of child template of current block - while ($this->child && $this->tplIndex <= $this->child->tplIndex) { - $this->child = $this->child->child; - } - $this->process($tpl); - } - - /** - * Goto child block or render this - * - * @param \Smarty_Internal_Template $tpl - * @param \Smarty_Internal_Block|null $parent - */ - public function process(Smarty_Internal_Template $tpl, Smarty_Internal_Block $parent = null) - { - $inheritance = &$tpl->ext->_inheritance; - if ($this->hide && !isset($this->child)) { - return; - } - if (isset($this->child) && $this->child->hide && !isset($this->child->child)) { - $this->child = null; - } - $this->parent = $parent; - if ($this->append && !$this->prepend && isset($parent)) { - $this->callParent($tpl); - } - if ($this->callsChild || !isset($this->child) || ($this->child->hide && !isset($this->child->child))) { - $this->subTemplateNesting = 0; - array_unshift($inheritance->blockCallStack, $this); - $this->callBlock($tpl); - array_shift($inheritance->blockCallStack); - } else { - $this->child->process($tpl, $this); - } - if ($this->prepend && isset($parent)) { - $this->callParent($tpl); - if ($this->append) { - if ($this->callsChild || !isset($this->child) || ($this->child->hide && !isset($this->child->child))) { - $this->subTemplateNesting = 0; - array_unshift($inheritance->blockCallStack, $this); - $this->callBlock($tpl); - array_shift($inheritance->blockCallStack); - } else { - $this->child->process($tpl, $this); - } - } - } - $this->parent = null; + $this->tplIndex = $tplIndex; } /** @@ -150,35 +94,4 @@ class Smarty_Internal_Block public function callBlock(Smarty_Internal_Template $tpl) { } - - /** - * Render child on {$smarty.block.child} - * - * @param \Smarty_Internal_Template $tpl - */ - public function callChild(Smarty_Internal_Template $tpl) - { - if (isset($this->child)) { - $this->child->process($tpl, $this); - } - } - - /** - * Render parent on {$smarty.block.parent} or {block append/prepend} * - * - * @param \Smarty_Internal_Template $tpl - * - * @throws \SmartyException - */ - public function callParent(Smarty_Internal_Template $tpl) - { - if (isset($this->parent)) { - $this->parent->subTemplateNesting = 0; - array_unshift($tpl->ext->_inheritance->blockCallStack, $this->parent); - $this->parent->callBlock($tpl); - array_shift($tpl->ext->_inheritance->blockCallStack); - } else { - throw new SmartyException("inheritance: illegal {\$smarty.block.parent} or {block append/prepend} used in parent template '{$tpl->ext->_inheritance->sources[$this->tplIndex]->filepath}' block '{$this->name}'"); - } - } } \ No newline at end of file diff --git a/libs/sysplugins/smarty_internal_compile_block.php b/libs/sysplugins/smarty_internal_compile_block.php index c84f7d87..e2878947 100644 --- a/libs/sysplugins/smarty_internal_compile_block.php +++ b/libs/sysplugins/smarty_internal_compile_block.php @@ -121,7 +121,7 @@ class Smarty_Internal_Compile_Block extends Smarty_Internal_Compile_Shared_Inher $compiler->has_code = true; $compiler->suppressNocacheProcessing = true; $compiler->_cache[ 'blockParams' ][ $compiler->_cache[ 'blockNesting' ] ][ 'callsChild' ] = 'true'; - $output = "callChild(\$_smarty_tpl);\n?>\n"; + $output = "inheritance->callChild(\$_smarty_tpl, \$this);\n?>\n"; return $output; } @@ -141,7 +141,7 @@ class Smarty_Internal_Compile_Block extends Smarty_Internal_Compile_Shared_Inher } $compiler->suppressNocacheProcessing = true; $compiler->has_code = true; - $output = "callParent(\$_smarty_tpl);\n?>\n"; + $output = "inheritance->callParent(\$_smarty_tpl, \$this);\n?>\n"; return $output; } } @@ -180,16 +180,9 @@ class Smarty_Internal_Compile_Blockclose extends Smarty_Internal_Compile_Shared_ $_functionCode = $compiler->parser->current_buffer; // setup buffer for template function code $compiler->parser->current_buffer = new Smarty_Internal_ParseTree_Template(); - if ($compiler->template->source->type == 'file') { - $sourceInfo = $compiler->template->source->filepath; - } else { - $basename = $compiler->template->source->handler->getBasename($compiler->template->source); - $sourceInfo = - $compiler->template->source->type . ':' . ($basename ? $basename : $compiler->template->source->name); - } $output = " $value) { @@ -238,9 +231,9 @@ class Smarty_Internal_Compile_Blockclose extends Smarty_Internal_Compile_Shared_ $compiler->parser->current_buffer = $_buffer; $output = "_cache[ 'blockNesting' ] == 1) { - $output .= "new {$_className}(\$_smarty_tpl, $_name);\n"; + $output .= "\$_smarty_tpl->inheritance->instanceBlock(\$_smarty_tpl, '$_className', $_name);\n"; } else { - $output .= "new {$_className}(\$_smarty_tpl, $_name, \$this->tplIndex);\n"; + $output .= "\$_smarty_tpl->inheritance->instanceBlock(\$_smarty_tpl, '$_className', $_name, \$this->tplIndex);\n"; } $output .= "?>\n"; $compiler->_cache[ 'blockNesting' ] --; diff --git a/libs/sysplugins/smarty_internal_compile_extends.php b/libs/sysplugins/smarty_internal_compile_extends.php index 2e4b543c..ccbb54fa 100644 --- a/libs/sysplugins/smarty_internal_compile_extends.php +++ b/libs/sysplugins/smarty_internal_compile_extends.php @@ -99,7 +99,7 @@ class Smarty_Internal_Compile_Extends extends Smarty_Internal_Compile_Shared_Inh private function compileEndChild(Smarty_Internal_TemplateCompilerBase $compiler) { $compiler->parser->template_postfix[] = new Smarty_Internal_ParseTree_Tag($compiler->parser, - "ext->_inheritance->endChild(\$_smarty_tpl);\n?>\n"); + "inheritance->endChild(\$_smarty_tpl);\n?>\n"); } /** diff --git a/libs/sysplugins/smarty_internal_compile_include.php b/libs/sysplugins/smarty_internal_compile_include.php index 8078b369..3c840e67 100644 --- a/libs/sysplugins/smarty_internal_compile_include.php +++ b/libs/sysplugins/smarty_internal_compile_include.php @@ -297,8 +297,8 @@ class Smarty_Internal_Compile_Include extends Smarty_Internal_CompileBase if (!($tpl->source->handler->uncompiled) && $tpl->source->exists) { $compiler->parent_compiler->mergedSubTemplatesData[ $uid ][ $t_hash ][ 'uid' ] = $tpl->source->uid; - if (isset($compiler->template->ext->_inheritance)) { - $tpl->ext->_inheritance = clone $compiler->template->ext->_inheritance; + if (isset($compiler->template->inheritance)) { + $tpl->inheritance = clone $compiler->template->inheritance; } $tpl->compiled = new Smarty_Template_Compiled(); $tpl->compiled->nocache_hash = $compiler->parent_compiler->template->compiled->nocache_hash; diff --git a/libs/sysplugins/smarty_internal_compile_shared_inheritance.php b/libs/sysplugins/smarty_internal_compile_shared_inheritance.php index d2089760..c9557659 100644 --- a/libs/sysplugins/smarty_internal_compile_shared_inheritance.php +++ b/libs/sysplugins/smarty_internal_compile_shared_inheritance.php @@ -40,7 +40,7 @@ class Smarty_Internal_Compile_Shared_Inheritance extends Smarty_Internal_Compile */ static function postCompile(Smarty_Internal_TemplateCompilerBase $compiler, $initChildSequence = false) { - $compiler->prefixCompiledCode .= "ext->_inheritance->init(\$_smarty_tpl, " . + $compiler->prefixCompiledCode .= "_loadInheritance();\n\$_smarty_tpl->inheritance->init(\$_smarty_tpl, " . var_export($initChildSequence, true) . ");\n?>\n"; } } \ No newline at end of file diff --git a/libs/sysplugins/smarty_internal_extension_handler.php b/libs/sysplugins/smarty_internal_extension_handler.php index 71f06de6..edeb3958 100644 --- a/libs/sysplugins/smarty_internal_extension_handler.php +++ b/libs/sysplugins/smarty_internal_extension_handler.php @@ -10,7 +10,6 @@ * @subpackage PluginsInternal * @author Uwe Tews * - * @property Smarty_Internal_Runtime_Inheritance $_inheritance * @property Smarty_Internal_Runtime_TplFunction $_tplFunction * @property Smarty_Internal_Runtime_Foreach $_foreach * @property Smarty_Internal_Runtime_WriteFile $_writeFile diff --git a/libs/sysplugins/smarty_internal_resource_file.php b/libs/sysplugins/smarty_internal_resource_file.php index fcf7e4f3..adb3b90b 100644 --- a/libs/sysplugins/smarty_internal_resource_file.php +++ b/libs/sysplugins/smarty_internal_resource_file.php @@ -45,7 +45,7 @@ class Smarty_Internal_Resource_File extends Smarty_Resource } $parentPath = $_template->parent->source->filepath; // if we are inside an {block} tag the path must be relative to template of {block} - if (isset($_template->ext->_inheritance) && $path = $_template->ext->_inheritance->getBlockFilepath()) { + if (isset($_template->inheritance) && $path = $_template->inheritance->getBlockFilepath()) { $parentPath = $path; } // normalize path diff --git a/libs/sysplugins/smarty_internal_runtime_inheritance.php b/libs/sysplugins/smarty_internal_runtime_inheritance.php index eefc899c..66e81463 100644 --- a/libs/sysplugins/smarty_internal_runtime_inheritance.php +++ b/libs/sysplugins/smarty_internal_runtime_inheritance.php @@ -71,8 +71,8 @@ class Smarty_Internal_Runtime_Inheritance { // if called while executing parent template it must be a sub-template with new inheritance root if ($initChild && $this->state == 3 && (strpos($tpl->template_resource, 'extendsall') === false)) { - $tpl->ext->_inheritance = new Smarty_Internal_Runtime_Inheritance(); - $tpl->ext->_inheritance->init($tpl, $initChild, $blockNames); + $tpl->inheritance = new Smarty_Internal_Runtime_Inheritance(); + $tpl->inheritance->init($tpl, $initChild, $blockNames); return; } // start of child sub template(s) @@ -83,6 +83,8 @@ class Smarty_Internal_Runtime_Inheritance ob_start(); } $this->inheritanceLevel ++; + $tpl->startRenderCallbacks[ 'inheritance' ] = array($this, 'subTemplateStart'); + $tpl->endRenderCallbacks[ 'inheritance' ] = array($this, 'subTemplateEnd'); } // in parent state {include} will not increment template index if ($this->state != 3) { @@ -110,6 +112,114 @@ class Smarty_Internal_Runtime_Inheritance } } + /** + * Smarty_Internal_Block constructor. + * - if outer level {block} of child template ($state == 1) save it as child root block + * - otherwise process inheritance and render + * + * @param \Smarty_Internal_Template $tpl + * @param $className + * @param string $name + * @param int|null $tplIndex index of outer level {block} if nested + */ + public function instanceBlock(Smarty_Internal_Template $tpl, $className, $name, $tplIndex = null) + { + $block = new $className($name, $tplIndex ? $tplIndex : $this->tplIndex); + if (isset($this->childRoot[ $name ])) { + $block->child = $this->childRoot[ $name ]; + } + if ($this->state == 1) { + $this->childRoot[ $name ] = $block; + return; + } + // make sure we got child block of child template of current block + while ($block->child && $block->tplIndex <= $block->child->tplIndex) { + $block->child = $block->child->child; + } + $this->process($tpl, $block); + } + + /** + * Goto child block or render this + * + * @param \Smarty_Internal_Template $tpl + * @param \Smarty_Internal_Block $block + * @param \Smarty_Internal_Block|null $parent + * + * @throws \SmartyException + */ + public function process(Smarty_Internal_Template $tpl, Smarty_Internal_Block $block, + Smarty_Internal_Block $parent = null) + { + if ($block->hide && !isset($block->child)) { + return; + } + if (isset($block->child) && $block->child->hide && !isset($block->child->child)) { + $block->child = null; + } + $block->parent = $parent; + if ($block->append && !$block->prepend && isset($parent)) { + $this->callParent($tpl, $block); + } + if ($block->callsChild || !isset($block->child) || ($block->child->hide && !isset($block->child->child))) { + $block->subTemplateNesting = 0; + $this->blockCallStack[] = $block; + $block->callBlock($tpl); + array_pop($this->blockCallStack); + } else { + $this->process($tpl, $block->child, $block); + } + if ($block->prepend && isset($parent)) { + $this->callParent($tpl, $block); + if ($block->append) { + if ($block->callsChild || !isset($block->child) || + ($block->child->hide && !isset($block->child->child)) + ) { + $block->subTemplateNesting = 0; + $this->blockCallStack[] = $block; + $block->callBlock($tpl); + array_pop($this->blockCallStack); + } else { + $this->process($tpl, $block->child, $block); + } + } + } + $block->parent = null; + } + + /** + * Render child on {$smarty.block.child} + * + * @param \Smarty_Internal_Template $tpl + * @param \Smarty_Internal_Block $block + */ + public function callChild(Smarty_Internal_Template $tpl, Smarty_Internal_Block $block) + { + if (isset($block->child)) { + $this->process($tpl, $block->child, $block); + } + } + + /** + * Render parent on {$smarty.block.parent} or {block append/prepend} * + * + * @param \Smarty_Internal_Template $tpl + * @param \Smarty_Internal_Block $block + * + * @throws \SmartyException + */ + public function callParent(Smarty_Internal_Template $tpl, Smarty_Internal_Block $block) + { + if (isset($block->parent)) { + $block->parent->subTemplateNesting = 0; + $this->blockCallStack[] = $block->parent; + $block->parent->callBlock($tpl); + array_pop($this->blockCallStack); + } else { + throw new SmartyException("inheritance: illegal {\$smarty.block.parent} or {block append/prepend} used in parent template '{$tpl->inheritance->sources[$block->tplIndex]->filepath}' block '{$block->name}'"); + } + } + /** * Return source filepath of current {block} if not in sub-template * @@ -117,8 +227,9 @@ class Smarty_Internal_Runtime_Inheritance */ public function getBlockFilepath() { - if (!empty($this->blockCallStack) && $this->blockCallStack[ 0 ]->subTemplateNesting === 0) { - return $this->sources[ $this->blockCallStack[ 0 ]->tplIndex ]->filepath; + $count = count($this->blockCallStack); + if ($count && $this->blockCallStack[ $count - 1 ]->subTemplateNesting === 0) { + return $this->sources[ $this->blockCallStack[ $count - 1 ]->tplIndex ]->filepath; } return false; } @@ -128,8 +239,9 @@ class Smarty_Internal_Runtime_Inheritance */ public function subTemplateStart() { - if (!empty($this->blockCallStack)) { - $this->blockCallStack[ 0 ]->subTemplateNesting ++; + $count = count($this->blockCallStack); + if ($count) { + $this->blockCallStack[ $count - 1 ]->subTemplateNesting ++; } } @@ -138,8 +250,9 @@ class Smarty_Internal_Runtime_Inheritance */ public function subTemplateEnd() { - if (!empty($this->blockCallStack)) { - $this->blockCallStack[ 0 ]->subTemplateNesting --; + $count = count($this->blockCallStack); + if ($count && $this->blockCallStack[ $count - 1 ]->subTemplateNesting) { + $this->blockCallStack[ $count - 1 ]->subTemplateNesting --; } } } diff --git a/libs/sysplugins/smarty_internal_template.php b/libs/sysplugins/smarty_internal_template.php index 84952c4b..8c9d92ac 100644 --- a/libs/sysplugins/smarty_internal_template.php +++ b/libs/sysplugins/smarty_internal_template.php @@ -46,6 +46,13 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase */ public $source = null; + /** + * Inheritance runtime extension + * + * @var Smarty_Internal_Runtime_Inheritance + */ + public $inheritance = null; + /** * Template resource * @@ -256,7 +263,7 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase $smarty = &$this->smarty; $_templateId = $smarty->_getTemplateId($template, $cache_id, $compile_id, $caching, $tpl); // recursive call ? - if ($tpl->_getTemplateId() != $_templateId) { + if (isset($tpl->templateId) ? $tpl->templateId : $tpl->_getTemplateId() != $_templateId) { // already in template cache? if (isset($smarty->_cache[ 'tplObjects' ][ $_templateId ])) { // copy data from cached object @@ -330,10 +337,6 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase } } $tpl->_cache = array(); - if (isset($tpl->ext->_inheritance)) { - $saved_inheritance = $tpl->ext->_inheritance; - $saved_inheritance->subTemplateStart(); - } if (isset($uid)) { if ($smarty->debugging) { $smarty->_debug->start_template($tpl); @@ -351,12 +354,6 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase $tpl->render(); } } - if (isset($saved_inheritance)) { - $saved_inheritance->subTemplateEnd(); - $tpl->ext->_inheritance = $saved_inheritance; - } else { - unset($tpl->ext->_inheritance); - } } /** @@ -553,6 +550,29 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase } } + /** + * Load inheritance object + * + */ + public function _loadInheritance() + { + if (!isset($this->inheritance)) { + $this->inheritance = new Smarty_Internal_Runtime_Inheritance(); + } + } + + /** + * Unload inheritance object + * + */ + public function _cleanUp() + { + $this->tpl_function = array(); + $this->startRenderCallbacks = array(); + $this->endRenderCallbacks = array(); + $this->inheritance = null; + } + /** * Load compiler object * diff --git a/libs/sysplugins/smarty_internal_templatebase.php b/libs/sysplugins/smarty_internal_templatebase.php index 21c03282..525091e0 100644 --- a/libs/sysplugins/smarty_internal_templatebase.php +++ b/libs/sysplugins/smarty_internal_templatebase.php @@ -198,9 +198,8 @@ abstract class Smarty_Internal_TemplateBase extends Smarty_Internal_Data $template->tpl_vars = array_merge(Smarty::$global_tpl_vars, $template->tpl_vars); } $result = $template->render(false, $function); - unset($template->ext->_inheritance); - $template->tpl_function = array(); - if ($saveVars) { + $template->_cleanUp(); + if ($saveVars) { $template->tpl_vars = $savedTplVars; $template->config_vars = $savedConfigVars; } else { diff --git a/libs/sysplugins/smarty_resource.php b/libs/sysplugins/smarty_resource.php index 9697e939..b66b1530 100644 --- a/libs/sysplugins/smarty_resource.php +++ b/libs/sysplugins/smarty_resource.php @@ -216,7 +216,7 @@ abstract class Smarty_Resource ) { $parentPath = $obj->parent->source->filepath; // if we are inside an {block} tag the path must be relative to template of {block} - if (isset($obj->ext->_inheritance) && $path = $obj->ext->_inheritance->getBlockFilepath()) { + if (isset($obj->inheritance) && $path = $obj->inheritance->getBlockFilepath()) { $parentPath = $path; } $name = $smarty->_realpath(dirname($parentPath) . DS . $name);