Compare commits

..

2 Commits

60 changed files with 1580 additions and 1579 deletions
-15
View File
@@ -6,21 +6,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
## [5.1.0] - 2024-04-22
- Prevent deprecation notices during compilation in PHP8.3 [#996](https://github.com/smarty-php/smarty/issues/996)
- Fix that getTemplateVars would return an array of objects instead of the assigned variables values [#994](https://github.com/smarty-php/smarty/issues/994)
- Fix Smarty::assign() not returning $this when called with an array as first parameter [#972](https://github.com/smarty-php/smarty/pull/972)
- Documented support for `{if $element is in $array}` syntax [#937](https://github.com/smarty-php/smarty/issues/937)
- Added support for `{if $element is not in $array}` syntax [#937](https://github.com/smarty-php/smarty/issues/937)
- Using stream variables in templates now throws a deprecation notice [#933](https://github.com/smarty-php/smarty/pull/933)
- Internal compiler classes always return a string (the internal has_code flag has been removed for simplicity) [#918](https://github.com/smarty-php/smarty/pull/918)
- Fix invalid classnames in Runtime code for foreach [#1000](https://github.com/smarty-php/smarty/issues/1000)
## [5.0.1] - 2024-03-27
- Fix error in Smarty\Smarty::compileAllTemplates() by including missing FilesystemIterator class [#966](https://github.com/smarty-php/smarty/issues/966)
## [5.0.0] - 2024-03-25
- Fixed that scoped variables would overwrite parent scope [#952](https://github.com/smarty-php/smarty/issues/952)
- Removed publicly accessible `$tpl->_var_stack` variable
+1
View File
@@ -0,0 +1 @@
- Internal compiler classes always return a string (the internal has_code flag has been removed for simplicity) [#918](https://github.com/smarty-php/smarty/pull/918)
-3
View File
@@ -10,7 +10,4 @@ template.
{$foo:bar}
```
NB. Support for using streams to call variables is deprecated since Smarty v5.1 and will be removed
in a future version.
See also [`Template Resources`](../resources.md)
@@ -27,30 +27,6 @@ Various basic operators can be applied directly to variable values.
> complex, it may be a good idea to move the bits that do not deal
> explicitly with presentation to PHP by way of plugins or modifiers.
## List
The following is a list of recognized operators, which must be
separated from surrounding elements by spaces. Note that items listed in
\[brackets\] are optional. PHP equivalents are shown where applicable.
| Operator | Alternates | Syntax Example | Meaning | PHP Equivalent |
|--------------------|------------|----------------------|--------------------------------|--------------------|
| == | eq | $a eq $b | equals | == |
| != | ne, neq | $a neq $b | not equals | != |
| > | gt | $a gt $b | greater than | > |
| < | lt | $a lt $b | less than | < |
| >= | gte, ge | $a ge $b | greater than or equal | >= |
| <= | lte, le | $a le $b | less than or equal | <= |
| === | | $a === 0 | check for identity | === |
| ! | not | not $a | negation (unary) | ! |
| % | mod | $a mod $b | modulo | % |
| is \[not\] div by | | $a is not div by 4 | divisible by | $a % $b == 0 |
| is \[not\] even | | $a is not even | \[not\] an even number (unary) | $a % 2 == 0 |
| is \[not\] even by | | $a is not even by $b | grouping level \[not\] even | ($a / $b) % 2 == 0 |
| is \[not\] odd | | $a is not odd | \[not\] an odd number (unary) | $a % 2 != 0 |
| is \[not\] odd by | | $a is not odd by $b | \[not\] an odd grouping | ($a / $b) % 2 != 0 |
| is in | | $a is in $b | exists in array | in_array($a, $b) |
| is \[not\] in | | $a is not in $b | does not exist in array | !in_array($a, $b) |
## Ternary
You can use the `?:` (or ternary) operator to test one expression and present the value
of the second or third expression, based on the result of the test.
@@ -3,8 +3,32 @@
`{if}` statements in Smarty have much the same flexibility as PHP
[if](https://www.php.net/if) statements, with a few added features for the
template engine. Every `{if}` must be paired with a matching `{/if}`.
`{else}` and `{elseif}` are also permitted. All [operators](../language-basic-syntax/language-syntax-operators.md) are recognized, such as *==*,
*\|\|*, *or*, *&&*, *and*, etc and you can use modifiers as functions, such as *is_array()*.
`{else}` and `{elseif}` are also permitted. All PHP conditionals and
functions are recognized, such as *\|\|*, *or*, *&&*, *and*,
*is_array()*, etc.
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.
## Qualifiers
| Qualifier | Alternates | Syntax Example | Meaning | PHP Equivalent |
|--------------------|------------|----------------------|--------------------------------|--------------------|
| == | eq | $a eq $b | equals | == |
| != | ne, neq | $a neq $b | not equals | != |
| > | gt | $a gt $b | greater than | > |
| < | lt | $a lt $b | less than | < |
| >= | gte, ge | $a ge $b | greater than or equal | >= |
| <= | lte, le | $a le $b | less than or equal | <= |
| === | | $a === 0 | check for identity | === |
| ! | not | not $a | negation (unary) | ! |
| % | mod | $a mod $b | modulo | % |
| is \[not\] div by | | $a is not div by 4 | divisible by | $a % $b == 0 |
| is \[not\] even | | $a is not even | \[not\] an even number (unary) | $a % 2 == 0 |
| is \[not\] even by | | $a is not even by $b | grouping level \[not\] even | ($a / $b) % 2 == 0 |
| is \[not\] odd | | $a is not odd | \[not\] an odd number (unary) | $a % 2 != 0 |
| is \[not\] odd by | | $a is not odd by $b | \[not\] an odd grouping | ($a / $b) % 2 != 0 |
## Examples
```smarty
@@ -3,8 +3,31 @@
`{while}` loops in Smarty have much the same flexibility as PHP
[while](https://www.php.net/while) statements, with a few added features for
the template engine. Every `{while}` must be paired with a matching
`{/while}`. All [operators](../language-basic-syntax/language-syntax-operators.md) are recognized, such as *==*,
*\|\|*, *or*, *&&*, *and*, etc and you can use modifiers as functions, such as *is_array()*.
`{/while}`. All PHP conditionals and functions are recognized, such as
*\|\|*, *or*, *&&*, *and*, *is_array()*, etc.
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.
## Qualifiers
| Qualifier | Alternates | Syntax Example | Meaning | PHP Equivalent |
|--------------------|------------|----------------------|--------------------------------|--------------------|
| == | eq | $a eq $b | equals | == |
| != | ne, neq | $a neq $b | not equals | != |
| > | gt | $a gt $b | greater than | > |
| < | lt | $a lt $b | less than | < |
| >= | gte, ge | $a ge $b | greater than or equal | >= |
| <= | lte, le | $a le $b | less than or equal | <= |
| === | | $a === 0 | check for identity | === |
| ! | not | not $a | negation (unary) | ! |
| % | mod | $a mod $b | modulo | % |
| is \[not\] div by | | $a is not div by 4 | divisible by | $a % $b == 0 |
| is \[not\] even | | $a is not even | \[not\] an even number (unary) | $a % 2 == 0 |
| is \[not\] even by | | $a is not even by $b | grouping level \[not\] even | ($a / $b) % 2 == 0 |
| is \[not\] odd | | $a is not odd | \[not\] an odd number (unary) | $a % 2 != 0 |
| is \[not\] odd by | | $a is not odd by $b | \[not\] an odd grouping | ($a / $b) % 2 != 0 |
## Examples
```smarty
@@ -1,9 +0,0 @@
# is_array
Return true if the variable passed to it is an array.
## Basic usage
```smarty
{if $myVar|is_array}it's an array{/if}
```
-1
View File
@@ -60,7 +60,6 @@ nav:
- 'escape': 'designers/language-modifiers/language-modifier-escape.md'
- 'from_charset': 'designers/language-modifiers/language-modifier-from-charset.md'
- 'indent': 'designers/language-modifiers/language-modifier-indent.md'
- 'is_array': 'designers/language-modifiers/language-modifier-is_array.md'
- 'isset': 'designers/language-modifiers/language-modifier-isset.md'
- 'join': 'designers/language-modifiers/language-modifier-join.md'
- 'json_encode': 'designers/language-modifiers/language-modifier-json-encode.md'
+3
View File
@@ -20,6 +20,9 @@ use Smarty\Template;
* - indent_char - string (" ")
* - wrap_boundary - boolean (true)
*
* @link https://www.smarty.net/manual/en/language.function.textformat.php {textformat}
* (Smarty online manual)
*
* @param array $params parameters
* @param string $content contents of the block
* @param Template $template template object
@@ -11,6 +11,8 @@ namespace Smarty\Compile\Modifier;
* Input: string to catenate
* Example: {$var|cat:"foo"}
*
* @link https://www.smarty.net/manual/en/language.modifier.cat.php cat
* (Smarty online manual)
* @author Uwe Tews
*/
@@ -6,6 +6,8 @@ namespace Smarty\Compile\Modifier;
* Name: count_characters
* Purpose: count the number of characters in a text
*
* @link https://www.smarty.net/manual/en/language.modifier.count.characters.php count_characters (Smarty online
* manual)
* @author Uwe Tews
*/
@@ -6,6 +6,8 @@ namespace Smarty\Compile\Modifier;
* Name: count_paragraphs
* Purpose: count the number of paragraphs in a text
*
* @link https://www.smarty.net/manual/en/language.modifier.count.paragraphs.php
* count_paragraphs (Smarty online manual)
* @author Uwe Tews
*/
@@ -6,6 +6,8 @@ namespace Smarty\Compile\Modifier;
* Name: count_sentences
* Purpose: count the number of sentences in a text
*
* @link https://www.smarty.net/manual/en/language.modifier.count.paragraphs.php
* count_sentences (Smarty online manual)
* @author Uwe Tews
*/
@@ -6,6 +6,7 @@ namespace Smarty\Compile\Modifier;
* Name: count_words
* Purpose: count the number of words in a text
*
* @link https://www.smarty.net/manual/en/language.modifier.count.words.php count_words (Smarty online manual)
* @author Uwe Tews
*/
@@ -6,6 +6,7 @@ namespace Smarty\Compile\Modifier;
* Name: default
* Purpose: designate default value for empty variables
*
* @link https://www.smarty.net/manual/en/language.modifier.default.php default (Smarty online manual)
* @author Uwe Tews
*/
@@ -9,6 +9,7 @@ use Smarty\Exception;
* Name: escape
* Purpose: escape string for output
*
* @link https://www.smarty.net/docsv2/en/language.modifier.escape count_characters (Smarty online manual)
* @author Rodney Rehm
*/
@@ -6,6 +6,7 @@ namespace Smarty\Compile\Modifier;
* Name: indent
* Purpose: indent lines of text
*
* @link https://www.smarty.net/manual/en/language.modifier.indent.php indent (Smarty online manual)
* @author Uwe Tews
*/
@@ -6,6 +6,7 @@ namespace Smarty\Compile\Modifier;
* Name: lower
* Purpose: convert string to lowercase
*
* @link https://www.smarty.net/manual/en/language.modifier.lower.php lower (Smarty online manual)
* @author Monte Ohrt <monte at ohrt dot com>
* @author Uwe Tews
*/
@@ -7,6 +7,7 @@ namespace Smarty\Compile\Modifier;
* Name: nl2br
* Purpose: insert HTML line breaks before all newlines in a string
*
* @link https://www.smarty.net/docs/en/language.modifier.nl2br.tpl nl2br (Smarty online manual)
*/
class Nl2brModifierCompiler extends Base {
@@ -7,6 +7,7 @@ namespace Smarty\Compile\Modifier;
* Name: round
* Purpose: Returns the rounded value of num to specified precision (number of digits after the decimal point)
*
* @link https://www.smarty.net/docs/en/language.modifier.round.tpl round (Smarty online manual)
*/
class RoundModifierCompiler extends Base {
@@ -6,6 +6,7 @@ namespace Smarty\Compile\Modifier;
* Name: str_repeat
* Purpose: returns string repeated times times
*
* @link https://www.smarty.net/docs/en/language.modifier.str_repeat.tpl str_repeat (Smarty online manual)
*/
class StrRepeatModifierCompiler extends Base {
@@ -6,6 +6,7 @@ namespace Smarty\Compile\Modifier;
* Name: string_format
* Purpose: format strings via sprintf
*
* @link https://www.smarty.net/manual/en/language.modifier.string.format.php string_format (Smarty online manual)
* @author Uwe Tews
*/
@@ -9,6 +9,7 @@ namespace Smarty\Compile\Modifier;
* Example: {$var|strip} {$var|strip:"&nbsp;"}
* Date: September 25th, 2002
*
* @link https://www.smarty.net/manual/en/language.modifier.strip.php strip (Smarty online manual)
* @author Uwe Tews
*/
@@ -6,6 +6,7 @@ namespace Smarty\Compile\Modifier;
* Name: strip_tags
* Purpose: strip html tags from text
*
* @link https://www.smarty.net/docs/en/language.modifier.strip.tags.tpl strip_tags (Smarty online manual)
* @author Uwe Tews
*/
@@ -7,6 +7,7 @@ namespace Smarty\Compile\Modifier;
* Name: strlen
* Purpose: return the length of the given string
*
* @link https://www.smarty.net/docs/en/language.modifier.strlen.tpl strlen (Smarty online manual)
*/
class StrlenModifierCompiler extends Base {
@@ -6,6 +6,7 @@ namespace Smarty\Compile\Modifier;
* Name: lower
* Purpose: convert string to uppercase
*
* @link https://www.smarty.net/manual/en/language.modifier.upper.php lower (Smarty online manual)
* @author Uwe Tews
*/
@@ -6,6 +6,7 @@ namespace Smarty\Compile\Modifier;
* Name: wordwrap
* Purpose: wrap a string of text at a given length
*
* @link https://www.smarty.net/manual/en/language.modifier.wordwrap.php wordwrap (Smarty online manual)
* @author Uwe Tews
*/
+2 -3
View File
@@ -680,8 +680,7 @@ class Template extends BaseCompiler {
*
* @return string
*/
public function appendCode(string $left, string $right): string
{
public function appendCode($left, $right) {
if (preg_match('/\s*\?>\s?$/D', $left) && preg_match('/^<\?php\s+/', $right)) {
$left = preg_replace('/\s*\?>\s?$/D', "\n", $left);
$left .= preg_replace('/^<\?php\s+/', '', $right);
@@ -1057,7 +1056,7 @@ class Template extends BaseCompiler {
$prefixArray = array_merge($this->prefix_code, array_pop($this->prefixCodeStack));
$this->prefixCodeStack[] = [];
foreach ($prefixArray as $c) {
$code = $this->appendCode($code, (string) $c);
$code = $this->appendCode($code, $c);
}
$this->prefix_code = [];
return $code;
+10 -5
View File
@@ -109,7 +109,7 @@ class Data
foreach ($tpl_var as $_key => $_val) {
$this->assign($_key, $_val, $nocache, $scope);
}
return $this;
return;
}
switch ($scope ?? $this->getDefaultScope()) {
case self::SCOPE_GLOBAL:
@@ -163,6 +163,8 @@ class Data
* be not cached
*
* @return Data
* @link https://www.smarty.net/docs/en/api.append.tpl
*
* @api Smarty::append()
*/
public function append($tpl_var, $value = null, $merge = false, $nocache = false)
@@ -216,6 +218,7 @@ class Data
*
* @return mixed variable value or or array of variables
* @api Smarty::getTemplateVars()
* @link https://www.smarty.net/docs/en/api.get.template.vars.tpl
*
*/
public function getTemplateVars($varName = null, $searchParents = true)
@@ -224,10 +227,7 @@ class Data
return $this->getValue($varName, $searchParents);
}
return array_merge(
$this->parent && $searchParents ? $this->parent->getTemplateVars() : [],
array_map(function(Variable $var) { return $var->getValue(); }, $this->tpl_vars)
);
return array_merge($this->parent && $searchParents ? $this->parent->getTemplateVars() : [], $this->tpl_vars);
}
/**
@@ -351,6 +351,7 @@ class Data
* @param string|array $tpl_var the template variable(s) to clear
*
* @return Data
* @link https://www.smarty.net/docs/en/api.clear.assign.tpl
*
* @api Smarty::clearAssign()
*/
@@ -370,6 +371,7 @@ class Data
* clear all the assigned template variables.
*
* @return Data
* @link https://www.smarty.net/docs/en/api.clear.all.assign.tpl
*
* @api Smarty::clearAllAssign()
*/
@@ -385,6 +387,7 @@ class Data
* @param string|null $name variable name or null
*
* @return Data
* @link https://www.smarty.net/docs/en/api.clear.config.tpl
*
* @api Smarty::clearConfig()
*/
@@ -437,6 +440,7 @@ class Data
*
* @return mixed variable value or or array of variables
* @throws Exception
* @link https://www.smarty.net/docs/en/api.get.config.vars.tpl
*
* @api Smarty::getConfigVars()
*/
@@ -458,6 +462,7 @@ class Data
* @returns $this
* @throws \Exception
* @link https://www.smarty.net/docs/en/api.config.load.tpl
*
* @api Smarty::configLoad()
*/
+7
View File
@@ -113,6 +113,7 @@ class DefaultExtension extends Base {
* Name: spacify
* Purpose: add spaces between characters in a string
*
* @link https://www.smarty.net/manual/en/language.modifier.spacify.php spacify (Smarty online manual)
* @author Monte Ohrt <monte at ohrt dot com>
*
* @param string $string input string
@@ -233,6 +234,7 @@ class DefaultExtension extends Base {
* - format: strftime format for output
* - default_date: default date if $string is empty
*
* @link https://www.smarty.net/manual/en/language.modifier.date.format.php date_format (Smarty online manual)
* @author Monte Ohrt <monte at ohrt dot com>
*
* @param string $string input date string
@@ -384,6 +386,7 @@ class DefaultExtension extends Base {
* Name: escape
* Purpose: escape string for output
*
* @link https://www.smarty.net/docs/en/language.modifier.escape
* @author Monte Ohrt <monte at ohrt dot com>
*
* @param string $string input string
@@ -651,6 +654,8 @@ class DefaultExtension extends Base {
* Name: regex_replace
* Purpose: regular expression search/replace
*
* @link https://www.smarty.net/manual/en/language.modifier.regex.replace.php
* regex_replace (Smarty online manual)
* @author Monte Ohrt <monte at ohrt dot com>
*
* @param string $string input string
@@ -698,6 +703,7 @@ class DefaultExtension extends Base {
* Name: replace
* Purpose: simple search/replace
*
* @link https://www.smarty.net/manual/en/language.modifier.replace.php replace (Smarty online manual)
* @author Monte Ohrt <monte at ohrt dot com>
* @author Uwe Tews
*
@@ -720,6 +726,7 @@ class DefaultExtension extends Base {
* optionally splitting in the middle of a word, and
* appending the $etc string or inserting $etc into the middle.
*
* @link https://www.smarty.net/manual/en/language.modifier.truncate.php truncate (Smarty online manual)
* @author Monte Ohrt <monte at ohrt dot com>
*
* @param string $string input string
+2
View File
@@ -13,6 +13,8 @@ use Smarty\Template;
* @param Template $template template object
*
* @return string|null
*@link https://www.smarty.net/manual/en/language.function.counter.php {counter}
* (Smarty online manual)
*
* @author Monte Ohrt <monte at ohrt dot com>
*/
+2
View File
@@ -26,6 +26,8 @@ use Smarty\Template;
* {cycle name=row values="one,two,three" reset=true}
* {cycle name=row}
*
* @link https://www.smarty.net/manual/en/language.function.cycle.php {cycle}
* (Smarty online manual)
* @author Monte Ohrt <monte at ohrt dot com>
* @author credit to Mark Priatel <mpriatel@rogers.com>
* @author credit to Gerard <gerard@interfold.com>
+2
View File
@@ -10,6 +10,8 @@ use Smarty\Template;
* Name: fetch
* Purpose: fetch file, web or ftp data and display results
*
* @link https://www.smarty.net/manual/en/language.function.fetch.php {fetch}
* (Smarty online manual)
* @author Monte Ohrt <monte at ohrt dot com>
*
* @param array $params parameters
+2
View File
@@ -27,6 +27,8 @@ use Smarty\Template;
* - assign (optional) - assign the output as an array to this variable
* - escape (optional) - escape the content (not value), defaults to true
*
* @link https://www.smarty.net/manual/en/language.function.html.checkboxes.php {html_checkboxes}
* (Smarty online manual)
* @author Christopher Kvarme <christopher.kvarme@flashjab.com>
* @author credits to Monte Ohrt <monte at ohrt dot com>
* @version 1.0
+2
View File
@@ -20,6 +20,8 @@ use Smarty\Template;
* - basedir - (optional) - base directory for absolute paths, default is environment variable DOCUMENT_ROOT
* - path_prefix - prefix for path output (optional, default empty)
*
* @link https://www.smarty.net/manual/en/language.function.html.image.php {html_image}
* (Smarty online manual)
* @author Monte Ohrt <monte at ohrt dot com>
* @author credits to Duda <duda@big.hu>
* @version 1.0
+2
View File
@@ -19,6 +19,8 @@ use Smarty\Template;
* - id (optional) - string default not set
* - class (optional) - string default not set
*
* @link https://www.smarty.net/manual/en/language.function.html.options.php {html_image}
* (Smarty online manual)
* @author Monte Ohrt <monte at ohrt dot com>
* @author Ralf Strehle (minor optimization) <ralf dot strehle at yahoo dot de>
*
+2
View File
@@ -27,6 +27,8 @@ use Smarty\Template;
* {html_radios values=$ids name='box' separator='<br>' output=$names}
* {html_radios values=$ids checked=$checked separator='<br>' output=$names}
*
* @link https://www.smarty.net/manual/en/language.function.html.radios.php {html_radios}
* (Smarty online manual)
* @author Christopher Kvarme <christopher.kvarme@flashjab.com>
* @author credits to Monte Ohrt <monte at ohrt dot com>
* @version 1.0
+2
View File
@@ -26,6 +26,8 @@ use Smarty\Template;
* - 2.0 complete rewrite for performance,
* added attributes month_names, *_id
*
* @link https://www.smarty.net/manual/en/language.function.html.select.date.php {html_select_date}
* (Smarty online manual)
* @version 2.0
* @author Andrei Zmievski
* @author Monte Ohrt <monte at ohrt dot com>
+2
View File
@@ -9,6 +9,8 @@ use Smarty\Template;
* Name: html_select_time
* Purpose: Prints the dropdowns for time selection
*
* @link https://www.smarty.net/manual/en/language.function.html.select.time.php {html_select_time}
* (Smarty online manual)
* @author Roberto Berto <roberto@berto.net>
* @author Monte Ohrt <monte AT ohrt DOT com>
*
+2
View File
@@ -37,6 +37,8 @@ use Smarty\Template;
* @return string
*@author credit to boots <boots dot smarty at yahoo dot com>
* @version 1.1
* @link https://www.smarty.net/manual/en/language.function.html.table.php {html_table}
* (Smarty online manual)
*
* @author Monte Ohrt <monte at ohrt dot com>
* @author credit to Messju Mohr <messju at lammfellpuschen dot de>
+2
View File
@@ -35,6 +35,8 @@ use Smarty\Template;
* {mailto address="me@domain.com" cc="you@domain.com,they@domain.com"}
* {mailto address="me@domain.com" extra='class="mailto"'}
*
* @link https://www.smarty.net/manual/en/language.function.mailto.php {mailto}
* (Smarty online manual)
* @version 1.2
* @author Monte Ohrt <monte at ohrt dot com>
* @author credits to Jason Sweat (added cc, bcc and subject functionality)
+2
View File
@@ -10,6 +10,8 @@ use Smarty\Template;
* Name: math
* Purpose: handle math computations in template
*
* @link https://www.smarty.net/manual/en/language.function.math.php {math}
* (Smarty online manual)
* @author Monte Ohrt <monte at ohrt dot com>
*
* @param array $params parameters
+39 -39
View File
@@ -567,7 +567,7 @@ class TemplateLexer
public function yylex3()
{
if (!isset($this->yy_global_pattern3)) {
$this->yy_global_pattern3 = $this->replace("/\G(\\s*SMARTYrdel)|\G((SMARTYldel)SMARTYal)|\G([\"])|\G('[^'\\\\]*(?:\\\\.[^'\\\\]*)*')|\G([$][0-9]*[a-zA-Z_]\\w*)|\G([$])|\G(\\s+is\\s+(not\\s+)?in\\s+)|\G(\\s+as\\s+)|\G(\\s+to\\s+)|\G(\\s+step\\s+)|\G(\\s+instanceof\\s+)|\G(\\s*([!=][=]{1,2}|[<][=>]?|[>][=]?|[&|]{2})\\s*)|\G(\\s+(eq|ne|neq|gt|ge|gte|lt|le|lte|mod|and|or|xor)\\s+)|\G(\\s+is\\s+(not\\s+)?(odd|even|div)\\s+by\\s+)|\G(\\s+is\\s+(not\\s+)?(odd|even))|\G([!]\\s*|not\\s+)|\G([(](int(eger)?|bool(ean)?|float|double|real|string|binary|array|object)[)]\\s*)|\G(\\s*[(]\\s*)|\G(\\s*[)])|\G(\\[\\s*)|\G(\\s*\\])|\G(\\s*[-][>]\\s*)|\G(\\s*[=][>]\\s*)|\G(\\s*[=]\\s*)|\G(([+]|[-]){2})|\G(\\s*([+]|[-])\\s*)|\G(\\s*([*]{1,2}|[%\/^&]|[<>]{2})\\s*)|\G([@])|\G(array\\s*[(]\\s*)|\G([#])|\G(\\s+[0-9]*[a-zA-Z_][a-zA-Z0-9_\-:]*\\s*[=]\\s*)|\G(([0-9]*[a-zA-Z_]\\w*)?(\\\\[0-9]*[a-zA-Z_]\\w*)+)|\G([0-9]*[a-zA-Z_]\\w*)|\G(\\d+)|\G([`])|\G([|][@]?)|\G([.])|\G(\\s*[,]\\s*)|\G(\\s*[;]\\s*)|\G([:]{2})|\G(\\s*[:]\\s*)|\G(\\s*[?]\\s*)|\G(0[xX][0-9a-fA-F]+)|\G(\\s+)|\G([\S\s])/isS");
$this->yy_global_pattern3 = $this->replace("/\G(\\s*SMARTYrdel)|\G((SMARTYldel)SMARTYal)|\G([\"])|\G('[^'\\\\]*(?:\\\\.[^'\\\\]*)*')|\G([$][0-9]*[a-zA-Z_]\\w*)|\G([$])|\G(\\s+is\\s+in\\s+)|\G(\\s+as\\s+)|\G(\\s+to\\s+)|\G(\\s+step\\s+)|\G(\\s+instanceof\\s+)|\G(\\s*([!=][=]{1,2}|[<][=>]?|[>][=]?|[&|]{2})\\s*)|\G(\\s+(eq|ne|neq|gt|ge|gte|lt|le|lte|mod|and|or|xor)\\s+)|\G(\\s+is\\s+(not\\s+)?(odd|even|div)\\s+by\\s+)|\G(\\s+is\\s+(not\\s+)?(odd|even))|\G([!]\\s*|not\\s+)|\G([(](int(eger)?|bool(ean)?|float|double|real|string|binary|array|object)[)]\\s*)|\G(\\s*[(]\\s*)|\G(\\s*[)])|\G(\\[\\s*)|\G(\\s*\\])|\G(\\s*[-][>]\\s*)|\G(\\s*[=][>]\\s*)|\G(\\s*[=]\\s*)|\G(([+]|[-]){2})|\G(\\s*([+]|[-])\\s*)|\G(\\s*([*]{1,2}|[%\/^&]|[<>]{2})\\s*)|\G([@])|\G(array\\s*[(]\\s*)|\G([#])|\G(\\s+[0-9]*[a-zA-Z_][a-zA-Z0-9_\-:]*\\s*[=]\\s*)|\G(([0-9]*[a-zA-Z_]\\w*)?(\\\\[0-9]*[a-zA-Z_]\\w*)+)|\G([0-9]*[a-zA-Z_]\\w*)|\G(\\d+)|\G([`])|\G([|][@]?)|\G([.])|\G(\\s*[,]\\s*)|\G(\\s*[;]\\s*)|\G([:]{2})|\G(\\s*[:]\\s*)|\G(\\s*[?]\\s*)|\G(0[xX][0-9a-fA-F]+)|\G(\\s+)|\G([\S\s])/isS");
}
if (!isset($this->dataLength)) {
$this->dataLength = strlen($this->data);
@@ -659,122 +659,122 @@ class TemplateLexer
$this->token = \Smarty\Parser\TemplateParser::TP_ISIN;
}
public function yy_r3_10()
public function yy_r3_9()
{
$this->token = \Smarty\Parser\TemplateParser::TP_AS;
}
public function yy_r3_11()
public function yy_r3_10()
{
$this->token = \Smarty\Parser\TemplateParser::TP_TO;
}
public function yy_r3_12()
public function yy_r3_11()
{
$this->token = \Smarty\Parser\TemplateParser::TP_STEP;
}
public function yy_r3_13()
public function yy_r3_12()
{
$this->token = \Smarty\Parser\TemplateParser::TP_INSTANCEOF;
}
public function yy_r3_14()
public function yy_r3_13()
{
$this->token = \Smarty\Parser\TemplateParser::TP_LOGOP;
}
public function yy_r3_16()
public function yy_r3_15()
{
$this->token = \Smarty\Parser\TemplateParser::TP_SLOGOP;
}
public function yy_r3_18()
public function yy_r3_17()
{
$this->token = \Smarty\Parser\TemplateParser::TP_TLOGOP;
}
public function yy_r3_21()
public function yy_r3_20()
{
$this->token = \Smarty\Parser\TemplateParser::TP_SINGLECOND;
}
public function yy_r3_24()
public function yy_r3_23()
{
$this->token = \Smarty\Parser\TemplateParser::TP_NOT;
}
public function yy_r3_25()
public function yy_r3_24()
{
$this->token = \Smarty\Parser\TemplateParser::TP_TYPECAST;
}
public function yy_r3_29()
public function yy_r3_28()
{
$this->token = \Smarty\Parser\TemplateParser::TP_OPENP;
}
public function yy_r3_30()
public function yy_r3_29()
{
$this->token = \Smarty\Parser\TemplateParser::TP_CLOSEP;
}
public function yy_r3_31()
public function yy_r3_30()
{
$this->token = \Smarty\Parser\TemplateParser::TP_OPENB;
}
public function yy_r3_32()
public function yy_r3_31()
{
$this->token = \Smarty\Parser\TemplateParser::TP_CLOSEB;
}
public function yy_r3_33()
public function yy_r3_32()
{
$this->token = \Smarty\Parser\TemplateParser::TP_PTR;
}
public function yy_r3_34()
public function yy_r3_33()
{
$this->token = \Smarty\Parser\TemplateParser::TP_APTR;
}
public function yy_r3_35()
public function yy_r3_34()
{
$this->token = \Smarty\Parser\TemplateParser::TP_EQUAL;
}
public function yy_r3_36()
public function yy_r3_35()
{
$this->token = \Smarty\Parser\TemplateParser::TP_INCDEC;
}
public function yy_r3_38()
public function yy_r3_37()
{
$this->token = \Smarty\Parser\TemplateParser::TP_UNIMATH;
}
public function yy_r3_40()
public function yy_r3_39()
{
$this->token = \Smarty\Parser\TemplateParser::TP_MATH;
}
public function yy_r3_42()
public function yy_r3_41()
{
$this->token = \Smarty\Parser\TemplateParser::TP_AT;
}
public function yy_r3_43()
public function yy_r3_42()
{
$this->token = \Smarty\Parser\TemplateParser::TP_ARRAYOPEN;
}
public function yy_r3_44()
public function yy_r3_43()
{
$this->token = \Smarty\Parser\TemplateParser::TP_HATCH;
}
public function yy_r3_45()
public function yy_r3_44()
{
// resolve conflicts with shorttag and right_delimiter starting with '='
@@ -786,73 +786,73 @@ class TemplateLexer
$this->token = \Smarty\Parser\TemplateParser::TP_ATTR;
}
}
public function yy_r3_46()
public function yy_r3_45()
{
$this->token = \Smarty\Parser\TemplateParser::TP_NAMESPACE;
}
public function yy_r3_49()
public function yy_r3_48()
{
$this->token = \Smarty\Parser\TemplateParser::TP_ID;
}
public function yy_r3_50()
public function yy_r3_49()
{
$this->token = \Smarty\Parser\TemplateParser::TP_INTEGER;
}
public function yy_r3_51()
public function yy_r3_50()
{
$this->token = \Smarty\Parser\TemplateParser::TP_BACKTICK;
$this->yypopstate();
}
public function yy_r3_52()
public function yy_r3_51()
{
$this->token = \Smarty\Parser\TemplateParser::TP_VERT;
}
public function yy_r3_53()
public function yy_r3_52()
{
$this->token = \Smarty\Parser\TemplateParser::TP_DOT;
}
public function yy_r3_54()
public function yy_r3_53()
{
$this->token = \Smarty\Parser\TemplateParser::TP_COMMA;
}
public function yy_r3_55()
public function yy_r3_54()
{
$this->token = \Smarty\Parser\TemplateParser::TP_SEMICOLON;
}
public function yy_r3_56()
public function yy_r3_55()
{
$this->token = \Smarty\Parser\TemplateParser::TP_DOUBLECOLON;
}
public function yy_r3_57()
public function yy_r3_56()
{
$this->token = \Smarty\Parser\TemplateParser::TP_COLON;
}
public function yy_r3_58()
public function yy_r3_57()
{
$this->token = \Smarty\Parser\TemplateParser::TP_QMARK;
}
public function yy_r3_59()
public function yy_r3_58()
{
$this->token = \Smarty\Parser\TemplateParser::TP_HEX;
}
public function yy_r3_60()
public function yy_r3_59()
{
$this->token = \Smarty\Parser\TemplateParser::TP_SPACE;
}
public function yy_r3_61()
public function yy_r3_60()
{
$this->token = \Smarty\Parser\TemplateParser::TP_TEXT;
+1 -1
View File
@@ -324,7 +324,7 @@ class TemplateLexer
slop = ~\s+(eq|ne|neq|gt|ge|gte|lt|le|lte|mod|and|or|xor)\s+~
tlop = ~\s+is\s+(not\s+)?(odd|even|div)\s+by\s+~
scond = ~\s+is\s+(not\s+)?(odd|even)~
isin = ~\s+is\s+(not\s+)?in\s+~
isin = ~\s+is\s+in\s+~
as = ~\s+as\s+~
to = ~\s+to\s+~
step = ~\s+step\s+~
+3 -3
View File
@@ -47,18 +47,18 @@ class Dq extends Base
if ($subtree instanceof Code) {
$this->subtrees[ $last_subtree ]->data =
$parser->compiler->appendCode(
(string) $this->subtrees[ $last_subtree ]->data,
$this->subtrees[ $last_subtree ]->data,
'<?php echo ' . $subtree->data . ';?>'
);
} elseif ($subtree instanceof DqContent) {
$this->subtrees[ $last_subtree ]->data =
$parser->compiler->appendCode(
(string) $this->subtrees[ $last_subtree ]->data,
$this->subtrees[ $last_subtree ]->data,
'<?php echo "' . $subtree->data . '";?>'
);
} else {
$this->subtrees[ $last_subtree ]->data =
$parser->compiler->appendCode((string) $this->subtrees[ $last_subtree ]->data, (string) $subtree->data);
$parser->compiler->appendCode($this->subtrees[ $last_subtree ]->data, $subtree->data);
}
} else {
$this->subtrees[] = $subtree;
+2 -2
View File
@@ -62,9 +62,9 @@ class Tag extends Base
public function assign_to_var(\Smarty\Parser\TemplateParser $parser)
{
$var = $parser->compiler->getNewPrefixVariable();
$tmp = $parser->compiler->appendCode('<?php ob_start();?>', (string) $this->data);
$tmp = $parser->compiler->appendCode('<?php ob_start();?>', $this->data);
$tmp = $parser->compiler->appendCode($tmp, "<?php {$var}=ob_get_clean();?>");
$parser->compiler->appendPrefixCode($tmp);
$parser->compiler->appendPrefixCode((string) $tmp);
return $var;
}
}
+1 -1
View File
@@ -114,7 +114,7 @@ class Template extends Base
break;
case 'tag':
foreach ($chunk['subtrees'] as $subtree) {
$text = $parser->compiler->appendCode($text, (string) $subtree->to_smarty_php($parser));
$text = $parser->compiler->appendCode($text, $subtree->to_smarty_php($parser));
}
$code .= $text;
break;
File diff suppressed because it is too large Load Diff
+5 -14
View File
@@ -663,21 +663,12 @@ expr(res) ::= expr(e1) scond(c). {
res = c . e1 . ')';
}
isin(res) ::= ISIN(o). {
static $isin = [
'isin' => 'in_array(',
'isnotin' => '!in_array(',
];
$op = strtolower(str_replace(' ', '', o));
res = $isin[$op];
expr(res) ::= expr(e1) ISIN array(a). {
res = 'in_array('.e1.','.a.')';
}
expr(res) ::= expr(e1) isin(c) array(a). {
res = c . e1.','.a.')';
}
expr(res) ::= expr(e1) isin(c) value(v). {
res = c . e1.',(array)'.v.')';
expr(res) ::= expr(e1) ISIN value(v). {
res = 'in_array('.e1.',(array)'.v.')';
}
// null coalescing
@@ -805,7 +796,7 @@ value(res) ::= varindexed(vi) DOUBLECOLON static_class_access(r). {
// Smarty tag
value(res) ::= smartytag(st). {
$prefixVar = $this->compiler->getNewPrefixVariable();
$tmp = $this->compiler->appendCode('<?php ob_start();?>', (string) st);
$tmp = $this->compiler->appendCode('<?php ob_start();?>', st);
$this->compiler->appendPrefixCode($this->compiler->appendCode($tmp, "<?php {$prefixVar} = ob_get_clean();?>"));
res = $prefixVar;
}
+10 -8
View File
@@ -116,20 +116,22 @@ class ForeachRuntime {
*
* @return int the count for arrays and objects that implement countable, 1 for other objects that don't, and 0
* for empty elements
* @throws \Exception
*/
public function count($value): int
{
if ($value instanceof \IteratorAggregate) {
public function count($value) {
if ($value instanceof IteratorAggregate) {
// Note: getIterator() returns a Traversable, not an Iterator
// thus rewind() and valid() methods may not be present
return iterator_count($value->getIterator());
} elseif ($value instanceof \Iterator) {
return $value instanceof \Generator ? 1 : iterator_count($value);
} elseif ($value instanceof \Countable) {
} elseif ($value instanceof Iterator) {
return $value instanceof Generator ? 1 : iterator_count($value);
} elseif ($value instanceof Countable) {
return count($value);
} elseif ($value instanceof PDOStatement) {
return $value->rowCount();
} elseif ($value instanceof Traversable) {
return iterator_count($value);
}
return count((array) $value);
return count((array)$value);
}
/**
+47 -32
View File
@@ -2,7 +2,6 @@
namespace Smarty;
use FilesystemIterator;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
use Smarty\Cacheresource\File;
@@ -13,12 +12,11 @@ use Smarty\Extension\CoreExtension;
use Smarty\Extension\DefaultExtension;
use Smarty\Extension\ExtensionInterface;
use Smarty\Filter\Output\TrimWhitespace;
use Smarty\Runtime\CaptureRuntime;
use Smarty\Runtime\DefaultPluginHandlerRuntime;
use Smarty\Runtime\ForeachRuntime;
use Smarty\Runtime\InheritanceRuntime;
use Smarty\Runtime\TplFunctionRuntime;
use Smarty\Resource\BasePlugin;
use Smarty\Smarty\Runtime\CaptureRuntime;
use Smarty\Smarty\Runtime\ForeachRuntime;
use Smarty\Smarty\Runtime\InheritanceRuntime;
use Smarty\Smarty\Runtime\TplFunctionRuntime;
/**
* Project: Smarty: the PHP compiling template engine
@@ -40,6 +38,7 @@ use Smarty\Runtime\TplFunctionRuntime;
* Smarty mailing list. Send a blank e-mail to
* smarty-discussion-subscribe@googlegroups.com
*
* @link https://www.smarty.net/
* @author Monte Ohrt <monte at ohrt dot com>
* @author Uwe Tews <uwe dot tews at gmail dot com>
* @author Rodney Rehm
@@ -54,7 +53,7 @@ class Smarty extends \Smarty\TemplateBase {
/**
* smarty version
*/
const SMARTY_VERSION = '5.1.0';
const SMARTY_VERSION = '5.0.0';
/**
* define caching modes
@@ -535,6 +534,8 @@ class Smarty extends \Smarty\TemplateBase {
/**
* Load an additional extension.
*
* @param Base $extension
*
* @return void
*/
public function addExtension(ExtensionInterface $extension) {
@@ -580,7 +581,7 @@ class Smarty extends \Smarty\TemplateBase {
*
* @param string|\Smarty\Security $security_class if a string is used, it must be class-name
*
* @return static current Smarty instance for chaining
* @return Smarty current Smarty instance for chaining
* @throws \Smarty\Exception
*/
public function enableSecurity($security_class = null) {
@@ -591,7 +592,7 @@ class Smarty extends \Smarty\TemplateBase {
/**
* Disable security
*
* @return static current Smarty instance for chaining
* @return Smarty current Smarty instance for chaining
*/
public function disableSecurity() {
$this->security_policy = null;
@@ -605,7 +606,7 @@ class Smarty extends \Smarty\TemplateBase {
* @param string $key of the array element to assign the template dir to
* @param bool $isConfig true for config_dir
*
* @return static current Smarty instance for chaining
* @return Smarty current Smarty instance for chaining
*/
public function addTemplateDir($template_dir, $key = null, $isConfig = false) {
if ($isConfig) {
@@ -670,7 +671,7 @@ class Smarty extends \Smarty\TemplateBase {
* @param string|array $template_dir directory(s) of template sources
* @param bool $isConfig true for config_dir
*
* @return static current Smarty instance for chaining
* @return Smarty current Smarty instance for chaining
*/
public function setTemplateDir($template_dir, $isConfig = false) {
if ($isConfig) {
@@ -690,7 +691,7 @@ class Smarty extends \Smarty\TemplateBase {
* @param string|array $config_dir directory(s) of config sources
* @param mixed $key key of the array element to assign the config dir to
*
* @return static current Smarty instance for chaining
* @return Smarty current Smarty instance for chaining
*/
public function addConfigDir($config_dir, $key = null) {
return $this->addTemplateDir($config_dir, $key, true);
@@ -712,7 +713,7 @@ class Smarty extends \Smarty\TemplateBase {
*
* @param $config_dir
*
* @return static current Smarty instance for chaining
* @return Smarty current Smarty instance for chaining
*/
public function setConfigDir($config_dir) {
return $this->setTemplateDir($config_dir, true);
@@ -728,6 +729,7 @@ class Smarty extends \Smarty\TemplateBase {
*
* @return $this
* @throws \Smarty\Exception
* @link https://www.smarty.net/docs/en/api.register.plugin.tpl
*
* @api Smarty::registerPlugin()
*/
@@ -754,6 +756,7 @@ class Smarty extends \Smarty\TemplateBase {
* @param string $name name of template tag
*
* @return array|null
* @link https://www.smarty.net/docs/en/api.unregister.plugin.tpl
*
* @api Smarty::unregisterPlugin()
*/
@@ -771,6 +774,7 @@ class Smarty extends \Smarty\TemplateBase {
* @param string $name name of template tag
*
* @return $this
* @link https://www.smarty.net/docs/en/api.unregister.plugin.tpl
*
* @api Smarty::unregisterPlugin()
*/
@@ -786,7 +790,7 @@ class Smarty extends \Smarty\TemplateBase {
*
* @param null|array|string $plugins_dir
*
* @return static current Smarty instance for chaining
* @return Smarty current Smarty instance for chaining
* @deprecated since 5.0
*/
public function addPluginsDir($plugins_dir) {
@@ -819,7 +823,7 @@ class Smarty extends \Smarty\TemplateBase {
*
* @param string|array $plugins_dir directory(s) of plugins
*
* @return static current Smarty instance for chaining
* @return Smarty current Smarty instance for chaining
* @deprecated since 5.0
*/
public function setPluginsDir($plugins_dir) {
@@ -844,6 +848,7 @@ class Smarty extends \Smarty\TemplateBase {
*
* @return $this
* @throws Exception if $callback is not callable
* @link https://www.smarty.net/docs/en/api.register.default.plugin.handler.tpl
*
* @api Smarty::registerDefaultPluginHandler()
*
@@ -880,7 +885,7 @@ class Smarty extends \Smarty\TemplateBase {
*
* @param string $compile_dir directory to store compiled templates in
*
* @return static current Smarty instance for chaining
* @return Smarty current Smarty instance for chaining
*/
public function setCompileDir($compile_dir) {
$this->_normalizeDir('compile_dir', $compile_dir);
@@ -906,7 +911,7 @@ class Smarty extends \Smarty\TemplateBase {
*
* @param string $cache_dir directory to store cached templates in
*
* @return static current Smarty instance for chaining
* @return Smarty current Smarty instance for chaining
*/
public function setCacheDir($cache_dir) {
$this->_normalizeDir('cache_dir', $cache_dir);
@@ -1169,7 +1174,7 @@ class Smarty extends \Smarty\TemplateBase {
/**
* Get Smarty object
*
* @return static
* @return Smarty
*/
public function getSmarty() {
return $this;
@@ -1247,6 +1252,7 @@ class Smarty extends \Smarty\TemplateBase {
*
* @return int number of cache files deleted
* @throws \Smarty\Exception
* @link https://www.smarty.net/docs/en/api.clear.cache.tpl
*
* @api Smarty::clearCache()
*/
@@ -1266,6 +1272,7 @@ class Smarty extends \Smarty\TemplateBase {
* @param string $type resource type
*
* @return int number of cache files deleted
* @link https://www.smarty.net/docs/en/api.clear.all.cache.tpl
*
* @api Smarty::clearAllCache()
*/
@@ -1282,6 +1289,7 @@ class Smarty extends \Smarty\TemplateBase {
*
* @return int number of template files deleted
* @throws \Smarty\Exception
* @link https://www.smarty.net/docs/en/api.clear.compiled.template.tpl
*
* @api Smarty::clearCompiledTemplate()
*/
@@ -1747,15 +1755,15 @@ class Smarty extends \Smarty\TemplateBase {
// Lazy load runtimes when/if needed
switch ($type) {
case 'Capture':
return $this->runtimes[$type] = new CaptureRuntime();
return $this->runtimes[$type] = new \Smarty\Runtime\CaptureRuntime();
case 'Foreach':
return $this->runtimes[$type] = new ForeachRuntime();
return $this->runtimes[$type] = new \Smarty\Runtime\ForeachRuntime();
case 'Inheritance':
return $this->runtimes[$type] = new InheritanceRuntime();
return $this->runtimes[$type] = new \Smarty\Runtime\InheritanceRuntime();
case 'TplFunction':
return $this->runtimes[$type] = new TplFunctionRuntime();
return $this->runtimes[$type] = new \Smarty\Runtime\TplFunctionRuntime();
case 'DefaultPluginHandler':
return $this->runtimes[$type] = new DefaultPluginHandlerRuntime(
return $this->runtimes[$type] = new \Smarty\Runtime\DefaultPluginHandlerRuntime(
$this->getDefaultPluginHandlerFunc()
);
}
@@ -1795,6 +1803,7 @@ class Smarty extends \Smarty\TemplateBase {
* @return bool
* @throws \Smarty\Exception
* @api Smarty::loadFilter()
* @link https://www.smarty.net/docs/en/api.load.filter.tpl
*
* @deprecated since 5.0
*/
@@ -1842,10 +1851,11 @@ class Smarty extends \Smarty\TemplateBase {
* @param string $type filter type
* @param string $name filter name
*
* @return static
* @return TemplateBase
* @throws \Smarty\Exception
* @api Smarty::unloadFilter()
*
* @link https://www.smarty.net/docs/en/api.unload.filter.tpl
*
* @deprecated since 5.0
*/
@@ -1888,7 +1898,8 @@ class Smarty extends \Smarty\TemplateBase {
* @param string $name name of resource type
* @param Base $resource_handler
*
* @return static
* @return Smarty
* @link https://www.smarty.net/docs/en/api.register.cacheresource.tpl
*
* @api Smarty::registerCacheResource()
*
@@ -1909,8 +1920,9 @@ class Smarty extends \Smarty\TemplateBase {
*
* @param $name
*
* @return static
* @return Smarty
* @api Smarty::unregisterCacheResource()
* @link https://www.smarty.net/docs/en/api.unregister.cacheresource.tpl
*
* @deprecated since 5.0
*
@@ -1942,8 +1954,9 @@ class Smarty extends \Smarty\TemplateBase {
* @param callable $callback
* @param string|null $name optional filter name
*
* @return static
* @return TemplateBase
* @throws \Smarty\Exception
* @link https://www.smarty.net/docs/en/api.register.filter.tpl
*
* @api Smarty::registerFilter()
*/
@@ -2001,10 +2014,11 @@ class Smarty extends \Smarty\TemplateBase {
* @param string $type filter type
* @param callback|string $name the name previously used in ::registerFilter
*
* @return static
* @return TemplateBase
* @throws \Smarty\Exception
* @api Smarty::unregisterFilter()
*
* @link https://www.smarty.net/docs/en/api.unregister.filter.tpl
*
*/
public function unregisterFilter($type, $name) {
@@ -2038,7 +2052,7 @@ class Smarty extends \Smarty\TemplateBase {
* @param array|string $modifiers modifier or list of modifiers
* to add
*
* @return static
* @return \Smarty|Template
* @api Smarty::addDefaultModifiers()
*
*/
@@ -2068,7 +2082,7 @@ class Smarty extends \Smarty\TemplateBase {
* @param array|string $modifiers modifier or list of modifiers
* to set
*
* @return static
* @return TemplateBase
* @api Smarty::setDefaultModifiers()
*
*/
@@ -2117,7 +2131,7 @@ class Smarty extends \Smarty\TemplateBase {
* @throws \Smarty\Exception
*/
public function display($template = null, $cache_id = null, $compile_id = null) {
$this->returnOrCreateTemplate($template, $cache_id, $compile_id)->display();
return $this->returnOrCreateTemplate($template, $cache_id, $compile_id)->display();
}
/**
@@ -2187,6 +2201,7 @@ class Smarty extends \Smarty\TemplateBase {
* @return bool cache status
* @throws \Exception
* @throws \Smarty\Exception
* @link https://www.smarty.net/docs/en/api.is.cached.tpl
*
* @api Smarty::isCached()
*/
+1 -3
View File
@@ -555,9 +555,6 @@ class Template extends TemplateBase {
*/
public function getStreamVariable($variable)
{
trigger_error("Using stream variables (\`\{\$foo:bar\}\`)is deprecated.", E_USER_DEPRECATED);
$_result = '';
$fp = fopen($variable, 'r+');
if ($fp) {
@@ -604,6 +601,7 @@ class Template extends TemplateBase {
* @return bool cache status
* @throws \Exception
* @throws \Smarty\Exception
* @link https://www.smarty.net/docs/en/api.is.cached.tpl
*
* @api Smarty::isCached()
*/
+18 -11
View File
@@ -73,8 +73,9 @@ abstract class TemplateBase extends Data {
* @param bool $format smarty argument format, else traditional
* @param array $block_methods list of block-methods
*
* @return static
* @return \Smarty|\Smarty\Template
* @throws \Smarty\Exception
* @link https://www.smarty.net/docs/en/api.register.object.tpl
*
* @api Smarty::registerObject()
*/
@@ -113,8 +114,9 @@ abstract class TemplateBase extends Data {
*
* @param string $object_name name of object
*
* @return static
* @return TemplateBase
* @api Smarty::unregisterObject()
* @link https://www.smarty.net/docs/en/api.unregister.object.tpl
*
*/
public function unregisterObject($object_name) {
@@ -177,6 +179,7 @@ abstract class TemplateBase extends Data {
* @return Data data object
* @throws Exception
* @api Smarty::createData()
* @link https://www.smarty.net/docs/en/api.create.data.tpl
*
*/
public function createData(Data $parent = null, $name = null) {
@@ -219,6 +222,7 @@ abstract class TemplateBase extends Data {
*
* @return object
* @throws \Smarty\Exception if no such object is found
* @link https://www.smarty.net/docs/en/api.get.registered.object.tpl
*
* @api Smarty::getRegisteredObject()
*/
@@ -251,7 +255,7 @@ abstract class TemplateBase extends Data {
* @param array|string $literals literal or list of literals
* to addto add
*
* @return static
* @return TemplateBase
* @throws \Smarty\Exception
* @api Smarty::addLiterals()
*
@@ -269,7 +273,7 @@ abstract class TemplateBase extends Data {
* @param array|string $literals literal or list of literals
* to setto set
*
* @return static
* @return TemplateBase
* @throws \Smarty\Exception
* @api Smarty::setLiterals()
*
@@ -312,9 +316,10 @@ abstract class TemplateBase extends Data {
* @param string $class_impl the referenced PHP class to
* register
*
* @return static
* @return TemplateBase
* @throws \Smarty\Exception
* @api Smarty::registerClass()
* @link https://www.smarty.net/docs/en/api.register.class.tpl
*
*/
public function registerClass($class_name, $class_impl) {
@@ -333,7 +338,7 @@ abstract class TemplateBase extends Data {
*
* @param callable $callback class/method name
*
* @return static
* @return TemplateBase
* @throws Exception if $callback is not callable
* @api Smarty::registerDefaultConfigHandler()
*
@@ -353,7 +358,7 @@ abstract class TemplateBase extends Data {
*
* @param callable $callback class/method name
*
* @return static
* @return TemplateBase
* @throws Exception if $callback is not callable
* @api Smarty::registerDefaultTemplateHandler()
*
@@ -372,9 +377,10 @@ abstract class TemplateBase extends Data {
* Registers a resource to fetch a template
*
* @param string $name name of resource type
* @param \Smarty\Resource\BasePlugin $resource_handler instance of Smarty\Resource\BasePlugin
* @param Smarty\Resource\Base $resource_handler instance of Smarty\Resource\Base
*
* @return static
* @return \Smarty|\Smarty\Template
* @link https://www.smarty.net/docs/en/api.register.resource.tpl
*
* @api Smarty::registerResource()
*/
@@ -389,8 +395,9 @@ abstract class TemplateBase extends Data {
*
* @param string $type name of resource type
*
* @return static
* @return TemplateBase
* @api Smarty::unregisterResource()
* @link https://www.smarty.net/docs/en/api.unregister.resource.tpl
*
*/
public function unregisterResource($type) {
@@ -406,7 +413,7 @@ abstract class TemplateBase extends Data {
*
* @param string $tpl_name
*
* @return static
* @return TemplateBase
* @throws Exception if file is not readable
* @api Smarty::setDebugTemplate()
*
+1 -1
View File
@@ -66,7 +66,7 @@ function smarty_make_timestamp($string)
|| (interface_exists('DateTimeInterface', false) && $string instanceof DateTimeInterface)
) {
return (int)$string->format('U'); // PHP 5.2 BC
} elseif (strlen($string) === 14 && ctype_digit((string)$string)) {
} elseif (strlen($string) === 14 && ctype_digit($string)) {
// it is mysql timestamp format of YYYYMMDDHHMMSS?
return mktime(
substr($string, 8, 2),
+355 -355
View File
@@ -10,411 +10,411 @@ use Smarty\CompilerException;
/**
* class for security test
*
*
*
*
*/
class SecurityTest extends PHPUnit_Smarty
{
public function setUp(): void
{
$this->setUpSmarty(__DIR__);
public function setUp(): void
{
$this->setUpSmarty(__DIR__);
$this->smarty->setForceCompile(true);
$this->smarty->enableSecurity();
}
public function testInit()
{
$this->cleanDirs();
}
$this->smarty->setForceCompile(true);
$this->smarty->enableSecurity();
}
public function testInit()
{
$this->cleanDirs();
}
/**
* test that security is loaded
*/
public function testSecurityLoaded()
{
$this->assertTrue(is_object($this->smarty->security_policy));
}
/**
* test that security is loaded
*/
public function testSecurityLoaded()
{
$this->assertTrue(is_object($this->smarty->security_policy));
}
/**
* test trusted PHP function
*/
public function testTrustedFunction()
{
$this->assertEquals("5", $this->smarty->fetch('string:{assign var=foo value=[1,2,3,4,5]}{count($foo)}'));
}
/**
* test trusted PHP function
*/
public function testTrustedFunction()
{
$this->assertEquals("5", $this->smarty->fetch('string:{assign var=foo value=[1,2,3,4,5]}{count($foo)}'));
}
/**
* test trusted modifier
* @deprecated
*/
public function testTrustedModifier()
{
$this->assertEquals("5", @$this->smarty->fetch('string:{assign var=foo value=[1,2,3,4,5]}{$foo|@count}'));
}
/**
* test trusted modifier
* @deprecated
*/
public function testTrustedModifier()
{
$this->assertEquals("5", @$this->smarty->fetch('string:{assign var=foo value=[1,2,3,4,5]}{$foo|@count}'));
}
/**
* test not trusted modifier
*
*
* @deprecated
*/
public function testNotTrustedModifier()
{
$this->smarty->security_policy->disabled_modifiers[] = 'escape';
$this->expectException(\Smarty\Exception::class);
$this->expectExceptionMessage('modifier \'escape\' disabled by security setting');
@$this->smarty->fetch('string:{assign var=foo value=[1,2,3,4,5]}{$foo|escape}');
}
/**
* test not trusted modifier
*
*
* @deprecated
*/
public function testNotTrustedModifier()
{
$this->smarty->security_policy->disabled_modifiers[] = 'escape';
$this->expectException(\Smarty\Exception::class);
$this->expectExceptionMessage('modifier \'escape\' disabled by security setting');
@$this->smarty->fetch('string:{assign var=foo value=[1,2,3,4,5]}{$foo|escape}');
}
/**
* test allowed tags
*/
public function testAllowedTags1()
{
$this->smarty->security_policy->allowed_tags = array('counter');
$this->assertEquals("1", $this->smarty->fetch('string:{counter start=1}'));
}
/**
* test allowed tags
*/
public function testAllowedTags1()
{
$this->smarty->security_policy->allowed_tags = array('counter');
$this->assertEquals("1", $this->smarty->fetch('string:{counter start=1}'));
}
/**
* test not allowed tag
*
*
*/
public function testNotAllowedTags2()
{
$this->expectException(\Smarty\Exception::class);
$this->expectExceptionMessage('tag \'cycle\' not allowed by security setting');
$this->smarty->security_policy->allowed_tags = array('counter');
$this->smarty->fetch('string:{counter}{cycle values="1,2"}');
}
/**
* test not allowed tag
*
*
*/
public function testNotAllowedTags2()
{
$this->expectException(\Smarty\Exception::class);
$this->expectExceptionMessage('tag \'cycle\' not allowed by security setting');
$this->smarty->security_policy->allowed_tags = array('counter');
$this->smarty->fetch('string:{counter}{cycle values="1,2"}');
}
/**
* test disabled tag
*
*
*/
public function testDisabledTags()
{
$this->expectException(\Smarty\Exception::class);
$this->expectExceptionMessage('tag \'cycle\' disabled by security setting');
$this->smarty->security_policy->disabled_tags = array('cycle');
$this->smarty->fetch('string:{counter}{cycle values="1,2"}');
}
/**
* test disabled tag
*
*
*/
public function testDisabledTags()
{
$this->expectException(\Smarty\Exception::class);
$this->expectExceptionMessage('tag \'cycle\' disabled by security setting');
$this->smarty->security_policy->disabled_tags = array('cycle');
$this->smarty->fetch('string:{counter}{cycle values="1,2"}');
}
/**
* test allowed modifier
*/
public function testAllowedModifier1()
{
error_reporting(E_ALL & E_STRICT);
$this->smarty->security_policy->allowed_modifiers = array('capitalize');
$this->assertEquals("Hello World", $this->smarty->fetch('string:{"hello world"|capitalize}'));
error_reporting(E_ALL | E_STRICT);
}
/**
* test allowed modifier
*/
public function testAllowedModifier1()
{
error_reporting(E_ALL & E_STRICT);
$this->smarty->security_policy->allowed_modifiers = array('capitalize');
$this->assertEquals("Hello World", $this->smarty->fetch('string:{"hello world"|capitalize}'));
error_reporting(E_ALL | E_STRICT);
}
public function testAllowedModifier2()
{
$this->smarty->security_policy->allowed_modifiers = array('upper');
$this->assertEquals("HELLO WORLD", $this->smarty->fetch('string:{"hello world"|upper}'));
}
public function testAllowedModifier2()
{
$this->smarty->security_policy->allowed_modifiers = array('upper');
$this->assertEquals("HELLO WORLD", $this->smarty->fetch('string:{"hello world"|upper}'));
}
/**
* test not allowed modifier
*
*
*/
public function testNotAllowedModifier()
{
$this->expectException(\Smarty\Exception::class);
$this->expectExceptionMessage('modifier \'lower\' not allowed by security setting');
$this->smarty->security_policy->allowed_modifiers = array('upper');
$this->smarty->fetch('string:{"hello"|upper}{"world"|lower}');
}
/**
* test not allowed modifier
*
*
*/
public function testNotAllowedModifier()
{
$this->expectException(\Smarty\Exception::class);
$this->expectExceptionMessage('modifier \'lower\' not allowed by security setting');
$this->smarty->security_policy->allowed_modifiers = array('upper');
$this->smarty->fetch('string:{"hello"|upper}{"world"|lower}');
}
/**
* test disabled modifier
*
*
*/
public function testDisabledModifier()
{
$this->expectException(\Smarty\Exception::class);
$this->expectExceptionMessage('modifier \'lower\' disabled by security setting');
$this->smarty->security_policy->disabled_modifiers = array('lower');
$this->smarty->fetch('string:{"hello"|upper}{"world"|lower}');
}
/**
* test disabled modifier
*
*
*/
public function testDisabledModifier()
{
$this->expectException(\Smarty\Exception::class);
$this->expectExceptionMessage('modifier \'lower\' disabled by security setting');
$this->smarty->security_policy->disabled_modifiers = array('lower');
$this->smarty->fetch('string:{"hello"|upper}{"world"|lower}');
}
/**
* test Smarty no longer handles embedded PHP
*/
public function testSmartyPhpAllow()
{
$this->assertEquals('<?php echo "hello world"; ?>', $this->smarty->fetch('string:<?php echo "hello world"; ?>'));
}
/**
* test Smarty no longer handles embedded PHP
*/
public function testSmartyPhpAllow()
{
$this->assertEquals('<?php echo "hello world"; ?>', $this->smarty->fetch('string:<?php echo "hello world"; ?>'));
}
public function testSmartyPhpAllow2()
{
$this->assertEquals('<? echo "hello world"; ?>', $this->smarty->fetch('string:<? echo "hello world"; ?>'));
}
public function testSmartyPhpAllow2()
{
$this->assertEquals('<? echo "hello world"; ?>', $this->smarty->fetch('string:<? echo "hello world"; ?>'));
}
public function testSmartyPhpAllow3()
{
$this->assertEquals('<% echo "hello world"; %>', $this->smarty->fetch('string:<% echo "hello world"; %>'));
}
public function testSmartyPhpAllow3()
{
$this->assertEquals('<% echo "hello world"; %>', $this->smarty->fetch('string:<% echo "hello world"; %>'));
}
/**
* test standard directory
*/
public function testStandardDirectory()
{
$content = $this->smarty->fetch('string:{include file="helloworld.tpl"}');
$this->assertEquals("hello world", $content);
}
/**
* test standard directory
*/
public function testStandardDirectory()
{
$content = $this->smarty->fetch('string:{include file="helloworld.tpl"}');
$this->assertEquals("hello world", $content);
}
/**
* test trusted directory
*/
public function testTrustedDirectory()
{
$this->smarty->security_policy->secure_dir = array('.' . DIRECTORY_SEPARATOR . 'templates_2' . DIRECTORY_SEPARATOR);
$this->assertEquals("hello world", $this->smarty->fetch('string:{include file="templates_2/hello.tpl"}'));
}
/**
* test trusted directory
*/
public function testTrustedDirectory()
{
$this->smarty->security_policy->secure_dir = array('.' . DIRECTORY_SEPARATOR . 'templates_2' . DIRECTORY_SEPARATOR);
$this->assertEquals("hello world", $this->smarty->fetch('string:{include file="templates_2/hello.tpl"}'));
}
/**
* test not trusted directory
*
*
*
*/
public function testNotTrustedDirectory()
{
$this->expectException(\Smarty\Exception::class);
$this->expectExceptionMessage('not trusted file path');
$this->smarty->security_policy->secure_dir = array(str_replace('\\', '/', __DIR__ . '/templates_3/'));
$this->smarty->fetch('string:{include file="templates_2/hello.tpl"}');
}
/**
* test not trusted directory
*
*
*
*/
public function testNotTrustedDirectory()
{
$this->expectException(\Smarty\Exception::class);
$this->expectExceptionMessage('not trusted file path');
$this->smarty->security_policy->secure_dir = array(str_replace('\\', '/', __DIR__ . '/templates_3/'));
$this->smarty->fetch('string:{include file="templates_2/hello.tpl"}');
}
/**
* test disabled security for not trusted dir
*/
public function testDisabledTrustedDirectory()
{
$this->smarty->disableSecurity();
$this->assertEquals("hello world", $this->smarty->fetch('string:{include file="templates_2/hello.tpl"}'));
}
/**
* test disabled security for not trusted dir
*/
public function testDisabledTrustedDirectory()
{
$this->smarty->disableSecurity();
$this->assertEquals("hello world", $this->smarty->fetch('string:{include file="templates_2/hello.tpl"}'));
}
/**
* test trusted static class
*/
public function testTrustedStaticClass()
{
$this->smarty->security_policy->static_classes = array('mysecuritystaticclass');
$tpl = $this->smarty->createTemplate('string:{mysecuritystaticclass::square(5)}');
$this->assertEquals('25', $this->smarty->fetch($tpl));
}
/**
* test trusted static class
*/
public function testTrustedStaticClass()
{
$this->smarty->security_policy->static_classes = array('mysecuritystaticclass');
$tpl = $this->smarty->createTemplate('string:{mysecuritystaticclass::square(5)}');
$this->assertEquals('25', $this->smarty->fetch($tpl));
}
/**
* test not trusted PHP function
*
*
*/
public function testNotTrustedStaticClass()
{
$this->expectException(\Smarty\Exception::class);
$this->expectExceptionMessage('access to static class \'mysecuritystaticclass\' not allowed by security setting');
$this->smarty->security_policy->static_classes = array('null');
$this->smarty->fetch('string:{mysecuritystaticclass::square(5)}');
}
/**
* test not trusted PHP function
*
*
*/
public function testNotTrustedStaticClass()
{
$this->expectException(\Smarty\Exception::class);
$this->expectExceptionMessage('access to static class \'mysecuritystaticclass\' not allowed by security setting');
$this->smarty->security_policy->static_classes = array('null');
$this->smarty->fetch('string:{mysecuritystaticclass::square(5)}');
}
/**
* test not trusted PHP function
*/
public function testNotTrustedStaticClassEval()
{
$this->expectException(\Smarty\Exception::class);
$this->expectExceptionMessage('dynamic static class not allowed by security setting');
$this->smarty->security_policy->static_classes = array('null');
$this->smarty->fetch('string:{$test = "mysecuritystaticclass"}{$test::square(5)}');
}
/**
* test not trusted PHP function
*/
public function testNotTrustedStaticClassEval()
{
$this->expectException(\Smarty\Exception::class);
$this->expectExceptionMessage('dynamic static class not allowed by security setting');
$this->smarty->security_policy->static_classes = array('null');
$this->smarty->fetch('string:{$test = "mysecuritystaticclass"}{$test::square(5)}');
}
/**
* test not trusted PHP function
*/
public function testNotTrustedStaticClassSmartyVar()
{
$this->expectException(\Smarty\Exception::class);
$this->expectExceptionMessage('dynamic static class not allowed by security setting');
$this->smarty->security_policy->static_classes = array('null');
$this->smarty->fetch('string:{$smarty.template_object::square(5)}');
}
/**
* test not trusted PHP function
*/
public function testNotTrustedStaticClassSmartyVar()
{
$this->expectException(\Smarty\Exception::class);
$this->expectExceptionMessage('dynamic static class not allowed by security setting');
$this->smarty->security_policy->static_classes = array('null');
$this->smarty->fetch('string:{$smarty.template_object::square(5)}');
}
public function testChangedTrustedDirectory()
{
$this->smarty->security_policy->secure_dir = array(
'.' . DIRECTORY_SEPARATOR . 'templates_2' . DIRECTORY_SEPARATOR,
);
$this->assertEquals("hello world", $this->smarty->fetch('string:{include file="templates_2/hello.tpl"}'));
public function testChangedTrustedDirectory()
{
$this->smarty->security_policy->secure_dir = array(
'.' . DIRECTORY_SEPARATOR . 'templates_2' . DIRECTORY_SEPARATOR,
);
$this->assertEquals("hello world", $this->smarty->fetch('string:{include file="templates_2/hello.tpl"}'));
$this->smarty->security_policy->secure_dir = array(
'.' . DIRECTORY_SEPARATOR . 'templates_2' . DIRECTORY_SEPARATOR,
'.' . DIRECTORY_SEPARATOR . 'templates_3' . DIRECTORY_SEPARATOR,
);
$this->assertEquals("templates_3", $this->smarty->fetch('string:{include file="templates_3/dirname.tpl"}'));
}
/**
* test template file exits
*
*
*
*/
public function testTemplateTrustedStream()
{
stream_wrapper_register("global", ResourceStreamSecurity::class)
or die("Failed to register protocol");
$fp = fopen("global://mytest", "r+");
fwrite($fp, 'hello world {$foo}');
fclose($fp);
$this->smarty->security_policy->streams= array('global');
$tpl = $this->smarty->createTemplate('global:mytest');
$this->assertTrue($tpl->getSource()->exists);
stream_wrapper_unregister("global");
}
/**
*
*
* test template file exits
*/
public function testTemplateNotTrustedStream()
{
$this->expectException(\Smarty\Exception::class);
$this->expectExceptionMessage('stream \'global\' not allowed by security setting');
stream_wrapper_register("global", ResourceStreamSecurity::class)
or die("Failed to register protocol");
$fp = fopen("global://mytest", "r+");
fwrite($fp, 'hello world {$foo}');
fclose($fp);
$this->smarty->security_policy->streams= array('notrusted');
$tpl = $this->smarty->createTemplate('global:mytest');
$this->assertTrue($tpl->getSource()->exists);
stream_wrapper_unregister("global");
}
$this->smarty->security_policy->secure_dir = array(
'.' . DIRECTORY_SEPARATOR . 'templates_2' . DIRECTORY_SEPARATOR,
'.' . DIRECTORY_SEPARATOR . 'templates_3' . DIRECTORY_SEPARATOR,
);
$this->assertEquals("templates_3", $this->smarty->fetch('string:{include file="templates_3/dirname.tpl"}'));
}
/**
* test template file exits
*
*
*
*/
public function testTemplateTrustedStream()
{
stream_wrapper_register("global", ResourceStreamSecurity::class)
or die("Failed to register protocol");
$fp = fopen("global://mytest", "r+");
fwrite($fp, 'hello world {$foo}');
fclose($fp);
$this->smarty->security_policy->streams= array('global');
$tpl = $this->smarty->createTemplate('global:mytest');
$this->assertTrue($tpl->getSource()->exists);
stream_wrapper_unregister("global");
}
/**
*
*
* test template file exits
*/
public function testTemplateNotTrustedStream()
{
$this->expectException(\Smarty\Exception::class);
$this->expectExceptionMessage('stream \'global\' not allowed by security setting');
stream_wrapper_register("global", ResourceStreamSecurity::class)
or die("Failed to register protocol");
$fp = fopen("global://mytest", "r+");
fwrite($fp, 'hello world {$foo}');
fclose($fp);
$this->smarty->security_policy->streams= array('notrusted');
$tpl = $this->smarty->createTemplate('global:mytest');
$this->assertTrue($tpl->getSource()->exists);
stream_wrapper_unregister("global");
}
/**
*
* @group slow
*/
public function testTrustedUri()
{
$this->smarty->security_policy->trusted_uri = array(
'#https://www.smarty.net$#i'
);
$this->assertStringContainsString('<title>Preface | Smarty</title>', $this->smarty->fetch('string:{fetch file="https://www.smarty.net/docs/en/preface.tpl"}'));
}
public function testTrustedUri()
{
$this->smarty->security_policy->trusted_uri = array(
'#https://s4otw4nhg.erteorteortert.nusuchtld$#i'
);
/**
*
*
*/
public function testNotTrustedUri()
{
$this->expectException(\Smarty\Exception::class);
$this->expectExceptionMessage('URI \'https://www.smarty.net/docs/en/preface.tpl\' not allowed by security setting');
$this->smarty->security_policy->trusted_uri = array();
$this->assertStringContainsString('<title>Preface | Smarty</title>', $this->smarty->fetch('string:{fetch file="https://www.smarty.net/docs/en/preface.tpl"}'));
}
$this->expectException(\Smarty\Exception::class);
$this->expectExceptionMessage('{fetch} cannot read resource \'https://s4otw4nhg.erteorteortert.nusuchtld/docs/en/preface.tpl\'');
$this->smarty->fetch('string:{fetch file="https://s4otw4nhg.erteorteortert.nusuchtld/docs/en/preface.tpl"}');
}
/**
*
*
*/
public function testNotTrustedUri()
{
$this->expectException(\Smarty\Exception::class);
$this->expectExceptionMessage('URI \'https://example.net\' not allowed by security setting');
$this->smarty->security_policy->trusted_uri = [];
$this->assertStringContainsString(
'<title>Preface | Smarty</title>',
$this->smarty->fetch('string:{fetch file="https://example.net"}')
);
}
/**
* In security mode, accessing $smarty.template_object should be illegal.
*/
public function testSmartyTemplateObject() {
$this->expectException(CompilerException::class);
$this->smarty->display('string:{$smarty.template_object}');
}
/**
* In security mode, accessing $smarty.template_object should be illegal.
*/
public function testSmartyTemplateObject() {
$this->expectException(CompilerException::class);
$this->smarty->display('string:{$smarty.template_object}');
}
}
class mysecuritystaticclass
{
const STATIC_CONSTANT_VALUE = 3;
static $static_var = 5;
const STATIC_CONSTANT_VALUE = 3;
static $static_var = 5;
static function square($i)
{
return $i * $i;
}
static function square($i)
{
return $i * $i;
}
}
#[AllowDynamicProperties]
class ResourceStreamSecurity
{
private $position;
private $varname;
private $position;
private $varname;
public function stream_open($path, $mode, $options, &$opened_path)
{
$url = parse_url($path);
$this->varname = $url["host"];
$this->position = 0;
public function stream_open($path, $mode, $options, &$opened_path)
{
$url = parse_url($path);
$this->varname = $url["host"];
$this->position = 0;
return true;
}
return true;
}
public function stream_read($count)
{
$p = &$this->position;
$ret = substr($GLOBALS[$this->varname], $p, $count);
$p += strlen($ret);
public function stream_read($count)
{
$p = &$this->position;
$ret = substr($GLOBALS[$this->varname], $p, $count);
$p += strlen($ret);
return $ret;
}
return $ret;
}
public function stream_write($data)
{
$v = &$GLOBALS[$this->varname];
$l = strlen($data);
$p = &$this->position;
$v = substr($v ?? '', 0, $p) . $data . substr($v ?? '', $p += $l);
public function stream_write($data)
{
$v = &$GLOBALS[$this->varname];
$l = strlen($data);
$p = &$this->position;
$v = substr($v ?? '', 0, $p) . $data . substr($v ?? '', $p += $l);
return $l;
}
return $l;
}
public function stream_tell()
{
return $this->position;
}
public function stream_tell()
{
return $this->position;
}
public function stream_eof()
{
if (!isset($GLOBALS[$this->varname])) {
return true;
}
public function stream_eof()
{
if (!isset($GLOBALS[$this->varname])) {
return true;
}
return $this->position >= strlen($GLOBALS[$this->varname]);
}
return $this->position >= strlen($GLOBALS[$this->varname]);
}
public function stream_seek($offset, $whence)
{
$l = strlen($GLOBALS[$this->varname]);
$p = &$this->position;
switch ($whence) {
case SEEK_SET:
$newPos = $offset;
break;
case SEEK_CUR:
$newPos = $p + $offset;
break;
case SEEK_END:
$newPos = $l + $offset;
break;
default:
return false;
}
$ret = ($newPos >= 0 && $newPos <= $l);
if ($ret) {
$p = $newPos;
}
return $ret;
}
public function stream_seek($offset, $whence)
{
$l = strlen($GLOBALS[$this->varname]);
$p = &$this->position;
switch ($whence) {
case SEEK_SET:
$newPos = $offset;
break;
case SEEK_CUR:
$newPos = $p + $offset;
break;
case SEEK_END:
$newPos = $l + $offset;
break;
default:
return false;
}
$ret = ($newPos >= 0 && $newPos <= $l);
if ($ret) {
$p = $newPos;
}
return $ret;
}
}
@@ -42,15 +42,4 @@ class AssignTest extends PHPUnit_Smarty
$this->smarty->assign(array('foo' => 'bar', 'foo2' => 'bar2'));
$this->assertEquals('bar bar2', $this->smarty->fetch('eval:{$foo} {$foo2}'));
}
/**
* Test that assign returns this.
*/
public function testAssignReturnsThis()
{
$this->assertEquals(
'data',
$this->smarty->assign(['dummy' => 'data'])->fetch('eval:{$dummy}')
);
}
}
@@ -1,126 +1,112 @@
<?php
/**
* Smarty PHPunit tests getTemplateVars method
*
* @author Uwe Tews
*/
/**
* class for getTemplateVars method test
*
*
*
*
*/
class GetTemplateVarsTest extends PHPUnit_Smarty
{
public function setUp(): void
{
$this->setUpSmarty(__DIR__);
}
public function setUp(): void
{
$this->setUpSmarty(__DIR__);
}
public function testInit()
{
$this->cleanDirs();
}
/**
* test root getTemplateVars single value
*/
public function testGetSingleTemplateVarScopeRoot()
{
$this->smarty->assign('foo', 'bar');
$this->smarty->assign('blar', 'buh');
$this->assertEquals("bar", $this->smarty->getTemplateVars('foo'));
}
/**
* test root getTemplateVars all values
*/
public function testGetAllTemplateVarsScopeRoot()
{
$this->smarty->assign('foo', 'bar');
$this->smarty->assign('blar', 'buh');
$vars = $this->smarty->getTemplateVars();
$this->assertTrue(is_array($vars));
$this->assertEquals("bar", $vars['foo']);
$this->assertEquals("buh", $vars['blar']);
}
public function testInit()
{
$this->cleanDirs();
}
/**
* test root getTemplateVars single value
*/
public function testGetSingleTemplateVarScopeRoot()
{
$this->smarty->assign('foo', 'bar');
$this->smarty->assign('blar', 'buh');
$this->assertEquals("bar", $this->smarty->getTemplateVars('foo'));
}
/**
* test single variable with data object chain
*/
public function testGetSingleTemplateVarScopeAll()
{
$data1 = $this->smarty->createData($this->smarty);
$data2 = $this->smarty->createData($data1);
$this->smarty->assign('foo', 'bar');
$this->smarty->assign('blar', 'buh');
$this->assertEquals("bar", $data2->getTemplateVars('foo'));
}
/**
* test root getTemplateVars all values
*/
public function testGetAllTemplateVarsScopeRoot()
{
$this->smarty->assign('foo', 'bar');
$this->smarty->assign('blar', 'buh');
$vars = $this->smarty->getTemplateVars();
$this->assertTrue(is_array($vars));
$this->assertEquals("bar", $vars['foo']);
$this->assertEquals("buh", $vars['blar']);
}
/**
* test get all variables with data object chain
*/
public function testGetAllTemplateVarsScopeAll()
{
$data1 = $this->smarty->createData($this->smarty);
$data2 = $this->smarty->createData($data1);
$this->smarty->assign('foo', 'bar');
$data1->assign('blar', 'buh');
$data2->assign('foo2', 'bar2');
$vars = $data2->getTemplateVars(null);
$this->assertTrue(is_array($vars));
$this->assertEquals("bar", $vars['foo']);
$this->assertEquals("bar2", $vars['foo2']);
$this->assertEquals("buh", $vars['blar']);
}
/**
* test single variable with data object chain
*/
public function testGetSingleTemplateVarScopeAll()
{
$data1 = $this->smarty->createData($this->smarty);
$data2 = $this->smarty->createData($data1);
$this->smarty->assign('foo', 'bar');
$this->smarty->assign('blar', 'buh');
$this->assertEquals("bar", $data2->getTemplateVars('foo'));
}
/**
* test get all variables with data object chain search parents disabled
*/
public function testGetAllTemplateVarsScopeAllNoParents()
{
$data1 = $this->smarty->createData($this->smarty);
$data2 = $this->smarty->createData($data1);
$this->smarty->assign('foo', 'bar');
$data1->assign('blar', 'buh');
$data2->assign('foo2', 'bar2');
$vars = $data2->getTemplateVars(null, false);
$this->assertTrue(is_array($vars));
$this->assertFalse(isset($vars['foo']));
$this->assertEquals("bar2", $vars['foo2']);
$this->assertFalse(isset($vars['blar']));
}
/**
* test get all variables with data object chain
*/
public function testGetAllTemplateVarsScopeAll()
{
$data1 = $this->smarty->createData($this->smarty);
$data2 = $this->smarty->createData($data1);
$this->smarty->assign('foo', 'bar');
$data1->assign('blar', 'buh');
$data2->assign('foo2', 'bar2');
$vars = $data2->getTemplateVars(null);
$this->assertTrue(is_array($vars));
$this->assertEquals("bar", $vars['foo']);
$this->assertEquals("bar2", $vars['foo2']);
$this->assertEquals("buh", $vars['blar']);
}
/**
* test get single variables with data object chain search parents disabled
*/
public function testGetSingleTemplateVarsScopeAllNoParents()
{
error_reporting(error_reporting() & ~(E_NOTICE | E_USER_NOTICE));
$data1 = $this->smarty->createData($this->smarty);
$data2 = $this->smarty->createData($data1);
$this->smarty->assign('foo', 'bar');
$data1->assign('blar', 'buh');
$data2->assign('foo2', 'bar2');
$this->assertEquals("", $data2->getTemplateVars('foo', false));
$this->assertEquals("bar2", $data2->getTemplateVars('foo2', false));
$this->assertEquals("", $data2->getTemplateVars('blar', false));
}
/**
* test that variable assigned by global assign in template is included in getTemplateVars
*/
public function testAssignedInTemplate()
{
$this->smarty->fetch('string:{assign var="b" value="x" scope="global"}');
$this->assertEquals('x', $this->smarty->getTemplateVars('b'));
}
/**
* test that getTemplateVars returns simple array of values
*/
public function testSimpleCallReturnsArrayWithAllValues()
{
$this->smarty->assign('foo', 'bar');
$this->smarty->assign('i', 3);
$vars = $this->smarty->getTemplateVars();
$this->assertArrayHasKey('foo', $vars);
$this->assertArrayHasKey('i', $vars);
$this->assertEquals('bar', $vars['foo']);
$this->assertEquals(3,$vars['i']);
}
/**
* test get all variables with data object chain search parents disabled
*/
public function testGetAllTemplateVarsScopeAllNoParents()
{
$data1 = $this->smarty->createData($this->smarty);
$data2 = $this->smarty->createData($data1);
$this->smarty->assign('foo', 'bar');
$data1->assign('blar', 'buh');
$data2->assign('foo2', 'bar2');
$vars = $data2->getTemplateVars(null, false);
$this->assertTrue(is_array($vars));
$this->assertFalse(isset($vars['foo']));
$this->assertEquals("bar2", $vars['foo2']);
$this->assertFalse(isset($vars['blar']));
}
/**
* test get single variables with data object chain search parents disabled
*/
public function testGetSingleTemplateVarsScopeAllNoParents()
{
error_reporting(error_reporting() & ~(E_NOTICE | E_USER_NOTICE));
$data1 = $this->smarty->createData($this->smarty);
$data2 = $this->smarty->createData($data1);
$this->smarty->assign('foo', 'bar');
$data1->assign('blar', 'buh');
$data2->assign('foo2', 'bar2');
$this->assertEquals("", $data2->getTemplateVars('foo', false));
$this->assertEquals("bar2", $data2->getTemplateVars('foo2', false));
$this->assertEquals("", $data2->getTemplateVars('blar', false));
}
}
@@ -169,12 +169,6 @@ class CompileIfTest extends PHPUnit_Smarty
array('{if {counter start=1} == 1}yes{else}no{/if}', 'yes', 'Tag1', $i ++),
array('{if false}false{elseif {counter start=1} == 1}yes{else}no{/if}', 'yes', 'Tag2', $i ++),
array('{if {counter start=1} == 0}false{elseif {counter} == 2}yes{else}no{/if}', 'yes', 'Tag3', $i ++),
array('{if 2 is in ["foo", 2]}yes{else}no{/if}', 'yes', 'IsIn', $i++),
array('{if 2 is in ["foo", "bar"]}yes{else}no{/if}', 'no', 'IsIn2', $i++),
array('{if 2 is not in ["foo", "bar"]}yes{else}no{/if}', 'yes', 'IsNotIn', $i++),
array('{if 2 is not in ["foo", 2]}yes{else}no{/if}', 'no', 'IsNotIn2', $i++),
);
}
@@ -1,71 +1,85 @@
<?php
/**
* Smarty PHPunit tests of modifier
*
* @author Rodney Rehm
*/
/**
* class testing fetch function
* class for modifier tests
*
*
*
*
*/
class PluginFunctionFetchTest extends PHPUnit_Smarty
{
public function setUp(): void
{
$this->setUpSmarty(__DIR__);
}
public function setUp(): void
{
$this->setUpSmarty(__DIR__);
}
public function testInit()
{
$this->cleanDirs();
}
public function testInit()
{
$this->cleanDirs();
}
/**
* test {fetch} from local file
*/
public function testFetchFile()
{
$this->assertStringContainsString(
'ct4hn8nzgm;cgzm;',
$this->smarty->fetch('string:{fetch file="./testfile.txt"}')
);
}
/**
* test {fetch} non-existing file
*/
public function testFetchNonExistingFile()
{
$this->expectException(\Smarty\Exception::class);
$this->expectExceptionMessage('{fetch} cannot read resource \'./no/such/file\'');
$this->smarty->fetch('string:{fetch file="./no/such/file"}');
}
/**
* test {fetch} from UIR
*
*
* @group slow
*/
public function testFetchUri()
{
$this->assertStringContainsString('<title>Preface | Smarty</title>', $this->smarty->fetch('string:{fetch file="https://www.smarty.net/docs/en/preface.tpl"}'));
}
/**
* test {fetch file=...} access to file from path not aloo/wed by security settings
*
* @run InSeparateProcess
*
*/
public function testFetchSecurity()
{
$this->expectException(\Smarty\Exception::class);
$this->expectExceptionMessage('not trusted file path');
$this->cleanDirs();
$dir=$this->smarty->getTemplateDir();
$this->smarty->enableSecurity();
$this->smarty->fetch('string:{fetch file=\''. $dir[0]. '../../../../../etc/passwd\'}');
}
/**
* test {fetch file=...} access to file from path not aloo/wed by security settings
*
* @run InSeparateProcess
*
*/
public function testFetchSecurity2()
{
$this->expectException(\Smarty\Exception::class);
$this->expectExceptionMessage('not trusted file path');
$this->cleanDirs();
$this->smarty->getTemplateDir();
$this->smarty->enableSecurity();
$this->smarty->setTemplateDir('/templates');
$this->smarty->fetch('string:{fetch file="/templates/../etc/passwd"}');
}
/**
* test {fetch} invalid uri
*
*
*
*/
public function testFetchInvalidUri()
{
$this->expectException(\Smarty\Exception::class);
$this->expectExceptionMessage('{fetch} cannot read resource \'https://foo.smarty.net/foo.dat\'');
$this->smarty->fetch('string:{fetch file="https://foo.smarty.net/foo.dat"}');
}
/**
* test {fetch file=...} access to file from path not aloo/wed by security settings
*
* @run InSeparateProcess
*
*/
public function testFetchSecurity()
{
$this->expectException(\Smarty\Exception::class);
$this->expectExceptionMessage('not trusted file path');
$this->cleanDirs();
$dir=$this->smarty->getTemplateDir();
$this->smarty->enableSecurity();
$this->smarty->fetch('string:{fetch file=\''. $dir[0]. '../../../../../etc/passwd\'}');
}
/**
* test {fetch file=...} access to file from path not aloo/wed by security settings
*
* @run InSeparateProcess
*
*/
public function testFetchSecurity2()
{
$this->expectException(\Smarty\Exception::class);
$this->expectExceptionMessage('not trusted file path');
$this->cleanDirs();
$this->smarty->getTemplateDir();
$this->smarty->enableSecurity();
$this->smarty->setTemplateDir('/templates');
$this->smarty->fetch('string:{fetch file="/templates/../etc/passwd"}');
}
}
@@ -1 +0,0 @@
ct4hn8nzgm;cgzm;