diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 449146c9e..33224fcb6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,6 +31,7 @@ jobs: - "7.4" - "8.0" - "8.1" + - "8.2" compiler: - default @@ -42,6 +43,9 @@ jobs: - os: ubuntu-latest php-version: "8.1" compiler: jit + - os: ubuntu-latest + php-version: "8.2" + compiler: jit steps: - name: Checkout diff --git a/CHANGELOG.md b/CHANGELOG.md index 333035cac..0ccdfd6b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added +- PHP8.2 compatibility [#775](https://github.com/smarty-php/smarty/pull/775) + ### Changed - Include docs and demo in the releases [#799](https://github.com/smarty-php/smarty/issues/799) - Using PHP functions as modifiers now 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) diff --git a/README.md b/README.md index 782f0b2cb..0ef3cfab6 100644 --- a/README.md +++ b/README.md @@ -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.1. +Smarty can be run with PHP 7.1 to PHP 8.2. ## Installation Smarty versions 3.1.11 or later can be installed with [Composer](https://getcomposer.org/). diff --git a/docker-compose.yml b/docker-compose.yml index d46608bff..cc90fb8b5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -38,3 +38,8 @@ services: service: base build: dockerfile: ./utilities/testrunners/php81/Dockerfile + php82: + extends: + service: base + build: + dockerfile: ./utilities/testrunners/php82/Dockerfile diff --git a/docs/getting-started.md b/docs/getting-started.md index de55ffe8e..2a1391f4b 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -2,7 +2,7 @@ What is Smarty? ============== ## Requirements -Smarty can be run with PHP 7.1 to PHP 8.1. +Smarty can be run with PHP 7.1 to PHP 8.2. ## Installation Smarty versions 3.1.11 or later can be installed with [Composer](https://getcomposer.org/). diff --git a/libs/plugins/modifier.escape.php b/libs/plugins/modifier.escape.php index 3ce483827..11e44682e 100644 --- a/libs/plugins/modifier.escape.php +++ b/libs/plugins/modifier.escape.php @@ -23,7 +23,6 @@ */ function smarty_modifier_escape($string, $esc_type = 'html', $char_set = null, $double_encode = true) { - static $_double_encode = true; static $is_loaded_1 = false; static $is_loaded_2 = false; if (!$char_set) { @@ -34,87 +33,15 @@ function smarty_modifier_escape($string, $esc_type = 'html', $char_set = null, $ switch ($esc_type) { case 'html': - if ($_double_encode) { - // php >=5.3.2 - go native - return htmlspecialchars($string, ENT_QUOTES, $char_set, $double_encode); - } else { - if ($double_encode) { - // php <5.2.3 - only handle double encoding - return htmlspecialchars($string, ENT_QUOTES, $char_set); - } else { - // php <5.2.3 - prevent double encoding - $string = preg_replace('!&(#?\w+);!', '%%%SMARTY_START%%%\\1%%%SMARTY_END%%%', $string); - $string = htmlspecialchars($string, ENT_QUOTES, $char_set); - $string = str_replace( - array( - '%%%SMARTY_START%%%', - '%%%SMARTY_END%%%' - ), - array( - '&', - ';' - ), - $string - ); - return $string; - } - } + return htmlspecialchars($string, ENT_QUOTES, $char_set, $double_encode); // no break case 'htmlall': if (Smarty::$_MBSTRING) { - // mb_convert_encoding ignores htmlspecialchars() - if ($_double_encode) { - // php >=5.3.2 - go native - $string = htmlspecialchars($string, ENT_QUOTES, $char_set, $double_encode); - } else { - if ($double_encode) { - // php <5.2.3 - only handle double encoding - $string = htmlspecialchars($string, ENT_QUOTES, $char_set); - } else { - // php <5.2.3 - prevent double encoding - $string = preg_replace('!&(#?\w+);!', '%%%SMARTY_START%%%\\1%%%SMARTY_END%%%', $string); - $string = htmlspecialchars($string, ENT_QUOTES, $char_set); - $string = - str_replace( - array( - '%%%SMARTY_START%%%', - '%%%SMARTY_END%%%' - ), - array( - '&', - ';' - ), - $string - ); - return $string; - } - } - // htmlentities() won't convert everything, so use mb_convert_encoding - return mb_convert_encoding($string, 'HTML-ENTITIES', $char_set); + $string = mb_convert_encoding($string, 'UTF-8', $char_set); + return htmlentities($string, ENT_QUOTES, 'UTF-8', $double_encode); } // no MBString fallback - if ($_double_encode) { - return htmlentities($string, ENT_QUOTES, $char_set, $double_encode); - } else { - if ($double_encode) { - return htmlentities($string, ENT_QUOTES, $char_set); - } else { - $string = preg_replace('!&(#?\w+);!', '%%%SMARTY_START%%%\\1%%%SMARTY_END%%%', $string); - $string = htmlentities($string, ENT_QUOTES, $char_set); - $string = str_replace( - array( - '%%%SMARTY_START%%%', - '%%%SMARTY_END%%%' - ), - array( - '&', - ';' - ), - $string - ); - return $string; - } - } + return htmlentities($string, ENT_QUOTES, $char_set, $double_encode); // no break case 'url': return rawurlencode($string); diff --git a/libs/plugins/modifiercompiler.escape.php b/libs/plugins/modifiercompiler.escape.php index 1fc5e7817..602c3dbfc 100644 --- a/libs/plugins/modifiercompiler.escape.php +++ b/libs/plugins/modifiercompiler.escape.php @@ -18,12 +18,10 @@ * @param Smarty_Internal_TemplateCompilerBase $compiler * * @return string with compiled code - * @throws \SmartyException + * @throws SmartyException */ function smarty_modifiercompiler_escape($params, Smarty_Internal_TemplateCompilerBase $compiler) { - static $_double_encode = true; - static $is_loaded = false; $compiler->template->_checkPlugins( array( array( @@ -41,41 +39,18 @@ function smarty_modifiercompiler_escape($params, Smarty_Internal_TemplateCompile } switch ($esc_type) { case 'html': - if ($_double_encode) { - return 'htmlspecialchars((string)' . $params[ 0 ] . ', ENT_QUOTES, ' . var_export($char_set, true) . ', ' . - var_export($double_encode, true) . ')'; - } elseif ($double_encode) { - return 'htmlspecialchars((string)' . $params[ 0 ] . ', ENT_QUOTES, ' . var_export($char_set, true) . ')'; - } else { - // fall back to modifier.escape.php - } + return 'htmlspecialchars((string)' . $params[ 0 ] . ', ENT_QUOTES, ' . var_export($char_set, true) . ', ' . + var_export($double_encode, true) . ')'; // no break case 'htmlall': if (Smarty::$_MBSTRING) { - if ($_double_encode) { - // php >=5.2.3 - go native - return 'mb_convert_encoding(htmlspecialchars((string)' . $params[ 0 ] . ', ENT_QUOTES, ' . - var_export($char_set, true) . ', ' . var_export($double_encode, true) . - '), "HTML-ENTITIES", ' . var_export($char_set, true) . ')'; - } elseif ($double_encode) { - // php <5.2.3 - only handle double encoding - return 'mb_convert_encoding(htmlspecialchars((string)' . $params[ 0 ] . ', ENT_QUOTES, ' . - var_export($char_set, true) . '), "HTML-ENTITIES", ' . var_export($char_set, true) . ')'; - } else { - // fall back to modifier.escape.php - } + return 'htmlentities(mb_convert_encoding((string)' . $params[ 0 ] . ', \'UTF-8\', ' . + var_export($char_set, true) . '), ENT_QUOTES, \'UTF-8\', ' . + var_export($double_encode, true) . ')'; } // no MBString fallback - if ($_double_encode) { - // php >=5.2.3 - go native - return 'htmlentities((string)' . $params[ 0 ] . ', ENT_QUOTES, ' . var_export($char_set, true) . ', ' . - var_export($double_encode, true) . ')'; - } elseif ($double_encode) { - // php <5.2.3 - only handle double encoding - return 'htmlentities((string)' . $params[ 0 ] . ', ENT_QUOTES, ' . var_export($char_set, true) . ')'; - } else { - // fall back to modifier.escape.php - } + return 'htmlentities((string)' . $params[ 0 ] . ', ENT_QUOTES, ' . var_export($char_set, true) . ', ' . + var_export($double_encode, true) . ')'; // no break case 'url': return 'rawurlencode((string)' . $params[ 0 ] . ')'; diff --git a/libs/plugins/modifiercompiler.unescape.php b/libs/plugins/modifiercompiler.unescape.php index 3438fe3e0..9e1f06d67 100644 --- a/libs/plugins/modifiercompiler.unescape.php +++ b/libs/plugins/modifiercompiler.unescape.php @@ -39,9 +39,9 @@ function smarty_modifiercompiler_unescape($params, Smarty_Internal_TemplateCompi case 'entity': case 'htmlall': if (Smarty::$_MBSTRING) { - return 'mb_convert_encoding(' . $params[ 0 ] . ', ' . $params[ 2 ] . ', \'HTML-ENTITIES\')'; + return 'html_entity_decode(mb_convert_encoding(' . $params[ 0 ] . ', ' . $params[ 2 ] . ', \'UTF-8\'), ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401, ' . $params[ 2 ] . ')'; } - return 'html_entity_decode(' . $params[ 0 ] . ', ENT_NOQUOTES, ' . $params[ 2 ] . ')'; + return 'html_entity_decode(' . $params[ 0 ] . ', ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401, ' . $params[ 2 ] . ')'; case 'html': return 'htmlspecialchars_decode(' . $params[ 0 ] . ', ENT_QUOTES)'; case 'url': diff --git a/libs/sysplugins/smarty_internal_extension_handler.php b/libs/sysplugins/smarty_internal_extension_handler.php index 634ad8315..3ef040ab1 100644 --- a/libs/sysplugins/smarty_internal_extension_handler.php +++ b/libs/sysplugins/smarty_internal_extension_handler.php @@ -36,6 +36,7 @@ * @property Smarty_Internal_Method_RegisterPlugin $registerPlugin * @property mixed|\Smarty_Template_Cached configLoad */ +#[\AllowDynamicProperties] class Smarty_Internal_Extension_Handler { public $objType = null; diff --git a/libs/sysplugins/smarty_internal_runtime_make_nocache.php b/libs/sysplugins/smarty_internal_runtime_make_nocache.php index 53069148d..7994aa048 100644 --- a/libs/sysplugins/smarty_internal_runtime_make_nocache.php +++ b/libs/sysplugins/smarty_internal_runtime_make_nocache.php @@ -22,7 +22,7 @@ public function save(Smarty_Internal_Template $tpl, $var) { if (isset($tpl->tpl_vars[ $var ])) { $export = - preg_replace('/^Smarty_Variable::__set_state[(]|[)]$/', '', var_export($tpl->tpl_vars[ $var ], true)); + preg_replace('/^\\\\?Smarty_Variable::__set_state[(]|[)]$/', '', var_export($tpl->tpl_vars[ $var ], true)); if (preg_match('/(\w+)::__set_state/', $export, $match)) { throw new SmartyException("{make_nocache \${$var}} in template '{$tpl->source->name}': variable does contain object '{$match[1]}' not implementing method '__set_state'"); } diff --git a/libs/sysplugins/smarty_internal_template.php b/libs/sysplugins/smarty_internal_template.php index bf627ce72..72d1d52e0 100644 --- a/libs/sysplugins/smarty_internal_template.php +++ b/libs/sysplugins/smarty_internal_template.php @@ -24,6 +24,7 @@ * * @method bool mustCompile() */ +#[\AllowDynamicProperties] class Smarty_Internal_Template extends Smarty_Internal_TemplateBase { /** diff --git a/libs/sysplugins/smarty_security.php b/libs/sysplugins/smarty_security.php index 974c63529..97cd0521d 100644 --- a/libs/sysplugins/smarty_security.php +++ b/libs/sysplugins/smarty_security.php @@ -19,6 +19,7 @@ /** * This class does contain the security settings */ +#[\AllowDynamicProperties] class Smarty_Security { diff --git a/libs/sysplugins/smarty_variable.php b/libs/sysplugins/smarty_variable.php index 914d99bd7..6a534228b 100644 --- a/libs/sysplugins/smarty_variable.php +++ b/libs/sysplugins/smarty_variable.php @@ -7,6 +7,7 @@ * @package Smarty * @subpackage Template */ +#[\AllowDynamicProperties] class Smarty_Variable { /** diff --git a/tests/UnitTests/ResourceTests/Stream/StreamResourceTest.php b/tests/UnitTests/ResourceTests/Stream/StreamResourceTest.php index 57dbd9eb8..e5eedcc18 100644 --- a/tests/UnitTests/ResourceTests/Stream/StreamResourceTest.php +++ b/tests/UnitTests/ResourceTests/Stream/StreamResourceTest.php @@ -206,6 +206,7 @@ public function testSmartyIsCached() } } +#[AllowDynamicProperties] class ResourceStream { private $position; diff --git a/tests/UnitTests/SecurityTests/SecurityTest.php b/tests/UnitTests/SecurityTests/SecurityTest.php index e1469a8d6..7631a0a6b 100644 --- a/tests/UnitTests/SecurityTests/SecurityTest.php +++ b/tests/UnitTests/SecurityTests/SecurityTest.php @@ -391,6 +391,7 @@ class Security extends Smarty_Security { } +#[AllowDynamicProperties] class ResourceStreamSecurity { private $position; diff --git a/tests/UnitTests/SmartyMethodsTests/RegisterObject/CompileRegisteredObjectFunctionTest.php b/tests/UnitTests/SmartyMethodsTests/RegisterObject/CompileRegisteredObjectFunctionTest.php index 63a7b52dd..eaee13600 100644 --- a/tests/UnitTests/SmartyMethodsTests/RegisterObject/CompileRegisteredObjectFunctionTest.php +++ b/tests/UnitTests/SmartyMethodsTests/RegisterObject/CompileRegisteredObjectFunctionTest.php @@ -15,6 +15,11 @@ */ class CompileRegisteredObjectFunctionTest extends PHPUnit_Smarty { + /** + * @var RegObject + */ + private $object; + public function setUp(): void { $this->setUpSmarty(__DIR__); diff --git a/tests/UnitTests/TemplateSource/TagTests/PluginModifier/PluginModifierCharsetTest.php b/tests/UnitTests/TemplateSource/TagTests/PluginModifier/PluginModifierCharsetTest.php index 423b593c0..92ff95141 100644 --- a/tests/UnitTests/TemplateSource/TagTests/PluginModifier/PluginModifierCharsetTest.php +++ b/tests/UnitTests/TemplateSource/TagTests/PluginModifier/PluginModifierCharsetTest.php @@ -23,7 +23,7 @@ public function setUp(): void public function testToLatin1() { $encoded = "hällö wörld 1"; - $result = utf8_decode($encoded); + $result = mb_convert_encoding($encoded, 'ISO-8859-1', 'UTF-8'); $tpl = $this->smarty->createTemplate('string:{"' . $encoded . '"|to_charset}'); $this->assertEquals(str_replace("\r", '', $result), $tpl->fetch()); } @@ -33,7 +33,7 @@ public function testToLatin1WithoutMbstring() Smarty::$_MBSTRING = false; $this->smarty->setCompileId('mb'); $encoded = "hällö wörld 2"; - $result = utf8_decode($encoded); + $result = mb_convert_encoding($encoded, 'ISO-8859-1', 'UTF-8'); $tpl = $this->smarty->createTemplate('string:{"' . $encoded . '"|to_charset}'); $this->assertEquals($encoded, $tpl->fetch()); Smarty::$_MBSTRING = true; @@ -42,7 +42,7 @@ public function testToLatin1WithoutMbstring() public function testFromLatin1() { $result = "hällö wörld 3"; - $encoded = utf8_decode($result); + $encoded = mb_convert_encoding($result, 'ISO-8859-1', 'UTF-8'); $tpl = $this->smarty->createTemplate('string:{"' . $encoded . '"|from_charset}'); $this->assertEquals(str_replace("\r", '', $result), $tpl->fetch()); } @@ -52,7 +52,7 @@ public function testFromLatin1WithoutMbstring() Smarty::$_MBSTRING = false; $this->smarty->setCompileId('mb'); $result = "hällö wörld 4"; - $encoded = utf8_decode($result); + $encoded = mb_convert_encoding($result, 'ISO-8859-1', 'UTF-8'); $tpl = $this->smarty->createTemplate('string:{"' . $encoded . '"|from_charset}'); $this->assertEquals($encoded, $tpl->fetch()); Smarty::$_MBSTRING = true; diff --git a/tests/UnitTests/TemplateSource/TagTests/PluginModifier/PluginModifierEscapeTest.php b/tests/UnitTests/TemplateSource/TagTests/PluginModifier/PluginModifierEscapeTest.php index 0782a01cb..309a71ab8 100644 --- a/tests/UnitTests/TemplateSource/TagTests/PluginModifier/PluginModifierEscapeTest.php +++ b/tests/UnitTests/TemplateSource/TagTests/PluginModifier/PluginModifierEscapeTest.php @@ -20,12 +20,19 @@ public function setUp(): void $this->setUpSmarty(__DIR__); } - public function testHtml() + public function testHtmlCompiled() { $tpl = $this->smarty->createTemplate('string:{"I\'m some to ä be \"escaped\" or ©"|escape:"html"}'); $this->assertEquals("I'm some <html> to ä be "escaped" or &copy;", $this->smarty->fetch($tpl)); } + public function testHtmlModifier() + { + $tpl = $this->smarty->createTemplate('string:{"I\'m some to ä be \"escaped\" or ©"|escape:$mode}'); + $this->smarty->assign('mode', 'html'); + $this->assertEquals("I'm some <html> to ä be "escaped" or &copy;", $this->smarty->fetch($tpl)); + } + public function testHtmlWithoutMbstring() { Smarty::$_MBSTRING = false;$this->smarty->setCompileId('mb'); @@ -48,13 +55,20 @@ public function testHtmlDoubleWithoutMbstring() Smarty::$_MBSTRING = true; } - public function testHtmlall() + public function testHtmlallCompiled() { $tpl = $this->smarty->createTemplate('string:{"I\'m some to ä be \"escaped\" or ©"|escape:"htmlall"}'); $this->assertEquals("I'm some <html> to ä be "escaped" or &copy;", $this->smarty->fetch($tpl)); } - public function testHtmlallWithoutMbstring() + public function testHtmlallModifier() + { + $tpl = $this->smarty->createTemplate('string:{"I\'m some to ä be \"escaped\" or ©"|escape:$mode}'); + $this->smarty->assign('mode', 'htmlall'); + $this->assertEquals("I'm some <html> to ä be "escaped" or &copy;", $this->smarty->fetch($tpl)); + } + + public function testHtmlallWithoutMbstringCompiled() { Smarty::$_MBSTRING = false;$this->smarty->setCompileId('mb'); $tpl = $this->smarty->createTemplate('string:{"I\'m some to ä be \"escaped\" or ©"|escape:"htmlall"}'); @@ -62,6 +76,15 @@ public function testHtmlallWithoutMbstring() Smarty::$_MBSTRING = true; } + public function testHtmlallWithoutMbstringModifier() + { + Smarty::$_MBSTRING = false;$this->smarty->setCompileId('mb'); + $tpl = $this->smarty->createTemplate('string:{"I\'m some to ä be \"escaped\" or ©"|escape:$mode}'); + $this->smarty->assign('mode', 'htmlall'); + $this->assertEquals("I'm some <html> to ä be "escaped" or &copy;", $this->smarty->fetch($tpl)); + Smarty::$_MBSTRING = true; + } + public function testHtmlallDouble() { $tpl = $this->smarty->createTemplate('string:{"I\'m some to ä be \"escaped\" or ©"|escape:"htmlall":null:false}'); @@ -76,12 +99,19 @@ public function testHtmlallDoubleWithoutMbstring() Smarty::$_MBSTRING = true; } - public function testUrl() + public function testUrlCompiled() { $tpl = $this->smarty->createTemplate('string:{"http://some.encoded.com/url?parts#foo"|escape:"url"}'); $this->assertEquals("http%3A%2F%2Fsome.encoded.com%2Furl%3Fparts%23foo", $this->smarty->fetch($tpl)); } + public function testUrlModifier() + { + $tpl = $this->smarty->createTemplate('string:{"http://some.encoded.com/url?parts#foo"|escape:$mode}'); + $this->smarty->assign('mode', 'url'); + $this->assertEquals("http%3A%2F%2Fsome.encoded.com%2Furl%3Fparts%23foo", $this->smarty->fetch($tpl)); + } + public function testUrlWithoutMbstring() { Smarty::$_MBSTRING = false;$this->smarty->setCompileId('mb'); @@ -203,7 +233,7 @@ public function testNonstd() public function testNonstdWithoutMbstring() { Smarty::$_MBSTRING = false;$this->smarty->setCompileId('mb'); - $tpl = $this->smarty->createTemplate('string:{"' . utf8_decode('sma\'rty@»example«.com') . '"|escape:"nonstd"}'); + $tpl = $this->smarty->createTemplate('string:{"' . mb_convert_encoding('sma\'rty@»example«.com', 'ISO-8859-1', 'UTF-8') . '"|escape:"nonstd"}'); $this->assertEquals("sma'rty@»example«.com", $this->smarty->fetch($tpl)); Smarty::$_MBSTRING = true; } diff --git a/tests/UnitTests/TemplateSource/TagTests/PluginModifier/PluginModifierStripTest.php b/tests/UnitTests/TemplateSource/TagTests/PluginModifier/PluginModifierStripTest.php index fbef16b0a..ab1a43849 100644 --- a/tests/UnitTests/TemplateSource/TagTests/PluginModifier/PluginModifierStripTest.php +++ b/tests/UnitTests/TemplateSource/TagTests/PluginModifier/PluginModifierStripTest.php @@ -30,7 +30,7 @@ public function testUnicodeSpaces() { // Some Unicode Spaces $string = " hello spaced       words "; - $string = mb_convert_encoding($string, 'UTF-8', "HTML-ENTITIES"); + $string = html_entity_decode($string, ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401, 'UTF-8'); $tpl = $this->smarty->createTemplate('string:{"' . $string . '"|strip}'); $this->assertEquals(" hello spaced words ", $this->smarty->fetch($tpl)); } diff --git a/tests/UnitTests/TemplateSource/TagTests/PluginModifier/PluginModifierUnescapeTest.php b/tests/UnitTests/TemplateSource/TagTests/PluginModifier/PluginModifierUnescapeTest.php index e3e4ac6b2..2fdefb2eb 100644 --- a/tests/UnitTests/TemplateSource/TagTests/PluginModifier/PluginModifierUnescapeTest.php +++ b/tests/UnitTests/TemplateSource/TagTests/PluginModifier/PluginModifierUnescapeTest.php @@ -40,8 +40,8 @@ public function testHtmlWithoutMbstring() public function testHtmlall() { - $encoded = "aäЗдра><&amp;ääвсствуйте"; - $result = "aäЗдра><&ääвсствуйте"; + $encoded = "'"aäЗдра><&amp;ääвсствуйте"; + $result = "'\"aäЗдра><&ääвсствуйте"; $tpl = $this->smarty->createTemplate('string:{"' . $encoded . '"|unescape:"htmlall"}'); $this->assertEquals($result, $this->smarty->fetch($tpl)); } @@ -49,8 +49,8 @@ public function testHtmlall() public function testHtmlallWithoutMbstring() { Smarty::$_MBSTRING = false;$this->smarty->setCompileId('mb'); - $encoded = "aäЗдра><&amp;ääвсствуйте"; - $result = "aäЗдра><&ääвсствуйте"; + $encoded = "'"aäЗдра><&amp;ääвсствуйте"; + $result = "'\"aäЗдра><&ääвсствуйте"; $tpl = $this->smarty->createTemplate('string:{"' . $encoded . '"|unescape:"htmlall"}'); $this->assertEquals($result, $this->smarty->fetch($tpl)); Smarty::$_MBSTRING = true; diff --git a/tests/UnitTests/TemplateSource/ValueTests/Variables/Stream/StreamVariableTest.php b/tests/UnitTests/TemplateSource/ValueTests/Variables/Stream/StreamVariableTest.php index feca410e6..c832fc70c 100644 --- a/tests/UnitTests/TemplateSource/ValueTests/Variables/Stream/StreamVariableTest.php +++ b/tests/UnitTests/TemplateSource/ValueTests/Variables/Stream/StreamVariableTest.php @@ -68,6 +68,7 @@ public function testStreamVariable3() // } } +#[AllowDynamicProperties] class VariableStream { private $position; diff --git a/utilities/testrunners/php82/Dockerfile b/utilities/testrunners/php82/Dockerfile new file mode 100644 index 000000000..6b7392ea8 --- /dev/null +++ b/utilities/testrunners/php82/Dockerfile @@ -0,0 +1,10 @@ +FROM php:8.2-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