diff --git a/change_log.txt b/change_log.txt index fd957ec8..d74c5f28 100644 --- a/change_log.txt +++ b/change_log.txt @@ -1,4 +1,7 @@  ===== 3.1.30-dev ===== (xx.xx.xx) + 24.04.2016 + - bugfix nested {include} with relative file path could fail when called in {block} ... {/block} https://github.com/smarty-php/smarty/issues/218 + 14.04.2016 - bugfix special variable {$smarty.capture.name} was not case sensitive on name https://github.com/smarty-php/smarty/issues/210 - bugfix the default template handler must calculate the source uid https://github.com/smarty-php/smarty/issues/205 diff --git a/libs/Smarty.class.php b/libs/Smarty.class.php index 031c1c10..9fe5670d 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/62'; + const SMARTY_VERSION = '3.1.30-dev/63'; /** * define variable scopes diff --git a/libs/sysplugins/smarty_internal_block.php b/libs/sysplugins/smarty_internal_block.php index d00b14a6..9a67757b 100644 --- a/libs/sysplugins/smarty_internal_block.php +++ b/libs/sysplugins/smarty_internal_block.php @@ -65,6 +65,13 @@ class Smarty_Internal_Block */ public $tplIndex = 0; + /** + * Nesting level of called sub-templates + * + * @var int + */ + public $subTemplateNesting = 0; + /** * Smarty_Internal_Block constructor. * - if outer level {block} of child template ($state == 1) save it as child root block @@ -75,12 +82,13 @@ class Smarty_Internal_Block */ public function __construct(Smarty_Internal_Template $tpl, $tplIndex = null) { - $this->tplIndex = $tplIndex ? $tplIndex : $tpl->ext->_inheritance->tplIndex; - if (isset($tpl->ext->_inheritance->childRoot[ $this->name ])) { - $this->child = $tpl->ext->_inheritance->childRoot[ $this->name ]; + $inheritance = &$tpl->ext->_inheritance; + $this->tplIndex = $tplIndex ? $tplIndex : $inheritance->tplIndex; + if (isset($inheritance->childRoot[ $this->name ])) { + $this->child = $inheritance->childRoot[ $this->name ]; } - if ($tpl->ext->_inheritance->state == 1) { - $tpl->ext->_inheritance->childRoot[ $this->name ] = $this; + if ($inheritance->state == 1) { + $inheritance->childRoot[ $this->name ] = $this; return; } // make sure we got child block of child template of current block @@ -98,6 +106,7 @@ class Smarty_Internal_Block */ public function process(Smarty_Internal_Template $tpl, Smarty_Internal_Block $parent = null) { + $inheritance = &$tpl->ext->_inheritance; if ($this->hide && !isset($this->child)) { return; } @@ -109,7 +118,10 @@ class Smarty_Internal_Block $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); } @@ -117,7 +129,10 @@ class Smarty_Internal_Block $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); } @@ -157,9 +172,12 @@ class Smarty_Internal_Block 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->templateResource[$this->tplIndex]}' block '{$this->name}'"); + 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 cc9fc6aa..0d3c59ba 100644 --- a/libs/sysplugins/smarty_internal_compile_block.php +++ b/libs/sysplugins/smarty_internal_compile_block.php @@ -201,7 +201,6 @@ class Smarty_Internal_Compile_Blockclose extends Smarty_Internal_Compile_Shared_ if ($compiler->template->compiled->has_nocache_code) { $output .= "\$_smarty_tpl->cached->hashes['{$compiler->template->compiled->nocache_hash}'] = true;\n"; } - $output .= "\$_smarty_tpl->ext->_inheritance->blockNesting++;\n"; if (isset($_assign)) { $output .= "ob_start();\n"; } @@ -214,8 +213,6 @@ class Smarty_Internal_Compile_Blockclose extends Smarty_Internal_Compile_Shared_ if (isset($_assign)) { $output .= "\$_smarty_tpl->assign({$_assign}, ob_get_clean());\n"; } - //$output .= "/*%%SmartyNocache:{$compiler->template->compiled->nocache_hash}%%*/\n"; - $output .= "\$_smarty_tpl->ext->_inheritance->blockNesting--;\n"; $output .= "}\n"; $output .= "}\n"; $output .= "/* {/block '{$_name}'} */\n\n"; diff --git a/libs/sysplugins/smarty_internal_resource_file.php b/libs/sysplugins/smarty_internal_resource_file.php index 784a0fa3..fcf7e4f3 100644 --- a/libs/sysplugins/smarty_internal_resource_file.php +++ b/libs/sysplugins/smarty_internal_resource_file.php @@ -43,16 +43,13 @@ class Smarty_Internal_Resource_File extends Smarty_Resource ) { throw new SmartyException("Template '{$file}' cannot be relative to template of resource type '{$_template->parent->source->type}'"); } - // if we are inside an {block} tag the path must be relative to current template - if (isset($_template->ext->_inheritance) && $_template->ext->_inheritance->blockNesting && - $_template->parent->parent->_objType == 2 - ) { - $path = dirname($_template->parent->parent->source->filepath) . DS . $file; - } else { - $path = dirname($_template->parent->source->filepath) . DS . $file; + $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()) { + $parentPath = $path; } // normalize path - $path = $source->smarty->_realpath($path); + $path = $source->smarty->_realpath(dirname($parentPath) . DS . $file); // files relative to a template only get one shot return is_file($path) ? $path : false; } diff --git a/libs/sysplugins/smarty_internal_runtime_inheritance.php b/libs/sysplugins/smarty_internal_runtime_inheritance.php index 96eba319..eefc899c 100644 --- a/libs/sysplugins/smarty_internal_runtime_inheritance.php +++ b/libs/sysplugins/smarty_internal_runtime_inheritance.php @@ -45,19 +45,19 @@ class Smarty_Internal_Runtime_Inheritance public $tplIndex = - 1; /** - * current block nesting level - * - * @var int - */ - public $blockNesting = 0; - - /** - * Array of source template names + * Array of template source objects * - key template index * - * @var string[] + * @var Smarty_Template_Source[] */ - public $templateResource = array(); + public $sources = array(); + + /** + * Call stack of block objects + * + * @var Smarty_Internal_Block[] + */ + public $blockCallStack = array(); /** * Initialize inheritance @@ -87,7 +87,7 @@ class Smarty_Internal_Runtime_Inheritance // in parent state {include} will not increment template index if ($this->state != 3) { $this->tplIndex ++; - $this->templateResource[ $this->tplIndex ] = $tpl->template_resource; + $this->sources[ $this->tplIndex ] = $tpl->source; } // if state was waiting for parent change state to parent if ($this->state == 2) { @@ -109,4 +109,37 @@ class Smarty_Internal_Runtime_Inheritance $this->state = 2; } } + + /** + * Return source filepath of current {block} if not in sub-template + * + * @return bool|string filepath or false + */ + public function getBlockFilepath() + { + if (!empty($this->blockCallStack) && $this->blockCallStack[ 0 ]->subTemplateNesting === 0) { + return $this->sources[ $this->blockCallStack[ 0 ]->tplIndex ]->filepath; + } + return false; + } + + /** + * Increment sub-template nesting count in current block object + */ + public function subTemplateStart() + { + if (!empty($this->blockCallStack)) { + $this->blockCallStack[ 0 ]->subTemplateNesting ++; + } + } + + /** + * Decrement sub-template nesting count in current block object + */ + public function subTemplateEnd() + { + if (!empty($this->blockCallStack)) { + $this->blockCallStack[ 0 ]->subTemplateNesting --; + } + } } diff --git a/libs/sysplugins/smarty_internal_template.php b/libs/sysplugins/smarty_internal_template.php index 02ce83d8..7a9a7d1e 100644 --- a/libs/sysplugins/smarty_internal_template.php +++ b/libs/sysplugins/smarty_internal_template.php @@ -101,7 +101,6 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase */ public $endRenderCallbacks = array(); - /** * Create template data object * Some of the global Smarty settings copied to template scope @@ -330,7 +329,10 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase } } $tpl->_cache = array(); - $saved_inheritance = isset($tpl->ext->_inheritance) ? $tpl->ext->_inheritance : null; + if (isset($tpl->ext->_inheritance)) { + $saved_inheritance = $tpl->ext->_inheritance; + $saved_inheritance->subTemplateStart(); + } if (isset($uid)) { if ($smarty->debugging) { $smarty->_debug->start_template($tpl); @@ -349,6 +351,7 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase } } if (isset($saved_inheritance)) { + $saved_inheritance->subTemplateEnd(); $tpl->ext->_inheritance = $saved_inheritance; } else { unset($tpl->ext->_inheritance);