- new tag {make_nocache} read NEW_FEATURES.txt https://github.com/smarty-php/smarty/issues/110

This commit is contained in:
uwetews
2016-02-14 02:54:38 +01:00
parent 3756588858
commit 0f7f0d87b6
16 changed files with 1038 additions and 859 deletions

View File

@@ -4,6 +4,27 @@ This file contains a brief description of new features which have been added to
Smarty 3.1.30 Smarty 3.1.30
New tag {make_nocache}
======================
Syntax: {make_nocache $foo}
This tag makes a variable which does exists normally only while rendering the compiled template
available in the cached template for use in not cached expressions.
Expample:
{foreach from=$list item=item}
<li>{$item.name} {make_nocache $item}{if $current==$item.id} ACTIVE{/if}</li>
{/foreach}
The {foreach} loop is rendered while processing the compiled template, but $current is a nocache
variable. Normally the {if $current==$item.id} would fail as the $item variable is unkown in the
cached template. {make_nocache $item} does make the current $item value known in thee cached template.
{make_nocache} is ignored when caching is disabled or the variable does exists as nocache variable.
NOTE: if the variable value does contain objects these must have the __set_state method implemented.
Scope Attributes Scope Attributes
================ ================
The scope handling has been updated to cover all cases of variable assignments in templates. The scope handling has been updated to cover all cases of variable assignments in templates.

View File

@@ -1,4 +1,7 @@
 ===== 3.1.30-dev ===== (xx.xx.xx)  ===== 3.1.30-dev ===== (xx.xx.xx)
14.02.2016
- new tag {make_nocache} read NEW_FEATURES.txt https://github.com/smarty-php/smarty/issues/110
11.02.2016 11.02.2016
- improvement added KnockoutJS comments to trimwhitespace outputfilter https://github.com/smarty-php/smarty/issues/82 - improvement added KnockoutJS comments to trimwhitespace outputfilter https://github.com/smarty-php/smarty/issues/82
https://github.com/smarty-php/smarty/pull/181 https://github.com/smarty-php/smarty/pull/181

View File

@@ -316,6 +316,7 @@ class Smarty_Internal_Templatelexer
block = ~block~ block = ~block~
if = ~(if|elseif|else if|while)\s+~ if = ~(if|elseif|else if|while)\s+~
for = ~for\s+~ for = ~for\s+~
makenocache = ~make_nocache\s+~
foreach = ~foreach(?![^\s])~ foreach = ~foreach(?![^\s])~
setfilter = ~setfilter\s+~ setfilter = ~setfilter\s+~
instanceof = ~\s+instanceof\s+~ instanceof = ~\s+instanceof\s+~
@@ -398,6 +399,11 @@ class Smarty_Internal_Templatelexer
$this->yybegin(self::TAGBODY); $this->yybegin(self::TAGBODY);
$this->taglineno = $this->line; $this->taglineno = $this->line;
} }
ldel makenocache {
$this->token = Smarty_Internal_Templateparser::TP_LDELMAKENOCACHE;
$this->yybegin(self::TAGBODY);
$this->taglineno = $this->line;
}
ldel id nocacherdel { ldel id nocacherdel {
$this->yypopstate(); $this->yypopstate();
$this->token = Smarty_Internal_Templateparser::TP_SIMPLETAG; $this->token = Smarty_Internal_Templateparser::TP_SIMPLETAG;

View File

@@ -453,6 +453,11 @@ tag(res) ::= LDEL ID(i) PTR ID(me) modifierlist(l) attributes(a). {
res .= $this->compiler->compileTag('private_modifier',array(),array('modifierlist'=>l,'value'=>'ob_get_clean()')).';?>'; res .= $this->compiler->compileTag('private_modifier',array(),array('modifierlist'=>l,'value'=>'ob_get_clean()')).';?>';
} }
// nocache tag
tag(res) ::= LDELMAKENOCACHE DOLLARID(i). {
res = $this->compiler->compileTag('make_nocache',array(array('var'=>'\''.substr(i,1).'\'')));
}
// {if}, {elseif} and {while} tag // {if}, {elseif} and {while} tag
tag(res) ::= LDELIF(i) expr(ie). { tag(res) ::= LDELIF(i) expr(ie). {
$tag = trim(substr(i,$this->lex->ldel_length)); $tag = trim(substr(i,$this->lex->ldel_length));

View File

@@ -121,7 +121,7 @@ class Smarty extends Smarty_Internal_TemplateBase
/** /**
* smarty version * smarty version
*/ */
const SMARTY_VERSION = '3.1.30-dev/38'; const SMARTY_VERSION = '3.1.30-dev/39';
/** /**
* define variable scopes * define variable scopes

View File

@@ -55,7 +55,7 @@ class Smarty_Internal_Compile_For extends Smarty_Internal_CompileBase
$var = $_statement[ 'var' ]; $var = $_statement[ 'var' ];
$index = ''; $index = '';
} }
$output .= "\$_smarty_tpl->tpl_vars[$var] = new Smarty_Variable;\n"; $output .= "\$_smarty_tpl->tpl_vars[$var] = new Smarty_Variable(null, \$_smarty_tpl->isRenderingCache);\n";
$output .= "\$_smarty_tpl->tpl_vars[$var]->value{$index} = {$_statement['value']};\n"; $output .= "\$_smarty_tpl->tpl_vars[$var]->value{$index} = {$_statement['value']};\n";
} }
if (is_array($_attr[ 'var' ])) { if (is_array($_attr[ 'var' ])) {
@@ -75,7 +75,7 @@ class Smarty_Internal_Compile_For extends Smarty_Internal_CompileBase
$var = $_statement[ 'var' ]; $var = $_statement[ 'var' ];
$index = ''; $index = '';
} }
$output .= "\$_smarty_tpl->tpl_vars[$var] = new Smarty_Variable;"; $output .= "\$_smarty_tpl->tpl_vars[$var] = new Smarty_Variable(null, \$_smarty_tpl->isRenderingCache);";
if (isset($_attr[ 'step' ])) { if (isset($_attr[ 'step' ])) {
$output .= "\$_smarty_tpl->tpl_vars[$var]->step = $_attr[step];"; $output .= "\$_smarty_tpl->tpl_vars[$var]->step = $_attr[step];";
} else { } else {

View File

@@ -148,10 +148,10 @@ class Smarty_Internal_Compile_Functionclose extends Smarty_Internal_CompileBase
$output .= "ob_start();\n"; $output .= "ob_start();\n";
$output .= "\$_smarty_tpl->compiled->has_nocache_code = true;\n"; $output .= "\$_smarty_tpl->compiled->has_nocache_code = true;\n";
$output .= $_paramsCode; $output .= $_paramsCode;
$output .= "foreach (\$params as \$key => \$value) {\n\$_smarty_tpl->tpl_vars[\$key] = new Smarty_Variable(\$value);\n}"; $output .= "foreach (\$params as \$key => \$value) {\n\$_smarty_tpl->tpl_vars[\$key] = new Smarty_Variable(\$value, \$_smarty_tpl->isRenderingCache);\n}";
$output .= "\$params = var_export(\$params, true);\n"; $output .= "\$params = var_export(\$params, true);\n";
$output .= "echo \"/*%%SmartyNocache:{$compiler->template->compiled->nocache_hash}%%*/<?php "; $output .= "echo \"/*%%SmartyNocache:{$compiler->template->compiled->nocache_hash}%%*/<?php ";
$output .= "\\\$_smarty_tpl->smarty->ext->_tplFunction->saveTemplateVariables(\\\$_smarty_tpl, '{$_name}');\nforeach (\$params as \\\$key => \\\$value) {\n\\\$_smarty_tpl->tpl_vars[\\\$key] = new Smarty_Variable(\\\$value);\n}\n?>"; $output .= "\\\$_smarty_tpl->smarty->ext->_tplFunction->saveTemplateVariables(\\\$_smarty_tpl, '{$_name}');\nforeach (\$params as \\\$key => \\\$value) {\n\\\$_smarty_tpl->tpl_vars[\\\$key] = new Smarty_Variable(\\\$value, \\\$_smarty_tpl->isRenderingCache);\n}\n?>";
$output .= "/*/%%SmartyNocache:{$compiler->template->compiled->nocache_hash}%%*/\n\";?>"; $output .= "/*/%%SmartyNocache:{$compiler->template->compiled->nocache_hash}%%*/\n\";?>";
$compiler->parser->current_buffer->append_subtree($compiler->parser, $compiler->parser->current_buffer->append_subtree($compiler->parser,
new Smarty_Internal_ParseTree_Tag($compiler->parser, new Smarty_Internal_ParseTree_Tag($compiler->parser,
@@ -179,7 +179,7 @@ class Smarty_Internal_Compile_Functionclose extends Smarty_Internal_CompileBase
$output .= "if (!function_exists('{$_funcName}')) {\n"; $output .= "if (!function_exists('{$_funcName}')) {\n";
$output .= "function {$_funcName}(\$_smarty_tpl,\$params) {\n"; $output .= "function {$_funcName}(\$_smarty_tpl,\$params) {\n";
$output .= $_paramsCode; $output .= $_paramsCode;
$output .= "foreach (\$params as \$key => \$value) {\n\$_smarty_tpl->tpl_vars[\$key] = new Smarty_Variable(\$value);\n}?>"; $output .= "foreach (\$params as \$key => \$value) {\n\$_smarty_tpl->tpl_vars[\$key] = new Smarty_Variable(\$value, \$_smarty_tpl->isRenderingCache);\n}?>";
$compiler->parser->current_buffer->append_subtree($compiler->parser, $compiler->parser->current_buffer->append_subtree($compiler->parser,
new Smarty_Internal_ParseTree_Tag($compiler->parser, new Smarty_Internal_ParseTree_Tag($compiler->parser,
$output)); $output));

View File

@@ -0,0 +1,64 @@
<?php
/**
* Smarty Internal Plugin Compile Make_Nocache
* Compiles the {make_nocache} tag
*
* @package Smarty
* @subpackage Compiler
* @author Uwe Tews
*/
/**
* Smarty Internal Plugin Compile Make_Nocache Class
*
* @package Smarty
* @subpackage Compiler
*/
class Smarty_Internal_Compile_Make_Nocache extends Smarty_Internal_CompileBase
{
/**
* Attribute definition: Overwrites base class.
*
* @var array
* @see Smarty_Internal_CompileBase
*/
public $option_flags = array();
/**
* Array of names of required attribute required by tag
*
* @var array
*/
public $required_attributes = array('var');
/**
* Shorttag attribute order defined by its names
*
* @var array
*/
public $shorttag_order = array('var');
/**
* Compiles code for the {make_nocache} 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 compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter)
{
// check and get attributes
$_attr = $this->getAttributes($compiler, $args);
if ($compiler->template->caching) {
$output = "<?php \$_smarty_tpl->smarty->ext->_make_nocache->save(\$_smarty_tpl, {$_attr[ 'var' ]});\n?>\n";
$compiler->has_code = true;
$compiler->suppressNocacheProcessing = true;
return $output;
} else {
return true;
}
}
}

View File

@@ -45,13 +45,13 @@ class Smarty_Internal_Runtime_Foreach
if (isset($tpl->tpl_vars[ $key ])) { if (isset($tpl->tpl_vars[ $key ])) {
$saveVars[ $key ] = $tpl->tpl_vars[ $key ]; $saveVars[ $key ] = $tpl->tpl_vars[ $key ];
} }
$tpl->tpl_vars[ $key ] = new Smarty_Variable(); $tpl->tpl_vars[ $key ] = new Smarty_Variable(null, $tpl->isRenderingCache);
} }
if (!is_array($from) && !is_object($from)) { if (!is_array($from) && !is_object($from)) {
settype($from, 'array'); settype($from, 'array');
} }
$total = $needTotal ? $this->count($from) : 1; $total = $needTotal ? $this->count($from) : 1;
$tpl->tpl_vars[ $item ] = new Smarty_Variable(); $tpl->tpl_vars[ $item ] = new Smarty_Variable(null, $tpl->isRenderingCache);
if ($needTotal) { if ($needTotal) {
$tpl->tpl_vars[ $item ]->total = $total; $tpl->tpl_vars[ $item ]->total = $total;
} }

View File

@@ -0,0 +1,56 @@
<?php
/**
* {make_nocache} Runtime Methods save(), store()
*
* @package Smarty
* @subpackage PluginsInternal
* @author Uwe Tews
*
*/
class Smarty_Internal_Runtime_Make_Nocache
{
/**
* Save current variable value while rendering compiled template and inject nocache code to
* assign variable value in cahed template
*
* @param \Smarty_Internal_Template $tpl
* @param string $var variable name
*
* @throws \SmartyException
*/
public function save(Smarty_Internal_Template $tpl, $var)
{
if (isset($tpl->tpl_vars[ $var ])) {
$export = preg_replace('/^Smarty_Variable::__set_state[(]|\s|[)]$/', '',
var_export($tpl->tpl_vars[ $var ], true));
if (preg_match('/(\w+)::__set_state/', $export, $match)) {
throw new SmartyException("{make_nocache \${$var}} in template '{$tpl->source->name}': variable does contain object '{$match[1]}' not implementing method '__set_state'");
}
echo "/*%%SmartyNocache:{$tpl->compiled->nocache_hash}%%*/<?php " .
addcslashes("\$_smarty_tpl->smarty->ext->_make_nocache->store(\$_smarty_tpl, '{$var}', " . $export,
'\\') . ");?>\n/*/%%SmartyNocache:{$tpl->compiled->nocache_hash}%%*/";
}
}
/**
* Store variable value saved while rendering compiled template in cached template context
*
* @param \Smarty_Internal_Template $tpl
* @param string $var variable name
* @param array $properties
*/
public function store(Smarty_Internal_Template $tpl, $var, $properties)
{
// do not overwrite existing nocache variables
if (!isset($tpl->tpl_vars[ $var ]) || !$tpl->tpl_vars[ $var ]->nocache) {
$newVar = new Smarty_Variable();
unset($properties[ 'nocache' ]);
foreach ($properties as $k => $v) {
$newVar->$k = $v;
}
$tpl->tpl_vars[ $var ] = $newVar;
}
}
}

View File

@@ -81,6 +81,13 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
*/ */
public $scope = 0; public $scope = 0;
/**
* Flag which is set while rending a cache file
*
* @var bool
*/
public $isRenderingCache = false;
/** /**
* 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
@@ -311,7 +318,7 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
if (!empty($data)) { if (!empty($data)) {
// set up variable values // set up variable values
foreach ($data as $_key => $_val) { foreach ($data as $_key => $_val) {
$tpl->tpl_vars[ $_key ] = new Smarty_Variable($_val); $tpl->tpl_vars[ $_key ] = new Smarty_Variable($_val, $this->isRenderingCache);
} }
} }
if ($tpl->caching == 9999 && $tpl->compiled->has_nocache_code) { if ($tpl->caching == 9999 && $tpl->compiled->has_nocache_code) {
@@ -334,7 +341,6 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
$tpl->render(); $tpl->render();
} }
} }
$i = 0;
} }
/** /**
@@ -376,11 +382,11 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
if (isset($this->tpl_vars[ $varName ])) { if (isset($this->tpl_vars[ $varName ])) {
$this->tpl_vars[ $varName ] = clone $this->tpl_vars[ $varName ]; $this->tpl_vars[ $varName ] = clone $this->tpl_vars[ $varName ];
$this->tpl_vars[ $varName ]->value = $value; $this->tpl_vars[ $varName ]->value = $value;
if ($nocache) { if ($nocache || $this->isRenderingCache) {
$this->tpl_vars[ $varName ]->nocache = $nocache; $this->tpl_vars[ $varName ]->nocache = true;
} }
} else { } else {
$this->tpl_vars[ $varName ] = new Smarty_Variable($value, $nocache); $this->tpl_vars[ $varName ] = new Smarty_Variable($value, $nocache || $this->isRenderingCache);
} }
if (isset($scope) || isset($this->scope)) { if (isset($scope) || isset($this->scope)) {
$this->smarty->ext->_updateScope->_updateScope($this, $varName, $scope); $this->smarty->ext->_updateScope->_updateScope($this, $varName, $scope);

View File

@@ -816,7 +816,8 @@ abstract class Smarty_Internal_TemplateCompilerBase
'#(:SMARTY@!@|>)\s+(?=@!@SMARTY:|<)#s' => '\1\2', '#(:SMARTY@!@|>)\s+(?=@!@SMARTY:|<)#s' => '\1\2',
// remove spaces between attributes (but not in attribute values!) // remove spaces between attributes (but not in attribute values!)
'#(([a-z0-9]\s*=\s*("[^"]*?")|(\'[^\']*?\'))|<[a-z0-9_]+)\s+([a-z/>])#is' => '\1 \5', '#(([a-z0-9]\s*=\s*("[^"]*?")|(\'[^\']*?\'))|<[a-z0-9_]+)\s+([a-z/>])#is' => '\1 \5',
'#^\s+<#Ss' => $this->has_output ? ' <' : '<', '#>[\040\011]+$#Ss' => '> ', '#>[\040\011]*[\n]\s*$#Ss' => '>', $this->stripRegEx => '',); '#^\s+<#Ss' => $this->has_output ? ' <' : '<', '#>[\040\011]+$#Ss' => '> ',
'#>[\040\011]*[\n]\s*$#Ss' => '>', $this->stripRegEx => '',);
$text = preg_replace(array_keys($expressions), array_values($expressions), $text); $text = preg_replace(array_keys($expressions), array_values($expressions), $text);
$_offset = 0; $_offset = 0;

View File

@@ -423,10 +423,10 @@ class Smarty_Internal_Templatelexer
$this->yy_global_pattern2 = $this->yy_global_pattern2 =
"/\G(" . $this->ldel . "\\s*(if|elseif|else if|while)\\s+)|\G(" . $this->ldel . "\\s*for\\s+)|\G(" . "/\G(" . $this->ldel . "\\s*(if|elseif|else if|while)\\s+)|\G(" . $this->ldel . "\\s*for\\s+)|\G(" .
$this->ldel . "\\s*foreach(?![^\s]))|\G(" . $this->ldel . "\\s*setfilter\\s+)|\G(" . $this->ldel . $this->ldel . "\\s*foreach(?![^\s]))|\G(" . $this->ldel . "\\s*setfilter\\s+)|\G(" . $this->ldel .
"\\s*[0-9]*[a-zA-Z_]\\w*(\\s+nocache)?\\s*" . $this->rdel . ")|\G(" . $this->ldel . "\\s*make_nocache\\s+)|\G(" . $this->ldel . "\\s*[0-9]*[a-zA-Z_]\\w*(\\s+nocache)?\\s*" . $this->rdel .
"\\s*[\/](?:(?!block)[0-9]*[a-zA-Z_]\\w*)\\s*" . $this->rdel . ")|\G(" . $this->ldel . ")|\G(" . $this->ldel . "\\s*[\/](?:(?!block)[0-9]*[a-zA-Z_]\\w*)\\s*" . $this->rdel . ")|\G(" .
"\\s*[$][0-9]*[a-zA-Z_]\\w*(\\s+nocache)?\\s*" . $this->rdel . ")|\G(" . $this->ldel . "\\s*[\/])|\G(" . $this->ldel . "\\s*[$][0-9]*[a-zA-Z_]\\w*(\\s+nocache)?\\s*" . $this->rdel . ")|\G(" . $this->ldel .
$this->ldel . "\\s*)/isS"; "\\s*[\/])|\G(" . $this->ldel . "\\s*)/isS";
} }
if ($this->counter >= strlen($this->data)) { if ($this->counter >= strlen($this->data)) {
return false; // end of input return false; // end of input
@@ -509,6 +509,14 @@ class Smarty_Internal_Templatelexer
} }
function yy_r2_6() function yy_r2_6()
{
$this->token = Smarty_Internal_Templateparser::TP_LDELMAKENOCACHE;
$this->yybegin(self::TAGBODY);
$this->taglineno = $this->line;
}
function yy_r2_7()
{ {
$this->yypopstate(); $this->yypopstate();
@@ -516,7 +524,7 @@ class Smarty_Internal_Templatelexer
$this->taglineno = $this->line; $this->taglineno = $this->line;
} }
function yy_r2_8() function yy_r2_9()
{ {
$this->yypopstate(); $this->yypopstate();
@@ -524,7 +532,7 @@ class Smarty_Internal_Templatelexer
$this->taglineno = $this->line; $this->taglineno = $this->line;
} }
function yy_r2_9() function yy_r2_10()
{ {
if ($this->_yy_stack[ count($this->_yy_stack) - 1 ] == self::TEXT) { if ($this->_yy_stack[ count($this->_yy_stack) - 1 ] == self::TEXT) {
@@ -539,7 +547,7 @@ class Smarty_Internal_Templatelexer
} }
} }
function yy_r2_11() function yy_r2_12()
{ {
$this->token = Smarty_Internal_Templateparser::TP_LDELSLASH; $this->token = Smarty_Internal_Templateparser::TP_LDELSLASH;
@@ -547,7 +555,7 @@ class Smarty_Internal_Templatelexer
$this->taglineno = $this->line; $this->taglineno = $this->line;
} }
function yy_r2_12() function yy_r2_13()
{ {
$this->token = Smarty_Internal_Templateparser::TP_LDEL; $this->token = Smarty_Internal_Templateparser::TP_LDEL;

File diff suppressed because it is too large Load Diff

View File

@@ -384,6 +384,7 @@ class Smarty_Internal_TestInstall
'smarty_internal_compile_include_php.php' => true, 'smarty_internal_compile_include_php.php' => true,
'smarty_internal_compile_insert.php' => true, 'smarty_internal_compile_insert.php' => true,
'smarty_internal_compile_ldelim.php' => true, 'smarty_internal_compile_ldelim.php' => true,
'smarty_internal_compile_make_nocache.php' => true,
'smarty_internal_compile_nocache.php' => true, 'smarty_internal_compile_nocache.php' => true,
'smarty_internal_compile_private_block_plugin.php' => true, 'smarty_internal_compile_private_block_plugin.php' => true,
'smarty_internal_compile_private_foreachsection.php' => true, 'smarty_internal_compile_private_foreachsection.php' => true,
@@ -474,6 +475,7 @@ class Smarty_Internal_TestInstall
'smarty_internal_runtime_foreach.php' => true, 'smarty_internal_runtime_foreach.php' => true,
'smarty_internal_runtime_getincludepath.php' => true, 'smarty_internal_runtime_getincludepath.php' => true,
'smarty_internal_runtime_inheritance.php' => true, 'smarty_internal_runtime_inheritance.php' => true,
'smarty_internal_runtime_make_nocache.php' => true,
'smarty_internal_runtime_tplfunction.php' => true, 'smarty_internal_runtime_tplfunction.php' => true,
'smarty_internal_runtime_updatecache.php' => true, 'smarty_internal_runtime_updatecache.php' => true,
'smarty_internal_runtime_updatescope.php' => true, 'smarty_internal_runtime_updatescope.php' => true,

View File

@@ -104,6 +104,7 @@ abstract class Smarty_Template_Resource_Base
*/ */
public function getRenderedTemplateCode(Smarty_Internal_Template $_template, $unifunc = null) public function getRenderedTemplateCode(Smarty_Internal_Template $_template, $unifunc = null)
{ {
$_template->isRenderingCache = $this instanceof Smarty_Template_Cached;
$unifunc = isset($unifunc) ? $unifunc : $this->unifunc; $unifunc = isset($unifunc) ? $unifunc : $this->unifunc;
$level = ob_get_level(); $level = ob_get_level();
try { try {
@@ -128,9 +129,11 @@ abstract class Smarty_Template_Resource_Base
if (isset($_template->smarty->security_policy)) { if (isset($_template->smarty->security_policy)) {
$_template->smarty->security_policy->exitTemplate(); $_template->smarty->security_policy->exitTemplate();
} }
$_template->isRenderingCache = false;
return null; return null;
} }
catch (Exception $e) { catch (Exception $e) {
$_template->isRenderingCache = false;
while (ob_get_level() > $level) { while (ob_get_level() > $level) {
ob_end_clean(); ob_end_clean();
} }