mirror of
https://github.com/smarty-php/smarty.git
synced 2025-08-02 09:24:28 +02:00
Bugfix/1100 modifier called like a function compiled to modifier name not callback (#1101)
* Fixed that modifiers called like function would be compiled to modifier name instead of calling the registered callback
This commit is contained in:
1
changelog/1100.md
Normal file
1
changelog/1100.md
Normal file
@@ -0,0 +1 @@
|
|||||||
|
- Fixed that modifiers called like function would be compiled to modifier name instead of calling the registered callback [#1100](https://github.com/smarty-php/smarty/issues/1100)
|
@@ -455,28 +455,28 @@ abstract class Smarty_Internal_TemplateCompilerBase
|
|||||||
$this->smarty->_current_file = $this->template->source->filepath;
|
$this->smarty->_current_file = $this->template->source->filepath;
|
||||||
// get template source
|
// get template source
|
||||||
if (!empty($this->template->source->components)) {
|
if (!empty($this->template->source->components)) {
|
||||||
$_compiled_code = '<?php $_smarty_tpl->_loadInheritance(); $_smarty_tpl->inheritance->init($_smarty_tpl, true); ?>';
|
$_compiled_code = '<?php $_smarty_tpl->_loadInheritance(); $_smarty_tpl->inheritance->init($_smarty_tpl, true); ?>';
|
||||||
|
|
||||||
$i = 0;
|
$i = 0;
|
||||||
$reversed_components = array_reverse($this->template->getSource()->components);
|
$reversed_components = array_reverse($this->template->getSource()->components);
|
||||||
foreach ($reversed_components as $source) {
|
foreach ($reversed_components as $source) {
|
||||||
$i++;
|
$i++;
|
||||||
if ($i === count($reversed_components)) {
|
if ($i === count($reversed_components)) {
|
||||||
$_compiled_code .= '<?php $_smarty_tpl->inheritance->endChild($_smarty_tpl); ?>';
|
$_compiled_code .= '<?php $_smarty_tpl->inheritance->endChild($_smarty_tpl); ?>';
|
||||||
}
|
}
|
||||||
$_compiled_code .= $this->compileTag(
|
$_compiled_code .= $this->compileTag(
|
||||||
'include',
|
'include',
|
||||||
[
|
[
|
||||||
var_export($source->resource, true),
|
var_export($source->resource, true),
|
||||||
['scope' => 'parent'],
|
['scope' => 'parent'],
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
$_compiled_code = $this->postFilter($_compiled_code, $this->template);
|
$_compiled_code = $this->postFilter($_compiled_code, $this->template);
|
||||||
} else {
|
} else {
|
||||||
// get template source
|
// get template source
|
||||||
$_content = $this->template->source->getContent();
|
$_content = $this->template->source->getContent();
|
||||||
$_compiled_code = $this->postFilter($this->doCompile($this->preFilter($_content), true));
|
$_compiled_code = $this->postFilter($this->doCompile($this->preFilter($_content), true));
|
||||||
}
|
}
|
||||||
if (!empty($this->required_plugins[ 'compiled' ]) || !empty($this->required_plugins[ 'nocache' ])) {
|
if (!empty($this->required_plugins[ 'compiled' ]) || !empty($this->required_plugins[ 'nocache' ])) {
|
||||||
$_compiled_code = '<?php ' . $this->compileRequiredPlugins() . "?>\n" . $_compiled_code;
|
$_compiled_code = '<?php ' . $this->compileRequiredPlugins() . "?>\n" . $_compiled_code;
|
||||||
@@ -617,7 +617,8 @@ abstract class Smarty_Internal_TemplateCompilerBase
|
|||||||
{
|
{
|
||||||
if (!$this->smarty->security_policy || $this->smarty->security_policy->isTrustedPhpFunction($name, $this)) {
|
if (!$this->smarty->security_policy || $this->smarty->security_policy->isTrustedPhpFunction($name, $this)) {
|
||||||
if (strcasecmp($name, 'isset') === 0 || strcasecmp($name, 'empty') === 0
|
if (strcasecmp($name, 'isset') === 0 || strcasecmp($name, 'empty') === 0
|
||||||
|| strcasecmp($name, 'array') === 0 || is_callable($name)
|
|| strcasecmp($name, 'array') === 0
|
||||||
|
|| (is_callable($name) && !isset($this->smarty->registered_plugins[Smarty::PLUGIN_MODIFIER][$name]))
|
||||||
) {
|
) {
|
||||||
$func_name = smarty_strtolower_ascii($name);
|
$func_name = smarty_strtolower_ascii($name);
|
||||||
|
|
||||||
@@ -649,28 +650,42 @@ abstract class Smarty_Internal_TemplateCompilerBase
|
|||||||
}
|
}
|
||||||
if ($func_name === 'empty') {
|
if ($func_name === 'empty') {
|
||||||
return $func_name . '(' .
|
return $func_name . '(' .
|
||||||
str_replace("')->value", "',null,true,false)->value", $parameter[ 0 ]) . ')';
|
str_replace("')->value", "',null,true,false)->value", $parameter[0]) . ')';
|
||||||
} else {
|
} else {
|
||||||
return $func_name . '(' . $parameter[ 0 ] . ')';
|
return $func_name . '(' . $parameter[0] . ')';
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!$this->smarty->loadPlugin('smarty_modifiercompiler_' . $name)
|
!$this->smarty->loadPlugin('smarty_modifiercompiler_' . $name)
|
||||||
&& !isset($this->smarty->registered_plugins[Smarty::PLUGIN_MODIFIER][$name])
|
&& !isset($this->smarty->registered_plugins[Smarty::PLUGIN_MODIFIER][$name])
|
||||||
&& !in_array($name, ['time', 'join', 'is_array', 'in_array', 'count'])
|
&& !in_array($name, ['time', 'join', 'is_array', 'in_array', 'count'])
|
||||||
) {
|
) {
|
||||||
trigger_error('Using unregistered function "' . $name . '" in a template is deprecated and will be ' .
|
trigger_error('Using unregistered function "' . $name . '" in a template is deprecated and will be ' .
|
||||||
'removed in a future release. Use Smarty::registerPlugin to explicitly register ' .
|
'removed in a future release. Use Smarty::registerPlugin to explicitly register ' .
|
||||||
'a custom modifier.', E_USER_DEPRECATED);
|
'a custom modifier.', E_USER_DEPRECATED);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $name . '(' . implode(',', $parameter) . ')';
|
return $name . '(' . implode(',', $parameter) . ')';
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
$this->trigger_template_error("unknown function '{$name}'");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isset($this->smarty->registered_plugins[Smarty::PLUGIN_MODIFIER][$name])) {
|
||||||
|
if ($name === $this->smarty->registered_plugins[Smarty::PLUGIN_MODIFIER][$name][0]) {
|
||||||
|
return $name . '(' . implode(',', $parameter) . ')';
|
||||||
|
}
|
||||||
|
|
||||||
|
return sprintf(
|
||||||
|
'call_user_func_array($_smarty_tpl->registered_plugins[ \'%s\' ][ %s ][ 0 ], array( %s ))',
|
||||||
|
Smarty::PLUGIN_MODIFIER,
|
||||||
|
var_export($name, true),
|
||||||
|
implode(',', $parameter)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->trigger_template_error("unknown function '{$name}'");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -0,0 +1,55 @@
|
|||||||
|
<?php
|
||||||
|
// first class callables where introduced in PHP 8.1
|
||||||
|
if (PHP_VERSION_ID >= 80100) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* class for register modifier with (first class) callables tests
|
||||||
|
*
|
||||||
|
* @runTestsInSeparateProcess
|
||||||
|
* @preserveGlobalState disabled
|
||||||
|
* @backupStaticAttributes enabled
|
||||||
|
*/
|
||||||
|
class RegisterModifierFirstClassCallablesTest extends PHPUnit_Smarty
|
||||||
|
{
|
||||||
|
public function setUp(): void
|
||||||
|
{
|
||||||
|
$this->setUpSmarty(__DIR__);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function testInit()
|
||||||
|
{
|
||||||
|
$this->cleanDirs();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testRegisterFirstClassCallable()
|
||||||
|
{
|
||||||
|
$this->smarty->registerPlugin(Smarty::PLUGIN_MODIFIER, 'testmodifier', eval('return strrev(...);'));
|
||||||
|
$this->assertEquals('mosredna', $this->smarty->fetch('string:{"andersom"|testmodifier}'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testRegisterFirstClassCallableSameName()
|
||||||
|
{
|
||||||
|
$this->smarty->registerPlugin(Smarty::PLUGIN_MODIFIER, 'mymodifier', eval('return strrev(...);'));
|
||||||
|
$this->assertEquals('mosredna', $this->smarty->fetch('string:{"andersom"|mymodifier}'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testRegisterFirstClassCallableAsFunc()
|
||||||
|
{
|
||||||
|
$this->smarty->registerPlugin(Smarty::PLUGIN_MODIFIER, 'kprint_r_out', eval('return strrev(...);'));
|
||||||
|
$this->smarty->assign('myVar', 'andersom');
|
||||||
|
$this->assertEquals('mosredna', $this->smarty->fetch('string:{kprint_r_out($myVar)}'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testRegisterFirstClassCallableSameNameAsPhpFunc()
|
||||||
|
{
|
||||||
|
$this->smarty->registerPlugin(Smarty::PLUGIN_MODIFIER, 'mymodifierfcc', eval('return strrev(...);'));
|
||||||
|
$this->assertEquals('mosredna', $this->smarty->fetch('string:{mymodifierfcc("andersom")}'));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function mymodifierfcc($a, $b, $c)
|
||||||
|
{
|
||||||
|
return "$a function $b $c";
|
||||||
|
}
|
@@ -88,6 +88,22 @@ class RegisterModifierTest extends PHPUnit_Smarty
|
|||||||
$this->smarty->unregisterPlugin(Smarty::PLUGIN_MODIFIER, 'testmodifier');
|
$this->smarty->unregisterPlugin(Smarty::PLUGIN_MODIFIER, 'testmodifier');
|
||||||
$this->assertTrue(isset($this->smarty->registered_plugins[Smarty::PLUGIN_BLOCK]['testmodifier']));
|
$this->assertTrue(isset($this->smarty->registered_plugins[Smarty::PLUGIN_BLOCK]['testmodifier']));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function testRegisterNativePhpFuncAsString()
|
||||||
|
{
|
||||||
|
$this->smarty->registerPlugin(Smarty::PLUGIN_MODIFIER, 'strrev', 'strrev');
|
||||||
|
$this->smarty->assign('myVar', 'andersom');
|
||||||
|
$this->assertEquals('mosredna', $this->smarty->fetch('string:{strrev($myVar)}'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testRegisterNativePhpFuncUnderDifferentName()
|
||||||
|
{
|
||||||
|
$this->smarty->registerPlugin(Smarty::PLUGIN_MODIFIER, 'k_xyz_a', 'strrev');
|
||||||
|
$this->smarty->assign('myVar', 'andersom');
|
||||||
|
$this->assertEquals('mosredna', $this->smarty->fetch('string:{k_xyz_a($myVar)}'));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function mymodifier($a, $b, $c)
|
function mymodifier($a, $b, $c)
|
||||||
|
Reference in New Issue
Block a user