mirror of
https://github.com/smarty-php/smarty.git
synced 2025-08-03 09:54:27 +02:00
Fixed scope in variable assignments in included and extended templates, fixed dependencies for testing freshness of caches. Added some unit tests and fixed a class reference to pass some more tests.
This commit is contained in:
@@ -65,7 +65,7 @@ class Assign extends Base
|
|||||||
if ($_attr[ 'noscope' ]) {
|
if ($_attr[ 'noscope' ]) {
|
||||||
$_scope = -1;
|
$_scope = -1;
|
||||||
} else {
|
} else {
|
||||||
$_scope = isset($_attr['scope']) ? $this->convertScope($_attr['scope']) : 0;
|
$_scope = isset($_attr['scope']) ? $this->convertScope($_attr['scope']) : null;
|
||||||
}
|
}
|
||||||
// optional parameter
|
// optional parameter
|
||||||
$_params = '';
|
$_params = '';
|
||||||
@@ -80,9 +80,9 @@ class Assign extends Base
|
|||||||
$output .= "settype(\$_tmp_array, 'array');\n";
|
$output .= "settype(\$_tmp_array, 'array');\n";
|
||||||
$output .= "}\n";
|
$output .= "}\n";
|
||||||
$output .= "\$_tmp_array{$parameter['smarty_internal_index']} = {$_attr['value']};\n";
|
$output .= "\$_tmp_array{$parameter['smarty_internal_index']} = {$_attr['value']};\n";
|
||||||
$output .= "\$_smarty_tpl->assign({$_var}, \$_tmp_array{$_params}, false, {$_scope});?>";
|
$output .= "\$_smarty_tpl->assign({$_var}, \$_tmp_array{$_params}, false, " . var_export($_scope, true) . ");?>";
|
||||||
} else {
|
} else {
|
||||||
$output = "<?php \$_smarty_tpl->assign({$_var}, {$_attr['value']}{$_params}, false, {$_scope});?>";
|
$output = "<?php \$_smarty_tpl->assign({$_var}, {$_attr['value']}{$_params}, false, " . var_export($_scope, true) . ");?>";
|
||||||
}
|
}
|
||||||
return $output;
|
return $output;
|
||||||
}
|
}
|
||||||
|
@@ -217,7 +217,9 @@ class IncludeTag extends Base {
|
|||||||
if (isset($_assign)) {
|
if (isset($_assign)) {
|
||||||
$_output .= "ob_start();\n";
|
$_output .= "ob_start();\n";
|
||||||
}
|
}
|
||||||
$_output .= "\$_smarty_tpl->_subTemplateRender({$fullResourceName}, {$_cache_id}, \$_smarty_tpl->compile_id, {$_caching}, {$_cache_lifetime}, {$_vars}, '{$compiler->getParentCompiler()->mergedSubTemplatesData[$uid][$t_hash]['uid']}', '{$compiler->getParentCompiler()->mergedSubTemplatesData[$uid][$t_hash]['func']}');\n";
|
$_output .= "\$_smarty_tpl->_subTemplateRender({$fullResourceName}, {$_cache_id}, \$_smarty_tpl->compile_id,
|
||||||
|
{$_caching}, {$_cache_lifetime}, {$_vars}, '{$compiler->getParentCompiler()->mergedSubTemplatesData[$uid][$t_hash]['uid']}',
|
||||||
|
'{$compiler->getParentCompiler()->mergedSubTemplatesData[$uid][$t_hash]['func']}', (int) {$_scope});\n";
|
||||||
if (isset($_assign)) {
|
if (isset($_assign)) {
|
||||||
$_output .= "\$_smarty_tpl->assign({$_assign}, ob_get_clean(), false, {$_scope});\n";
|
$_output .= "\$_smarty_tpl->assign({$_assign}, ob_get_clean(), false, {$_scope});\n";
|
||||||
}
|
}
|
||||||
@@ -232,7 +234,7 @@ class IncludeTag extends Base {
|
|||||||
if (isset($_assign)) {
|
if (isset($_assign)) {
|
||||||
$_output .= "ob_start();\n";
|
$_output .= "ob_start();\n";
|
||||||
}
|
}
|
||||||
$_output .= "\$_smarty_tpl->_subTemplateRender({$fullResourceName}, $_cache_id, \$_smarty_tpl->compile_id, $_caching, $_cache_lifetime, $_vars);\n";
|
$_output .= "\$_smarty_tpl->_subTemplateRender({$fullResourceName}, $_cache_id, \$_smarty_tpl->compile_id, $_caching, $_cache_lifetime, $_vars, null, null, (int) {$_scope});\n";
|
||||||
if (isset($_assign)) {
|
if (isset($_assign)) {
|
||||||
$_output .= "\$_smarty_tpl->assign({$_assign}, ob_get_clean(), false, {$_scope});\n";
|
$_output .= "\$_smarty_tpl->assign({$_assign}, ob_get_clean(), false, {$_scope});\n";
|
||||||
}
|
}
|
||||||
|
@@ -72,8 +72,10 @@ class CodeFrame
|
|||||||
$output .= ");\n";
|
$output .= ");\n";
|
||||||
}
|
}
|
||||||
if ($cache && $this->_template->getSmarty()->hasRuntime('TplFunction')) {
|
if ($cache && $this->_template->getSmarty()->hasRuntime('TplFunction')) {
|
||||||
$output .= "\$_smarty_tpl->getSmarty()->getRuntime('TplFunction')->registerTplFunctions(\$_smarty_tpl, " .
|
if ($tplfunctions = $this->_template->getSmarty()->getRuntime('TplFunction')->getTplFunction($this->_template)) {
|
||||||
var_export($this->_template->getSmarty()->getRuntime('TplFunction')->getTplFunction($this->_template), true) . ");\n";
|
$output .= "\$_smarty_tpl->getSmarty()->getRuntime('TplFunction')->registerTplFunctions(\$_smarty_tpl, " .
|
||||||
|
var_export($tplfunctions, true) . ");\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$output .= "?>";
|
$output .= "?>";
|
||||||
$output .= $content;
|
$output .= $content;
|
||||||
|
29
src/Data.php
29
src/Data.php
@@ -47,6 +47,12 @@ class Data
|
|||||||
*/
|
*/
|
||||||
public $config_vars = array();
|
public $config_vars = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default scope for new variables
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
private $defaultScope = self::SCOPE_LOCAL;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* create Smarty data object
|
* create Smarty data object
|
||||||
*
|
*
|
||||||
@@ -83,7 +89,7 @@ class Data
|
|||||||
* @return Data current Data (or Smarty or \Smarty\Template) instance for
|
* @return Data current Data (or Smarty or \Smarty\Template) instance for
|
||||||
* chaining
|
* chaining
|
||||||
*/
|
*/
|
||||||
public function assign($tpl_var, $value = null, $nocache = false, $scope = 0)
|
public function assign($tpl_var, $value = null, $nocache = false, $scope = null)
|
||||||
{
|
{
|
||||||
if (is_array($tpl_var)) {
|
if (is_array($tpl_var)) {
|
||||||
foreach ($tpl_var as $_key => $_val) {
|
foreach ($tpl_var as $_key => $_val) {
|
||||||
@@ -91,8 +97,7 @@ class Data
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
switch ($scope ?? $this->getDefaultScope()) {
|
||||||
switch ($scope) {
|
|
||||||
case self::SCOPE_GLOBAL:
|
case self::SCOPE_GLOBAL:
|
||||||
case self::SCOPE_SMARTY:
|
case self::SCOPE_SMARTY:
|
||||||
$this->getSmarty()->assign($tpl_var, $value);
|
$this->getSmarty()->assign($tpl_var, $value);
|
||||||
@@ -119,6 +124,7 @@ class Data
|
|||||||
$this->assign($tpl_var, $value);
|
$this->assign($tpl_var, $value);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case self::SCOPE_LOCAL:
|
||||||
default:
|
default:
|
||||||
$this->tpl_vars[ $tpl_var ] = new Variable($value, $nocache);
|
$this->tpl_vars[ $tpl_var ] = new Variable($value, $nocache);
|
||||||
}
|
}
|
||||||
@@ -439,4 +445,21 @@ class Data
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the default scope for new variables assigned in this template.
|
||||||
|
* @param int $scope
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function setDefaultScope(int $scope) {
|
||||||
|
$this->defaultScope = $scope;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the default scope for new variables assigned in this template.
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getDefaultScope(): int {
|
||||||
|
return $this->defaultScope;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -105,6 +105,7 @@ class Template extends TemplateBase {
|
|||||||
*/
|
*/
|
||||||
private $right_delimiter = null;
|
private $right_delimiter = null;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create template data object
|
* Create template data object
|
||||||
* Some of the global Smarty settings copied to template scope
|
* Some of the global Smarty settings copied to template scope
|
||||||
@@ -233,13 +234,13 @@ class Template extends TemplateBase {
|
|||||||
* @param mixed $cache_id cache id
|
* @param mixed $cache_id cache id
|
||||||
* @param mixed $compile_id compile id
|
* @param mixed $compile_id compile id
|
||||||
* @param integer $caching cache mode
|
* @param integer $caching cache mode
|
||||||
* @param integer $cache_lifetime life time of cache data
|
* @param integer $cache_lifetime lifetime of cache data
|
||||||
* @param array $extra_vars passed parameter template variables
|
* @param array $extra_vars passed parameter template variables
|
||||||
* @param string $uid file dependency uid
|
* @param null $uid file dependency uid
|
||||||
* @param string $content_func function name
|
* @param null $content_func function name
|
||||||
|
* @param int|null $scope
|
||||||
*
|
*
|
||||||
* @throws \Exception
|
* @throws Exception
|
||||||
* @throws \Smarty\Exception
|
|
||||||
*/
|
*/
|
||||||
public function _subTemplateRender(
|
public function _subTemplateRender(
|
||||||
$template_name,
|
$template_name,
|
||||||
@@ -249,12 +250,18 @@ class Template extends TemplateBase {
|
|||||||
$cache_lifetime,
|
$cache_lifetime,
|
||||||
array $extra_vars,
|
array $extra_vars,
|
||||||
$uid = null,
|
$uid = null,
|
||||||
$content_func = null
|
$content_func = null,
|
||||||
|
int $scope = null
|
||||||
) {
|
) {
|
||||||
|
|
||||||
$baseFilePath = $this->source && $this->getSource()->filepath ? dirname($this->getSource()->filepath) : null;
|
$baseFilePath = $this->source && $this->getSource()->filepath ? dirname($this->getSource()->filepath) : null;
|
||||||
|
|
||||||
$tpl = $this->getSmarty()->createTemplate($template_name, $cache_id, $compile_id, $this, $caching, $cache_lifetime, $baseFilePath);
|
$tpl = $this->getSmarty()->createTemplate($template_name, $cache_id, $compile_id, $this, $caching, $cache_lifetime, $baseFilePath);
|
||||||
|
$tpl->setCached($this->getCached()); // re-use the same Cache object across subtemplates to gather hashes and file dependencies.
|
||||||
|
|
||||||
|
if ($scope) {
|
||||||
|
$tpl->setDefaultScope($scope);
|
||||||
|
}
|
||||||
|
|
||||||
// copy variables
|
// copy variables
|
||||||
$tpl->tpl_vars = $this->tpl_vars;
|
$tpl->tpl_vars = $this->tpl_vars;
|
||||||
@@ -313,9 +320,6 @@ class Template extends TemplateBase {
|
|||||||
// $tpl->render();
|
// $tpl->render();
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Merge the hashes... @TODO refactor this?
|
|
||||||
$this->getCached()->hashes = array_merge($this->getCached()->hashes, $tpl->getCached()->hashes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -327,7 +331,7 @@ class Template extends TemplateBase {
|
|||||||
return isset($this->parent) && $this->parent instanceof Template;
|
return isset($this->parent) && $this->parent instanceof Template;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function assign($tpl_var, $value = null, $nocache = false, $scope = 0) {
|
public function assign($tpl_var, $value = null, $nocache = false, $scope = null) {
|
||||||
return parent::assign($tpl_var, $value, $nocache || $this->isRenderingCache, $scope);
|
return parent::assign($tpl_var, $value, $nocache || $this->isRenderingCache, $scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -810,4 +814,16 @@ class Template extends TemplateBase {
|
|||||||
public function setSource($source): void {
|
public function setSource($source): void {
|
||||||
$this->source = $source;
|
$this->source = $source;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the Cached object, so subtemplates can share one Cached object to gather meta-data.
|
||||||
|
*
|
||||||
|
* @param Cached $cached
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function setCached(Cached $cached) {
|
||||||
|
$this->cached = $cached;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -89,6 +89,23 @@ class ExtendsResourceTest extends PHPUnit_Smarty
|
|||||||
$this->assertStringContainsString("test:{$testNumber} compiled:{$compileTestNumber} rendered:{$renderTestNumber}", $result, $testName . ' - fetch() failure');
|
$this->assertStringContainsString("test:{$testNumber} compiled:{$compileTestNumber} rendered:{$renderTestNumber}", $result, $testName . ' - fetch() failure');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider data
|
||||||
|
*/
|
||||||
|
public function testCompileBlockIncreaseInChild_050($caching, $merge, $testNumber, $compileTestNumber, $renderTestNumber, $testName)
|
||||||
|
{
|
||||||
|
$this->smarty->registerFilter('pre', array($this, 'compiledPrefilter'));
|
||||||
|
$this->smarty->assign('test', $testNumber);
|
||||||
|
$this->smarty->caching = $caching;
|
||||||
|
$this->smarty->merge_compiled_includes = $merge;
|
||||||
|
if ($merge) {
|
||||||
|
$this->smarty->compile_id = 1;
|
||||||
|
}
|
||||||
|
$result = $this->smarty->fetch('extends:050_parent.tpl|050_child.tpl|050_grandchild.tpl');
|
||||||
|
$this->assertStringContainsString("var-bar-var", $result, $testName . ' - content');
|
||||||
|
$this->assertStringContainsString("test:{$testNumber} compiled:{$compileTestNumber} rendered:{$renderTestNumber}", $result, $testName . ' - fetch() failure');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* test grandchild/child/parent dependency test1
|
* test grandchild/child/parent dependency test1
|
||||||
*/
|
*/
|
||||||
|
@@ -0,0 +1 @@
|
|||||||
|
{$notfoo="notbar"}
|
@@ -0,0 +1 @@
|
|||||||
|
{$foo="bar"}
|
@@ -0,0 +1,2 @@
|
|||||||
|
test:{$test nocache} compiled:# rendered:{$test}
|
||||||
|
{block name='test'}var-{$foo}-var{/block}
|
@@ -36,7 +36,7 @@ function smarty_function_checkvar($params, \Smarty\Template $template)
|
|||||||
$i ++;
|
$i ++;
|
||||||
}
|
}
|
||||||
$ptr = $ptr->parent;
|
$ptr = $ptr->parent;
|
||||||
} elseif (in_array('data', $types) && !($ptr instanceof Template || $ptr instanceof Smarty)) {
|
} elseif (in_array('data', $types) && !($ptr instanceof Template || $ptr instanceof \Smarty\Smarty)) {
|
||||||
$output .= "#data:\${$var} =";
|
$output .= "#data:\${$var} =";
|
||||||
$output .= $ptr->hasVariable($var) ? preg_replace('/\s/', '', var_export($ptr->getValue($var), true)) : '>unassigned<';
|
$output .= $ptr->hasVariable($var) ? preg_replace('/\s/', '', var_export($ptr->getValue($var), true)) : '>unassigned<';
|
||||||
$ptr = $ptr->parent;
|
$ptr = $ptr->parent;
|
||||||
|
Reference in New Issue
Block a user