Skip to content

Commit

Permalink
- bugfix plugins may not be loaded if {function} or {block} tags are …
Browse files Browse the repository at this point in the history
…executed in nocache mode

   #371
  • Loading branch information
Uwe Tews committed Mar 28, 2018
1 parent cf22e98 commit 336c07c
Show file tree
Hide file tree
Showing 11 changed files with 175 additions and 111 deletions.
4 changes: 4 additions & 0 deletions change_log.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
===== 3.1.32 - dev ===
26.03.2018
- bugfix plugins may not be loaded if {function} or {block} tags are executed in nocache mode
https://github.com/smarty-php/smarty/issues/371

26.03.2018
- new feature {parent} = {$smarty.block.parent} {child} = {$smarty.block.child}

Expand Down
2 changes: 1 addition & 1 deletion libs/Smarty.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ class Smarty extends Smarty_Internal_TemplateBase
/**
* smarty version
*/
const SMARTY_VERSION = '3.1.32-dev-44';
const SMARTY_VERSION = '3.1.32-dev-45';
/**
* define variable scopes
*/
Expand Down
14 changes: 3 additions & 11 deletions libs/sysplugins/smarty_internal_compile_block.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $
array($_attr, $compiler->nocache, $compiler->parser->current_buffer,
$compiler->template->compiled->has_nocache_code,
$compiler->template->caching));
$compiler->saveRequiredPlugins(true);
$compiler->nocache = $compiler->nocache | $compiler->tag_nocache;
$compiler->parser->current_buffer = new Smarty_Internal_ParseTree_Template();
$compiler->template->compiled->has_nocache_code = false;
Expand Down Expand Up @@ -126,7 +127,8 @@ public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $
$output .= "public \${$property} = " . var_export($value,true) .";\n";
}
$output .= "public function callBlock(Smarty_Internal_Template \$_smarty_tpl) {\n";
//$output .= "/*/%%SmartyNocache:{$compiler->template->compiled->nocache_hash}%%*/\n";
$output .= $compiler->compileRequiredPlugins();
$compiler->restoreRequiredPlugins();
if ($compiler->template->compiled->has_nocache_code) {
$output .= "\$_smarty_tpl->cached->hashes['{$compiler->template->compiled->nocache_hash}'] = true;\n";
}
Expand All @@ -151,16 +153,6 @@ public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $
$output));
$compiler->blockOrFunctionCode .= $compiler->parser->current_buffer->to_smarty_php($compiler->parser);
$compiler->parser->current_buffer = new Smarty_Internal_ParseTree_Template();
// nocache plugins must be copied
if (!empty($compiler->template->compiled->required_plugins[ 'nocache' ])) {
foreach ($compiler->template->compiled->required_plugins[ 'nocache' ] as $plugin => $tmp) {
foreach ($tmp as $type => $data) {
$compiler->parent_compiler->template->compiled->required_plugins[ 'compiled' ][ $plugin ][ $type ] =
$data;
}
}
}

// restore old status
$compiler->template->compiled->has_nocache_code = $_has_nocache_code;
$compiler->tag_nocache = $compiler->nocache;
Expand Down
23 changes: 9 additions & 14 deletions libs/sysplugins/smarty_internal_compile_function.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler)
// Init temporary context
$compiler->parser->current_buffer = new Smarty_Internal_ParseTree_Template();
$compiler->template->compiled->has_nocache_code = false;
$compiler->saveRequiredPlugins(true);
return true;
}
}
Expand Down Expand Up @@ -134,13 +135,14 @@ public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler)
$output .= "if (!function_exists('{$_funcNameCaching}')) {\n";
$output .= "function {$_funcNameCaching} (Smarty_Internal_Template \$_smarty_tpl,\$params) {\n";
$output .= "ob_start();\n";
$output .= $compiler->compileRequiredPlugins();
$output .= "\$_smarty_tpl->compiled->has_nocache_code = true;\n";
$output .= $_paramsCode;
$output .= "foreach (\$params as \$key => \$value) {\n\$_smarty_tpl->tpl_vars[\$key] = new Smarty_Variable(\$value, \$_smarty_tpl->isRenderingCache);\n}";
$output .= "foreach (\$params as \$key => \$value) {\n\$_smarty_tpl->tpl_vars[\$key] = new Smarty_Variable(\$value, \$_smarty_tpl->isRenderingCache);\n}\n";
$output .= "\$params = var_export(\$params, true);\n";
$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, \\\$_smarty_tpl->isRenderingCache);\n}\n?>";
$output .= "/*/%%SmartyNocache:{$compiler->template->compiled->nocache_hash}%%*/\n\";?>";
$output .= "/*/%%SmartyNocache:{$compiler->template->compiled->nocache_hash}%%*/\";?>";
$compiler->parser->current_buffer->append_subtree($compiler->parser,
new Smarty_Internal_ParseTree_Tag($compiler->parser,
$output));
Expand All @@ -166,7 +168,9 @@ public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler)
$output .= "if (!function_exists('{$_funcName}')) {\n";
$output .= "function {$_funcName}(Smarty_Internal_Template \$_smarty_tpl,\$params) {\n";
$output .= $_paramsCode;
$output .= "foreach (\$params as \$key => \$value) {\n\$_smarty_tpl->tpl_vars[\$key] = new Smarty_Variable(\$value, \$_smarty_tpl->isRenderingCache);\n}?>";
$output .= "foreach (\$params as \$key => \$value) {\n\$_smarty_tpl->tpl_vars[\$key] = new Smarty_Variable(\$value, \$_smarty_tpl->isRenderingCache);\n}\n";
$output .= $compiler->compileCheckPlugins(array_merge($compiler->required_plugins[ 'compiled' ], $compiler->required_plugins[ 'nocache' ]));
$output .= "?>\n";
$compiler->parser->current_buffer->append_subtree($compiler->parser,
new Smarty_Internal_ParseTree_Tag($compiler->parser,
$output));
Expand All @@ -178,19 +182,10 @@ public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler)
new Smarty_Internal_ParseTree_Tag($compiler->parser,
$output));
$compiler->parent_compiler->blockOrFunctionCode .= $compiler->parser->current_buffer->to_smarty_php($compiler->parser);
// nocache plugins must be copied
if (!empty($compiler->template->compiled->required_plugins[ 'nocache' ])) {
foreach ($compiler->template->compiled->required_plugins[ 'nocache' ] as $plugin => $tmp) {
foreach ($tmp as $type => $data) {
$compiler->parent_compiler->template->compiled->required_plugins[ 'compiled' ][ $plugin ][ $type ] =
$data;
}
}
}
// restore old buffer

// restore old buffer
$compiler->parser->current_buffer = $saved_data[ 1 ];
// restore old status
$compiler->restoreRequiredPlugins();
$compiler->template->compiled->has_nocache_code = $saved_data[ 2 ];
$compiler->template->caching = $saved_data[ 3 ];
return true;
Expand Down
4 changes: 2 additions & 2 deletions libs/sysplugins/smarty_internal_compile_private_modifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,8 @@ public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $
}
}
}
if (isset($compiler->parent_compiler->template->compiled->required_plugins[ 'nocache' ][ $modifier ][ Smarty::PLUGIN_MODIFIER ][ 'file' ]) ||
isset($compiler->parent_compiler->template->compiled->required_plugins[ 'compiled' ][ $modifier ][ Smarty::PLUGIN_MODIFIER ][ 'file' ])
if (isset($compiler->required_plugins[ 'nocache' ][ $modifier ][ Smarty::PLUGIN_MODIFIER ][ 'file' ]) ||
isset($compiler->required_plugins[ 'compiled' ][ $modifier ][ Smarty::PLUGIN_MODIFIER ][ 'file' ])
) {
// was a plugin
$compiler->known_modifier_type[ $modifier ] = 4;
Expand Down
32 changes: 3 additions & 29 deletions libs/sysplugins/smarty_internal_runtime_codeframe.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,35 +58,9 @@ public function create(Smarty_Internal_Template $_template, $content = '', $func
var_export($_template->smarty->ext->_tplFunction->getTplFunction($_template), true) . ");\n";

}
// include code for plugins
if (!$cache) {
if (!empty($_template->compiled->required_plugins[ 'compiled' ])) {
foreach ($_template->compiled->required_plugins[ 'compiled' ] as $tmp) {
foreach ($tmp as $data) {
$file = addslashes($data[ 'file' ]);
if (is_array($data[ 'function' ])) {
$output .= "if (!is_callable(array('{$data['function'][0]}','{$data['function'][1]}'))) require_once '{$file}';\n";
} else {
$output .= "if (!is_callable('{$data['function']}')) require_once '{$file}';\n";
}
}
}
}
if ($_template->caching && !empty($_template->compiled->required_plugins[ 'nocache' ])) {
$_template->compiled->has_nocache_code = true;
$output .= "echo '/*%%SmartyNocache:{$_template->compiled->nocache_hash}%%*/<?php \$_smarty = \$_smarty_tpl->smarty; ";
foreach ($_template->compiled->required_plugins[ 'nocache' ] as $tmp) {
foreach ($tmp as $data) {
$file = addslashes($data[ 'file' ]);
if (is_array($data[ 'function' ])) {
$output .= addslashes("if (!is_callable(array('{$data['function'][0]}','{$data['function'][1]}'))) require_once '{$file}';\n");
} else {
$output .= addslashes("if (!is_callable('{$data['function']}')) require_once '{$file}';\n");
}
}
}
$output .= "?>/*/%%SmartyNocache:{$_template->compiled->nocache_hash}%%*/';\n";
}
// include code for required plugins
if (!$cache && isset($compiler)) {
$output .= $compiler->compileRequiredPlugins();
}
$output .= "?>";
$output .= $content;
Expand Down
6 changes: 2 additions & 4 deletions libs/sysplugins/smarty_internal_runtime_tplfunction.php
Original file line number Diff line number Diff line change
Expand Up @@ -120,15 +120,13 @@ public function addTplFuncToCache(Smarty_Internal_Template $tpl, $_name, $_funct
}
// add template function code to cache file
if (isset($tplPtr->cached)) {
/* @var Smarty_Template_Cached $cache */
$cache = $tplPtr->cached;
$content = $cache->read($tplPtr);
$content = $tplPtr->cached->read($tplPtr);
if ($content) {
// check if we must update file dependency
if (!preg_match("/'{$funcParam['uid']}'(.*?)'nocache_hash'/", $content, $match2)) {
$content = preg_replace("/('file_dependency'(.*?)\()/", "\\1{$match1[0]}", $content);
}
$tplPtr->smarty->ext->_updateCache->write($cache, $tplPtr,
$tplPtr->smarty->ext->_updateCache->write($tplPtr,
preg_replace('/\s*\?>\s*$/', "\n", $content) .
"\n" . preg_replace(array('/^\s*<\?php\s+/',
'/\s*\?>\s*$/',), "\n",
Expand Down
16 changes: 10 additions & 6 deletions libs/sysplugins/smarty_internal_runtime_updatecache.php
Original file line number Diff line number Diff line change
Expand Up @@ -115,41 +115,43 @@ public function removeNoCacheHash(Smarty_Template_Cached $cached,
$content = $_template->smarty->ext->_filterHandler->runFilter('output', $content, $_template);
}
// write cache file content
$this->writeCachedContent($cached, $_template, $content);
$this->writeCachedContent($_template, $content);
}

/**
* Writes the content to cache resource
*
* @param \Smarty_Template_Cached $cached
* @param Smarty_Internal_Template $_template
* @param string $content
*
* @return bool
*/
public function writeCachedContent(Smarty_Template_Cached $cached, Smarty_Internal_Template $_template, $content)
public function writeCachedContent(Smarty_Internal_Template $_template, $content)
{
if ($_template->source->handler->recompiled || !$_template->caching
) {
// don't write cache file
return false;
}
if (!isset($_template->cached)) {
$_template->loadCached();
}
$content = $_template->smarty->ext->_codeFrame->create($_template, $content, '', true);
return $this->write($cached, $_template, $content);
return $this->write($_template, $content);
}

/**
* Write this cache object to handler
*
* @param \Smarty_Template_Cached $cached
* @param Smarty_Internal_Template $_template template object
* @param string $content content to cache
*
* @return bool success
*/
public function write(Smarty_Template_Cached $cached, Smarty_Internal_Template $_template, $content)
public function write(Smarty_Internal_Template $_template, $content)
{
if (!$_template->source->handler->recompiled) {
$cached = $_template->cached;
if ($cached->handler->writeCachedContent($_template, $content)) {
$cached->content = null;
$cached->timestamp = time();
Expand All @@ -160,6 +162,7 @@ public function write(Smarty_Template_Cached $cached, Smarty_Internal_Template $
if ($_template->smarty->cache_locking) {
$cached->handler->releaseLock($_template->smarty, $cached);
}

return true;
}
$cached->content = null;
Expand All @@ -168,6 +171,7 @@ public function write(Smarty_Template_Cached $cached, Smarty_Internal_Template $
$cached->valid = false;
$cached->processed = false;
}

return false;
}
}
44 changes: 34 additions & 10 deletions libs/sysplugins/smarty_internal_template.php
Original file line number Diff line number Diff line change
Expand Up @@ -234,15 +234,6 @@ public function render($no_output_filter = true, $display = null)
$this->smarty->_debug->display_debug($this, true);
}
}
if ($this->_isSubTpl()) {
foreach ($this->compiled->required_plugins as $code => $tmp1) {
foreach ($tmp1 as $name => $tmp) {
foreach ($tmp as $type => $data) {
$this->parent->compiled->required_plugins[ $code ][ $name ][ $type ] = $data;
}
}
}
}
if (!$no_output_filter &&
(!$this->caching || $this->cached->has_nocache_code || $this->source->handler->recompiled) &&
(isset($this->smarty->autoload_filters[ 'output' ]) ||
Expand Down Expand Up @@ -428,6 +419,39 @@ public function _assignInScope($varName, $value, $nocache = false, $scope = 0)
}
}

/**
* Check if plugins are callable require file otherwise
*
* @param array $plugins required plugins
*
* @throws \SmartyException
*/
public function _checkPlugins($plugins) {
static $checked = array();
foreach($plugins as $plugin) {
$name = join('::', (array)$plugin[ 'function' ]);
if (!isset($checked[$name])) {
if (!is_callable($plugin['function'])) {
if (is_file($plugin['file'])) {
require_once $plugin['file'];
if (is_callable($plugin['function'])) {
$checked[ $name ] = true;
}
}
} else {
$checked[ $name ] = true;
}
}
if (!isset($checked[ $name ])) {
if (false !== $this->smarty->loadPlugin($name)) {
$checked[ $name ] = true;
} else {
throw new SmartyException("Plugin '{$name}' not callable");
}
}
}
}

/**
* This function is executed automatically when a compiled or cached template file is included
* - Decode saved properties from compiled template and cache files
Expand Down Expand Up @@ -523,7 +547,7 @@ public function compileTemplateSource()
*/
public function writeCachedContent($content)
{
return $this->smarty->ext->_updateCache->writeCachedContent($this->cached, $this, $content);
return $this->smarty->ext->_updateCache->writeCachedContent($this, $content);
}

/**
Expand Down
Loading

0 comments on commit 336c07c

Please sign in to comment.