Compare commits

..

2 Commits

162 changed files with 2428 additions and 4285 deletions
-1
View File
@@ -1 +0,0 @@
github: [wisskid]
+21 -6
View File
@@ -23,7 +23,6 @@ jobs:
matrix:
os:
- ubuntu-latest
- windows-latest
php-version:
- "7.2"
@@ -33,15 +32,31 @@ jobs:
- "8.1"
- "8.2"
- "8.3"
- "8.4"
- "8.5"
compiler:
- default
include:
- os: ubuntu-latest
php-version: "8.0"
compiler: jit
- os: ubuntu-latest
php-version: "8.1"
compiler: jit
- os: ubuntu-latest
php-version: "8.2"
compiler: jit
- os: ubuntu-latest
php-version: "8.3"
compiler: jit
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
- name: Override PHP ini values for JIT compiler
if: matrix.compiler == 'jit'
run: echo "PHP_INI_VALUES::assert.exception=1, zend.assertions=1, opcache.enable=1, opcache.enable_cli=1, opcache.optimization_level=-1, opcache.jit=1255, opcache.jit_buffer_size=32M" >> $GITHUB_ENV
- name: Install PHP with extensions
uses: shivammathur/setup-php@v2
@@ -53,7 +68,7 @@ jobs:
- name: Cache Composer packages
id: composer-cache
uses: actions/cache@v4
uses: actions/cache@v3
with:
path: vendor
key: v5r2-${{ runner.os }}-php-${{ matrix.php-version }}-${{ hashFiles('**/composer.lock') }}
@@ -61,7 +76,7 @@ jobs:
v5r1-${{ runner.os }}-php-${{ matrix.php-version }}-
- name: Install dependencies
run: composer install
uses: php-actions/composer@v6
- name: Run make
run: make -B
+1 -88
View File
@@ -6,98 +6,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
## [5.8.0] - 2026-02-15
- Added support for Backed Enums for php versions >= 8.1 [#1171](https://github.com/smarty-php/smarty/pull/1171)
- Added support for new 'matches' operator doing regex matching [#1169](https://github.com/smarty-php/smarty/pull/1169)
- Update documentation to clarify that include inline is currently not implemented in Smarty v5 [#1152](https://github.com/smarty-php/smarty/issues/1152)
- Support for Laravel Collections style object chaining for objects return from function calls implemented as modifiers [#1151](https://github.com/smarty-php/smarty/issues/1151)
## [5.7.0] - 2025-11-19
- PHP 8.5 support
## [5.6.0] - 2025-10-03
- Added support for shorttags in functions [#1005](https://github.com/smarty-php/smarty/issues/1005)
## [5.5.2] - 2025-08-26
- Fixed escaping of array/object keys in debug_print_var
## [5.5.1] - 2025-05-19
- Fix missing support for loading modifiercompilers from plugin dir in BCPluginsAdapter [#1132](https://github.com/smarty-php/smarty/pull/1132)
## [5.5.0] - 2025-05-03
- Support trailing comma in array [#1013](https://github.com/smarty-php/smarty/issues/1013)
## [5.4.5] - 2025-04-15
- Fixed deprecation notice in StringEval in PHP8.4 [#1119](https://github.com/smarty-php/smarty/issues/1119)
## [5.4.4] - 2025-04-13
- Fix syntax error occurring when registering a function plugin that ends with the string 'close' [#1122](https://github.com/smarty-php/smarty/issues/1122)
- Replace SMARTY_VERSION constant with $smarty.version in debug.tpl [#1073](https://github.com/smarty-php/smarty/issues/1073)
## [5.4.3] - 2024-12-23
- Fix PHP backtraces by qualifying/replacing `call_user_func_array` calls [#1074](https://github.com/smarty-php/smarty/issues/1074)
## [5.4.2] - 2024-11-20
- Support the deprecations introduced in PHP 8.4 and added tests for PHP 8.4 [#1043](https://github.com/smarty-php/smarty/pull/1043)
## [5.4.1] - 2024-08-29
- Enable (and fix) unit tests for Windows [#1046](https://github.com/smarty-php/smarty/pull/1046)
- Fix the use of "extends:" to define the inheritance tree on Windows [#1018](https://github.com/smarty-php/smarty/issues/1018)
## [5.4.0] - 2024-08-14
- Fixing forced OpCache invalidation on every template include, which is resulting in fast raising wasted OpCache memory [#1007](https://github.com/smarty-php/smarty/issues/1007)
- Improvement of auto-escaping [#1030](https://github.com/smarty-php/smarty/pull/1030)
## [5.3.1] - 2024-06-16
- Fixed error when using section with nocache [#1034](https://github.com/smarty-php/smarty/issues/1034)
## [5.3.0] - 2024-05-30
- Fix warning when calling hasVariable for an undefined variable [#977](https://github.com/smarty-php/smarty/issues/977)
- Added `$smarty->prependTemplateDir()` method [#1022](https://github.com/smarty-php/smarty/issues/1022)
## [5.2.0] - 2024-05-28
- Fixed a code injection vulnerability in extends-tag. This addresses CVE-2024-35226.
- Added `$smarty->setCacheModifiedCheck()` setter for cache_modified_check
- Added a PSR-4 loading script to allow Smarty to be used without Composer [#1017](https://github.com/smarty-php/smarty/pull/1017)
## [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.2] - 2024-03-28
- Fix Smarty::assign() not returning $this when called with an array as first parameter [#972](https://github.com/smarty-php/smarty/pull/972)
## [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
### Fixed
- Too many shorthand attributes error when using a modifier as a function with more than 3 parameters in an expression [#949](https://github.com/smarty-php/smarty/issues/949)
-2
View File
@@ -115,7 +115,5 @@ If you are a maintainer, you can publish the document using [mike](https://githu
mike deploy 5.x
```
Then, push the `gh-pages` branch.
## Attribution
This guide is based on the **contributing.md**. [Make your own](https://contributing.md/)!
+1 -9
View File
@@ -7,7 +7,7 @@ Smarty is a template engine for PHP, facilitating the separation of presentation
Read the [documentation](https://smarty-php.github.io/smarty/) to find out how to use it.
## Requirements
Smarty v5 can be run with PHP 7.2 to PHP 8.5.
Smarty v5 can be run with PHP 7.2 to PHP 8.3.
## Installation
Smarty versions 3.1.11 or later can be installed with [Composer](https://getcomposer.org/).
@@ -18,11 +18,3 @@ composer require smarty/smarty
````
More in the [Getting Started](./docs/getting-started.md) section of the docs.
## Sponsors
Smarty is sponsored by:
- Marc Laporte [@marclaporte](https://github.com/marclaporte)
- [Temma](https://github.com/Digicreon/Temma), the MVC framework based on Smarty
Thank you!
+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)
-5
View File
@@ -42,11 +42,6 @@ services:
service: base
build:
dockerfile: ./utilities/testrunners/php83/Dockerfile
php84:
extends:
service: base
build:
dockerfile: ./utilities/testrunners/php84/Dockerfile
volumes:
smarty-code:
+10 -42
View File
@@ -12,27 +12,24 @@ Use `getTemplateDir()` to retrieve the configured paths.
<?php
// set a single directory where the config files are stored
$smarty->setTemplateDir('./templates');
$smarty->setTemplateDir('./config');
// set multiple directories where templates are stored
$smarty->setTemplateDir(['./templates', './templates_2', './templates_3']);
// set multiple directories where config files are stored
$smarty->setTemplateDir(['./config', './config_2', './config_3']);
// add directory where templates files are stored to the current list of dirs
$smarty->addTemplateDir('./templates_1');
// add directory where config files are stored to the current list of dirs
$smarty->addTemplateDir('./config_1');
// add multiple directories to the current list of dirs
$smarty->addTemplateDir([
'./templates_2',
'./templates_3',
'./config_2',
'./config_3',
]);
// chaining of method calls
$smarty->setTemplateDir('./templates')
->addTemplateDir('./templates_1')
->addTemplateDir('./templates_2');
// insert a template dir before exising template dirs
$smarty->prependTemplateDir('./more_important_templates')
$smarty->setTemplateDir('./config')
->addTemplateDir('./config_1')
->addTemplateDir('./config_2');
// get all directories where config files are stored
$template_dirs = $smarty->getTemplateDir();
@@ -143,35 +140,6 @@ Enable auto-escaping for HTML as follows:
$smarty->setEscapeHtml(true);
```
When auto-escaping is enabled, the `|escape` modifier's default mode (`html`) has no effect,
to avoid double-escaping. It is possible to force it with the `force` mode.
Other modes (`htmlall`, `url`, `urlpathinfo`, `quotes`, `javascript`) may be used
with the result you might expect, without double-escaping.
Even when auto-escaping is enabled, you might want to display the content of a variable without
escaping it. To do so, use the `|raw` modifier.
Examples (with auto-escaping enabled):
```smarty
{* these three statements are identical *}
{$myVar}
{$myVar|escape}
{$myVar|escape:'html'}
{* no double-escaping on these statements *}
{$var|escape:'htmlall'}
{$myVar|escape:'url'}
{$myVar|escape:'urlpathinfo'}
{$myVar|escape:'quotes'}
{$myVar|escape:'javascript'}
{* no escaping at all *}
{$myVar|raw}
{* force double-escaping *}
{$myVar|escape:'force'}
```
## Disabling compile check
By default, Smarty tests to see if the
current template has changed since the last time
-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,144 +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) |
| matches | | $a matches $b | regex pattern match | preg_match($b, $a) |
## Regex Matching Operator
The `matches` operator allows you to test if a string matches a regular expression pattern.
### Basic Usage
```smarty
{if "hello" matches "/^[a-z]+$/"}
String matches the pattern!
{/if}
{if $email matches "/^[^@]+@[^@]+\.[^@]+$/"}
Valid email format
{else}
Invalid email format
{/if}
```
### Using Variables
```smarty
{$pattern = '/^[a-zA-Z0-9]{8,}$/'}
{if $password matches $pattern}
Password meets requirements
{else}
Password must be at least 8 alphanumeric characters
{/if}
```
### Pattern Modifiers
The `matches` operator supports all standard PHP regex modifiers:
```smarty
{* Case insensitive matching *}
{if "HELLO" matches "/hello/i"}
Matches (case insensitive)
{/if}
{* Multiline mode *}
{if "line1\nline2" matches "/line2$/m"}
Matches in multiline mode
{/if}
{* Dot matches newlines *}
{if "hello\nworld" matches "/hello.world/s"}
Matches with dotall modifier
{/if}
```
### Complex Conditions
The `matches` operator can be combined with other operators:
```smarty
{if $username matches "/^[a-z]+$/" && $username|length > 3}
Valid username
{else}
Username must be lowercase letters and at least 4 characters
{/if}
{if $input matches "/^[0-9]+$/" || $input matches "/^[a-z]+$/"}
Input is either numeric or lowercase letters
{else}
Invalid input format
{/if}
```
### Practical Examples
**Email Validation:**
```smarty
{if $email matches "/^[^@\s]+@[^@\s]+\.[^@\s]+$/"}
Valid email address
{else}
Please enter a valid email address
{/if}
```
**Password Strength:**
```smarty
{if $password matches "/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$/"}
Strong password
{else}
Password must contain uppercase, lowercase, numbers and be at least 8 characters
{/if}
```
**URL Validation:**
```smarty
{if $url matches "/^https?:\/\/(www\.)?[a-z0-9\-]+(\.[a-z]{2,})+/i"}
Valid URL format
{else}
Please enter a valid URL
{/if}
```
**Numeric Validation:**
```smarty
{if $input matches "/^[0-9]+$/"}
Valid numeric input
{else}
Please enter numbers only
{/if}
```
### Notes
- The `matches` operator uses PHP's `preg_match()` function internally
- Pattern delimiters must be valid regex delimiters (typically `/`)
- Invalid patterns will cause PHP warnings but won't break template execution
- For complex regex patterns, consider using variables for better readability
## 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,6 +9,7 @@
|----------------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 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,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
@@ -47,13 +47,11 @@ available within the included template.
## Option Flags
| Name | Description |
|-----------|--------------------------------------------------------------------------------------|
| nocache | Disables caching of this subtemplate |
| caching | Enable caching of this subtemplate |
| inline \* | If set, merge the compile-code of the subtemplate into the compiled calling template |
\* The `inline` option flag is currently not implemented in Smarty v5. Using it will not trigger an error, however.
| Name | Description |
|---------|--------------------------------------------------------------------------------------|
| nocache | Disables caching of this subtemplate |
| caching | Enable caching of this subtemplate |
| inline | If set, merge the compile-code of the subtemplate into the compiled calling template |
## 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,10 +0,0 @@
# empty
Returns true if var does not exist or has a value that is empty or equal to zero, aka falsey, see conversion to boolean. Otherwise returns false.
## Basic usage
```smarty
{if $myVar|empty}it's an empty variable{/if}
{if empty($myVar)}it's an empty variable{/if}
```
@@ -73,6 +73,6 @@ This snippet is useful for emails, but see also
<a href="mailto:{$EmailAddress|escape:'hex'}">{$EmailAddress|escape:'mail'}</a>
```
See also [auto-escaping](../../api/configuring.md#enabling-auto-escaping), [escaping smarty parsing](../language-basic-syntax/language-escaping.md),
See also [escaping smarty parsing](../language-basic-syntax/language-escaping.md),
[`{mailto}`](../language-custom-functions/language-function-mailto.md) and the [obfuscating email
addresses](../../appendixes/tips.md#obfuscating-e-mail-addresses) pages.
addresses](../../appendixes/tips.md#obfuscating-e-mail-addresses) page.
@@ -1,17 +0,0 @@
# in_array
test if value is contained in an array
## Basic usage
```smarty
{if in_array('value2', $myarray)} value2 is in myarray{/if}
```
Can be replaced by operator *is in*
```smarty
{if 'value2' is in $myarray}value2 is in myarray{/if}
```
See Also [operators](../language-basic-syntax/language-syntax-operators.md)
@@ -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,8 +0,0 @@
# raw
Prevents variable escaping when [auto-escaping](../../api/configuring.md#enabling-auto-escaping) is activated.
## Basic usage
```smarty
{$myVar|raw}
```
@@ -123,89 +123,4 @@ this will output:
```html
name: Zaphod Beeblebrox<br />
email: zaphod@slartibartfast.example.com<br />
```
## Backed Enums (PHP 8.1+)
Smarty supports accessing properties of [backed enums](https://www.php.net/manual/en/language.enumerations.backed.php) introduced in PHP 8.1.
### Accessing Enum Properties
You can access the `name` and `value` properties of backed enum cases:
```smarty
{* Access enum case properties *}
<option id="{MyEnum::Foo->name}">{MyEnum::Foo->value}</option>
```
### Complete Example
```php
<?php
use Smarty\Smarty;
// Define a backed enum
enum Status: string {
case Active = 'active';
case Inactive = 'inactive';
case Pending = 'pending';
}
$smarty = new Smarty();
$smarty->assign('currentStatus', Status::Active);
$smarty->display('template.tpl');
```
`template.tpl`:
```smarty
{* Display enum properties *}
Current status: {$currentStatus->name} (value: {$currentStatus->value})
{* Use in HTML attributes *}
<select name="status">
<option value="{Status::Active->value}" {if $currentStatus->name === 'Active'}selected{/if}>Active</option>
<option value="{Status::Inactive->value}" {if $currentStatus->name === 'Inactive'}selected{/if}>Inactive</option>
<option value="{Status::Pending->value}" {if $currentStatus->name === 'Pending'}selected{/if}>Pending</option>
</select>
```
This would output:
```html
Current status: Active (value: active)
<select name="status">
<option value="active" selected>Active</option>
<option value="inactive">Inactive</option>
<option value="pending">Pending</option>
</select>
```
### Integer-backed Enums
Integer-backed enums work the same way:
```php
<?php
enum Priority: int {
case Low = 1;
case Medium = 2;
case High = 3;
}
$smarty->assign('priority', Priority::High);
```
```smarty
{* Access integer enum properties *}
Priority level: {$priority->value} ({$priority->name})
```
Output:
```html
Priority level: 3 (High)
```
> **Note**: Backed enum support requires PHP 8.1 or higher. The enum must be registered or available in the current namespace.
```
-2
View File
@@ -22,8 +22,6 @@ Some of Smarty's features:
- [Template Inheritance](api/inheritance.md) for
easy management of template content.
- [Plugin](api/extending/introduction.md) architecture
- Regex pattern matching with the [`matches`](designers/language-basic-syntax/language-syntax-operators.md#regex-matching-operator) operator
- Support for PHP 8.1+ [backed enums](designers/language-variables/language-assigned-variables.md#backed-enums-php-81)
## Separation of presentation from application code
- This means templates can certainly contain logic under the condition
+1 -9
View File
@@ -1,7 +1,7 @@
# Getting started
## Requirements
Smarty can be run with PHP 7.2 to PHP 8.5.
Smarty can be run with PHP 7.2 to PHP 8.3.
## Installation
Smarty can be installed with [Composer](https://getcomposer.org/).
@@ -25,17 +25,9 @@ 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
-30
View File
@@ -1,30 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 21.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 343.3 174.5" style="enable-background:new 0 0 343.3 174.5;" xml:space="preserve">
<style type="text/css">
.st0{fill:#E60000;}
.st1{fill:#FFFFFF;}
</style>
<path class="st0" d="M333.8,0H9.5C4.3,0,0,4.3,0,9.5v155.4c0,5.3,4.3,9.5,9.5,9.5h324.3c5.3,0,9.5-4.3,9.5-9.5V9.5
C343.3,4.3,339,0,333.8,0z"/>
<g>
<path class="st1" d="M148.7,58.5c-5.2,0-4.7,4.3-4.7,9.5v38.6c0,5.3,4.3,9.5,9.5,9.5c5.2,0,9.5-4.3,9.5-9.5V81.5
C163,65.7,154,58.5,148.7,58.5L148.7,58.5z"/>
<path class="st1" d="M47.1,72.6c-5.2,0-4.7,4.3-4.7,9.5v24.5c0,5.2,4.3,9.5,9.5,9.5c5.2,0,9.5-4.3,9.5-9.5V95.5
C61.4,79.8,52.4,72.6,47.1,72.6L47.1,72.6z"/>
<path class="st1" d="M200.7,58.3c-7.4,0-13.8,6.9-15.2,11.4c-3-7.6-8.5-11.2-12.2-11.2c-5.2,0-4.7,4.3-4.7,9.5l0.1,9.5v29.1
c0,5.2,4.3,9.5,9.5,9.5c5.2,0,9.5-4.3,9.5-9.5V84.4c0-3.8,1.2-8.4,7-8.4c1.7,0,6.8,0,6.8,8.4v22.2c0,5.2,4.3,9.5,9.5,9.5
c5.2,0,9.5-4.3,9.5-9.5V79.8C220.5,66.5,212.9,58.3,200.7,58.3L200.7,58.3z"/>
<path class="st1" d="M130.8,58.4c-4.4,0-7.7,2.6-9.1,7.1l-6.1,19.9l-6.1-19.7c-1.4-4.6-5.1-7.4-9.6-7.4h-0.9
c-4.5,0-8.2,2.8-9.6,7.4l-5.4,17.5c-1.5-4.9-5.8-31.4-31.1-33c-8.7-0.5-11.2,4.7-12,7.6c-0.7,2.8-0.4,5.2,1.3,7.3
c1.7,2.2,5,2.5,8.9,4C61,73,63.6,81.8,65.9,87.3c0.8,1.9,6.4,20.8,6.4,20.8c1.8,5.2,5.4,8.1,10.2,8.1H83c4.8,0,8.4-2.9,10-7.8
l6.3-19.7l6.2,19.7c1.6,5,5.2,7.8,10,7.8h0.5c4.8,0,8.4-2.9,10.2-8L139.2,71l0-0.1c0.2-0.7,0.6-2.3,0.6-3.6
C139.8,62.3,135.9,58.4,130.8,58.4L130.8,58.4z"/>
<path class="st1" d="M276,99.9c-0.2-0.2-0.4-0.4-0.6-0.6l-14.1-14.4l11.3-9.6l0,0c1.9-1.8,4.1-4.3,4.1-8c0-4.3-3.2-8.7-8.6-8.7
c-3.6,0-5.9,1.9-8,3.9l-15,14.2c-1.6-12.5-9.2-18.4-14-18.4c-4.2,0-4.8,2.7-4.8,6.5c-0.1,1.1-0.1,2.4-0.1,3.7v38
c0,4.9,3.8,9.1,8.6,9.6c0.3,0,0.7,0.1,1,0.1c5.3,0,9.5-4.4,9.5-9.6v-7.5l3.3-3l14.5,16.4c0.6,0.6,1.3,1.3,2.1,1.9
c1.1,0.9,2.5,1.5,4.2,1.8c0.1,0,1.2,0.1,1.8,0.1c4.3-0.1,8.7-3.2,8.6-8.6C279.6,104.1,277.9,101.9,276,99.9L276,99.9z"/>
<circle class="st1" cx="293.3" cy="106.7" r="9.5"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.2 KiB

-22
View File
@@ -1,22 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generator: Adobe Illustrator 25.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1000 1000" style="enable-background:new 0 0 1000 1000;" xml:space="preserve">
<style type="text/css">
.st0{fill:#F5E0B4;}
.st1{fill:#383535;}
.st2{fill:#FBDE3D;}
.st3{fill:#8C919F;}
.st4{fill:#CACED5;}
.st5{fill:#FFFFFF;}
</style>
<g>
<polygon class="st0" points="782.2,925.8 733.4,643.2 996.4,532.7 745.7,396.4 823.6,120.2 560.7,232.2 391.6,0 313.7,274.7 26.5,260.1 194.4,491.3 3.6,705.5 289.4,721.3 340.5,1000 529.1,787 "/>
<path class="st1" d="M706.9,493.4c0-126-102.2-228.2-228.2-228.2c-126,0-228.2,102.2-228.2,228.2c0,81.8,43.1,153.6,107.8,193.8 v202.6l43.5,43.5l0.2-0.2h150.6l0.2,0.2l43.5-43.5V689C662.6,649,706.9,576.4,706.9,493.4z"/>
<path class="st2" d="M682.2,492.9c0-112.7-91.3-204-204-204s-204,91.3-204,204c0,78,43.8,145.8,108.1,180.1v93.6h191.7V673 C638.4,638.7,682.2,571,682.2,492.9z"/>
<g>
<polygon class="st3" points="382.7,790.4 382.7,881.1 412,910.3 544.9,910.3 574.1,881.1 574.1,790.4 "/>
<polygon class="st4" points="540,813.2 540,866.5 527,879.5 540.4,892.9 558.7,874.6 558.9,874.6 558.9,813.2 "/>
</g>
<path class="st5" d="M478.3,310.4c-5,0-9.1,4.1-9.1,9.1c0,5,4.1,9.1,9.1,9.1c90.7,0,164.3,73.5,164.3,164.3c0,5,4.1,9.1,9.1,9.1 s9.1-4.1,9.1-9.1C660.8,392.1,579.1,310.4,478.3,310.4z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

-68
View File
@@ -1,68 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="195mm"
height="43.093071mm"
viewBox="0 0 195 43.093071"
version="1.1"
id="svg1156"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs1153" />
<g
id="layer1"
transform="translate(-6.9662436,-7.8467567)">
<g
id="g21305-1"
style="font-size:33.5139px;line-height:1.25;stroke-width:0.0700042"
transform="translate(1.0553387,0.93988827)">
<g
id="g21248-5">
<rect
style="font-size:33.5139px;line-height:1.25;fill:#107ef4;fill-opacity:1;stroke:none;stroke-width:0.0727743"
id="rect846-9-0-1-2-7-2-1-9"
width="43.093071"
height="43.093071"
x="5.9109049"
y="6.9068685"
ry="2.4179134" />
<path
d="M 22.234889,18.179756 V 36.734061 H 19.567887 V 18.179756 h -6.882585 v -2.35155 h 16.403494 v 2.35155 z"
style="font-size:31.75px;line-height:1.25;font-family:FreeSans;-inkscape-font-specification:FreeSans;fill:#ffffff;stroke-width:0.238978"
id="path16874-7-9-2-4" />
<path
d="m 41.725989,35.328866 v 1.806679 q -0.946355,0.258097 -1.634613,0.258097 -2.380228,0 -2.46626,-2.380228 -1.691969,2.380228 -4.674422,2.380228 -1.548582,0 -2.580969,-0.745614 v 6.395069 H 27.989497 V 21.707084 h 2.380228 v 10.639329 q 0,1.347839 0.831645,2.150808 0.831646,0.802968 2.23684,0.802968 1.864034,0 2.982454,-1.376517 1.11842,-1.405195 1.11842,-3.699389 v -8.517199 h 2.380227 v 12.503362 q 0,1.175775 1.290485,1.175775 0.229419,0 0.516193,-0.05736 z"
style="font-size:31.75px;line-height:1.25;font-family:FreeSans;-inkscape-font-specification:FreeSans;fill:#ffffff;stroke-width:0.238978"
id="path16871-6-1-9-9" />
</g>
<g
aria-label="Temma"
transform="matrix(0.91459055,0,0,0.9686482,-4.3308403,0.67015143)"
id="text87274-2-5-0"
style="font-size:39.8454px;line-height:1.25;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans';fill:#000000;stroke-width:0.0205099">
<path
d="m 89.719297,15.597759 v 4.50253 h -10.24872 v 23.30956 h -5.578356 v -23.30956 h -10.24872 v -4.50253 z"
style="font-weight:600;font-family:Poppins;-inkscape-font-specification:'Poppins Semi-Bold';fill:#000000"
id="path7781-61-0-9" />
<path
d="m 109.19647,31.894528 q 0,1.195362 -0.15939,2.151652 H 92.899673 q 0.199227,2.390724 1.673504,3.745467 1.4743,1.354744 3.62597,1.354744 3.107933,0 4.422823,-2.669642 h 6.01666 q -0.95629,3.187632 -3.66578,5.259593 -2.70948,2.032115 -6.654173,2.032115 -3.18765,0 -5.737768,-1.394588 -2.51026,-1.434435 -3.944694,-4.024386 -1.394589,-2.589951 -1.394589,-5.97681 0,-3.426705 1.394589,-6.016656 1.394589,-2.589951 3.904849,-3.98454 2.510273,-1.394589 5.777613,-1.394589 3.147783,0 5.618193,1.354743 2.51026,1.354744 3.86501,3.865004 1.39459,2.470415 1.39459,5.697893 z m -5.77759,-1.593816 q -0.0398,-2.151652 -1.55397,-3.426705 -1.51411,-1.314898 -3.705613,-1.314898 -2.07197,0 -3.50643,1.275053 -1.394586,1.235207 -1.713349,3.46655 z"
style="font-weight:600;font-family:Poppins;-inkscape-font-specification:'Poppins Semi-Bold';fill:#000000"
id="path7783-8-3-1" />
<path
d="m 140.67428,21.016733 q 4.06423,0 6.53465,2.51026 2.51026,2.470415 2.51026,6.9331 v 12.949756 h -5.57836 V 31.217156 q 0,-2.589951 -1.3149,-3.944695 -1.3149,-1.394589 -3.58608,-1.394589 -2.27119,0 -3.62594,1.394589 -1.31489,1.354744 -1.31489,3.944695 v 12.192693 h -5.57836 V 31.217156 q 0,-2.589951 -1.3149,-3.944695 -1.3149,-1.394589 -3.58608,-1.394589 -2.31104,0 -3.66578,1.394589 -1.3149,1.354744 -1.3149,3.944695 v 12.192693 h -5.57836 V 21.335496 h 5.57836 v 2.669642 q 1.07583,-1.394589 2.74933,-2.191497 1.71336,-0.796908 3.74547,-0.796908 2.58995,0 4.62207,1.115671 2.03211,1.075826 3.14778,3.107942 1.07583,-1.91258 3.10795,-3.068096 2.07196,-1.155517 4.46268,-1.155517 z"
style="font-weight:600;font-family:Poppins;-inkscape-font-specification:'Poppins Semi-Bold';fill:#000000"
id="path7785-7-6-7" />
<path
d="m 182.4322,21.016733 q 4.06423,0 6.53465,2.51026 2.51026,2.470415 2.51026,6.9331 v 12.949756 h -5.57836 V 31.217156 q 0,-2.589951 -1.31489,-3.944695 -1.3149,-1.394589 -3.58609,-1.394589 -2.27119,0 -3.62593,1.394589 -1.3149,1.354744 -1.3149,3.944695 v 12.192693 h -5.57836 V 31.217156 q 0,-2.589951 -1.31489,-3.944695 -1.3149,-1.394589 -3.58609,-1.394589 -2.31103,0 -3.66578,1.394589 -1.3149,1.354744 -1.3149,3.944695 v 12.192693 h -5.57835 V 21.335496 h 5.57835 v 2.669642 q 1.07583,-1.394589 2.74934,-2.191497 1.71335,-0.796908 3.74546,-0.796908 2.58996,0 4.62207,1.115671 2.03212,1.075826 3.14779,3.107942 1.07582,-1.91258 3.10794,-3.068096 2.07196,-1.155517 4.46268,-1.155517 z"
style="font-weight:600;font-family:Poppins;-inkscape-font-specification:'Poppins Semi-Bold';fill:#000000"
id="path7787-9-1-7" />
<path
d="m 195.34205,32.292982 q 0,-3.347014 1.3149,-5.936965 1.35474,-2.589951 3.62593,-3.98454 2.31104,-1.394589 5.14006,-1.394589 2.47041,0 4.3033,0.996135 1.87274,0.996135 2.98841,2.51026 v -3.147787 h 5.6182 v 22.074353 h -5.6182 v -3.227478 q -1.07583,1.553971 -2.98841,2.589952 -1.87273,0.996134 -4.34315,0.996134 -2.78917,0 -5.10021,-1.434434 -2.27119,-1.434434 -3.62593,-4.024385 -1.3149,-2.629797 -1.3149,-6.016656 z m 17.3726,0.07969 q 0,-2.032116 -0.79691,-3.46655 -0.79691,-1.47428 -2.15165,-2.231343 -1.35475,-0.796908 -2.90872,-0.796908 -1.55397,0 -2.86887,0.757063 -1.31489,0.757062 -2.15165,2.231342 -0.79691,1.434435 -0.79691,3.426705 0,1.99227 0.79691,3.506395 0.83676,1.47428 2.15165,2.271188 1.35475,0.796908 2.86887,0.796908 1.55397,0 2.90872,-0.757062 1.35474,-0.796908 2.15165,-2.231343 0.79691,-1.47428 0.79691,-3.506395 z"
style="font-weight:600;font-family:Poppins;-inkscape-font-specification:'Poppins Semi-Bold';fill:#000000"
id="path7789-2-0-1" />
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 6.0 KiB

+1 -30
View File
@@ -8,25 +8,6 @@ It allows you to write **templates**, using **variables**, **modifiers**, **func
<p>
The number of pixels is: {math equation="x * y" x=$height y=$width}.
</p>
<p>
{if $email matches "/^[^@]+@[^@]+\.[^@]+$/"}
Valid email address
{else}
Please enter a valid email
{/if}
</p>
```
```html
<h1>Hello world</h1>
<p>
The number of pixels is: 307200.
</p>
<p>
Valid email address
</p>
```
When this template is rendered, with the value "Hello world" for the variable $title, 640 for $width,
@@ -51,14 +32,4 @@ and 480 for $height, the result is:
- [Troubleshooting](./appendixes/troubleshooting.md)
## Source code
- [Smarty repository at GitHub](https://github.com/smarty-php/smarty)
## Sponsors
### <img src="img/iwink-logo.svg" alt="iWink logo" width="100">
[iWink](https://www.iwink.nl/), fullservice digital agency
### <img src="img/temma-logo.svg" alt="Temma logo" width="100">
[Temma](https://www.temma.net/), the MVC framework based on Smarty
- [Smarty repository at GitHub](https://github.com/smarty-php/smarty)
-14
View File
@@ -49,11 +49,6 @@ $smarty->registerPlugin('modifier', 'my_special_func', 'my_special_func');
But you may want to consider writing a proper [extension](api/extending/extensions.md).
#### Passing parameters by reference
You cannot use plugins that expect a parameter by reference anymore. PHP-function such as `reset()`, `prev()`,
`next()` and `end()` can be registered as plugin, but they won't work because they expect a parameter by
reference and Smarty will try to pass it by value.
### Removed undocumented tags
Smarty 4 still supported some tags that have been carried over from previous version, but have never been documented.
@@ -107,15 +102,6 @@ Search your code for the following changes:
- `$smarty->assignByRef()` should be replaced with `$smarty->assign()`
- `$smarty->loadPlugin()` should be replaced with `$smarty->registerPlugin()`
### Removed undocumented magic API methods
Smarty v4 allowed setting (internal) properties for which no setter existed by using magic methods
that start with either `set` or `get`. This has been removed in Smarty 5.
For example, `$smarty->setErrorUnassigned(true);` would set the `error_unassigned` property.
Every setter of getter that was ever documented or unit tested has been kept.
### Removed PHP constants
The following constants have been removed to prevent global side effects.
-42
View File
@@ -1,42 +0,0 @@
<?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);
}
});
-4
View File
@@ -57,12 +57,9 @@ nav:
- 'date_format': 'designers/language-modifiers/language-modifier-date-format.md'
- 'debug_print_var': 'designers/language-modifiers/language-modifier-debug-print-var.md'
- 'default': 'designers/language-modifiers/language-modifier-default.md'
- 'empty': "designers/language-modifiers/language-modifier-empty.md"
- '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'
- 'in_array': 'designers/language-modifiers/language-modifier-in_array.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'
@@ -70,7 +67,6 @@ nav:
- 'noprint': 'designers/language-modifiers/language-modifier-noprint.md'
- 'number_format': 'designers/language-modifiers/language-modifier-number-format.md'
- 'nl2br': 'designers/language-modifiers/language-modifier-nl2br.md'
- 'raw': 'designers/language-modifiers/language-modifier-raw.md'
- 'regex_replace': 'designers/language-modifiers/language-modifier-regex-replace.md'
- 'replace': 'designers/language-modifiers/language-modifier-replace.md'
- 'round': 'designers/language-modifiers/language-modifier-round.md'
-1
View File
@@ -14,4 +14,3 @@ $COMPOSE_CMD run --rm php80 ./run-tests.sh $@ && \
$COMPOSE_CMD run --rm php81 ./run-tests.sh $@ && \
$COMPOSE_CMD run --rm php82 ./run-tests.sh $@
$COMPOSE_CMD run --rm php83 ./run-tests.sh $@
$COMPOSE_CMD run --rm php84 ./run-tests.sh $@
+1 -1
View File
@@ -14,6 +14,6 @@ class BlockPluginWrapper extends Base {
}
public function handle($params, $content, Template $template, &$repeat) {
return \call_user_func_array($this->callback, [$params, $content, &$template, &$repeat]);
return call_user_func_array($this->callback, [$params, $content, &$template, &$repeat]);
}
}
+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
+1 -1
View File
@@ -44,7 +44,7 @@ abstract class Base
*/
abstract public function process(
Template $_template,
?Cached $cached = null,
Cached $cached = null,
$update = false
);
+1 -1
View File
@@ -139,7 +139,7 @@ abstract class Custom extends Base
*/
public function process(
Template $_smarty_tpl,
?\Smarty\Template\Cached $cached = null,
\Smarty\Template\Cached $cached = null,
$update = false
) {
if (!$cached) {
+9 -3
View File
@@ -99,7 +99,7 @@ class File extends Base
*/
public function process(
Template $_smarty_tpl,
?Cached $cached = null,
Cached $cached = null,
$update = false
) {
$_smarty_tpl->getCached()->setValid(false);
@@ -127,6 +127,8 @@ class File extends Base
&& (!function_exists('ini_get') || strlen(ini_get('opcache.restrict_api'))) < 1
) {
opcache_invalidate($_template->getCached()->filepath, true);
} elseif (function_exists('apc_compile_file')) {
apc_compile_file($_template->getCached()->filepath);
}
$cached = $_template->getCached();
$cached->timestamp = $cached->exists = is_file($cached->filepath);
@@ -221,8 +223,10 @@ class File extends Base
$_filepath = (string)$_file;
// directory ?
if ($_file->isDir()) {
// delete folder if empty
@rmdir($_file->getPathname());
if (!$_cache->isDot()) {
// delete folder if empty
@rmdir($_file->getPathname());
}
} else {
// delete only php files
if (substr($_filepath, -4) !== '.php') {
@@ -275,6 +279,8 @@ class File extends Base
&& (!function_exists('ini_get') || strlen(ini_get("opcache.restrict_api")) < 1)
) {
opcache_invalidate($_filepath, true);
} elseif (function_exists('apc_delete_file')) {
apc_delete_file($_filepath);
}
}
}
+1 -1
View File
@@ -103,7 +103,7 @@ abstract class KeyValueStore extends Base
*/
public function process(
Template $_smarty_tpl,
?Cached $cached = null,
Cached $cached = null,
$update = false
) {
if (!$cached) {
-144
View File
@@ -1,144 +0,0 @@
<?php
namespace Smarty\Compile;
/**
* This class handles compiling the attributes.
*/
class AttributeCompiler
{
/**
* Array of names of required attributes required by tag
*
* @var array
*/
protected $required_attributes = [];
/**
* Array of names of optional attribute required by tag
* use array('_any') if there is no restriction of attributes names
*
* @var array
*/
protected $optional_attributes = [];
/**
* Shorttag attribute order defined by its names
*
* @var array
*/
protected $shorttag_order = [];
/**
* Array of names of valid option flags
*
* @var array
*/
protected $option_flags = [];
public function __construct(
array $required_attributes = [],
array $optional_attributes = [],
array $shorttag_order = [],
array $option_flags = []
) {
$this->required_attributes = $required_attributes;
$this->optional_attributes = $optional_attributes;
$this->shorttag_order = $shorttag_order;
$this->option_flags = $option_flags;
}
/**
* This function checks if the attributes passed are valid
* The attributes passed for the tag to compile are checked against the list of required and
* optional attributes. Required attributes must be present. Optional attributes are check against
* the corresponding list. The keyword '_any' specifies that any attribute will be accepted
* as valid
*
* @param object $compiler compiler object
* @param array $attributes attributes applied to the tag
*
* @return array of mapped attributes for further processing
*/
public function getAttributes($compiler, $attributes)
{
$_indexed_attr = [];
$options = array_fill_keys($this->option_flags, true);
foreach ($attributes as $key => $mixed) {
// shorthand ?
if (!is_array($mixed)) {
// options flag ?
if (isset($options[trim($mixed, '\'"')])) {
$_indexed_attr[trim($mixed, '\'"')] = true;
// shorthand attribute ?
} elseif (isset($this->shorttag_order[$key])) {
$_indexed_attr[$this->shorttag_order[$key]] = $mixed;
} else {
// too many shorthands
$compiler->trigger_template_error('too many shorthand attributes', null, true);
}
// named attribute
} else {
foreach ($mixed as $k => $v) {
// options flag?
if (isset($options[$k])) {
if (is_bool($v)) {
$_indexed_attr[$k] = $v;
} else {
if (is_string($v)) {
$v = trim($v, '\'" ');
}
// Mapping array for boolean option value
static $optionMap = [1 => true, 0 => false, 'true' => true, 'false' => false];
if (isset($optionMap[$v])) {
$_indexed_attr[$k] = $optionMap[$v];
} else {
$compiler->trigger_template_error(
"illegal value '" . var_export($v, true) .
"' for options flag '{$k}'",
null,
true
);
}
}
// must be named attribute
} else {
$_indexed_attr[$k] = $v;
}
}
}
}
// check if all required attributes present
foreach ($this->required_attributes as $attr) {
if (!isset($_indexed_attr[$attr])) {
$compiler->trigger_template_error("missing '{$attr}' attribute", null, true);
}
}
// check for not allowed attributes
if ($this->optional_attributes !== ['_any']) {
$allowedAttributes = array_fill_keys(
array_merge(
$this->required_attributes,
$this->optional_attributes,
$this->option_flags
),
true
);
foreach ($_indexed_attr as $key => $dummy) {
if (!isset($allowedAttributes[$key]) && $key !== 0) {
$compiler->trigger_template_error("unexpected '{$key}' attribute", null, true);
}
}
}
// default 'false' for all options flags not set
foreach ($this->option_flags as $flag) {
if (!isset($_indexed_attr[$flag])) {
$_indexed_attr[$flag] = false;
}
}
return $_indexed_attr;
}
}
+78 -6
View File
@@ -82,12 +82,84 @@ abstract class Base implements CompilerInterface {
* @return array of mapped attributes for further processing
*/
protected function getAttributes($compiler, $attributes) {
return (new AttributeCompiler(
$this->required_attributes,
$this->optional_attributes,
$this->shorttag_order,
$this->option_flags
))->getAttributes($compiler, $attributes);
$_indexed_attr = [];
$options = array_fill_keys($this->option_flags, true);
foreach ($attributes as $key => $mixed) {
// shorthand ?
if (!is_array($mixed)) {
// options flag ?
if (isset($options[trim($mixed, '\'"')])) {
$_indexed_attr[trim($mixed, '\'"')] = true;
// shorthand attribute ?
} elseif (isset($this->shorttag_order[$key])) {
$_indexed_attr[$this->shorttag_order[$key]] = $mixed;
} else {
// too many shorthands
$compiler->trigger_template_error('too many shorthand attributes', null, true);
}
// named attribute
} else {
foreach ($mixed as $k => $v) {
// options flag?
if (isset($options[$k])) {
if (is_bool($v)) {
$_indexed_attr[$k] = $v;
} else {
if (is_string($v)) {
$v = trim($v, '\'" ');
}
// Mapping array for boolean option value
static $optionMap = [1 => true, 0 => false, 'true' => true, 'false' => false];
if (isset($optionMap[$v])) {
$_indexed_attr[$k] = $optionMap[$v];
} else {
$compiler->trigger_template_error(
"illegal value '" . var_export($v, true) .
"' for options flag '{$k}'",
null,
true
);
}
}
// must be named attribute
} else {
$_indexed_attr[$k] = $v;
}
}
}
}
// check if all required attributes present
foreach ($this->required_attributes as $attr) {
if (!isset($_indexed_attr[$attr])) {
$compiler->trigger_template_error("missing '{$attr}' attribute", null, true);
}
}
// check for not allowed attributes
if ($this->optional_attributes !== ['_any']) {
$allowedAttributes = array_fill_keys(
array_merge(
$this->required_attributes,
$this->optional_attributes,
$this->option_flags
),
true
);
foreach ($_indexed_attr as $key => $dummy) {
if (!isset($allowedAttributes[$key]) && $key !== 0) {
$compiler->trigger_template_error("unexpected '{$key}' attribute", null, true);
}
}
}
// default 'false' for all options flags not set
foreach ($this->option_flags as $flag) {
if (!isset($_indexed_attr[$flag])) {
$_indexed_attr[$flag] = false;
}
}
return $_indexed_attr;
}
/**
+16 -20
View File
@@ -3,18 +3,24 @@
* Smarty Internal Plugin Compile Registered Function
* Compiles code for the execution of a registered function
*
* @author Uwe Tews
*/
namespace Smarty\Compile;
use Smarty\Compiler\Template;
use Smarty\FunctionHandler\AttributeFunctionHandlerInterface;
use Smarty\CompilerException;
/**
* Smarty Internal Plugin Compile Registered Function Class
*
*/
class FunctionCallCompiler extends Base {
/**
* Attribute definition: Overwrites base class.
*
@@ -45,27 +51,17 @@ class FunctionCallCompiler extends Base {
*/
public function compile($args, Template $compiler, $parameter = [], $tag = null, $function = null): string
{
// check and get attributes
$_attr = $this->getAttributes($compiler, $args);
unset($_attr['nocache']);
$_paramsArray = $this->formatParamsArray($_attr);
$_params = 'array(' . implode(',', $_paramsArray) . ')';
if ($functionHandler = $compiler->getSmarty()->getFunctionHandler($function)) {
$attribute_overrides = [];
if ($functionHandler instanceof AttributeFunctionHandlerInterface) {
$attribute_overrides = $functionHandler->getSupportedAttributes();
}
// check and get attributes
$_attr = (new AttributeCompiler(
$attribute_overrides['required_attributes'] ?? $this->required_attributes,
$attribute_overrides['optional_attributes'] ?? $this->optional_attributes,
$attribute_overrides['shorttag_order'] ?? $this->shorttag_order,
$attribute_overrides['option_flags'] ?? $this->option_flags
))->getAttributes($compiler, $args);
unset($_attr['nocache']);
$_paramsArray = $this->formatParamsArray($_attr);
$_params = 'array(' . implode(',', $_paramsArray) . ')';
// not cacheable?
$compiler->tag_nocache = $compiler->tag_nocache || !$functionHandler->isCacheable();
$output = "\$_smarty_tpl->getSmarty()->getFunctionHandler(" . var_export($function, true) . ")";
@@ -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
*/
@@ -24,32 +25,22 @@ class EscapeModifierCompiler extends Base {
}
switch ($esc_type) {
case 'html':
case 'force':
// in case of auto-escaping, and without the 'force' option, no double-escaping
if ($compiler->getSmarty()->escape_html && $esc_type != 'force')
return $params[0];
// otherwise, escape the variable
return 'htmlspecialchars((string)' . $params[ 0 ] . ', ENT_QUOTES, ' . var_export($char_set, true) . ', ' .
var_export($double_encode, true) . ')';
// no break
case 'htmlall':
$compiler->setRawOutput(true);
return 'htmlentities(mb_convert_encoding((string)' . $params[ 0 ] . ', \'UTF-8\', ' .
var_export($char_set, true) . '), ENT_QUOTES, \'UTF-8\', ' .
var_export($double_encode, true) . ')';
// no break
case 'url':
$compiler->setRawOutput(true);
return 'rawurlencode((string)' . $params[ 0 ] . ')';
case 'urlpathinfo':
$compiler->setRawOutput(true);
return 'str_replace("%2F", "/", rawurlencode((string)' . $params[ 0 ] . '))';
case 'quotes':
$compiler->setRawOutput(true);
// escape unescaped single quotes
return 'preg_replace("%(?<!\\\\\\\\)\'%", "\\\'", (string)' . $params[ 0 ] . ')';
case 'javascript':
$compiler->setRawOutput(true);
// escape quotes and backslashes, newlines, etc.
// see https://html.spec.whatwg.org/multipage/scripting.html#restrictions-for-contents-of-script-elements
return 'strtr((string)' .
@@ -63,4 +54,4 @@ class EscapeModifierCompiler extends Base {
}
return '$_smarty_tpl->getSmarty()->getModifierCallback(\'escape\')(' . join(', ', $params) . ')';
}
}
}
@@ -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 {
@@ -1,21 +0,0 @@
<?php
namespace Smarty\Compile\Modifier;
use Smarty\Exception;
/**
* Smarty raw modifier plugin
* Type: modifier
* Name: raw
* Purpose: when escaping is enabled by default, generates a raw output of a variable
*
* @author Amaury Bouchard
*/
class RawModifierCompiler extends Base {
public function compile($params, \Smarty\Compiler\Template $compiler) {
$compiler->setRawOutput(true);
return ($params[0]);
}
}
@@ -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
*/
+1 -1
View File
@@ -75,7 +75,7 @@ class ModifierCompiler extends Base {
}
}
}
return (string)$output;
return $output;
}
/**
+1 -2
View File
@@ -82,13 +82,12 @@ class PrintExpressionCompiler extends Base {
$output = $compiler->compileModifier($modifierlist, $output);
}
if ($compiler->getTemplate()->getSmarty()->escape_html && !$compiler->isRawOutput()) {
if ($compiler->getTemplate()->getSmarty()->escape_html) {
$output = "htmlspecialchars((string) ({$output}), ENT_QUOTES, '" . addslashes(\Smarty\Smarty::$_CHARSET) . "')";
}
}
$output = "<?php echo {$output};?>\n";
$compiler->setRawOutput(false);
}
return $output;
}
+5 -3
View File
@@ -43,7 +43,7 @@ class ConfigLoad extends Base {
* @var array
* @see BasePlugin
*/
protected $optional_attributes = ['section'];
protected $optional_attributes = ['section', 'scope'];
/**
* Attribute definition: Overwrites base class.
@@ -51,7 +51,7 @@ class ConfigLoad extends Base {
* @var array
* @see BasePlugin
*/
protected $option_flags = [];
protected $option_flags = ['nocache', 'noscope'];
/**
* Compiles code for the {config_load} tag
@@ -66,7 +66,9 @@ 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';
+62 -2
View File
@@ -32,7 +32,7 @@ class ExtendsTag extends Inheritance {
*
* @var array
*/
protected $optional_attributes = [];
protected $optional_attributes = ['extends_resource'];
/**
* Attribute definition: Overwrites base class.
@@ -64,7 +64,29 @@ class ExtendsTag extends Inheritance {
}
// add code to initialize inheritance
$this->registerInit($compiler, true);
$this->compileEndChild($compiler, $_attr['file']);
$file = trim($_attr['file'], '\'"');
if (strlen($file) > 8 && substr($file, 0, 8) === 'extends:') {
// generate code for each template
$files = array_reverse(explode('|', substr($file, 8)));
$i = 0;
foreach ($files as $file) {
if ($file[0] === '"') {
$file = trim($file, '".');
} else {
$file = "'{$file}'";
}
$i++;
if ($i === count($files) && isset($_attr['extends_resource'])) {
$this->compileEndChild($compiler);
}
$this->compileInclude($compiler, $file);
}
if (!isset($_attr['extends_resource'])) {
$this->compileEndChild($compiler);
}
} else {
$this->compileEndChild($compiler, $_attr['file']);
}
return '';
}
@@ -84,4 +106,42 @@ class ExtendsTag extends Inheritance {
(isset($template) ? ", {$template}, \$_smarty_current_dir" : '') . ");\n?>"
);
}
/**
* Add code for including subtemplate to end of template
*
* @param \Smarty\Compiler\Template $compiler
* @param string $template subtemplate name
*
* @throws \Smarty\CompilerException
* @throws \Smarty\Exception
*/
private function compileInclude(\Smarty\Compiler\Template $compiler, $template) {
$compiler->getParser()->template_postfix[] = new \Smarty\ParseTree\Tag(
$compiler->getParser(),
$compiler->compileTag(
'include',
[
$template,
['scope' => 'parent'],
]
)
);
}
/**
* Create source code for {extends} from source components array
*
* @param \Smarty\Template $template
*
* @return string
*/
public static function extendsSourceArrayCode(\Smarty\Template $template) {
$resources = [];
foreach ($template->getSource()->components as $source) {
$resources[] = $source->resource;
}
return $template->getLeftDelimiter() . 'extends file=\'extends:' . join('|', $resources) .
'\' extends_resource=true' . $template->getRightDelimiter();
}
}
+1 -1
View File
@@ -99,7 +99,7 @@ class Section extends ForeachSection {
if ($compiler->tag_nocache) {
// push a {nocache} tag onto the stack to prevent caching of this block
$this->openTag($compiler, 'nocache');
$this->openTag('nocache');
}
$this->openTag($compiler, 'section', ['section', $compiler->tag_nocache]);
+1 -1
View File
@@ -33,7 +33,7 @@ class SectionClose extends Base {
if ($nocache_pushed) {
// pop the pushed virtual nocache tag
$this->closeTag($compiler, 'nocache');
$this->closeTag('nocache');
}
$output = "<?php\n";
+1 -1
View File
@@ -41,7 +41,7 @@ class CodeFrame
$content = '',
$functions = '',
$cache = false,
?\Smarty\Compiler\Template $compiler = null
\Smarty\Compiler\Template $compiler = null
) {
// build property code
$properties[ 'version' ] = \Smarty\Smarty::SMARTY_VERSION;
+26 -66
View File
@@ -313,12 +313,6 @@ class Template extends BaseCompiler {
*/
private $noCacheStackDepth = 0;
/**
* disabled auto-escape (when set to true, the next variable output is not auto-escaped)
*
* @var boolean
*/
private $raw_output = false;
/**
* Initialize compiler
@@ -374,7 +368,7 @@ class Template extends BaseCompiler {
* @throws CompilerException
* @throws Exception
*/
public function compileTemplateSource(\Smarty\Template $template, ?\Smarty\Compiler\Template $parent_compiler = null) {
public function compileTemplateSource(\Smarty\Template $template, \Smarty\Compiler\Template $parent_compiler = null) {
try {
// save template object in compiler class
$this->template = $template;
@@ -409,37 +403,21 @@ class Template extends BaseCompiler {
}
// get template source
if (!empty($this->template->getSource()->components)) {
$_compiled_code = '<?php $_smarty_tpl->getInheritance()->init($_smarty_tpl, true); ?>';
$i = 0;
$reversed_components = array_reverse($this->template->getSource()->components);
foreach ($reversed_components as $source) {
$i++;
if ($i === count($reversed_components)) {
$_compiled_code .= '<?php $_smarty_tpl->getInheritance()->endChild($_smarty_tpl); ?>';
}
$_compiled_code .= $this->compileTag(
'include',
[
var_export($source->resource, true),
['scope' => 'parent'],
]
);
}
$_compiled_code = $this->smarty->runPostFilters($_compiled_code, $this->template);
// we have array of inheritance templates by extends: resource
// generate corresponding source code sequence
$_content =
ExtendsTag::extendsSourceArrayCode($this->template);
} else {
// get template source
$_content = $this->template->getSource()->getContent();
$_compiled_code = $this->smarty->runPostFilters(
$this->doCompile(
$this->smarty->runPreFilters($_content, $this->template),
true
),
$this->template
);
}
$_compiled_code = $this->smarty->runPostFilters(
$this->doCompile(
$this->smarty->runPreFilters($_content, $this->template),
true
),
$this->template
);
} catch (\Exception $e) {
if ($this->smarty->debugging) {
$this->smarty->getDebug()->end_compile($this->template);
@@ -505,7 +483,7 @@ class Template extends BaseCompiler {
*
* @return string
*/
public function triggerTagNoCache($variable): void {
public function compileVariable($variable) {
if (!strpos($variable, '(')) {
// not a variable variable
$var = trim($variable, '\'');
@@ -516,6 +494,7 @@ class Template extends BaseCompiler {
false
)->isNocache();
}
return '$_smarty_tpl->getValue(' . $variable . ')';
}
/**
@@ -664,7 +643,7 @@ class Template extends BaseCompiler {
$script = null;
$cacheable = true;
$result = \call_user_func_array(
$result = call_user_func_array(
$defaultPluginHandlerFunc,
[
$tag,
@@ -701,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);
@@ -1078,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;
@@ -1146,12 +1124,12 @@ class Template extends BaseCompiler {
}
// check if tag is a function
if ($this->smarty->getFunctionHandler($tag)) {
if (!isset($this->smarty->security_policy) || $this->smarty->security_policy->isTrustedTag($tag, $this)) {
if ($this->smarty->getFunctionHandler($base_tag)) {
if (!isset($this->smarty->security_policy) || $this->smarty->security_policy->isTrustedTag($base_tag, $this)) {
return (new \Smarty\Compile\PrintExpressionCompiler())->compile(
['nofilter'], // functions are never auto-escaped
$this,
['value' => $this->compileFunctionCall($tag, $args, $parameter)]
['value' => $this->compileFunctionCall($base_tag, $args, $parameter)]
);
}
}
@@ -1164,16 +1142,16 @@ class Template extends BaseCompiler {
}
// the default plugin handler is a handler of last resort, it may also handle not specifically registered tags.
if ($callback = $this->getPluginFromDefaultHandler($tag, Smarty::PLUGIN_COMPILER)) {
if ($callback = $this->getPluginFromDefaultHandler($base_tag, Smarty::PLUGIN_COMPILER)) {
if (!empty($parameter['modifierlist'])) {
throw new CompilerException('No modifiers allowed on ' . $tag);
throw new CompilerException('No modifiers allowed on ' . $base_tag);
}
$tagCompiler = new \Smarty\Compile\Tag\BCPluginWrapper($callback);
return $tagCompiler->compile($args, $this, $parameter);
}
if ($this->getPluginFromDefaultHandler($base_tag, Smarty::PLUGIN_FUNCTION)) {
return $this->defaultHandlerFunctionCallCompiler->compile($args, $this, $parameter, $tag, $tag);
return $this->defaultHandlerFunctionCallCompiler->compile($args, $this, $parameter, $tag, $base_tag);
}
if ($this->getPluginFromDefaultHandler($base_tag, Smarty::PLUGIN_BLOCK)) {
@@ -1280,10 +1258,9 @@ class Template extends BaseCompiler {
}
// call post compile callbacks
foreach ($this->postCompileCallbacks as $cb) {
$callbackFunction = $cb[0];
$parameters = $cb;
$parameters[0] = $this;
$callbackFunction(...$parameters);
$parameter = $cb;
$parameter[0] = $this;
call_user_func_array($cb[0], $parameter);
}
// return compiled code
return $this->prefixCompiledCode . $this->parser->retvalue . $this->postfixCompiledCode;
@@ -1492,21 +1469,4 @@ class Template extends BaseCompiler {
public function getTagStack(): array {
return $this->_tag_stack;
}
/**
* Should the next variable output be raw (true) or auto-escaped (false)
* @return bool
*/
public function isRawOutput(): bool {
return $this->raw_output;
}
/**
* Should the next variable output be raw (true) or auto-escaped (false)
* @param bool $raw_output
* @return void
*/
public function setRawOutput(bool $raw_output): void {
$this->raw_output = $raw_output;
}
}
+2 -2
View File
@@ -16,14 +16,14 @@ class CompilerException extends Exception {
* @param int $code The Exception code.
* @param string|null $filename The filename where the exception is thrown.
* @param int|null $line The line number where the exception is thrown.
* @param \Throwable|null $previous The previous exception used for the exception chaining.
* @param Throwable|null $previous The previous exception used for the exception chaining.
*/
public function __construct(
string $message = "",
int $code = 0,
?string $filename = null,
?int $line = null,
?\Throwable $previous = null
Throwable $previous = null
) {
parent::__construct($message, $code, $previous);
+11 -6
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);
}
/**
@@ -290,7 +290,7 @@ class Data
* @return bool
*/
public function hasVariable($varName): bool {
return !($this->getVariable($varName, true, false) instanceof UndefinedVariable);
return !($this->getVariable($varName) instanceof UndefinedVariable);
}
/**
@@ -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()
*/
+2 -2
View File
@@ -168,6 +168,7 @@ class BCPluginsAdapter extends Base {
}
public function loadPluginsFromDir(string $path) {
foreach([
'function',
'modifier',
@@ -176,7 +177,6 @@ class BCPluginsAdapter extends Base {
'prefilter',
'postfilter',
'outputfilter',
'modifiercompiler',
] as $type) {
foreach (glob($path . $type . '.?*.php') as $filename) {
$pluginName = $this->getPluginNameFromFilename($filename);
@@ -226,4 +226,4 @@ class BCPluginsAdapter extends Base {
return $matches[1];
}
}
}
+1 -1
View File
@@ -26,7 +26,7 @@ class CallbackWrapper {
public function handle(...$params) {
try {
return ($this->callback)(...$params);
return call_user_func_array($this->callback, $params);
} catch (\ArgumentCountError $e) {
throw new Exception("Invalid number of arguments to modifier " . $this->modifierName);
}
+10 -4
View File
@@ -35,7 +35,6 @@ class DefaultExtension extends Base {
case 'lower': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\LowerModifierCompiler(); break;
case 'nl2br': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\Nl2brModifierCompiler(); break;
case 'noprint': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\NoPrintModifierCompiler(); break;
case 'raw': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\RawModifierCompiler(); break;
case 'round': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\RoundModifierCompiler(); break;
case 'str_repeat': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\StrRepeatModifierCompiler(); break;
case 'string_format': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\StringFormatModifierCompiler(); break;
@@ -114,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
@@ -234,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
@@ -320,7 +321,7 @@ class DefaultExtension extends Base {
break;
}
foreach ($var as $curr_key => $curr_val) {
$results .= '<br>' . str_repeat('&nbsp;', $depth * 2) . '<b>' . htmlspecialchars(strtr($curr_key, $_replace)) .
$results .= '<br>' . str_repeat('&nbsp;', $depth * 2) . '<b>' . strtr($curr_key, $_replace) .
'</b> =&gt; ' .
$this->smarty_modifier_debug_print_var($curr_val, $max, $length, ++$depth, $objects);
$depth--;
@@ -338,7 +339,7 @@ class DefaultExtension extends Base {
}
$objects[] = $var;
foreach ($object_vars as $curr_key => $curr_val) {
$results .= '<br>' . str_repeat('&nbsp;', $depth * 2) . '<b> -&gt;' . htmlspecialchars(strtr($curr_key, $_replace)) .
$results .= '<br>' . str_repeat('&nbsp;', $depth * 2) . '<b> -&gt;' . strtr($curr_key, $_replace) .
'</b> = ' . $this->smarty_modifier_debug_print_var($curr_val, $max, $length, ++$depth, $objects);
$depth--;
}
@@ -385,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
@@ -652,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
@@ -699,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
*
@@ -721,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
@@ -754,4 +760,4 @@ class DefaultExtension extends Base {
return $string;
}
}
}
-77
View File
@@ -1,77 +0,0 @@
<?php
namespace Smarty\FunctionHandler;
use Smarty\Template;
/**
* Abstract implementation for function handlers which support custom attributes
*/
abstract class AttributeBase implements AttributeFunctionHandlerInterface
{
/**
* Array of names of required attribute required by tag
*
* @var array
*/
protected array $required_attributes = [];
/**
* Array of names of optional attribute required by tag
* use array('_any') if there is no restriction of attributes names
*
* @var array
*/
protected array $optional_attributes = [];
/**
* Shorttag attribute order defined by its names
*
* @var array
*/
protected array $shorttag_order = [];
/**
* Array of names of valid option flags
*
* @var array
*/
protected array $option_flags = [];
/**
* Return whether the output is cacheable.
* @var bool
*/
protected bool $cacheable = true;
/**
* Return whether the output is cacheable.
* @return bool
*/
public function isCacheable(): bool
{
return $this->cacheable;
}
/**
* Function body
* @param mixed $params The supplied parameters.
* @param Smarty\Template $template
* @return mixed
*/
abstract public function handle($params, Template $template): ?string;
/**
* Return the support attributes for this function.
* @return array<string, array>
*/
public function getSupportedAttributes(): array
{
return [
'required_attributes' => $this->required_attributes,
'optional_attributes' => $this->optional_attributes,
'shorttag_order' => $this->shorttag_order,
'option_flags' => $this->option_flags,
];
}
}
@@ -1,15 +0,0 @@
<?php
namespace Smarty\FunctionHandler;
/**
* Function handler interface with support for specifying supported properties
*/
interface AttributeFunctionHandlerInterface extends FunctionHandlerInterface
{
/**
* Returns an array with the supported attributes, flags, and shorttags
* @return array<string, array>
*/
public function getSupportedAttributes(): array;
}
+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 -45
View File
@@ -160,7 +160,6 @@ class TemplateLexer
'LOGOP' => '"<", "==" ... logical operator',
'TLOGOP' => '"lt", "eq" ... logical operator; "is div by" ... if condition',
'SCOND' => '"is even" ... if condition',
'MATCHES' => '"matches" regex operator',
);
/**
@@ -568,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+matches\\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);
@@ -660,127 +659,122 @@ class TemplateLexer
$this->token = \Smarty\Parser\TemplateParser::TP_ISIN;
}
public function yy_r3_10()
{
$this->token = \Smarty\Parser\TemplateParser::TP_MATCHES;
}
public function yy_r3_11()
public function yy_r3_9()
{
$this->token = \Smarty\Parser\TemplateParser::TP_AS;
}
public function yy_r3_12()
public function yy_r3_10()
{
$this->token = \Smarty\Parser\TemplateParser::TP_TO;
}
public function yy_r3_13()
public function yy_r3_11()
{
$this->token = \Smarty\Parser\TemplateParser::TP_STEP;
}
public function yy_r3_14()
public function yy_r3_12()
{
$this->token = \Smarty\Parser\TemplateParser::TP_INSTANCEOF;
}
public function yy_r3_15()
public function yy_r3_13()
{
$this->token = \Smarty\Parser\TemplateParser::TP_LOGOP;
}
public function yy_r3_17()
public function yy_r3_15()
{
$this->token = \Smarty\Parser\TemplateParser::TP_SLOGOP;
}
public function yy_r3_19()
public function yy_r3_17()
{
$this->token = \Smarty\Parser\TemplateParser::TP_TLOGOP;
}
public function yy_r3_22()
public function yy_r3_20()
{
$this->token = \Smarty\Parser\TemplateParser::TP_SINGLECOND;
}
public function yy_r3_25()
public function yy_r3_23()
{
$this->token = \Smarty\Parser\TemplateParser::TP_NOT;
}
public function yy_r3_26()
public function yy_r3_24()
{
$this->token = \Smarty\Parser\TemplateParser::TP_TYPECAST;
}
public function yy_r3_30()
public function yy_r3_28()
{
$this->token = \Smarty\Parser\TemplateParser::TP_OPENP;
}
public function yy_r3_31()
public function yy_r3_29()
{
$this->token = \Smarty\Parser\TemplateParser::TP_CLOSEP;
}
public function yy_r3_32()
public function yy_r3_30()
{
$this->token = \Smarty\Parser\TemplateParser::TP_OPENB;
}
public function yy_r3_33()
public function yy_r3_31()
{
$this->token = \Smarty\Parser\TemplateParser::TP_CLOSEB;
}
public function yy_r3_34()
public function yy_r3_32()
{
$this->token = \Smarty\Parser\TemplateParser::TP_PTR;
}
public function yy_r3_35()
public function yy_r3_33()
{
$this->token = \Smarty\Parser\TemplateParser::TP_APTR;
}
public function yy_r3_36()
public function yy_r3_34()
{
$this->token = \Smarty\Parser\TemplateParser::TP_EQUAL;
}
public function yy_r3_37()
public function yy_r3_35()
{
$this->token = \Smarty\Parser\TemplateParser::TP_INCDEC;
}
public function yy_r3_39()
public function yy_r3_37()
{
$this->token = \Smarty\Parser\TemplateParser::TP_UNIMATH;
}
public function yy_r3_41()
public function yy_r3_39()
{
$this->token = \Smarty\Parser\TemplateParser::TP_MATH;
}
public function yy_r3_43()
public function yy_r3_41()
{
$this->token = \Smarty\Parser\TemplateParser::TP_AT;
}
public function yy_r3_44()
public function yy_r3_42()
{
$this->token = \Smarty\Parser\TemplateParser::TP_ARRAYOPEN;
}
public function yy_r3_45()
public function yy_r3_43()
{
$this->token = \Smarty\Parser\TemplateParser::TP_HATCH;
}
public function yy_r3_46()
public function yy_r3_44()
{
// resolve conflicts with shorttag and right_delimiter starting with '='
@@ -792,73 +786,73 @@ class TemplateLexer
$this->token = \Smarty\Parser\TemplateParser::TP_ATTR;
}
}
public function yy_r3_47()
public function yy_r3_45()
{
$this->token = \Smarty\Parser\TemplateParser::TP_NAMESPACE;
}
public function yy_r3_50()
public function yy_r3_48()
{
$this->token = \Smarty\Parser\TemplateParser::TP_ID;
}
public function yy_r3_51()
public function yy_r3_49()
{
$this->token = \Smarty\Parser\TemplateParser::TP_INTEGER;
}
public function yy_r3_52()
public function yy_r3_50()
{
$this->token = \Smarty\Parser\TemplateParser::TP_BACKTICK;
$this->yypopstate();
}
public function yy_r3_53()
public function yy_r3_51()
{
$this->token = \Smarty\Parser\TemplateParser::TP_VERT;
}
public function yy_r3_54()
public function yy_r3_52()
{
$this->token = \Smarty\Parser\TemplateParser::TP_DOT;
}
public function yy_r3_55()
public function yy_r3_53()
{
$this->token = \Smarty\Parser\TemplateParser::TP_COMMA;
}
public function yy_r3_56()
public function yy_r3_54()
{
$this->token = \Smarty\Parser\TemplateParser::TP_SEMICOLON;
}
public function yy_r3_57()
public function yy_r3_55()
{
$this->token = \Smarty\Parser\TemplateParser::TP_DOUBLECOLON;
}
public function yy_r3_58()
public function yy_r3_56()
{
$this->token = \Smarty\Parser\TemplateParser::TP_COLON;
}
public function yy_r3_59()
public function yy_r3_57()
{
$this->token = \Smarty\Parser\TemplateParser::TP_QMARK;
}
public function yy_r3_60()
public function yy_r3_58()
{
$this->token = \Smarty\Parser\TemplateParser::TP_HEX;
}
public function yy_r3_61()
public function yy_r3_59()
{
$this->token = \Smarty\Parser\TemplateParser::TP_SPACE;
}
public function yy_r3_62()
public function yy_r3_60()
{
$this->token = \Smarty\Parser\TemplateParser::TP_TEXT;
+1 -6
View File
@@ -160,7 +160,6 @@ class TemplateLexer
'LOGOP' => '"<", "==" ... logical operator',
'TLOGOP' => '"lt", "eq" ... logical operator; "is div by" ... if condition',
'SCOND' => '"is even" ... if condition',
'MATCHES' => '"matches" regex operator',
);
/**
@@ -325,8 +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+~
matches = ~\s+matches\s+~
isin = ~\s+is\s+in\s+~
as = ~\s+as\s+~
to = ~\s+to\s+~
step = ~\s+step\s+~
@@ -471,9 +469,6 @@ class TemplateLexer
isin {
$this->token = \Smarty\Parser\TemplateParser::TP_ISIN;
}
matches {
$this->token = \Smarty\Parser\TemplateParser::TP_MATCHES;
}
as {
$this->token = \Smarty\Parser\TemplateParser::TP_AS;
}
+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;
+1124 -1371
View File
File diff suppressed because it is too large Load Diff
+37 -152
View File
@@ -19,7 +19,7 @@ use \Smarty\ParseTree\Code;
use \Smarty\ParseTree\Dq;
use \Smarty\ParseTree\DqContent;
use \Smarty\ParseTree\Tag;
use \Smarty\CompilerException;
/**
* Smarty Template Parser Class
@@ -306,8 +306,7 @@ smartytag(A) ::= SIMPELOUTPUT(B). {
$attributes[] = 'nocache';
$var = $match[1];
}
$this->compiler->triggerTagNoCache($var);
A = $this->compiler->compilePrintExpression('$_smarty_tpl->getValue(\''.$var.'\')', $attributes);
A = $this->compiler->compilePrintExpression($this->compiler->compileVariable('\''.$var.'\''), $attributes);
}
// simple tag like {name}
@@ -376,7 +375,7 @@ outattr(A) ::= output(B) attributes(C). {
A = array(B,C);
}
output(A) ::= variablevalue(B). {
output(A) ::= variable(B). {
A = B;
}
output(A) ::= value(B). {
@@ -664,26 +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.')';
}
// regex matching
expr(res) ::= expr(e1) matchop(c) value(e2). {
res = c . e2 . ',' . e1 . ') ';
expr(res) ::= expr(e1) ISIN value(v). {
res = 'in_array('.e1.',(array)'.v.')';
}
// null coalescing
@@ -695,8 +680,7 @@ nullcoalescing(res) ::= expr(v) QMARK QMARK expr(e2). {
// ternary
//
ternary(res) ::= expr(v) QMARK DOLLARID(e1) COLON expr(e2). {
$this->compiler->triggerTagNoCache(substr(e1,1));
res = v.' ? $_smarty_tpl->getValue(\''.substr(e1,1).'\') : '.e2;
res = v.' ? '. $this->compiler->compileVariable('\''.substr(e1,1).'\'') . ' : '.e2;
}
ternary(res) ::= expr(v) QMARK value(e1) COLON expr(e2). {
@@ -713,7 +697,7 @@ ternary(res) ::= expr(v) QMARK COLON expr(e2). {
}
// value
value(res) ::= variablevalue(v). {
value(res) ::= variable(v). {
res = v;
}
@@ -731,7 +715,7 @@ value(res) ::= TYPECAST(t) value(v). {
res = t.v;
}
value(res) ::= variablevalue(v) INCDEC(o). {
value(res) ::= variable(v) INCDEC(o). {
res = v.o;
}
@@ -778,10 +762,10 @@ value(res) ::= OPENP expr(e) CLOSEP. {
res = '('. e .')';
}
value(res) ::= variablevalue(v1) INSTANCEOF(i) ns1(v2). {
value(res) ::= variable(v1) INSTANCEOF(i) ns1(v2). {
res = v1.i.v2;
}
value(res) ::= variablevalue(v1) INSTANCEOF(i) variablevalue(v2). {
value(res) ::= variable(v1) INSTANCEOF(i) variable(v2). {
res = v1.i.v2;
}
@@ -804,8 +788,7 @@ value(res) ::= varindexed(vi) DOUBLECOLON static_class_access(r). {
if (vi['var'] === '\'smarty\'') {
$this->compiler->appendPrefixCode("<?php {$prefixVar} = ". (new \Smarty\Compile\SpecialVariableCompiler())->compile(array(),$this->compiler,vi['smarty_internal_index']).';?>');
} else {
$this->compiler->triggerTagNoCache(vi['var']);
$this->compiler->appendPrefixCode("<?php {$prefixVar} = \$_smarty_tpl->getValue(" . vi['var'] . ')'.vi['smarty_internal_index'].';?>');
$this->compiler->appendPrefixCode("<?php {$prefixVar} = ". $this->compiler->compileVariable(vi['var']).vi['smarty_internal_index'].';?>');
}
res = $prefixVar .'::'.r[0].r[1];
}
@@ -813,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;
}
@@ -855,88 +838,54 @@ ns1(res) ::= NAMESPACE(i). {
}
// variable lists
// multiple variables
variablelist(res) ::= variablelist(l) COMMA variable(v). {
res = array_merge(l,array(v));
}
variablelist(res) ::= variablelist(l) COMMA expr(e). {
res = array_merge(l,array(e));
}
// single variable
variablelist(res) ::= variable(v). {
res = array(v);
}
// single expression
variablelist(res) ::= expr(e). {
res = array(e);
}
// no variable
variablelist(res) ::= . {
res = array();
}
//
// variables
//
// Smarty variable (optional array)
variable(res) ::= DOLLARID(i). {
$this->compiler->triggerTagNoCache(substr(i,1));
res = array('$_smarty_tpl->hasVariable(\''.substr(i,1).'\')','$_smarty_tpl->getValue(\''.substr(i,1).'\')');
res = $this->compiler->compileVariable('\''.substr(i,1).'\'');
}
variable(res) ::= varindexed(vi). {
if (vi['var'] === '\'smarty\'') {
$smarty_var = (new \Smarty\Compile\SpecialVariableCompiler())->compile(array(),$this->compiler,vi['smarty_internal_index']);
res = array('true', $smarty_var);
res = $smarty_var;
} else {
// used for array reset,next,prev,end,current
$this->last_variable = vi['var'];
$this->last_index = vi['smarty_internal_index'];
$this->compiler->triggerTagNoCache(vi['var']);
res = array('true', '$_smarty_tpl->getValue(' . vi['var'] . ')'.vi['smarty_internal_index']);
res = $this->compiler->compileVariable(vi['var']).vi['smarty_internal_index'];
}
}
// variable with property
variable(res) ::= varvar(v) AT ID(p). {
res = array('true', '$_smarty_tpl->getVariable('. v .')->'.p);
res = '$_smarty_tpl->getVariable('. v .')->'.p;
}
// object
variable(res) ::= object(o). {
res = array('true', o);
res = o;
}
// config variable
configvariable(res) ::= HATCH ID(i) HATCH. {
variable(res) ::= HATCH ID(i) HATCH. {
res = $this->compiler->compileConfigVariable('\'' . i . '\'');
}
configvariable(res) ::= HATCH ID(i) HATCH arrayindex(a). {
variable(res) ::= HATCH ID(i) HATCH arrayindex(a). {
res = '(is_array($tmp = ' . $this->compiler->compileConfigVariable('\'' . i . '\'') . ') ? $tmp'.a.' :null)';
}
configvariable(res) ::= HATCH variablevalue(v) HATCH. {
variable(res) ::= HATCH variable(v) HATCH. {
res = $this->compiler->compileConfigVariable(v);
}
configvariable(res) ::= HATCH variablevalue(v) HATCH arrayindex(a). {
variable(res) ::= HATCH variable(v) HATCH arrayindex(a). {
res = '(is_array($tmp = ' . $this->compiler->compileConfigVariable(v) . ') ? $tmp'.a.' : null)';
}
variablevalue(res) ::= variable(v). {
res = v[1];
}
variablevalue(res) ::= configvariable(v). {
res = v;
}
varindexed(res) ::= DOLLARID(i) arrayindex(a). {
res = array('var'=>'\''.substr(i,1).'\'', 'smarty_internal_index'=>a);
}
@@ -960,17 +909,14 @@ arrayindex ::= . {
// single index definition
// Smarty2 style index
indexdef(res) ::= DOT DOLLARID(i). {
$this->compiler->triggerTagNoCache(substr(i,1));
res = '[$_smarty_tpl->getValue(\''.substr(i,1).'\')]';
res = '['.$this->compiler->compileVariable('\''.substr(i,1).'\'').']';
}
indexdef(res) ::= DOT varvar(v). {
$this->compiler->triggerTagNoCache(v);
res = '[$_smarty_tpl->getValue(' . v . ')]';
res = '['.$this->compiler->compileVariable(v).']';
}
indexdef(res) ::= DOT varvar(v) AT ID(p). {
$this->compiler->triggerTagNoCache(v);
res = '[$_smarty_tpl->getValue(' . v . ')->'.p.']';
res = '['.$this->compiler->compileVariable(v).'->'.p.']';
}
indexdef(res) ::= DOT ID(i). {
@@ -1001,10 +947,9 @@ indexdef(res) ::= OPENB INTEGER(n) CLOSEB. {
res = '['.n.']';
}
indexdef(res) ::= OPENB DOLLARID(i) CLOSEB. {
$this->compiler->triggerTagNoCache(substr(i,1));
res = '[$_smarty_tpl->getValue(\''.substr(i,1).'\')]';
res = '['.$this->compiler->compileVariable('\''.substr(i,1).'\'').']';
}
indexdef(res) ::= OPENB variablevalue(v) CLOSEB. {
indexdef(res) ::= OPENB variable(v) CLOSEB. {
res = '['.v.']';
}
indexdef(res) ::= OPENB value(v) CLOSEB. {
@@ -1046,8 +991,7 @@ varvarele(res) ::= ID(s). {
}
varvarele(res) ::= SIMPELOUTPUT(i). {
$var = trim(substr(i, $this->compiler->getLdelLength(), -$this->compiler->getRdelLength()), ' $');
$this->compiler->triggerTagNoCache($var);
res = '$_smarty_tpl->getValue(\''.$var.'\')';
res = $this->compiler->compileVariable('\''.$var.'\'');
}
// variable sections of element
@@ -1062,27 +1006,16 @@ object(res) ::= varindexed(vi) objectchain(oc). {
if (vi['var'] === '\'smarty\'') {
res = (new \Smarty\Compile\SpecialVariableCompiler())->compile(array(),$this->compiler,vi['smarty_internal_index']).oc;
} else {
$this->compiler->triggerTagNoCache(vi['var']);
res = '$_smarty_tpl->getValue(' . vi['var'] . ')'.vi['smarty_internal_index'].oc;
res = $this->compiler->compileVariable(vi['var']).vi['smarty_internal_index'].oc;
}
}
// optional objectchain - empty
optobjectchain(res) ::= . {
res = '';
}
// optional objectchain - present
optobjectchain(res) ::= objectchain(oc). {
res = oc;
}
// single element
objectchain(res) ::= objectelement(oe). {
res = oe;
}
// chain of elements
// chain of elements
objectchain(res) ::= objectchain(oc) objectelement(oe). {
res = oc.oe;
}
@@ -1099,8 +1032,7 @@ objectelement(res)::= PTR varvar(v) arrayindex(a). {
if ($this->security) {
$this->compiler->trigger_template_error (self::ERR2);
}
$this->compiler->triggerTagNoCache(v);
res = '->{$_smarty_tpl->getValue(' . v . ')'.a.'}';
res = '->{'.$this->compiler->compileVariable(v).a.'}';
}
objectelement(res)::= PTR LDEL expr(e) RDEL arrayindex(a). {
@@ -1126,41 +1058,8 @@ objectelement(res)::= PTR method(f). {
//
// function
//
function(res) ::= ns1(f) OPENP variablelist(v) CLOSEP optobjectchain(oc). {
if (f == 'isset') {
res = '(true';
if (count(v) == 0) {
throw new CompilerException("Invalid number of arguments for isset. isset expects at least one parameter.");
}
foreach (v as $value) {
if (is_array($value)) {
res .= ' && (' . $value[0] . ' && null !== (' . $value[1] . ' ?? null))';
} else {
res .= ' && (' . $value . ' !== null)';
}
}
res .= ')' . oc;
} elseif (f == 'empty') {
if (count(v) != 1) {
throw new CompilerException("Invalid number of arguments for empty. empty expects at exactly one parameter.");
}
if (is_array(v[0])) {
res = '( !' . v[0][0] . ' || empty(' . v[0][1] . '))' . oc;
} else {
res = 'false == ' . v[0] . oc;
}
} else {
$p = array();
foreach (v as $value) {
if (is_array($value)) {
$p[] = $value[1];
} else {
$p[] = $value;
}
}
res = $this->compiler->compileModifierInExpression(f, $p) . oc;
}
function(res) ::= ns1(f) OPENP params(p) CLOSEP. {
res = $this->compiler->compileModifierInExpression(f, p);
}
@@ -1179,8 +1078,7 @@ method(res) ::= DOLLARID(f) OPENP params(p) CLOSEP. {
$this->compiler->trigger_template_error (self::ERR2);
}
$prefixVar = $this->compiler->getNewPrefixVariable();
$this->compiler->triggerTagNoCache(substr(f,1));
$this->compiler->appendPrefixCode("<?php {$prefixVar} = \$_smarty_tpl->getValue('".substr(f,1).'\')'.';?>');
$this->compiler->appendPrefixCode("<?php {$prefixVar} = ".$this->compiler->compileVariable('\''.substr(f,1).'\'').';?>');
res = $prefixVar .'('. implode(',',p) .')';
}
@@ -1259,11 +1157,6 @@ static_class_access(res) ::= ID(v). {
res = array(v, '');
}
// static class constant with object chain
static_class_access(res) ::= ID(v) objectchain(oc). {
res = array(v, oc);
}
// static class variables
static_class_access(res) ::= DOLLARID(v) arrayindex(a). {
res = array(v, a, 'property');
@@ -1323,10 +1216,6 @@ scond(res) ::= SINGLECOND(o). {
res = $scond[$op];
}
matchop(res) ::= MATCHES(o). {
res = 'preg_match(';
}
//
// ARRAY element assignment
//
@@ -1345,10 +1234,6 @@ arrayelements(res) ::= arrayelements(a1) COMMA arrayelement(a). {
res = a1.','.a;
}
arrayelements(res) ::= arrayelements(a) COMMA. {
res = a.',';
}
arrayelements ::= . {
return;
}
@@ -1388,7 +1273,7 @@ doublequoted(res) ::= doublequotedcontent(o). {
res = new Dq($this, o);
}
doublequotedcontent(res) ::= BACKTICK variablevalue(v) BACKTICK. {
doublequotedcontent(res) ::= BACKTICK variable(v) BACKTICK. {
res = new Code('(string)'.v);
}
@@ -1400,7 +1285,7 @@ doublequotedcontent(res) ::= DOLLARID(i). {
res = new Code('(string)$_smarty_tpl->getValue(\''. substr(i,1) .'\')');
}
doublequotedcontent(res) ::= LDEL variablevalue(v) RDEL. {
doublequotedcontent(res) ::= LDEL variable(v) RDEL. {
res = new Code('(string)'.v);
}
+1 -1
View File
@@ -112,7 +112,7 @@ abstract class BasePlugin
* @param Source $source source object
* @param Template|null $_template template object
*/
abstract public function populate(Source $source, ?\Smarty\Template $_template = null);
abstract public function populate(Source $source, \Smarty\Template $_template = null);
/**
* populate Source Object with timestamp and exists from Resource
+1 -1
View File
@@ -50,7 +50,7 @@ abstract class CustomPlugin extends BasePlugin {
* @param Source $source source object
* @param Template|null $_template template object
*/
public function populate(Source $source, ?Template $_template = null) {
public function populate(Source $source, Template $_template = null) {
$source->uid = sha1($source->type . ':' . $source->name);
$mtime = $this->fetchTimestamp($source->name);
if ($mtime !== null) {
+2 -6
View File
@@ -23,7 +23,7 @@ class ExtendsPlugin extends BasePlugin
*
* @throws Exception
*/
public function populate(Source $source, ?Template $_template = null)
public function populate(Source $source, Template $_template = null)
{
$uid = '';
$sources = array();
@@ -93,11 +93,7 @@ class ExtendsPlugin extends BasePlugin
*/
public function getBasename(Source $source)
{
$search = array(':');
if (\Smarty\Smarty::$_IS_WINDOWS) {
$search = array(':', '|');
}
return str_replace($search, '.', basename($source->getResourceName()));
return str_replace(':', '.', basename($source->getResourceName()));
}
/*
+4 -7
View File
@@ -32,7 +32,7 @@ class FilePlugin extends BasePlugin {
*
* @throws Exception
*/
public function populate(Source $source, ?Template $_template = null) {
public function populate(Source $source, Template $_template = null) {
$source->uid = sha1(
$source->name . ($source->isConfig ? $source->getSmarty()->_joined_config_dir :
@@ -56,14 +56,11 @@ class FilePlugin extends BasePlugin {
* @param Source $source source object
*/
public function populateTimestamp(Source $source) {
$path = $this->getFilePath($source->name, $source->getSmarty(), $source->isConfig);
if (!$source->exists) {
$source->exists = ($path !== false && is_file($path));
if (!$source->exists && $path = $this->getFilePath($source->name, $source->getSmarty(), $source->isConfig)) {
$source->timestamp = $source->exists = is_file($path);
}
if ($source->exists && $path !== false) {
if ($source->exists && $path) {
$source->timestamp = filemtime($path);
} else {
$source->timestamp = 0;
}
}
+1 -1
View File
@@ -33,7 +33,7 @@ class StreamPlugin extends RecompiledPlugin {
*
* @return void
*/
public function populate(Source $source, ?Template $_template = null) {
public function populate(Source $source, Template $_template = null) {
$source->uid = false;
$source->content = $this->getContent($source);
$source->timestamp = $source->exists = !!$source->content;
+1 -1
View File
@@ -31,7 +31,7 @@ class StringEval extends RecompiledPlugin
*
* @return void
*/
public function populate(\Smarty\Template\Source $source, ?\Smarty\Template $_template = null)
public function populate(\Smarty\Template\Source $source, \Smarty\Template $_template = null)
{
$source->uid = sha1($source->name);
$source->timestamp = $source->exists = true;
+1 -1
View File
@@ -31,7 +31,7 @@ class StringPlugin extends BasePlugin {
*
* @return void
*/
public function populate(Source $source, ?Template $_template = null) {
public function populate(Source $source, Template $_template = null) {
$source->uid = sha1($source->name);
$source->timestamp = $source->exists = true;
}
+2 -2
View File
@@ -26,7 +26,7 @@ class DefaultPluginHandlerRuntime {
$script = null;
$cacheable = null;
return (\call_user_func_array(
return (call_user_func_array(
$this->defaultPluginHandler,
[
$tag,
@@ -54,7 +54,7 @@ class DefaultPluginHandlerRuntime {
$script = null;
$cacheable = null;
if (\call_user_func_array(
if (call_user_func_array(
$this->defaultPluginHandler,
[
$tag,

Some files were not shown because too many files have changed in this diff Show More