mirror of
https://github.com/smarty-php/smarty.git
synced 2026-08-05 13:04:23 +02:00
Compare commits
70 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 12587abea1 | |||
| 73da7e90f3 | |||
| c0d7a36124 | |||
| 8cc9a75964 | |||
| 21d7fbb67e | |||
| 1fc41e385d | |||
| fe325daec0 | |||
| 3f0f308a7b | |||
| b390e50974 | |||
| 0e46ae3add | |||
| 4d793ee04c | |||
| 7677b84058 | |||
| e7457d78cb | |||
| cbcd66e1de | |||
| 46cd224efb | |||
| d3b716a0b9 | |||
| 693502c341 | |||
| bb968469fa | |||
| 372f7cf41a | |||
| f659193c94 | |||
| 0b6166482a | |||
| 4ff25bbe59 | |||
| afbd71b868 | |||
| e26f82d02c | |||
| 6ad6a35824 | |||
| baa53399f5 | |||
| 37bea77ea7 | |||
| 0d33f3acde | |||
| 05adbf45f3 | |||
| df4795b803 | |||
| 5401418258 | |||
| a5bbba3f05 | |||
| a0664a4ab2 | |||
| a4b8466205 | |||
| 5d1ea5806a | |||
| ab247c723b | |||
| fb997111f4 | |||
| c6bff57950 | |||
| 07faafe4da | |||
| 295b7fb582 | |||
| cf9de567c1 | |||
| f47ac761af | |||
| 642a97adcc | |||
| 3bba3ff5e9 | |||
| b3b43af816 | |||
| 1b06b37db2 | |||
| a1b4c9c551 | |||
| cd58df7a26 | |||
| 70ed68ff5b | |||
| 598ccde435 | |||
| cb09fda90d | |||
| c8f1853bfe | |||
| 2f781e2e65 | |||
| 30c6ee64ab | |||
| fd90f7eac9 | |||
| 77b91a072b | |||
| 9ede0e40fa | |||
| 1ccfca17d6 | |||
| d6153d4d4d | |||
| 2289fa69f1 | |||
| 3cb3585432 | |||
| a2193eb4cf | |||
| 8ecde47203 | |||
| b978cb348e | |||
| 353ca06d07 | |||
| 20c08ac40d | |||
| 4aa1273a80 | |||
| 3232277bc5 | |||
| bbd09c7bfa | |||
| 52dc8adafb |
@@ -0,0 +1 @@
|
||||
github: [wisskid]
|
||||
@@ -23,6 +23,7 @@ jobs:
|
||||
matrix:
|
||||
os:
|
||||
- ubuntu-latest
|
||||
- windows-latest
|
||||
|
||||
php-version:
|
||||
- "7.2"
|
||||
@@ -32,31 +33,15 @@ 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@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
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install PHP with extensions
|
||||
uses: shivammathur/setup-php@v2
|
||||
@@ -68,7 +53,7 @@ jobs:
|
||||
|
||||
- name: Cache Composer packages
|
||||
id: composer-cache
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: vendor
|
||||
key: v5r2-${{ runner.os }}-php-${{ matrix.php-version }}-${{ hashFiles('**/composer.lock') }}
|
||||
@@ -76,7 +61,7 @@ jobs:
|
||||
v5r1-${{ runner.os }}-php-${{ matrix.php-version }}-
|
||||
|
||||
- name: Install dependencies
|
||||
uses: php-actions/composer@v6
|
||||
run: composer install
|
||||
|
||||
- name: Run make
|
||||
run: make -B
|
||||
|
||||
+61
-2
@@ -6,6 +6,65 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [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
|
||||
@@ -22,16 +81,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Internal compiler classes always return a string (the internal has_code flag has been removed for simplicity) [#918](https://github.com/smarty-php/smarty/pull/918)
|
||||
- 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)
|
||||
|
||||
|
||||
@@ -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.3.
|
||||
Smarty v5 can be run with PHP 7.2 to PHP 8.5.
|
||||
|
||||
## Installation
|
||||
Smarty versions 3.1.11 or later can be installed with [Composer](https://getcomposer.org/).
|
||||
@@ -18,3 +18,11 @@ 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 +0,0 @@
|
||||
- Added `$smarty->prependTemplateDir()` method [#1022](https://github.com/smarty-php/smarty/issues/1022)
|
||||
@@ -0,0 +1 @@
|
||||
- Update documentation to clarify that include inline is currently not implemented in Smarty v5 [#1152](https://github.com/smarty-php/smarty/issues/1152)
|
||||
@@ -1 +0,0 @@
|
||||
- Fix Smarty::assign() not returning $this when called with an array as first parameter [#972](https://github.com/smarty-php/smarty/pull/972)
|
||||
@@ -1 +0,0 @@
|
||||
- Fixed missing Smarty getErrorUnassigned/setErrorUnassigned methods [#979](https://github.com/smarty-php/smarty/issues/979)
|
||||
@@ -42,6 +42,11 @@ services:
|
||||
service: base
|
||||
build:
|
||||
dockerfile: ./utilities/testrunners/php83/Dockerfile
|
||||
php84:
|
||||
extends:
|
||||
service: base
|
||||
build:
|
||||
dockerfile: ./utilities/testrunners/php84/Dockerfile
|
||||
volumes:
|
||||
smarty-code:
|
||||
|
||||
|
||||
@@ -143,6 +143,35 @@ 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
|
||||
|
||||
@@ -47,11 +47,13 @@ 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 |
|
||||
| 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.
|
||||
|
||||
## Examples
|
||||
```smarty
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
# 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 [escaping smarty parsing](../language-basic-syntax/language-escaping.md),
|
||||
See also [auto-escaping](../../api/configuring.md#enabling-auto-escaping), [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) page.
|
||||
addresses](../../appendixes/tips.md#obfuscating-e-mail-addresses) pages.
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
# 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)
|
||||
@@ -0,0 +1,8 @@
|
||||
# raw
|
||||
|
||||
Prevents variable escaping when [auto-escaping](../../api/configuring.md#enabling-auto-escaping) is activated.
|
||||
|
||||
## Basic usage
|
||||
```smarty
|
||||
{$myVar|raw}
|
||||
```
|
||||
@@ -1,7 +1,7 @@
|
||||
# Getting started
|
||||
|
||||
## Requirements
|
||||
Smarty can be run with PHP 7.2 to PHP 8.3.
|
||||
Smarty can be run with PHP 7.2 to PHP 8.5.
|
||||
|
||||
## Installation
|
||||
Smarty can be installed with [Composer](https://getcomposer.org/).
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
<?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>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
@@ -0,0 +1,22 @@
|
||||
<?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>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
@@ -0,0 +1,68 @@
|
||||
<?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>
|
||||
|
After Width: | Height: | Size: 6.0 KiB |
+11
-1
@@ -32,4 +32,14 @@ and 480 for $height, the result is:
|
||||
- [Troubleshooting](./appendixes/troubleshooting.md)
|
||||
|
||||
## Source code
|
||||
- [Smarty repository at GitHub](https://github.com/smarty-php/smarty)
|
||||
- [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
|
||||
|
||||
@@ -49,6 +49,11 @@ $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.
|
||||
@@ -102,6 +107,15 @@ 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.
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ php utilities/update-smarty-version-number.php $1
|
||||
git add changelog CHANGELOG.md src/Smarty.php
|
||||
git commit -m "version bump"
|
||||
|
||||
git checkout support/5
|
||||
git checkout master
|
||||
git pull
|
||||
git merge --no-ff "release/$1"
|
||||
git branch -d "release/$1"
|
||||
|
||||
@@ -57,9 +57,11 @@ 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'
|
||||
@@ -68,6 +70,7 @@ 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'
|
||||
|
||||
@@ -14,3 +14,4 @@ $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 $@
|
||||
|
||||
@@ -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]);
|
||||
}
|
||||
}
|
||||
@@ -44,7 +44,7 @@ abstract class Base
|
||||
*/
|
||||
abstract public function process(
|
||||
Template $_template,
|
||||
Cached $cached = null,
|
||||
?Cached $cached = null,
|
||||
$update = false
|
||||
);
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
<?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;
|
||||
}
|
||||
}
|
||||
+6
-78
@@ -82,84 +82,12 @@ abstract class Base implements CompilerInterface {
|
||||
* @return array of mapped attributes for further processing
|
||||
*/
|
||||
protected 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;
|
||||
return (new AttributeCompiler(
|
||||
$this->required_attributes,
|
||||
$this->optional_attributes,
|
||||
$this->shorttag_order,
|
||||
$this->option_flags
|
||||
))->getAttributes($compiler, $attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,24 +3,18 @@
|
||||
* 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\CompilerException;
|
||||
use Smarty\FunctionHandler\AttributeFunctionHandlerInterface;
|
||||
|
||||
/**
|
||||
* Smarty Internal Plugin Compile Registered Function Class
|
||||
*
|
||||
|
||||
|
||||
*/
|
||||
class FunctionCallCompiler extends Base {
|
||||
|
||||
/**
|
||||
* Attribute definition: Overwrites base class.
|
||||
*
|
||||
@@ -51,17 +45,27 @@ 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) . ")";
|
||||
|
||||
@@ -24,22 +24,32 @@ 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)' .
|
||||
@@ -53,4 +63,4 @@ class EscapeModifierCompiler extends Base {
|
||||
}
|
||||
return '$_smarty_tpl->getSmarty()->getModifierCallback(\'escape\')(' . join(', ', $params) . ')';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
<?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]);
|
||||
}
|
||||
}
|
||||
@@ -75,7 +75,7 @@ class ModifierCompiler extends Base {
|
||||
}
|
||||
}
|
||||
}
|
||||
return $output;
|
||||
return (string)$output;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -82,12 +82,13 @@ class PrintExpressionCompiler extends Base {
|
||||
$output = $compiler->compileModifier($modifierlist, $output);
|
||||
}
|
||||
|
||||
if ($compiler->getTemplate()->getSmarty()->escape_html) {
|
||||
if ($compiler->getTemplate()->getSmarty()->escape_html && !$compiler->isRawOutput()) {
|
||||
$output = "htmlspecialchars((string) ({$output}), ENT_QUOTES, '" . addslashes(\Smarty\Smarty::$_CHARSET) . "')";
|
||||
}
|
||||
|
||||
}
|
||||
$output = "<?php echo {$output};?>\n";
|
||||
$compiler->setRawOutput(false);
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
|
||||
@@ -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('nocache');
|
||||
$this->openTag($compiler, 'nocache');
|
||||
}
|
||||
|
||||
$this->openTag($compiler, 'section', ['section', $compiler->tag_nocache]);
|
||||
|
||||
@@ -33,7 +33,7 @@ class SectionClose extends Base {
|
||||
|
||||
if ($nocache_pushed) {
|
||||
// pop the pushed virtual nocache tag
|
||||
$this->closeTag('nocache');
|
||||
$this->closeTag($compiler, 'nocache');
|
||||
}
|
||||
|
||||
$output = "<?php\n";
|
||||
|
||||
@@ -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;
|
||||
|
||||
+36
-13
@@ -313,6 +313,12 @@ 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
|
||||
@@ -368,7 +374,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;
|
||||
@@ -499,7 +505,7 @@ class Template extends BaseCompiler {
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function compileVariable($variable) {
|
||||
public function triggerTagNoCache($variable): void {
|
||||
if (!strpos($variable, '(')) {
|
||||
// not a variable variable
|
||||
$var = trim($variable, '\'');
|
||||
@@ -510,7 +516,6 @@ class Template extends BaseCompiler {
|
||||
false
|
||||
)->isNocache();
|
||||
}
|
||||
return '$_smarty_tpl->getValue(' . $variable . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -659,7 +664,7 @@ class Template extends BaseCompiler {
|
||||
$script = null;
|
||||
$cacheable = true;
|
||||
|
||||
$result = call_user_func_array(
|
||||
$result = \call_user_func_array(
|
||||
$defaultPluginHandlerFunc,
|
||||
[
|
||||
$tag,
|
||||
@@ -1141,12 +1146,12 @@ class Template extends BaseCompiler {
|
||||
}
|
||||
|
||||
// check if tag is a function
|
||||
if ($this->smarty->getFunctionHandler($base_tag)) {
|
||||
if (!isset($this->smarty->security_policy) || $this->smarty->security_policy->isTrustedTag($base_tag, $this)) {
|
||||
if ($this->smarty->getFunctionHandler($tag)) {
|
||||
if (!isset($this->smarty->security_policy) || $this->smarty->security_policy->isTrustedTag($tag, $this)) {
|
||||
return (new \Smarty\Compile\PrintExpressionCompiler())->compile(
|
||||
['nofilter'], // functions are never auto-escaped
|
||||
$this,
|
||||
['value' => $this->compileFunctionCall($base_tag, $args, $parameter)]
|
||||
['value' => $this->compileFunctionCall($tag, $args, $parameter)]
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1159,16 +1164,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($base_tag, Smarty::PLUGIN_COMPILER)) {
|
||||
if ($callback = $this->getPluginFromDefaultHandler($tag, Smarty::PLUGIN_COMPILER)) {
|
||||
if (!empty($parameter['modifierlist'])) {
|
||||
throw new CompilerException('No modifiers allowed on ' . $base_tag);
|
||||
throw new CompilerException('No modifiers allowed on ' . $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, $base_tag);
|
||||
return $this->defaultHandlerFunctionCallCompiler->compile($args, $this, $parameter, $tag, $tag);
|
||||
}
|
||||
|
||||
if ($this->getPluginFromDefaultHandler($base_tag, Smarty::PLUGIN_BLOCK)) {
|
||||
@@ -1275,9 +1280,10 @@ class Template extends BaseCompiler {
|
||||
}
|
||||
// call post compile callbacks
|
||||
foreach ($this->postCompileCallbacks as $cb) {
|
||||
$parameter = $cb;
|
||||
$parameter[0] = $this;
|
||||
call_user_func_array($cb[0], $parameter);
|
||||
$callbackFunction = $cb[0];
|
||||
$parameters = $cb;
|
||||
$parameters[0] = $this;
|
||||
$callbackFunction(...$parameters);
|
||||
}
|
||||
// return compiled code
|
||||
return $this->prefixCompiledCode . $this->parser->retvalue . $this->postfixCompiledCode;
|
||||
@@ -1486,4 +1492,21 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
+1
-1
@@ -290,7 +290,7 @@ class Data
|
||||
* @return bool
|
||||
*/
|
||||
public function hasVariable($varName): bool {
|
||||
return !($this->getVariable($varName) instanceof UndefinedVariable);
|
||||
return !($this->getVariable($varName, true, false) instanceof UndefinedVariable);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -168,7 +168,6 @@ class BCPluginsAdapter extends Base {
|
||||
}
|
||||
|
||||
public function loadPluginsFromDir(string $path) {
|
||||
|
||||
foreach([
|
||||
'function',
|
||||
'modifier',
|
||||
@@ -177,6 +176,7 @@ 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];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ class CallbackWrapper {
|
||||
|
||||
public function handle(...$params) {
|
||||
try {
|
||||
return call_user_func_array($this->callback, $params);
|
||||
return ($this->callback)(...$params);
|
||||
} catch (\ArgumentCountError $e) {
|
||||
throw new Exception("Invalid number of arguments to modifier " . $this->modifierName);
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ 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;
|
||||
@@ -319,7 +320,7 @@ class DefaultExtension extends Base {
|
||||
break;
|
||||
}
|
||||
foreach ($var as $curr_key => $curr_val) {
|
||||
$results .= '<br>' . str_repeat(' ', $depth * 2) . '<b>' . strtr($curr_key, $_replace) .
|
||||
$results .= '<br>' . str_repeat(' ', $depth * 2) . '<b>' . htmlspecialchars(strtr($curr_key, $_replace)) .
|
||||
'</b> => ' .
|
||||
$this->smarty_modifier_debug_print_var($curr_val, $max, $length, ++$depth, $objects);
|
||||
$depth--;
|
||||
@@ -337,7 +338,7 @@ class DefaultExtension extends Base {
|
||||
}
|
||||
$objects[] = $var;
|
||||
foreach ($object_vars as $curr_key => $curr_val) {
|
||||
$results .= '<br>' . str_repeat(' ', $depth * 2) . '<b> ->' . strtr($curr_key, $_replace) .
|
||||
$results .= '<br>' . str_repeat(' ', $depth * 2) . '<b> ->' . htmlspecialchars(strtr($curr_key, $_replace)) .
|
||||
'</b> = ' . $this->smarty_modifier_debug_print_var($curr_val, $max, $length, ++$depth, $objects);
|
||||
$depth--;
|
||||
}
|
||||
@@ -753,4 +754,4 @@ class DefaultExtension extends Base {
|
||||
return $string;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
<?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,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?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;
|
||||
}
|
||||
+1022
-895
File diff suppressed because it is too large
Load Diff
+113
-31
@@ -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,7 +306,8 @@ smartytag(A) ::= SIMPELOUTPUT(B). {
|
||||
$attributes[] = 'nocache';
|
||||
$var = $match[1];
|
||||
}
|
||||
A = $this->compiler->compilePrintExpression($this->compiler->compileVariable('\''.$var.'\''), $attributes);
|
||||
$this->compiler->triggerTagNoCache($var);
|
||||
A = $this->compiler->compilePrintExpression('$_smarty_tpl->getValue(\''.$var.'\')', $attributes);
|
||||
}
|
||||
|
||||
// simple tag like {name}
|
||||
@@ -375,7 +376,7 @@ outattr(A) ::= output(B) attributes(C). {
|
||||
A = array(B,C);
|
||||
}
|
||||
|
||||
output(A) ::= variable(B). {
|
||||
output(A) ::= variablevalue(B). {
|
||||
A = B;
|
||||
}
|
||||
output(A) ::= value(B). {
|
||||
@@ -689,7 +690,8 @@ nullcoalescing(res) ::= expr(v) QMARK QMARK expr(e2). {
|
||||
// ternary
|
||||
//
|
||||
ternary(res) ::= expr(v) QMARK DOLLARID(e1) COLON expr(e2). {
|
||||
res = v.' ? '. $this->compiler->compileVariable('\''.substr(e1,1).'\'') . ' : '.e2;
|
||||
$this->compiler->triggerTagNoCache(substr(e1,1));
|
||||
res = v.' ? $_smarty_tpl->getValue(\''.substr(e1,1).'\') : '.e2;
|
||||
}
|
||||
|
||||
ternary(res) ::= expr(v) QMARK value(e1) COLON expr(e2). {
|
||||
@@ -706,7 +708,7 @@ ternary(res) ::= expr(v) QMARK COLON expr(e2). {
|
||||
}
|
||||
|
||||
// value
|
||||
value(res) ::= variable(v). {
|
||||
value(res) ::= variablevalue(v). {
|
||||
res = v;
|
||||
}
|
||||
|
||||
@@ -724,7 +726,7 @@ value(res) ::= TYPECAST(t) value(v). {
|
||||
res = t.v;
|
||||
}
|
||||
|
||||
value(res) ::= variable(v) INCDEC(o). {
|
||||
value(res) ::= variablevalue(v) INCDEC(o). {
|
||||
res = v.o;
|
||||
}
|
||||
|
||||
@@ -771,10 +773,10 @@ value(res) ::= OPENP expr(e) CLOSEP. {
|
||||
res = '('. e .')';
|
||||
}
|
||||
|
||||
value(res) ::= variable(v1) INSTANCEOF(i) ns1(v2). {
|
||||
value(res) ::= variablevalue(v1) INSTANCEOF(i) ns1(v2). {
|
||||
res = v1.i.v2;
|
||||
}
|
||||
value(res) ::= variable(v1) INSTANCEOF(i) variable(v2). {
|
||||
value(res) ::= variablevalue(v1) INSTANCEOF(i) variablevalue(v2). {
|
||||
res = v1.i.v2;
|
||||
}
|
||||
|
||||
@@ -797,7 +799,8 @@ 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->appendPrefixCode("<?php {$prefixVar} = ". $this->compiler->compileVariable(vi['var']).vi['smarty_internal_index'].';?>');
|
||||
$this->compiler->triggerTagNoCache(vi['var']);
|
||||
$this->compiler->appendPrefixCode("<?php {$prefixVar} = \$_smarty_tpl->getValue(" . vi['var'] . ')'.vi['smarty_internal_index'].';?>');
|
||||
}
|
||||
res = $prefixVar .'::'.r[0].r[1];
|
||||
}
|
||||
@@ -847,54 +850,88 @@ 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). {
|
||||
res = $this->compiler->compileVariable('\''.substr(i,1).'\'');
|
||||
$this->compiler->triggerTagNoCache(substr(i,1));
|
||||
res = array('$_smarty_tpl->hasVariable(\''.substr(i,1).'\')','$_smarty_tpl->getValue(\''.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 = $smarty_var;
|
||||
res = array('true', $smarty_var);
|
||||
} else {
|
||||
// used for array reset,next,prev,end,current
|
||||
$this->last_variable = vi['var'];
|
||||
$this->last_index = vi['smarty_internal_index'];
|
||||
res = $this->compiler->compileVariable(vi['var']).vi['smarty_internal_index'];
|
||||
$this->compiler->triggerTagNoCache(vi['var']);
|
||||
res = array('true', '$_smarty_tpl->getValue(' . vi['var'] . ')'.vi['smarty_internal_index']);
|
||||
}
|
||||
}
|
||||
|
||||
// variable with property
|
||||
variable(res) ::= varvar(v) AT ID(p). {
|
||||
res = '$_smarty_tpl->getVariable('. v .')->'.p;
|
||||
res = array('true', '$_smarty_tpl->getVariable('. v .')->'.p);
|
||||
}
|
||||
|
||||
// object
|
||||
variable(res) ::= object(o). {
|
||||
res = o;
|
||||
res = array('true', o);
|
||||
}
|
||||
|
||||
// config variable
|
||||
variable(res) ::= HATCH ID(i) HATCH. {
|
||||
configvariable(res) ::= HATCH ID(i) HATCH. {
|
||||
res = $this->compiler->compileConfigVariable('\'' . i . '\'');
|
||||
}
|
||||
|
||||
variable(res) ::= HATCH ID(i) HATCH arrayindex(a). {
|
||||
configvariable(res) ::= HATCH ID(i) HATCH arrayindex(a). {
|
||||
res = '(is_array($tmp = ' . $this->compiler->compileConfigVariable('\'' . i . '\'') . ') ? $tmp'.a.' :null)';
|
||||
}
|
||||
|
||||
variable(res) ::= HATCH variable(v) HATCH. {
|
||||
configvariable(res) ::= HATCH variablevalue(v) HATCH. {
|
||||
res = $this->compiler->compileConfigVariable(v);
|
||||
}
|
||||
|
||||
variable(res) ::= HATCH variable(v) HATCH arrayindex(a). {
|
||||
configvariable(res) ::= HATCH variablevalue(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);
|
||||
}
|
||||
@@ -918,14 +955,17 @@ arrayindex ::= . {
|
||||
// single index definition
|
||||
// Smarty2 style index
|
||||
indexdef(res) ::= DOT DOLLARID(i). {
|
||||
res = '['.$this->compiler->compileVariable('\''.substr(i,1).'\'').']';
|
||||
$this->compiler->triggerTagNoCache(substr(i,1));
|
||||
res = '[$_smarty_tpl->getValue(\''.substr(i,1).'\')]';
|
||||
}
|
||||
indexdef(res) ::= DOT varvar(v). {
|
||||
res = '['.$this->compiler->compileVariable(v).']';
|
||||
$this->compiler->triggerTagNoCache(v);
|
||||
res = '[$_smarty_tpl->getValue(' . v . ')]';
|
||||
}
|
||||
|
||||
indexdef(res) ::= DOT varvar(v) AT ID(p). {
|
||||
res = '['.$this->compiler->compileVariable(v).'->'.p.']';
|
||||
$this->compiler->triggerTagNoCache(v);
|
||||
res = '[$_smarty_tpl->getValue(' . v . ')->'.p.']';
|
||||
}
|
||||
|
||||
indexdef(res) ::= DOT ID(i). {
|
||||
@@ -956,9 +996,10 @@ indexdef(res) ::= OPENB INTEGER(n) CLOSEB. {
|
||||
res = '['.n.']';
|
||||
}
|
||||
indexdef(res) ::= OPENB DOLLARID(i) CLOSEB. {
|
||||
res = '['.$this->compiler->compileVariable('\''.substr(i,1).'\'').']';
|
||||
$this->compiler->triggerTagNoCache(substr(i,1));
|
||||
res = '[$_smarty_tpl->getValue(\''.substr(i,1).'\')]';
|
||||
}
|
||||
indexdef(res) ::= OPENB variable(v) CLOSEB. {
|
||||
indexdef(res) ::= OPENB variablevalue(v) CLOSEB. {
|
||||
res = '['.v.']';
|
||||
}
|
||||
indexdef(res) ::= OPENB value(v) CLOSEB. {
|
||||
@@ -1000,7 +1041,8 @@ varvarele(res) ::= ID(s). {
|
||||
}
|
||||
varvarele(res) ::= SIMPELOUTPUT(i). {
|
||||
$var = trim(substr(i, $this->compiler->getLdelLength(), -$this->compiler->getRdelLength()), ' $');
|
||||
res = $this->compiler->compileVariable('\''.$var.'\'');
|
||||
$this->compiler->triggerTagNoCache($var);
|
||||
res = '$_smarty_tpl->getValue(\''.$var.'\')';
|
||||
}
|
||||
|
||||
// variable sections of element
|
||||
@@ -1015,7 +1057,8 @@ 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 {
|
||||
res = $this->compiler->compileVariable(vi['var']).vi['smarty_internal_index'].oc;
|
||||
$this->compiler->triggerTagNoCache(vi['var']);
|
||||
res = '$_smarty_tpl->getValue(' . vi['var'] . ')'.vi['smarty_internal_index'].oc;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1041,7 +1084,8 @@ objectelement(res)::= PTR varvar(v) arrayindex(a). {
|
||||
if ($this->security) {
|
||||
$this->compiler->trigger_template_error (self::ERR2);
|
||||
}
|
||||
res = '->{'.$this->compiler->compileVariable(v).a.'}';
|
||||
$this->compiler->triggerTagNoCache(v);
|
||||
res = '->{$_smarty_tpl->getValue(' . v . ')'.a.'}';
|
||||
}
|
||||
|
||||
objectelement(res)::= PTR LDEL expr(e) RDEL arrayindex(a). {
|
||||
@@ -1067,8 +1111,41 @@ objectelement(res)::= PTR method(f). {
|
||||
//
|
||||
// function
|
||||
//
|
||||
function(res) ::= ns1(f) OPENP params(p) CLOSEP. {
|
||||
res = $this->compiler->compileModifierInExpression(f, p);
|
||||
function(res) ::= ns1(f) OPENP variablelist(v) CLOSEP. {
|
||||
|
||||
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 .= ')';
|
||||
} 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] . '))';
|
||||
} else {
|
||||
res = 'false == ' . v[0];
|
||||
}
|
||||
} else {
|
||||
$p = array();
|
||||
foreach (v as $value) {
|
||||
if (is_array($value)) {
|
||||
$p[] = $value[1];
|
||||
} else {
|
||||
$p[] = $value;
|
||||
}
|
||||
}
|
||||
res = $this->compiler->compileModifierInExpression(f, $p);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1087,7 +1164,8 @@ method(res) ::= DOLLARID(f) OPENP params(p) CLOSEP. {
|
||||
$this->compiler->trigger_template_error (self::ERR2);
|
||||
}
|
||||
$prefixVar = $this->compiler->getNewPrefixVariable();
|
||||
$this->compiler->appendPrefixCode("<?php {$prefixVar} = ".$this->compiler->compileVariable('\''.substr(f,1).'\'').';?>');
|
||||
$this->compiler->triggerTagNoCache(substr(f,1));
|
||||
$this->compiler->appendPrefixCode("<?php {$prefixVar} = \$_smarty_tpl->getValue('".substr(f,1).'\')'.';?>');
|
||||
res = $prefixVar .'('. implode(',',p) .')';
|
||||
}
|
||||
|
||||
@@ -1243,6 +1321,10 @@ arrayelements(res) ::= arrayelements(a1) COMMA arrayelement(a). {
|
||||
res = a1.','.a;
|
||||
}
|
||||
|
||||
arrayelements(res) ::= arrayelements(a) COMMA. {
|
||||
res = a.',';
|
||||
}
|
||||
|
||||
arrayelements ::= . {
|
||||
return;
|
||||
}
|
||||
@@ -1282,7 +1364,7 @@ doublequoted(res) ::= doublequotedcontent(o). {
|
||||
res = new Dq($this, o);
|
||||
}
|
||||
|
||||
doublequotedcontent(res) ::= BACKTICK variable(v) BACKTICK. {
|
||||
doublequotedcontent(res) ::= BACKTICK variablevalue(v) BACKTICK. {
|
||||
res = new Code('(string)'.v);
|
||||
}
|
||||
|
||||
@@ -1294,7 +1376,7 @@ doublequotedcontent(res) ::= DOLLARID(i). {
|
||||
res = new Code('(string)$_smarty_tpl->getValue(\''. substr(i,1) .'\')');
|
||||
}
|
||||
|
||||
doublequotedcontent(res) ::= LDEL variable(v) RDEL. {
|
||||
doublequotedcontent(res) ::= LDEL variablevalue(v) RDEL. {
|
||||
res = new Code('(string)'.v);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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,7 +93,11 @@ class ExtendsPlugin extends BasePlugin
|
||||
*/
|
||||
public function getBasename(Source $source)
|
||||
{
|
||||
return str_replace(':', '.', basename($source->getResourceName()));
|
||||
$search = array(':');
|
||||
if (\Smarty\Smarty::$_IS_WINDOWS) {
|
||||
$search = array(':', '|');
|
||||
}
|
||||
return str_replace($search, '.', basename($source->getResourceName()));
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -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,11 +56,14 @@ class FilePlugin extends BasePlugin {
|
||||
* @param Source $source source object
|
||||
*/
|
||||
public function populateTimestamp(Source $source) {
|
||||
if (!$source->exists && $path = $this->getFilePath($source->name, $source->getSmarty(), $source->isConfig)) {
|
||||
$source->timestamp = $source->exists = is_file($path);
|
||||
$path = $this->getFilePath($source->name, $source->getSmarty(), $source->isConfig);
|
||||
if (!$source->exists) {
|
||||
$source->exists = ($path !== false && is_file($path));
|
||||
}
|
||||
if ($source->exists && $path) {
|
||||
if ($source->exists && $path !== false) {
|
||||
$source->timestamp = filemtime($path);
|
||||
} else {
|
||||
$source->timestamp = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -162,7 +162,7 @@ class InheritanceRuntime {
|
||||
private function processBlock(
|
||||
Template $tpl,
|
||||
\Smarty\Runtime\Block $block,
|
||||
\Smarty\Runtime\Block $parent = null
|
||||
?\Smarty\Runtime\Block $parent = null
|
||||
) {
|
||||
if ($block->hide && !isset($block->child)) {
|
||||
return;
|
||||
|
||||
+2
-17
@@ -54,7 +54,7 @@ class Smarty extends \Smarty\TemplateBase {
|
||||
/**
|
||||
* smarty version
|
||||
*/
|
||||
const SMARTY_VERSION = '5.2.0';
|
||||
const SMARTY_VERSION = '5.7.0';
|
||||
|
||||
/**
|
||||
* define caching modes
|
||||
@@ -2227,22 +2227,6 @@ class Smarty extends \Smarty\TemplateBase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether Smarty displays an error when using an unassigned variable
|
||||
*/
|
||||
public function getErrorUnassigned(): bool
|
||||
{
|
||||
return (bool) $this->error_unassigned;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set if Smarty should display an error on using an unassigned variable
|
||||
*/
|
||||
public function setErrorUnassigned(bool $error_unassigned): void
|
||||
{
|
||||
$this->error_unassigned = $error_unassigned;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets if Smarty should check If-Modified-Since headers to determine cache validity.
|
||||
* @param bool $cache_modified_check
|
||||
* @return void
|
||||
@@ -2252,3 +2236,4 @@ class Smarty extends \Smarty\TemplateBase {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -115,7 +115,7 @@ class Template extends TemplateBase {
|
||||
public function __construct(
|
||||
$template_resource,
|
||||
Smarty $smarty,
|
||||
\Smarty\Data $_parent = null,
|
||||
?\Smarty\Data $_parent = null,
|
||||
$_cache_id = null,
|
||||
$_compile_id = null,
|
||||
$_caching = null,
|
||||
@@ -248,7 +248,7 @@ class Template extends TemplateBase {
|
||||
$caching,
|
||||
$cache_lifetime,
|
||||
array $extra_vars = [],
|
||||
int $scope = null,
|
||||
?int $scope = null,
|
||||
?string $currentDir = null
|
||||
) {
|
||||
|
||||
@@ -462,7 +462,7 @@ class Template extends TemplateBase {
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
public function createCodeFrame($content = '', $functions = '', $cache = false, \Smarty\Compiler\Template $compiler = null) {
|
||||
public function createCodeFrame($content = '', $functions = '', $cache = false, ?\Smarty\Compiler\Template $compiler = null) {
|
||||
return $this->getCodeFrameCompiler()->create($content, $functions, $cache, $compiler);
|
||||
}
|
||||
|
||||
|
||||
@@ -136,7 +136,7 @@ class Compiled extends GeneratedPhpFile {
|
||||
if ($this->exists && !$_smarty_tpl->getSmarty()->force_compile
|
||||
&& !($_smarty_tpl->compile_check && $_smarty_tpl->getSource()->getTimeStamp() > $this->getTimeStamp())
|
||||
) {
|
||||
$this->loadCompiledTemplate($_smarty_tpl);
|
||||
$this->loadCompiledTemplate($_smarty_tpl, false);
|
||||
}
|
||||
|
||||
if (!$this->isValid) {
|
||||
@@ -241,16 +241,19 @@ class Compiled extends GeneratedPhpFile {
|
||||
* HHVM requires a workaround because of a PHP incompatibility
|
||||
*
|
||||
* @param Template $_smarty_tpl do not change/remove variable name, is used by compiled template
|
||||
* @param bool $invalidateCachedFiles forces a revalidation of the file in opcache or apc cache (if available)
|
||||
*
|
||||
*/
|
||||
private function loadCompiledTemplate(Template $_smarty_tpl) {
|
||||
|
||||
if (function_exists('opcache_invalidate')
|
||||
&& (!function_exists('ini_get') || strlen(ini_get("opcache.restrict_api")) < 1)
|
||||
) {
|
||||
opcache_invalidate($this->filepath, true);
|
||||
} elseif (function_exists('apc_compile_file')) {
|
||||
apc_compile_file($this->filepath);
|
||||
private function loadCompiledTemplate(Template $_smarty_tpl, bool $invalidateCachedFiles = true) {
|
||||
|
||||
if ($invalidateCachedFiles) {
|
||||
if (function_exists('opcache_invalidate')
|
||||
&& (!function_exists('ini_get') || strlen(ini_get("opcache.restrict_api")) < 1)
|
||||
) {
|
||||
opcache_invalidate($this->filepath, true);
|
||||
} elseif (function_exists('apc_compile_file')) {
|
||||
apc_compile_file($this->filepath);
|
||||
}
|
||||
}
|
||||
if (defined('HHVM_VERSION')) {
|
||||
eval('?>' . file_get_contents($this->filepath));
|
||||
|
||||
@@ -134,9 +134,9 @@ class Source {
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function load(
|
||||
Template $_template = null,
|
||||
Smarty $smarty = null,
|
||||
$template_resource = null
|
||||
?Template $_template = null,
|
||||
?Smarty $smarty = null,
|
||||
$template_resource = null
|
||||
) {
|
||||
if ($_template) {
|
||||
$smarty = $_template->getSmarty();
|
||||
@@ -203,7 +203,7 @@ class Source {
|
||||
*/
|
||||
public function _getDefaultTemplate($default_handler) {
|
||||
$_content = $_timestamp = null;
|
||||
$_return = call_user_func_array(
|
||||
$_return = \call_user_func_array(
|
||||
$default_handler,
|
||||
[$this->type, $this->name, &$_content, &$_timestamp, $this->smarty]
|
||||
);
|
||||
|
||||
@@ -104,7 +104,7 @@ abstract class TemplateBase extends Data {
|
||||
}
|
||||
// register the object
|
||||
$smarty->registered_objects[$object_name] =
|
||||
[$object, (array)$allowed_methods_properties, (boolean)$format, (array)$block_methods];
|
||||
[$object, (array)$allowed_methods_properties, (bool)$format, (array)$block_methods];
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -179,7 +179,7 @@ abstract class TemplateBase extends Data {
|
||||
* @api Smarty::createData()
|
||||
*
|
||||
*/
|
||||
public function createData(Data $parent = null, $name = null) {
|
||||
public function createData(?Data $parent = null, $name = null) {
|
||||
/* @var Smarty $smarty */
|
||||
$smarty = $this->getSmarty();
|
||||
$dataObj = new Data($parent, $smarty, $name);
|
||||
|
||||
+2
-1
@@ -108,7 +108,7 @@
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>Smarty {\Smarty\Smarty::SMARTY_VERSION} Debug Console
|
||||
<h1>Smarty {$smarty.version} Debug Console
|
||||
- {if isset($template_name)}{$template_name|debug_print_var nofilter} {/if}{if !empty($template_data)}Total Time {$execution_time|string_format:"%.5f"}{/if}</h1>
|
||||
|
||||
{if !empty($template_data)}
|
||||
@@ -144,6 +144,7 @@
|
||||
{$vars['attributes']|debug_print_var nofilter}
|
||||
{/if}
|
||||
</td>
|
||||
</tr>
|
||||
{/foreach}
|
||||
</table>
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ class PHPUnit_Smarty extends PHPUnit\Framework\TestCase
|
||||
*/
|
||||
public static function setUpBeforeClass(): void
|
||||
{
|
||||
error_reporting(E_ALL & ~E_STRICT & ~E_DEPRECATED & ~E_USER_DEPRECATED);
|
||||
error_reporting(E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED);
|
||||
self::$init = true;
|
||||
self::$pluginsdir =self::getSmartyPluginsDir();
|
||||
}
|
||||
|
||||
@@ -65,15 +65,34 @@ class UndefinedTemplateVarTest extends PHPUnit_Smarty
|
||||
*/
|
||||
public function testError()
|
||||
{
|
||||
$this->smarty->error_unassigned = true;
|
||||
$this->smarty->error_unassigned = true;
|
||||
$this->expectException(PHPUnit\Framework\Error\Error::class);
|
||||
$this->expectExceptionMessage('Undefined ');
|
||||
$this->expectExceptionMessage('Undefined ');
|
||||
$e1 = error_reporting();
|
||||
$this->assertEquals('undefined = ', $this->smarty->fetch('001_main.tpl'));
|
||||
$e2 = error_reporting();
|
||||
$this->assertEquals($e1, $e2);
|
||||
}
|
||||
|
||||
public function testNoError()
|
||||
{
|
||||
$this->smarty->error_unassigned = false;
|
||||
$e1 = error_reporting();
|
||||
$this->assertEquals('undefined = ', $this->smarty->fetch('001_main.tpl'));
|
||||
$e2 = error_reporting();
|
||||
$this->assertEquals($e1, $e2);
|
||||
}
|
||||
|
||||
public function testNoErrorForIssetOrEmpty()
|
||||
{
|
||||
$this->smarty->error_unassigned = true;
|
||||
$e1 = error_reporting();
|
||||
$this->assertEquals('undefined = ', $this->smarty->fetch('001_isset.tpl'));
|
||||
$this->assertEquals('undefined = ', $this->smarty->fetch('001_empty.tpl'));
|
||||
$e2 = error_reporting();
|
||||
$this->assertEquals($e1, $e2);
|
||||
}
|
||||
|
||||
public function testUndefinedSimpleVar() {
|
||||
$this->smarty->muteUndefinedOrNullWarnings();
|
||||
$tpl = $this->smarty->createTemplate('string:a{if $undef}def{/if}b');
|
||||
@@ -133,30 +152,30 @@ class UndefinedTemplateVarTest extends PHPUnit_Smarty
|
||||
}
|
||||
|
||||
|
||||
public function testDereferenceOnNull() {
|
||||
$this->smarty->setErrorReporting(E_ALL & ~E_WARNING & ~E_NOTICE);
|
||||
$this->smarty->muteUndefinedOrNullWarnings();
|
||||
$tpl = $this->smarty->createTemplate('string:a{if $object->myprop}def{/if}b');
|
||||
$this->smarty->assign('object', null);
|
||||
$this->assertEquals("ab", $this->smarty->fetch($tpl));
|
||||
}
|
||||
public function testDereferenceOnNull() {
|
||||
$this->smarty->setErrorReporting(E_ALL & ~E_WARNING & ~E_NOTICE);
|
||||
$this->smarty->muteUndefinedOrNullWarnings();
|
||||
$tpl = $this->smarty->createTemplate('string:a{if $object->myprop}def{/if}b');
|
||||
$this->smarty->assign('object', null);
|
||||
$this->assertEquals("ab", $this->smarty->fetch($tpl));
|
||||
}
|
||||
|
||||
|
||||
public function testDereferenceOnBool() {
|
||||
$this->smarty->setErrorReporting(E_ALL & ~E_NOTICE);
|
||||
$this->smarty->muteUndefinedOrNullWarnings();
|
||||
$tpl = $this->smarty->createTemplate('string:a{if $object->myprop}def{/if}b');
|
||||
$this->smarty->assign('object', false);
|
||||
$this->assertEquals("ab", $this->smarty->fetch($tpl));
|
||||
}
|
||||
public function testDereferenceOnBool() {
|
||||
$this->smarty->setErrorReporting(E_ALL & ~E_NOTICE);
|
||||
$this->smarty->muteUndefinedOrNullWarnings();
|
||||
$tpl = $this->smarty->createTemplate('string:a{if $object->myprop}def{/if}b');
|
||||
$this->smarty->assign('object', false);
|
||||
$this->assertEquals("ab", $this->smarty->fetch($tpl));
|
||||
}
|
||||
|
||||
|
||||
public function testDereferenceOnString() {
|
||||
$this->smarty->setErrorReporting(E_ALL & ~E_NOTICE);
|
||||
$this->smarty->muteUndefinedOrNullWarnings();
|
||||
$tpl = $this->smarty->createTemplate('string:a{if $object->myprop}def{/if}b');
|
||||
$this->smarty->assign('object', 'xyz');
|
||||
$this->assertEquals("ab", $this->smarty->fetch($tpl));
|
||||
}
|
||||
public function testDereferenceOnString() {
|
||||
$this->smarty->setErrorReporting(E_ALL & ~E_NOTICE);
|
||||
$this->smarty->muteUndefinedOrNullWarnings();
|
||||
$tpl = $this->smarty->createTemplate('string:a{if $object->myprop}def{/if}b');
|
||||
$this->smarty->assign('object', 'xyz');
|
||||
$this->assertEquals("ab", $this->smarty->fetch($tpl));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
undefined = {if empty($foo)}{/if}
|
||||
@@ -0,0 +1 @@
|
||||
undefined = {if isset($foo)}{/if}
|
||||
@@ -61,4 +61,68 @@ class AutoEscapeTest extends PHPUnit_Smarty
|
||||
$this->assertEquals("<p>hi</p>", $this->smarty->fetch($tpl));
|
||||
}
|
||||
|
||||
/**
|
||||
* test autoescape + raw modifier
|
||||
*/
|
||||
public function testAutoEscapeRaw() {
|
||||
$tpl = $this->smarty->createTemplate('eval:{$foo|raw}');
|
||||
$tpl->assign('foo', '<a@b.c>');
|
||||
$this->assertEquals("<a@b.c>", $this->smarty->fetch($tpl));
|
||||
}
|
||||
|
||||
/**
|
||||
* test autoescape + escape modifier = no double-escaping
|
||||
*/
|
||||
public function testAutoEscapeNoDoubleEscape() {
|
||||
$tpl = $this->smarty->createTemplate('eval:{$foo|escape}');
|
||||
$tpl->assign('foo', '<a@b.c>');
|
||||
$this->assertEquals("<a@b.c>", $this->smarty->fetch($tpl));
|
||||
}
|
||||
|
||||
/**
|
||||
* test autoescape + escape modifier = force double-escaping
|
||||
*/
|
||||
public function testAutoEscapeForceDoubleEscape() {
|
||||
$tpl = $this->smarty->createTemplate('eval:{$foo|escape:\'force\'}');
|
||||
$tpl->assign('foo', '<a@b.c>');
|
||||
$this->assertEquals("&lt;a@b.c&gt;", $this->smarty->fetch($tpl));
|
||||
}
|
||||
|
||||
/**
|
||||
* test autoescape + escape modifier = special escape
|
||||
*/
|
||||
public function testAutoEscapeSpecialEscape() {
|
||||
$tpl = $this->smarty->createTemplate('eval:{$foo|escape:\'url\'}');
|
||||
$tpl->assign('foo', 'aa bb');
|
||||
$this->assertEquals("aa%20bb", $this->smarty->fetch($tpl));
|
||||
}
|
||||
|
||||
/**
|
||||
* test autoescape + escape modifier = special escape
|
||||
*/
|
||||
public function testAutoEscapeSpecialEscape2() {
|
||||
$tpl = $this->smarty->createTemplate('eval:{$foo|escape:\'url\'}');
|
||||
$tpl->assign('foo', '<BR>');
|
||||
$this->assertEquals("%3CBR%3E", $this->smarty->fetch($tpl));
|
||||
}
|
||||
|
||||
/**
|
||||
* test autoescape + escape modifier = special escape
|
||||
*/
|
||||
public function testAutoEscapeSpecialEscape3() {
|
||||
$tpl = $this->smarty->createTemplate('eval:{$foo|escape:\'htmlall\'}');
|
||||
$tpl->assign('foo', '<BR>');
|
||||
$this->assertEquals("<BR>", $this->smarty->fetch($tpl));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* test autoescape + escape modifier = special escape
|
||||
*/
|
||||
public function testAutoEscapeSpecialEscape4() {
|
||||
$tpl = $this->smarty->createTemplate('eval:{$foo|escape:\'javascript\'}');
|
||||
$tpl->assign('foo', '<\'');
|
||||
$this->assertEquals("<\\'", $this->smarty->fetch($tpl));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -14,10 +14,13 @@ include_once __DIR__ . '/../_shared/CacheResourceTestCommon.php';
|
||||
class CacheResourceFileTest extends CacheResourceTestCommon
|
||||
{
|
||||
|
||||
private $directorySeparator;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
$this->setUpSmarty(__DIR__);
|
||||
parent::setUp();
|
||||
$this->directorySeparator = preg_quote(DIRECTORY_SEPARATOR, '/');
|
||||
$this->smarty->setCachingType('filetest');
|
||||
}
|
||||
|
||||
@@ -38,7 +41,8 @@ class CacheResourceFileTest extends CacheResourceTestCommon
|
||||
$this->smarty->setUseSubDirs(true);
|
||||
$tpl = $this->smarty->createTemplate('helloworld.tpl');
|
||||
|
||||
$this->assertRegExp('/.*\/([a-f0-9]{2}\/){3}.*.php/', $tpl->getCached()->filepath);
|
||||
$pattern = '/.*' . $this->directorySeparator . '([a-f0-9]{2}' . $this->directorySeparator . '){3}.*\.php/';
|
||||
$this->assertRegExp($pattern, $tpl->getCached()->filepath);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -51,7 +55,8 @@ class CacheResourceFileTest extends CacheResourceTestCommon
|
||||
$this->smarty->setUseSubDirs(true);
|
||||
$tpl = $this->smarty->createTemplate('helloworld.tpl', 'foo|bar');
|
||||
|
||||
$this->assertRegExp('/.*\/foo\/bar\/([a-f0-9]{2}\/){3}.*.php/', $tpl->getCached()->filepath);
|
||||
$pattern = '/.*' . $this->directorySeparator . 'foo' . $this->directorySeparator . 'bar' . $this->directorySeparator . '([a-f0-9]{2}' . $this->directorySeparator . '){3}.*\.php/';
|
||||
$this->assertRegExp($pattern, $tpl->getCached()->filepath);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,7 +68,9 @@ class CacheResourceFileTest extends CacheResourceTestCommon
|
||||
$this->smarty->cache_lifetime = 1000;
|
||||
$this->smarty->setUseSubDirs(true);
|
||||
$tpl = $this->smarty->createTemplate('helloworld.tpl', null, 'blar');
|
||||
$this->assertRegExp('/.*\/blar\/([a-f0-9]{2}\/){3}.*.php/', $tpl->getCached()->filepath);
|
||||
|
||||
$pattern = '/.*' . $this->directorySeparator . 'blar' . $this->directorySeparator . '([a-f0-9]{2}' . $this->directorySeparator . '){3}.*\.php/';
|
||||
$this->assertRegExp($pattern, $tpl->getCached()->filepath);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -75,7 +82,9 @@ class CacheResourceFileTest extends CacheResourceTestCommon
|
||||
$this->smarty->cache_lifetime = 1000;
|
||||
$this->smarty->setUseSubDirs(true);
|
||||
$tpl = $this->smarty->createTemplate('helloworld.tpl', 'foo|bar', 'blar');
|
||||
$this->assertRegExp('/.*\/foo\/bar\/blar\\/([a-f0-9]{2}\/){3}.*.php/', $tpl->getCached()->filepath);
|
||||
|
||||
$pattern = '/.*' . $this->directorySeparator . 'foo' . $this->directorySeparator . 'bar' . $this->directorySeparator . 'blar' . $this->directorySeparator . '([a-f0-9]{2}' . $this->directorySeparator . '){3}.*\.php/';
|
||||
$this->assertRegExp($pattern, $tpl->getCached()->filepath);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,7 +12,7 @@ class Smarty_Resource_FiletestPlugin extends FilePlugin
|
||||
* @param Source $source source object
|
||||
* @param Template $_template template object
|
||||
*/
|
||||
public function populate(Source $source, Template $_template = null)
|
||||
public function populate(Source $source, ?Template $_template = null)
|
||||
{
|
||||
parent::populate($source, $_template);
|
||||
if ($source->exists) {
|
||||
|
||||
@@ -0,0 +1,193 @@
|
||||
<?php
|
||||
|
||||
use Smarty\Compile\AttributeCompiler;
|
||||
use Smarty\Compiler\Template;
|
||||
|
||||
class AttributeCompilerTest extends PHPUnit\Framework\TestCase
|
||||
{
|
||||
/**
|
||||
* The template compiler.
|
||||
*/
|
||||
private $template_compiler;
|
||||
|
||||
/**
|
||||
* The attributes
|
||||
*/
|
||||
private $attributes = [];
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* Set up attribute compiler class
|
||||
*/
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->template_compiler = $this->createMock(Template::class);
|
||||
|
||||
// reset attributes to empty arrays
|
||||
$this->attributes = [
|
||||
'required_attributes' => [],
|
||||
'optional_attributes' => [],
|
||||
'shorttag_order' => [],
|
||||
'option_flags' => [],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the attribute compiler for testing.
|
||||
*/
|
||||
private function createAttributeCompiler() {
|
||||
return new AttributeCompiler(
|
||||
$this->attributes['required_attributes'],
|
||||
$this->attributes['optional_attributes'],
|
||||
$this->attributes['shorttag_order'],
|
||||
$this->attributes['option_flags']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests shorthand attribute compiling.
|
||||
*/
|
||||
public function testAttributeCompiler(): void
|
||||
{
|
||||
$this->attributes['shorttag_order'] = ['shorttag'];
|
||||
$this->attributes['required_attributes'] = ['required'];
|
||||
$this->attributes['option_flags'] = ['option', 'option_two'];
|
||||
|
||||
$payload = [
|
||||
0 => 'shorttag value',
|
||||
1 => [
|
||||
'required' => 'required_value'
|
||||
],
|
||||
2 => 'option',
|
||||
];
|
||||
|
||||
$this->assertEquals(
|
||||
$this->createAttributeCompiler()
|
||||
->getAttributes($this->template_compiler, $payload),
|
||||
[
|
||||
'shorttag' => 'shorttag value',
|
||||
'required' => 'required_value',
|
||||
'option' => true,
|
||||
'option_two' => false,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests normal optional attribute compiling.
|
||||
*/
|
||||
public function testAttributeCompilerOptionalArguments(): void
|
||||
{
|
||||
$this->attributes['optional_attributes'] = ['optional'];
|
||||
|
||||
$payload = [
|
||||
0 => [
|
||||
'optional' => 'optional value'
|
||||
],
|
||||
];
|
||||
|
||||
$this->assertEquals(
|
||||
$this->createAttributeCompiler()
|
||||
->getAttributes($this->template_compiler, $payload),
|
||||
[
|
||||
'optional' => 'optional value',
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
$this->createAttributeCompiler()
|
||||
->getAttributes($this->template_compiler, []),
|
||||
[]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests any attribute compiling.
|
||||
*/
|
||||
public function testAttributeCompilerAnyOptionalArguments(): void
|
||||
{
|
||||
$this->attributes['optional_attributes'] = ['_any'];
|
||||
|
||||
$payload = [
|
||||
0 => [
|
||||
'optional' => 'optional value'
|
||||
],
|
||||
1 => [
|
||||
'optional_two' => 'optional value two'
|
||||
],
|
||||
];
|
||||
|
||||
$this->assertEquals(
|
||||
$this->createAttributeCompiler()
|
||||
->getAttributes($this->template_compiler, $payload),
|
||||
[
|
||||
'optional' => 'optional value',
|
||||
'optional_two' => 'optional value two',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if the attribute compiler tries to throw a too many shorthand attributes error.
|
||||
*/
|
||||
public function testAttributeCompilerTooManyShorthands(): void
|
||||
{
|
||||
$payload = [
|
||||
0 => 'option one',
|
||||
];
|
||||
|
||||
$this->template_compiler
|
||||
->expects(self::once())
|
||||
->method('trigger_template_error')
|
||||
->with('too many shorthand attributes', null, true);
|
||||
|
||||
$this->createAttributeCompiler()
|
||||
->getAttributes($this->template_compiler, $payload);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if the attribute compiler tries to throw a missing required attribute error.
|
||||
*/
|
||||
public function testAttributeCompilerWithMissingRequiredAttributes(): void
|
||||
{
|
||||
$this->attributes['required_attributes'] = ['required'];
|
||||
|
||||
$this->template_compiler
|
||||
->expects(self::once())
|
||||
->method('trigger_template_error')
|
||||
->with('missing \'required\' attribute', null, true);
|
||||
|
||||
$this->createAttributeCompiler()
|
||||
->getAttributes($this->template_compiler, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if the attribute compiler tries to throw a illegal value template error.
|
||||
*/
|
||||
public function testAttributeCompilerWithInvalidOptionAttribute(): void
|
||||
{
|
||||
$this->attributes['option_flags'] = ['option'];
|
||||
|
||||
$this->template_compiler
|
||||
->expects(self::once())
|
||||
->method('trigger_template_error')
|
||||
->with('illegal value \'\'foo\'\' for options flag \'option\'', null, true);
|
||||
|
||||
$this->createAttributeCompiler()
|
||||
->getAttributes($this->template_compiler, [0 => ['option' => 'foo']]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if the attribute compiler tries to throw an unexpected attribute error.
|
||||
*/
|
||||
public function testAttributeCompilerWithInvalidUnexpectedAttribute(): void
|
||||
{
|
||||
$this->template_compiler
|
||||
->expects(self::once())
|
||||
->method('trigger_template_error')
|
||||
->with('unexpected \'unexpected\' attribute', null, true);
|
||||
|
||||
$this->createAttributeCompiler()
|
||||
->getAttributes($this->template_compiler, [0 => ['unexpected' => 'bar']]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
use Smarty\Compile\FunctionCallCompiler;
|
||||
use Smarty\Compiler\Template;
|
||||
use Smarty\FunctionHandler\AttributeFunctionHandlerInterface;
|
||||
use Smarty\Smarty;
|
||||
|
||||
class FunctionCallCompilerTest extends PHPUnit\Framework\TestCase
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
* Set up attribute compiler class
|
||||
*/
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->smarty = $this->createMock(Smarty::class);
|
||||
$this->template_compiler = $this->createMock(Template::class);
|
||||
$this->template_compiler
|
||||
->expects(self::once())
|
||||
->method('getSmarty')
|
||||
->willReturn($this->smarty);
|
||||
}
|
||||
|
||||
public function testAttributeFunctionHandlerInterface(): void
|
||||
{
|
||||
$attribute_function_handler = $this->createMock(AttributeFunctionHandlerInterface::class);
|
||||
|
||||
$attribute_function_handler
|
||||
->expects(self::once())
|
||||
->method('getSupportedAttributes')
|
||||
->willReturn([
|
||||
'required_attributes' => ['required'],
|
||||
'optional_attributes' => ['optional'],
|
||||
'shorttag_order' => ['short'],
|
||||
'option_flags' => ['option'],
|
||||
]);
|
||||
|
||||
$args = [
|
||||
0 => 'short',
|
||||
1 => 'option',
|
||||
2 => [
|
||||
'optional' => 'optional',
|
||||
],
|
||||
3 => [
|
||||
'required' => 'required',
|
||||
],
|
||||
];
|
||||
|
||||
$this->smarty
|
||||
->expects(self::once())
|
||||
->method('getFunctionHandler')
|
||||
->with('method')
|
||||
->willReturn($attribute_function_handler);
|
||||
|
||||
$function_call_compiler = new FunctionCallCompiler();
|
||||
|
||||
$this->assertEquals(
|
||||
$function_call_compiler->compile($args, $this->template_compiler, [], null, 'method'),
|
||||
'$_smarty_tpl->getSmarty()->getFunctionHandler(\'method\')->handle(array(\'short\'=>short,\'option\'=>1,\'optional\'=>optional,\'required\'=>required), $_smarty_tpl)'
|
||||
);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -34,7 +34,7 @@ class Smarty_Resource_AmbiguousPlugin extends FilePlugin
|
||||
* @param Source $source source object
|
||||
* @param Template $_template template object
|
||||
*/
|
||||
public function populate(Source $source, Template $_template = null)
|
||||
public function populate(Source $source, ?Template $_template = null)
|
||||
{
|
||||
$segment = '';
|
||||
if ($this->segment) {
|
||||
|
||||
@@ -16,7 +16,7 @@ use Smarty\Template\Source;
|
||||
|
||||
class Smarty_Resource_Db extends RecompiledPlugin {
|
||||
|
||||
public function populate(Source $source, Template $_template = null) {
|
||||
public function populate(Source $source, ?Template $_template = null) {
|
||||
$source->uid = sha1($source->resource);
|
||||
$source->timestamp = 1000000000;
|
||||
$source->exists = true;
|
||||
|
||||
@@ -16,7 +16,7 @@ use Smarty\Template\Source;
|
||||
|
||||
class Smarty_Resource_Db2 extends RecompiledPlugin
|
||||
{
|
||||
public function populate(Source $source, Template $_template = null)
|
||||
public function populate(Source $source, ?Template $_template = null)
|
||||
{
|
||||
$source->uid = sha1($source->resource);
|
||||
$source->timestamp = 0;
|
||||
|
||||
@@ -15,7 +15,7 @@ use Smarty\Template\Source;
|
||||
|
||||
class Smarty_Resource_Db3 extends Smarty\Resource\BasePlugin
|
||||
{
|
||||
public function populate(Source $source, Template $_template = null)
|
||||
public function populate(Source $source, ?Template $_template = null)
|
||||
{
|
||||
$source->uid = sha1($source->resource);
|
||||
$source->timestamp = 0;
|
||||
|
||||
@@ -16,7 +16,7 @@ use Smarty\Template\Source;
|
||||
|
||||
class Smarty_Resource_Db4 extends Smarty\Resource\BasePlugin
|
||||
{
|
||||
public function populate(Source $source, Template $_template = null)
|
||||
public function populate(Source $source, ?Template $_template = null)
|
||||
{
|
||||
$source->uid = sha1($source->resource);
|
||||
$source->timestamp = 0;
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
# Ignore anything in here, but keep this directory
|
||||
*
|
||||
@@ -1,2 +0,0 @@
|
||||
# Ignore anything in here, but keep this directory
|
||||
*
|
||||
@@ -192,6 +192,15 @@ class RegisterFunctionTest extends PHPUnit_Smarty
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* test registerPlugin for function name ending in 'close' #1122
|
||||
*/
|
||||
public function testRegisterFunctionEndingInClose()
|
||||
{
|
||||
$this->smarty->registerPlugin(Smarty::PLUGIN_FUNCTION, 'window_close', 'myfunction');
|
||||
$this->assertEquals('hello world 1', $this->smarty->fetch('eval:{window_close value=1}'));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function myfunction($params, $smarty)
|
||||
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
// first class callables where introduced in PHP 8.1
|
||||
if (PHP_VERSION_ID >= 80100) {
|
||||
|
||||
/**
|
||||
* class for register modifier with (first class) callables tests
|
||||
*
|
||||
* @runTestsInSeparateProcess
|
||||
* @preserveGlobalState disabled
|
||||
* @backupStaticAttributes enabled
|
||||
*/
|
||||
class RegisterModifierFirstClassCallablesTest extends PHPUnit_Smarty
|
||||
{
|
||||
public function setUp(): void
|
||||
{
|
||||
$this->setUpSmarty(__DIR__);
|
||||
}
|
||||
|
||||
|
||||
public function testInit()
|
||||
{
|
||||
$this->cleanDirs();
|
||||
}
|
||||
|
||||
public function testRegisterFirstClassCallable()
|
||||
{
|
||||
$this->smarty->registerPlugin(\Smarty\Smarty::PLUGIN_MODIFIER, 'testmodifier', eval('return strrev(...);'));
|
||||
$this->assertEquals('mosredna', $this->smarty->fetch('string:{"andersom"|testmodifier}'));
|
||||
}
|
||||
|
||||
public function testRegisterFirstClassCallableSameName()
|
||||
{
|
||||
$this->smarty->registerPlugin(\Smarty\Smarty::PLUGIN_MODIFIER, 'mymodifier', eval('return strrev(...);'));
|
||||
$this->assertEquals('mosredna', $this->smarty->fetch('string:{"andersom"|mymodifier}'));
|
||||
}
|
||||
|
||||
public function testRegisterFirstClassCallableAsFunc()
|
||||
{
|
||||
$this->smarty->registerPlugin(\Smarty\Smarty::PLUGIN_MODIFIER, 'kprint_r_out', eval('return strrev(...);'));
|
||||
$this->smarty->assign('myVar', 'andersom');
|
||||
$this->assertEquals('mosredna', $this->smarty->fetch('string:{kprint_r_out($myVar)}'));
|
||||
}
|
||||
|
||||
public function testRegisterFirstClassCallableSameNameAsPhpFunc()
|
||||
{
|
||||
$this->smarty->registerPlugin(\Smarty\Smarty::PLUGIN_MODIFIER, 'mymodifierfcc', eval('return strrev(...);'));
|
||||
$this->assertEquals('mosredna', $this->smarty->fetch('string:{mymodifierfcc("andersom")}'));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
function mymodifierfcc($a, $b, $c)
|
||||
{
|
||||
return "$a function $b $c";
|
||||
}
|
||||
@@ -135,6 +135,20 @@ class RegisterModifierTest extends PHPUnit_Smarty
|
||||
$this->assertEquals($expectedValue, $this->smarty->fetch('string:' . $template));
|
||||
}
|
||||
|
||||
public function testRegisterNativePhpFuncAsString()
|
||||
{
|
||||
$this->smarty->registerPlugin(\Smarty\Smarty::PLUGIN_MODIFIER, 'strrev', 'strrev');
|
||||
$this->smarty->assign('myVar', 'andersom');
|
||||
$this->assertEquals('mosredna', $this->smarty->fetch('string:{strrev($myVar)}'));
|
||||
}
|
||||
|
||||
public function testRegisterNativePhpFuncUnderDifferentName()
|
||||
{
|
||||
$this->smarty->registerPlugin(\Smarty\Smarty::PLUGIN_MODIFIER, 'k_xyz_a', 'strrev');
|
||||
$this->smarty->assign('myVar', 'andersom');
|
||||
$this->assertEquals('mosredna', $this->smarty->fetch('string:{k_xyz_a($myVar)}'));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class WildcardExtension extends \Smarty\Extension\Base {
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tests the ::hasVariable method
|
||||
*/
|
||||
class HasVariableTest extends PHPUnit_Smarty
|
||||
{
|
||||
public function setUp(): void
|
||||
{
|
||||
$this->setUpSmarty(__DIR__);
|
||||
}
|
||||
|
||||
|
||||
public function testInit()
|
||||
{
|
||||
$this->cleanDirs();
|
||||
}
|
||||
|
||||
public function testSimpleTrue()
|
||||
{
|
||||
$this->smarty->assign('foo', 'bar');
|
||||
$this->assertTrue($this->smarty->hasVariable('foo'));
|
||||
}
|
||||
|
||||
|
||||
public function testSimpleFalse()
|
||||
{
|
||||
$this->smarty->assign('foo', 'bar');
|
||||
$this->assertFalse($this->smarty->hasVariable('foox'));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,7 +4,7 @@ class NullCoalescingTest extends PHPUnit_Smarty {
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
$this->setUpSmarty('/tmp');
|
||||
$this->setUpSmarty(sys_get_temp_dir());
|
||||
$this->cleanDirs();
|
||||
}
|
||||
|
||||
|
||||
@@ -41,10 +41,9 @@ class CompileIfTest extends PHPUnit_Smarty
|
||||
$name = empty($testName) ? $testNumber : $testName;
|
||||
$file = "testIf_{$name}.tpl";
|
||||
$this->makeTemplateFile($file, $code);
|
||||
$this->smarty->assignGlobal('file', $file);
|
||||
$this->smarty->assign('file', $file);
|
||||
$this->smarty->assign('bar', 'buh');
|
||||
$this->assertEquals($result, $this->smarty->fetch($file),
|
||||
"testIf - {$code} - {$name}");
|
||||
$this->assertEquals($result, $this->smarty->fetch($file), "testIf - {$code} - {$name}");
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -148,4 +148,10 @@ class CompileSectionTest extends PHPUnit_Smarty
|
||||
);
|
||||
}
|
||||
|
||||
public function testSectionWithNocache()
|
||||
{
|
||||
$source = 'string:{section name=module start=0 loop=1 nocache}{/section}';
|
||||
$this->assertEquals('', $this->smarty->fetch($source));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -442,4 +442,28 @@ class CompileFunctionTest extends PHPUnit_Smarty
|
||||
$this->smarty->fetch('string:{function name=\'rce(){};echo "hi";function \'}{/function}');
|
||||
}
|
||||
|
||||
/**
|
||||
* test shorthand function definition with regular call
|
||||
*/
|
||||
public function testShorthand1()
|
||||
{
|
||||
$this->assertEquals("gribus", $this->smarty->fetch('shorthand1.tpl'));
|
||||
}
|
||||
|
||||
/**
|
||||
* test normal function definition with shorthand call
|
||||
*/
|
||||
public function testShorthand2()
|
||||
{
|
||||
$this->assertEquals("gribus", $this->smarty->fetch('shorthand2.tpl'));
|
||||
}
|
||||
|
||||
/**
|
||||
* test shorthand function definition with shorthand call
|
||||
*/
|
||||
public function testShorthand3()
|
||||
{
|
||||
$this->assertEquals("gribus", $this->smarty->fetch('shorthand3.tpl'));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
{function blah}gribus{/function}
|
||||
{call name=blah}
|
||||
@@ -0,0 +1,2 @@
|
||||
{function name=blah}gribus{/function}
|
||||
{blah}
|
||||
@@ -0,0 +1,2 @@
|
||||
{function blah}gribus{/function}
|
||||
{blah}
|
||||
@@ -4,7 +4,7 @@ class TernaryTest extends PHPUnit_Smarty {
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
$this->setUpSmarty('/tmp');
|
||||
$this->setUpSmarty(sys_get_temp_dir());
|
||||
$this->cleanDirs();
|
||||
}
|
||||
|
||||
|
||||
@@ -70,6 +70,8 @@ class ArrayTest extends PHPUnit_Smarty
|
||||
array('{$foo=[1,2,[7,8,9],4,5]}{$x=2}{$foo.$x.0}', '7', 'T13', $i++),
|
||||
array('{$foo=[1,2,[7,8,9],4,5]}{$x=0}{$foo.2.$x}', '7', 'T14', $i++),
|
||||
array('{$foo=[1,2,[7,8,9],4,5]}{$x=[1,0]}{$foo.2.{$x.1}}', '7', 'T15', $i++),
|
||||
array('{$foo=[1,2,3,4,5,]}{foreach $foo as $bar}{$bar}{/foreach}', '12345', 'T16', $i++),
|
||||
array('{$foo=[1,2,3,4,5,[6,7,8,],]}{$foo[5][2]}', '8', 'T17', $i++),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ class My_Resource_Extendsall extends \Smarty\Resource\ExtendsPlugin
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function populate(Source $source, Template $_template = null)
|
||||
public function populate(Source $source, ?Template $_template = null)
|
||||
{
|
||||
$uid = '';
|
||||
$sources = array();
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
FROM php:8.4-cli-bullseye
|
||||
|
||||
## Basic utilities
|
||||
RUN apt-get update -yqq && apt-get install -y curl apt-utils git zip unzip
|
||||
|
||||
## Composer
|
||||
COPY ./utilities/testrunners/shared/install-composer.sh /root/install-composer.sh
|
||||
WORKDIR /root
|
||||
RUN sh ./install-composer.sh
|
||||
RUN mv ./composer.phar /usr/local/bin/composer
|
||||
@@ -0,0 +1,10 @@
|
||||
FROM php:8.5-rc-cli-bullseye
|
||||
|
||||
## Basic utilities
|
||||
RUN apt-get update -yqq && apt-get install -y curl apt-utils git zip unzip
|
||||
|
||||
## Composer
|
||||
COPY ./utilities/testrunners/shared/install-composer.sh /root/install-composer.sh
|
||||
WORKDIR /root
|
||||
RUN sh ./install-composer.sh
|
||||
RUN mv ./composer.phar /usr/local/bin/composer
|
||||
Reference in New Issue
Block a user