From fd64cc688ad6a88bb7ed5494841a48037a1a4eff Mon Sep 17 00:00:00 2001 From: Simon Wisselink Date: Sat, 7 Jan 2023 23:06:47 +0100 Subject: [PATCH] Removed PHP functions and checks for the already removed php modifiers. Re-implemented functions as regular functions. Probably should compile these directly. --- .../language-function-if.md | 4 - .../advanced-features-security.md | 23 +----- src/Compile/FunctionCallCompiler.php | 16 +++- src/Compiler/Template.php | 81 +++---------------- src/Extension/DefaultExtension.php | 6 ++ src/FunctionHandler/Count.php | 36 +++++++++ src/FunctionHandler/EmptyHandler.php | 27 +++++++ src/FunctionHandler/InArray.php | 30 +++++++ src/FunctionHandler/IsArray.php | 21 +++++ src/FunctionHandler/IssetHandler.php | 30 +++++++ src/FunctionHandler/Time.php | 21 +++++ src/Parser/TemplateParser.y | 4 +- src/Security.php | 76 ----------------- tests/PHPUnit_Smarty.php | 2 +- .../UnitTests/SecurityTests/SecurityTest.php | 41 +--------- .../TagTests/PluginFunction/CountTest.php | 28 +++++++ .../TagTests/PluginFunction/EmptyTest.php | 44 ++++++++++ .../TagTests/PluginFunction/InArrayTest.php | 27 +++++++ .../TagTests/PluginFunction/IsArrayTest.php | 28 +++++++ .../TagTests/PluginFunction/IssetTest.php | 45 +++++++++++ .../TagTests/PluginFunction/TimeTest.php | 20 +++++ 21 files changed, 393 insertions(+), 217 deletions(-) create mode 100644 src/FunctionHandler/Count.php create mode 100644 src/FunctionHandler/EmptyHandler.php create mode 100644 src/FunctionHandler/InArray.php create mode 100644 src/FunctionHandler/IsArray.php create mode 100644 src/FunctionHandler/IssetHandler.php create mode 100644 src/FunctionHandler/Time.php create mode 100644 tests/UnitTests/TemplateSource/TagTests/PluginFunction/CountTest.php create mode 100644 tests/UnitTests/TemplateSource/TagTests/PluginFunction/EmptyTest.php create mode 100644 tests/UnitTests/TemplateSource/TagTests/PluginFunction/InArrayTest.php create mode 100644 tests/UnitTests/TemplateSource/TagTests/PluginFunction/IsArrayTest.php create mode 100644 tests/UnitTests/TemplateSource/TagTests/PluginFunction/IssetTest.php create mode 100644 tests/UnitTests/TemplateSource/TagTests/PluginFunction/TimeTest.php diff --git a/docs/designers/language-builtin-functions/language-function-if.md b/docs/designers/language-builtin-functions/language-function-if.md index 2c1d68ee..7e48a958 100644 --- a/docs/designers/language-builtin-functions/language-function-if.md +++ b/docs/designers/language-builtin-functions/language-function-if.md @@ -8,10 +8,6 @@ template engine. Every `{if}` must be paired with a matching `{/if}`. functions are recognized, such as *\|\|*, *or*, *&&*, *and*, *is\_array()*, etc. -If securty is enabled, only PHP functions from `$php_functions` property -of the securty policy are allowed. See the -[Security](#advanced.features.security) section for details. - The following is a list of recognized qualifiers, which must be separated from surrounding elements by spaces. Note that items listed in \[brackets\] are optional. PHP equivalents are shown where applicable. diff --git a/docs/programmers/advanced-features/advanced-features-security.md b/docs/programmers/advanced-features/advanced-features-security.md index eeea8e56..51010125 100644 --- a/docs/programmers/advanced-features/advanced-features-security.md +++ b/docs/programmers/advanced-features/advanced-features-security.md @@ -53,19 +53,6 @@ instance of the Smarty\_Security class. These are the possible settings: static classes. To disable access to all static classes set \$static\_classes = null. -- `$php_functions` is an array of PHP functions that are considered - trusted and can be used from within template. To disable access to - all PHP functions set \$php\_functions = null. An empty array ( - \$php\_functions = array() ) will allow all PHP functions. The - default is array(\'isset\', \'empty\', \'count\', \'sizeof\', - \'in\_array\', \'is\_array\',\'time\',\'nl2br\'). - -- `$php_modifiers` is an array of PHP functions that are considered - trusted and can be used from within template as modifier. To disable - access to all PHP modifier set \$php\_modifier = null. An empty - array ( \$php\_modifier = array() ) will allow all PHP functions. - The default is array(\'escape\',\'count\'). - - `$streams` is an array of streams that are considered trusted and can be used from within template. To disable access to all streams set \$streams = null. An empty array ( \$streams = array() ) will @@ -105,10 +92,7 @@ Smarty\_Security class or create an instance of it. php_functions = null; - // allow everthing as modifier - $my_security_policy->php_modifiers = array(); + $my_security_policy->allow_constants = false; // enable security $smarty->enableSecurity($my_security_policy); ?> diff --git a/src/Compile/FunctionCallCompiler.php b/src/Compile/FunctionCallCompiler.php index 3e3a3217..655213a2 100644 --- a/src/Compile/FunctionCallCompiler.php +++ b/src/Compile/FunctionCallCompiler.php @@ -11,6 +11,7 @@ namespace Smarty\Compile; use Smarty\Compiler\Template; +use Smarty\CompilerException; /** * Smarty Internal Plugin Compile Registered Function Class @@ -28,6 +29,13 @@ class FunctionCallCompiler extends Base { */ public $optional_attributes = ['_any']; + /** + * Shorttag attribute order defined by its names + * + * @var array + */ + protected $shorttag_order = ['var1', 'var2', 'var3']; + /** * Compiles code for the execution of a registered function * @@ -42,12 +50,14 @@ class FunctionCallCompiler extends Base { * @throws \Smarty\Exception */ public function compile($args, Template $compiler, $parameter = [], $tag = null, $function = null) { + // check and get attributes $_attr = $this->getAttributes($compiler, $args); unset($_attr['nocache']); - - $functionHandler = $compiler->smarty->getFunctionHandler($function); + if (!$functionHandler = $compiler->smarty->getFunctionHandler($function)) { + throw new CompilerException("Cannot compile unknown function $function."); + } // not cacheable? $compiler->tag_nocache = $compiler->tag_nocache || !$functionHandler->isCacheable(); @@ -65,6 +75,6 @@ class FunctionCallCompiler extends Base { if (!empty($parameter['modifierlist'])) { $output = $compiler->compileModifier($parameter['modifierlist'], $output); } - return "\n"; + return $output; } } diff --git a/src/Compiler/Template.php b/src/Compiler/Template.php index b4de6de4..72157cb1 100644 --- a/src/Compiler/Template.php +++ b/src/Compiler/Template.php @@ -529,77 +529,6 @@ class Template extends BaseCompiler { return '$_smarty_tpl->getConfigVariable(' . $variable . ')'; } - /** - * compile PHP function call - * - * @param string $name - * @param array $parameter - * - * @return string - * @throws \Smarty\CompilerException - */ - public function compilePHPFunctionCall($name, $parameter) { - if (!$this->smarty->security_policy || $this->smarty->security_policy->isTrustedPhpFunction($name, $this)) { - if (strcasecmp($name, 'isset') === 0 || strcasecmp($name, 'empty') === 0 - || strcasecmp($name, 'array') === 0 || is_callable($name) - ) { - $func_name = smarty_strtolower_ascii($name); - - if ($func_name === 'isset') { - if (count($parameter) === 0) { - $this->trigger_template_error('Illegal number of parameter in "isset()"'); - } - - $pa = []; - foreach ($parameter as $p) { - $pa[] = $this->syntaxMatchesVariable($p) ? 'isset(' . $p . ')' : '(' . $p . ' !== null )'; - } - return '(' . implode(' && ', $pa) . ')'; - - } elseif (in_array( - $func_name, - [ - 'empty', - 'reset', - 'current', - 'end', - 'prev', - 'next', - ] - ) - ) { - if (count($parameter) !== 1) { - $this->trigger_template_error("Illegal number of parameter in '{$func_name()}'"); - } - if ($func_name === 'empty') { - return $func_name . '(' . - str_replace("')->value", "',null,true,false)->value", $parameter[0]) . ')'; - } else { - return $func_name . '(' . $parameter[0] . ')'; - } - } else { - return $name . '(' . implode(',', $parameter) . ')'; - } - } else { - $this->trigger_template_error("unknown function '{$name}'"); - } - } - } - - /** - * Determines whether the passed string represents a valid (PHP) variable. - * This is important, because `isset()` only works on variables and `empty()` can only be passed - * a variable prior to php5.5 - * - * @param $string - * - * @return bool - */ - private function syntaxMatchesVariable($string) { - static $regex_pattern = '/^\$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*((->)[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*|\[.*]*\])*$/'; - return 1 === preg_match($regex_pattern, trim($string)); - } - /** * This method is called from parser to process a text content section if strip is enabled * - remove text from inheritance child templates as they may generate output @@ -1278,7 +1207,11 @@ class Template extends BaseCompiler { // check if tag is a function if ($this->smarty->getFunctionHandler($base_tag)) { if (!isset($this->smarty->security_policy) || $this->smarty->security_policy->isTrustedTag($base_tag, $this)) { - return $this->functionCallCompiler->compile($args, $this, $parameter, $tag, $base_tag); + return (new \Smarty\Compile\PrintExpressionCompiler())->compile( + [], + $this, + ['value' => $this->compileFunctionCall($base_tag, $args, $parameter)] + ); } } @@ -1483,4 +1416,8 @@ class Template extends BaseCompiler { ); } + public function compileFunctionCall(string $base_tag, array $args, array $parameter = []) { + return $this->functionCallCompiler->compile($args, $this, $parameter, $base_tag, $base_tag); + } + } diff --git a/src/Extension/DefaultExtension.php b/src/Extension/DefaultExtension.php index b0ba4cb7..d8903485 100644 --- a/src/Extension/DefaultExtension.php +++ b/src/Extension/DefaultExtension.php @@ -69,8 +69,10 @@ class DefaultExtension extends Base { } switch ($functionName) { + case 'count': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\Count(); break; case 'counter': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\Counter(); break; case 'cycle': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\Cycle(); break; + case 'empty': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\EmptyHandler(); break; case 'fetch': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\Fetch(); break; case 'html_checkboxes': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\HtmlCheckboxes(); break; case 'html_image': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\HtmlImage(); break; @@ -79,8 +81,12 @@ class DefaultExtension extends Base { 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 'isset': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\IssetHandler(); break; case 'mailto': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\Mailto(); break; case 'math': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\Math(); break; + case 'time': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\Time(); break; } return $this->functionHandlers[$functionName] ?? null; diff --git a/src/FunctionHandler/Count.php b/src/FunctionHandler/Count.php new file mode 100644 index 00000000..c1241f7b --- /dev/null +++ b/src/FunctionHandler/Count.php @@ -0,0 +1,36 @@ + 2) { + throw new Exception("Invalid number of arguments for in_array. in_arrays expects 2 or 3 parameters."); + } + + $value = $params[0]; + + if ($value instanceof \Countable) { + return $value->count(); + } + + $mode = count($params) == 2 ? (int) $params[1] : COUNT_NORMAL; + return count((array) $value, $mode); + } + +} \ No newline at end of file diff --git a/src/FunctionHandler/EmptyHandler.php b/src/FunctionHandler/EmptyHandler.php new file mode 100644 index 00000000..3a89ab3b --- /dev/null +++ b/src/FunctionHandler/EmptyHandler.php @@ -0,0 +1,27 @@ + 3) { + throw new Exception("Invalid number of arguments for in_array. in_arrays expects 2 or 3 parameters."); + } + + // default to false, true if param 3 is set to true + $needle = $params[0]; + $haystack = (array) $params[1]; + $strict = count($params) == 3 && $params[2]; + + return in_array($needle, $haystack, $strict); + } + +} \ No newline at end of file diff --git a/src/FunctionHandler/IsArray.php b/src/FunctionHandler/IsArray.php new file mode 100644 index 00000000..06cd585d --- /dev/null +++ b/src/FunctionHandler/IsArray.php @@ -0,0 +1,21 @@ + 0) { + throw new Exception("Invalid number of arguments for time. time expects no parameters."); + } + return time(); + } + +} \ No newline at end of file diff --git a/src/Parser/TemplateParser.y b/src/Parser/TemplateParser.y index f688dbb3..b5c58c14 100644 --- a/src/Parser/TemplateParser.y +++ b/src/Parser/TemplateParser.y @@ -1037,7 +1037,7 @@ objectelement(res)::= PTR method(f). { // function // function(res) ::= ns1(f) OPENP params(p) CLOSEP. { - res = $this->compiler->compilePHPFunctionCall(f, p); + res = $this->compiler->compileFunctionCall(f, p); } @@ -1071,7 +1071,7 @@ params(res) ::= expr(e). { res = array(e); } - // kein parameter + // no parameter params(res) ::= . { res = array(); } diff --git a/src/Security.php b/src/Security.php index 4385e276..c1c4ecca 100644 --- a/src/Security.php +++ b/src/Security.php @@ -94,24 +94,6 @@ class Security { */ public $trusted_static_properties = []; - /** - * This is an array of trusted PHP functions. - * If empty all functions are allowed. - * To disable all PHP functions set $php_functions = null. - * - * @var array - */ - public $php_functions = ['isset', 'empty', 'count', 'sizeof', 'in_array', 'is_array', 'time',]; - - /** - * This is an array of trusted PHP modifiers. - * If empty all modifiers are allowed. - * To disable all modifier set $php_modifiers = null. - * - * @var array - */ - public $php_modifiers = ['escape', 'count', 'sizeof', 'nl2br',]; - /** * This is an array of allowed tags. * If empty no restriction by allowed_tags. @@ -216,27 +198,6 @@ class Security { */ protected $_secure_dir = []; - /** - * Cache for $php_resource_dir lookup - * - * @var array - */ - protected $_php_resource_dir = null; - - /** - * Cache for $trusted_dir lookup - * - * @var array - */ - protected $_trusted_dir = null; - - /** - * Cache for $_include_array lookup - * - * @var array - */ - protected $_include_dir = []; - /** * @param Smarty $smarty */ @@ -244,24 +205,6 @@ class Security { $this->smarty = $smarty; } - /** - * Check if PHP function is trusted. - * - * @param string $function_name - * @param object $compiler compiler object - * - * @return boolean true if function is trusted - */ - public function isTrustedPhpFunction($function_name, $compiler) { - if (isset($this->php_functions) - && (empty($this->php_functions) || in_array($function_name, $this->php_functions)) - ) { - return true; - } - $compiler->trigger_template_error("PHP function '{$function_name}' not allowed by security setting"); - return false; // should not, but who knows what happens to the compiler in the future? - } - /** * Check if static class is trusted. * @@ -317,25 +260,6 @@ class Security { return false; // should not, but who knows what happens to the compiler in the future? } - /** - * Check if PHP modifier is trusted. - * - * @param string $modifier_name - * @param object $compiler compiler object - * - * @return boolean true if modifier is trusted - * @deprecated - */ - public function isTrustedPhpModifier($modifier_name, $compiler) { - if (isset($this->php_modifiers) - && (empty($this->php_modifiers) || in_array($modifier_name, $this->php_modifiers)) - ) { - return true; - } - $compiler->trigger_template_error("modifier '{$modifier_name}' not allowed by security setting"); - return false; // should not, but who knows what happens to the compiler in the future? - } - /** * Check if tag is trusted. * diff --git a/tests/PHPUnit_Smarty.php b/tests/PHPUnit_Smarty.php index 3e3dab7c..b8d45a51 100644 --- a/tests/PHPUnit_Smarty.php +++ b/tests/PHPUnit_Smarty.php @@ -64,7 +64,7 @@ class PHPUnit_Smarty extends PHPUnit\Framework\TestCase */ public static function setUpBeforeClass(): void { - error_reporting(E_ALL & ~E_STRICT); + error_reporting(E_ALL & ~E_STRICT & ~E_DEPRECATED & ~E_USER_DEPRECATED); self::$init = true; self::$pluginsdir =self::getSmartyPluginsDir(); } diff --git a/tests/UnitTests/SecurityTests/SecurityTest.php b/tests/UnitTests/SecurityTests/SecurityTest.php index 99ad953f..ab560c4c 100644 --- a/tests/UnitTests/SecurityTests/SecurityTest.php +++ b/tests/UnitTests/SecurityTests/SecurityTest.php @@ -40,32 +40,9 @@ class SecurityTest extends PHPUnit_Smarty /** * test trusted PHP function */ - public function testTrustedPHPFunction() + public function testTrustedFunction() { - $this->assertEquals("5", $this->smarty->fetch('string:{assign var=foo value=[1,2,3,4,5]}{sizeof($foo)}')); - } - -/** - * test not trusted PHP function - * - * - */ - public function testNotTrustedPHPFunction() - { - $this->expectException(\Smarty\Exception::class); - $this->expectExceptionMessage('PHP function \'sizeof\' not allowed by security setting'); - $this->smarty->security_policy->php_functions = array('null'); - $this->smarty->fetch('string:{assign var=foo value=[1,2,3,4,5]}{sizeof($foo)}'); - } - -/** - * test not trusted PHP function at disabled security - */ - public function testDisabledTrustedPHPFunction() - { - $this->smarty->security_policy->php_functions = array('null'); - $this->smarty->disableSecurity(); - $this->assertEquals("5", $this->smarty->fetch('string:{assign var=foo value=[1,2,3,4,5]}{sizeof($foo)}')); + $this->assertEquals("5", $this->smarty->fetch('string:{assign var=foo value=[1,2,3,4,5]}{count($foo)}')); } /** @@ -74,7 +51,7 @@ class SecurityTest extends PHPUnit_Smarty */ public function testTrustedModifier() { - $this->assertEquals("5", @$this->smarty->fetch('string:{assign var=foo value=[1,2,3,4,5]}{$foo|@sizeof}')); + $this->assertEquals("5", @$this->smarty->fetch('string:{assign var=foo value=[1,2,3,4,5]}{$foo|@count}')); } /** @@ -87,21 +64,9 @@ class SecurityTest extends PHPUnit_Smarty { $this->expectException(\Smarty\Exception::class); $this->expectExceptionMessage('modifier \'sizeof\' not allowed by security setting'); - $this->smarty->security_policy->php_modifiers = array('null'); @$this->smarty->fetch('string:{assign var=foo value=[1,2,3,4,5]}{$foo|@sizeof}'); } -/** - * test not trusted modifier at disabled security - * @deprecated - */ - public function testDisabledTrustedModifier() - { - $this->smarty->security_policy->php_modifiers = array('null'); - $this->smarty->disableSecurity(); - @$this->assertEquals("5", $this->smarty->fetch('string:{assign var=foo value=[1,2,3,4,5]}{$foo|@sizeof}')); - } - /** * test allowed tags */ diff --git a/tests/UnitTests/TemplateSource/TagTests/PluginFunction/CountTest.php b/tests/UnitTests/TemplateSource/TagTests/PluginFunction/CountTest.php new file mode 100644 index 00000000..b4e78c48 --- /dev/null +++ b/tests/UnitTests/TemplateSource/TagTests/PluginFunction/CountTest.php @@ -0,0 +1,28 @@ +setUpSmarty(__DIR__); + } + + public function testBasicSyntax() { + $this->assertEquals('3', $this->smarty->fetch("string:{count([1,2,3])}")); + } + + public function testNonRecursive() { + $this->assertEquals('3', $this->smarty->fetch("string:{count([1,2,[3,4]])}")); + } + + public function testRecursive() { + $this->assertEquals('5', $this->smarty->fetch("string:{count([1,2,[3,4]], 1)}")); + } + + public function testInvalidParameters() { + $this->expectException(\Smarty\Exception::class); + $this->expectExceptionMessage('Invalid number of arguments'); + $this->assertEquals("", $this->smarty->fetch("string:{count()}")); + } + +} \ No newline at end of file diff --git a/tests/UnitTests/TemplateSource/TagTests/PluginFunction/EmptyTest.php b/tests/UnitTests/TemplateSource/TagTests/PluginFunction/EmptyTest.php new file mode 100644 index 00000000..2e73db63 --- /dev/null +++ b/tests/UnitTests/TemplateSource/TagTests/PluginFunction/EmptyTest.php @@ -0,0 +1,44 @@ +setUpSmarty(__DIR__); + } + + public function testBasicSyntax() { + $this->assertEquals("yay", $this->smarty->fetch("string:{if empty(\$noSuch)}yay{/if}")); + } + + public function testEmptyStringIsEmpty() { + $this->assertEquals("yay", $this->smarty->fetch("string:{if empty('')}yay{/if}")); + } + + public function testFalseIsEmpty() { + $this->smarty->assign('test', false); + $this->assertEquals("yay", $this->smarty->fetch("string:{if empty(\$test)}yay{/if}")); + } + + public function testIntZeroIsEmpty() { + $this->smarty->assign('test', 0); + $this->assertEquals("yay", $this->smarty->fetch("string:{if empty(\$test)}yay{/if}")); + } + + public function testStringZeroIsEmpty() { + $this->smarty->assign('test', '0'); + $this->assertEquals("yay", $this->smarty->fetch("string:{if empty(\$test)}yay{/if}")); + } + + public function testIntThreeIsNotEmpty() { + $this->smarty->assign('test', 3); + $this->assertEquals("nay", $this->smarty->fetch("string:{if empty(\$test)}yay{else}nay{/if}")); + } + + public function testInvalidParameters() { + $this->expectException(\Smarty\Exception::class); + $this->expectExceptionMessage('Invalid number of arguments'); + $this->assertEquals("", $this->smarty->fetch("string:{empty(3, 'foo')}")); + } + +} \ No newline at end of file diff --git a/tests/UnitTests/TemplateSource/TagTests/PluginFunction/InArrayTest.php b/tests/UnitTests/TemplateSource/TagTests/PluginFunction/InArrayTest.php new file mode 100644 index 00000000..b27c2585 --- /dev/null +++ b/tests/UnitTests/TemplateSource/TagTests/PluginFunction/InArrayTest.php @@ -0,0 +1,27 @@ +setUpSmarty(__DIR__); + } + + public function testBasicSyntax() + { + $this->assertEquals("yay", $this->smarty->fetch("string:{if in_array(3,[3])}yay{/if}")); + } + + public function testNotInArray() + { + $this->assertEquals("nay", $this->smarty->fetch("string:{if in_array(2,[3])}yay{else}nay{/if}")); + } + + public function testInvalidParameters() + { + $this->expectException(\Smarty\Exception::class); + $this->expectExceptionMessage('Invalid number of arguments'); + $this->assertEquals("", $this->smarty->fetch("string:{in_array('foo')}")); + } + +} \ No newline at end of file diff --git a/tests/UnitTests/TemplateSource/TagTests/PluginFunction/IsArrayTest.php b/tests/UnitTests/TemplateSource/TagTests/PluginFunction/IsArrayTest.php new file mode 100644 index 00000000..65731d27 --- /dev/null +++ b/tests/UnitTests/TemplateSource/TagTests/PluginFunction/IsArrayTest.php @@ -0,0 +1,28 @@ +setUpSmarty(__DIR__); + } + + public function testBasicSyntax() { + $this->assertEquals("yay", $this->smarty->fetch("string:{if is_array([3])}yay{/if}")); + } + + public function testIntNotIsArray() { + $this->assertEquals("nay", $this->smarty->fetch("string:{if is_array(2)}yay{else}nay{/if}")); + } + + public function testStringNotIsArray() { + $this->assertEquals("nay", $this->smarty->fetch("string:{if is_array('foo')}yay{else}nay{/if}")); + } + + public function testInvalidParameters() { + $this->expectException(\Smarty\Exception::class); + $this->expectExceptionMessage('Invalid number of arguments'); + $this->assertEquals("", $this->smarty->fetch("string:{is_array(3, 'foo')}")); + } + +} \ No newline at end of file diff --git a/tests/UnitTests/TemplateSource/TagTests/PluginFunction/IssetTest.php b/tests/UnitTests/TemplateSource/TagTests/PluginFunction/IssetTest.php new file mode 100644 index 00000000..a27c7e71 --- /dev/null +++ b/tests/UnitTests/TemplateSource/TagTests/PluginFunction/IssetTest.php @@ -0,0 +1,45 @@ +setUpSmarty(__DIR__); + } + + public function testBasicSyntax() { + $this->assertEquals("nay", $this->smarty->fetch("string:{if isset(\$noSuch)}yay{else}nay{/if}")); + } + + public function testEmptyStringIsset() { + $this->assertEquals("yay", $this->smarty->fetch("string:{if isset('')}yay{/if}")); + } + + public function testFalseIsset() { + $this->smarty->assign('test', false); + $this->assertEquals("yay", $this->smarty->fetch("string:{if isset(\$test)}yay{/if}")); + } + + public function testIntZeroIsset() { + $this->smarty->assign('test', 0); + $this->assertEquals("yay", $this->smarty->fetch("string:{if isset(\$test)}yay{/if}")); + } + + public function testMultivar() { + $this->smarty->assign('test', 0); + $this->smarty->assign('test2', 'pizza'); + $this->assertEquals("yay", $this->smarty->fetch("string:{if isset(\$test, \$test2)}yay{/if}")); + } + + public function testMultivarOneNotset() { + $this->smarty->assign('test', 0); + $this->assertEquals("nay", $this->smarty->fetch("string:{if isset(\$test, \$test2)}yay{else}nay{/if}")); + } + + public function testInvalidParameters() { + $this->expectException(\Smarty\Exception::class); + $this->expectExceptionMessage('Invalid number of arguments'); + $this->assertEquals("", $this->smarty->fetch("string:{empty(3, 'foo')}")); + } + +} \ No newline at end of file diff --git a/tests/UnitTests/TemplateSource/TagTests/PluginFunction/TimeTest.php b/tests/UnitTests/TemplateSource/TagTests/PluginFunction/TimeTest.php new file mode 100644 index 00000000..d64fd92d --- /dev/null +++ b/tests/UnitTests/TemplateSource/TagTests/PluginFunction/TimeTest.php @@ -0,0 +1,20 @@ +setUpSmarty(__DIR__); + } + + public function testBasicSyntax() { + $this->assertStringMatchesFormat('%d', $this->smarty->fetch("string:{time()}")); + } + + public function testInvalidParameters() { + $this->expectException(\Smarty\Exception::class); + $this->expectExceptionMessage('Invalid number of arguments'); + $this->assertEquals("", $this->smarty->fetch("string:{time(3, 'foo')}")); + } + +} \ No newline at end of file