mirror of
https://github.com/smarty-php/smarty.git
synced 2025-08-02 17:34: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) {
|
||||
/* @var string $modifier */
|
||||
$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)
|
||||
|| $compiler->getSmarty()->security_policy->isTrustedModifier($modifier, $compiler)
|
||||
) {
|
||||
|
||||
if ($handler = $compiler->getModifierCompiler($modifier)) {
|
||||
$output = $handler->compile($single_modifier, $compiler);
|
||||
|
||||
$output = $handler->compile($modifier_params, $compiler);
|
||||
} elseif ($compiler->getSmarty()->getModifierCallback($modifier)) {
|
||||
$output = sprintf(
|
||||
'$_smarty_tpl->getSmarty()->getModifierCallback(%s)(%s)',
|
||||
@@ -60,7 +63,7 @@ class ModifierCompiler extends Base {
|
||||
$params
|
||||
);
|
||||
} 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)) {
|
||||
if (!is_array($function)) {
|
||||
$output = "{$function}({$params})";
|
||||
|
@@ -65,8 +65,6 @@ class Configfile extends BaseCompiler {
|
||||
* @param Smarty $smarty global instance
|
||||
*/
|
||||
public function __construct(Smarty $smarty) {
|
||||
$this->smarty = $smarty;
|
||||
// get required plugins
|
||||
$this->smarty = $smarty;
|
||||
$this->config_data['sections'] = [];
|
||||
$this->config_data['vars'] = [];
|
||||
@@ -104,7 +102,7 @@ class Configfile extends BaseCompiler {
|
||||
) . "\n",
|
||||
$this
|
||||
);
|
||||
/* @var ConfigfileParser $this->parser */
|
||||
|
||||
$this->parser = new ConfigfileParser($this->lex, $this);
|
||||
if ($this->smarty->_parserdebug) {
|
||||
$this->parser->PrintTrace();
|
||||
|
@@ -28,6 +28,7 @@ class DefaultExtension extends Base {
|
||||
case 'from_charset': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\FromCharsetModifierCompiler(); break;
|
||||
case 'indent': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\IndentModifierCompiler(); 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 'nl2br': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\Nl2brModifierCompiler(); 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_tags': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\StripTagsModifierCompiler(); 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 'unescape': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\UnescapeModifierCompiler(); 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 'escape': return [$this, 'smarty_modifier_escape'];
|
||||
case 'explode': return [$this, 'smarty_modifier_explode'];
|
||||
case 'implode': return [$this, 'smarty_modifier_implode'];
|
||||
case 'mb_wordwrap': return [$this, 'smarty_modifier_mb_wordwrap'];
|
||||
case 'number_format': return [$this, 'smarty_modifier_number_format'];
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* Type: modifier
|
||||
|
@@ -103,7 +103,8 @@ class RegisterModifierTest extends PHPUnit_Smarty
|
||||
|
||||
public function dataUnknownModifiers(): array {
|
||||
return [
|
||||
['{"blah"|substr:1:2}', 'la'],
|
||||
['{" blah"|ltrim:" "}', 'blah'],
|
||||
['{"blah"|strrev}', 'halb'],
|
||||
['{"blah"|ucfirst}', '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