bugfix $smarty.block.child and $smarty.block.parent could not be used like any

$smarty special variable https://github.com/smarty-php/smarty/issues/393
This commit is contained in:
Uwe Tews
2017-10-12 08:21:12 +02:00
parent 34fc5e6b46
commit b271173a2d
14 changed files with 1681 additions and 1802 deletions

View File

@@ -1,4 +1,8 @@
===== 3.1.32 - dev === ===== 3.1.32 - dev ===
12.10.2017
- bugfix $smarty.block.child and $smarty.block.parent could not be used like any
$smarty special variable https://github.com/smarty-php/smarty/issues/393
07.10.2017 07.10.2017
- bugfix modification of 9.8.2017 did fail on some recursive - bugfix modification of 9.8.2017 did fail on some recursive
tag nesting. https://github.com/smarty-php/smarty/issues/389 tag nesting. https://github.com/smarty-php/smarty/issues/389

View File

@@ -344,7 +344,6 @@ class Smarty_Internal_Templatelexer
rdel = ~\s*SMARTYrdel~ rdel = ~\s*SMARTYrdel~
nocacherdel = ~(\s+nocache)?\s*SMARTYrdel~ nocacherdel = ~(\s+nocache)?\s*SMARTYrdel~
notblockid = ~(?:(?!block)[0-9]*[a-zA-Z_]\w*)~ notblockid = ~(?:(?!block)[0-9]*[a-zA-Z_]\w*)~
smartyblockchildparent = ~[\$]smarty\.block\.(child|parent)~
integer = ~\d+~ integer = ~\d+~
hex = ~0[xX][0-9a-fA-F]+~ hex = ~0[xX][0-9a-fA-F]+~
math = ~\s*([*]{1,2}|[%/^&]|[<>]{2})\s*~ math = ~\s*([*]{1,2}|[%/^&]|[<>]{2})\s*~
@@ -515,10 +514,6 @@ class Smarty_Internal_Templatelexer
singlequotestring { singlequotestring {
$this->token = Smarty_Internal_Templateparser::TP_SINGLEQUOTESTRING; $this->token = Smarty_Internal_Templateparser::TP_SINGLEQUOTESTRING;
} }
smartyblockchildparent {
$this->token = Smarty_Internal_Templateparser::TP_SMARTYBLOCKCHILDPARENT;
$this->taglineno = $this->line;
}
dollar id { dollar id {
$this->token = Smarty_Internal_Templateparser::TP_DOLLARID; $this->token = Smarty_Internal_Templateparser::TP_DOLLARID;
} }

View File

@@ -514,18 +514,6 @@ tag(res) ::= LDELSETFILTER ID(m) modparameters(p) modifierlist(l). {
res = $this->compiler->compileTag('setfilter',array(),array('modifier_list'=>array_merge(array(array_merge(array(m),p)),l))); res = $this->compiler->compileTag('setfilter',array(),array('modifier_list'=>array_merge(array(array_merge(array(m),p)),l)));
} }
// {$smarty.block.child} or {$smarty.block.parent}
tag(res) ::= LDEL SMARTYBLOCKCHILDPARENT(i). {
$j = strrpos(i,'.');
if (i[$j+1] == 'c') {
// {$smarty.block.child}
res = $this->compiler->compileTag('block_child',array());;
} else {
// {$smarty.block.parent}
res = $this->compiler->compileTag('block_parent',array());;
}
}
// end of block tag {/....} // end of block tag {/....}
smartytag(res)::= CLOSETAG(t). { smartytag(res)::= CLOSETAG(t). {

View File

@@ -108,7 +108,7 @@ class Smarty extends Smarty_Internal_TemplateBase
/** /**
* smarty version * smarty version
*/ */
const SMARTY_VERSION = '3.1.32-dev-23'; const SMARTY_VERSION = '3.1.32-dev-24';
/** /**
* define variable scopes * define variable scopes
@@ -893,7 +893,7 @@ class Smarty extends Smarty_Internal_TemplateBase
$dir = &$this->template_dir; $dir = &$this->template_dir;
} }
if ($isConfig ? !$this->_configDirNormalized : !$this->_templateDirNormalized) { if ($isConfig ? !$this->_configDirNormalized : !$this->_templateDirNormalized) {
$this->_nomalizeTemplateConfig($isConfig); $this->_normalizeTemplateConfig($isConfig);
} }
if ($index !== null) { if ($index !== null) {
return isset($dir[ $index ]) ? $dir[ $index ] : null; return isset($dir[ $index ]) ? $dir[ $index ] : null;
@@ -1068,7 +1068,7 @@ class Smarty extends Smarty_Internal_TemplateBase
* @param bool $isConfig true for config_dir * @param bool $isConfig true for config_dir
* *
*/ */
private function _nomalizeTemplateConfig($isConfig) private function _normalizeTemplateConfig($isConfig)
{ {
if ($isConfig) { if ($isConfig) {
$processed = &$this->_processedConfigDir; $processed = &$this->_processedConfigDir;
@@ -1115,7 +1115,7 @@ class Smarty extends Smarty_Internal_TemplateBase
$data = null; $data = null;
} }
if (!$this->_templateDirNormalized) { if (!$this->_templateDirNormalized) {
$this->_nomalizeTemplateConfig(false); $this->_normalizeTemplateConfig(false);
} }
$_templateId = $this->_getTemplateId($template, $cache_id, $compile_id); $_templateId = $this->_getTemplateId($template, $cache_id, $compile_id);
$tpl = null; $tpl = null;

View File

@@ -38,7 +38,7 @@ class Smarty_Internal_Block
public $prepend = false; public $prepend = false;
/** /**
* Block calls {$smarty.block.child} * Block calls $smarty.block.child
* *
* @var bool * @var bool
*/ */

View File

@@ -61,7 +61,7 @@ class Smarty_Internal_Compile_Block extends Smarty_Internal_Compile_Shared_Inher
* @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
* @param array $parameter array with compilation parameter * @param array $parameter array with compilation parameter
* *
* @return bool true * @return string compiled code
*/ */
public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter) public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter)
{ {
@@ -83,7 +83,9 @@ class Smarty_Internal_Compile_Block extends Smarty_Internal_Compile_Shared_Inher
$compiler->_cache['blockClass'][ $compiler->_cache['blockNesting'] ] = $_className; $compiler->_cache['blockClass'][ $compiler->_cache['blockNesting'] ] = $_className;
$compiler->_cache['blockParams'][ $compiler->_cache['blockNesting'] ] = array(); $compiler->_cache['blockParams'][ $compiler->_cache['blockNesting'] ] = array();
$compiler->_cache['blockParams'][1]['subBlocks'][ trim($_attr['name'], '"\'') ][] = $_className; $compiler->_cache['blockParams'][1]['subBlocks'][ trim($_attr['name'], '"\'') ][] = $_className;
$this->openTag($compiler, 'block', array($_attr, $compiler->nocache, $compiler->parser->current_buffer, $this->openTag($compiler,
'block',
array($_attr, $compiler->nocache, $compiler->parser->current_buffer,
$compiler->template->compiled->has_nocache_code, $compiler->template->compiled->has_nocache_code,
$compiler->template->caching)); $compiler->template->caching));
// must whole block be nocache ? // must whole block be nocache ?
@@ -99,6 +101,45 @@ class Smarty_Internal_Compile_Block extends Smarty_Internal_Compile_Shared_Inher
$compiler->template->compiled->has_nocache_code = false; $compiler->template->compiled->has_nocache_code = false;
$compiler->suppressNocacheProcessing = true; $compiler->suppressNocacheProcessing = true;
} }
/**
* Compiles code for the {$smarty.foreach.xxx} or {$smarty.section.xxx}tag
*
* @param array $args array with attributes from parser
* @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
* @param array $parameter array with compilation parameter
*
* @return string compiled code
* @throws \SmartyCompilerException
*/
public function compileSpecialVariable($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter)
{
$name = isset($parameter[1]) ? $compiler->getId($parameter[1]) : false;
if (!$name) {
$compiler->trigger_template_error("invalid \"\$smarty.block\" expected \"\$smarty.block.child\" or \"\$smarty.block.parent\"",
null,
true);
}
if (!isset($compiler->_cache['blockNesting'])) {
$compiler->trigger_template_error(" \"\$smarty.block.{$name}\" used outside {block} tags ",
$compiler->parser->lex->taglineno);
}
$compiler->has_code = true;
$compiler->suppressNocacheProcessing = true;
switch ($name) {
case 'child':
$compiler->_cache['blockParams'][ $compiler->_cache['blockNesting'] ]['callsChild'] = 'true';
return '$_smarty_tpl->inheritance->callChild($_smarty_tpl, $this, true)';
break;
case 'parent':
return '$_smarty_tpl->inheritance->callParent($_smarty_tpl, $this, null, true)';
break;
default:
$compiler->trigger_template_error("invalid \"\$smarty.block.{$name}\" expected \"\$smarty.block.child\" or \"\$smarty.block.parent\"",
null,
true);
}
}
} }
/** /**
@@ -114,7 +155,7 @@ class Smarty_Internal_Compile_Blockclose extends Smarty_Internal_Compile_Shared_
* @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
* @param array $parameter array with compilation parameter * @param array $parameter array with compilation parameter
* *
* @return bool true * @return string compiled code
*/ */
public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter) public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter)
{ {

View File

@@ -1,54 +0,0 @@
<?php
/*
* This file is part of Smarty.
*
* (c) 2015 Uwe Tews
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Smarty Internal Plugin Compile Block Parent Class
*
* @author Uwe Tews <uwe.tews@googlemail.com>
*/
class Smarty_Internal_Compile_Block_Child extends Smarty_Internal_CompileBase
{
/**
* Attribute definition: Overwrites base class.
*
* @var array
* @see Smarty_Internal_CompileBase
*/
public $option_flags = array();
/**
* Saved compiler object
*
* @var Smarty_Internal_TemplateCompilerBase
*/
public $compiler = null;
/**
* Compiles code for the {block_parent} tag
*
* @param array $args array with attributes from parser
* @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
* @param array $parameter array with compilation parameter
*
* @return bool true
*/
public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter)
{
if (!isset($compiler->_cache[ 'blockNesting' ])) {
$compiler->trigger_template_error(' tag {$smarty.block.child} used outside {block} tags ',
$compiler->parser->lex->taglineno);
}
$compiler->has_code = true;
$compiler->suppressNocacheProcessing = true;
$compiler->_cache[ 'blockParams' ][ $compiler->_cache[ 'blockNesting' ] ][ 'callsChild' ] = 'true';
$output = "<?php \n\$_smarty_tpl->inheritance->callChild(\$_smarty_tpl, \$this);\n?>\n";
return $output;
}
}

View File

@@ -1,73 +0,0 @@
<?php
/*
* This file is part of Smarty.
*
* (c) 2015 Uwe Tews
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Smarty Internal Plugin Compile Block Parent Class
*
* @author Uwe Tews <uwe.tews@googlemail.com>
*/
class Smarty_Internal_Compile_Block_Parent extends Smarty_Internal_Compile_Shared_Inheritance
{
/**
* Attribute definition: Overwrites base class.
*
* @var array
* @see Smarty_Internal_CompileBase
*/
public $optional_attributes = array('name');
/**
* Attribute definition: Overwrites base class.
*
* @var array
* @see Smarty_Internal_CompileBase
*/
public $shorttag_order = array('name');
/**
* Attribute definition: Overwrites base class.
*
* @var array
* @see Smarty_Internal_CompileBase
*/
public $option_flags = array();
/**
* Saved compiler object
*
* @var Smarty_Internal_TemplateCompilerBase
*/
public $compiler = null;
/**
* Compiles code for the {block_parent} tag
*
* @param array $args array with attributes from parser
* @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
* @param array $parameter array with compilation parameter
*
* @return bool true
*/
public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter)
{
// check and get attributes
$_attr = $this->getAttributes($compiler, $args);
if (!isset($compiler->_cache[ 'blockNesting' ])) {
$compiler->trigger_template_error(' tag {$smarty.block.parent} used outside {block} tags ',
$compiler->parser->lex->taglineno);
}
$compiler->suppressNocacheProcessing = true;
$compiler->has_code = true;
$output = "<?php \n\$_smarty_tpl->inheritance->callParent(\$_smarty_tpl, \$this" .
(isset($_attr[ 'name' ]) ? ", {$_attr[ 'name' ]}" : '') . ");\n?>\n";
return $output;
}
}

View File

@@ -51,6 +51,9 @@ class Smarty_Internal_Compile_Private_Special_Variable extends Smarty_Internal_C
return ''; return '';
case 'now': case 'now':
return 'time()'; return 'time()';
case 'block':
$tag = $compiler->getTagCompiler('block');
return $tag->compileSpecialVariable(array(), $compiler, $_index);
case 'cookies': case 'cookies':
if (isset($compiler->smarty->security_policy) && if (isset($compiler->smarty->security_policy) &&
!$compiler->smarty->security_policy->allow_super_globals !$compiler->smarty->security_policy->allow_super_globals

View File

@@ -16,22 +16,6 @@
*/ */
class Smarty_Internal_Compile_Shared_Inheritance extends Smarty_Internal_CompileBase class Smarty_Internal_Compile_Shared_Inheritance extends Smarty_Internal_CompileBase
{ {
/**
* Register post compile callback to compile inheritance initialization code
*
* @param \Smarty_Internal_TemplateCompilerBase $compiler
* @param bool|false $initChildSequence if true force child template
*/
public function registerInit(Smarty_Internal_TemplateCompilerBase $compiler, $initChildSequence = false)
{
if ($initChildSequence || !isset($compiler->_cache[ 'inheritanceInit' ])) {
$compiler->registerPostCompileCallback(array('Smarty_Internal_Compile_Shared_Inheritance', 'postCompile'),
array($initChildSequence), 'inheritanceInit', $initChildSequence);
$compiler->_cache[ 'inheritanceInit' ] = true;
}
}
/** /**
* Compile inheritance initialization code as prefix * Compile inheritance initialization code as prefix
* *
@@ -43,4 +27,22 @@ class Smarty_Internal_Compile_Shared_Inheritance extends Smarty_Internal_Compile
$compiler->prefixCompiledCode .= "<?php \$_smarty_tpl->_loadInheritance();\n\$_smarty_tpl->inheritance->init(\$_smarty_tpl, " . $compiler->prefixCompiledCode .= "<?php \$_smarty_tpl->_loadInheritance();\n\$_smarty_tpl->inheritance->init(\$_smarty_tpl, " .
var_export($initChildSequence, true) . ");\n?>\n"; var_export($initChildSequence, true) . ");\n?>\n";
} }
/**
* Register post compile callback to compile inheritance initialization code
*
* @param \Smarty_Internal_TemplateCompilerBase $compiler
* @param bool|false $initChildSequence if true force child template
*/
public function registerInit(Smarty_Internal_TemplateCompilerBase $compiler, $initChildSequence = false)
{
if ($initChildSequence || !isset($compiler->_cache['inheritanceInit'])) {
$compiler->registerPostCompileCallback(array('Smarty_Internal_Compile_Shared_Inheritance', 'postCompile'),
array($initChildSequence),
'inheritanceInit',
$initChildSequence);
$compiler->_cache['inheritanceInit'] = true;
}
}
} }

View File

@@ -111,9 +111,18 @@ class Smarty_Internal_Runtime_Inheritance
ob_end_clean(); ob_end_clean();
$this->state = 2; $this->state = 2;
} }
if (isset($template) && (($tpl->parent->_isTplObj() && $tpl->parent->source->type !== 'extends') || $tpl->smarty->extends_recursion)) { if (isset($template) && (($tpl->parent->_isTplObj() && $tpl->parent->source->type !== 'extends') ||
$tpl->_subTemplateRender($template, $tpl->cache_id, $tpl->compile_id, $tpl->caching ? 9999 : 0, $tpl->smarty->extends_recursion)) {
$tpl->cache_lifetime, array(), 2, false, $uid, $func); $tpl->_subTemplateRender($template,
$tpl->cache_id,
$tpl->compile_id,
$tpl->caching ? 9999 : 0,
$tpl->cache_lifetime,
array(),
2,
false,
$uid,
$func);
} }
} }
@@ -153,7 +162,8 @@ class Smarty_Internal_Runtime_Inheritance
* *
* @throws \SmartyException * @throws \SmartyException
*/ */
public function process(Smarty_Internal_Template $tpl, Smarty_Internal_Block $block, public function process(Smarty_Internal_Template $tpl,
Smarty_Internal_Block $block,
Smarty_Internal_Block $parent = null) Smarty_Internal_Block $parent = null)
{ {
if ($block->hide && !isset($block->child)) { if ($block->hide && !isset($block->child)) {
@@ -187,30 +197,47 @@ class Smarty_Internal_Runtime_Inheritance
} }
/** /**
* Render child on {$smarty.block.child} * Render child on $smarty.block.child
* *
* @param \Smarty_Internal_Template $tpl * @param \Smarty_Internal_Template $tpl
* @param \Smarty_Internal_Block $block * @param \Smarty_Internal_Block $block
* @param boolean $returnContent flag if content shall be returned
*
* @return null|string null or block content dependent on $returnContent
*/ */
public function callChild(Smarty_Internal_Template $tpl, Smarty_Internal_Block $block) public function callChild(Smarty_Internal_Template $tpl, Smarty_Internal_Block $block, $returnContent = false)
{ {
if ($returnContent) {
ob_start();
}
if (isset($block->child)) { if (isset($block->child)) {
$this->process($tpl, $block->child, $block); $this->process($tpl, $block->child, $block);
} }
if ($returnContent) {
return ob_get_clean();
}
return;
} }
/** /**
* Render parent on {$smarty.block.parent} or {block append/prepend} * * Render parent block on $smarty.block.parent or {block append/prepend} *
* *
* @param \Smarty_Internal_Template $tpl * @param \Smarty_Internal_Template $tpl
* @param \Smarty_Internal_Block $block * @param \Smarty_Internal_Block $block
* @param null|string $name
* @param boolean $returnContent flag if content shall be returned
* *
* @param null $name * @return null|string null or block content dependent on $returnContent
*
* @throws \SmartyException * @throws \SmartyException
*/ */
public function callParent(Smarty_Internal_Template $tpl, Smarty_Internal_Block $block, $name = null) public function callParent(Smarty_Internal_Template $tpl,
Smarty_Internal_Block $block,
$name = null,
$returnContent = false)
{ {
if ($returnContent) {
ob_start();
}
if (isset($name)) { if (isset($name)) {
$block = $block->parent; $block = $block->parent;
while (isset($block)) { while (isset($block)) {
@@ -223,11 +250,17 @@ class Smarty_Internal_Runtime_Inheritance
} else if (isset($block->parent)) { } else if (isset($block->parent)) {
$this->callBlock($block->parent, $tpl); $this->callBlock($block->parent, $tpl);
} else { } 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}'"); 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}'");
} }
if ($returnContent) {
return ob_get_clean();
}
return;
} }
/** /**
* redender block
*
* @param \Smarty_Internal_Block $block * @param \Smarty_Internal_Block $block
* @param \Smarty_Internal_Template $tpl * @param \Smarty_Internal_Template $tpl
*/ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -372,8 +372,6 @@ class Smarty_Internal_TestInstall
'smarty_internal_compile_append.php' => true, 'smarty_internal_compile_append.php' => true,
'smarty_internal_compile_assign.php' => true, 'smarty_internal_compile_assign.php' => true,
'smarty_internal_compile_block.php' => true, 'smarty_internal_compile_block.php' => true,
'smarty_internal_compile_block_child.php' => true,
'smarty_internal_compile_block_parent.php' => true,
'smarty_internal_compile_break.php' => true, 'smarty_internal_compile_break.php' => true,
'smarty_internal_compile_call.php' => true, 'smarty_internal_compile_call.php' => true,
'smarty_internal_compile_capture.php' => true, 'smarty_internal_compile_capture.php' => true,