mirror of
https://github.com/smarty-php/smarty.git
synced 2025-08-03 01:44:26 +02:00
Implemented support for substr, implode and json_encode as modifiers.
Fixes #939
This commit is contained in:
1
changelog/939.md
Normal file
1
changelog/939.md
Normal file
@@ -0,0 +1 @@
|
|||||||
|
- Add support for implode, substr and json_encode as modifiers/functions in templates [#939](https://github.com/smarty-php/smarty/issues/939)
|
14
src/Compile/Modifier/JsonEncodeModifierCompiler.php
Normal file
14
src/Compile/Modifier/JsonEncodeModifierCompiler.php
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Smarty\Compile\Modifier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Smarty json_encode modifier plugin
|
||||||
|
*/
|
||||||
|
class JsonEncodeModifierCompiler extends Base {
|
||||||
|
|
||||||
|
public function compile($params, \Smarty\Compiler\Template $compiler) {
|
||||||
|
return 'json_encode(' . $params[0] . (isset($params[1]) ? ', (int) ' . $params[1] : '') . ')';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
15
src/Compile/Modifier/SubstrModifierCompiler.php
Normal file
15
src/Compile/Modifier/SubstrModifierCompiler.php
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Smarty\Compile\Modifier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Smarty substr modifier plugin
|
||||||
|
*/
|
||||||
|
class SubstrModifierCompiler extends Base {
|
||||||
|
|
||||||
|
public function compile($params, \Smarty\Compiler\Template $compiler) {
|
||||||
|
return 'substr((string) ' . $params[0] . ', (int) ' . $params[1] .
|
||||||
|
(isset($params[2]) ? ', (int) ' . $params[2] : '') . ')';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -43,16 +43,19 @@ class ModifierCompiler extends Base {
|
|||||||
foreach ($parameter['modifierlist'] as $single_modifier) {
|
foreach ($parameter['modifierlist'] as $single_modifier) {
|
||||||
/* @var string $modifier */
|
/* @var string $modifier */
|
||||||
$modifier = $single_modifier[0];
|
$modifier = $single_modifier[0];
|
||||||
$single_modifier[0] = $output;
|
|
||||||
$params = implode(',', $single_modifier);
|
|
||||||
|
$modifier_params = array_values($single_modifier);
|
||||||
|
|
||||||
|
$modifier_params[0] = $output;
|
||||||
|
$params = implode(',', $modifier_params);
|
||||||
|
|
||||||
if (!is_object($compiler->getSmarty()->security_policy)
|
if (!is_object($compiler->getSmarty()->security_policy)
|
||||||
|| $compiler->getSmarty()->security_policy->isTrustedModifier($modifier, $compiler)
|
|| $compiler->getSmarty()->security_policy->isTrustedModifier($modifier, $compiler)
|
||||||
) {
|
) {
|
||||||
|
|
||||||
if ($handler = $compiler->getModifierCompiler($modifier)) {
|
if ($handler = $compiler->getModifierCompiler($modifier)) {
|
||||||
$output = $handler->compile($single_modifier, $compiler);
|
$output = $handler->compile($modifier_params, $compiler);
|
||||||
|
|
||||||
} elseif ($compiler->getSmarty()->getModifierCallback($modifier)) {
|
} elseif ($compiler->getSmarty()->getModifierCallback($modifier)) {
|
||||||
$output = sprintf(
|
$output = sprintf(
|
||||||
'$_smarty_tpl->getSmarty()->getModifierCallback(%s)(%s)',
|
'$_smarty_tpl->getSmarty()->getModifierCallback(%s)(%s)',
|
||||||
@@ -60,7 +63,7 @@ class ModifierCompiler extends Base {
|
|||||||
$params
|
$params
|
||||||
);
|
);
|
||||||
} elseif ($callback = $compiler->getPluginFromDefaultHandler($modifier, \Smarty\Smarty::PLUGIN_MODIFIERCOMPILER)) {
|
} elseif ($callback = $compiler->getPluginFromDefaultHandler($modifier, \Smarty\Smarty::PLUGIN_MODIFIERCOMPILER)) {
|
||||||
$output = (new \Smarty\Compile\Modifier\BCPluginWrapper($callback))->compile($single_modifier, $compiler);
|
$output = (new \Smarty\Compile\Modifier\BCPluginWrapper($callback))->compile($modifier_params, $compiler);
|
||||||
} elseif ($function = $compiler->getPluginFromDefaultHandler($modifier, \Smarty\Smarty::PLUGIN_MODIFIER)) {
|
} elseif ($function = $compiler->getPluginFromDefaultHandler($modifier, \Smarty\Smarty::PLUGIN_MODIFIER)) {
|
||||||
if (!is_array($function)) {
|
if (!is_array($function)) {
|
||||||
$output = "{$function}({$params})";
|
$output = "{$function}({$params})";
|
||||||
|
@@ -65,8 +65,6 @@ class Configfile extends BaseCompiler {
|
|||||||
* @param Smarty $smarty global instance
|
* @param Smarty $smarty global instance
|
||||||
*/
|
*/
|
||||||
public function __construct(Smarty $smarty) {
|
public function __construct(Smarty $smarty) {
|
||||||
$this->smarty = $smarty;
|
|
||||||
// get required plugins
|
|
||||||
$this->smarty = $smarty;
|
$this->smarty = $smarty;
|
||||||
$this->config_data['sections'] = [];
|
$this->config_data['sections'] = [];
|
||||||
$this->config_data['vars'] = [];
|
$this->config_data['vars'] = [];
|
||||||
@@ -104,7 +102,7 @@ class Configfile extends BaseCompiler {
|
|||||||
) . "\n",
|
) . "\n",
|
||||||
$this
|
$this
|
||||||
);
|
);
|
||||||
/* @var ConfigfileParser $this->parser */
|
|
||||||
$this->parser = new ConfigfileParser($this->lex, $this);
|
$this->parser = new ConfigfileParser($this->lex, $this);
|
||||||
if ($this->smarty->_parserdebug) {
|
if ($this->smarty->_parserdebug) {
|
||||||
$this->parser->PrintTrace();
|
$this->parser->PrintTrace();
|
||||||
|
@@ -28,6 +28,7 @@ class DefaultExtension extends Base {
|
|||||||
case 'from_charset': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\FromCharsetModifierCompiler(); break;
|
case 'from_charset': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\FromCharsetModifierCompiler(); break;
|
||||||
case 'indent': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\IndentModifierCompiler(); break;
|
case 'indent': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\IndentModifierCompiler(); break;
|
||||||
case 'isset': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\IssetModifierCompiler(); break;
|
case 'isset': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\IssetModifierCompiler(); break;
|
||||||
|
case 'json_encode': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\JsonEncodeModifierCompiler(); break;
|
||||||
case 'lower': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\LowerModifierCompiler(); break;
|
case 'lower': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\LowerModifierCompiler(); break;
|
||||||
case 'nl2br': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\Nl2brModifierCompiler(); break;
|
case 'nl2br': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\Nl2brModifierCompiler(); break;
|
||||||
case 'noprint': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\NoPrintModifierCompiler(); break;
|
case 'noprint': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\NoPrintModifierCompiler(); break;
|
||||||
@@ -37,6 +38,7 @@ class DefaultExtension extends Base {
|
|||||||
case 'strip': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\StripModifierCompiler(); break;
|
case 'strip': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\StripModifierCompiler(); break;
|
||||||
case 'strip_tags': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\StripTagsModifierCompiler(); break;
|
case 'strip_tags': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\StripTagsModifierCompiler(); break;
|
||||||
case 'strlen': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\StrlenModifierCompiler(); break;
|
case 'strlen': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\StrlenModifierCompiler(); break;
|
||||||
|
case 'substr': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\SubstrModifierCompiler(); break;
|
||||||
case 'to_charset': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\ToCharsetModifierCompiler(); break;
|
case 'to_charset': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\ToCharsetModifierCompiler(); break;
|
||||||
case 'unescape': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\UnescapeModifierCompiler(); break;
|
case 'unescape': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\UnescapeModifierCompiler(); break;
|
||||||
case 'upper': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\UpperModifierCompiler(); break;
|
case 'upper': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\UpperModifierCompiler(); break;
|
||||||
@@ -54,6 +56,7 @@ class DefaultExtension extends Base {
|
|||||||
case 'debug_print_var': return [$this, 'smarty_modifier_debug_print_var'];
|
case 'debug_print_var': return [$this, 'smarty_modifier_debug_print_var'];
|
||||||
case 'escape': return [$this, 'smarty_modifier_escape'];
|
case 'escape': return [$this, 'smarty_modifier_escape'];
|
||||||
case 'explode': return [$this, 'smarty_modifier_explode'];
|
case 'explode': return [$this, 'smarty_modifier_explode'];
|
||||||
|
case 'implode': return [$this, 'smarty_modifier_implode'];
|
||||||
case 'mb_wordwrap': return [$this, 'smarty_modifier_mb_wordwrap'];
|
case 'mb_wordwrap': return [$this, 'smarty_modifier_mb_wordwrap'];
|
||||||
case 'number_format': return [$this, 'smarty_modifier_number_format'];
|
case 'number_format': return [$this, 'smarty_modifier_number_format'];
|
||||||
case 'regex_replace': return [$this, 'smarty_modifier_regex_replace'];
|
case 'regex_replace': return [$this, 'smarty_modifier_regex_replace'];
|
||||||
@@ -522,6 +525,27 @@ class DefaultExtension extends Base {
|
|||||||
return explode($separator, $string ?? '', $limit ?? PHP_INT_MAX);
|
return explode($separator, $string ?? '', $limit ?? PHP_INT_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Smarty implode modifier plugin
|
||||||
|
* Type: modifier
|
||||||
|
* Name: implode
|
||||||
|
* Purpose: join an array of values into a single string
|
||||||
|
*
|
||||||
|
* @param array $values
|
||||||
|
* @param string $separator
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function smarty_modifier_implode($values, $separator = '')
|
||||||
|
{
|
||||||
|
if (is_array($separator)) {
|
||||||
|
trigger_error("Using implode with the separator first is deprecated. " .
|
||||||
|
"Call implode using the array first, separator second.", E_USER_DEPRECATED);
|
||||||
|
return implode((string) ($values ?? ''), (array) $separator);
|
||||||
|
}
|
||||||
|
return implode((string) ($separator ?? ''), (array) $values);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Smarty wordwrap modifier plugin
|
* Smarty wordwrap modifier plugin
|
||||||
* Type: modifier
|
* Type: modifier
|
||||||
|
@@ -103,7 +103,8 @@ class RegisterModifierTest extends PHPUnit_Smarty
|
|||||||
|
|
||||||
public function dataUnknownModifiers(): array {
|
public function dataUnknownModifiers(): array {
|
||||||
return [
|
return [
|
||||||
['{"blah"|substr:1:2}', 'la'],
|
['{" blah"|ltrim:" "}', 'blah'],
|
||||||
|
['{"blah"|strrev}', 'halb'],
|
||||||
['{"blah"|ucfirst}', 'Blah'],
|
['{"blah"|ucfirst}', 'Blah'],
|
||||||
['{"blah"|md5}', md5('blah')],
|
['{"blah"|md5}', md5('blah')],
|
||||||
];
|
];
|
||||||
|
@@ -0,0 +1,52 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Smarty PHPunit tests of modifier
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace UnitTests\TemplateSource\TagTests\PluginModifier;
|
||||||
|
use PHPUnit_Smarty;
|
||||||
|
|
||||||
|
class PluginModifierImplodeTest extends PHPUnit_Smarty
|
||||||
|
{
|
||||||
|
public function setUp(): void
|
||||||
|
{
|
||||||
|
$this->setUpSmarty(__DIR__);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testDefault()
|
||||||
|
{
|
||||||
|
$tpl = $this->smarty->createTemplate('string:{$v|implode}');
|
||||||
|
$tpl->assign("v", ["1", "2"]);
|
||||||
|
$this->assertEquals("12", $this->smarty->fetch($tpl));
|
||||||
|
}
|
||||||
|
public function testWithSeparator()
|
||||||
|
{
|
||||||
|
$tpl = $this->smarty->createTemplate('string:{$v|implode:","}');
|
||||||
|
$tpl->assign("v", ["a", "b"]);
|
||||||
|
$this->assertEquals("a,b", $this->smarty->fetch($tpl));
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
|
public function testLegacyArgumentOrder()
|
||||||
|
{
|
||||||
|
$tpl = $this->smarty->createTemplate('string:{","|implode:$v}');
|
||||||
|
$tpl->assign("v", ["a", "b"]);
|
||||||
|
$this->assertEquals("a,b", $this->smarty->fetch($tpl));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testInConditional()
|
||||||
|
{
|
||||||
|
$tpl = $this->smarty->createTemplate('string:{if implode($v) == "abc"}good{else}bad{/if}');
|
||||||
|
$tpl->assign("v", ['a','b','c']);
|
||||||
|
$this->assertEquals("good", $this->smarty->fetch($tpl));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testInConditionalWithSeparator()
|
||||||
|
{
|
||||||
|
$tpl = $this->smarty->createTemplate('string:{if implode($v, "-") == "a-b-c"}good{else}bad{/if}');
|
||||||
|
$tpl->assign("v", ['a','b','c']);
|
||||||
|
$this->assertEquals("good", $this->smarty->fetch($tpl));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,72 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Smarty PHPunit tests of modifier
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace UnitTests\TemplateSource\TagTests\PluginModifier;
|
||||||
|
use PHPUnit_Smarty;
|
||||||
|
|
||||||
|
class PluginModifierJsonEncodeTest extends PHPUnit_Smarty
|
||||||
|
{
|
||||||
|
public function setUp(): void
|
||||||
|
{
|
||||||
|
$this->setUpSmarty(__DIR__);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider dataForDefault
|
||||||
|
*/
|
||||||
|
public function testDefault($value, $expected)
|
||||||
|
{
|
||||||
|
$tpl = $this->smarty->createTemplate('string:{$v|json_encode}');
|
||||||
|
$tpl->assign("v", $value);
|
||||||
|
$this->assertEquals($expected, $this->smarty->fetch($tpl));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider dataForDefault
|
||||||
|
*/
|
||||||
|
public function testDefaultAsFunction($value, $expected)
|
||||||
|
{
|
||||||
|
$tpl = $this->smarty->createTemplate('string:{json_encode($v)}');
|
||||||
|
$tpl->assign("v", $value);
|
||||||
|
$this->assertEquals($expected, $this->smarty->fetch($tpl));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function dataForDefault() {
|
||||||
|
return [
|
||||||
|
["abc", '"abc"'],
|
||||||
|
[["abc"], '["abc"]'],
|
||||||
|
[["abc",["a"=>2]], '["abc",{"a":2}]'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider dataForForceObject
|
||||||
|
*/
|
||||||
|
public function testForceObject($value, $expected)
|
||||||
|
{
|
||||||
|
$tpl = $this->smarty->createTemplate('string:{$v|json_encode:16}');
|
||||||
|
$tpl->assign("v", $value);
|
||||||
|
$this->assertEquals($expected, $this->smarty->fetch($tpl));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider dataForForceObject
|
||||||
|
*/
|
||||||
|
public function testForceObjectAsFunction($value, $expected)
|
||||||
|
{
|
||||||
|
$tpl = $this->smarty->createTemplate('string:{json_encode($v,16)}');
|
||||||
|
$tpl->assign("v", $value);
|
||||||
|
$this->assertEquals($expected, $this->smarty->fetch($tpl));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function dataForForceObject() {
|
||||||
|
return [
|
||||||
|
["abc", '"abc"'],
|
||||||
|
[["abc"], '{"0":"abc"}'],
|
||||||
|
[["abc",["a"=>2]], '{"0":"abc","1":{"a":2}}'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,44 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Smarty PHPunit tests of modifier
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace UnitTests\TemplateSource\TagTests\PluginModifier;
|
||||||
|
use PHPUnit_Smarty;
|
||||||
|
|
||||||
|
class PluginModifierSubstrTest extends PHPUnit_Smarty
|
||||||
|
{
|
||||||
|
public function setUp(): void
|
||||||
|
{
|
||||||
|
$this->setUpSmarty(__DIR__);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testDefault()
|
||||||
|
{
|
||||||
|
$tpl = $this->smarty->createTemplate('string:{$v|substr:1}');
|
||||||
|
$tpl->assign("v", "abc");
|
||||||
|
$this->assertEquals("bc", $this->smarty->fetch($tpl));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testTwoArguments()
|
||||||
|
{
|
||||||
|
$tpl = $this->smarty->createTemplate('string:{$v|substr:1:1}');
|
||||||
|
$tpl->assign("v", "abc");
|
||||||
|
$this->assertEquals("b", $this->smarty->fetch($tpl));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testNegativeOffset()
|
||||||
|
{
|
||||||
|
$tpl = $this->smarty->createTemplate('string:{$v|substr:-1}');
|
||||||
|
$tpl->assign("v", "abc");
|
||||||
|
$this->assertEquals("c", $this->smarty->fetch($tpl));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testInConditional()
|
||||||
|
{
|
||||||
|
$tpl = $this->smarty->createTemplate('string:{if substr($v, -1) == "c"}good{else}bad{/if}');
|
||||||
|
$tpl->assign("v", "abc");
|
||||||
|
$this->assertEquals("good", $this->smarty->fetch($tpl));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Reference in New Issue
Block a user