Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Too many shorthand attributes #953

Merged
merged 1 commit into from
Mar 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Fixed
- Too many shorthand attributes error when using a modifier as a function with more than 3 parameters in an expression [#949](https://github.com/smarty-php/smarty/issues/949)

### Removed
- Dropped support for undocumented `{time()}` added in v5.0.0 since we already have the documented `{$smarty.now}`

## [5.0.0-rc3] - 2024-02-26

### Added
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,6 @@ Object chaining:

{$object->method1($x)->method2($y)}

Direct PHP function access:

{time()}
```

> **Note**
Expand Down
24 changes: 10 additions & 14 deletions src/Compile/FunctionCallCompiler.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class FunctionCallCompiler extends Base {
*
* @var array
*/
protected $shorttag_order = ['var1', 'var2', 'var3'];
protected $shorttag_order = [];

/**
* Compiles code for the execution of a registered function
Expand All @@ -58,19 +58,15 @@ public function compile($args, Template $compiler, $parameter = [], $tag = null,
$_paramsArray = $this->formatParamsArray($_attr);
$_params = 'array(' . implode(',', $_paramsArray) . ')';

try {
$value = array_shift($_attr);
$output = $compiler->compileModifier([array_merge([$function], $_attr)], $value);
} catch (\Smarty\CompilerException $e) {
if ($functionHandler = $compiler->getSmarty()->getFunctionHandler($function)) {

// not cacheable?
$compiler->tag_nocache = $compiler->tag_nocache || !$functionHandler->isCacheable();
$output = "\$_smarty_tpl->getSmarty()->getFunctionHandler(" . var_export($function, true) . ")";
$output .= "->handle($_params, \$_smarty_tpl)";
} else {
throw $e;
}

if ($functionHandler = $compiler->getSmarty()->getFunctionHandler($function)) {

// not cacheable?
$compiler->tag_nocache = $compiler->tag_nocache || !$functionHandler->isCacheable();
$output = "\$_smarty_tpl->getSmarty()->getFunctionHandler(" . var_export($function, true) . ")";
$output .= "->handle($_params, \$_smarty_tpl)";
} else {
$compiler->trigger_template_error("unknown function '{$function}'", null, true);
}

if (!empty($parameter['modifierlist'])) {
Expand Down
19 changes: 19 additions & 0 deletions src/Compile/Modifier/IsArrayModifierCompiler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php
namespace Smarty\Compile\Modifier;
use Smarty\CompilerException;

/**
* Smarty is_array modifier plugin
*/
class IsArrayModifierCompiler extends Base {

public function compile($params, \Smarty\Compiler\Template $compiler) {

if (count($params) !== 1) {
throw new CompilerException("Invalid number of arguments for is_array. is_array expects exactly 1 parameter.");
}

return 'is_array(' . $params[0] . ')';
}

}
5 changes: 5 additions & 0 deletions src/Compiler/Template.php
Original file line number Diff line number Diff line change
Expand Up @@ -1369,6 +1369,11 @@ public function compileFunctionCall(string $base_tag, array $args, array $parame
return $this->functionCallCompiler->compile($args, $this, $parameter, $base_tag, $base_tag);
}

public function compileModifierInExpression(string $function, array $_attr) {
$value = array_shift($_attr);
return $this->compileModifier([array_merge([$function], $_attr)], $value);
}

/**
* @return TemplateParser|null
*/
Expand Down
25 changes: 21 additions & 4 deletions src/Extension/DefaultExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace Smarty\Extension;

use Smarty\Exception;

class DefaultExtension extends Base {

private $modifiers = [];
Expand All @@ -27,6 +29,7 @@ public function getModifierCompiler(string $modifier): ?\Smarty\Compile\Modifier
case 'escape': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\EscapeModifierCompiler(); 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 'is_array': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\IsArrayModifierCompiler(); 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;
Expand Down Expand Up @@ -57,6 +60,7 @@ public function getModifierCallback(string $modifierName) {
case 'escape': return [$this, 'smarty_modifier_escape'];
case 'explode': return [$this, 'smarty_modifier_explode'];
case 'implode': return [$this, 'smarty_modifier_implode'];
case 'in_array': return [$this, 'smarty_modifier_in_array'];
case 'join': return [$this, 'smarty_modifier_join'];
case 'mb_wordwrap': return [$this, 'smarty_modifier_mb_wordwrap'];
case 'number_format': return [$this, 'smarty_modifier_number_format'];
Expand Down Expand Up @@ -87,12 +91,8 @@ public function getFunctionHandler(string $functionName): ?\Smarty\FunctionHandl
case 'html_select_date': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\HtmlSelectDate(); break;
case 'html_select_time': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\HtmlSelectTime(); break;
case 'html_table': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\HtmlTable(); break;
case 'in_array': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\InArray(); break;
case 'is_array': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\IsArray(); break;
case 'mailto': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\Mailto(); break;
case 'math': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\Math(); break;
case 'strlen': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\Strlen(); break;
case 'time': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\Time(); break;
}

return $this->functionHandlers[$functionName] ?? null;
Expand Down Expand Up @@ -570,6 +570,23 @@ public function smarty_modifier_implode($values, $separator = '')
return implode((string) ($separator ?? ''), (array) $values);
}

/**
* Smarty in_array modifier plugin
* Type: modifier
* Name: in_array
* Purpose: test if value is contained in an array
*
* @param mixed $needle
* @param array $array
* @param bool $strict
*
* @return bool
*/
public function smarty_modifier_in_array($needle, $array, $strict = false)
{
return in_array($needle, (array) $array, (bool) $strict);
}

/**
* Smarty join modifier plugin
* Type: modifier
Expand Down
30 changes: 0 additions & 30 deletions src/FunctionHandler/InArray.php

This file was deleted.

21 changes: 0 additions & 21 deletions src/FunctionHandler/IsArray.php

This file was deleted.

28 changes: 0 additions & 28 deletions src/FunctionHandler/Strlen.php

This file was deleted.

21 changes: 0 additions & 21 deletions src/FunctionHandler/Time.php

This file was deleted.

2 changes: 1 addition & 1 deletion src/Parser/TemplateParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -2675,7 +2675,7 @@ public function yy_r147(){
}
// line 1063 "src/Parser/TemplateParser.y"
public function yy_r148(){
$this->_retvalue = $this->compiler->compileFunctionCall($this->yystack[$this->yyidx + -3]->minor, $this->yystack[$this->yyidx + -1]->minor);
$this->_retvalue = $this->compiler->compileModifierInExpression($this->yystack[$this->yyidx + -3]->minor, $this->yystack[$this->yyidx + -1]->minor);
}
// line 1071 "src/Parser/TemplateParser.y"
public function yy_r149(){
Expand Down
2 changes: 1 addition & 1 deletion src/Parser/TemplateParser.y
Original file line number Diff line number Diff line change
Expand Up @@ -1061,7 +1061,7 @@ objectelement(res)::= PTR method(f). {
// function
//
function(res) ::= ns1(f) OPENP params(p) CLOSEP. {
res = $this->compiler->compileFunctionCall(f, p);
res = $this->compiler->compileModifierInExpression(f, p);
}


Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ public function testEmpty2()
public function testEmpty3()
{
$this->smarty->disableSecurity();
$this->getSmarty()->registerPlugin(\Smarty\Smarty::PLUGIN_FUNCTION, 'pass', function ($v) { return $v; });
$this->getSmarty()->registerPlugin(\Smarty\Smarty::PLUGIN_MODIFIER, 'pass', function ($v) { return $v; });
$this->smarty->assign('var', array(true,
(int) 1,
(float) 0.1,
Expand All @@ -99,7 +99,7 @@ public function testEmpty3()
public function testEmpty4()
{
$this->smarty->disableSecurity();
$this->getSmarty()->registerPlugin(\Smarty\Smarty::PLUGIN_FUNCTION, 'pass', function ($v) { return $v; });
$this->getSmarty()->registerPlugin(\Smarty\Smarty::PLUGIN_MODIFIER, 'pass', function ($v) { return $v; });
$this->smarty->assign('var', new TestIsset());
$expected = ' true , false , false , true , true , true , false ';
$this->assertEquals($expected, $this->smarty->fetch('string:{strip}{if empty($var->isNull)} true {else} false {/IF}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

class TooManyShorthandAttributes949Test extends PHPUnit_Smarty
{

public function testPregMatchAll() {
$smarty = new \Smarty\Smarty();
$smarty->registerPlugin('modifier', 'var_dump', 'var_dump');
$templateStr = "eval:{\$a = 'blah'}{\$b = array()}{if var_dump('', \$a, \$b, 2)|noprint}blah{else}nah{/if}";
$this->assertEquals(
'nah',
$smarty->fetch($templateStr)
);
}

}
Loading