mirror of
https://github.com/smarty-php/smarty.git
synced 2026-08-04 04:24:18 +02:00
Compare commits
47 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4fec27ccc2 | |||
| fea0d02d99 | |||
| 4efa427a87 | |||
| 30b1c5bf6d | |||
| 3f871f9f7a | |||
| e161babbd4 | |||
| f8e63fc480 | |||
| 82397ec7f0 | |||
| 17da1f585e | |||
| 293bc20db0 | |||
| 818b96ffbd | |||
| 7b5ec8a065 | |||
| 4af5cc760d | |||
| 41d80b99ac | |||
| 2b0ba0eabc | |||
| 66edb56911 | |||
| 15e48b6af3 | |||
| d5adea5863 | |||
| 8041d0a4e8 | |||
| 94d9861d29 | |||
| 63ff7d81e0 | |||
| e6b6a0cbb2 | |||
| 0912124c33 | |||
| c0306d9942 | |||
| 3fff0813e8 | |||
| 3714d9ad8d | |||
| 1820e875dc | |||
| a112c7446c | |||
| aab7f3db71 | |||
| 08c90664f0 | |||
| f2a66365de | |||
| c338585791 | |||
| c011891247 | |||
| 6ca6f72750 | |||
| 39c150ae58 | |||
| 58991f3f63 | |||
| 4038fa615b | |||
| 198338e2a2 | |||
| bc4e70f2c0 | |||
| b28b85dbf4 | |||
| ad73f4943b | |||
| 4d22803c32 | |||
| 9ee3cce380 | |||
| babec0f29b | |||
| 212bf88eb2 | |||
| 26332c9de4 | |||
| af2e12d58e |
@@ -31,6 +31,7 @@ jobs:
|
||||
- "8.0"
|
||||
- "8.1"
|
||||
- "8.2"
|
||||
- "8.3"
|
||||
|
||||
compiler:
|
||||
- default
|
||||
@@ -45,6 +46,9 @@ jobs:
|
||||
- os: ubuntu-latest
|
||||
php-version: "8.2"
|
||||
compiler: jit
|
||||
- os: ubuntu-latest
|
||||
php-version: "8.3"
|
||||
compiler: jit
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
|
||||
+37
-1
@@ -6,8 +6,43 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [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)
|
||||
|
||||
### Removed
|
||||
- Dropped support for undocumented `{time()}` added in v5.0.0 since we already have the documented `{$smarty.now}`
|
||||
|
||||
## [5.0.0-rc3] - 2024-02-26
|
||||
|
||||
### Added
|
||||
- PHP8.3 support [#925](https://github.com/smarty-php/smarty/issues/925)
|
||||
- Backlink to GitHub in docs
|
||||
- Explain how to do escaping and set-up auto-escaping in docs [#865](https://github.com/smarty-php/smarty/issues/865)
|
||||
- Link to variable scope page in the documentation for the assign tag [#878](https://github.com/smarty-php/smarty/issues/878)
|
||||
- Add support for implode, substr and json_encode as modifiers/functions in templates [#939](https://github.com/smarty-php/smarty/issues/939)
|
||||
- Add template path to CompilerException to enable rich debug features [#935](https://github.com/smarty-php/smarty/issues/935)
|
||||
|
||||
### Fixed
|
||||
- The {debug} tag was broken in v5 [#922](https://github.com/smarty-php/smarty/issues/922)
|
||||
- Documentation on `{if $x is even by $y}` syntax
|
||||
- Fix incorrect compilation of expressions when escape_html=true [#930](https://github.com/smarty-php/smarty/pull/930)
|
||||
|
||||
## [5.0.0-rc2] - 2023-11-11
|
||||
|
||||
### Fixed
|
||||
- Registered output filters wouldn't run [#899](https://github.com/smarty-php/smarty/issues/899)
|
||||
- Use of negative numbers in {math} equations [#895](https://github.com/smarty-php/smarty/issues/895)
|
||||
- Do not auto-html-escape custom function results [#906](https://github.com/smarty-php/smarty/issues/906)
|
||||
- Fix case-sensitive tag names [#907](https://github.com/smarty-php/smarty/issues/907)
|
||||
|
||||
### Removed
|
||||
- Removed `$smarty->registered_filters` array
|
||||
@@ -34,7 +69,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
multibyte extension for optimal performance.
|
||||
- Smarty no longer calls `mb_internal_encoding()` and doesn't check for deprecated `mbstring.func_overload` ini directive [#480](https://github.com/smarty-php/smarty/issues/480)
|
||||
- Generated `<script>` tags lo longer have deprecated `type="text/javascript"` or `language="Javascript"` attributes [#815](https://github.com/smarty-php/smarty/issues/815)
|
||||
- Smarty will throw a compiler exception insteadd of silently ignoring a modifier on a function call, like this: `{include|dot:"x-template-id" file="included.dot.tpl"}` [#526](https://github.com/smarty-php/smarty/issues/526)
|
||||
- Smarty will throw a compiler exception instead of silently ignoring a modifier on a function call, like this: `{include|dot:"x-template-id" file="included.dot.tpl"}` [#526](https://github.com/smarty-php/smarty/issues/526)
|
||||
- The documentation was largely rewritten
|
||||
|
||||
### Deprecated
|
||||
@@ -66,6 +101,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Removed constants such as SMARTY_DIR to prevent global side effects.
|
||||
- Removed direct access to `$smarty->template_dir`. Use `$smarty->setTemplateDir()`.
|
||||
- Removed direct access to `$smarty->cache_dir`. Use `$smarty->setCacheDir()`.
|
||||
- Removed direct access to `$smarty->compile_dir`. Use `$smarty->setCompileDir()`.
|
||||
- Removed `$smarty->loadPlugin()`, use `$smarty->registerPlugin()` instead.
|
||||
- Removed `$smarty->appendByRef()` and `$smarty->assignByRef()`.
|
||||
- Removed `$smarty->_current_file`
|
||||
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
# Contributing to Smarty
|
||||
|
||||
First off, thanks for taking the time to contribute! ❤️
|
||||
|
||||
> And if you like the project, but just don't have time to contribute, that's fine. There are other easy ways to support the project and show your appreciation, which we would also be very happy about:
|
||||
> - Star the project
|
||||
> - Tell a friend about it
|
||||
> - Refer this project in your project's readme
|
||||
> - Mention the project at local meetups and tell your friends/colleagues
|
||||
|
||||
## I Have a Question
|
||||
|
||||
> If you want to ask a question, we assume that you have read the available [Documentation](https://smarty-php.github.io/smarty).
|
||||
|
||||
Before you ask a question, it is best to search for existing [Issues](https://github.com/smarty-php/smarty/issues) that might help you.
|
||||
In case you have found a suitable issue and still need clarification, you can write your question in this issue.
|
||||
It is also advisable to search the internet for answers first.
|
||||
|
||||
If you then still feel the need to ask a question and need clarification, we recommend the following:
|
||||
|
||||
- [Open an Issue](https://github.com/smarty-php/smarty/issues/new).
|
||||
- Provide as much context as you can about what you're running into.
|
||||
- Provide Smarty and PHP versions
|
||||
|
||||
We will then take care of the issue as soon as possible.
|
||||
|
||||
## I Want To Contribute
|
||||
|
||||
> ### Legal Notice
|
||||
> When contributing to this project, you must agree that you have authored 100% of the content,
|
||||
> that you have the necessary rights to the content and that the content you contribute may be provided under the project license.
|
||||
|
||||
### Reporting Bugs
|
||||
|
||||
#### Before Submitting a Bug Report
|
||||
|
||||
A good bug report shouldn't leave others needing to chase you up for more information. Therefore, we ask you to
|
||||
investigate carefully, collect information and describe the issue in detail in your report. Please complete the
|
||||
following steps in advance to help us fix any potential bug as fast as possible.
|
||||
|
||||
- Make sure that you are using the latest version.
|
||||
- Determine if your bug is really a bug and not an error on your side. (Make sure that you have read the [documentation](https://smarty-php.github.io/smarty). If you are looking for support, you might want to check [this section](#i-have-a-question)).
|
||||
- To see if other users have experienced (and potentially already solved) the same issue you are having, check if there is not already a bug report existing for your bug or error in the [bug tracker](https://github.com/smarty-php/smarty/issues?q=label%3Abug).
|
||||
- Also make sure to search the internet (including Stack Overflow) to see if users outside of the GitHub community have discussed the issue.
|
||||
- Collect information about the bug:
|
||||
- For an Exception: please provide the Stack trace
|
||||
- OS (Windows, Linux, macOS)
|
||||
- PHP version
|
||||
- Smarty version
|
||||
- A minimal snippet of (your) code that triggers the bug
|
||||
- Expected output versus actual output
|
||||
- Can you reliably reproduce the issue? And can you also reproduce it with older versions?
|
||||
|
||||
#### How Do I Submit a Good Bug Report?
|
||||
|
||||
> You must never report security related issues, vulnerabilities or bugs including sensitive information to the issue tracker, or elsewhere in public.
|
||||
> For sensitive bugs, please see [SECURITY.md](SECURITY.md).
|
||||
|
||||
We use GitHub issues to track bugs and errors. If you run into an issue with the project:
|
||||
|
||||
- Open an [Issue](https://github.com/smarty-php/smarty/issues/new). (Since we can't be sure at this point whether it is a bug or not, we ask you not to talk about a bug yet and not to label the issue.)
|
||||
- Explain the behavior you would expect and the actual behavior.
|
||||
- Please provide as much context as possible and describe the *reproduction steps* that someone else can follow to recreate the issue on their own. This usually includes your code. For good bug reports you should isolate the problem and create a reduced test case.
|
||||
- Provide the information you collected in the previous section.
|
||||
|
||||
Once it's filed:
|
||||
|
||||
- The project team will label the issue accordingly.
|
||||
- A team member will try to reproduce the issue with your provided steps. If there are no reproduction steps or no obvious way to reproduce the issue, the team will ask you for those steps and mark the issue as `needs-repro`. Bugs with the `needs-repro` tag will not be addressed until they are reproduced.
|
||||
- If the team is able to reproduce the issue, it will be marked `needs-fix`, as well as possibly other tags (such as `critical`), and the issue will be left to be implemented by someone.
|
||||
|
||||
|
||||
|
||||
### Suggesting Enhancements
|
||||
|
||||
This section guides you through submitting an enhancement suggestion for CONTRIBUTING.md, **including completely new features and minor improvements to existing functionality**. Following these guidelines will help maintainers and the community to understand your suggestion and find related suggestions.
|
||||
|
||||
|
||||
#### Before Submitting an Enhancement
|
||||
|
||||
- Make sure that you are using the latest version.
|
||||
- Read the [documentation](https://smarty-php.github.io/smarty) carefully and find out if the functionality is already covered, maybe by an individual configuration.
|
||||
- Perform a [search](https://github.com/smarty-php/smarty/issues) to see if the enhancement has already been suggested. If it has, add a comment to the existing issue instead of opening a new one.
|
||||
- Find out whether your idea fits with the scope and aims of the project. It's up to you to make a strong case to convince the project's developers of the merits of this feature. Keep in mind that we want features that will be useful to the majority of our users and not just a small subset. If you're just targeting a minority of users, consider writing an add-on/plugin library.
|
||||
|
||||
|
||||
#### How Do I Submit a Good Enhancement Suggestion?
|
||||
|
||||
Enhancement suggestions are tracked as [GitHub issues](https://github.com/smarty-php/smarty/issues).
|
||||
|
||||
- Use a **clear and descriptive title** for the issue to identify the suggestion.
|
||||
- Provide a **step-by-step description of the suggested enhancement** in as many details as possible.
|
||||
- **Describe the current behavior** and **explain which behavior you expected to see instead** and why. At this point you can also tell which alternatives do not work for you.
|
||||
- You may want to **include screenshots and animated GIFs** which help you demonstrate the steps or point out the part which the suggestion is related to. You can use [this tool](https://www.cockos.com/licecap/) to record GIFs on macOS and Windows, and [this tool](https://github.com/colinkeenan/silentcast) or [this tool](https://github.com/GNOME/byzanz) on Linux.
|
||||
- **Explain why this enhancement would be useful** to most CONTRIBUTING.md users. You may also want to point out the other projects that solved it better and which could serve as inspiration.
|
||||
|
||||
|
||||
### Improving The Documentation
|
||||
|
||||
The [docs](docs/index.md) are written in markdown, configured in [mkdocs.yml](mkdocs.yml) and published
|
||||
to [GitHub pages](https://smarty-php.github.io/smarty) using [mkdocs](https://www.mkdocs.org/) and [mike](https://github.com/jimporter/mike).
|
||||
|
||||
To preview the docs while you are writing, run:
|
||||
```bash
|
||||
mkdocs serve
|
||||
```
|
||||
This should launch a local web server and give you a link to open in your browser.
|
||||
|
||||
When you are finished, commit your changes and provide a [Pull Request](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request).
|
||||
|
||||
#### Publishing the docs
|
||||
If you are a maintainer, you can publish the document using [mike](https://github.com/jimporter/mike). Make sure you provide the correct version.
|
||||
|
||||
```bash
|
||||
mike deploy 5.x
|
||||
```
|
||||
|
||||
## Attribution
|
||||
This guide is based on the **contributing.md**. [Make your own](https://contributing.md/)!
|
||||
@@ -3,12 +3,6 @@ all: lexers parsers
|
||||
lexers: src/Lexer/ConfigfileLexer.php src/Lexer/TemplateLexer.php
|
||||
parsers: src/Parser/ConfigfileParser.php src/Parser/TemplateParser.php
|
||||
|
||||
docs:
|
||||
mike deploy 5.x
|
||||
|
||||
test-docs:
|
||||
mkdocs serve
|
||||
|
||||
src/Lexer/ConfigfileLexer.php: src/Lexer/ConfigfileLexer.plex
|
||||
php ./utilities/make-lexer.php src/Lexer/ConfigfileLexer.plex src/Lexer/ConfigfileLexer.php
|
||||
|
||||
|
||||
@@ -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.2.
|
||||
Smarty v5 can be run with PHP 7.2 to PHP 8.3.
|
||||
|
||||
## Installation
|
||||
Smarty versions 3.1.11 or later can be installed with [Composer](https://getcomposer.org/).
|
||||
|
||||
+37
-1
@@ -5,7 +5,7 @@ services:
|
||||
context: .
|
||||
dockerfile: ./utilities/testrunners/php72/Dockerfile
|
||||
volumes:
|
||||
- .:/app
|
||||
- smarty-code:/app
|
||||
working_dir: /app
|
||||
php72:
|
||||
extends:
|
||||
@@ -37,3 +37,39 @@ services:
|
||||
service: base
|
||||
build:
|
||||
dockerfile: ./utilities/testrunners/php82/Dockerfile
|
||||
php83:
|
||||
extends:
|
||||
service: base
|
||||
build:
|
||||
dockerfile: ./utilities/testrunners/php83/Dockerfile
|
||||
volumes:
|
||||
smarty-code:
|
||||
|
||||
x-mutagen:
|
||||
sync:
|
||||
defaults:
|
||||
symlink:
|
||||
mode: "posix-raw"
|
||||
ignore:
|
||||
vcs: true
|
||||
paths:
|
||||
- ".docker"
|
||||
- ".env.docker"
|
||||
- ".bundles"
|
||||
- "docker-compose.yml"
|
||||
- ".idea"
|
||||
- ".DS_Store"
|
||||
mode: "two-way-resolved"
|
||||
configurationBeta:
|
||||
permissions:
|
||||
defaultOwner: "id:${APP_USER_ID}"
|
||||
defaultGroup: "id:${APP_GROUP_ID}"
|
||||
defaultFileMode: 0666
|
||||
defaultDirectoryMode: 0755
|
||||
permissions:
|
||||
defaultOwner: "id:${APP_USER_ID}"
|
||||
defaultGroup: "id:${APP_GROUP_ID}"
|
||||
smarty-code:
|
||||
alpha: "."
|
||||
beta: "volume://smarty-code"
|
||||
|
||||
|
||||
+2
-1
@@ -89,4 +89,5 @@ Run this, and you will see:
|
||||
```
|
||||
|
||||
Note how the [escape modifier](../designers/language-modifiers/language-modifier-escape.md)
|
||||
translated the `&` character into the proper HTML syntax `&`.
|
||||
translated the `&` character into the proper HTML syntax `&`.
|
||||
Read more about auto-escaping in the [next section](./configuring.md).
|
||||
@@ -122,6 +122,24 @@ $smarty->setCacheDir('/data/caches');
|
||||
$cacheDir = $smarty->getCacheDir();
|
||||
```
|
||||
|
||||
## Enabling auto-escaping
|
||||
By default, Smarty does not escape anything you render in your templates. If you use
|
||||
Smarty to render a HTML-page, this means that you will have to make sure that you do
|
||||
not render any characters that have a special meaning in HTML, such as `&`, `<` and `>`,
|
||||
or apply the [escape modifier](../designers/language-modifiers/language-modifier-escape.md)
|
||||
to anything you want to render.
|
||||
|
||||
If you forget to do so, you may break your HTML page, or even create a vulnerability for
|
||||
attacks known as [XSS or Cross Site Scripting](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html).
|
||||
|
||||
Luckily, you can tell Smarty to automatically apply the escape modifier to any dynamic part of your template.
|
||||
It's like Smarty magically adds `|escape` to every variable you use on a web page.
|
||||
|
||||
Enable auto-escaping for HTML as follows:
|
||||
```php
|
||||
$smarty->setEscapeHtml(true);
|
||||
```
|
||||
|
||||
## Disabling compile check
|
||||
By default, Smarty tests to see if the
|
||||
current template has changed since the last time
|
||||
|
||||
@@ -88,9 +88,6 @@ Object chaining:
|
||||
|
||||
{$object->method1($x)->method2($y)}
|
||||
|
||||
Direct PHP function access:
|
||||
|
||||
{time()}
|
||||
```
|
||||
|
||||
> **Note**
|
||||
|
||||
@@ -8,12 +8,12 @@ execution of a template**.
|
||||
|----------------|------------|-----------------------------------------------------------------------|
|
||||
| var | | The name of the variable being assigned |
|
||||
| value | | The value being assigned |
|
||||
| scope | (optional) | The scope of the assigned variable: \'parent\',\'root\' or \'global\' |
|
||||
| scope | (optional) | The scope of the assigned variable: 'parent','root' or 'global' |
|
||||
|
||||
## Attributes of the {$var=...} syntax
|
||||
| Attribute Name | Required | Description |
|
||||
|----------------|------------|-----------------------------------------------------------------------|
|
||||
| scope | (optional) | The scope of the assigned variable: \'parent\',\'root\' or \'global\' |
|
||||
| scope | (optional) | The scope of the assigned variable: 'parent','root' or 'global' |
|
||||
|
||||
## Option Flags
|
||||
| Name | Description |
|
||||
@@ -102,6 +102,8 @@ A global variable is seen by all templates.
|
||||
{$foo="bar" scope="global"}
|
||||
```
|
||||
|
||||
For more information on variable scope, please read the page on [variable scopes](../language-variables/language-variable-scopes.md).
|
||||
|
||||
To access `{assign}` variables from a php script use
|
||||
[`getTemplateVars()`](../../programmers/api-functions/api-get-template-vars.md).
|
||||
Here's the template that creates the variable `$foo`.
|
||||
|
||||
@@ -252,7 +252,7 @@ iteration.
|
||||
|
||||
```smarty
|
||||
{foreach $myNames as $name}
|
||||
{if $name@iteration is even by 3}
|
||||
{if $name@index is even by 3}
|
||||
<span style="color: #000">{$name}</span>
|
||||
{else}
|
||||
<span style="color: #eee">{$name}</span>
|
||||
|
||||
@@ -85,11 +85,11 @@ The template above includes the example `links.tpl` below
|
||||
|
||||
```smarty
|
||||
<div id="box">
|
||||
<h3>{$title}{/h3>
|
||||
<h3>{$title}</h3>
|
||||
<ul>
|
||||
{foreach from=$links item=l}
|
||||
.. do stuff ...
|
||||
</foreach}
|
||||
{/foreach}
|
||||
</ul>
|
||||
</div>
|
||||
```
|
||||
|
||||
@@ -326,10 +326,10 @@ The template to output the database result in a HTML table
|
||||
|
||||
```smarty
|
||||
<table>
|
||||
<tr><th> </th><th>Name></th><th>Home</th><th>Cell</th><th>Email</th></tr>
|
||||
<tr><th> </th><th>Name</th><th>Home</th><th>Cell</th><th>Email</th></tr>
|
||||
{section name=co loop=$contacts}
|
||||
<tr>
|
||||
<td><a href="view.php?id={$contacts[co].id}">view<a></td>
|
||||
<td><a href="view.php?id={$contacts[co].id}">view</a></td>
|
||||
<td>{$contacts[co].name}</td>
|
||||
<td>{$contacts[co].home}</td>
|
||||
<td>{$contacts[co].cell}</td>
|
||||
@@ -465,7 +465,7 @@ header block every five rows.
|
||||
<table>
|
||||
{section name=co loop=$contacts}
|
||||
{if $smarty.section.co.iteration is div by 5}
|
||||
<tr><th> </th><th>Name></th><th>Home</th><th>Cell</th><th>Email</th></tr>
|
||||
<tr><th> </th><th>Name</th><th>Home</th><th>Cell</th><th>Email</th></tr>
|
||||
{/if}
|
||||
<tr>
|
||||
<td><a href="view.php?id={$contacts[co].id}">view<a></td>
|
||||
@@ -478,13 +478,13 @@ header block every five rows.
|
||||
</table>
|
||||
```
|
||||
|
||||
An example that uses the `iteration` property to alternate a text color every
|
||||
An example that uses the `index` property to alternate a text color every
|
||||
third row.
|
||||
|
||||
```smarty
|
||||
<table>
|
||||
{section name=co loop=$contacts}
|
||||
{if $smarty.section.co.iteration is even by 3}
|
||||
{if $smarty.section.co.index is even by 3}
|
||||
<span style="color: #ffffff">{$contacts[co].name}</span>
|
||||
{else}
|
||||
<span style="color: #dddddd">{$contacts[co].name}</span>
|
||||
|
||||
@@ -6,34 +6,10 @@ or strings. To apply a modifier,
|
||||
specify the value followed by a `|` (pipe) and the modifier name. A
|
||||
modifier may accept additional parameters that affect its behavior.
|
||||
These parameters follow the modifier name and are separated by a `:`
|
||||
(colon). Also, *all php-functions can be used as modifiers implicitly*
|
||||
(more below) and modifiers can be
|
||||
[combined](../language-combining-modifiers.md).
|
||||
(colon).
|
||||
|
||||
- [capitalize](language-modifier-capitalize.md)
|
||||
- [cat](language-modifier-cat.md)
|
||||
- [count_characters](language-modifier-count-characters.md)
|
||||
- [count_paragraphs](language-modifier-count-paragraphs.md)
|
||||
- [count_sentences](language-modifier-count-sentences.md)
|
||||
- [count_words](language-modifier-count-words.md)
|
||||
- [date_format](language-modifier-date-format.md)
|
||||
- [default](language-modifier-default.md)
|
||||
- [escape](language-modifier-escape.md)
|
||||
- [from_charset](language-modifier-from-charset.md)
|
||||
- [indent](language-modifier-indent.md)
|
||||
- [lower](language-modifier-lower.md)
|
||||
- [nl2br](language-modifier-nl2br.md)
|
||||
- [regex_replace](language-modifier-regex-replace.md)
|
||||
- [replace](language-modifier-replace.md)
|
||||
- [spacify](language-modifier-spacify.md)
|
||||
- [string_format](language-modifier-string-format.md)
|
||||
- [strip](language-modifier-strip.md)
|
||||
- [strip_tags](language-modifier-strip-tags.md)
|
||||
- [to_charset](language-modifier-to-charset.md)
|
||||
- [truncate](language-modifier-truncate.md)
|
||||
- [unescape](language-modifier-unescape.md)
|
||||
- [upper](language-modifier-upper.md)
|
||||
- [wordwrap](language-modifier-wordwrap.md)
|
||||
Modifiers can be applied to any type of variables, including arrays
|
||||
and objects.
|
||||
|
||||
## Examples
|
||||
|
||||
@@ -65,40 +41,63 @@ These parameters follow the modifier name and are separated by a `:`
|
||||
{* php's count *}
|
||||
{$myArray|@count}
|
||||
|
||||
{* this will uppercase and truncate the whole array *}
|
||||
{* this will uppercase the whole array *}
|
||||
<select name="name_id">
|
||||
{html_options output=$my_array|upper|truncate:20}
|
||||
{html_options output=$my_array|upper}
|
||||
</select>
|
||||
```
|
||||
|
||||
- Modifiers can be applied to any type of variables, including arrays
|
||||
and objects.
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> The default behavior was changed with Smarty 3. In Smarty 2.x, you
|
||||
> had to use an "`@`" symbol to apply a modifier to an array, such
|
||||
> as `{$articleTitle|@count}`. With Smarty 3, the "`@`" is no
|
||||
> longer necessary, and is ignored.
|
||||
>
|
||||
> If you want a modifier to apply to each individual item of an
|
||||
> array, you will either need to loop the array in the template, or
|
||||
> provide for this functionality inside your modifier function.
|
||||
## Combining Modifiers
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> Second, in Smarty 2.x, modifiers were applied to the result of
|
||||
> math expressions like `{8+2}`, meaning that
|
||||
> `{8+2|count_characters}` would give `2`, as 8+2=10 and 10 is two
|
||||
> characters long. With Smarty 3, modifiers are applied to the
|
||||
> variables or atomic expressions before executing the calculations,
|
||||
> so since 2 is one character long, `{8+2|count_characters}`
|
||||
> gives 9. To get the old result use parentheses like
|
||||
> `{(8+2)|count_characters}`.
|
||||
You can apply any number of modifiers to a variable. They will be
|
||||
applied in the order they are combined, from left to right. They must be
|
||||
separated with a `|` (pipe) character.
|
||||
|
||||
- Custom modifiers can be registered
|
||||
with the [`registerPlugin()`](../../programmers/api-functions/api-register-plugin.md)
|
||||
function.
|
||||
```php
|
||||
<?php
|
||||
|
||||
$smarty->assign('articleTitle', 'Smokers are Productive, but Death Cuts Efficiency.');
|
||||
```
|
||||
|
||||
where template is:
|
||||
|
||||
```smarty
|
||||
{$articleTitle}
|
||||
{$articleTitle|upper|spacify}
|
||||
{$articleTitle|lower|spacify|truncate}
|
||||
{$articleTitle|lower|truncate:30|spacify}
|
||||
{$articleTitle|lower|spacify|truncate:30:". . ."}
|
||||
```
|
||||
|
||||
|
||||
The above example will output:
|
||||
|
||||
```
|
||||
Smokers are Productive, but Death Cuts Efficiency.
|
||||
S M O K E R S A R ....snip.... H C U T S E F F I C I E N C Y .
|
||||
s m o k e r s a r ....snip.... b u t d e a t h c u t s...
|
||||
s m o k e r s a r e p r o d u c t i v e , b u t . . .
|
||||
s m o k e r s a r e p. . .
|
||||
```
|
||||
|
||||
## Using modifiers in expressions
|
||||
|
||||
Modifiers can also be used in expressions. For example, you can use the [isset modifier](./language-modifier-isset.md)
|
||||
to test if a variable holds a value different from null.
|
||||
|
||||
```smarty
|
||||
{if $varA|isset}
|
||||
<b>variable A is set</b>
|
||||
{/if}
|
||||
```
|
||||
|
||||
You can also use modifiers in expressions in a PHP-style syntax:
|
||||
|
||||
```smarty
|
||||
{if isset($varA)}
|
||||
<b>variable A is set</b>
|
||||
{/if}
|
||||
```
|
||||
|
||||
See also [`registerPlugin()`](../../programmers/api-functions/api-register-plugin.md), [combining
|
||||
modifiers](../language-combining-modifiers.md). and [extending smarty with
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
# count
|
||||
|
||||
Returns the number of elements in an array (or Countable object). Will return 0 for null.
|
||||
Returns 1 for any other type (such as a string).
|
||||
|
||||
If the optional mode parameter is set to 1, count() will recursively count the array.
|
||||
This is particularly useful for counting all the elements of a multidimensional array.
|
||||
|
||||
## Basic usage
|
||||
```smarty
|
||||
{if $myVar|count > 3}4 or more{/if}
|
||||
{if count($myVar) > 3}4 or more{/if}
|
||||
```
|
||||
|
||||
|
||||
## Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|----------|--------------------------------------------------------|
|
||||
| 1 | int | No | If set to 1, count() will recursively count the array. |
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
# debug_print_var
|
||||
|
||||
|
||||
|
||||
Returns the value of the given variable in a human-readable format in HTML.
|
||||
Used in the [debug console](../chapter-debugging-console.md), but you can also use it in your template
|
||||
while developing to see what is going on under the hood.
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> Use for debugging only! Since you may accidentally reveal sensitive information or introduce vulnerabilities such as XSS using this
|
||||
method never use it in production.
|
||||
|
||||
## Basic usage
|
||||
```smarty
|
||||
{$myVar|debug_print_var}
|
||||
```
|
||||
|
||||
|
||||
## Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|----------|------------------------------------------------------------------------|
|
||||
| 1 | int | No | maximum recursion depth if $var is an array or object (defaults to 10) |
|
||||
| 2 | int | No | maximum string length if $var is a string (defaults to 40) |
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
# isset
|
||||
|
||||
Returns true if the variable(s) passed to it are different from null.
|
||||
|
||||
If multiple parameters are supplied then isset() will return true only if all of the parameters are
|
||||
not null.
|
||||
|
||||
## Basic usage
|
||||
```smarty
|
||||
{if $myVar|isset}all set!{/if}
|
||||
```
|
||||
@@ -0,0 +1,26 @@
|
||||
# join
|
||||
|
||||
Returns a string containing all the element of the given array
|
||||
with the separator string between each.
|
||||
|
||||
## Basic usage
|
||||
|
||||
For `$myArray` populated with `['a','b','c']`, the following will return the string `abc`.
|
||||
```smarty
|
||||
{$myArray|join}
|
||||
```
|
||||
|
||||
|
||||
## Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|--------|----------|-------------------------------------------------------------|
|
||||
| 1 | string | No | glue used between array elements. Defaults to empty string. |
|
||||
|
||||
## Examples
|
||||
|
||||
|
||||
For `$myArray` populated with `[1,2,3]`, the following will return the string `1-2-3`.
|
||||
```smarty
|
||||
{$myArray|join:"-"}
|
||||
```
|
||||
@@ -0,0 +1,27 @@
|
||||
# json_encode
|
||||
|
||||
Transforms a value into a valid JSON string.
|
||||
|
||||
## Basic usage
|
||||
```smarty
|
||||
{$user|json_encode}
|
||||
```
|
||||
Depending on the value of `$user` this would return a string in JSON-format, e.g. `{"username":"my_username","email":"my_username@smarty.net"}`.
|
||||
|
||||
|
||||
## Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|----------|-------------------------------------------------------------------------------------------|
|
||||
| 1 | int | No | bitmask of flags, directly passed to [PHP's json_encode](https://www.php.net/json_encode) |
|
||||
|
||||
|
||||
## Examples
|
||||
|
||||
By passing `16` as the second parameter, you can force json_encode to always format the JSON-string as an object.
|
||||
Without it, an array `$myArray = ["a","b"]` would be formatted as a javascript array:
|
||||
|
||||
```smarty
|
||||
{$myArray|json_encode} # renders: ["a","b"]
|
||||
{$myArray|json_encode:16} # renders: {"0":"a","1":"b"}
|
||||
```
|
||||
@@ -0,0 +1,9 @@
|
||||
# noprint
|
||||
|
||||
Always returns an empty string. This can be used to call a function or a method on an object that
|
||||
returns output, and suppress the output.
|
||||
|
||||
## Basic usage
|
||||
```smarty
|
||||
{$controller->sendEmail()|noprint}
|
||||
```
|
||||
@@ -0,0 +1,32 @@
|
||||
# number_format
|
||||
|
||||
Allows you to format a number using decimals and a thousands-separator. By default, the number of decimals is 0
|
||||
and the number is rounded.
|
||||
|
||||
## Basic usage
|
||||
```smarty
|
||||
{$num = 2000.151}
|
||||
{$num|number_format} # renders: 2,000
|
||||
```
|
||||
|
||||
|
||||
## Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|--------|----------|---------------------------------------|
|
||||
| 1 | int | No | number of decimals (defaults to 0) |
|
||||
| 2 | string | No | decimal separator (defaults to ".") |
|
||||
| 3 | string | No | thousands-separator (defaults to ",") |
|
||||
|
||||
|
||||
## Examples
|
||||
|
||||
```smarty
|
||||
{$num = 2000.151}
|
||||
{$num|number_format:2} # renders: 2,000.15
|
||||
```
|
||||
|
||||
```smarty
|
||||
{$num = 2000.151}
|
||||
{$num|number_format:2:".":""} # renders: 2000.15
|
||||
```
|
||||
@@ -0,0 +1,35 @@
|
||||
# round
|
||||
|
||||
Rounds a number to the specified precision.
|
||||
|
||||
## Basic usage
|
||||
```smarty
|
||||
{3.14|round} # renders: 3
|
||||
```
|
||||
|
||||
```smarty
|
||||
{3.141592|round:2} # renders: 3.14
|
||||
```
|
||||
|
||||
## Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|----------|---------------------------|
|
||||
| 1 | int | No | precision (defaults to 0) |
|
||||
| 2 | int | No | mode (defaults to 1) |
|
||||
|
||||
If 'precision' is negative, the number is rounded to the nearest power of 10. See examples below.
|
||||
|
||||
The parameter 'mode' defines how the rounding is done. By default, 2.5 is rounded to 3, whereas 2.45 is rounded to 2.
|
||||
You usually don't need to change this. For more details on rounding modes,
|
||||
see [PHP's documentation on round](https://www.php.net/manual/en/function.round).
|
||||
|
||||
## Examples
|
||||
|
||||
By passing `16` as the second parameter, you can force json_encode to always format the JSON-string as an object.
|
||||
Without it, an array `$myArray = ["a","b"]` would be formatted as a javascript array:
|
||||
|
||||
```smarty
|
||||
{$myArray|json_encode} # renders: ["a","b"]
|
||||
{$myArray|json_encode:16} # renders: {"0":"a","1":"b"}
|
||||
```
|
||||
@@ -0,0 +1,32 @@
|
||||
# split
|
||||
|
||||
Splits a string into an array, using the optional second parameter as the separator.
|
||||
|
||||
## Basic usage
|
||||
|
||||
For `$chars` populated with `'abc'`, the following will produce a html list with 3 elements (a, b and c).
|
||||
```smarty
|
||||
<ol>
|
||||
{foreach $chars|split as $char}
|
||||
<li>{$char|escape}</li>
|
||||
{/foreach}
|
||||
</ol>
|
||||
```
|
||||
|
||||
## Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|--------|----------|------------------------------------------------------------------------------------------------------------------------------|
|
||||
| 1 | string | No | separator used to split the string on. Defaults to empty string, causing each character in the source string to be separate. |
|
||||
|
||||
## Examples
|
||||
|
||||
|
||||
For `$ids` populated with `'1,2,3'`, the following will produce a html list with 3 elements (1, 2 and 3).
|
||||
```smarty
|
||||
<ol>
|
||||
{foreach $ids|split:',' as $id}
|
||||
<li>{$id|escape}</li>
|
||||
{/foreach}
|
||||
</ol>
|
||||
```
|
||||
@@ -0,0 +1,14 @@
|
||||
# str_repeat
|
||||
|
||||
Repeats the given value n times.
|
||||
|
||||
## Basic usage
|
||||
```smarty
|
||||
{"hi"|str_repeat:2} # renders: hihi
|
||||
```
|
||||
|
||||
## Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|----------|-----------------------|
|
||||
| 1 | int | yes | number of repetitions |
|
||||
@@ -0,0 +1,9 @@
|
||||
# strlen
|
||||
|
||||
Returns the length (number of characters) in the given string, including spaces.
|
||||
|
||||
## Basic usage
|
||||
```smarty
|
||||
{"Smarty"|strlen} # renders: 6
|
||||
{156|strlen} # renders: 3
|
||||
```
|
||||
@@ -0,0 +1,25 @@
|
||||
# substr
|
||||
|
||||
Returns a part (substring) of the given string starting at a given offset.
|
||||
|
||||
## Basic usage
|
||||
```smarty
|
||||
{"Smarty"|substr:2} # renders: arty
|
||||
{"Smarty"|substr:2:3} # renders: art
|
||||
```
|
||||
|
||||
## Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|----------|-----------------------------------------------------|
|
||||
| 1 | int | yes | offset (zero based, can be negative) |
|
||||
| 2 | int | no | length of substring returned (unlimited of omitted) |
|
||||
|
||||
|
||||
## Examples
|
||||
|
||||
When used with a negative offset, the substring starts n characters from the end of the string counting backwards.
|
||||
```smarty
|
||||
{"Smarty"|substr:-2} # renders: ty
|
||||
{"Smarty"|substr:-2:1} # renders: t
|
||||
```
|
||||
@@ -29,5 +29,5 @@ If Strike isn't Settled Quickly it may Last a While.
|
||||
IF STRIKE ISN'T SETTLED QUICKLY IT MAY LAST A WHILE.
|
||||
```
|
||||
|
||||
See also [`lower`](lower) and
|
||||
See also [`lower`](./language-modifier-lower.md) and
|
||||
[`capitalize`](language-modifier-capitalize.md).
|
||||
|
||||
+2
-2
@@ -134,8 +134,8 @@ that would be needed otherwise? Does the codebase or framework you plan
|
||||
on using have the features you need for the presentation component?
|
||||
|
||||
## Sites using Smarty
|
||||
Many well-known PHP projects make use of Smarty such as XOOPS CMS, CMS Made Simple, Tiki
|
||||
CMS/Groupware and X-Cart to name a few.
|
||||
Many well-known PHP projects make use of Smarty such as XOOPS CMS, CMS Made Simple,
|
||||
Tiki Wiki CMS Groupware and X-Cart to name a few.
|
||||
|
||||
## Summary
|
||||
Whether you are using Smarty for a small website or massive enterprise
|
||||
|
||||
+20
-4
@@ -1,7 +1,7 @@
|
||||
# Getting started
|
||||
|
||||
## Requirements
|
||||
Smarty can be run with PHP 7.2 to PHP 8.2.
|
||||
Smarty can be run with PHP 7.2 to PHP 8.3.
|
||||
|
||||
## Installation
|
||||
Smarty can be installed with [Composer](https://getcomposer.org/).
|
||||
@@ -16,9 +16,9 @@ To get the latest, unreleased version, use:
|
||||
composer require smarty/smarty:dev-master
|
||||
```
|
||||
|
||||
To get the previous stable version of Smarty, Smarty 3, use:
|
||||
To get the previous stable version of Smarty, Smarty 4, use:
|
||||
```shell
|
||||
composer require smarty/smarty:^3
|
||||
composer require smarty/smarty:^4
|
||||
```
|
||||
|
||||
Here's how you create an instance of Smarty in your PHP scripts:
|
||||
@@ -86,7 +86,7 @@ needs to be located in the [`$template_dir`](./programmers/api-variables/variabl
|
||||
|
||||
```smarty
|
||||
{* Smarty *}
|
||||
Hello {$name}, welcome to Smarty!
|
||||
<h1>Hello {$name|escape}, welcome to Smarty!</h1>
|
||||
```
|
||||
|
||||
> **Note**
|
||||
@@ -132,6 +132,20 @@ Now, run your PHP file. You should see *"Hello Ned, welcome to Smarty!"*
|
||||
|
||||
You have completed the basic setup for Smarty!
|
||||
|
||||
## Escaping
|
||||
You may have noticed that the example template above renders the `$name` variable using
|
||||
the [escape modifier](./designers/language-modifiers/language-modifier-escape.md). This
|
||||
modifier makes string 'safe' to use in the context of an HTML page.
|
||||
|
||||
If you are primarily using Smarty for HTML-pages, it is recommended to enable automatic
|
||||
escaping. This way, you don't have to add `|escape` to every variable you use on a web page.
|
||||
Smarty will handle it automatically for you!
|
||||
|
||||
Enable auto-escaping for HTML as follows:
|
||||
```php
|
||||
$smarty->setEscapeHtml(true);
|
||||
```
|
||||
|
||||
## Extended Setup
|
||||
|
||||
This is a continuation of the [basic installation](#installation), please read that first!
|
||||
@@ -156,6 +170,8 @@ class My_GuestBook extends Smarty {
|
||||
$this->setCompileDir('/web/www.example.com/guestbook/templates_c/');
|
||||
$this->setConfigDir('/web/www.example.com/guestbook/configs/');
|
||||
$this->setCacheDir('/web/www.example.com/guestbook/cache/');
|
||||
|
||||
$this->setEscapeHtml(true);
|
||||
|
||||
$this->caching = Smarty::CACHING_LIFETIME_CURRENT;
|
||||
$this->assign('app_name', 'Guest Book');
|
||||
|
||||
@@ -26,5 +26,10 @@ and 480 for $height, the result is:
|
||||
- [Features](./features.md) - or "Why do I want Smarty?"
|
||||
|
||||
## Help
|
||||
- [Search or create an issue](https://github.com/smarty-php/smarty/issues)
|
||||
- [Upgrading from an older version](upgrading.md)
|
||||
- [Some random tips & tricks](./appendixes/tips.md)
|
||||
- [Troubleshooting](./appendixes/troubleshooting.md)
|
||||
|
||||
## Source code
|
||||
- [Smarty repository at GitHub](https://github.com/smarty-php/smarty)
|
||||
@@ -0,0 +1,157 @@
|
||||
# Upgrading from an older version
|
||||
|
||||
## Upgrading from v4 to v5
|
||||
|
||||
Smarty 5 adds support for PHP8.2 and drops support for PHP7.1. Smarty also adds support for new features
|
||||
such as the ternary operator (`{$test ? $a : $b}` and `{$var ?: $value_if_falsy}`), the null coalescing operator (`{$var ?? $value_if_null}`)
|
||||
and positional parameters for custom tags.
|
||||
Smarty 5 also has a brand-new extension architecture that allows you to write neat extension packs.
|
||||
|
||||
### Namespaces
|
||||
All Smarty code has been moved into the `\Smarty` namespace. This reduces
|
||||
the chance of conflicts with other (your) code.
|
||||
|
||||
For simple use-cases, you only need to add `use Smarty\Smarty;` to your script and everything will work.
|
||||
|
||||
```php
|
||||
<?php
|
||||
use Smarty\Smarty;
|
||||
$smarty = new Smarty();
|
||||
|
||||
$smarty->display('homepage.tpl');
|
||||
```
|
||||
For more information, see [getting started](getting-started.md).
|
||||
|
||||
If you extend Smarty or use Smarty plug-ins, please review your code to see if they assume specific class or method names.
|
||||
E.g.: `Smarty_Internal_Template` is now `\Smarty\Template\`, `SmartyException` is now `\Smarty\Exception`.
|
||||
|
||||
### Variable scope bubbling
|
||||
Template variable scope bubbling has been simplified and made more consistent. The global scope now equals the Smarty
|
||||
scope in order to avoid global state side effects. Please read the [documentation on language variable scope](designers/language-variables/language-variable-scopes.md)
|
||||
for more details.
|
||||
|
||||
Also, `{config_load}` no longer has a `scope` parameter, which means you can no longer load config
|
||||
from inside your template into the global scope (again, to avoid global state side effects). If you
|
||||
need to set global config, use the [configLoad API method](api/variables/config-files.md) from your PHP code.
|
||||
|
||||
### Using native PHP-functions or userland functions in your templates
|
||||
You can no longer use native PHP-functions or userland functions in your templates without registering them.
|
||||
If you need a function in your templates, register it first.
|
||||
|
||||
The easiest way to do so is as follows:
|
||||
```php
|
||||
// native PHP functions used as modifiers need to be registered
|
||||
$smarty->registerPlugin('modifier', 'substr', 'substr');
|
||||
|
||||
// userland PHP functions used as modifiers need to be registered
|
||||
$smarty->registerPlugin('modifier', 'my_special_func', 'my_special_func');
|
||||
```
|
||||
|
||||
But you may want to consider writing a proper [extension](api/extending/extensions.md).
|
||||
|
||||
### Removed undocumented tags
|
||||
|
||||
Smarty 4 still supported some tags that have been carried over from previous version, but have never been documented.
|
||||
|
||||
- `{block_parent}` should be replaced with `{$smarty.block.parent}`
|
||||
- `{parent}` should be replaced with `{$smarty.block.parent}`
|
||||
- `{block_child}` should be replaced with `{$smarty.block.child}`
|
||||
- `{child}` should be replaced with `{$smarty.block.child}`
|
||||
|
||||
- `{make_nocache}` is no longer supported
|
||||
- `{insert}` is no longer supported
|
||||
|
||||
### Removed Smarty API properties
|
||||
|
||||
In Smarty 4, you could make many configuration changes by directly accessing public properties on the Smarty object in PHP.
|
||||
In many cases, these properties have been made private, and you should now use the appropriate setter method:
|
||||
|
||||
- `$smarty->left_delimiter` should be replaced with `$smarty->getLeftDelimiter()`/`$smarty->setLeftDelimiter()`
|
||||
- `$smarty->right_delimiter` should be replaced with `$smarty->getRightDelimiter()`/`$smarty->setRightDelimiter()`
|
||||
- `$smarty->autoload_filters` should be replaced with `$smarty->registerFilter()`
|
||||
- `$smarty->template_dir` should be replaced with `$smarty->setTemplateDir()`
|
||||
- `$smarty->cache_dir` should be replaced with `$smarty->setCacheDir()`
|
||||
- `$smarty->compile_dir` should be replaced with `$smarty->setCompileDir()`
|
||||
|
||||
Other public properties have been removed altogether, and you should no longer access them:
|
||||
|
||||
- `$smarty->_current_file`
|
||||
- `$smarty->allow_ambiguous_resources` (ambiguous resources handlers should still work)
|
||||
- `$smarty->registered_filters`
|
||||
- `$smarty->direct_access_security`
|
||||
- `$smarty->trusted_dir`
|
||||
- `$smarty->allow_php_templates`
|
||||
- `$smarty->php_functions`
|
||||
- `$smarty->php_modifiers`
|
||||
|
||||
### Backwards incompatible changes to custom plugins
|
||||
|
||||
We have dropped support for `$smarty->plugins_dir` and `$smarty->use_include_path`.
|
||||
Use `$smarty->addPluginsDir()` or consider writing a proper [extension](api/extending/extensions.md).
|
||||
|
||||
The 'insert' plugin type is no longer supported.
|
||||
|
||||
The `$cache_attrs` parameter for registered plugins is no longer supported.
|
||||
|
||||
### Removed Smarty API methods
|
||||
|
||||
Search your code for the following changes:
|
||||
|
||||
- `$smarty->getTags()` is no longer supported
|
||||
- `$smarty->appendByRef()` should be replaced with `$smarty->append()`
|
||||
- `$smarty->assignByRef()` should be replaced with `$smarty->assign()`
|
||||
- `$smarty->loadPlugin()` should be replaced with `$smarty->registerPlugin()`
|
||||
|
||||
### Removed PHP constants
|
||||
|
||||
The following constants have been removed to prevent global side effects.
|
||||
|
||||
- `SMARTY_DIR`
|
||||
- `SMARTY_SYSPLUGINS_DIR`
|
||||
- `SMARTY_PLUGINS_DIR`
|
||||
- `SMARTY_MBSTRING`
|
||||
- `SMARTY_HELPER_FUNCTIONS_LOADED`
|
||||
|
||||
### Other changes
|
||||
|
||||
- Smarty now always runs in multibyte mode. Make sure you use the [PHP multibyte extension](https://www.php.net/manual/en/book.mbstring.php) in production for optimal performance.
|
||||
- Generated `<script>` tags lo longer have deprecated `type="text/javascript"` or `language="Javascript"` attributes
|
||||
- Smarty will throw a compiler exception instead of silently ignoring a modifier on a function call, like this: `{include|dot:"x-template-id" file="included.dot.tpl"}`
|
||||
- The ::getFile() method of a CompilerException will now return the full path of the template being compiled, if possible. This used to be 'file:relative_dir/filename.tpl'.
|
||||
|
||||
## Upgrading from v3 to v4
|
||||
|
||||
Smarty 4 is mostly identical to Smarty 3. Most notably, it adds support for PHP8 and drops support for PHP7.0 and below.
|
||||
Additionally, some deprecated features that have long been discouraged have been dropped from the language.
|
||||
|
||||
### Muting PHP8 warnings
|
||||
If you simultaneously upgrade Smarty to v4 van PHP to v8, you may notice your error logs filling up with warnings about undefined or null template vars
|
||||
due to a change in how PHP handles these. This may be helpful to spot errors, but if you find this annoying, you can use
|
||||
`$smarty->muteUndefinedOrNullWarnings()` to make Smarty convert these warnings into notices.
|
||||
|
||||
### ASP tags
|
||||
You can no longer user ASP-style tags like `<% %>` and `<%= %>` in your templates.
|
||||
Replace them with `{...}` tags.
|
||||
|
||||
### SmartyBC
|
||||
Check your codebase for `SmartyBC`.
|
||||
We have dropped deprecated API calls that where only accessible through the SmartyBC class.
|
||||
|
||||
### No more embedded PHP
|
||||
We have completely dropped support for `{php}` and `{include_php}` tags and embedded PHP in templates.
|
||||
Check your templates for this, and rewrite any embedded PHP blocks, by moving logic to your PHP files or by
|
||||
creating a [custom tag](./api/extending/tags.md).
|
||||
|
||||
### Other changes
|
||||
|
||||
Search your code for the following changes:
|
||||
|
||||
- `SMARTY_RESOURCE_CHAR_SET` and `SMARTY_RESOURCE_DATE_FORMAT` constants have been removed
|
||||
- `Smarty::muteExpectedErrors` and `Smarty::unmuteExpectedErrors` API methods have been removed
|
||||
- `Smarty::getVariable` method has been removed. Use [Smarty::getTemplateVars](designers/language-builtin-functions/language-function-assign.md) instead.
|
||||
- [Smarty::registerResource](api/resources.md) no longer accepts an array of callback functions
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+5
-4
@@ -8,13 +8,14 @@ else
|
||||
fi
|
||||
|
||||
git checkout -b "release/$1"
|
||||
sed -i "s/## \\[Unreleased\\]/## \\[Unreleased\\]\\n\\n## \\[$1\\] - $(date +%Y-%m-%d)/" CHANGELOG.md
|
||||
sed -i "s/const SMARTY_VERSION = '[^']\+';/const SMARTY_VERSION = '$1';/" src/Smarty.php
|
||||
|
||||
git add CHANGELOG.md src/Smarty.php
|
||||
php utilities/update-changelog.php $1
|
||||
php utilities/update-smarty-version-number.php $1
|
||||
|
||||
git add changelog CHANGELOG.md src/Smarty.php
|
||||
git commit -m "version bump"
|
||||
|
||||
git checkout master
|
||||
git checkout support/5
|
||||
git pull
|
||||
git merge --no-ff "release/$1"
|
||||
git branch -d "release/$1"
|
||||
|
||||
+15
-2
@@ -26,7 +26,9 @@ markdown_extensions:
|
||||
|
||||
nav:
|
||||
- Home: 'index.md'
|
||||
- 'Getting started': 'getting-started.md'
|
||||
- 'Getting started':
|
||||
- Introduction: 'getting-started.md'
|
||||
- 'Upgrading from an older version': 'upgrading.md'
|
||||
- 'Language reference':
|
||||
- 'Basic Syntax':
|
||||
- Introduction: 'designers/language-basic-syntax/index.md'
|
||||
@@ -47,29 +49,40 @@ nav:
|
||||
- 'Introduction': 'designers/language-modifiers/index.md'
|
||||
- 'capitalize': 'designers/language-modifiers/language-modifier-capitalize.md'
|
||||
- 'cat': 'designers/language-modifiers/language-modifier-cat.md'
|
||||
- 'count': 'designers/language-modifiers/language-modifier-count.md'
|
||||
- 'count_characters': 'designers/language-modifiers/language-modifier-count-characters.md'
|
||||
- 'count_paragraphs': 'designers/language-modifiers/language-modifier-count-paragraphs.md'
|
||||
- 'count_sentences': 'designers/language-modifiers/language-modifier-count-sentences.md'
|
||||
- 'count_words': 'designers/language-modifiers/language-modifier-count-words.md'
|
||||
- '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'
|
||||
- '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'
|
||||
- 'isset': 'designers/language-modifiers/language-modifier-isset.md'
|
||||
- 'join': 'designers/language-modifiers/language-modifier-join.md'
|
||||
- 'json_encode': 'designers/language-modifiers/language-modifier-json-encode.md'
|
||||
- 'lower': 'designers/language-modifiers/language-modifier-lower.md'
|
||||
- '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'
|
||||
- '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'
|
||||
- 'spacify': 'designers/language-modifiers/language-modifier-spacify.md'
|
||||
- 'split': 'designers/language-modifiers/language-modifier-split.md'
|
||||
- 'str_repeat': 'designers/language-modifiers/language-modifier-str-repeat.md'
|
||||
- 'string_format': 'designers/language-modifiers/language-modifier-string-format.md'
|
||||
- 'strip': 'designers/language-modifiers/language-modifier-strip.md'
|
||||
- 'strip_tags': 'designers/language-modifiers/language-modifier-strip-tags.md'
|
||||
- 'strlen': 'designers/language-modifiers/language-modifier-strlen.md'
|
||||
- 'substr': 'designers/language-modifiers/language-modifier-substr.md'
|
||||
- 'to_charset': 'designers/language-modifiers/language-modifier-to-charset.md'
|
||||
- 'truncate': 'designers/language-modifiers/language-modifier-truncate.md'
|
||||
- 'unescape': 'designers/language-modifiers/language-modifier-unescape.md'
|
||||
- 'upper': 'designers/language-modifiers/language-modifier-upper.md'
|
||||
- 'wordwrap': 'designers/language-modifiers/language-modifier-wordwrap.md'
|
||||
- 'Combining Modifiers': 'designers/language-combining-modifiers.md'
|
||||
- 'Builtin Tags':
|
||||
- 'Introduction': 'designers/language-builtin-functions/index.md'
|
||||
- '{append}': 'designers/language-builtin-functions/language-function-append.md'
|
||||
|
||||
@@ -5,9 +5,12 @@
|
||||
# - ./run-tests-for-all-php-versions.sh --group 20221124
|
||||
# - ./run-tests-for-all-php-versions.sh --exclude-group slow
|
||||
|
||||
docker-compose run php72 ./run-tests.sh $@ && \
|
||||
docker-compose run php73 ./run-tests.sh $@ && \
|
||||
docker-compose run php74 ./run-tests.sh $@ && \
|
||||
docker-compose run php80 ./run-tests.sh $@ && \
|
||||
docker-compose run php81 ./run-tests.sh $@ && \
|
||||
docker-compose run php82 ./run-tests.sh $@
|
||||
COMPOSE_CMD="mutagen-compose"
|
||||
|
||||
$COMPOSE_CMD run --rm php72 ./run-tests.sh $@ && \
|
||||
$COMPOSE_CMD run --rm php73 ./run-tests.sh $@ && \
|
||||
$COMPOSE_CMD run --rm php74 ./run-tests.sh $@ && \
|
||||
$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 $@
|
||||
|
||||
@@ -34,7 +34,7 @@ class FunctionCallCompiler extends Base {
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $shorttag_order = ['var1', 'var2', 'var3'];
|
||||
protected $shorttag_order = [];
|
||||
|
||||
/**
|
||||
* Compiles code for the execution of a registered function
|
||||
@@ -58,19 +58,15 @@ class FunctionCallCompiler extends Base {
|
||||
$_paramsArray = $this->formatParamsArray($_attr);
|
||||
$_params = 'array(' . implode(',', $_paramsArray) . ')';
|
||||
|
||||
try {
|
||||
$value = array_shift($_attr);
|
||||
$output = $compiler->compileModifier([array_merge([$function], $_attr)], $value);
|
||||
} catch (\Smarty\CompilerException $e) {
|
||||
if ($functionHandler = $compiler->getSmarty()->getFunctionHandler($function)) {
|
||||
|
||||
// not cacheable?
|
||||
$compiler->tag_nocache = $compiler->tag_nocache || !$functionHandler->isCacheable();
|
||||
$output = "\$_smarty_tpl->getSmarty()->getFunctionHandler(" . var_export($function, true) . ")";
|
||||
$output .= "->handle($_params, \$_smarty_tpl)";
|
||||
} else {
|
||||
throw $e;
|
||||
}
|
||||
if ($functionHandler = $compiler->getSmarty()->getFunctionHandler($function)) {
|
||||
|
||||
// not cacheable?
|
||||
$compiler->tag_nocache = $compiler->tag_nocache || !$functionHandler->isCacheable();
|
||||
$output = "\$_smarty_tpl->getSmarty()->getFunctionHandler(" . var_export($function, true) . ")";
|
||||
$output .= "->handle($_params, \$_smarty_tpl)";
|
||||
} else {
|
||||
$compiler->trigger_template_error("unknown function '{$function}'", null, true);
|
||||
}
|
||||
|
||||
if (!empty($parameter['modifierlist'])) {
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
namespace Smarty\Compile\Modifier;
|
||||
use Smarty\CompilerException;
|
||||
|
||||
/**
|
||||
* Smarty is_array modifier plugin
|
||||
*/
|
||||
class IsArrayModifierCompiler extends Base {
|
||||
|
||||
public function compile($params, \Smarty\Compiler\Template $compiler) {
|
||||
|
||||
if (count($params) !== 1) {
|
||||
throw new CompilerException("Invalid number of arguments for is_array. is_array expects exactly 1 parameter.");
|
||||
}
|
||||
|
||||
return 'is_array(' . $params[0] . ')';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace Smarty\Compile\Modifier;
|
||||
|
||||
/**
|
||||
* Smarty json_encode modifier plugin
|
||||
*/
|
||||
class JsonEncodeModifierCompiler extends Base {
|
||||
|
||||
public function compile($params, \Smarty\Compiler\Template $compiler) {
|
||||
return 'json_encode(' . $params[0] . (isset($params[1]) ? ', (int) ' . $params[1] : '') . ')';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Smarty\Compile\Modifier;
|
||||
|
||||
/**
|
||||
* Smarty substr modifier plugin
|
||||
*/
|
||||
class SubstrModifierCompiler extends Base {
|
||||
|
||||
public function compile($params, \Smarty\Compiler\Template $compiler) {
|
||||
return 'substr((string) ' . $params[0] . ', (int) ' . $params[1] .
|
||||
(isset($params[2]) ? ', (int) ' . $params[2] : '') . ')';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -43,16 +43,19 @@ class ModifierCompiler extends Base {
|
||||
foreach ($parameter['modifierlist'] as $single_modifier) {
|
||||
/* @var string $modifier */
|
||||
$modifier = $single_modifier[0];
|
||||
$single_modifier[0] = $output;
|
||||
$params = implode(',', $single_modifier);
|
||||
|
||||
|
||||
$modifier_params = array_values($single_modifier);
|
||||
|
||||
$modifier_params[0] = $output;
|
||||
$params = implode(',', $modifier_params);
|
||||
|
||||
if (!is_object($compiler->getSmarty()->security_policy)
|
||||
|| $compiler->getSmarty()->security_policy->isTrustedModifier($modifier, $compiler)
|
||||
) {
|
||||
|
||||
if ($handler = $compiler->getModifierCompiler($modifier)) {
|
||||
$output = $handler->compile($single_modifier, $compiler);
|
||||
|
||||
$output = $handler->compile($modifier_params, $compiler);
|
||||
} elseif ($compiler->getSmarty()->getModifierCallback($modifier)) {
|
||||
$output = sprintf(
|
||||
'$_smarty_tpl->getSmarty()->getModifierCallback(%s)(%s)',
|
||||
@@ -60,7 +63,7 @@ class ModifierCompiler extends Base {
|
||||
$params
|
||||
);
|
||||
} elseif ($callback = $compiler->getPluginFromDefaultHandler($modifier, \Smarty\Smarty::PLUGIN_MODIFIERCOMPILER)) {
|
||||
$output = (new \Smarty\Compile\Modifier\BCPluginWrapper($callback))->compile($single_modifier, $compiler);
|
||||
$output = (new \Smarty\Compile\Modifier\BCPluginWrapper($callback))->compile($modifier_params, $compiler);
|
||||
} elseif ($function = $compiler->getPluginFromDefaultHandler($modifier, \Smarty\Smarty::PLUGIN_MODIFIER)) {
|
||||
if (!is_array($function)) {
|
||||
$output = "{$function}({$params})";
|
||||
|
||||
@@ -84,7 +84,7 @@ class PrintExpressionCompiler extends Base {
|
||||
}
|
||||
|
||||
if ($compiler->getTemplate()->getSmarty()->escape_html) {
|
||||
$output = "htmlspecialchars((string) {$output}, ENT_QUOTES, '" . addslashes(\Smarty\Smarty::$_CHARSET) . "')";
|
||||
$output = "htmlspecialchars((string) ({$output}), ENT_QUOTES, '" . addslashes(\Smarty\Smarty::$_CHARSET) . "')";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ class FunctionClose extends Base {
|
||||
$output .= "foreach (\$params as \$key => \$value) {\n\$_smarty_tpl->assign(\$key, \$value);\n}\n";
|
||||
$output .= "\$params = var_export(\$params, true);\n";
|
||||
$output .= "echo \"/*%%SmartyNocache:{$compiler->getTemplate()->getCompiled()->nocache_hash}%%*/<?php ";
|
||||
$output .= "\\\$_smarty_tpl->getSmarty()->getRuntime('TplFunction')->saveTemplateVariables(\\\$_smarty_tpl, '{$_name}');\nforeach (\$params as \\\$key => \\\$value) {\n\\\$_smarty_tpl->assign(\\\$key, \\\$value);\n}\n?>";
|
||||
$output .= "\\\$_smarty_tpl->pushStack();\nforeach (\$params as \\\$key => \\\$value) {\n\\\$_smarty_tpl->assign(\\\$key, \\\$value);\n}\n?>";
|
||||
$output .= "/*/%%SmartyNocache:{$compiler->getTemplate()->getCompiled()->nocache_hash}%%*/\";?>";
|
||||
$compiler->getParser()->current_buffer->append_subtree(
|
||||
$compiler->getParser(),
|
||||
@@ -86,7 +86,7 @@ class FunctionClose extends Base {
|
||||
);
|
||||
$compiler->getParser()->current_buffer->append_subtree($compiler->getParser(), $_functionCode);
|
||||
$output = "<?php echo \"/*%%SmartyNocache:{$compiler->getTemplate()->getCompiled()->nocache_hash}%%*/<?php ";
|
||||
$output .= "\\\$_smarty_tpl->getSmarty()->getRuntime('TplFunction')->restoreTemplateVariables(\\\$_smarty_tpl, '{$_name}');?>\n";
|
||||
$output .= "\\\$_smarty_tpl->popStack();?>\n";
|
||||
$output .= "/*/%%SmartyNocache:{$compiler->getTemplate()->getCompiled()->nocache_hash}%%*/\";\n?>";
|
||||
$output .= "<?php echo str_replace('{$compiler->getTemplate()->getCompiled()->nocache_hash}', \$_smarty_tpl->getCompiled()->nocache_hash ?? '', ob_get_clean());\n";
|
||||
$output .= "}\n}\n";
|
||||
|
||||
@@ -121,6 +121,6 @@ class CodeFrame
|
||||
* @return string
|
||||
*/
|
||||
public function insertLocalVariables(): string {
|
||||
return '$_smarty_current_dir = ' . var_export(dirname($this->_template->getSource()->getFilepath()), true) . ";\n";
|
||||
return '$_smarty_current_dir = ' . var_export(dirname($this->_template->getSource()->getFilepath() ?? '.'), true) . ";\n";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,8 +65,6 @@ class Configfile extends BaseCompiler {
|
||||
* @param Smarty $smarty global instance
|
||||
*/
|
||||
public function __construct(Smarty $smarty) {
|
||||
$this->smarty = $smarty;
|
||||
// get required plugins
|
||||
$this->smarty = $smarty;
|
||||
$this->config_data['sections'] = [];
|
||||
$this->config_data['vars'] = [];
|
||||
@@ -104,7 +102,7 @@ class Configfile extends BaseCompiler {
|
||||
) . "\n",
|
||||
$this
|
||||
);
|
||||
/* @var ConfigfileParser $this->parser */
|
||||
|
||||
$this->parser = new ConfigfileParser($this->lex, $this);
|
||||
if ($this->smarty->_parserdebug) {
|
||||
$this->parser->PrintTrace();
|
||||
|
||||
@@ -464,7 +464,7 @@ class Template extends BaseCompiler {
|
||||
public function compileTag($tag, $args, $parameter = []) {
|
||||
$this->prefixCodeStack[] = $this->prefix_code;
|
||||
$this->prefix_code = [];
|
||||
$result = $this->compileTag2(strtolower($tag), $args, $parameter);
|
||||
$result = $this->compileTag2($tag, $args, $parameter);
|
||||
$this->prefix_code = array_merge($this->prefix_code, array_pop($this->prefixCodeStack));
|
||||
return $result;
|
||||
}
|
||||
@@ -591,6 +591,7 @@ class Template extends BaseCompiler {
|
||||
* @return ?\Smarty\Compile\CompilerInterface tag compiler object or null if not found or untrusted by security policy
|
||||
*/
|
||||
public function getTagCompiler($tag): ?\Smarty\Compile\CompilerInterface {
|
||||
$tag = strtolower($tag);
|
||||
|
||||
if (isset($this->smarty->security_policy) && !$this->smarty->security_policy->isTrustedTag($tag, $this)) {
|
||||
return null;
|
||||
@@ -847,7 +848,7 @@ class Template extends BaseCompiler {
|
||||
$e = new CompilerException(
|
||||
$error_text,
|
||||
0,
|
||||
$this->template->getSource()->getFullResourceName(),
|
||||
$this->template->getSource()->getFilepath() ?? $this->template->getSource()->getFullResourceName(),
|
||||
$line
|
||||
);
|
||||
$e->source = trim(preg_replace('![\t\r\n]+!', ' ', $match[$line - 1]));
|
||||
@@ -1114,7 +1115,7 @@ class Template extends BaseCompiler {
|
||||
}
|
||||
}
|
||||
|
||||
// call to function previousely defined by {function} tag
|
||||
// call to function previously defined by {function} tag
|
||||
if ($this->canCompileTemplateFunctionCall($tag)) {
|
||||
|
||||
if (!empty($parameter['modifierlist'])) {
|
||||
@@ -1140,7 +1141,7 @@ class Template extends BaseCompiler {
|
||||
if ($this->smarty->getFunctionHandler($base_tag)) {
|
||||
if (!isset($this->smarty->security_policy) || $this->smarty->security_policy->isTrustedTag($base_tag, $this)) {
|
||||
return (new \Smarty\Compile\PrintExpressionCompiler())->compile(
|
||||
[],
|
||||
['nofilter'], // functions are never auto-escaped
|
||||
$this,
|
||||
['value' => $this->compileFunctionCall($base_tag, $args, $parameter)]
|
||||
);
|
||||
@@ -1368,6 +1369,11 @@ class Template extends BaseCompiler {
|
||||
return $this->functionCallCompiler->compile($args, $this, $parameter, $base_tag, $base_tag);
|
||||
}
|
||||
|
||||
public function compileModifierInExpression(string $function, array $_attr) {
|
||||
$value = array_shift($_attr);
|
||||
return $this->compileModifier([array_merge([$function], $_attr)], $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return TemplateParser|null
|
||||
*/
|
||||
|
||||
@@ -47,6 +47,20 @@ class Data
|
||||
*/
|
||||
public $config_vars = array();
|
||||
|
||||
/**
|
||||
* This variable will hold a stack of template variables.
|
||||
*
|
||||
* @var null|array
|
||||
*/
|
||||
private $_var_stack = [];
|
||||
|
||||
/**
|
||||
* This variable will hold a stack of config variables.
|
||||
*
|
||||
* @var null|array
|
||||
*/
|
||||
private $_config_stack = [];
|
||||
|
||||
/**
|
||||
* Default scope for new variables
|
||||
* @var int
|
||||
@@ -493,4 +507,20 @@ class Data
|
||||
public function setParent($parent): void {
|
||||
$this->parent = $parent;
|
||||
}
|
||||
|
||||
public function pushStack(): void {
|
||||
$stackList = [];
|
||||
foreach ($this->tpl_vars as $name => $variable) {
|
||||
$stackList[$name] = clone $variable; // variables are stored in Variable objects
|
||||
}
|
||||
$this->_var_stack[] = $this->tpl_vars;
|
||||
$this->tpl_vars = $stackList;
|
||||
|
||||
$this->_config_stack[] = $this->config_vars;
|
||||
}
|
||||
|
||||
public function popStack(): void {
|
||||
$this->tpl_vars = array_pop($this->_var_stack);
|
||||
$this->config_vars = array_pop($this->_config_stack);
|
||||
}
|
||||
}
|
||||
|
||||
+37
-46
@@ -6,16 +6,7 @@ namespace Smarty;
|
||||
* Smarty Internal Plugin Debug
|
||||
* Class to collect data for the Smarty Debugging Console
|
||||
*
|
||||
|
||||
|
||||
* @author Uwe Tews
|
||||
*/
|
||||
|
||||
/**
|
||||
* Smarty Internal Plugin Debug Class
|
||||
*
|
||||
|
||||
|
||||
*/
|
||||
class Debug extends Data
|
||||
{
|
||||
@@ -24,14 +15,14 @@ class Debug extends Data
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $template_data = array();
|
||||
public $template_data = [];
|
||||
|
||||
/**
|
||||
* List of uid's which shall be ignored
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $ignore_uid = array();
|
||||
public $ignore_uid = [];
|
||||
|
||||
/**
|
||||
* Index of display() and fetch() calls
|
||||
@@ -50,10 +41,10 @@ class Debug extends Data
|
||||
/**
|
||||
* Start logging template
|
||||
*
|
||||
* @param \Smarty\Template $template template
|
||||
* @param Template $template template
|
||||
* @param null $mode true: display false: fetch null: subtemplate
|
||||
*/
|
||||
public function start_template(\Smarty\Template $template, $mode = null)
|
||||
public function start_template(Template $template, $mode = null)
|
||||
{
|
||||
if (isset($mode) && !$template->_isSubTpl()) {
|
||||
$this->index++;
|
||||
@@ -67,9 +58,9 @@ class Debug extends Data
|
||||
/**
|
||||
* End logging of cache time
|
||||
*
|
||||
* @param \Smarty\Template $template cached template
|
||||
* @param Template $template cached template
|
||||
*/
|
||||
public function end_template(\Smarty\Template $template)
|
||||
public function end_template(Template $template)
|
||||
{
|
||||
$key = $this->get_key($template);
|
||||
$this->template_data[ $this->index ][ $key ][ 'total_time' ] +=
|
||||
@@ -79,15 +70,15 @@ class Debug extends Data
|
||||
/**
|
||||
* Start logging of compile time
|
||||
*
|
||||
* @param \Smarty\Template $template
|
||||
* @param Template $template
|
||||
*/
|
||||
public function start_compile(\Smarty\Template $template)
|
||||
public function start_compile(Template $template)
|
||||
{
|
||||
static $_is_stringy = array('string' => true, 'eval' => true);
|
||||
if (!empty($template->getCompiler()->trace_uid)) {
|
||||
$key = $template->getCompiler()->trace_uid;
|
||||
if (!isset($this->template_data[ $this->index ][ $key ])) {
|
||||
$this->saveTemplateData($_is_stringy, $template, $key);
|
||||
$this->saveTemplateData($_is_stringy, $template, $key);
|
||||
}
|
||||
} else {
|
||||
if (isset($this->ignore_uid[ $template->getSource()->uid ])) {
|
||||
@@ -101,9 +92,9 @@ class Debug extends Data
|
||||
/**
|
||||
* End logging of compile time
|
||||
*
|
||||
* @param \Smarty\Template $template
|
||||
* @param Template $template
|
||||
*/
|
||||
public function end_compile(\Smarty\Template $template)
|
||||
public function end_compile(Template $template)
|
||||
{
|
||||
if (!empty($template->getCompiler()->trace_uid)) {
|
||||
$key = $template->getCompiler()->trace_uid;
|
||||
@@ -120,9 +111,9 @@ class Debug extends Data
|
||||
/**
|
||||
* Start logging of render time
|
||||
*
|
||||
* @param \Smarty\Template $template
|
||||
* @param Template $template
|
||||
*/
|
||||
public function start_render(\Smarty\Template $template)
|
||||
public function start_render(Template $template)
|
||||
{
|
||||
$key = $this->get_key($template);
|
||||
$this->template_data[ $this->index ][ $key ][ 'start_time' ] = microtime(true);
|
||||
@@ -131,9 +122,9 @@ class Debug extends Data
|
||||
/**
|
||||
* End logging of compile time
|
||||
*
|
||||
* @param \Smarty\Template $template
|
||||
* @param Template $template
|
||||
*/
|
||||
public function end_render(\Smarty\Template $template)
|
||||
public function end_render(Template $template)
|
||||
{
|
||||
$key = $this->get_key($template);
|
||||
$this->template_data[ $this->index ][ $key ][ 'render_time' ] +=
|
||||
@@ -143,9 +134,9 @@ class Debug extends Data
|
||||
/**
|
||||
* Start logging of cache time
|
||||
*
|
||||
* @param \Smarty\Template $template cached template
|
||||
* @param Template $template cached template
|
||||
*/
|
||||
public function start_cache(\Smarty\Template $template)
|
||||
public function start_cache(Template $template)
|
||||
{
|
||||
$key = $this->get_key($template);
|
||||
$this->template_data[ $this->index ][ $key ][ 'start_time' ] = microtime(true);
|
||||
@@ -154,9 +145,9 @@ class Debug extends Data
|
||||
/**
|
||||
* End logging of cache time
|
||||
*
|
||||
* @param \Smarty\Template $template cached template
|
||||
* @param Template $template cached template
|
||||
*/
|
||||
public function end_cache(\Smarty\Template $template)
|
||||
public function end_cache(Template $template)
|
||||
{
|
||||
$key = $this->get_key($template);
|
||||
$this->template_data[ $this->index ][ $key ][ 'cache_time' ] +=
|
||||
@@ -166,9 +157,9 @@ class Debug extends Data
|
||||
/**
|
||||
* Register template object
|
||||
*
|
||||
* @param \Smarty\Template $template cached template
|
||||
* @param Template $template cached template
|
||||
*/
|
||||
public function register_template(\Smarty\Template $template)
|
||||
public function register_template(Template $template)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -184,13 +175,13 @@ class Debug extends Data
|
||||
/**
|
||||
* Opens a window for the Smarty Debugging Console and display the data
|
||||
*
|
||||
* @param \Smarty\Template|\Smarty $obj object to debug
|
||||
* @param Template|Smarty $obj object to debug
|
||||
* @param bool $full
|
||||
*
|
||||
* @throws \Exception
|
||||
* @throws \Smarty\Exception
|
||||
* @throws Exception
|
||||
*/
|
||||
public function display_debug($obj, $full = false)
|
||||
public function display_debug($obj, bool $full = false)
|
||||
{
|
||||
if (!$full) {
|
||||
$this->offset++;
|
||||
@@ -200,18 +191,18 @@ class Debug extends Data
|
||||
$smarty = $obj->getSmarty();
|
||||
// create fresh instance of smarty for displaying the debug console
|
||||
// to avoid problems if the application did overload the Smarty class
|
||||
$debObj = new \Smarty\Smarty();
|
||||
$debObj = new Smarty();
|
||||
// copy the working dirs from application
|
||||
$debObj->setCompileDir($smarty->getCompileDir());
|
||||
$debObj->compile_check = \Smarty::COMPILECHECK_ON;
|
||||
$debObj->compile_check = Smarty::COMPILECHECK_ON;
|
||||
$debObj->security_policy = null;
|
||||
$debObj->debugging = false;
|
||||
$debObj->debugging_ctrl = 'NONE';
|
||||
$debObj->error_reporting = E_ALL & ~E_NOTICE;
|
||||
$debObj->debug_tpl = $smarty->debug_tpl ?? 'file:' . __DIR__ . '/../debug.tpl';
|
||||
$debObj->debug_tpl = $smarty->debug_tpl ?? 'file:' . __DIR__ . '/debug.tpl';
|
||||
$debObj->registered_resources = array();
|
||||
$debObj->escape_html = true;
|
||||
$debObj->caching = \Smarty::CACHING_OFF;
|
||||
$debObj->caching = Smarty::CACHING_OFF;
|
||||
// prepare information of assigned variables
|
||||
$ptr = $this->get_debug_vars($obj);
|
||||
$_assigned_vars = $ptr->tpl_vars;
|
||||
@@ -223,7 +214,7 @@ class Debug extends Data
|
||||
$displayMode = $debugging === 2 || !$full;
|
||||
$offset = $this->offset * 50;
|
||||
$_template = $debObj->doCreateTemplate($debObj->debug_tpl);
|
||||
if ($obj instanceof \Smarty\Template) {
|
||||
if ($obj instanceof Template) {
|
||||
$_template->assign('template_name', $templateName);
|
||||
} elseif ($obj instanceof Smarty || $full) {
|
||||
$_template->assign('template_data', $this->template_data[$this->index]);
|
||||
@@ -298,11 +289,11 @@ class Debug extends Data
|
||||
/**
|
||||
* Return key into $template_data for template
|
||||
*
|
||||
* @param \Smarty\Template $template template object
|
||||
* @param Template $template template object
|
||||
*
|
||||
* @return string key into $template_data
|
||||
*/
|
||||
private function get_key(\Smarty\Template $template)
|
||||
private function get_key(Template $template)
|
||||
{
|
||||
static $_is_stringy = array('string' => true, 'eval' => true);
|
||||
|
||||
@@ -319,9 +310,9 @@ class Debug extends Data
|
||||
/**
|
||||
* Ignore template
|
||||
*
|
||||
* @param \Smarty\Template $template
|
||||
* @param Template $template
|
||||
*/
|
||||
public function ignore(\Smarty\Template $template)
|
||||
public function ignore(Template $template)
|
||||
{
|
||||
$this->ignore_uid[$template->getSource()->uid] = true;
|
||||
}
|
||||
@@ -329,9 +320,9 @@ class Debug extends Data
|
||||
/**
|
||||
* handle 'URL' debugging mode
|
||||
*
|
||||
* @param \Smarty $smarty
|
||||
* @param Smarty $smarty
|
||||
*/
|
||||
public function debugUrl(\Smarty $smarty)
|
||||
public function debugUrl(Smarty $smarty)
|
||||
{
|
||||
if (isset($_SERVER[ 'QUERY_STRING' ])) {
|
||||
$_query_string = $_SERVER[ 'QUERY_STRING' ];
|
||||
@@ -360,12 +351,12 @@ class Debug extends Data
|
||||
|
||||
/**
|
||||
* @param array $_is_stringy
|
||||
* @param \Smarty\Template $template
|
||||
* @param Template $template
|
||||
* @param string $key
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function saveTemplateData(array $_is_stringy, \Smarty\Template $template, string $key): void {
|
||||
private function saveTemplateData(array $_is_stringy, Template $template, string $key): void {
|
||||
if (isset($_is_stringy[$template->getSource()->type])) {
|
||||
$this->template_data[$this->index][$key]['name'] =
|
||||
'\'' . substr($template->getSource()->name, 0, 25) . '...\'';
|
||||
|
||||
@@ -77,7 +77,7 @@ class ErrorHandler
|
||||
}
|
||||
|
||||
if ($this->allowUndefinedArrayKeys && preg_match(
|
||||
'/^(Undefined index|Undefined array key|Trying to access array offset on value of type)/',
|
||||
'/^(Undefined index|Undefined array key|Trying to access array offset on)/',
|
||||
$errstr
|
||||
)) {
|
||||
return; // suppresses this error
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace Smarty\Extension;
|
||||
|
||||
use Smarty\Exception;
|
||||
|
||||
class DefaultExtension extends Base {
|
||||
|
||||
private $modifiers = [];
|
||||
@@ -27,7 +29,9 @@ class DefaultExtension extends Base {
|
||||
case 'escape': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\EscapeModifierCompiler(); break;
|
||||
case 'from_charset': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\FromCharsetModifierCompiler(); break;
|
||||
case 'indent': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\IndentModifierCompiler(); break;
|
||||
case 'is_array': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\IsArrayModifierCompiler(); break;
|
||||
case 'isset': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\IssetModifierCompiler(); break;
|
||||
case 'json_encode': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\JsonEncodeModifierCompiler(); break;
|
||||
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;
|
||||
@@ -37,6 +41,7 @@ class DefaultExtension extends Base {
|
||||
case 'strip': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\StripModifierCompiler(); break;
|
||||
case 'strip_tags': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\StripTagsModifierCompiler(); break;
|
||||
case 'strlen': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\StrlenModifierCompiler(); break;
|
||||
case 'substr': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\SubstrModifierCompiler(); break;
|
||||
case 'to_charset': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\ToCharsetModifierCompiler(); break;
|
||||
case 'unescape': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\UnescapeModifierCompiler(); break;
|
||||
case 'upper': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\UpperModifierCompiler(); break;
|
||||
@@ -54,11 +59,15 @@ class DefaultExtension extends Base {
|
||||
case 'debug_print_var': return [$this, 'smarty_modifier_debug_print_var'];
|
||||
case 'escape': return [$this, 'smarty_modifier_escape'];
|
||||
case 'explode': return [$this, 'smarty_modifier_explode'];
|
||||
case 'implode': return [$this, 'smarty_modifier_implode'];
|
||||
case 'in_array': return [$this, 'smarty_modifier_in_array'];
|
||||
case 'join': return [$this, 'smarty_modifier_join'];
|
||||
case 'mb_wordwrap': return [$this, 'smarty_modifier_mb_wordwrap'];
|
||||
case 'number_format': return [$this, 'smarty_modifier_number_format'];
|
||||
case 'regex_replace': return [$this, 'smarty_modifier_regex_replace'];
|
||||
case 'replace': return [$this, 'smarty_modifier_replace'];
|
||||
case 'spacify': return [$this, 'smarty_modifier_spacify'];
|
||||
case 'split': return [$this, 'smarty_modifier_split'];
|
||||
case 'truncate': return [$this, 'smarty_modifier_truncate'];
|
||||
}
|
||||
return null;
|
||||
@@ -82,12 +91,8 @@ class DefaultExtension extends Base {
|
||||
case 'html_select_date': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\HtmlSelectDate(); break;
|
||||
case 'html_select_time': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\HtmlSelectTime(); break;
|
||||
case 'html_table': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\HtmlTable(); break;
|
||||
case 'in_array': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\InArray(); break;
|
||||
case 'is_array': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\IsArray(); break;
|
||||
case 'mailto': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\Mailto(); break;
|
||||
case 'math': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\Math(); break;
|
||||
case 'strlen': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\Strlen(); break;
|
||||
case 'time': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\Time(); break;
|
||||
}
|
||||
|
||||
return $this->functionHandlers[$functionName] ?? null;
|
||||
@@ -211,7 +216,7 @@ class DefaultExtension extends Base {
|
||||
* > 1 would be returned, unless value was null, in which case 0 would be returned.
|
||||
*/
|
||||
|
||||
if ($arrayOrObject instanceof Countable || is_array($arrayOrObject)) {
|
||||
if ($arrayOrObject instanceof \Countable || is_array($arrayOrObject)) {
|
||||
return count($arrayOrObject, (int) $mode);
|
||||
} elseif ($arrayOrObject === null) {
|
||||
return 0;
|
||||
@@ -518,10 +523,91 @@ class DefaultExtension extends Base {
|
||||
*/
|
||||
public function smarty_modifier_explode($separator, $string, ?int $limit = null)
|
||||
{
|
||||
trigger_error("Using explode is deprecated. " .
|
||||
"Use split, using the array first, separator second.", E_USER_DEPRECATED);
|
||||
// provide $string default to prevent deprecation errors in PHP >=8.1
|
||||
return explode($separator, $string ?? '', $limit ?? PHP_INT_MAX);
|
||||
}
|
||||
|
||||
/**
|
||||
* Smarty split modifier plugin
|
||||
* Type: modifier
|
||||
* Name: split
|
||||
* Purpose: split a string by a string
|
||||
*
|
||||
* @param string $string
|
||||
* @param string $separator
|
||||
* @param int|null $limit
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function smarty_modifier_split($string, $separator, ?int $limit = null)
|
||||
{
|
||||
// provide $string default to prevent deprecation errors in PHP >=8.1
|
||||
return explode($separator, $string ?? '', $limit ?? PHP_INT_MAX);
|
||||
}
|
||||
|
||||
/**
|
||||
* Smarty implode modifier plugin
|
||||
* Type: modifier
|
||||
* Name: implode
|
||||
* Purpose: join an array of values into a single string
|
||||
*
|
||||
* @param array $values
|
||||
* @param string $separator
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function smarty_modifier_implode($values, $separator = '')
|
||||
{
|
||||
|
||||
trigger_error("Using implode is deprecated. " .
|
||||
"Use join using the array first, separator second.", E_USER_DEPRECATED);
|
||||
|
||||
if (is_array($separator)) {
|
||||
return implode((string) ($values ?? ''), (array) $separator);
|
||||
}
|
||||
return implode((string) ($separator ?? ''), (array) $values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Smarty in_array modifier plugin
|
||||
* Type: modifier
|
||||
* Name: in_array
|
||||
* Purpose: test if value is contained in an array
|
||||
*
|
||||
* @param mixed $needle
|
||||
* @param array $array
|
||||
* @param bool $strict
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function smarty_modifier_in_array($needle, $array, $strict = false)
|
||||
{
|
||||
return in_array($needle, (array) $array, (bool) $strict);
|
||||
}
|
||||
|
||||
/**
|
||||
* Smarty join modifier plugin
|
||||
* Type: modifier
|
||||
* Name: join
|
||||
* Purpose: join an array of values into a single string
|
||||
*
|
||||
* @param array $values
|
||||
* @param string $separator
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function smarty_modifier_join($values, $separator = '')
|
||||
{
|
||||
if (is_array($separator)) {
|
||||
trigger_error("Using join with the separator first is deprecated. " .
|
||||
"Call join using the array first, separator second.", E_USER_DEPRECATED);
|
||||
return implode((string) ($values ?? ''), (array) $separator);
|
||||
}
|
||||
return implode((string) ($separator ?? ''), (array) $values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Smarty wordwrap modifier plugin
|
||||
* Type: modifier
|
||||
|
||||
@@ -2,20 +2,82 @@
|
||||
|
||||
namespace Smarty\Extension;
|
||||
|
||||
use Smarty\BlockHandler\BlockHandlerInterface;
|
||||
use Smarty\Compile\CompilerInterface;
|
||||
use Smarty\Compile\Modifier\ModifierCompilerInterface;
|
||||
use Smarty\FunctionHandler\FunctionHandlerInterface;
|
||||
|
||||
interface ExtensionInterface {
|
||||
|
||||
public function getTagCompiler(string $tag): ?\Smarty\Compile\CompilerInterface;
|
||||
/**
|
||||
* Either return \Smarty\Compile\CompilerInterface that will compile the given $tag or
|
||||
* return null to indicate that you do not know how to handle this $tag. (Another Extension might.)
|
||||
*
|
||||
* @param string $tag
|
||||
* @return CompilerInterface|null
|
||||
*/
|
||||
public function getTagCompiler(string $tag): ?CompilerInterface;
|
||||
|
||||
public function getModifierCompiler(string $modifier): ?\Smarty\Compile\Modifier\ModifierCompilerInterface;
|
||||
/**
|
||||
* Either return \Smarty\Compile\Modifier\ModifierCompilerInterface that will compile the given $modifier or
|
||||
* return null to indicate that you do not know how to handle this $modifier. (Another Extension might.)
|
||||
*
|
||||
* @param string $modifier
|
||||
* @return ModifierCompilerInterface|null
|
||||
*/
|
||||
public function getModifierCompiler(string $modifier): ?ModifierCompilerInterface;
|
||||
|
||||
public function getFunctionHandler(string $functionName): ?\Smarty\FunctionHandler\FunctionHandlerInterface;
|
||||
/**
|
||||
* Either return \Smarty\FunctionHandler\FunctionHandlerInterface that will handle the given $functionName or
|
||||
* return null to indicate that you do not know how to handle this $functionName. (Another Extension might.)
|
||||
*
|
||||
* @param string $functionName
|
||||
* @return FunctionHandlerInterface|null
|
||||
*/
|
||||
public function getFunctionHandler(string $functionName): ?FunctionHandlerInterface;
|
||||
|
||||
public function getBlockHandler(string $blockTagName): ?\Smarty\BlockHandler\BlockHandlerInterface;
|
||||
/**
|
||||
* Either return \Smarty\BlockHandler\BlockHandlerInterface that will handle the given $blockTagName or return null
|
||||
* to indicate that you do not know how to handle this $blockTagName. (Another Extension might.)
|
||||
*
|
||||
* @param string $blockTagName
|
||||
* @return BlockHandlerInterface|null
|
||||
*/
|
||||
public function getBlockHandler(string $blockTagName): ?BlockHandlerInterface;
|
||||
|
||||
/**
|
||||
* Either return a callable that takes at least 1 parameter (a string) and returns a modified string or return null
|
||||
* to indicate that you do not know how to handle this $modifierName. (Another Extension might.)
|
||||
*
|
||||
* The callable can accept additional optional parameters.
|
||||
*
|
||||
* @param string $modifierName
|
||||
* @return callable|null
|
||||
*/
|
||||
public function getModifierCallback(string $modifierName);
|
||||
|
||||
/**
|
||||
* Return a list of prefilters that will all be applied, in sequence.
|
||||
* Template prefilters can be used to preprocess templates before they are compiled.
|
||||
*
|
||||
* @return \Smarty\Filter\FilterInterface[]
|
||||
*/
|
||||
public function getPreFilters(): array;
|
||||
|
||||
/**
|
||||
* Return a list of postfilters that will all be applied, in sequence.
|
||||
* Template postfilters can be used to process compiled template code (so, after the compilation).
|
||||
*
|
||||
* @return \Smarty\Filter\FilterInterface[]
|
||||
*/
|
||||
public function getPostFilters(): array;
|
||||
|
||||
/**
|
||||
* Return a list of outputfilters that will all be applied, in sequence.
|
||||
* Template outputfilters can be used to change template output just before it is rendered.
|
||||
*
|
||||
* @return \Smarty\Filter\FilterInterface[]
|
||||
*/
|
||||
public function getOutputFilters(): array;
|
||||
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Smarty\FunctionHandler;
|
||||
|
||||
use Smarty\Exception;
|
||||
use Smarty\Template;
|
||||
|
||||
/**
|
||||
* in_array(mixed $needle, array $haystack, bool $strict = false): bool
|
||||
* Returns true if needle is found in the array, false otherwise
|
||||
*/
|
||||
class InArray extends Base {
|
||||
|
||||
public function handle($params, Template $template) {
|
||||
|
||||
$params = array_values($params ?? []);
|
||||
|
||||
if (count($params) < 2 || count($params) > 3) {
|
||||
throw new Exception("Invalid number of arguments for in_array. in_arrays expects 2 or 3 parameters.");
|
||||
}
|
||||
|
||||
// default to false, true if param 3 is set to true
|
||||
$needle = $params[0];
|
||||
$haystack = (array) $params[1];
|
||||
$strict = count($params) == 3 && $params[2];
|
||||
|
||||
return in_array($needle, $haystack, $strict);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Smarty\FunctionHandler;
|
||||
|
||||
use Smarty\Exception;
|
||||
use Smarty\Template;
|
||||
|
||||
/**
|
||||
* is_array(mixed $value): bool
|
||||
* Returns true if value is an array, false otherwise.
|
||||
*/
|
||||
class IsArray extends Base {
|
||||
|
||||
public function handle($params, Template $template) {
|
||||
if (count($params) !== 1) {
|
||||
throw new Exception("Invalid number of arguments for is_array. is_array expects exactly 1 parameter.");
|
||||
}
|
||||
return is_array(reset($params));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -66,7 +66,7 @@ class Math extends Base {
|
||||
$equation = preg_replace('/\s+/', '', $equation);
|
||||
|
||||
// Adapted from https://www.php.net/manual/en/function.eval.php#107377
|
||||
$number = '(?:\d+(?:[,.]\d+)?|pi|π)'; // What is a number
|
||||
$number = '-?(?:\d+(?:[,.]\d+)?|pi|π)'; // What is a number
|
||||
$functionsOrVars = '((?:0x[a-fA-F0-9]+)|([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*))';
|
||||
$operators = '[,+\/*\^%-]'; // Allowed math operators
|
||||
$regexp = '/^((' . $number . '|' . $functionsOrVars . '|(' . $functionsOrVars . '\s*\((?1)*\)|\((?1)*\)))(?:' . $operators . '(?1))?)+$/';
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Smarty\FunctionHandler;
|
||||
|
||||
use Smarty\Exception;
|
||||
use Smarty\Template;
|
||||
|
||||
/**
|
||||
* Get string length
|
||||
*
|
||||
* strlen(string $string): int
|
||||
*
|
||||
* Returns length of the string on success, and 0 if the string is empty.
|
||||
*/
|
||||
class Strlen extends Base {
|
||||
|
||||
public function handle($params, Template $template) {
|
||||
|
||||
$params = array_values($params ?? []);
|
||||
|
||||
if (count($params) !== 1) {
|
||||
throw new Exception("Invalid number of arguments for strlen. strlen expects exactly 1 parameter.");
|
||||
}
|
||||
|
||||
return strlen((string) $params[0]);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Smarty\FunctionHandler;
|
||||
|
||||
use Smarty\Exception;
|
||||
use Smarty\Template;
|
||||
|
||||
/**
|
||||
* is_array(mixed $value): bool
|
||||
* Returns true if value is an array, false otherwise.
|
||||
*/
|
||||
class Time extends Base {
|
||||
|
||||
public function handle($params, Template $template) {
|
||||
if (count($params) > 0) {
|
||||
throw new Exception("Invalid number of arguments for time. time expects no parameters.");
|
||||
}
|
||||
return time();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2675,7 +2675,7 @@ public static $yy_action = array(
|
||||
}
|
||||
// line 1063 "src/Parser/TemplateParser.y"
|
||||
public function yy_r148(){
|
||||
$this->_retvalue = $this->compiler->compileFunctionCall($this->yystack[$this->yyidx + -3]->minor, $this->yystack[$this->yyidx + -1]->minor);
|
||||
$this->_retvalue = $this->compiler->compileModifierInExpression($this->yystack[$this->yyidx + -3]->minor, $this->yystack[$this->yyidx + -1]->minor);
|
||||
}
|
||||
// line 1071 "src/Parser/TemplateParser.y"
|
||||
public function yy_r149(){
|
||||
|
||||
@@ -1061,7 +1061,7 @@ objectelement(res)::= PTR method(f). {
|
||||
// function
|
||||
//
|
||||
function(res) ::= ns1(f) OPENP params(p) CLOSEP. {
|
||||
res = $this->compiler->compileFunctionCall(f, p);
|
||||
res = $this->compiler->compileModifierInExpression(f, p);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -26,31 +26,26 @@ class TplFunctionRuntime {
|
||||
*/
|
||||
public function callTemplateFunction(Template $tpl, $name, $params, $nocache) {
|
||||
$funcParam = $tpl->tplFunctions[$name] ?? ($tpl->getSmarty()->tplFunctions[$name] ?? null);
|
||||
if (isset($funcParam)) {
|
||||
if (!$tpl->caching || ($tpl->caching && $nocache)) {
|
||||
$function = $funcParam['call_name'];
|
||||
if (!isset($funcParam)) {
|
||||
throw new \Smarty\Exception("Unable to find template function '{$name}'");
|
||||
}
|
||||
|
||||
if (!$tpl->caching || ($tpl->caching && $nocache)) {
|
||||
$function = $funcParam['call_name'];
|
||||
} else {
|
||||
if (isset($funcParam['call_name_caching'])) {
|
||||
$function = $funcParam['call_name_caching'];
|
||||
} else {
|
||||
if (isset($funcParam['call_name_caching'])) {
|
||||
$function = $funcParam['call_name_caching'];
|
||||
} else {
|
||||
$function = $funcParam['call_name'];
|
||||
}
|
||||
}
|
||||
if (function_exists($function)) {
|
||||
$this->saveTemplateVariables($tpl, $name);
|
||||
$function($tpl, $params);
|
||||
$this->restoreTemplateVariables($tpl, $name);
|
||||
return;
|
||||
}
|
||||
// try to load template function dynamically
|
||||
if ($this->addTplFuncToCache($tpl, $name, $function)) {
|
||||
$this->saveTemplateVariables($tpl, $name);
|
||||
$function($tpl, $params);
|
||||
$this->restoreTemplateVariables($tpl, $name);
|
||||
return;
|
||||
$function = $funcParam['call_name'];
|
||||
}
|
||||
}
|
||||
throw new \Smarty\Exception("Unable to find template function '{$name}'");
|
||||
if (!function_exists($function) && !$this->addTplFuncToCache($tpl, $name, $function)) {
|
||||
throw new \Smarty\Exception("Unable to find template function '{$name}'");
|
||||
}
|
||||
|
||||
$tpl->pushStack();
|
||||
$function($tpl, $params);
|
||||
$tpl->popStack();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -146,28 +141,4 @@ class TplFunctionRuntime {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save current template variables on stack
|
||||
*
|
||||
* @param \Smarty\Template $tpl
|
||||
* @param string $name stack name
|
||||
*/
|
||||
public function saveTemplateVariables(Template $tpl, $name) {
|
||||
$tpl->_var_stack[] =
|
||||
['tpl' => $tpl->tpl_vars, 'config' => $tpl->config_vars, 'name' => "_tplFunction_{$name}"];
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore saved variables into template objects
|
||||
*
|
||||
* @param \Smarty\Template $tpl
|
||||
* @param string $name stack name
|
||||
*/
|
||||
public function restoreTemplateVariables(Template $tpl, $name) {
|
||||
if (isset($tpl->_var_stack)) {
|
||||
$vars = array_pop($tpl->_var_stack);
|
||||
$tpl->tpl_vars = $vars['tpl'];
|
||||
$tpl->config_vars = $vars['config'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -261,6 +261,8 @@ class Security {
|
||||
* @return boolean true if tag is trusted
|
||||
*/
|
||||
public function isTrustedTag($tag_name, $compiler) {
|
||||
$tag_name = strtolower($tag_name);
|
||||
|
||||
// check for internal always required tags
|
||||
if (in_array($tag_name, ['assign', 'call'])) {
|
||||
return true;
|
||||
|
||||
+18
-15
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Smarty;
|
||||
|
||||
use FilesystemIterator;
|
||||
use RecursiveDirectoryIterator;
|
||||
use RecursiveIteratorIterator;
|
||||
use Smarty\Cacheresource\File;
|
||||
@@ -12,11 +13,12 @@ use Smarty\Extension\CoreExtension;
|
||||
use Smarty\Extension\DefaultExtension;
|
||||
use Smarty\Extension\ExtensionInterface;
|
||||
use Smarty\Filter\Output\TrimWhitespace;
|
||||
use Smarty\Resource\BasePlugin;
|
||||
use Smarty\Smarty\Runtime\CaptureRuntime;
|
||||
use Smarty\Smarty\Runtime\ForeachRuntime;
|
||||
use Smarty\Smarty\Runtime\InheritanceRuntime;
|
||||
use Smarty\Smarty\Runtime\TplFunctionRuntime;
|
||||
use Smarty\Runtime\CaptureRuntime;
|
||||
use Smarty\Runtime\DefaultPluginHandlerRuntime;
|
||||
use Smarty\Runtime\ForeachRuntime;
|
||||
use Smarty\Runtime\InheritanceRuntime;
|
||||
use Smarty\Runtime\TplFunctionRuntime;
|
||||
|
||||
|
||||
/**
|
||||
* Project: Smarty: the PHP compiling template engine
|
||||
@@ -53,7 +55,7 @@ class Smarty extends \Smarty\TemplateBase {
|
||||
/**
|
||||
* smarty version
|
||||
*/
|
||||
const SMARTY_VERSION = '5.0.0-rc1';
|
||||
const SMARTY_VERSION = '5.0.1';
|
||||
|
||||
/**
|
||||
* define caching modes
|
||||
@@ -251,9 +253,10 @@ class Smarty extends \Smarty\TemplateBase {
|
||||
|
||||
/**
|
||||
* debug mode
|
||||
* Setting this to true enables the debug-console.
|
||||
* Setting this to true enables the debug-console. Setting it to 2 enables individual Debug Console window by
|
||||
* template name.
|
||||
*
|
||||
* @var boolean
|
||||
* @var boolean|int
|
||||
*/
|
||||
public $debugging = false;
|
||||
|
||||
@@ -1754,15 +1757,15 @@ class Smarty extends \Smarty\TemplateBase {
|
||||
// Lazy load runtimes when/if needed
|
||||
switch ($type) {
|
||||
case 'Capture':
|
||||
return $this->runtimes[$type] = new \Smarty\Runtime\CaptureRuntime();
|
||||
return $this->runtimes[$type] = new CaptureRuntime();
|
||||
case 'Foreach':
|
||||
return $this->runtimes[$type] = new \Smarty\Runtime\ForeachRuntime();
|
||||
return $this->runtimes[$type] = new ForeachRuntime();
|
||||
case 'Inheritance':
|
||||
return $this->runtimes[$type] = new \Smarty\Runtime\InheritanceRuntime();
|
||||
return $this->runtimes[$type] = new InheritanceRuntime();
|
||||
case 'TplFunction':
|
||||
return $this->runtimes[$type] = new \Smarty\Runtime\TplFunctionRuntime();
|
||||
return $this->runtimes[$type] = new TplFunctionRuntime();
|
||||
case 'DefaultPluginHandler':
|
||||
return $this->runtimes[$type] = new \Smarty\Runtime\DefaultPluginHandlerRuntime(
|
||||
return $this->runtimes[$type] = new DefaultPluginHandlerRuntime(
|
||||
$this->getDefaultPluginHandlerFunc()
|
||||
);
|
||||
}
|
||||
@@ -2051,7 +2054,7 @@ class Smarty extends \Smarty\TemplateBase {
|
||||
* @param array|string $modifiers modifier or list of modifiers
|
||||
* to add
|
||||
*
|
||||
* @return \Smarty|Template
|
||||
* @return Smarty
|
||||
* @api Smarty::addDefaultModifiers()
|
||||
*
|
||||
*/
|
||||
@@ -2130,7 +2133,7 @@ class Smarty extends \Smarty\TemplateBase {
|
||||
* @throws \Smarty\Exception
|
||||
*/
|
||||
public function display($template = null, $cache_id = null, $compile_id = null) {
|
||||
return $this->returnOrCreateTemplate($template, $cache_id, $compile_id)->display();
|
||||
$this->returnOrCreateTemplate($template, $cache_id, $compile_id)->display();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+2
-4
@@ -645,8 +645,7 @@ class Template extends TemplateBase {
|
||||
} else {
|
||||
|
||||
// After rendering a template, the tpl/config variables are reset, so the template can be re-used.
|
||||
$savedTplVars = $this->tpl_vars;
|
||||
$savedConfigVars = $this->config_vars;
|
||||
$this->pushStack();
|
||||
|
||||
// Start output-buffering.
|
||||
ob_start();
|
||||
@@ -654,8 +653,7 @@ class Template extends TemplateBase {
|
||||
$result = $this->render(false, $function);
|
||||
|
||||
// Restore the template to its previous state
|
||||
$this->tpl_vars = $savedTplVars;
|
||||
$this->config_vars = $savedConfigVars;
|
||||
$this->popStack();
|
||||
}
|
||||
|
||||
if (isset($errorHandler)) {
|
||||
|
||||
@@ -271,11 +271,11 @@ class Source {
|
||||
return $this->type . ':' . $this->name;
|
||||
}
|
||||
|
||||
public function getFilepath(): string {
|
||||
public function getFilepath(): ?string {
|
||||
if ($this->handler instanceof FilePlugin) {
|
||||
return $this->handler->getFilePath($this->name, $this->smarty, $this->isConfig);
|
||||
}
|
||||
return '.';
|
||||
return null;
|
||||
}
|
||||
|
||||
public function isConfig(): bool {
|
||||
|
||||
@@ -59,13 +59,6 @@ abstract class TemplateBase extends Data {
|
||||
*/
|
||||
public $tplFunctions = [];
|
||||
|
||||
/**
|
||||
* When initialized to an (empty) array, this variable will hold a stack of template variables.
|
||||
*
|
||||
* @var null|array
|
||||
*/
|
||||
public $_var_stack = null;
|
||||
|
||||
/**
|
||||
* @var Debug
|
||||
*/
|
||||
@@ -384,9 +377,9 @@ abstract class TemplateBase extends Data {
|
||||
* Registers a resource to fetch a template
|
||||
*
|
||||
* @param string $name name of resource type
|
||||
* @param Smarty\Resource\Base $resource_handler instance of Smarty\Resource\Base
|
||||
* @param \Smarty\Resource\BasePlugin $resource_handler instance of Smarty\Resource\BasePlugin
|
||||
*
|
||||
* @return \Smarty|\Smarty\Template
|
||||
* @return \Smarty\Smarty|\Smarty\Template
|
||||
* @link https://www.smarty.net/docs/en/api.register.resource.tpl
|
||||
*
|
||||
* @api Smarty::registerResource()
|
||||
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
{capture name='_smarty_debug' assign=debug_output}
|
||||
{capture name='_smarty_debug' assign='debug_output'}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
@@ -108,7 +108,7 @@
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>Smarty {Smarty::SMARTY_VERSION} Debug Console
|
||||
<h1>Smarty {\Smarty\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)}
|
||||
@@ -166,7 +166,7 @@
|
||||
</body>
|
||||
</html>
|
||||
{/capture}
|
||||
<script type="text/javascript">
|
||||
<script>
|
||||
_smarty_console = window.open("", "console{$targetWindow}", "width=1024,height=600,left={$offset},top={$offset},resizable,scrollbars=yes");
|
||||
_smarty_console.document.write("{$debug_output|escape:'javascript' nofilter}");
|
||||
_smarty_console.document.close();
|
||||
|
||||
+1
-1
@@ -66,7 +66,7 @@ function smarty_make_timestamp($string)
|
||||
|| (interface_exists('DateTimeInterface', false) && $string instanceof DateTimeInterface)
|
||||
) {
|
||||
return (int)$string->format('U'); // PHP 5.2 BC
|
||||
} elseif (strlen($string) === 14 && ctype_digit($string)) {
|
||||
} elseif (strlen($string) === 14 && ctype_digit((string)$string)) {
|
||||
// it is mysql timestamp format of YYYYMMDDHHMMSS?
|
||||
return mktime(
|
||||
substr($string, 8, 2),
|
||||
|
||||
@@ -30,4 +30,35 @@ class AutoEscapeTest extends PHPUnit_Smarty
|
||||
$tpl->assign('foo', '<a@b.c>');
|
||||
$this->assertEquals("<a@b.c>", $this->smarty->fetch($tpl));
|
||||
}
|
||||
|
||||
/**
|
||||
* test 'escapeHtml' property
|
||||
* @group issue906
|
||||
*/
|
||||
public function testAutoEscapeDoesNotEscapeFunctionPlugins()
|
||||
{
|
||||
$this->smarty->registerPlugin(
|
||||
\Smarty\Smarty::PLUGIN_FUNCTION,
|
||||
'horizontal_rule',
|
||||
function ($params, $smarty) { return "<hr>"; }
|
||||
);
|
||||
$tpl = $this->smarty->createTemplate('eval:{horizontal_rule}');
|
||||
$this->assertEquals("<hr>", $this->smarty->fetch($tpl));
|
||||
}
|
||||
|
||||
/**
|
||||
* test 'escapeHtml' property
|
||||
* @group issue906
|
||||
*/
|
||||
public function testAutoEscapeDoesNotEscapeBlockPlugins()
|
||||
{
|
||||
$this->smarty->registerPlugin(
|
||||
\Smarty\Smarty::PLUGIN_BLOCK,
|
||||
'paragraphify',
|
||||
function ($params, $content) { return $content == null ? null : "<p>".$content."</p>"; }
|
||||
);
|
||||
$tpl = $this->smarty->createTemplate('eval:{paragraphify}hi{/paragraphify}');
|
||||
$this->assertEquals("<p>hi</p>", $this->smarty->fetch($tpl));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -39,6 +39,17 @@ class RegisterFunctionTest extends PHPUnit_Smarty
|
||||
$this->assertEquals('hello world 1', $this->smarty->fetch('eval:{testfunction value=1}'));
|
||||
}
|
||||
|
||||
/**
|
||||
* test registerPlugin method for function case-sensitive
|
||||
*/
|
||||
public function testRegisterFunctionCaseInsensitive()
|
||||
{
|
||||
$this->smarty->registerPlugin(Smarty::PLUGIN_FUNCTION, 'testFunction', 'myfunction');
|
||||
$this->assertEquals('myfunction',
|
||||
$this->smarty->getRegisteredPlugin(Smarty::PLUGIN_FUNCTION, 'testFunction')[0]);
|
||||
$this->assertEquals('hello world 1', $this->smarty->fetch('eval:{testFunction value=1}'));
|
||||
}
|
||||
|
||||
/**
|
||||
* test registerPlugin method for function class
|
||||
*/
|
||||
@@ -143,7 +154,7 @@ class RegisterFunctionTest extends PHPUnit_Smarty
|
||||
public function testUnregisterFunctionNotRegistered()
|
||||
{
|
||||
$this->smarty->unregisterPlugin(Smarty::PLUGIN_FUNCTION, 'testfunction');
|
||||
$this->assertNull($this->smarty->getRegisteredPlugin(Smarty::PLUGIN_FUNCTION, 'testfunction'));
|
||||
$this->assertNull($this->smarty->getRegisteredPlugin(Smarty::PLUGIN_FUNCTION, 'testfunction'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -153,8 +164,34 @@ class RegisterFunctionTest extends PHPUnit_Smarty
|
||||
{
|
||||
$this->smarty->registerPlugin(Smarty::PLUGIN_BLOCK, 'testfunction', 'myfunction');
|
||||
$this->smarty->unregisterPlugin(Smarty::PLUGIN_FUNCTION, 'testfunction');
|
||||
$this->assertIsArray($this->smarty->getRegisteredPlugin(Smarty::PLUGIN_BLOCK, 'testfunction'));
|
||||
$this->assertIsArray($this->smarty->getRegisteredPlugin(Smarty::PLUGIN_BLOCK, 'testfunction'));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test case (in)sensitivy of plugin functions
|
||||
* @param $registerName
|
||||
* @param $templateString
|
||||
* @return void
|
||||
* @throws \Smarty\Exception
|
||||
* @group issue907
|
||||
* @dataProvider dataProviderForCaseSensitivity
|
||||
*/
|
||||
public function testCaseSensitivity($registerName, $templateString) {
|
||||
$this->smarty->registerPlugin(
|
||||
Smarty::PLUGIN_FUNCTION,
|
||||
$registerName,
|
||||
function($params, $smarty) { return 'function-output'; });
|
||||
$this->assertEquals('function-output', $this->smarty->fetch('string:' . $templateString));
|
||||
}
|
||||
|
||||
public function dataProviderForCaseSensitivity() {
|
||||
return [
|
||||
['customTag', '{customTag}'],
|
||||
['customtag', '{customtag}'],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function myfunction($params, $smarty)
|
||||
|
||||
@@ -103,7 +103,8 @@ class RegisterModifierTest extends PHPUnit_Smarty
|
||||
|
||||
public function dataUnknownModifiers(): array {
|
||||
return [
|
||||
['{"blah"|substr:1:2}', 'la'],
|
||||
['{" blah"|ltrim:" "}', 'blah'],
|
||||
['{"blah"|strrev}', 'halb'],
|
||||
['{"blah"|ucfirst}', 'Blah'],
|
||||
['{"blah"|md5}', md5('blah')],
|
||||
];
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace UnitTests\TemplateSource\TagTests\Debug;
|
||||
use PHPUnit_Smarty;
|
||||
use Smarty\Smarty;
|
||||
|
||||
/**
|
||||
* Smarty PHPunit tests of {debug} tag
|
||||
*/
|
||||
class PluginModifierStripTagsTest extends PHPUnit_Smarty {
|
||||
|
||||
public function setUp(): void {
|
||||
$this->setUpSmarty(__DIR__);
|
||||
}
|
||||
public function testDefault() {
|
||||
$tpl = $this->smarty->createTemplate('eval:{debug}');
|
||||
$output = $this->smarty->fetch($tpl);
|
||||
$this->assertStringContainsString("<script", $output);
|
||||
$this->assertStringContainsString("</script>", $output);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -103,7 +103,37 @@ class CompileIfTest extends PHPUnit_Smarty
|
||||
array('{if 6 is not even}yes{else}no{/if}', 'no', 'IsNotEven', $i ++),
|
||||
array('{if 3 is odd}yes{else}no{/if}', 'yes', 'IsOdd', $i ++),
|
||||
array('{if 3 is not odd}yes{else}no{/if}', 'no', 'IsNotOdd', $i ++),
|
||||
array('{$foo=3}{if 3 is odd by $foo}yes{else}no{/if}', 'yes', 'IsOddByVar', $i ++),
|
||||
|
||||
array('{if 0 is even by 3}yes{else}no{/if}', 'yes', 'IsEvenByTest0', $i ++),
|
||||
array('{if 1 is even by 3}yes{else}no{/if}', 'yes', 'IsEvenByTest1', $i ++),
|
||||
array('{if 2 is even by 3}yes{else}no{/if}', 'yes', 'IsEvenByTest2', $i ++),
|
||||
array('{if 3 is even by 3}yes{else}no{/if}', 'no', 'IsEvenByTest3', $i ++),
|
||||
array('{if 4 is even by 3}yes{else}no{/if}', 'no', 'IsEvenByTest4', $i ++),
|
||||
array('{if 5 is even by 3}yes{else}no{/if}', 'no', 'IsEvenByTest5', $i ++),
|
||||
array('{if 6 is even by 3}yes{else}no{/if}', 'yes', 'IsEvenByTest6', $i ++),
|
||||
array('{if 7 is even by 3}yes{else}no{/if}', 'yes', 'IsEvenByTest7', $i ++),
|
||||
|
||||
array('{if 0 is odd by 3}yes{else}no{/if}', 'no', 'IsOddByTest0', $i ++),
|
||||
array('{if 1 is odd by 3}yes{else}no{/if}', 'no', 'IsOddByTest1', $i ++),
|
||||
array('{if 2 is odd by 3}yes{else}no{/if}', 'no', 'IsOddByTest2', $i ++),
|
||||
array('{if 3 is odd by 3}yes{else}no{/if}', 'yes', 'IsOddByTest3', $i ++),
|
||||
array('{if 4 is odd by 3}yes{else}no{/if}', 'yes', 'IsOddByTest4', $i ++),
|
||||
array('{if 5 is odd by 3}yes{else}no{/if}', 'yes', 'IsOddByTest5', $i ++),
|
||||
array('{if 6 is odd by 3}yes{else}no{/if}', 'no', 'IsOddByTest6', $i ++),
|
||||
array('{if 7 is odd by 3}yes{else}no{/if}', 'no', 'IsOddByTest7', $i ++),
|
||||
|
||||
array('{if 2 is even by 3}yes{else}no{/if}', 'yes', 'IsEvenByVal1', $i ++),
|
||||
array('{if 3 is even by 2}yes{else}no{/if}', 'no', 'IsEvenByVal2', $i ++),
|
||||
array('{if 4 is even by 3}yes{else}no{/if}', 'no', 'IsEvenByVal3', $i ++),
|
||||
array('{$foo=3}{if 2 is even by $foo}yes{else}no{/if}', 'yes', 'IsEvenByVar1', $i ++),
|
||||
array('{$foo=2}{if 3 is even by $foo}yes{else}no{/if}', 'no', 'IsEvenByVar2', $i ++),
|
||||
array('{$foo=3}{if 4 is even by $foo}yes{else}no{/if}', 'no', 'IsEvenByVar3', $i ++),
|
||||
array('{if 2 is odd by 3}yes{else}no{/if}', 'no', 'IsOddByVal1', $i ++),
|
||||
array('{if 3 is odd by 2}yes{else}no{/if}', 'yes', 'IsOddByVal2', $i ++),
|
||||
array('{if 4 is odd by 3}yes{else}no{/if}', 'yes', 'IsOddByVal3', $i ++),
|
||||
array('{$foo=3}{if 2 is odd by $foo}yes{else}no{/if}', 'no', 'IsOddByVar1', $i ++),
|
||||
array('{$foo=2}{if 3 is odd by $foo}yes{else}no{/if}', 'yes', 'IsOddByVar2', $i ++),
|
||||
array('{$foo=3}{if 4 is odd by $foo}yes{else}no{/if}', 'yes', 'IsOddByVar3', $i ++),
|
||||
array('{$foo=3}{$bar=6}{if $bar is not odd by $foo}yes{else}no{/if}', 'yes', 'IsNotOddByVar', $i ++),
|
||||
array('{$foo=3}{$bar=3}{if 3+$bar is not odd by $foo}yes{else}no{/if}', 'yes', 'ExprIsNotOddByVar', $i ++),
|
||||
array('{$foo=2}{$bar=6}{if (3+$bar) is not odd by ($foo+1)}yes{else}no{/if}', 'no', 'ExprIsNotOddByExpr', $i ++),
|
||||
|
||||
@@ -15,6 +15,10 @@ class IssetTest extends \PHPUnit_Smarty {
|
||||
$this->assertEquals("yay", $this->smarty->fetch("string:{if isset('')}yay{/if}"));
|
||||
}
|
||||
|
||||
public function testEmptyStringIssetModifierSyntax() {
|
||||
$this->assertEquals("yay", $this->smarty->fetch("string:{if ''|isset}yay{/if}"));
|
||||
}
|
||||
|
||||
public function testFalseIsset() {
|
||||
$this->smarty->assign('test', false);
|
||||
$this->assertEquals("yay", $this->smarty->fetch("string:{if isset(\$test)}yay{/if}"));
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace UnitTests\TemplateSource\TagTests\PluginFunction;
|
||||
class TimeTest extends \PHPUnit_Smarty {
|
||||
|
||||
public function setUp(): void {
|
||||
$this->setUpSmarty(__DIR__);
|
||||
}
|
||||
|
||||
public function testBasicSyntax() {
|
||||
$this->assertStringMatchesFormat('%d', $this->smarty->fetch("string:{time()}"));
|
||||
}
|
||||
|
||||
public function testInvalidParameters() {
|
||||
$this->expectException(\Smarty\Exception::class);
|
||||
$this->expectExceptionMessage('Invalid number of arguments');
|
||||
$this->assertEquals("", $this->smarty->fetch("string:{time(3, 'foo')}"));
|
||||
}
|
||||
|
||||
}
|
||||
+1
-3
@@ -18,9 +18,7 @@ class PluginModifierExplodeTest extends \PHPUnit_Smarty
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
* @throws \Smarty\Exception
|
||||
*
|
||||
* @deprecated
|
||||
* @dataProvider explodeDataProvider
|
||||
*/
|
||||
public function testExplode($template, $subject, $expectedString)
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
/**
|
||||
* Smarty PHPunit tests of modifier
|
||||
*/
|
||||
|
||||
namespace UnitTests\TemplateSource\TagTests\PluginModifier;
|
||||
use PHPUnit_Smarty;
|
||||
|
||||
class PluginModifierImplodeTest extends PHPUnit_Smarty
|
||||
{
|
||||
public function setUp(): void
|
||||
{
|
||||
$this->setUpSmarty(__DIR__);
|
||||
}
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
public function testDefault()
|
||||
{
|
||||
$tpl = $this->smarty->createTemplate('string:{$v|implode}');
|
||||
$tpl->assign("v", ["1", "2"]);
|
||||
$this->assertEquals("12", $this->smarty->fetch($tpl));
|
||||
}
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
public function testWithSeparator()
|
||||
{
|
||||
$tpl = $this->smarty->createTemplate('string:{$v|implode:","}');
|
||||
$tpl->assign("v", ["a", "b"]);
|
||||
$this->assertEquals("a,b", $this->smarty->fetch($tpl));
|
||||
}
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
public function testLegacyArgumentOrder()
|
||||
{
|
||||
$tpl = $this->smarty->createTemplate('string:{","|implode:$v}');
|
||||
$tpl->assign("v", ["a", "b"]);
|
||||
$this->assertEquals("a,b", $this->smarty->fetch($tpl));
|
||||
}
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
public function testInConditional()
|
||||
{
|
||||
$tpl = $this->smarty->createTemplate('string:{if implode($v) == "abc"}good{else}bad{/if}');
|
||||
$tpl->assign("v", ['a','b','c']);
|
||||
$this->assertEquals("good", $this->smarty->fetch($tpl));
|
||||
}
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
public function testInConditionalWithSeparator()
|
||||
{
|
||||
$tpl = $this->smarty->createTemplate('string:{if implode($v, "-") == "a-b-c"}good{else}bad{/if}');
|
||||
$tpl->assign("v", ['a','b','c']);
|
||||
$this->assertEquals("good", $this->smarty->fetch($tpl));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
/**
|
||||
* Smarty PHPunit tests of modifier
|
||||
*/
|
||||
|
||||
namespace UnitTests\TemplateSource\TagTests\PluginModifier;
|
||||
use PHPUnit_Smarty;
|
||||
|
||||
class PluginModifierJoinTest extends PHPUnit_Smarty
|
||||
{
|
||||
public function setUp(): void
|
||||
{
|
||||
$this->setUpSmarty(__DIR__);
|
||||
}
|
||||
|
||||
public function testDefault()
|
||||
{
|
||||
$tpl = $this->smarty->createTemplate('string:{$v|join}');
|
||||
$tpl->assign("v", ["1", "2"]);
|
||||
$this->assertEquals("12", $this->smarty->fetch($tpl));
|
||||
}
|
||||
public function testWithSeparator()
|
||||
{
|
||||
$tpl = $this->smarty->createTemplate('string:{$v|join:","}');
|
||||
$tpl->assign("v", ["a", "b"]);
|
||||
$this->assertEquals("a,b", $this->smarty->fetch($tpl));
|
||||
}
|
||||
|
||||
public function testInConditional()
|
||||
{
|
||||
$tpl = $this->smarty->createTemplate('string:{if join($v) == "abc"}good{else}bad{/if}');
|
||||
$tpl->assign("v", ['a','b','c']);
|
||||
$this->assertEquals("good", $this->smarty->fetch($tpl));
|
||||
}
|
||||
|
||||
public function testInConditionalWithSeparator()
|
||||
{
|
||||
$tpl = $this->smarty->createTemplate('string:{if join($v, "-") == "a-b-c"}good{else}bad{/if}');
|
||||
$tpl->assign("v", ['a','b','c']);
|
||||
$this->assertEquals("good", $this->smarty->fetch($tpl));
|
||||
}
|
||||
|
||||
}
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
/**
|
||||
* Smarty PHPunit tests of modifier
|
||||
*/
|
||||
|
||||
namespace UnitTests\TemplateSource\TagTests\PluginModifier;
|
||||
use PHPUnit_Smarty;
|
||||
|
||||
class PluginModifierJsonEncodeTest extends PHPUnit_Smarty
|
||||
{
|
||||
public function setUp(): void
|
||||
{
|
||||
$this->setUpSmarty(__DIR__);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataForDefault
|
||||
*/
|
||||
public function testDefault($value, $expected)
|
||||
{
|
||||
$tpl = $this->smarty->createTemplate('string:{$v|json_encode}');
|
||||
$tpl->assign("v", $value);
|
||||
$this->assertEquals($expected, $this->smarty->fetch($tpl));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataForDefault
|
||||
*/
|
||||
public function testDefaultAsFunction($value, $expected)
|
||||
{
|
||||
$tpl = $this->smarty->createTemplate('string:{json_encode($v)}');
|
||||
$tpl->assign("v", $value);
|
||||
$this->assertEquals($expected, $this->smarty->fetch($tpl));
|
||||
}
|
||||
|
||||
public function dataForDefault() {
|
||||
return [
|
||||
["abc", '"abc"'],
|
||||
[["abc"], '["abc"]'],
|
||||
[["abc",["a"=>2]], '["abc",{"a":2}]'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataForForceObject
|
||||
*/
|
||||
public function testForceObject($value, $expected)
|
||||
{
|
||||
$tpl = $this->smarty->createTemplate('string:{$v|json_encode:16}');
|
||||
$tpl->assign("v", $value);
|
||||
$this->assertEquals($expected, $this->smarty->fetch($tpl));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataForForceObject
|
||||
*/
|
||||
public function testForceObjectAsFunction($value, $expected)
|
||||
{
|
||||
$tpl = $this->smarty->createTemplate('string:{json_encode($v,16)}');
|
||||
$tpl->assign("v", $value);
|
||||
$this->assertEquals($expected, $this->smarty->fetch($tpl));
|
||||
}
|
||||
|
||||
public function dataForForceObject() {
|
||||
return [
|
||||
["abc", '"abc"'],
|
||||
[["abc"], '{"0":"abc"}'],
|
||||
[["abc",["a"=>2]], '{"0":"abc","1":{"a":2}}'],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace UnitTests\TemplateSource\TagTests\PluginModifier;
|
||||
|
||||
/**
|
||||
* class for modifier tests
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
class PluginModifierSplitTest extends \PHPUnit_Smarty
|
||||
{
|
||||
public function setUp(): void
|
||||
{
|
||||
$this->setUpSmarty(__DIR__);
|
||||
$this->smarty->registerPlugin('modifier', 'json_encode', 'json_encode');
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider explodeDataProvider
|
||||
*/
|
||||
public function testSplit($template, $subject, $expectedString)
|
||||
{
|
||||
$this->smarty->assign('subject', $subject);
|
||||
|
||||
$tpl = $this->smarty->createTemplate($template);
|
||||
$res = $this->smarty->fetch($tpl);
|
||||
|
||||
$this->assertEquals($expectedString, $res);
|
||||
}
|
||||
|
||||
public function explodeDataProvider()
|
||||
{
|
||||
return [
|
||||
'default' => [
|
||||
'template' => 'string:{$subject|split:","|json_encode}',
|
||||
'subject' => 'a,b,c,d',
|
||||
'expectedString' => '["a","b","c","d"]',
|
||||
],
|
||||
'withNoDelimiterFound' => [
|
||||
'template' => 'string:{$subject|split:","|json_encode}',
|
||||
'subject' => 'abcd',
|
||||
'expectedString' => '["abcd"]',
|
||||
],
|
||||
'withNull' => [
|
||||
'template' => 'string:{$subject|split:","|json_encode}',
|
||||
'subject' => null,
|
||||
'expectedString' => '[""]',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
/**
|
||||
* Smarty PHPunit tests of modifier
|
||||
*/
|
||||
|
||||
namespace UnitTests\TemplateSource\TagTests\PluginModifier;
|
||||
use PHPUnit_Smarty;
|
||||
|
||||
class PluginModifierSubstrTest extends PHPUnit_Smarty
|
||||
{
|
||||
public function setUp(): void
|
||||
{
|
||||
$this->setUpSmarty(__DIR__);
|
||||
}
|
||||
|
||||
public function testDefault()
|
||||
{
|
||||
$tpl = $this->smarty->createTemplate('string:{$v|substr:1}');
|
||||
$tpl->assign("v", "abc");
|
||||
$this->assertEquals("bc", $this->smarty->fetch($tpl));
|
||||
}
|
||||
|
||||
public function testTwoArguments()
|
||||
{
|
||||
$tpl = $this->smarty->createTemplate('string:{$v|substr:1:1}');
|
||||
$tpl->assign("v", "abc");
|
||||
$this->assertEquals("b", $this->smarty->fetch($tpl));
|
||||
}
|
||||
|
||||
public function testNegativeOffset()
|
||||
{
|
||||
$tpl = $this->smarty->createTemplate('string:{$v|substr:-1}');
|
||||
$tpl->assign("v", "abc");
|
||||
$this->assertEquals("c", $this->smarty->fetch($tpl));
|
||||
}
|
||||
|
||||
public function testInConditional()
|
||||
{
|
||||
$tpl = $this->smarty->createTemplate('string:{if substr($v, -1) == "c"}good{else}bad{/if}');
|
||||
$tpl->assign("v", "abc");
|
||||
$this->assertEquals("good", $this->smarty->fetch($tpl));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -93,6 +93,14 @@ class MathTest extends PHPUnit_Smarty
|
||||
$this->assertEquals($expected, $this->smarty->fetch($tpl));
|
||||
}
|
||||
|
||||
public function testNegativeNumbers()
|
||||
{
|
||||
$this->smarty->disableSecurity();
|
||||
$expected = "-19 -- 4.1";
|
||||
$tpl = $this->smarty->createTemplate('eval:{$x = 4}{$y = 5.5}{math equation="-2.0*(x+y)" x=$x y=$y} -- {math equation="-20.5 / -5"}');
|
||||
$this->assertEquals($expected, $this->smarty->fetch($tpl));
|
||||
}
|
||||
|
||||
public function testSyntaxFormat()
|
||||
{
|
||||
$this->smarty->disableSecurity();
|
||||
|
||||
@@ -79,7 +79,7 @@ class PhpFunctionTest extends PHPUnit_Smarty
|
||||
public function testEmpty3()
|
||||
{
|
||||
$this->smarty->disableSecurity();
|
||||
$this->getSmarty()->registerPlugin(\Smarty\Smarty::PLUGIN_FUNCTION, 'pass', function ($v) { return $v; });
|
||||
$this->getSmarty()->registerPlugin(\Smarty\Smarty::PLUGIN_MODIFIER, 'pass', function ($v) { return $v; });
|
||||
$this->smarty->assign('var', array(true,
|
||||
(int) 1,
|
||||
(float) 0.1,
|
||||
@@ -99,7 +99,7 @@ class PhpFunctionTest extends PHPUnit_Smarty
|
||||
public function testEmpty4()
|
||||
{
|
||||
$this->smarty->disableSecurity();
|
||||
$this->getSmarty()->registerPlugin(\Smarty\Smarty::PLUGIN_FUNCTION, 'pass', function ($v) { return $v; });
|
||||
$this->getSmarty()->registerPlugin(\Smarty\Smarty::PLUGIN_MODIFIER, 'pass', function ($v) { return $v; });
|
||||
$this->smarty->assign('var', new TestIsset());
|
||||
$expected = ' true , false , false , true , true , true , false ';
|
||||
$this->assertEquals($expected, $this->smarty->fetch('string:{strip}{if empty($var->isNull)} true {else} false {/IF}
|
||||
|
||||
@@ -325,4 +325,13 @@ class ScopeTest extends PHPUnit_Smarty
|
||||
$this->smarty->assign('scope', 'none');
|
||||
$r = $this->smarty->fetch('test_function_scope.tpl');
|
||||
}
|
||||
|
||||
public function testFunctionScopeIsLocalByDefault()
|
||||
{
|
||||
$this->assertEquals(
|
||||
'a',
|
||||
$this->smarty->fetch('string:{function name=test}{$var="b"}{/function}{$var="a"}{test}{$var}')
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
class TooManyShorthandAttributes949Test extends PHPUnit_Smarty
|
||||
{
|
||||
|
||||
public function testPregMatchAll() {
|
||||
$smarty = new \Smarty\Smarty();
|
||||
$smarty->registerPlugin('modifier', 'var_dump', 'var_dump');
|
||||
$templateStr = "eval:{\$a = 'blah'}{\$b = array()}{if var_dump('', \$a, \$b, 2)|noprint}blah{else}nah{/if}";
|
||||
$this->assertEquals(
|
||||
'nah',
|
||||
$smarty->fetch($templateStr)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -29,12 +29,6 @@ function smarty_function_checkvar($params, \Smarty\Template $template)
|
||||
if (in_array('template', $types) && $ptr instanceof Template) {
|
||||
$output .= "#{$ptr->getSource()->name}:\${$var} =";
|
||||
$output .= $ptr->hasVariable($var) ? preg_replace('/\s/', '', var_export($ptr->getValue($var), true)) : '>unassigned<';
|
||||
$i = 0;
|
||||
while (isset($ptr->_var_stack[ $i ])) {
|
||||
$output .= "#{$ptr->_var_stack[ $i ]['name']} = ";
|
||||
$output .= isset($ptr->_var_stack[ $i ][ 'tpl' ][$var]) ? preg_replace('/\s/', '', var_export($ptr->_var_stack[ $i ][ 'tpl' ][$var]->value, true)) : '>unassigned<';
|
||||
$i ++;
|
||||
}
|
||||
$ptr = $ptr->parent;
|
||||
} elseif (in_array('data', $types) && !($ptr instanceof Template || $ptr instanceof \Smarty\Smarty)) {
|
||||
$output .= "#data:\${$var} =";
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
FROM php:8.3-cli
|
||||
|
||||
## 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,42 @@
|
||||
<?php
|
||||
|
||||
// This takes the *.md files in changelog/ dir and inserts them
|
||||
// right below the '## [Unreleased]' marker in CHANGELOG.md
|
||||
|
||||
$path_to_main_changelog = 'CHANGELOG.md';
|
||||
$marker = '## [Unreleased]';
|
||||
$changelog_files_pattern = 'changelog/*.md';
|
||||
$new_version = $argv[1];
|
||||
|
||||
$file_contents = file_get_contents($path_to_main_changelog);
|
||||
|
||||
foreach (glob($changelog_files_pattern) as $filename) {
|
||||
$content_to_insert = file_get_contents($filename);
|
||||
|
||||
if (!endsWithNewline($content_to_insert)) {
|
||||
$content_to_insert .= "\n";
|
||||
}
|
||||
|
||||
$file_contents = str_replace(
|
||||
$marker,
|
||||
$marker . $content_to_insert,
|
||||
$file_contents
|
||||
);
|
||||
unlink($filename);
|
||||
}
|
||||
|
||||
|
||||
// add the version number and date
|
||||
$file_contents = str_replace(
|
||||
$marker,
|
||||
$marker . sprintf("\n\n## [%s] - %s\n", $new_version, date('Y-m-d')),
|
||||
$file_contents
|
||||
);
|
||||
|
||||
file_put_contents($path_to_main_changelog, $file_contents);
|
||||
|
||||
|
||||
function endsWithNewline($str): bool
|
||||
{
|
||||
return preg_match('/[\r\n]$/', $str) === 1;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
// This takes the Smarty class file and updates the SMARTY_VERSION constant
|
||||
|
||||
$path_to_smarty_class = 'src/Smarty.php';
|
||||
$pattern = "/const SMARTY_VERSION = '[^']+'/";
|
||||
$replacement = "const SMARTY_VERSION = '" . $argv[1] . "'";
|
||||
|
||||
$file_contents = preg_replace($pattern, $replacement, file_get_contents($path_to_smarty_class));
|
||||
|
||||
file_put_contents($path_to_smarty_class, $file_contents);
|
||||
Reference in New Issue
Block a user