Compare commits

...

29 Commits

Author SHA1 Message Date
Simon Wisselink 5de6092a56 added changelog 2024-05-24 00:15:02 +02:00
Scott Baker 32c8339492 Some fixes per Wisskid in the PR 2024-05-15 08:45:01 -07:00
Scott Baker 2042979701 Update example docs to point at libs/ 2024-05-15 08:14:21 -07:00
Scott Baker d0270fb8ea Move to /libs/ 2024-05-15 08:11:01 -07:00
Scott Baker 39db8ce64f Correct a path in the example 2024-05-14 12:28:56 -07:00
Scott Baker 11cc46c942 Add standalone instantiation documentation 2024-05-14 12:23:52 -07:00
Scott Baker d974bde2c4 Add a PSR-4 loading script to allow Smarty to be used without Composer
Fix a directory path
2024-05-14 12:09:25 -07:00
Simon Wisselink 3293a873bd Remove unused attributes from config_load (#1004)
fixes #993
2024-04-29 10:01:40 +02:00
Simon Wisselink 8d53d3cbf2 Merge branch 'release/5.1.0' 2024-04-23 00:22:15 +02:00
Simon Wisselink 47c4864dd1 version bump 2024-04-23 00:22:13 +02:00
Simon Wisselink f411247aa1 Prevent notices on null to string conversion in Template::appendCode (#1002)
Fixes #996
2024-04-19 11:14:07 +02:00
Simon Wisselink 9a8702d937 Corrected invalid classnames in Runtime code for foreach (#1001)
Fixes #1000
2024-04-19 10:42:54 +02:00
Simon Wisselink 5ee4363000 Fix change in signature of getTemplateVars (#995) 2024-04-13 16:53:05 +02:00
kynx 77c0b74e3b Fix docblock types (#992) 2024-04-11 20:31:30 +02:00
Simon Wisselink 34adf4e54c Fixed unit tests to not rely on the existence of any domain or unavailability of internet access when running tests. (#987) 2024-04-06 23:41:20 +02:00
Simon Wisselink 5400b53edf Revert "fix release tooling to support/5 branch"
This reverts commit 569cef71d0.
2024-04-05 22:40:31 +02:00
Simon Wisselink 599bcee13e Fix Smarty::assign() not returning when called with an array as first parameter. (#973)
Fixes #972
2024-04-05 22:38:57 +02:00
Simon Wisselink 569cef71d0 fix release tooling to support/5 branch 2024-04-05 22:38:57 +02:00
Simon Wisselink 0972503aef version bump 2024-04-05 22:38:57 +02:00
Shad 46b15e6365 add is_array modifier doc (#984) 2024-04-03 19:57:09 +02:00
Simon Wisselink beafa5ec31 Merge branch 'release/5.0.1' 2024-03-27 22:57:07 +01:00
Simon Wisselink 82a815aafb version bump 2024-03-27 22:57:04 +01:00
Simon Wisselink 4efa427a87 Fix missing and bogus use lines in src/Smarty.php. (#970) 2024-03-27 22:55:23 +01:00
Wim Wisselink 30b1c5bf6d Deprecation fix for providing a non string value to ctype_digit (#960) 2024-03-27 22:55:23 +01:00
Markus Frühauf 3f871f9f7a Fix docblock information after Smarty 5 namespace changes (#968) 2024-03-27 22:55:23 +01:00
Simon Wisselink cafe5e1e59 Fix missing and bogus use lines in src/Smarty.php. (#970) 2024-03-27 22:53:03 +01:00
Wim Wisselink a58d869502 Deprecation fix for providing a non string value to ctype_digit (#960) 2024-03-27 11:48:38 +01:00
Markus Frühauf 28e11b114b Fix docblock information after Smarty 5 namespace changes (#968) 2024-03-27 11:47:42 +01:00
Simon Wisselink 1da30e76e8 Documented support for is in, added support for is not in. (#955)
* Documented support for `is in`, added support for `is not in`.
Fixes #937
* minor docs improvement
2024-03-25 13:54:02 +01:00
65 changed files with 1627 additions and 1587 deletions
+15
View File
@@ -6,6 +6,21 @@ 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 @@
- Added a PSR-4 loading script to allow Smarty to be used without Composer [#1017](https://github.com/smarty-php/smarty/pull/1017)
-1
View File
@@ -1 +0,0 @@
- 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)
-1
View File
@@ -1 +0,0 @@
- Using stream variables in templates now throws a deprecation notice [#933](https://github.com/smarty-php/smarty/pull/933)
@@ -27,6 +27,30 @@ 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.
@@ -9,7 +9,6 @@
|----------------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| file | Yes | The name of the config file to include |
| section | No | The name of the section to load |
| scope | no | How the scope of the loaded variables are treated, which must be one of local, parent or global. local means variables are loaded into the local template context. parent means variables are loaded into both the local context and the parent template that called it. global means variables are available to all templates. |
## Examples
@@ -3,32 +3,8 @@
`{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 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 |
`{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()*.
## Examples
```smarty
@@ -3,31 +3,8 @@
`{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 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 |
`{/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()*.
## Examples
```smarty
@@ -0,0 +1,9 @@
# 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}
```
+8
View File
@@ -25,9 +25,17 @@ Here's how you create an instance of Smarty in your PHP scripts:
```php
<?php
// Instantiated via composer
require 'vendor/autoload.php';
use Smarty\Smarty;
$smarty = new Smarty();
// or ...
// Instantiated directly
require("/path/to/smarty/libs/Smarty.class.php");
use Smarty\Smarty;
$smarty = new Smarty();
```
Now that the library files are in place, it's time to set up the Smarty
+42
View File
@@ -0,0 +1,42 @@
<?php
/////////////////////////////////////////////////////////////////////
// This is a stub PSR-4 loading script that gets all the pieces of //
// Smarty 5.x loaded without requiring the use of composer. It's //
// not really a 'class' file, but the name is used so we're //
// backwards compatible with previous versions of Smarty. //
// //
// Example: //
// require_once("/path/to/smarty/libs/Smarty.class.php"); //
// //
// $smarty = new Smarty\Smarty; //
// $smarty->testInstall(); //
/////////////////////////////////////////////////////////////////////
define('__SMARTY_DIR', __DIR__ . '/../src/');
// Global function declarations
require_once(__SMARTY_DIR . "/functions.php");
spl_autoload_register(function ($class) {
// Class prefix
$prefix = 'Smarty\\';
// Does the class use the namespace prefix?
$len = strlen($prefix);
if (strncmp($prefix, $class, $len) !== 0) {
// If not, move to the next registered autoloader
return;
}
// Hack off the prefix part
$relative_class = substr($class, $len);
// Build a path to the include file
$file = __SMARTY_DIR . str_replace('\\', '/', $relative_class) . '.php';
// If the file exists, require it
if (file_exists($file)) {
require_once($file);
}
});
+1
View File
@@ -60,6 +60,7 @@ 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,9 +20,6 @@ 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,8 +11,6 @@ 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,8 +6,6 @@ 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,8 +6,6 @@ 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,8 +6,6 @@ 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,7 +6,6 @@ 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,7 +6,6 @@ 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,7 +9,6 @@ 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,7 +6,6 @@ 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,7 +6,6 @@ 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,7 +7,6 @@ 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,7 +7,6 @@ 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,7 +6,6 @@ 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,7 +6,6 @@ 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,7 +9,6 @@ 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,7 +6,6 @@ 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,7 +7,6 @@ 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,7 +6,6 @@ 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,7 +6,6 @@ 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
*/
+3 -5
View File
@@ -43,7 +43,7 @@ class ConfigLoad extends Base {
* @var array
* @see BasePlugin
*/
protected $optional_attributes = ['section', 'scope'];
protected $optional_attributes = ['section'];
/**
* Attribute definition: Overwrites base class.
@@ -51,7 +51,7 @@ class ConfigLoad extends Base {
* @var array
* @see BasePlugin
*/
protected $option_flags = ['nocache', 'noscope'];
protected $option_flags = [];
/**
* Compiles code for the {config_load} tag
@@ -66,9 +66,7 @@ class ConfigLoad extends Base {
{
// check and get attributes
$_attr = $this->getAttributes($compiler, $args);
if ($_attr['nocache'] === true) {
$compiler->trigger_template_error('nocache option not allowed', null, true);
}
// save possible attributes
$conf_file = $_attr['file'];
$section = $_attr['section'] ?? 'null';
+3 -2
View File
@@ -680,7 +680,8 @@ class Template extends BaseCompiler {
*
* @return string
*/
public function appendCode($left, $right) {
public function appendCode(string $left, string $right): string
{
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);
@@ -1056,7 +1057,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, $c);
$code = $this->appendCode($code, (string) $c);
}
$this->prefix_code = [];
return $code;
+5 -10
View File
@@ -109,7 +109,7 @@ class Data
foreach ($tpl_var as $_key => $_val) {
$this->assign($_key, $_val, $nocache, $scope);
}
return;
return $this;
}
switch ($scope ?? $this->getDefaultScope()) {
case self::SCOPE_GLOBAL:
@@ -163,8 +163,6 @@ 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)
@@ -218,7 +216,6 @@ 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)
@@ -227,7 +224,10 @@ class Data
return $this->getValue($varName, $searchParents);
}
return array_merge($this->parent && $searchParents ? $this->parent->getTemplateVars() : [], $this->tpl_vars);
return array_merge(
$this->parent && $searchParents ? $this->parent->getTemplateVars() : [],
array_map(function(Variable $var) { return $var->getValue(); }, $this->tpl_vars)
);
}
/**
@@ -351,7 +351,6 @@ 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()
*/
@@ -371,7 +370,6 @@ 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()
*/
@@ -387,7 +385,6 @@ 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()
*/
@@ -440,7 +437,6 @@ 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()
*/
@@ -462,7 +458,6 @@ class Data
* @returns $this
* @throws \Exception
* @link https://www.smarty.net/docs/en/api.config.load.tpl
*
* @api Smarty::configLoad()
*/
-7
View File
@@ -113,7 +113,6 @@ 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
@@ -234,7 +233,6 @@ 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
@@ -386,7 +384,6 @@ 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
@@ -654,8 +651,6 @@ 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
@@ -703,7 +698,6 @@ 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
*
@@ -726,7 +720,6 @@ 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,8 +13,6 @@ 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,8 +26,6 @@ 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,8 +10,6 @@ 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,8 +27,6 @@ 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,8 +20,6 @@ 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,8 +19,6 @@ 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,8 +27,6 @@ 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,8 +26,6 @@ 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,8 +9,6 @@ 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,8 +37,6 @@ 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,8 +35,6 @@ 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,8 +10,6 @@ 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+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+(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");
}
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_9()
public function yy_r3_10()
{
$this->token = \Smarty\Parser\TemplateParser::TP_AS;
}
public function yy_r3_10()
public function yy_r3_11()
{
$this->token = \Smarty\Parser\TemplateParser::TP_TO;
}
public function yy_r3_11()
public function yy_r3_12()
{
$this->token = \Smarty\Parser\TemplateParser::TP_STEP;
}
public function yy_r3_12()
public function yy_r3_13()
{
$this->token = \Smarty\Parser\TemplateParser::TP_INSTANCEOF;
}
public function yy_r3_13()
public function yy_r3_14()
{
$this->token = \Smarty\Parser\TemplateParser::TP_LOGOP;
}
public function yy_r3_15()
public function yy_r3_16()
{
$this->token = \Smarty\Parser\TemplateParser::TP_SLOGOP;
}
public function yy_r3_17()
public function yy_r3_18()
{
$this->token = \Smarty\Parser\TemplateParser::TP_TLOGOP;
}
public function yy_r3_20()
public function yy_r3_21()
{
$this->token = \Smarty\Parser\TemplateParser::TP_SINGLECOND;
}
public function yy_r3_23()
public function yy_r3_24()
{
$this->token = \Smarty\Parser\TemplateParser::TP_NOT;
}
public function yy_r3_24()
public function yy_r3_25()
{
$this->token = \Smarty\Parser\TemplateParser::TP_TYPECAST;
}
public function yy_r3_28()
public function yy_r3_29()
{
$this->token = \Smarty\Parser\TemplateParser::TP_OPENP;
}
public function yy_r3_29()
public function yy_r3_30()
{
$this->token = \Smarty\Parser\TemplateParser::TP_CLOSEP;
}
public function yy_r3_30()
public function yy_r3_31()
{
$this->token = \Smarty\Parser\TemplateParser::TP_OPENB;
}
public function yy_r3_31()
public function yy_r3_32()
{
$this->token = \Smarty\Parser\TemplateParser::TP_CLOSEB;
}
public function yy_r3_32()
public function yy_r3_33()
{
$this->token = \Smarty\Parser\TemplateParser::TP_PTR;
}
public function yy_r3_33()
public function yy_r3_34()
{
$this->token = \Smarty\Parser\TemplateParser::TP_APTR;
}
public function yy_r3_34()
public function yy_r3_35()
{
$this->token = \Smarty\Parser\TemplateParser::TP_EQUAL;
}
public function yy_r3_35()
public function yy_r3_36()
{
$this->token = \Smarty\Parser\TemplateParser::TP_INCDEC;
}
public function yy_r3_37()
public function yy_r3_38()
{
$this->token = \Smarty\Parser\TemplateParser::TP_UNIMATH;
}
public function yy_r3_39()
public function yy_r3_40()
{
$this->token = \Smarty\Parser\TemplateParser::TP_MATH;
}
public function yy_r3_41()
public function yy_r3_42()
{
$this->token = \Smarty\Parser\TemplateParser::TP_AT;
}
public function yy_r3_42()
public function yy_r3_43()
{
$this->token = \Smarty\Parser\TemplateParser::TP_ARRAYOPEN;
}
public function yy_r3_43()
public function yy_r3_44()
{
$this->token = \Smarty\Parser\TemplateParser::TP_HATCH;
}
public function yy_r3_44()
public function yy_r3_45()
{
// 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_45()
public function yy_r3_46()
{
$this->token = \Smarty\Parser\TemplateParser::TP_NAMESPACE;
}
public function yy_r3_48()
public function yy_r3_49()
{
$this->token = \Smarty\Parser\TemplateParser::TP_ID;
}
public function yy_r3_49()
public function yy_r3_50()
{
$this->token = \Smarty\Parser\TemplateParser::TP_INTEGER;
}
public function yy_r3_50()
public function yy_r3_51()
{
$this->token = \Smarty\Parser\TemplateParser::TP_BACKTICK;
$this->yypopstate();
}
public function yy_r3_51()
public function yy_r3_52()
{
$this->token = \Smarty\Parser\TemplateParser::TP_VERT;
}
public function yy_r3_52()
public function yy_r3_53()
{
$this->token = \Smarty\Parser\TemplateParser::TP_DOT;
}
public function yy_r3_53()
public function yy_r3_54()
{
$this->token = \Smarty\Parser\TemplateParser::TP_COMMA;
}
public function yy_r3_54()
public function yy_r3_55()
{
$this->token = \Smarty\Parser\TemplateParser::TP_SEMICOLON;
}
public function yy_r3_55()
public function yy_r3_56()
{
$this->token = \Smarty\Parser\TemplateParser::TP_DOUBLECOLON;
}
public function yy_r3_56()
public function yy_r3_57()
{
$this->token = \Smarty\Parser\TemplateParser::TP_COLON;
}
public function yy_r3_57()
public function yy_r3_58()
{
$this->token = \Smarty\Parser\TemplateParser::TP_QMARK;
}
public function yy_r3_58()
public function yy_r3_59()
{
$this->token = \Smarty\Parser\TemplateParser::TP_HEX;
}
public function yy_r3_59()
public function yy_r3_60()
{
$this->token = \Smarty\Parser\TemplateParser::TP_SPACE;
}
public function yy_r3_60()
public function yy_r3_61()
{
$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+in\s+~
isin = ~\s+is\s+(not\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(
$this->subtrees[ $last_subtree ]->data,
(string) $this->subtrees[ $last_subtree ]->data,
'<?php echo ' . $subtree->data . ';?>'
);
} elseif ($subtree instanceof DqContent) {
$this->subtrees[ $last_subtree ]->data =
$parser->compiler->appendCode(
$this->subtrees[ $last_subtree ]->data,
(string) $this->subtrees[ $last_subtree ]->data,
'<?php echo "' . $subtree->data . '";?>'
);
} else {
$this->subtrees[ $last_subtree ]->data =
$parser->compiler->appendCode($this->subtrees[ $last_subtree ]->data, $subtree->data);
$parser->compiler->appendCode((string) $this->subtrees[ $last_subtree ]->data, (string) $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();?>', $this->data);
$tmp = $parser->compiler->appendCode('<?php ob_start();?>', (string) $this->data);
$tmp = $parser->compiler->appendCode($tmp, "<?php {$var}=ob_get_clean();?>");
$parser->compiler->appendPrefixCode((string) $tmp);
$parser->compiler->appendPrefixCode($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, $subtree->to_smarty_php($parser));
$text = $parser->compiler->appendCode($text, (string) $subtree->to_smarty_php($parser));
}
$code .= $text;
break;
File diff suppressed because it is too large Load Diff
+14 -5
View File
@@ -663,12 +663,21 @@ expr(res) ::= expr(e1) scond(c). {
res = c . e1 . ')';
}
expr(res) ::= expr(e1) ISIN array(a). {
res = 'in_array('.e1.','.a.')';
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 value(v). {
res = 'in_array('.e1.',(array)'.v.')';
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.')';
}
// null coalescing
@@ -796,7 +805,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();?>', st);
$tmp = $this->compiler->appendCode('<?php ob_start();?>', (string) st);
$this->compiler->appendPrefixCode($this->compiler->appendCode($tmp, "<?php {$prefixVar} = ob_get_clean();?>"));
res = $prefixVar;
}
+8 -10
View File
@@ -116,22 +116,20 @@ 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) {
if ($value instanceof IteratorAggregate) {
public function count($value): int
{
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);
}
/**
+32 -47
View File
@@ -2,6 +2,7 @@
namespace Smarty;
use FilesystemIterator;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
use Smarty\Cacheresource\File;
@@ -12,11 +13,12 @@ use Smarty\Extension\CoreExtension;
use Smarty\Extension\DefaultExtension;
use Smarty\Extension\ExtensionInterface;
use Smarty\Filter\Output\TrimWhitespace;
use Smarty\Resource\BasePlugin;
use Smarty\Smarty\Runtime\CaptureRuntime;
use Smarty\Smarty\Runtime\ForeachRuntime;
use Smarty\Smarty\Runtime\InheritanceRuntime;
use Smarty\Smarty\Runtime\TplFunctionRuntime;
use Smarty\Runtime\CaptureRuntime;
use Smarty\Runtime\DefaultPluginHandlerRuntime;
use Smarty\Runtime\ForeachRuntime;
use Smarty\Runtime\InheritanceRuntime;
use Smarty\Runtime\TplFunctionRuntime;
/**
* Project: Smarty: the PHP compiling template engine
@@ -38,7 +40,6 @@ use Smarty\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
@@ -53,7 +54,7 @@ class Smarty extends \Smarty\TemplateBase {
/**
* smarty version
*/
const SMARTY_VERSION = '5.0.0';
const SMARTY_VERSION = '5.1.0';
/**
* define caching modes
@@ -534,8 +535,6 @@ class Smarty extends \Smarty\TemplateBase {
/**
* Load an additional extension.
*
* @param Base $extension
*
* @return void
*/
public function addExtension(ExtensionInterface $extension) {
@@ -581,7 +580,7 @@ class Smarty extends \Smarty\TemplateBase {
*
* @param string|\Smarty\Security $security_class if a string is used, it must be class-name
*
* @return Smarty current Smarty instance for chaining
* @return static current Smarty instance for chaining
* @throws \Smarty\Exception
*/
public function enableSecurity($security_class = null) {
@@ -592,7 +591,7 @@ class Smarty extends \Smarty\TemplateBase {
/**
* Disable security
*
* @return Smarty current Smarty instance for chaining
* @return static current Smarty instance for chaining
*/
public function disableSecurity() {
$this->security_policy = null;
@@ -606,7 +605,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 Smarty current Smarty instance for chaining
* @return static current Smarty instance for chaining
*/
public function addTemplateDir($template_dir, $key = null, $isConfig = false) {
if ($isConfig) {
@@ -671,7 +670,7 @@ class Smarty extends \Smarty\TemplateBase {
* @param string|array $template_dir directory(s) of template sources
* @param bool $isConfig true for config_dir
*
* @return Smarty current Smarty instance for chaining
* @return static current Smarty instance for chaining
*/
public function setTemplateDir($template_dir, $isConfig = false) {
if ($isConfig) {
@@ -691,7 +690,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 Smarty current Smarty instance for chaining
* @return static current Smarty instance for chaining
*/
public function addConfigDir($config_dir, $key = null) {
return $this->addTemplateDir($config_dir, $key, true);
@@ -713,7 +712,7 @@ class Smarty extends \Smarty\TemplateBase {
*
* @param $config_dir
*
* @return Smarty current Smarty instance for chaining
* @return static current Smarty instance for chaining
*/
public function setConfigDir($config_dir) {
return $this->setTemplateDir($config_dir, true);
@@ -729,7 +728,6 @@ class Smarty extends \Smarty\TemplateBase {
*
* @return $this
* @throws \Smarty\Exception
* @link https://www.smarty.net/docs/en/api.register.plugin.tpl
*
* @api Smarty::registerPlugin()
*/
@@ -756,7 +754,6 @@ 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()
*/
@@ -774,7 +771,6 @@ 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()
*/
@@ -790,7 +786,7 @@ class Smarty extends \Smarty\TemplateBase {
*
* @param null|array|string $plugins_dir
*
* @return Smarty current Smarty instance for chaining
* @return static current Smarty instance for chaining
* @deprecated since 5.0
*/
public function addPluginsDir($plugins_dir) {
@@ -823,7 +819,7 @@ class Smarty extends \Smarty\TemplateBase {
*
* @param string|array $plugins_dir directory(s) of plugins
*
* @return Smarty current Smarty instance for chaining
* @return static current Smarty instance for chaining
* @deprecated since 5.0
*/
public function setPluginsDir($plugins_dir) {
@@ -848,7 +844,6 @@ 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()
*
@@ -885,7 +880,7 @@ class Smarty extends \Smarty\TemplateBase {
*
* @param string $compile_dir directory to store compiled templates in
*
* @return Smarty current Smarty instance for chaining
* @return static current Smarty instance for chaining
*/
public function setCompileDir($compile_dir) {
$this->_normalizeDir('compile_dir', $compile_dir);
@@ -911,7 +906,7 @@ class Smarty extends \Smarty\TemplateBase {
*
* @param string $cache_dir directory to store cached templates in
*
* @return Smarty current Smarty instance for chaining
* @return static current Smarty instance for chaining
*/
public function setCacheDir($cache_dir) {
$this->_normalizeDir('cache_dir', $cache_dir);
@@ -1174,7 +1169,7 @@ class Smarty extends \Smarty\TemplateBase {
/**
* Get Smarty object
*
* @return Smarty
* @return static
*/
public function getSmarty() {
return $this;
@@ -1252,7 +1247,6 @@ 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()
*/
@@ -1272,7 +1266,6 @@ 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()
*/
@@ -1289,7 +1282,6 @@ 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()
*/
@@ -1755,15 +1747,15 @@ class Smarty extends \Smarty\TemplateBase {
// Lazy load runtimes when/if needed
switch ($type) {
case 'Capture':
return $this->runtimes[$type] = new \Smarty\Runtime\CaptureRuntime();
return $this->runtimes[$type] = new CaptureRuntime();
case 'Foreach':
return $this->runtimes[$type] = new \Smarty\Runtime\ForeachRuntime();
return $this->runtimes[$type] = new ForeachRuntime();
case 'Inheritance':
return $this->runtimes[$type] = new \Smarty\Runtime\InheritanceRuntime();
return $this->runtimes[$type] = new InheritanceRuntime();
case 'TplFunction':
return $this->runtimes[$type] = new \Smarty\Runtime\TplFunctionRuntime();
return $this->runtimes[$type] = new TplFunctionRuntime();
case 'DefaultPluginHandler':
return $this->runtimes[$type] = new \Smarty\Runtime\DefaultPluginHandlerRuntime(
return $this->runtimes[$type] = new DefaultPluginHandlerRuntime(
$this->getDefaultPluginHandlerFunc()
);
}
@@ -1803,7 +1795,6 @@ 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
*/
@@ -1851,11 +1842,10 @@ class Smarty extends \Smarty\TemplateBase {
* @param string $type filter type
* @param string $name filter name
*
* @return TemplateBase
* @return static
* @throws \Smarty\Exception
* @api Smarty::unloadFilter()
*
* @link https://www.smarty.net/docs/en/api.unload.filter.tpl
*
* @deprecated since 5.0
*/
@@ -1898,8 +1888,7 @@ class Smarty extends \Smarty\TemplateBase {
* @param string $name name of resource type
* @param Base $resource_handler
*
* @return Smarty
* @link https://www.smarty.net/docs/en/api.register.cacheresource.tpl
* @return static
*
* @api Smarty::registerCacheResource()
*
@@ -1920,9 +1909,8 @@ class Smarty extends \Smarty\TemplateBase {
*
* @param $name
*
* @return Smarty
* @return static
* @api Smarty::unregisterCacheResource()
* @link https://www.smarty.net/docs/en/api.unregister.cacheresource.tpl
*
* @deprecated since 5.0
*
@@ -1954,9 +1942,8 @@ class Smarty extends \Smarty\TemplateBase {
* @param callable $callback
* @param string|null $name optional filter name
*
* @return TemplateBase
* @return static
* @throws \Smarty\Exception
* @link https://www.smarty.net/docs/en/api.register.filter.tpl
*
* @api Smarty::registerFilter()
*/
@@ -2014,11 +2001,10 @@ class Smarty extends \Smarty\TemplateBase {
* @param string $type filter type
* @param callback|string $name the name previously used in ::registerFilter
*
* @return TemplateBase
* @return static
* @throws \Smarty\Exception
* @api Smarty::unregisterFilter()
*
* @link https://www.smarty.net/docs/en/api.unregister.filter.tpl
*
*/
public function unregisterFilter($type, $name) {
@@ -2052,7 +2038,7 @@ class Smarty extends \Smarty\TemplateBase {
* @param array|string $modifiers modifier or list of modifiers
* to add
*
* @return \Smarty|Template
* @return static
* @api Smarty::addDefaultModifiers()
*
*/
@@ -2082,7 +2068,7 @@ class Smarty extends \Smarty\TemplateBase {
* @param array|string $modifiers modifier or list of modifiers
* to set
*
* @return TemplateBase
* @return static
* @api Smarty::setDefaultModifiers()
*
*/
@@ -2131,7 +2117,7 @@ class Smarty extends \Smarty\TemplateBase {
* @throws \Smarty\Exception
*/
public function display($template = null, $cache_id = null, $compile_id = null) {
return $this->returnOrCreateTemplate($template, $cache_id, $compile_id)->display();
$this->returnOrCreateTemplate($template, $cache_id, $compile_id)->display();
}
/**
@@ -2201,7 +2187,6 @@ 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
View File
@@ -604,7 +604,6 @@ 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()
*/
+11 -18
View File
@@ -73,9 +73,8 @@ abstract class TemplateBase extends Data {
* @param bool $format smarty argument format, else traditional
* @param array $block_methods list of block-methods
*
* @return \Smarty|\Smarty\Template
* @return static
* @throws \Smarty\Exception
* @link https://www.smarty.net/docs/en/api.register.object.tpl
*
* @api Smarty::registerObject()
*/
@@ -114,9 +113,8 @@ abstract class TemplateBase extends Data {
*
* @param string $object_name name of object
*
* @return TemplateBase
* @return static
* @api Smarty::unregisterObject()
* @link https://www.smarty.net/docs/en/api.unregister.object.tpl
*
*/
public function unregisterObject($object_name) {
@@ -179,7 +177,6 @@ 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) {
@@ -222,7 +219,6 @@ 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()
*/
@@ -255,7 +251,7 @@ abstract class TemplateBase extends Data {
* @param array|string $literals literal or list of literals
* to addto add
*
* @return TemplateBase
* @return static
* @throws \Smarty\Exception
* @api Smarty::addLiterals()
*
@@ -273,7 +269,7 @@ abstract class TemplateBase extends Data {
* @param array|string $literals literal or list of literals
* to setto set
*
* @return TemplateBase
* @return static
* @throws \Smarty\Exception
* @api Smarty::setLiterals()
*
@@ -316,10 +312,9 @@ abstract class TemplateBase extends Data {
* @param string $class_impl the referenced PHP class to
* register
*
* @return TemplateBase
* @return static
* @throws \Smarty\Exception
* @api Smarty::registerClass()
* @link https://www.smarty.net/docs/en/api.register.class.tpl
*
*/
public function registerClass($class_name, $class_impl) {
@@ -338,7 +333,7 @@ abstract class TemplateBase extends Data {
*
* @param callable $callback class/method name
*
* @return TemplateBase
* @return static
* @throws Exception if $callback is not callable
* @api Smarty::registerDefaultConfigHandler()
*
@@ -358,7 +353,7 @@ abstract class TemplateBase extends Data {
*
* @param callable $callback class/method name
*
* @return TemplateBase
* @return static
* @throws Exception if $callback is not callable
* @api Smarty::registerDefaultTemplateHandler()
*
@@ -377,10 +372,9 @@ abstract class TemplateBase extends Data {
* Registers a resource to fetch a template
*
* @param string $name name of resource type
* @param Smarty\Resource\Base $resource_handler instance of Smarty\Resource\Base
* @param \Smarty\Resource\BasePlugin $resource_handler instance of Smarty\Resource\BasePlugin
*
* @return \Smarty|\Smarty\Template
* @link https://www.smarty.net/docs/en/api.register.resource.tpl
* @return static
*
* @api Smarty::registerResource()
*/
@@ -395,9 +389,8 @@ abstract class TemplateBase extends Data {
*
* @param string $type name of resource type
*
* @return TemplateBase
* @return static
* @api Smarty::unregisterResource()
* @link https://www.smarty.net/docs/en/api.unregister.resource.tpl
*
*/
public function unregisterResource($type) {
@@ -413,7 +406,7 @@ abstract class TemplateBase extends Data {
*
* @param string $tpl_name
*
* @return TemplateBase
* @return static
* @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)) {
} elseif (strlen($string) === 14 && ctype_digit((string)$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");
}
/**
*
* @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"}'));
}
$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");
}
/**
*
*
*/
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"}'));
}
public function testTrustedUri()
{
$this->smarty->security_policy->trusted_uri = array(
'#https://s4otw4nhg.erteorteortert.nusuchtld$#i'
);
/**
* In security mode, accessing $smarty.template_object should be illegal.
*/
public function testSmartyTemplateObject() {
$this->expectException(CompilerException::class);
$this->smarty->display('string:{$smarty.template_object}');
}
$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}');
}
}
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,4 +42,15 @@ 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,112 +1,126 @@
<?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'));
}
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']);
}
/**
* 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 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 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
*/
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 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 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 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));
}
/**
* 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 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,6 +169,12 @@ 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,85 +1,71 @@
<?php
/**
* Smarty PHPunit tests of modifier
*
* @author Rodney Rehm
*/
/**
* class for modifier tests
*
*
*
*
* class testing fetch function
*/
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} 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} 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} 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"}');
}
/**
* 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"}');
}
}
@@ -0,0 +1 @@
ct4hn8nzgm;cgzm;