mirror of
https://github.com/smarty-php/smarty.git
synced 2026-08-04 04:24:18 +02:00
Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 42b869e3a0 | |||
| 4cb00900d7 | |||
| 204f3bc74e | |||
| 409802db04 | |||
| 1015e5472b | |||
| c7a271323b | |||
| e2cb9873ff | |||
| f4152e9b81 | |||
| 5d0dd09632 | |||
| 9d559827fd | |||
| 5e2a9fbb26 | |||
| 9614a59199 | |||
| ee58a2173b | |||
| 29dd621b53 | |||
| de1bc77f7f | |||
| 326b2da8da | |||
| e0cbbdf6ea | |||
| b4bbc17f1c | |||
| 6e067ed327 | |||
| 3931d8f54b | |||
| d8c1dfe56e | |||
| 6887e55ded | |||
| 642fd69fea | |||
| 17a7d6fb5b | |||
| b96a5c3953 | |||
| 2ff66e0fcc | |||
| d6c4274822 |
@@ -32,6 +32,7 @@ jobs:
|
||||
- "8.0"
|
||||
- "8.1"
|
||||
- "8.2"
|
||||
- "8.3"
|
||||
|
||||
compiler:
|
||||
- default
|
||||
@@ -46,7 +47,9 @@ jobs:
|
||||
- os: ubuntu-latest
|
||||
php-version: "8.2"
|
||||
compiler: jit
|
||||
|
||||
- os: ubuntu-latest
|
||||
php-version: "8.3"
|
||||
compiler: jit
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
@@ -6,8 +6,35 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [4.5.1] - 2024-03-18
|
||||
|
||||
|
||||
## [4.5.0] - 2024-03-18
|
||||
|
||||
|
||||
### Changed
|
||||
- Using unregistered static class methods in expressions now also triggers a deprecation notice because we will drop support for this in the next major release [#813](https://github.com/smarty-php/smarty/issues/813)
|
||||
|
||||
## [4.4.1] - 2024-02-26
|
||||
- Fixed internal release-tooling
|
||||
|
||||
## [4.4.0] - 2024-02-26
|
||||
### Changed
|
||||
- Using the `|implode`, `|json_encode` and `|substr` modifiers does not generate a deprecation warning anymore as they will continue to be supported in v5 [#939](https://github.com/smarty-php/smarty/issues/939)
|
||||
|
||||
### Added
|
||||
- PHP8.3 support [#925](https://github.com/smarty-php/smarty/issues/925)
|
||||
|
||||
### Fixed
|
||||
- Incorrect compilation of expressions when escape_html=true [#930](https://github.com/smarty-php/smarty/pull/930)
|
||||
|
||||
## [4.3.4] - 2023-09-14
|
||||
|
||||
## [4.3.3] - 2023-09-14
|
||||
|
||||
### Fixed
|
||||
- `|strip_tags` does not work if the input is 0 [#890](https://github.com/smarty-php/smarty/issues/890)
|
||||
- Use of negative numbers in {math} equations [#895](https://github.com/smarty-php/smarty/issues/895)
|
||||
|
||||
## [4.3.2] - 2023-07-19
|
||||
|
||||
|
||||
@@ -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 can be run with PHP 7.1 to PHP 8.2.
|
||||
Smarty can be run with PHP 7.1 to PHP 8.3.
|
||||
|
||||
## Installation
|
||||
Smarty versions 3.1.11 or later can be installed with [Composer](https://getcomposer.org/).
|
||||
|
||||
@@ -42,3 +42,8 @@ services:
|
||||
service: base
|
||||
build:
|
||||
dockerfile: ./utilities/testrunners/php82/Dockerfile
|
||||
php83:
|
||||
extends:
|
||||
service: base
|
||||
build:
|
||||
dockerfile: ./utilities/testrunners/php83/Dockerfile
|
||||
@@ -1,7 +1,7 @@
|
||||
# Getting started
|
||||
|
||||
## Requirements
|
||||
Smarty can be run with PHP 7.1 to PHP 8.2.
|
||||
Smarty can be run with PHP 7.1 to PHP 8.3.
|
||||
|
||||
## Installation
|
||||
Smarty can be installed with [Composer](https://getcomposer.org/).
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
# Upgrading from an older version
|
||||
|
||||
## 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 [plugin function](./programmers/plugins/plugins-functions.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](programmers/api-functions/api-get-template-vars.md) instead.
|
||||
- [Smarty::registerResource](programmers/api-functions/api-register-resource.md) no longer accepts an array of callback functions
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -785,6 +785,9 @@ value(res) ::= ns1(c)DOUBLECOLON static_class_access(s). {
|
||||
if (isset($this->smarty->registered_classes[c])) {
|
||||
res = $this->smarty->registered_classes[c].'::'.s[0].s[1];
|
||||
} else {
|
||||
trigger_error('Using unregistered static method "' . c.'::'.s[0] . '" in a template is deprecated and will be ' .
|
||||
'removed in a future release. Use Smarty::registerClass to explicitly register ' .
|
||||
'a class for access.', E_USER_DEPRECATED);
|
||||
res = c.'::'.s[0].s[1];
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -107,7 +107,7 @@ class Smarty extends Smarty_Internal_TemplateBase
|
||||
/**
|
||||
* smarty version
|
||||
*/
|
||||
const SMARTY_VERSION = '4.3.2';
|
||||
const SMARTY_VERSION = '4.5.1';
|
||||
/**
|
||||
* define variable scopes
|
||||
*/
|
||||
|
||||
@@ -67,7 +67,7 @@ function smarty_function_math($params, $template)
|
||||
$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))?)+$/';
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
/**
|
||||
* Smarty plugin
|
||||
*
|
||||
* @package Smarty
|
||||
* @subpackage PluginsModifier
|
||||
*/
|
||||
|
||||
function smarty_modifier_implode($values, $separator = '')
|
||||
{
|
||||
if (is_array($separator)) {
|
||||
return implode((string) ($values ?? ''), (array) $separator);
|
||||
}
|
||||
return implode((string) ($separator ?? ''), (array) $values);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Smarty plugin
|
||||
*
|
||||
* @package Smarty
|
||||
* @subpackage PluginsModifierCompiler
|
||||
*/
|
||||
function smarty_modifiercompiler_json_encode($params) {
|
||||
return 'json_encode(' . $params[0] . (isset($params[1]) ? ', (int) ' . $params[1] : '') . ')';
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Smarty plugin
|
||||
*
|
||||
* @package Smarty
|
||||
* @subpackage PluginsModifierCompiler
|
||||
*/
|
||||
function smarty_modifiercompiler_substr($params) {
|
||||
return 'substr((string) ' . $params[0] . ', (int) ' . $params[1] .
|
||||
(isset($params[2]) ? ', (int) ' . $params[2] : '') . ')';
|
||||
}
|
||||
@@ -109,9 +109,11 @@ class Smarty_Internal_Compile_Private_Modifier extends Smarty_Internal_CompileBa
|
||||
if (!is_object($compiler->smarty->security_policy)
|
||||
|| $compiler->smarty->security_policy->isTrustedPhpModifier($modifier, $compiler)
|
||||
) {
|
||||
trigger_error('Using php-function "' . $modifier . '" as a modifier is deprecated and will be ' .
|
||||
'removed in a future release. Use Smarty::registerPlugin to explicitly register ' .
|
||||
'a custom modifier.', E_USER_DEPRECATED);
|
||||
if (!in_array($modifier, ['time', 'join', 'is_array', 'in_array'])) {
|
||||
trigger_error('Using unregistered function "' . $modifier . '" in a template is deprecated and will be ' .
|
||||
'removed in a future release. Use Smarty::registerPlugin to explicitly register ' .
|
||||
'a custom modifier.', E_USER_DEPRECATED);
|
||||
}
|
||||
$output = "{$modifier}({$params})";
|
||||
}
|
||||
$compiler->known_modifier_type[ $modifier ] = $type;
|
||||
|
||||
@@ -93,7 +93,7 @@ class Smarty_Internal_Compile_Private_Print_Expression extends Smarty_Internal_C
|
||||
}
|
||||
// autoescape html
|
||||
if ($compiler->template->smarty->escape_html) {
|
||||
$output = "htmlspecialchars((string) {$output}, ENT_QUOTES, '" . addslashes(Smarty::$_CHARSET) . "')";
|
||||
$output = "htmlspecialchars((string) ({$output}), ENT_QUOTES, '" . addslashes(Smarty::$_CHARSET) . "')";
|
||||
}
|
||||
// loop over registered filters
|
||||
if (!empty($compiler->template->smarty->registered_filters[ Smarty::FILTER_VARIABLE ])) {
|
||||
|
||||
@@ -94,7 +94,7 @@ class Smarty_Internal_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
|
||||
|
||||
@@ -640,7 +640,17 @@ abstract class Smarty_Internal_TemplateCompilerBase
|
||||
return $func_name . '(' . $parameter[ 0 ] . ')';
|
||||
}
|
||||
} else {
|
||||
return $name . '(' . implode(',', $parameter) . ')';
|
||||
$first_param = array_shift($parameter);
|
||||
$modifier = array_merge(array($name), $parameter);
|
||||
// Now, compile the function call as a modifier
|
||||
return $this->compileTag(
|
||||
'private_modifier',
|
||||
array(),
|
||||
array(
|
||||
'modifierlist' => array($modifier),
|
||||
'value' => $first_param
|
||||
)
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$this->trigger_template_error("unknown function '{$name}'");
|
||||
|
||||
@@ -2425,6 +2425,9 @@ public static $yy_action = array(
|
||||
if (isset($this->smarty->registered_classes[$this->yystack[$this->yyidx + -2]->minor])) {
|
||||
$this->_retvalue = $this->smarty->registered_classes[$this->yystack[$this->yyidx + -2]->minor].'::'.$this->yystack[$this->yyidx + 0]->minor[0].$this->yystack[$this->yyidx + 0]->minor[1];
|
||||
} else {
|
||||
trigger_error('Using unregistered static method "' . $this->yystack[$this->yyidx + -2]->minor.'::'.$this->yystack[$this->yyidx + 0]->minor[0] . '" in a template is deprecated and will be ' .
|
||||
'removed in a future release. Use Smarty::registerClass to explicitly register ' .
|
||||
'a class for access.', E_USER_DEPRECATED);
|
||||
$this->_retvalue = $this->yystack[$this->yyidx + -2]->minor.'::'.$this->yystack[$this->yyidx + 0]->minor[0].$this->yystack[$this->yyidx + 0]->minor[1];
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -253,7 +253,7 @@ class Smarty_Security
|
||||
*
|
||||
* @param string $function_name
|
||||
* @param object $compiler compiler object
|
||||
*
|
||||
* @deprecated
|
||||
* @return boolean true if function is trusted
|
||||
*/
|
||||
public function isTrustedPhpFunction($function_name, $compiler)
|
||||
|
||||
@@ -85,7 +85,7 @@ class Smarty_Template_Compiled extends Smarty_Template_Resource_Base
|
||||
*
|
||||
* @param Smarty_Internal_Template $_template
|
||||
*
|
||||
* @return string
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function render(Smarty_Internal_Template $_template)
|
||||
|
||||
+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';/" libs/Smarty.class.php
|
||||
|
||||
git add CHANGELOG.md libs/Smarty.class.php
|
||||
php utilities/update-changelog.php $1
|
||||
php utilities/update-smarty-version-number.php $1
|
||||
|
||||
git add changelog CHANGELOG.md libs/Smarty.class.php
|
||||
git commit -m "version bump"
|
||||
|
||||
git checkout master
|
||||
git checkout support/4
|
||||
git pull
|
||||
git merge --no-ff "release/$1"
|
||||
git branch -d "release/$1"
|
||||
|
||||
+3
-1
@@ -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'
|
||||
- 'Designers':
|
||||
- 'Basic Syntax':
|
||||
- Introduction: 'designers/language-basic-syntax/index.md'
|
||||
|
||||
+5
-1
@@ -15,7 +15,11 @@
|
||||
timeoutForSmallTests="1"
|
||||
timeoutForMediumTests="10"
|
||||
timeoutForLargeTests="60"
|
||||
verbose="false">
|
||||
verbose="false"
|
||||
convertErrorsToExceptions="true"
|
||||
convertNoticesToExceptions="true"
|
||||
convertWarningsToExceptions="true"
|
||||
convertDeprecationsToExceptions="true">
|
||||
<testsuites>
|
||||
<testsuite name="foo">
|
||||
<directory>./tests/UnitTests/</directory>
|
||||
|
||||
@@ -5,9 +5,13 @@
|
||||
# - ./run-tests-for-all-php-versions.sh --group 20221124
|
||||
# - ./run-tests-for-all-php-versions.sh --exclude-group slow
|
||||
|
||||
docker-compose run php71 ./run-tests.sh $@ && \
|
||||
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 $@
|
||||
COMPOSE_CMD="mutagen-compose"
|
||||
|
||||
$COMPOSE_CMD run --rm php71 ./run-tests.sh $@ && \
|
||||
$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 $@
|
||||
|
||||
@@ -149,7 +149,7 @@ class PHPUnit_Smarty extends PHPUnit\Framework\TestCase
|
||||
$this->smarty->setCacheDir(__DIR__ . '/cache');
|
||||
}
|
||||
|
||||
$this->getSmartyObj();
|
||||
$this->smarty->setErrorReporting(E_ALL &~ E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -30,4 +30,36 @@ 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::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::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));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -49,6 +49,6 @@ class LoadPluginTest extends PHPUnit_Smarty
|
||||
*/
|
||||
public function testLoadPluginSmartyPluginCounter()
|
||||
{
|
||||
$this->assertTrue($this->smarty->loadPlugin('Smarty_Function_Counter') == true);
|
||||
$this->assertTrue($this->smarty->loadPlugin('Smarty_function_counter') == true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ class SecurityTest extends PHPUnit_Smarty
|
||||
*/
|
||||
public function testTrustedPHPFunction()
|
||||
{
|
||||
$this->assertEquals("5", $this->smarty->fetch('string:{assign var=foo value=[1,2,3,4,5]}{sizeof($foo)}'));
|
||||
$this->assertEquals("5", $this->smarty->fetch('string:{assign var=foo value=[1,2,3,4,5]}{count($foo)}'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -75,7 +75,7 @@ class SecurityTest extends PHPUnit_Smarty
|
||||
{
|
||||
$this->smarty->security_policy->php_functions = array('null');
|
||||
$this->smarty->disableSecurity();
|
||||
$this->assertEquals("5", $this->smarty->fetch('string:{assign var=foo value=[1,2,3,4,5]}{sizeof($foo)}'));
|
||||
$this->assertEquals("5", $this->smarty->fetch('string:{assign var=foo value=[1,2,3,4,5]}{count($foo)}'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -46,7 +46,7 @@ class ClearAllAssignTest extends PHPUnit_Smarty
|
||||
*/
|
||||
public function testClearAllAssignInTemplate()
|
||||
{
|
||||
error_reporting((error_reporting() & ~(E_NOTICE | E_USER_NOTICE | E_WARNING)));
|
||||
$this->smarty->setErrorReporting($this->smarty->error_reporting & ~(E_NOTICE | E_USER_NOTICE | E_WARNING));
|
||||
$this->_tpl->clearAllAssign();
|
||||
$this->assertEquals('foobar', $this->smarty->fetch($this->_tpl));
|
||||
}
|
||||
@@ -56,7 +56,7 @@ class ClearAllAssignTest extends PHPUnit_Smarty
|
||||
*/
|
||||
public function testClearAllAssignInData()
|
||||
{
|
||||
error_reporting((error_reporting() & ~(E_NOTICE | E_USER_NOTICE | E_WARNING)));
|
||||
$this->smarty->setErrorReporting($this->smarty->error_reporting & ~(E_NOTICE | E_USER_NOTICE | E_WARNING));
|
||||
$this->_data->clearAllAssign();
|
||||
$this->assertEquals('fooblar', $this->smarty->fetch($this->_tpl));
|
||||
}
|
||||
@@ -66,7 +66,7 @@ class ClearAllAssignTest extends PHPUnit_Smarty
|
||||
*/
|
||||
public function testClearAllAssignInSmarty()
|
||||
{
|
||||
error_reporting((error_reporting() & ~(E_NOTICE | E_USER_NOTICE | E_WARNING)));
|
||||
$this->smarty->setErrorReporting($this->smarty->error_reporting & ~(E_NOTICE | E_USER_NOTICE | E_WARNING));
|
||||
$this->smarty->clearAllAssign();
|
||||
$this->assertEquals('barblar', $this->smarty->fetch($this->_tpl));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
/**
|
||||
* Smarty PHPunit tests of modifier
|
||||
*/
|
||||
|
||||
/**
|
||||
* class for modifier tests
|
||||
*
|
||||
* @runTestsInSeparateProcess
|
||||
* @preserveGlobalState disabled
|
||||
* @backupStaticAttributes enabled
|
||||
*/
|
||||
class PluginModifierImplodeTest extends PHPUnit_Smarty
|
||||
{
|
||||
public function setUp(): void
|
||||
{
|
||||
$this->setUpSmarty(__DIR__);
|
||||
}
|
||||
|
||||
public function testDefault()
|
||||
{
|
||||
$tpl = $this->smarty->createTemplate('string:{""|implode:$v}');
|
||||
$tpl->assign("v", ["1", "2"]);
|
||||
$this->assertEquals("12", $this->smarty->fetch($tpl));
|
||||
}
|
||||
public function testWithSeparator()
|
||||
{
|
||||
$tpl = $this->smarty->createTemplate('string:{","|implode:$v}');
|
||||
$tpl->assign("v", ["a", "b"]);
|
||||
$this->assertEquals("a,b", $this->smarty->fetch($tpl));
|
||||
}
|
||||
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));
|
||||
}
|
||||
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));
|
||||
}
|
||||
}
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
/**
|
||||
* Smarty PHPunit tests of modifier
|
||||
*/
|
||||
|
||||
/**
|
||||
* class for modifier tests
|
||||
*
|
||||
* @runTestsInSeparateProcess
|
||||
* @preserveGlobalState disabled
|
||||
* @backupStaticAttributes enabled
|
||||
*/
|
||||
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,48 @@
|
||||
<?php
|
||||
/**
|
||||
* Smarty PHPunit tests of modifier
|
||||
*/
|
||||
|
||||
/**
|
||||
* class for modifier tests
|
||||
*
|
||||
* @runTestsInSeparateProcess
|
||||
* @preserveGlobalState disabled
|
||||
* @backupStaticAttributes enabled
|
||||
*/
|
||||
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));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -101,6 +101,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();
|
||||
|
||||
@@ -57,6 +57,7 @@ class PhpFunctionTest extends PHPUnit_Smarty
|
||||
public function testEmpty2()
|
||||
{
|
||||
$this->smarty->disableSecurity();
|
||||
$this->smarty->registerPlugin('modifier', 'pass', 'pass');
|
||||
$this->smarty->assign('var', array(null,
|
||||
false,
|
||||
(int) 0,
|
||||
@@ -78,6 +79,7 @@ class PhpFunctionTest extends PHPUnit_Smarty
|
||||
public function testEmpty3()
|
||||
{
|
||||
$this->smarty->disableSecurity();
|
||||
$this->smarty->registerPlugin('modifier', 'pass', 'pass');
|
||||
$this->smarty->assign('var', array(true,
|
||||
(int) 1,
|
||||
(float) 0.1,
|
||||
@@ -114,6 +116,7 @@ class PhpFunctionTest extends PHPUnit_Smarty
|
||||
public function testIsset1()
|
||||
{
|
||||
$this->smarty->disableSecurity();
|
||||
$this->smarty->registerPlugin('modifier', 'pass', 'pass');
|
||||
$this->smarty->assign('isNull', null);
|
||||
$this->smarty->assign('isSet', 1);
|
||||
$this->smarty->assign('arr', array('isNull' => null, 'isSet' => 1));
|
||||
@@ -155,7 +158,7 @@ class PhpFunctionTest extends PHPUnit_Smarty
|
||||
public function testIsset3($strTemplate, $result)
|
||||
{
|
||||
$this->smarty->disableSecurity();
|
||||
|
||||
$this->smarty->registerPlugin('modifier', 'intval', 'intval');
|
||||
$this->smarty->assign('varobject', new TestIsset());
|
||||
$this->smarty->assign('vararray', $vararray = array(
|
||||
'keythatexists' => false,
|
||||
@@ -196,6 +199,105 @@ class PhpFunctionTest extends PHPUnit_Smarty
|
||||
array('{if isset($_varsimple{$key})}true{else}false{/if}', 'true'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests various PHP functions (deprecated)
|
||||
* @dataProvider dataVariousPHPFunctions
|
||||
*/
|
||||
public function testVariousPHPFunctions($strTemplate, $value, $expected) {
|
||||
$this->smarty->disableSecurity();
|
||||
$this->cleanDirs();
|
||||
$this->smarty->assign('value', $value);
|
||||
$this->assertEquals($expected, $this->smarty->fetch('string:' . $strTemplate));
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testIsset3
|
||||
*/
|
||||
public function dataVariousPHPFunctions()
|
||||
{
|
||||
return array(
|
||||
array('{$a = count($value)}{$a}', array(1,2,3), '3'),
|
||||
array('{$a = in_array("b", $value)}{$a}', array(1,'b',3), true),
|
||||
array('{$a = strlen(uniqid())}{$a}', '', 13),
|
||||
array('{$a = date("Y", $value)}{$a}', strtotime("01-01-2030"), 2030),
|
||||
array('{$a = PhpFunctionTest::sayHi($value)}{$a}', 'mario', 'hi mario'),
|
||||
array('{$a = pass($value)}{$a}', 'mario', 'mario'),
|
||||
array('{$a = 1}{$b = Closure::fromCallable($value)}{$a}', 'strlen', 1),
|
||||
);
|
||||
}
|
||||
|
||||
public static function sayHi($value) {
|
||||
return 'hi ' . $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that each function that will not be supported in Smarty 5 does throw an E_USER_DEPRECATED notice.
|
||||
* @dataProvider dataDeprecationNoticesForSmarty5
|
||||
* @deprecated
|
||||
*/
|
||||
public function testDeprecationNoticesForSmarty5($strTemplateSource, $expected = '', $shouldTriggerDeprecationNotice = false) {
|
||||
|
||||
// this overrides the error reporting level set in \PHPUnit_Smarty::setUpSmarty
|
||||
$previousErrorReporting = $this->smarty->error_reporting;
|
||||
$this->smarty->setErrorReporting($previousErrorReporting | E_USER_DEPRECATED);
|
||||
|
||||
$this->smarty->assign('a', 'a');
|
||||
$this->smarty->assign('ar', [1,2]);
|
||||
$this->smarty->assign('f', 3.14);
|
||||
|
||||
$errorMessage = '';
|
||||
|
||||
try {
|
||||
$output = $this->smarty->fetch('string:' . $strTemplateSource);
|
||||
} catch (Exception $e) {
|
||||
$errorMessage = $e->getMessage();
|
||||
}
|
||||
|
||||
if ($shouldTriggerDeprecationNotice) {
|
||||
$this->assertStringContainsString('Using unregistered function', $errorMessage);
|
||||
} else {
|
||||
$this->assertEquals($expected, $output);
|
||||
$this->assertEquals('', $errorMessage);
|
||||
}
|
||||
|
||||
$this->smarty->setErrorReporting($previousErrorReporting);
|
||||
}
|
||||
|
||||
public function dataDeprecationNoticesForSmarty5()
|
||||
{
|
||||
|
||||
return [
|
||||
|
||||
['{if empty($a)}{else}b{/if}', 'b', false],
|
||||
['{json_encode($a)}', '"a"', false],
|
||||
['{nl2br($a)}', 'a', false],
|
||||
['{$a|nl2br}', 'a', false],
|
||||
['{round($f, 1)}', '3.1', false],
|
||||
['{$f|round}', '3', false],
|
||||
['{str_repeat($a, 2)}', 'aa', false],
|
||||
['{$a|str_repeat:3}', 'aaa', false],
|
||||
['{$a|strip_tags}', 'a', false],
|
||||
['{$a|strlen}', '1', false],
|
||||
['{$a|substr:-1}', 'a', false],
|
||||
['{$f|substr:-1}', '4', false],
|
||||
['{$ar|count}', '2', false],
|
||||
['{foreach "."|explode:$f as $n}{$n}{/foreach}', '314', false],
|
||||
['{"-"|implode:$ar}', '1-2', false],
|
||||
['{"-"|join:$ar}', '1-2', false],
|
||||
['{$f|wordwrap:2:"k":true}', "3.k14", false],
|
||||
['{$f|number_format:1:","}', "3,1", false],
|
||||
['{if in_array(1, $ar)}yes{/if}', "yes", false],
|
||||
['{if is_array($ar)}yes{/if}', "yes", false],
|
||||
['{if time() gt 0}yes{/if}', "yes", false],
|
||||
|
||||
['{if array_chunk($ar, 2)}x{else}y{/if}', '', true],
|
||||
['{$a|addslashes}', '', true],
|
||||
['{$a|sha1}', '', true],
|
||||
['{$a|get_parent_class}', '', true],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -299,4 +299,12 @@ class ScopeTest extends PHPUnit_Smarty
|
||||
$this->smarty->assign('scope', 'none');
|
||||
$r = $this->smarty->fetch('test_function_scope.tpl');
|
||||
}
|
||||
|
||||
public function testFunctionScopeIsLocalByDefault()
|
||||
{
|
||||
$r = $this->smarty->fetch('string:{function name=test}{$var="b"}{/function}{$var="a"}{test}{$var}');
|
||||
$this->assertEquals('a', $r);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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 = 'libs/Smarty.class.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