diff --git a/composer.lock b/composer.lock index 19941a9e7..f493e8db6 100644 --- a/composer.lock +++ b/composer.lock @@ -1024,6 +1024,82 @@ ], "time": "2024-01-29T20:11:03+00:00" }, + { + "name": "symfony/polyfill-php81", + "version": "v1.30.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php81.git", + "reference": "3fb075789fb91f9ad9af537c4012d523085bd5af" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/3fb075789fb91f9ad9af537c4012d523085bd5af", + "reference": "3fb075789fb91f9ad9af537c4012d523085bd5af", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php81\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php81/tree/v1.30.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-06-19T12:30:46+00:00" + }, { "name": "symfony/polyfill-php83", "version": "v1.29.0", @@ -1276,16 +1352,16 @@ }, { "name": "twig/twig", - "version": "v3.10.3", + "version": "v3.11.0", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "67f29781ffafa520b0bbfbd8384674b42db04572" + "reference": "e80fb8ebba85c7341a97a9ebf825d7fd4b77708d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/67f29781ffafa520b0bbfbd8384674b42db04572", - "reference": "67f29781ffafa520b0bbfbd8384674b42db04572", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/e80fb8ebba85c7341a97a9ebf825d7fd4b77708d", + "reference": "e80fb8ebba85c7341a97a9ebf825d7fd4b77708d", "shasum": "" }, "require": { @@ -1293,7 +1369,8 @@ "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-ctype": "^1.8", "symfony/polyfill-mbstring": "^1.3", - "symfony/polyfill-php80": "^1.22" + "symfony/polyfill-php80": "^1.22", + "symfony/polyfill-php81": "^1.29" }, "require-dev": { "psr/container": "^1.0|^2.0", @@ -1339,7 +1416,7 @@ ], "support": { "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v3.10.3" + "source": "https://github.com/twigphp/Twig/tree/v3.11.0" }, "funding": [ { @@ -1351,7 +1428,7 @@ "type": "tidelift" } ], - "time": "2024-05-16T10:04:27+00:00" + "time": "2024-08-08T16:15:16+00:00" }, { "name": "zoujingli/wechat-developer", diff --git a/upload/system/storage/vendor/composer/autoload_classmap.php b/upload/system/storage/vendor/composer/autoload_classmap.php index 8599552ab..8bfe0d3fb 100644 --- a/upload/system/storage/vendor/composer/autoload_classmap.php +++ b/upload/system/storage/vendor/composer/autoload_classmap.php @@ -7,6 +7,7 @@ return array( 'Attribute' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Attribute.php', + 'CURLStringFile' => $vendorDir . '/symfony/polyfill-php81/Resources/stubs/CURLStringFile.php', 'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php', 'DateError' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/DateError.php', 'DateException' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/DateException.php', @@ -19,6 +20,7 @@ 'DateRangeError' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/DateRangeError.php', 'Override' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/Override.php', 'PhpToken' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php', + 'ReturnTypeWillChange' => $vendorDir . '/symfony/polyfill-php81/Resources/stubs/ReturnTypeWillChange.php', 'SQLite3Exception' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/SQLite3Exception.php', 'Stringable' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Stringable.php', 'UnhandledMatchError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php', diff --git a/upload/system/storage/vendor/composer/autoload_files.php b/upload/system/storage/vendor/composer/autoload_files.php index 54003c4c7..95c41dc18 100644 --- a/upload/system/storage/vendor/composer/autoload_files.php +++ b/upload/system/storage/vendor/composer/autoload_files.php @@ -13,6 +13,7 @@ '320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php', '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php', '662a729f963d39afe703c9d9b7ab4a8c' => $vendorDir . '/symfony/polyfill-php83/bootstrap.php', + '23c18046f52bef3eea034657bafda50f' => $vendorDir . '/symfony/polyfill-php81/bootstrap.php', '89efb1254ef2d1c5d80096acd12c4098' => $vendorDir . '/twig/twig/src/Resources/core.php', 'ffecb95d45175fd40f75be8a23b34f90' => $vendorDir . '/twig/twig/src/Resources/debug.php', 'c7baa00073ee9c61edf148c51917cfb4' => $vendorDir . '/twig/twig/src/Resources/escaper.php', diff --git a/upload/system/storage/vendor/composer/autoload_psr4.php b/upload/system/storage/vendor/composer/autoload_psr4.php index 0602e2b5c..313d5f25e 100644 --- a/upload/system/storage/vendor/composer/autoload_psr4.php +++ b/upload/system/storage/vendor/composer/autoload_psr4.php @@ -13,6 +13,7 @@ 'Twig\\' => array($vendorDir . '/twig/twig/src'), 'Tools\\PHPStan\\' => array($baseDir . '/tools/phpstan'), 'Symfony\\Polyfill\\Php83\\' => array($vendorDir . '/symfony/polyfill-php83'), + 'Symfony\\Polyfill\\Php81\\' => array($vendorDir . '/symfony/polyfill-php81'), 'Symfony\\Polyfill\\Php80\\' => array($vendorDir . '/symfony/polyfill-php80'), 'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'), 'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'), diff --git a/upload/system/storage/vendor/composer/autoload_static.php b/upload/system/storage/vendor/composer/autoload_static.php index b3a605878..9beecd570 100644 --- a/upload/system/storage/vendor/composer/autoload_static.php +++ b/upload/system/storage/vendor/composer/autoload_static.php @@ -14,6 +14,7 @@ class ComposerStaticInit723df5bcd9366cc0d09a11e95c1b3994 '320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php', '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php', '662a729f963d39afe703c9d9b7ab4a8c' => __DIR__ . '/..' . '/symfony/polyfill-php83/bootstrap.php', + '23c18046f52bef3eea034657bafda50f' => __DIR__ . '/..' . '/symfony/polyfill-php81/bootstrap.php', '89efb1254ef2d1c5d80096acd12c4098' => __DIR__ . '/..' . '/twig/twig/src/Resources/core.php', 'ffecb95d45175fd40f75be8a23b34f90' => __DIR__ . '/..' . '/twig/twig/src/Resources/debug.php', 'c7baa00073ee9c61edf148c51917cfb4' => __DIR__ . '/..' . '/twig/twig/src/Resources/escaper.php', @@ -36,6 +37,7 @@ class ComposerStaticInit723df5bcd9366cc0d09a11e95c1b3994 'S' => array ( 'Symfony\\Polyfill\\Php83\\' => 23, + 'Symfony\\Polyfill\\Php81\\' => 23, 'Symfony\\Polyfill\\Php80\\' => 23, 'Symfony\\Polyfill\\Mbstring\\' => 26, 'Symfony\\Polyfill\\Ctype\\' => 23, @@ -94,6 +96,10 @@ class ComposerStaticInit723df5bcd9366cc0d09a11e95c1b3994 array ( 0 => __DIR__ . '/..' . '/symfony/polyfill-php83', ), + 'Symfony\\Polyfill\\Php81\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/polyfill-php81', + ), 'Symfony\\Polyfill\\Php80\\' => array ( 0 => __DIR__ . '/..' . '/symfony/polyfill-php80', @@ -155,6 +161,7 @@ class ComposerStaticInit723df5bcd9366cc0d09a11e95c1b3994 public static $classMap = array ( 'Attribute' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Attribute.php', + 'CURLStringFile' => __DIR__ . '/..' . '/symfony/polyfill-php81/Resources/stubs/CURLStringFile.php', 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php', 'DateError' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/DateError.php', 'DateException' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/DateException.php', @@ -167,6 +174,7 @@ class ComposerStaticInit723df5bcd9366cc0d09a11e95c1b3994 'DateRangeError' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/DateRangeError.php', 'Override' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/Override.php', 'PhpToken' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php', + 'ReturnTypeWillChange' => __DIR__ . '/..' . '/symfony/polyfill-php81/Resources/stubs/ReturnTypeWillChange.php', 'SQLite3Exception' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/SQLite3Exception.php', 'Stringable' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Stringable.php', 'UnhandledMatchError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php', diff --git a/upload/system/storage/vendor/composer/installed.json b/upload/system/storage/vendor/composer/installed.json index f90c54a08..b6f3fd9b8 100644 --- a/upload/system/storage/vendor/composer/installed.json +++ b/upload/system/storage/vendor/composer/installed.json @@ -1060,6 +1060,85 @@ ], "install-path": "../symfony/polyfill-php80" }, + { + "name": "symfony/polyfill-php81", + "version": "v1.30.0", + "version_normalized": "1.30.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php81.git", + "reference": "3fb075789fb91f9ad9af537c4012d523085bd5af" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/3fb075789fb91f9ad9af537c4012d523085bd5af", + "reference": "3fb075789fb91f9ad9af537c4012d523085bd5af", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "time": "2024-06-19T12:30:46+00:00", + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "installation-source": "dist", + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php81\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php81/tree/v1.30.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/polyfill-php81" + }, { "name": "symfony/polyfill-php83", "version": "v1.29.0", @@ -1321,17 +1400,17 @@ }, { "name": "twig/twig", - "version": "v3.10.3", - "version_normalized": "3.10.3.0", + "version": "v3.11.0", + "version_normalized": "3.11.0.0", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "67f29781ffafa520b0bbfbd8384674b42db04572" + "reference": "e80fb8ebba85c7341a97a9ebf825d7fd4b77708d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/67f29781ffafa520b0bbfbd8384674b42db04572", - "reference": "67f29781ffafa520b0bbfbd8384674b42db04572", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/e80fb8ebba85c7341a97a9ebf825d7fd4b77708d", + "reference": "e80fb8ebba85c7341a97a9ebf825d7fd4b77708d", "shasum": "" }, "require": { @@ -1339,13 +1418,14 @@ "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-ctype": "^1.8", "symfony/polyfill-mbstring": "^1.3", - "symfony/polyfill-php80": "^1.22" + "symfony/polyfill-php80": "^1.22", + "symfony/polyfill-php81": "^1.29" }, "require-dev": { "psr/container": "^1.0|^2.0", "symfony/phpunit-bridge": "^5.4.9|^6.4|^7.0" }, - "time": "2024-05-16T10:04:27+00:00", + "time": "2024-08-08T16:15:16+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -1387,7 +1467,7 @@ ], "support": { "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v3.10.3" + "source": "https://github.com/twigphp/Twig/tree/v3.11.0" }, "funding": [ { diff --git a/upload/system/storage/vendor/composer/installed.php b/upload/system/storage/vendor/composer/installed.php index 15f480517..51539ab5d 100644 --- a/upload/system/storage/vendor/composer/installed.php +++ b/upload/system/storage/vendor/composer/installed.php @@ -3,7 +3,7 @@ 'name' => 'opencart/opencart-3', 'pretty_version' => 'dev-main', 'version' => 'dev-main', - 'reference' => '0af4476208ead002238873406912b850e6dc14ab', + 'reference' => '02de2c4f0c4931886b61604f44332c3c91d8aa8e', 'type' => 'project', 'install_path' => __DIR__ . '/../../../../../', 'aliases' => array(), @@ -58,7 +58,7 @@ 'opencart/opencart-3' => array( 'pretty_version' => 'dev-main', 'version' => 'dev-main', - 'reference' => '0af4476208ead002238873406912b850e6dc14ab', + 'reference' => '02de2c4f0c4931886b61604f44332c3c91d8aa8e', 'type' => 'project', 'install_path' => __DIR__ . '/../../../../../', 'aliases' => array(), @@ -163,6 +163,15 @@ 'aliases' => array(), 'dev_requirement' => false, ), + 'symfony/polyfill-php81' => array( + 'pretty_version' => 'v1.30.0', + 'version' => '1.30.0.0', + 'reference' => '3fb075789fb91f9ad9af537c4012d523085bd5af', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/polyfill-php81', + 'aliases' => array(), + 'dev_requirement' => false, + ), 'symfony/polyfill-php83' => array( 'pretty_version' => 'v1.29.0', 'version' => '1.29.0.0', @@ -191,9 +200,9 @@ 'dev_requirement' => false, ), 'twig/twig' => array( - 'pretty_version' => 'v3.10.3', - 'version' => '3.10.3.0', - 'reference' => '67f29781ffafa520b0bbfbd8384674b42db04572', + 'pretty_version' => 'v3.11.0', + 'version' => '3.11.0.0', + 'reference' => 'e80fb8ebba85c7341a97a9ebf825d7fd4b77708d', 'type' => 'library', 'install_path' => __DIR__ . '/../twig/twig', 'aliases' => array(), diff --git a/upload/system/storage/vendor/symfony/polyfill-php81/LICENSE b/upload/system/storage/vendor/symfony/polyfill-php81/LICENSE new file mode 100644 index 000000000..99c6bdf35 --- /dev/null +++ b/upload/system/storage/vendor/symfony/polyfill-php81/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2021-present Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/upload/system/storage/vendor/symfony/polyfill-php81/Php81.php b/upload/system/storage/vendor/symfony/polyfill-php81/Php81.php new file mode 100644 index 000000000..f0507b765 --- /dev/null +++ b/upload/system/storage/vendor/symfony/polyfill-php81/Php81.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Polyfill\Php81; + +/** + * @author Nicolas Grekas + * + * @internal + */ +final class Php81 +{ + public static function array_is_list(array $array): bool + { + if ([] === $array || $array === array_values($array)) { + return true; + } + + $nextKey = -1; + + foreach ($array as $k => $v) { + if ($k !== ++$nextKey) { + return false; + } + } + + return true; + } +} diff --git a/upload/system/storage/vendor/symfony/polyfill-php81/README.md b/upload/system/storage/vendor/symfony/polyfill-php81/README.md new file mode 100644 index 000000000..c07ef7820 --- /dev/null +++ b/upload/system/storage/vendor/symfony/polyfill-php81/README.md @@ -0,0 +1,18 @@ +Symfony Polyfill / Php81 +======================== + +This component provides features added to PHP 8.1 core: + +- [`array_is_list`](https://php.net/array_is_list) +- [`enum_exists`](https://php.net/enum-exists) +- [`MYSQLI_REFRESH_REPLICA`](https://php.net/mysqli.constants#constantmysqli-refresh-replica) constant +- [`ReturnTypeWillChange`](https://wiki.php.net/rfc/internal_method_return_types) +- [`CURLStringFile`](https://php.net/CURLStringFile) (but only if PHP >= 7.4 is used) + +More information can be found in the +[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md). + +License +======= + +This library is released under the [MIT license](LICENSE). diff --git a/upload/system/storage/vendor/symfony/polyfill-php81/Resources/stubs/CURLStringFile.php b/upload/system/storage/vendor/symfony/polyfill-php81/Resources/stubs/CURLStringFile.php new file mode 100644 index 000000000..5ff93fcaf --- /dev/null +++ b/upload/system/storage/vendor/symfony/polyfill-php81/Resources/stubs/CURLStringFile.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +if (\PHP_VERSION_ID >= 70400 && extension_loaded('curl')) { + /** + * @property string $data + */ + class CURLStringFile extends CURLFile + { + private $data; + + public function __construct(string $data, string $postname, string $mime = 'application/octet-stream') + { + $this->data = $data; + parent::__construct('data://application/octet-stream;base64,'.base64_encode($data), $mime, $postname); + } + + public function __set(string $name, $value): void + { + if ('data' !== $name) { + $this->$name = $value; + + return; + } + + if (is_object($value) ? !method_exists($value, '__toString') : !is_scalar($value)) { + throw new TypeError('Cannot assign '.gettype($value).' to property CURLStringFile::$data of type string'); + } + + $this->name = 'data://application/octet-stream;base64,'.base64_encode($value); + } + + public function __isset(string $name): bool + { + return isset($this->$name); + } + + public function &__get(string $name) + { + return $this->$name; + } + } +} diff --git a/upload/system/storage/vendor/symfony/polyfill-php81/Resources/stubs/ReturnTypeWillChange.php b/upload/system/storage/vendor/symfony/polyfill-php81/Resources/stubs/ReturnTypeWillChange.php new file mode 100644 index 000000000..cb7720a8d --- /dev/null +++ b/upload/system/storage/vendor/symfony/polyfill-php81/Resources/stubs/ReturnTypeWillChange.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +if (\PHP_VERSION_ID < 80100) { + #[Attribute(Attribute::TARGET_METHOD)] + final class ReturnTypeWillChange + { + public function __construct() + { + } + } +} diff --git a/upload/system/storage/vendor/symfony/polyfill-php81/bootstrap.php b/upload/system/storage/vendor/symfony/polyfill-php81/bootstrap.php new file mode 100644 index 000000000..9f872e02f --- /dev/null +++ b/upload/system/storage/vendor/symfony/polyfill-php81/bootstrap.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Polyfill\Php81 as p; + +if (\PHP_VERSION_ID >= 80100) { + return; +} + +if (defined('MYSQLI_REFRESH_SLAVE') && !defined('MYSQLI_REFRESH_REPLICA')) { + define('MYSQLI_REFRESH_REPLICA', 64); +} + +if (!function_exists('array_is_list')) { + function array_is_list(array $array): bool { return p\Php81::array_is_list($array); } +} + +if (!function_exists('enum_exists')) { + function enum_exists(string $enum, bool $autoload = true): bool { return $autoload && class_exists($enum) && false; } +} diff --git a/upload/system/storage/vendor/symfony/polyfill-php81/composer.json b/upload/system/storage/vendor/symfony/polyfill-php81/composer.json new file mode 100644 index 000000000..381af79ac --- /dev/null +++ b/upload/system/storage/vendor/symfony/polyfill-php81/composer.json @@ -0,0 +1,33 @@ +{ + "name": "symfony/polyfill-php81", + "type": "library", + "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", + "keywords": ["polyfill", "shim", "compatibility", "portable"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=7.1" + }, + "autoload": { + "psr-4": { "Symfony\\Polyfill\\Php81\\": "" }, + "files": [ "bootstrap.php" ], + "classmap": [ "Resources/stubs" ] + }, + "minimum-stability": "dev", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + } +} diff --git a/upload/system/storage/vendor/twig/twig/CHANGELOG b/upload/system/storage/vendor/twig/twig/CHANGELOG index aecaab239..dd776e083 100644 --- a/upload/system/storage/vendor/twig/twig/CHANGELOG +++ b/upload/system/storage/vendor/twig/twig/CHANGELOG @@ -1,3 +1,24 @@ +# 3.11.0 (2024-08-08) + + * Add `Twig\Cache\ChainCache` and `Twig\Cache\ReadOnlyFilesystemCache` + * Add the possibility to deprecate attributes and nodes on `Node` + * Add the possibility to add a package and a version to the `deprecated` tag + * Add the possibility to add a package for filter/function/test deprecations + * Mark `ConstantExpression` as being `@final` + * Add the `find` filter + * Fix optimizer mode validation in `OptimizerNodeVisitor` + * Add the possibility to yield from a generator in `PrintNode` + * Add the `shuffle` filter + * Add the `singular` and `plural` filters in `StringExtension` + * Deprecate the second argument of `Twig\Node\Expression\CallExpression::compileArguments()` + * Deprecate `Twig\ExpressionParser\parseHashExpression()` in favor of + `Twig\ExpressionParser::parseMappingExpression()` + * Deprecate `Twig\ExpressionParser\parseArrayExpression()` in favor of + `Twig\ExpressionParser::parseSequenceExpression()` + * Add `sequence` and `mapping` tests + * Deprecate `Twig\Node\Expression\NameExpression::isSimple()` and + `Twig\Node\Expression\NameExpression::isSpecial()` + # 3.10.3 (2024-05-16) * Fix missing ; in generated code diff --git a/upload/system/storage/vendor/twig/twig/composer.json b/upload/system/storage/vendor/twig/twig/composer.json index 57ba92964..26cb4972e 100644 --- a/upload/system/storage/vendor/twig/twig/composer.json +++ b/upload/system/storage/vendor/twig/twig/composer.json @@ -28,7 +28,8 @@ "symfony/polyfill-php80": "^1.22", "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "^1.3", - "symfony/polyfill-ctype": "^1.8" + "symfony/polyfill-ctype": "^1.8", + "symfony/polyfill-php81": "^1.29" }, "require-dev": { "symfony/phpunit-bridge": "^5.4.9|^6.4|^7.0", diff --git a/upload/system/storage/vendor/twig/twig/src/Cache/ChainCache.php b/upload/system/storage/vendor/twig/twig/src/Cache/ChainCache.php new file mode 100644 index 000000000..18c66f35f --- /dev/null +++ b/upload/system/storage/vendor/twig/twig/src/Cache/ChainCache.php @@ -0,0 +1,81 @@ + + */ +final class ChainCache implements CacheInterface +{ + private $caches; + + /** + * @param iterable $caches The ordered list of caches used to store and fetch cached items + */ + public function __construct(iterable $caches) + { + $this->caches = $caches; + } + + public function generateKey(string $name, string $className): string + { + return $className.'#'.$name; + } + + public function write(string $key, string $content): void + { + $splitKey = $this->splitKey($key); + + foreach ($this->caches as $cache) { + $cache->write($cache->generateKey(...$splitKey), $content); + } + } + + public function load(string $key): void + { + [$name, $className] = $this->splitKey($key); + + foreach ($this->caches as $cache) { + $cache->load($cache->generateKey($name, $className)); + + if (class_exists($className, false)) { + break; + } + } + } + + public function getTimestamp(string $key): int + { + $splitKey = $this->splitKey($key); + + foreach ($this->caches as $cache) { + if (0 < $timestamp = $cache->getTimestamp($cache->generateKey(...$splitKey))) { + return $timestamp; + } + } + + return 0; + } + + /** + * @return string[] + */ + private function splitKey(string $key): array + { + return array_reverse(explode('#', $key, 2)); + } +} diff --git a/upload/system/storage/vendor/twig/twig/src/Cache/FilesystemCache.php b/upload/system/storage/vendor/twig/twig/src/Cache/FilesystemCache.php index 4024adbd7..2e79fac05 100644 --- a/upload/system/storage/vendor/twig/twig/src/Cache/FilesystemCache.php +++ b/upload/system/storage/vendor/twig/twig/src/Cache/FilesystemCache.php @@ -50,11 +50,11 @@ public function write(string $key, string $content): void if (false === @mkdir($dir, 0777, true)) { clearstatcache(true, $dir); if (!is_dir($dir)) { - throw new \RuntimeException(sprintf('Unable to create the cache directory (%s).', $dir)); + throw new \RuntimeException(\sprintf('Unable to create the cache directory (%s).', $dir)); } } } elseif (!is_writable($dir)) { - throw new \RuntimeException(sprintf('Unable to write in the cache directory (%s).', $dir)); + throw new \RuntimeException(\sprintf('Unable to write in the cache directory (%s).', $dir)); } $tmpFile = tempnam($dir, basename($key)); @@ -73,7 +73,7 @@ public function write(string $key, string $content): void return; } - throw new \RuntimeException(sprintf('Failed to write cache file "%s".', $key)); + throw new \RuntimeException(\sprintf('Failed to write cache file "%s".', $key)); } public function getTimestamp(string $key): int diff --git a/upload/system/storage/vendor/twig/twig/src/Cache/ReadOnlyFilesystemCache.php b/upload/system/storage/vendor/twig/twig/src/Cache/ReadOnlyFilesystemCache.php new file mode 100644 index 000000000..3ba6514c9 --- /dev/null +++ b/upload/system/storage/vendor/twig/twig/src/Cache/ReadOnlyFilesystemCache.php @@ -0,0 +1,25 @@ + + */ +class ReadOnlyFilesystemCache extends FilesystemCache +{ + public function write(string $key, string $content): void + { + // Do nothing with the content, it's a read-only filesystem. + } +} diff --git a/upload/system/storage/vendor/twig/twig/src/Compiler.php b/upload/system/storage/vendor/twig/twig/src/Compiler.php index a2379d138..1e7ed04c6 100644 --- a/upload/system/storage/vendor/twig/twig/src/Compiler.php +++ b/upload/system/storage/vendor/twig/twig/src/Compiler.php @@ -144,7 +144,7 @@ public function write(...$strings) */ public function string(string $value) { - $this->source .= sprintf('"%s"', addcslashes($value, "\0\t\"\$\\")); + $this->source .= \sprintf('"%s"', addcslashes($value, "\0\t\"\$\\")); return $this; } @@ -196,7 +196,7 @@ public function repr($value) public function addDebugInfo(Node $node) { if ($node->getTemplateLine() != $this->lastLine) { - $this->write(sprintf("// line %d\n", $node->getTemplateLine())); + $this->write(\sprintf("// line %d\n", $node->getTemplateLine())); $this->sourceLine += substr_count($this->source, "\n", $this->sourceOffset); $this->sourceOffset = \strlen($this->source); @@ -244,7 +244,7 @@ public function outdent(int $step = 1) public function getVarName(): string { - return sprintf('__internal_compile_%d', $this->varNameSalt++); + return \sprintf('__internal_compile_%d', $this->varNameSalt++); } private function checkForEcho(string $string): void diff --git a/upload/system/storage/vendor/twig/twig/src/Environment.php b/upload/system/storage/vendor/twig/twig/src/Environment.php index b035249b0..32b13135c 100644 --- a/upload/system/storage/vendor/twig/twig/src/Environment.php +++ b/upload/system/storage/vendor/twig/twig/src/Environment.php @@ -43,11 +43,11 @@ */ class Environment { - public const VERSION = '3.10.3'; - public const VERSION_ID = 301003; - public const MAJOR_VERSION = 3; - public const MINOR_VERSION = 10; - public const RELEASE_VERSION = 3; + public const VERSION = '3.11.0'; + public const VERSION_ID = 301100; + public const MAJOR_VERSION = 4; + public const MINOR_VERSION = 11; + public const RELEASE_VERSION = 0; public const EXTRA_VERSION = ''; private $charset; @@ -63,7 +63,6 @@ class Environment private $resolvedGlobals; private $loadedTemplates; private $strictVariables; - private $templateClassPrefix = '__TwigTemplate_'; private $originalCache; private $extensionSet; private $runtimeLoaders = []; @@ -290,7 +289,7 @@ public function getTemplateClass(string $name, ?int $index = null): string { $key = $this->getLoader()->getCacheKey($name).$this->optionsHash; - return $this->templateClassPrefix.hash(\PHP_VERSION_ID < 80100 ? 'sha256' : 'xxh128', $key).(null === $index ? '' : '___'.$index); + return '__TwigTemplate_'.hash(\PHP_VERSION_ID < 80100 ? 'sha256' : 'xxh128', $key).(null === $index ? '' : '___'.$index); } /** @@ -393,7 +392,7 @@ public function loadTemplate(string $cls, string $name, ?int $index = null): Tem } if (!class_exists($cls, false)) { - throw new RuntimeError(sprintf('Failed to load Twig template "%s", index "%s": cache might be corrupted.', $name, $index), -1, $source); + throw new RuntimeError(\sprintf('Failed to load Twig template "%s", index "%s": cache might be corrupted.', $name, $index), -1, $source); } } } @@ -418,9 +417,9 @@ public function createTemplate(string $template, ?string $name = null): Template { $hash = hash(\PHP_VERSION_ID < 80100 ? 'sha256' : 'xxh128', $template, false); if (null !== $name) { - $name = sprintf('%s (string template %s)', $name, $hash); + $name = \sprintf('%s (string template %s)', $name, $hash); } else { - $name = sprintf('__string_template__%s', $hash); + $name = \sprintf('__string_template__%s', $hash); } $loader = new ChainLoader([ @@ -485,7 +484,7 @@ public function resolveTemplate($names): TemplateWrapper return $this->load($name); } - throw new LoaderError(sprintf('Unable to find one of the following templates: "%s".', implode('", "', $names))); + throw new LoaderError(\sprintf('Unable to find one of the following templates: "%s".', implode('", "', $names))); } public function setLexer(Lexer $lexer) @@ -554,7 +553,7 @@ public function compileSource(Source $source): string $e->setSourceContext($source); throw $e; } catch (\Exception $e) { - throw new SyntaxError(sprintf('An exception has been thrown during the compilation of a template ("%s").', $e->getMessage()), -1, $source, $e); + throw new SyntaxError(\sprintf('An exception has been thrown during the compilation of a template ("%s").', $e->getMessage()), -1, $source, $e); } } @@ -632,7 +631,7 @@ public function getRuntime(string $class) return $this->runtimes[$class] = $runtime; } - throw new RuntimeError(sprintf('Unable to load the "%s" runtime.', $class)); + throw new RuntimeError(\sprintf('Unable to load the "%s" runtime.', $class)); } public function addExtension(ExtensionInterface $extension) @@ -803,7 +802,7 @@ public function getFunctions(): array public function addGlobal(string $name, $value) { if ($this->extensionSet->isInitialized() && !\array_key_exists($name, $this->getGlobals())) { - throw new \LogicException(sprintf('Unable to add global "%s" as the runtime or the extensions have already been initialized.', $name)); + throw new \LogicException(\sprintf('Unable to add global "%s" as the runtime or the extensions have already been initialized.', $name)); } if (null !== $this->resolvedGlobals) { diff --git a/upload/system/storage/vendor/twig/twig/src/Error/Error.php b/upload/system/storage/vendor/twig/twig/src/Error/Error.php index 0df213598..4efd9cafb 100644 --- a/upload/system/storage/vendor/twig/twig/src/Error/Error.php +++ b/upload/system/storage/vendor/twig/twig/src/Error/Error.php @@ -143,15 +143,15 @@ private function updateRepr(): void if ($this->name) { if (\is_string($this->name) || (\is_object($this->name) && method_exists($this->name, '__toString'))) { - $name = sprintf('"%s"', $this->name); + $name = \sprintf('"%s"', $this->name); } else { $name = json_encode($this->name); } - $this->message .= sprintf(' in %s', $name); + $this->message .= \sprintf(' in %s', $name); } if ($this->lineno && $this->lineno >= 0) { - $this->message .= sprintf(' at line %d', $this->lineno); + $this->message .= \sprintf(' at line %d', $this->lineno); } if ($dot) { diff --git a/upload/system/storage/vendor/twig/twig/src/Error/SyntaxError.php b/upload/system/storage/vendor/twig/twig/src/Error/SyntaxError.php index 77c437c68..841b653f5 100644 --- a/upload/system/storage/vendor/twig/twig/src/Error/SyntaxError.php +++ b/upload/system/storage/vendor/twig/twig/src/Error/SyntaxError.php @@ -41,6 +41,6 @@ public function addSuggestions(string $name, array $items): void asort($alternatives); - $this->appendMessage(sprintf(' Did you mean "%s"?', implode('", "', array_keys($alternatives)))); + $this->appendMessage(\sprintf(' Did you mean "%s"?', implode('", "', array_keys($alternatives)))); } } diff --git a/upload/system/storage/vendor/twig/twig/src/ExpressionParser.php b/upload/system/storage/vendor/twig/twig/src/ExpressionParser.php index 6839bc932..844844048 100644 --- a/upload/system/storage/vendor/twig/twig/src/ExpressionParser.php +++ b/upload/system/storage/vendor/twig/twig/src/ExpressionParser.php @@ -265,7 +265,7 @@ public function parsePrimaryExpression() if (isset($this->unaryOperators[$token->getValue()])) { $class = $this->unaryOperators[$token->getValue()]['class']; if (!\in_array($class, [NegUnary::class, PosUnary::class])) { - throw new SyntaxError(sprintf('Unexpected unary operator "%s".', $token->getValue()), $token->getLine(), $this->parser->getStream()->getSourceContext()); + throw new SyntaxError(\sprintf('Unexpected unary operator "%s".', $token->getValue()), $token->getLine(), $this->parser->getStream()->getSourceContext()); } $this->parser->getStream()->next(); @@ -278,13 +278,13 @@ public function parsePrimaryExpression() // no break default: if ($token->test(/* Token::PUNCTUATION_TYPE */ 9, '[')) { - $node = $this->parseArrayExpression(); + $node = $this->parseSequenceExpression(); } elseif ($token->test(/* Token::PUNCTUATION_TYPE */ 9, '{')) { - $node = $this->parseHashExpression(); + $node = $this->parseMappingExpression(); } elseif ($token->test(/* Token::OPERATOR_TYPE */ 8, '=') && ('==' === $this->parser->getStream()->look(-1)->getValue() || '!=' === $this->parser->getStream()->look(-1)->getValue())) { - throw new SyntaxError(sprintf('Unexpected operator of value "%s". Did you try to use "===" or "!==" for strict comparison? Use "is same as(value)" instead.', $token->getValue()), $token->getLine(), $this->parser->getStream()->getSourceContext()); + throw new SyntaxError(\sprintf('Unexpected operator of value "%s". Did you try to use "===" or "!==" for strict comparison? Use "is same as(value)" instead.', $token->getValue()), $token->getLine(), $this->parser->getStream()->getSourceContext()); } else { - throw new SyntaxError(sprintf('Unexpected token "%s" of value "%s".', Token::typeToEnglish($token->getType()), $token->getValue()), $token->getLine(), $this->parser->getStream()->getSourceContext()); + throw new SyntaxError(\sprintf('Unexpected token "%s" of value "%s".', Token::typeToEnglish($token->getType()), $token->getValue()), $token->getLine(), $this->parser->getStream()->getSourceContext()); } } @@ -319,16 +319,26 @@ public function parseStringExpression() return $expr; } + /** + * @deprecated since 3.11, use parseSequenceExpression() instead + */ public function parseArrayExpression() + { + trigger_deprecation('twig/twig', '3.11', 'Calling "%s()" is deprecated, use "parseSequenceExpression()" instead.', __METHOD__); + + return $this->parseSequenceExpression(); + } + + public function parseSequenceExpression() { $stream = $this->parser->getStream(); - $stream->expect(/* Token::PUNCTUATION_TYPE */ 9, '[', 'An array element was expected'); + $stream->expect(/* Token::PUNCTUATION_TYPE */ 9, '[', 'A sequence element was expected'); $node = new ArrayExpression([], $stream->getCurrent()->getLine()); $first = true; while (!$stream->test(/* Token::PUNCTUATION_TYPE */ 9, ']')) { if (!$first) { - $stream->expect(/* Token::PUNCTUATION_TYPE */ 9, ',', 'An array element must be followed by a comma'); + $stream->expect(/* Token::PUNCTUATION_TYPE */ 9, ',', 'A sequence element must be followed by a comma'); // trailing ,? if ($stream->test(/* Token::PUNCTUATION_TYPE */ 9, ']')) { @@ -346,21 +356,31 @@ public function parseArrayExpression() $node->addElement($this->parseExpression()); } } - $stream->expect(/* Token::PUNCTUATION_TYPE */ 9, ']', 'An opened array is not properly closed'); + $stream->expect(/* Token::PUNCTUATION_TYPE */ 9, ']', 'An opened sequence is not properly closed'); return $node; } + /** + * @deprecated since 3.11, use parseMappingExpression() instead + */ public function parseHashExpression() + { + trigger_deprecation('twig/twig', '3.11', 'Calling "%s()" is deprecated, use "parseMappingExpression()" instead.', __METHOD__); + + return $this->parseMappingExpression(); + } + + public function parseMappingExpression() { $stream = $this->parser->getStream(); - $stream->expect(/* Token::PUNCTUATION_TYPE */ 9, '{', 'A hash element was expected'); + $stream->expect(/* Token::PUNCTUATION_TYPE */ 9, '{', 'A mapping element was expected'); $node = new ArrayExpression([], $stream->getCurrent()->getLine()); $first = true; while (!$stream->test(/* Token::PUNCTUATION_TYPE */ 9, '}')) { if (!$first) { - $stream->expect(/* Token::PUNCTUATION_TYPE */ 9, ',', 'A hash value must be followed by a comma'); + $stream->expect(/* Token::PUNCTUATION_TYPE */ 9, ',', 'A mapping value must be followed by a comma'); // trailing ,? if ($stream->test(/* Token::PUNCTUATION_TYPE */ 9, '}')) { @@ -377,7 +397,7 @@ public function parseHashExpression() continue; } - // a hash key can be: + // a mapping key can be: // // * a number -- 12 // * a string -- 'a' @@ -399,15 +419,15 @@ public function parseHashExpression() } else { $current = $stream->getCurrent(); - throw new SyntaxError(sprintf('A hash key must be a quoted string, a number, a name, or an expression enclosed in parentheses (unexpected token "%s" of value "%s".', Token::typeToEnglish($current->getType()), $current->getValue()), $current->getLine(), $stream->getSourceContext()); + throw new SyntaxError(\sprintf('A mapping key must be a quoted string, a number, a name, or an expression enclosed in parentheses (unexpected token "%s" of value "%s".', Token::typeToEnglish($current->getType()), $current->getValue()), $current->getLine(), $stream->getSourceContext()); } - $stream->expect(/* Token::PUNCTUATION_TYPE */ 9, ':', 'A hash key must be followed by a colon (:)'); + $stream->expect(/* Token::PUNCTUATION_TYPE */ 9, ':', 'A mapping key must be followed by a colon (:)'); $value = $this->parseExpression(); $node->addElement($value, $key); } - $stream->expect(/* Token::PUNCTUATION_TYPE */ 9, '}', 'An opened hash is not properly closed'); + $stream->expect(/* Token::PUNCTUATION_TYPE */ 9, '}', 'An opened mapping is not properly closed'); return $node; } @@ -505,7 +525,7 @@ public function parseSubscriptExpression($node) } } } else { - throw new SyntaxError(sprintf('Expected name or number, got value "%s" of type %s.', $token->getValue(), Token::typeToEnglish($token->getType())), $lineno, $stream->getSourceContext()); + throw new SyntaxError(\sprintf('Expected name or number, got value "%s" of type %s.', $token->getValue(), Token::typeToEnglish($token->getType())), $lineno, $stream->getSourceContext()); } if ($node instanceof NameExpression && null !== $this->parser->getImportedSymbol('template', $node->getAttribute('name'))) { @@ -623,7 +643,7 @@ public function parseArguments($namedArguments = false, $definition = false, $al $name = null; if ($namedArguments && $token = $stream->nextIf(/* Token::OPERATOR_TYPE */ 8, '=')) { if (!$value instanceof NameExpression) { - throw new SyntaxError(sprintf('A parameter name must be a string, "%s" given.', \get_class($value)), $token->getLine(), $stream->getSourceContext()); + throw new SyntaxError(\sprintf('A parameter name must be a string, "%s" given.', \get_class($value)), $token->getLine(), $stream->getSourceContext()); } $name = $value->getAttribute('name'); @@ -631,7 +651,7 @@ public function parseArguments($namedArguments = false, $definition = false, $al $value = $this->parsePrimaryExpression(); if (!$this->checkConstantExpression($value)) { - throw new SyntaxError('A default value for an argument must be a constant (a boolean, a string, a number, or an array).', $token->getLine(), $stream->getSourceContext()); + throw new SyntaxError('A default value for an argument must be a constant (a boolean, a string, a number, a sequence, or a mapping).', $token->getLine(), $stream->getSourceContext()); } } else { $value = $this->parseExpression(0, $allowArrow); @@ -671,7 +691,7 @@ public function parseAssignmentExpression() } $value = $token->getValue(); if (\in_array(strtr($value, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), ['true', 'false', 'none', 'null'])) { - throw new SyntaxError(sprintf('You cannot assign a value to "%s".', $value), $token->getLine(), $stream->getSourceContext()); + throw new SyntaxError(\sprintf('You cannot assign a value to "%s".', $value), $token->getLine(), $stream->getSourceContext()); } $targets[] = new AssignNameExpression($value, $token->getLine()); @@ -742,7 +762,7 @@ private function getTest(int $line): array } } - $e = new SyntaxError(sprintf('Unknown "%s" test.', $name), $line, $stream->getSourceContext()); + $e = new SyntaxError(\sprintf('Unknown "%s" test.', $name), $line, $stream->getSourceContext()); $e->addSuggestions($name, array_keys($this->env->getTests())); throw $e; @@ -752,18 +772,15 @@ private function getTestNodeClass(TwigTest $test): string { if ($test->isDeprecated()) { $stream = $this->parser->getStream(); - $message = sprintf('Twig Test "%s" is deprecated', $test->getName()); + $message = \sprintf('Twig Test "%s" is deprecated', $test->getName()); - if ($test->getDeprecatedVersion()) { - $message .= sprintf(' since version %s', $test->getDeprecatedVersion()); - } if ($test->getAlternative()) { - $message .= sprintf('. Use "%s" instead', $test->getAlternative()); + $message .= \sprintf('. Use "%s" instead', $test->getAlternative()); } $src = $stream->getSourceContext(); - $message .= sprintf(' in %s at line %d.', $src->getPath() ?: $src->getName(), $stream->getCurrent()->getLine()); + $message .= \sprintf(' in %s at line %d.', $src->getPath() ?: $src->getName(), $stream->getCurrent()->getLine()); - @trigger_error($message, \E_USER_DEPRECATED); + trigger_deprecation($test->getDeprecatingPackage(), $test->getDeprecatedVersion(), $message); } return $test->getNodeClass(); @@ -772,24 +789,21 @@ private function getTestNodeClass(TwigTest $test): string private function getFunctionNodeClass(string $name, int $line): string { if (!$function = $this->env->getFunction($name)) { - $e = new SyntaxError(sprintf('Unknown "%s" function.', $name), $line, $this->parser->getStream()->getSourceContext()); + $e = new SyntaxError(\sprintf('Unknown "%s" function.', $name), $line, $this->parser->getStream()->getSourceContext()); $e->addSuggestions($name, array_keys($this->env->getFunctions())); throw $e; } if ($function->isDeprecated()) { - $message = sprintf('Twig Function "%s" is deprecated', $function->getName()); - if ($function->getDeprecatedVersion()) { - $message .= sprintf(' since version %s', $function->getDeprecatedVersion()); - } + $message = \sprintf('Twig Function "%s" is deprecated', $function->getName()); if ($function->getAlternative()) { - $message .= sprintf('. Use "%s" instead', $function->getAlternative()); + $message .= \sprintf('. Use "%s" instead', $function->getAlternative()); } $src = $this->parser->getStream()->getSourceContext(); - $message .= sprintf(' in %s at line %d.', $src->getPath() ?: $src->getName(), $line); + $message .= \sprintf(' in %s at line %d.', $src->getPath() ?: $src->getName(), $line); - @trigger_error($message, \E_USER_DEPRECATED); + trigger_deprecation($function->getDeprecatingPackage(), $function->getDeprecatedVersion(), $message); } return $function->getNodeClass(); @@ -798,24 +812,21 @@ private function getFunctionNodeClass(string $name, int $line): string private function getFilterNodeClass(string $name, int $line): string { if (!$filter = $this->env->getFilter($name)) { - $e = new SyntaxError(sprintf('Unknown "%s" filter.', $name), $line, $this->parser->getStream()->getSourceContext()); + $e = new SyntaxError(\sprintf('Unknown "%s" filter.', $name), $line, $this->parser->getStream()->getSourceContext()); $e->addSuggestions($name, array_keys($this->env->getFilters())); throw $e; } if ($filter->isDeprecated()) { - $message = sprintf('Twig Filter "%s" is deprecated', $filter->getName()); - if ($filter->getDeprecatedVersion()) { - $message .= sprintf(' since version %s', $filter->getDeprecatedVersion()); - } + $message = \sprintf('Twig Filter "%s" is deprecated', $filter->getName()); if ($filter->getAlternative()) { - $message .= sprintf('. Use "%s" instead', $filter->getAlternative()); + $message .= \sprintf('. Use "%s" instead', $filter->getAlternative()); } $src = $this->parser->getStream()->getSourceContext(); - $message .= sprintf(' in %s at line %d.', $src->getPath() ?: $src->getName(), $line); + $message .= \sprintf(' in %s at line %d.', $src->getPath() ?: $src->getName(), $line); - @trigger_error($message, \E_USER_DEPRECATED); + trigger_deprecation($filter->getDeprecatingPackage(), $filter->getDeprecatedVersion(), $message); } return $filter->getNodeClass(); diff --git a/upload/system/storage/vendor/twig/twig/src/Extension/AbstractExtension.php b/upload/system/storage/vendor/twig/twig/src/Extension/AbstractExtension.php index 422925f31..a1b083b68 100644 --- a/upload/system/storage/vendor/twig/twig/src/Extension/AbstractExtension.php +++ b/upload/system/storage/vendor/twig/twig/src/Extension/AbstractExtension.php @@ -40,6 +40,6 @@ public function getFunctions() public function getOperators() { - return []; + return [[], []]; } } diff --git a/upload/system/storage/vendor/twig/twig/src/Extension/CoreExtension.php b/upload/system/storage/vendor/twig/twig/src/Extension/CoreExtension.php index d7915ef9b..5ac80884a 100644 --- a/upload/system/storage/vendor/twig/twig/src/Extension/CoreExtension.php +++ b/upload/system/storage/vendor/twig/twig/src/Extension/CoreExtension.php @@ -218,9 +218,11 @@ public function getFilters(): array new TwigFilter('filter', [self::class, 'filter'], ['needs_environment' => true]), new TwigFilter('map', [self::class, 'map'], ['needs_environment' => true]), new TwigFilter('reduce', [self::class, 'reduce'], ['needs_environment' => true]), + new TwigFilter('find', [self::class, 'find'], ['needs_environment' => true]), // string/array filters new TwigFilter('reverse', [self::class, 'reverse'], ['needs_charset' => true]), + new TwigFilter('shuffle', [self::class, 'shuffle'], ['needs_charset' => true]), new TwigFilter('length', [self::class, 'length'], ['needs_charset' => true]), new TwigFilter('slice', [self::class, 'slice'], ['needs_charset' => true]), new TwigFilter('first', [self::class, 'first'], ['needs_charset' => true]), @@ -260,6 +262,8 @@ public function getTests(): array new TwigTest('constant', null, ['node_class' => ConstantTest::class]), new TwigTest('empty', [self::class, 'testEmpty']), new TwigTest('iterable', 'is_iterable'), + new TwigTest('sequence', [self::class, 'testSequence']), + new TwigTest('mapping', [self::class, 'testMapping']), ]; } @@ -329,7 +333,7 @@ public static function cycle($values, $position): string } if (!\count($values)) { - throw new RuntimeError('The "cycle" function does not work on empty arrays.'); + throw new RuntimeError('The "cycle" function does not work on empty sequences/mappings.'); } return $values[$position % \count($values)]; @@ -399,7 +403,7 @@ public static function random(string $charset, $values = null, $max = null) $values = self::toArray($values); if (0 === \count($values)) { - throw new RuntimeError('The random function cannot pick from an empty array.'); + throw new RuntimeError('The random function cannot pick from an empty sequence/mapping.'); } return $values[array_rand($values, 1)]; @@ -455,7 +459,7 @@ public function modifyDate($date, $modifier) */ public static function sprintf($format, ...$values): string { - return sprintf($format ?? '', ...$values); + return \sprintf($format ?? '', ...$values); } /** @@ -536,7 +540,7 @@ public function convertDate($date = null, $timezone = null) public static function replace($str, $from): string { if (!is_iterable($from)) { - throw new RuntimeError(sprintf('The "replace" filter expects an array or "Traversable" as replace values, got "%s".', \is_object($from) ? \get_class($from) : \gettype($from))); + throw new RuntimeError(\sprintf('The "replace" filter expects a sequence/mapping or "Traversable" as replace values, got "%s".', \is_object($from) ? \get_class($from) : \gettype($from))); } return strtr($str ?? '', self::toArray($from)); @@ -633,7 +637,7 @@ public static function merge(...$arrays): array foreach ($arrays as $argNumber => $array) { if (!is_iterable($array)) { - throw new RuntimeError(sprintf('The merge filter only works with arrays or "Traversable", got "%s" for argument %d.', \gettype($array), $argNumber + 1)); + throw new RuntimeError(\sprintf('The merge filter only works with sequences/mappings or "Traversable", got "%s" for argument %d.', \gettype($array), $argNumber + 1)); } $result = array_merge($result, self::toArray($array)); @@ -895,6 +899,42 @@ public static function reverse(string $charset, $item, $preserveKeys = false) return $string; } + /** + * Shuffles an array, a \Traversable instance, or a string. + * The function does not preserve keys. + * + * @param array|\Traversable|string|null $item + * + * @return mixed + * + * @internal + */ + public static function shuffle(string $charset, $item) + { + if (\is_string($item)) { + if ('UTF-8' !== $charset) { + $item = self::convertEncoding($item, 'UTF-8', $charset); + } + + $item = preg_split('/(?getTemplateName()), $lineno, $source); + throw new RuntimeError(\sprintf('Macro "%s" is not defined in template "%s".', substr($method, \strlen('macro_')), $template->getTemplateName()), $lineno, $source); } return $template->$method(...$args); @@ -1285,6 +1325,56 @@ public static function testEmpty($value): bool return '' === $value || false === $value || null === $value || [] === $value; } + /** + * Checks if a variable is a sequence. + * + * {# evaluates to true if the foo variable is a sequence #} + * {% if foo is sequence %} + * {# ... #} + * {% endif %} + * + * @param mixed $value + * + * @internal + */ + public static function testSequence($value): bool + { + if ($value instanceof \ArrayObject) { + $value = $value->getArrayCopy(); + } + + if ($value instanceof \Traversable) { + $value = iterator_to_array($value); + } + + return \is_array($value) && array_is_list($value); + } + + /** + * Checks if a variable is a mapping. + * + * {# evaluates to true if the foo variable is a mapping #} + * {% if foo is mapping %} + * {# ... #} + * {% endif %} + * + * @param mixed $value + * + * @internal + */ + public static function testMapping($value): bool + { + if ($value instanceof \ArrayObject) { + $value = $value->getArrayCopy(); + } + + if ($value instanceof \Traversable) { + $value = iterator_to_array($value); + } + + return (\is_array($value) && !array_is_list($value)) || \is_object($value); + } + /** * Renders a template. * @@ -1382,10 +1472,10 @@ public static function constant($constant, $object = null) if (!\defined($constant)) { if ('::class' === strtolower(substr($constant, -7))) { - throw new RuntimeError(sprintf('You cannot use the Twig function "constant()" to access "%s". You could provide an object and call constant("class", $object) or use the class name directly as a string.', $constant)); + throw new RuntimeError(\sprintf('You cannot use the Twig function "constant()" to access "%s". You could provide an object and call constant("class", $object) or use the class name directly as a string.', $constant)); } - throw new RuntimeError(sprintf('Constant "%s" is undefined.', $constant)); + throw new RuntimeError(\sprintf('Constant "%s" is undefined.', $constant)); } return \constant($constant); @@ -1424,10 +1514,10 @@ public static function constantIsDefined($constant, $object = null): bool public static function batch($items, $size, $fill = null, $preserveKeys = true): array { if (!is_iterable($items)) { - throw new RuntimeError(sprintf('The "batch" filter expects an array or "Traversable", got "%s".', \is_object($items) ? \get_class($items) : \gettype($items))); + throw new RuntimeError(\sprintf('The "batch" filter expects a sequence/mapping or "Traversable", got "%s".', \is_object($items) ? \get_class($items) : \gettype($items))); } - $size = ceil($size); + $size = (int) ceil($size); $result = array_chunk(self::toArray($items, $preserveKeys), $size, $preserveKeys); @@ -1486,25 +1576,25 @@ public static function getAttribute(Environment $env, Source $source, $object, $ } if ($object instanceof \ArrayAccess) { - $message = sprintf('Key "%s" in object with ArrayAccess of class "%s" does not exist.', $arrayItem, \get_class($object)); + $message = \sprintf('Key "%s" in object with ArrayAccess of class "%s" does not exist.', $arrayItem, \get_class($object)); } elseif (\is_object($object)) { - $message = sprintf('Impossible to access a key "%s" on an object of class "%s" that does not implement ArrayAccess interface.', $item, \get_class($object)); + $message = \sprintf('Impossible to access a key "%s" on an object of class "%s" that does not implement ArrayAccess interface.', $item, \get_class($object)); } elseif (\is_array($object)) { if (empty($object)) { - $message = sprintf('Key "%s" does not exist as the array is empty.', $arrayItem); + $message = \sprintf('Key "%s" does not exist as the sequence/mapping is empty.', $arrayItem); } else { - $message = sprintf('Key "%s" for array with keys "%s" does not exist.', $arrayItem, implode(', ', array_keys($object))); + $message = \sprintf('Key "%s" for sequence/mapping with keys "%s" does not exist.', $arrayItem, implode(', ', array_keys($object))); } } elseif (/* Template::ARRAY_CALL */ 'array' === $type) { if (null === $object) { - $message = sprintf('Impossible to access a key ("%s") on a null variable.', $item); + $message = \sprintf('Impossible to access a key ("%s") on a null variable.', $item); } else { - $message = sprintf('Impossible to access a key ("%s") on a %s variable ("%s").', $item, \gettype($object), $object); + $message = \sprintf('Impossible to access a key ("%s") on a %s variable ("%s").', $item, \gettype($object), $object); } } elseif (null === $object) { - $message = sprintf('Impossible to access an attribute ("%s") on a null variable.', $item); + $message = \sprintf('Impossible to access an attribute ("%s") on a null variable.', $item); } else { - $message = sprintf('Impossible to access an attribute ("%s") on a %s variable ("%s").', $item, \gettype($object), $object); + $message = \sprintf('Impossible to access an attribute ("%s") on a %s variable ("%s").', $item, \gettype($object), $object); } throw new RuntimeError($message, $lineno, $source); @@ -1521,11 +1611,11 @@ public static function getAttribute(Environment $env, Source $source, $object, $ } if (null === $object) { - $message = sprintf('Impossible to invoke a method ("%s") on a null variable.', $item); + $message = \sprintf('Impossible to invoke a method ("%s") on a null variable.', $item); } elseif (\is_array($object)) { - $message = sprintf('Impossible to invoke a method ("%s") on an array.', $item); + $message = \sprintf('Impossible to invoke a method ("%s") on a sequence/mapping.', $item); } else { - $message = sprintf('Impossible to invoke a method ("%s") on a %s variable ("%s").', $item, \gettype($object), $object); + $message = \sprintf('Impossible to invoke a method ("%s") on a %s variable ("%s").', $item, \gettype($object), $object); } throw new RuntimeError($message, $lineno, $source); @@ -1612,7 +1702,7 @@ public static function getAttribute(Environment $env, Source $source, $object, $ return; } - throw new RuntimeError(sprintf('Neither the property "%1$s" nor one of the methods "%1$s()", "get%1$s()"/"is%1$s()"/"has%1$s()" or "__call()" exist and have public access in class "%2$s".', $item, $class), $lineno, $source); + throw new RuntimeError(\sprintf('Neither the property "%1$s" nor one of the methods "%1$s()", "get%1$s()"/"is%1$s()"/"has%1$s()" or "__call()" exist and have public access in class "%2$s".', $item, $class), $lineno, $source); } if ($isDefinedTest) { @@ -1661,7 +1751,7 @@ public static function column($array, $name, $index = null): array if ($array instanceof \Traversable) { $array = iterator_to_array($array); } elseif (!\is_array($array)) { - throw new RuntimeError(sprintf('The column filter only works with arrays or "Traversable", got "%s" as first argument.', \gettype($array))); + throw new RuntimeError(\sprintf('The column filter only works with sequences/mappings or "Traversable", got "%s" as first argument.', \gettype($array))); } return array_column($array, $name, $index); @@ -1673,7 +1763,7 @@ public static function column($array, $name, $index = null): array public static function filter(Environment $env, $array, $arrow) { if (!is_iterable($array)) { - throw new RuntimeError(sprintf('The "filter" filter expects an array or "Traversable", got "%s".', \is_object($array) ? \get_class($array) : \gettype($array))); + throw new RuntimeError(\sprintf('The "filter" filter expects a sequence/mapping or "Traversable", got "%s".', \is_object($array) ? \get_class($array) : \gettype($array))); } self::checkArrowInSandbox($env, $arrow, 'filter', 'filter'); @@ -1686,6 +1776,22 @@ public static function filter(Environment $env, $array, $arrow) return new \CallbackFilterIterator(new \IteratorIterator($array), $arrow); } + /** + * @internal + */ + public static function find(Environment $env, $array, $arrow) + { + self::checkArrowInSandbox($env, $arrow, 'find', 'filter'); + + foreach ($array as $k => $v) { + if ($arrow($v, $k)) { + return $v; + } + } + + return null; + } + /** * @internal */ @@ -1709,7 +1815,7 @@ public static function reduce(Environment $env, $array, $arrow, $initial = null) self::checkArrowInSandbox($env, $arrow, 'reduce', 'filter'); if (!\is_array($array) && !$array instanceof \Traversable) { - throw new RuntimeError(sprintf('The "reduce" filter only works with arrays or "Traversable", got "%s" as first argument.', \gettype($array))); + throw new RuntimeError(\sprintf('The "reduce" filter only works with sequences/mappings or "Traversable", got "%s" as first argument.', \gettype($array))); } $accumulator = $initial; @@ -1758,7 +1864,7 @@ public static function arrayEvery(Environment $env, $array, $arrow) public static function checkArrowInSandbox(Environment $env, $arrow, $thing, $type) { if (!$arrow instanceof \Closure && $env->hasExtension(SandboxExtension::class) && $env->getExtension(SandboxExtension::class)->isSandboxed()) { - throw new RuntimeError(sprintf('The callable passed to the "%s" %s must be a Closure in sandbox mode.', $thing, $type)); + throw new RuntimeError(\sprintf('The callable passed to the "%s" %s must be a Closure in sandbox mode.', $thing, $type)); } } diff --git a/upload/system/storage/vendor/twig/twig/src/Extension/EscaperExtension.php b/upload/system/storage/vendor/twig/twig/src/Extension/EscaperExtension.php index 3360ef671..d8e9b6e48 100644 --- a/upload/system/storage/vendor/twig/twig/src/Extension/EscaperExtension.php +++ b/upload/system/storage/vendor/twig/twig/src/Extension/EscaperExtension.php @@ -14,6 +14,7 @@ use Twig\Environment; use Twig\FileExtensionEscapingStrategy; use Twig\Node\Expression\ConstantExpression; +use Twig\Node\Expression\Filter\RawFilter; use Twig\Node\Node; use Twig\NodeVisitor\EscaperNodeVisitor; use Twig\Runtime\EscaperRuntime; @@ -52,7 +53,7 @@ public function getFilters(): array return [ new TwigFilter('escape', [EscaperRuntime::class, 'escape'], ['is_safe_callback' => [self::class, 'escapeFilterIsSafe']]), new TwigFilter('e', [EscaperRuntime::class, 'escape'], ['is_safe_callback' => [self::class, 'escapeFilterIsSafe']]), - new TwigFilter('raw', [self::class, 'raw'], ['is_safe' => ['all']]), + new TwigFilter('raw', null, ['is_safe' => ['all'], 'node_class' => RawFilter::class]), ]; } @@ -117,8 +118,8 @@ public function getDefaultStrategy(string $name) /** * Defines a new escaper to be used via the escape filter. * - * @param string $strategy The strategy name that should be used as a strategy in the escape call - * @param callable(Environment, string, string) $callable A valid PHP callable + * @param string $strategy The strategy name that should be used as a strategy in the escape call + * @param callable(Environment, string, string): string $callable A valid PHP callable * * @deprecated since Twig 3.10 */ @@ -127,7 +128,7 @@ public function setEscaper($strategy, callable $callable) trigger_deprecation('twig/twig', '3.10', 'The "%s()" method is deprecated, use the "Twig\Runtime\EscaperRuntime::setEscaper()" method instead (be warned that Environment is not passed anymore to the callable).', __METHOD__); if (!isset($this->environment)) { - throw new \LogicException(sprintf('You must call "setEnvironment()" before calling "%s()".', __METHOD__)); + throw new \LogicException(\sprintf('You must call "setEnvironment()" before calling "%s()".', __METHOD__)); } $this->escapers[$strategy] = $callable; @@ -141,7 +142,7 @@ public function setEscaper($strategy, callable $callable) /** * Gets all defined escapers. * - * @return array An array of escapers + * @return array An array of escapers * * @deprecated since Twig 3.10 */ @@ -160,7 +161,7 @@ public function setSafeClasses(array $safeClasses = []) trigger_deprecation('twig/twig', '3.10', 'The "%s()" method is deprecated, use the "Twig\Runtime\EscaperRuntime::setSafeClasses()" method instead.', __METHOD__); if (!isset($this->escaper)) { - throw new \LogicException(sprintf('You must call "setEnvironment()" before calling "%s()".', __METHOD__)); + throw new \LogicException(\sprintf('You must call "setEnvironment()" before calling "%s()".', __METHOD__)); } $this->escaper->setSafeClasses($safeClasses); @@ -174,24 +175,12 @@ public function addSafeClass(string $class, array $strategies) trigger_deprecation('twig/twig', '3.10', 'The "%s()" method is deprecated, use the "Twig\Runtime\EscaperRuntime::addSafeClass()" method instead.', __METHOD__); if (!isset($this->escaper)) { - throw new \LogicException(sprintf('You must call "setEnvironment()" before calling "%s()".', __METHOD__)); + throw new \LogicException(\sprintf('You must call "setEnvironment()" before calling "%s()".', __METHOD__)); } $this->escaper->addSafeClass($class, $strategies); } - /** - * Marks a variable as being safe. - * - * @param string $string A PHP variable - * - * @internal - */ - public static function raw($string) - { - return $string; - } - /** * @internal */ diff --git a/upload/system/storage/vendor/twig/twig/src/Extension/ExtensionInterface.php b/upload/system/storage/vendor/twig/twig/src/Extension/ExtensionInterface.php index ab9c2c37c..10a42b6b1 100644 --- a/upload/system/storage/vendor/twig/twig/src/Extension/ExtensionInterface.php +++ b/upload/system/storage/vendor/twig/twig/src/Extension/ExtensionInterface.php @@ -12,8 +12,7 @@ namespace Twig\Extension; use Twig\ExpressionParser; -use Twig\Node\Expression\Binary\AbstractBinary; -use Twig\Node\Expression\Unary\AbstractUnary; +use Twig\Node\Expression\AbstractExpression; use Twig\NodeVisitor\NodeVisitorInterface; use Twig\TokenParser\TokenParserInterface; use Twig\TwigFilter; @@ -68,8 +67,8 @@ public function getFunctions(); * @return array First array of unary operators, second array of binary operators * * @psalm-return array{ - * array}>, - * array, associativity: ExpressionParser::OPERATOR_*}> + * array}>, + * array, associativity: ExpressionParser::OPERATOR_*}> * } */ public function getOperators(); diff --git a/upload/system/storage/vendor/twig/twig/src/Extension/StagingExtension.php b/upload/system/storage/vendor/twig/twig/src/Extension/StagingExtension.php index 0ea47f90c..59db2ca7d 100644 --- a/upload/system/storage/vendor/twig/twig/src/Extension/StagingExtension.php +++ b/upload/system/storage/vendor/twig/twig/src/Extension/StagingExtension.php @@ -35,7 +35,7 @@ final class StagingExtension extends AbstractExtension public function addFunction(TwigFunction $function): void { if (isset($this->functions[$function->getName()])) { - throw new \LogicException(sprintf('Function "%s" is already registered.', $function->getName())); + throw new \LogicException(\sprintf('Function "%s" is already registered.', $function->getName())); } $this->functions[$function->getName()] = $function; @@ -49,7 +49,7 @@ public function getFunctions(): array public function addFilter(TwigFilter $filter): void { if (isset($this->filters[$filter->getName()])) { - throw new \LogicException(sprintf('Filter "%s" is already registered.', $filter->getName())); + throw new \LogicException(\sprintf('Filter "%s" is already registered.', $filter->getName())); } $this->filters[$filter->getName()] = $filter; @@ -73,7 +73,7 @@ public function getNodeVisitors(): array public function addTokenParser(TokenParserInterface $parser): void { if (isset($this->tokenParsers[$parser->getTag()])) { - throw new \LogicException(sprintf('Tag "%s" is already registered.', $parser->getTag())); + throw new \LogicException(\sprintf('Tag "%s" is already registered.', $parser->getTag())); } $this->tokenParsers[$parser->getTag()] = $parser; @@ -87,7 +87,7 @@ public function getTokenParsers(): array public function addTest(TwigTest $test): void { if (isset($this->tests[$test->getName()])) { - throw new \LogicException(sprintf('Test "%s" is already registered.', $test->getName())); + throw new \LogicException(\sprintf('Test "%s" is already registered.', $test->getName())); } $this->tests[$test->getName()] = $test; diff --git a/upload/system/storage/vendor/twig/twig/src/ExtensionSet.php b/upload/system/storage/vendor/twig/twig/src/ExtensionSet.php index d32200ceb..8b59a13e1 100644 --- a/upload/system/storage/vendor/twig/twig/src/ExtensionSet.php +++ b/upload/system/storage/vendor/twig/twig/src/ExtensionSet.php @@ -15,6 +15,7 @@ use Twig\Extension\ExtensionInterface; use Twig\Extension\GlobalsInterface; use Twig\Extension\StagingExtension; +use Twig\Node\Expression\AbstractExpression; use Twig\Node\Expression\Binary\AbstractBinary; use Twig\Node\Expression\Unary\AbstractUnary; use Twig\NodeVisitor\NodeVisitorInterface; @@ -39,9 +40,9 @@ final class ExtensionSet private $tests; /** @var array */ private $functions; - /** @var array}> */ + /** @var array}> */ private $unaryOperators; - /** @var array, associativity: ExpressionParser::OPERATOR_*}> */ + /** @var array, associativity: ExpressionParser::OPERATOR_*}> */ private $binaryOperators; /** @var array */ private $globals; @@ -70,7 +71,7 @@ public function getExtension(string $class): ExtensionInterface $class = ltrim($class, '\\'); if (!isset($this->extensions[$class])) { - throw new RuntimeError(sprintf('The "%s" extension is not enabled.', $class)); + throw new RuntimeError(\sprintf('The "%s" extension is not enabled.', $class)); } return $this->extensions[$class]; @@ -125,11 +126,11 @@ public function addExtension(ExtensionInterface $extension): void $class = \get_class($extension); if ($this->initialized) { - throw new \LogicException(sprintf('Unable to register extension "%s" as extensions have already been initialized.', $class)); + throw new \LogicException(\sprintf('Unable to register extension "%s" as extensions have already been initialized.', $class)); } if (isset($this->extensions[$class])) { - throw new \LogicException(sprintf('Unable to register extension "%s" as it is already registered.', $class)); + throw new \LogicException(\sprintf('Unable to register extension "%s" as it is already registered.', $class)); } $this->extensions[$class] = $extension; @@ -138,7 +139,7 @@ public function addExtension(ExtensionInterface $extension): void public function addFunction(TwigFunction $function): void { if ($this->initialized) { - throw new \LogicException(sprintf('Unable to add function "%s" as extensions have already been initialized.', $function->getName())); + throw new \LogicException(\sprintf('Unable to add function "%s" as extensions have already been initialized.', $function->getName())); } $this->staging->addFunction($function); @@ -194,7 +195,7 @@ public function registerUndefinedFunctionCallback(callable $callable): void public function addFilter(TwigFilter $filter): void { if ($this->initialized) { - throw new \LogicException(sprintf('Unable to add filter "%s" as extensions have already been initialized.', $filter->getName())); + throw new \LogicException(\sprintf('Unable to add filter "%s" as extensions have already been initialized.', $filter->getName())); } $this->staging->addFilter($filter); @@ -330,7 +331,7 @@ public function getGlobals(): array $extGlobals = $extension->getGlobals(); if (!\is_array($extGlobals)) { - throw new \UnexpectedValueException(sprintf('"%s::getGlobals()" must return an array of globals.', \get_class($extension))); + throw new \UnexpectedValueException(\sprintf('"%s::getGlobals()" must return an array of globals.', \get_class($extension))); } $globals = array_merge($globals, $extGlobals); @@ -346,7 +347,7 @@ public function getGlobals(): array public function addTest(TwigTest $test): void { if ($this->initialized) { - throw new \LogicException(sprintf('Unable to add test "%s" as extensions have already been initialized.', $test->getName())); + throw new \LogicException(\sprintf('Unable to add test "%s" as extensions have already been initialized.', $test->getName())); } $this->staging->addTest($test); @@ -391,7 +392,7 @@ public function getTest(string $name): ?TwigTest } /** - * @return array}> + * @return array}> */ public function getUnaryOperators(): array { @@ -403,7 +404,7 @@ public function getUnaryOperators(): array } /** - * @return array, associativity: ExpressionParser::OPERATOR_*}> + * @return array, associativity: ExpressionParser::OPERATOR_*}> */ public function getBinaryOperators(): array { @@ -466,11 +467,11 @@ private function initExtension(ExtensionInterface $extension): void // operators if ($operators = $extension->getOperators()) { if (!\is_array($operators)) { - throw new \InvalidArgumentException(sprintf('"%s::getOperators()" must return an array with operators, got "%s".', \get_class($extension), \is_object($operators) ? \get_class($operators) : \gettype($operators).(\is_resource($operators) ? '' : '#'.$operators))); + throw new \InvalidArgumentException(\sprintf('"%s::getOperators()" must return an array with operators, got "%s".', \get_class($extension), \is_object($operators) ? \get_class($operators) : \gettype($operators).(\is_resource($operators) ? '' : '#'.$operators))); } if (2 !== \count($operators)) { - throw new \InvalidArgumentException(sprintf('"%s::getOperators()" must return an array of 2 elements, got %d.', \get_class($extension), \count($operators))); + throw new \InvalidArgumentException(\sprintf('"%s::getOperators()" must return an array of 2 elements, got %d.', \get_class($extension), \count($operators))); } $this->unaryOperators = array_merge($this->unaryOperators, $operators[0]); diff --git a/upload/system/storage/vendor/twig/twig/src/Lexer.php b/upload/system/storage/vendor/twig/twig/src/Lexer.php index e15e896f5..8973fbbc8 100644 --- a/upload/system/storage/vendor/twig/twig/src/Lexer.php +++ b/upload/system/storage/vendor/twig/twig/src/Lexer.php @@ -211,7 +211,7 @@ public function tokenize(Source $source): TokenStream if (!empty($this->brackets)) { [$expect, $lineno] = array_pop($this->brackets); - throw new SyntaxError(sprintf('Unclosed "%s".', $expect), $lineno, $this->source); + throw new SyntaxError(\sprintf('Unclosed "%s".', $expect), $lineno, $this->source); } return new TokenStream($this->tokens, $this->source); @@ -311,7 +311,7 @@ private function lexExpression(): void $this->moveCursor($match[0]); if ($this->cursor >= $this->end) { - throw new SyntaxError(sprintf('Unclosed "%s".', self::STATE_BLOCK === $this->state ? 'block' : 'variable'), $this->currentVarBlockLine, $this->source); + throw new SyntaxError(\sprintf('Unclosed "%s".', self::STATE_BLOCK === $this->state ? 'block' : 'variable'), $this->currentVarBlockLine, $this->source); } } @@ -353,12 +353,12 @@ private function lexExpression(): void // closing bracket elseif (str_contains(')]}', $this->code[$this->cursor])) { if (empty($this->brackets)) { - throw new SyntaxError(sprintf('Unexpected "%s".', $this->code[$this->cursor]), $this->lineno, $this->source); + throw new SyntaxError(\sprintf('Unexpected "%s".', $this->code[$this->cursor]), $this->lineno, $this->source); } [$expect, $lineno] = array_pop($this->brackets); if ($this->code[$this->cursor] != strtr($expect, '([{', ')]}')) { - throw new SyntaxError(sprintf('Unclosed "%s".', $expect), $lineno, $this->source); + throw new SyntaxError(\sprintf('Unclosed "%s".', $expect), $lineno, $this->source); } } @@ -378,7 +378,7 @@ private function lexExpression(): void } // unlexable else { - throw new SyntaxError(sprintf('Unexpected character "%s".', $this->code[$this->cursor]), $this->lineno, $this->source); + throw new SyntaxError(\sprintf('Unexpected character "%s".', $this->code[$this->cursor]), $this->lineno, $this->source); } } @@ -428,14 +428,14 @@ private function lexString(): void } elseif (preg_match(self::REGEX_DQ_STRING_DELIM, $this->code, $match, 0, $this->cursor)) { [$expect, $lineno] = array_pop($this->brackets); if ('"' != $this->code[$this->cursor]) { - throw new SyntaxError(sprintf('Unclosed "%s".', $expect), $lineno, $this->source); + throw new SyntaxError(\sprintf('Unclosed "%s".', $expect), $lineno, $this->source); } $this->popState(); ++$this->cursor; } else { // unlexable - throw new SyntaxError(sprintf('Unexpected character "%s".', $this->code[$this->cursor]), $this->lineno, $this->source); + throw new SyntaxError(\sprintf('Unexpected character "%s".', $this->code[$this->cursor]), $this->lineno, $this->source); } } diff --git a/upload/system/storage/vendor/twig/twig/src/Loader/ArrayLoader.php b/upload/system/storage/vendor/twig/twig/src/Loader/ArrayLoader.php index 5d726c35a..ce613c9cc 100644 --- a/upload/system/storage/vendor/twig/twig/src/Loader/ArrayLoader.php +++ b/upload/system/storage/vendor/twig/twig/src/Loader/ArrayLoader.php @@ -46,7 +46,7 @@ public function setTemplate(string $name, string $template): void public function getSourceContext(string $name): Source { if (!isset($this->templates[$name])) { - throw new LoaderError(sprintf('Template "%s" is not defined.', $name)); + throw new LoaderError(\sprintf('Template "%s" is not defined.', $name)); } return new Source($this->templates[$name], $name); @@ -60,7 +60,7 @@ public function exists(string $name): bool public function getCacheKey(string $name): string { if (!isset($this->templates[$name])) { - throw new LoaderError(sprintf('Template "%s" is not defined.', $name)); + throw new LoaderError(\sprintf('Template "%s" is not defined.', $name)); } return $name.':'.$this->templates[$name]; @@ -69,7 +69,7 @@ public function getCacheKey(string $name): string public function isFresh(string $name, int $time): bool { if (!isset($this->templates[$name])) { - throw new LoaderError(sprintf('Template "%s" is not defined.', $name)); + throw new LoaderError(\sprintf('Template "%s" is not defined.', $name)); } return true; diff --git a/upload/system/storage/vendor/twig/twig/src/Loader/ChainLoader.php b/upload/system/storage/vendor/twig/twig/src/Loader/ChainLoader.php index fbf4f3a06..163c029f8 100644 --- a/upload/system/storage/vendor/twig/twig/src/Loader/ChainLoader.php +++ b/upload/system/storage/vendor/twig/twig/src/Loader/ChainLoader.php @@ -63,7 +63,7 @@ public function getSourceContext(string $name): Source } } - throw new LoaderError(sprintf('Template "%s" is not defined%s.', $name, $exceptions ? ' ('.implode(', ', $exceptions).')' : '')); + throw new LoaderError(\sprintf('Template "%s" is not defined%s.', $name, $exceptions ? ' ('.implode(', ', $exceptions).')' : '')); } public function exists(string $name): bool @@ -96,7 +96,7 @@ public function getCacheKey(string $name): string } } - throw new LoaderError(sprintf('Template "%s" is not defined%s.', $name, $exceptions ? ' ('.implode(', ', $exceptions).')' : '')); + throw new LoaderError(\sprintf('Template "%s" is not defined%s.', $name, $exceptions ? ' ('.implode(', ', $exceptions).')' : '')); } public function isFresh(string $name, int $time): bool @@ -114,6 +114,6 @@ public function isFresh(string $name, int $time): bool } } - throw new LoaderError(sprintf('Template "%s" is not defined%s.', $name, $exceptions ? ' ('.implode(', ', $exceptions).')' : '')); + throw new LoaderError(\sprintf('Template "%s" is not defined%s.', $name, $exceptions ? ' ('.implode(', ', $exceptions).')' : '')); } } diff --git a/upload/system/storage/vendor/twig/twig/src/Loader/FilesystemLoader.php b/upload/system/storage/vendor/twig/twig/src/Loader/FilesystemLoader.php index 8472796f7..c60964f5f 100644 --- a/upload/system/storage/vendor/twig/twig/src/Loader/FilesystemLoader.php +++ b/upload/system/storage/vendor/twig/twig/src/Loader/FilesystemLoader.php @@ -89,7 +89,7 @@ public function addPath(string $path, string $namespace = self::MAIN_NAMESPACE): $checkPath = $this->isAbsolutePath($path) ? $path : $this->rootPath.$path; if (!is_dir($checkPath)) { - throw new LoaderError(sprintf('The "%s" directory does not exist ("%s").', $path, $checkPath)); + throw new LoaderError(\sprintf('The "%s" directory does not exist ("%s").', $path, $checkPath)); } $this->paths[$namespace][] = rtrim($path, '/\\'); @@ -105,7 +105,7 @@ public function prependPath(string $path, string $namespace = self::MAIN_NAMESPA $checkPath = $this->isAbsolutePath($path) ? $path : $this->rootPath.$path; if (!is_dir($checkPath)) { - throw new LoaderError(sprintf('The "%s" directory does not exist ("%s").', $path, $checkPath)); + throw new LoaderError(\sprintf('The "%s" directory does not exist ("%s").', $path, $checkPath)); } $path = rtrim($path, '/\\'); @@ -195,7 +195,7 @@ protected function findTemplate(string $name, bool $throw = true) } if (!isset($this->paths[$namespace])) { - $this->errorCache[$name] = sprintf('There are no registered paths for namespace "%s".', $namespace); + $this->errorCache[$name] = \sprintf('There are no registered paths for namespace "%s".', $namespace); if (!$throw) { return null; @@ -218,7 +218,7 @@ protected function findTemplate(string $name, bool $throw = true) } } - $this->errorCache[$name] = sprintf('Unable to find template "%s" (looked into: %s).', $name, implode(', ', $this->paths[$namespace])); + $this->errorCache[$name] = \sprintf('Unable to find template "%s" (looked into: %s).', $name, implode(', ', $this->paths[$namespace])); if (!$throw) { return null; @@ -236,7 +236,7 @@ private function parseName(string $name, string $default = self::MAIN_NAMESPACE) { if (isset($name[0]) && '@' == $name[0]) { if (false === $pos = strpos($name, '/')) { - throw new LoaderError(sprintf('Malformed namespaced template name "%s" (expecting "@namespace/template_name").', $name)); + throw new LoaderError(\sprintf('Malformed namespaced template name "%s" (expecting "@namespace/template_name").', $name)); } $namespace = substr($name, 1, $pos - 1); @@ -265,7 +265,7 @@ private function validateName(string $name): void } if ($level < 0) { - throw new LoaderError(sprintf('Looks like you try to load a template outside configured directories (%s).', $name)); + throw new LoaderError(\sprintf('Looks like you try to load a template outside configured directories (%s).', $name)); } } } diff --git a/upload/system/storage/vendor/twig/twig/src/Node/BlockNode.php b/upload/system/storage/vendor/twig/twig/src/Node/BlockNode.php index 65174c02c..15973a343 100644 --- a/upload/system/storage/vendor/twig/twig/src/Node/BlockNode.php +++ b/upload/system/storage/vendor/twig/twig/src/Node/BlockNode.php @@ -32,7 +32,7 @@ public function compile(Compiler $compiler): void { $compiler ->addDebugInfo($this) - ->write(sprintf("public function block_%s(\$context, array \$blocks = [])\n", $this->getAttribute('name')), "{\n") + ->write(\sprintf("public function block_%s(\$context, array \$blocks = [])\n", $this->getAttribute('name')), "{\n") ->indent() ->write("\$macros = \$this->macros;\n") ; diff --git a/upload/system/storage/vendor/twig/twig/src/Node/BlockReferenceNode.php b/upload/system/storage/vendor/twig/twig/src/Node/BlockReferenceNode.php index f48082be3..23c73eabe 100644 --- a/upload/system/storage/vendor/twig/twig/src/Node/BlockReferenceNode.php +++ b/upload/system/storage/vendor/twig/twig/src/Node/BlockReferenceNode.php @@ -32,7 +32,7 @@ public function compile(Compiler $compiler): void { $compiler ->addDebugInfo($this) - ->write(sprintf("yield from \$this->unwrap()->yieldBlock('%s', \$context, \$blocks);\n", $this->getAttribute('name'))) + ->write(\sprintf("yield from \$this->unwrap()->yieldBlock('%s', \$context, \$blocks);\n", $this->getAttribute('name'))) ; } } diff --git a/upload/system/storage/vendor/twig/twig/src/Node/CheckSecurityCallNode.php b/upload/system/storage/vendor/twig/twig/src/Node/CheckSecurityCallNode.php index 66aaeb52c..9c162d129 100644 --- a/upload/system/storage/vendor/twig/twig/src/Node/CheckSecurityCallNode.php +++ b/upload/system/storage/vendor/twig/twig/src/Node/CheckSecurityCallNode.php @@ -23,7 +23,7 @@ class CheckSecurityCallNode extends Node public function compile(Compiler $compiler) { $compiler - ->write("\$this->sandbox = \$this->env->getExtension(SandboxExtension::class);\n") + ->write("\$this->sandbox = \$this->extensions[SandboxExtension::class];\n") ->write("\$this->checkSecurity();\n") ; } diff --git a/upload/system/storage/vendor/twig/twig/src/Node/DeprecatedNode.php b/upload/system/storage/vendor/twig/twig/src/Node/DeprecatedNode.php index 2dc425dd3..afeb8332e 100644 --- a/upload/system/storage/vendor/twig/twig/src/Node/DeprecatedNode.php +++ b/upload/system/storage/vendor/twig/twig/src/Node/DeprecatedNode.php @@ -35,21 +35,39 @@ public function compile(Compiler $compiler): void $expr = $this->getNode('expr'); - if ($expr instanceof ConstantExpression) { - $compiler->write('@trigger_error(') - ->subcompile($expr); - } else { + if (!$expr instanceof ConstantExpression) { $varName = $compiler->getVarName(); - $compiler->write(sprintf('$%s = ', $varName)) + $compiler + ->write(\sprintf('$%s = ', $varName)) ->subcompile($expr) ->raw(";\n") - ->write(sprintf('@trigger_error($%s', $varName)); + ; + } + + $compiler->write('trigger_deprecation('); + if ($this->hasNode('package')) { + $compiler->subcompile($this->getNode('package')); + } else { + $compiler->raw("''"); + } + $compiler->raw(', '); + if ($this->hasNode('version')) { + $compiler->subcompile($this->getNode('version')); + } else { + $compiler->raw("''"); + } + $compiler->raw(', '); + + if ($expr instanceof ConstantExpression) { + $compiler->subcompile($expr); + } else { + $compiler->write(\sprintf('$%s', $varName)); } $compiler - ->raw('.') - ->string(sprintf(' ("%s" at line %d).', $this->getTemplateName(), $this->getTemplateLine())) - ->raw(", E_USER_DEPRECATED);\n") + ->raw(".") + ->string(\sprintf(' in "%s" at line %d.', $this->getTemplateName(), $this->getTemplateLine())) + ->raw(");\n") ; } } diff --git a/upload/system/storage/vendor/twig/twig/src/Node/Expression/AbstractExpression.php b/upload/system/storage/vendor/twig/twig/src/Node/Expression/AbstractExpression.php index 42da0559d..1692f5671 100644 --- a/upload/system/storage/vendor/twig/twig/src/Node/Expression/AbstractExpression.php +++ b/upload/system/storage/vendor/twig/twig/src/Node/Expression/AbstractExpression.php @@ -21,4 +21,8 @@ */ abstract class AbstractExpression extends Node { + public function isGenerator(): bool + { + return $this->hasAttribute('is_generator') && $this->getAttribute('is_generator'); + } } diff --git a/upload/system/storage/vendor/twig/twig/src/Node/Expression/Binary/EndsWithBinary.php b/upload/system/storage/vendor/twig/twig/src/Node/Expression/Binary/EndsWithBinary.php index 73fa20b1f..a73a5608d 100644 --- a/upload/system/storage/vendor/twig/twig/src/Node/Expression/Binary/EndsWithBinary.php +++ b/upload/system/storage/vendor/twig/twig/src/Node/Expression/Binary/EndsWithBinary.php @@ -20,11 +20,11 @@ public function compile(Compiler $compiler): void $left = $compiler->getVarName(); $right = $compiler->getVarName(); $compiler - ->raw(sprintf('(is_string($%s = ', $left)) + ->raw(\sprintf('(is_string($%s = ', $left)) ->subcompile($this->getNode('left')) - ->raw(sprintf(') && is_string($%s = ', $right)) + ->raw(\sprintf(') && is_string($%s = ', $right)) ->subcompile($this->getNode('right')) - ->raw(sprintf(') && str_ends_with($%1$s, $%2$s))', $left, $right)) + ->raw(\sprintf(') && str_ends_with($%1$s, $%2$s))', $left, $right)) ; } diff --git a/upload/system/storage/vendor/twig/twig/src/Node/Expression/Binary/StartsWithBinary.php b/upload/system/storage/vendor/twig/twig/src/Node/Expression/Binary/StartsWithBinary.php index 22eff92a7..4519f30d9 100644 --- a/upload/system/storage/vendor/twig/twig/src/Node/Expression/Binary/StartsWithBinary.php +++ b/upload/system/storage/vendor/twig/twig/src/Node/Expression/Binary/StartsWithBinary.php @@ -20,11 +20,11 @@ public function compile(Compiler $compiler): void $left = $compiler->getVarName(); $right = $compiler->getVarName(); $compiler - ->raw(sprintf('(is_string($%s = ', $left)) + ->raw(\sprintf('(is_string($%s = ', $left)) ->subcompile($this->getNode('left')) - ->raw(sprintf(') && is_string($%s = ', $right)) + ->raw(\sprintf(') && is_string($%s = ', $right)) ->subcompile($this->getNode('right')) - ->raw(sprintf(') && str_starts_with($%1$s, $%2$s))', $left, $right)) + ->raw(\sprintf(') && str_starts_with($%1$s, $%2$s))', $left, $right)) ; } diff --git a/upload/system/storage/vendor/twig/twig/src/Node/Expression/BlockReferenceExpression.php b/upload/system/storage/vendor/twig/twig/src/Node/Expression/BlockReferenceExpression.php index 13e72df17..629382233 100644 --- a/upload/system/storage/vendor/twig/twig/src/Node/Expression/BlockReferenceExpression.php +++ b/upload/system/storage/vendor/twig/twig/src/Node/Expression/BlockReferenceExpression.php @@ -66,7 +66,7 @@ private function compileTemplateCall(Compiler $compiler, string $method): Compil ; } - $compiler->raw(sprintf('->unwrap()->%s', $method)); + $compiler->raw(\sprintf('->unwrap()->%s', $method)); return $this->compileBlockArguments($compiler); } diff --git a/upload/system/storage/vendor/twig/twig/src/Node/Expression/CallExpression.php b/upload/system/storage/vendor/twig/twig/src/Node/Expression/CallExpression.php index d6ac5fc46..cd81df47a 100644 --- a/upload/system/storage/vendor/twig/twig/src/Node/Expression/CallExpression.php +++ b/upload/system/storage/vendor/twig/twig/src/Node/Expression/CallExpression.php @@ -15,10 +15,11 @@ use Twig\Error\SyntaxError; use Twig\Extension\ExtensionInterface; use Twig\Node\Node; +use Twig\Util\ReflectionCallable; abstract class CallExpression extends AbstractExpression { - private $reflector; + private $reflector = null; protected function compileCallable(Compiler $compiler) { @@ -27,28 +28,30 @@ protected function compileCallable(Compiler $compiler) if (\is_string($callable) && !str_contains($callable, '::')) { $compiler->raw($callable); } else { - [$r, $callable] = $this->reflectCallable($callable); + $rc = $this->reflectCallable($callable); + $r = $rc->getReflector(); + $callable = $rc->getCallable(); if (\is_string($callable)) { $compiler->raw($callable); } elseif (\is_array($callable) && \is_string($callable[0])) { if (!$r instanceof \ReflectionMethod || $r->isStatic()) { - $compiler->raw(sprintf('%s::%s', $callable[0], $callable[1])); + $compiler->raw(\sprintf('%s::%s', $callable[0], $callable[1])); } else { - $compiler->raw(sprintf('$this->env->getRuntime(\'%s\')->%s', $callable[0], $callable[1])); + $compiler->raw(\sprintf('$this->env->getRuntime(\'%s\')->%s', $callable[0], $callable[1])); } } elseif (\is_array($callable) && $callable[0] instanceof ExtensionInterface) { $class = \get_class($callable[0]); if (!$compiler->getEnvironment()->hasExtension($class)) { // Compile a non-optimized call to trigger a \Twig\Error\RuntimeError, which cannot be a compile-time error - $compiler->raw(sprintf('$this->env->getExtension(\'%s\')', $class)); + $compiler->raw(\sprintf('$this->env->getExtension(\'%s\')', $class)); } else { - $compiler->raw(sprintf('$this->extensions[\'%s\']', ltrim($class, '\\'))); + $compiler->raw(\sprintf('$this->extensions[\'%s\']', ltrim($class, '\\'))); } - $compiler->raw(sprintf('->%s', $callable[1])); + $compiler->raw(\sprintf('->%s', $callable[1])); } else { - $compiler->raw(sprintf('$this->env->get%s(\'%s\')->getCallable()', ucfirst($this->getAttribute('type')), $this->getAttribute('name'))); + $compiler->raw(\sprintf('$this->env->get%s(\'%s\')->getCallable()', ucfirst($this->getAttribute('type')), $this->getAttribute('name'))); } } @@ -57,6 +60,10 @@ protected function compileCallable(Compiler $compiler) protected function compileArguments(Compiler $compiler, $isArray = false): void { + if (\func_num_args() >= 2) { + trigger_deprecation('twig/twig', '3.11', 'Passing a second argument to "%s()" is deprecated.', __METHOD__); + } + $compiler->raw($isArray ? '[' : '('); $first = true; @@ -127,7 +134,7 @@ protected function getArguments($callable, $arguments) $named = true; $name = $this->normalizeName($name); } elseif ($named) { - throw new SyntaxError(sprintf('Positional arguments cannot be used after named arguments for %s "%s".', $callType, $callName), $this->getTemplateLine(), $this->getSourceContext()); + throw new SyntaxError(\sprintf('Positional arguments cannot be used after named arguments for %s "%s".', $callType, $callName), $this->getTemplateLine(), $this->getSourceContext()); } $parameters[$name] = $node; @@ -140,9 +147,9 @@ protected function getArguments($callable, $arguments) if (!$callable) { if ($named) { - $message = sprintf('Named arguments are not supported for %s "%s".', $callType, $callName); + $message = \sprintf('Named arguments are not supported for %s "%s".', $callType, $callName); } else { - $message = sprintf('Arbitrary positional arguments are not supported for %s "%s".', $callType, $callName); + $message = \sprintf('Arbitrary positional arguments are not supported for %s "%s".', $callType, $callName); } throw new \LogicException($message); @@ -168,11 +175,11 @@ protected function getArguments($callable, $arguments) if (\array_key_exists($name, $parameters)) { if (\array_key_exists($pos, $parameters)) { - throw new SyntaxError(sprintf('Argument "%s" is defined twice for %s "%s".', $name, $callType, $callName), $this->getTemplateLine(), $this->getSourceContext()); + throw new SyntaxError(\sprintf('Argument "%s" is defined twice for %s "%s".', $name, $callType, $callName), $this->getTemplateLine(), $this->getSourceContext()); } if (\count($missingArguments)) { - throw new SyntaxError(sprintf( + throw new SyntaxError(\sprintf( 'Argument "%s" could not be assigned for %s "%s(%s)" because it is mapped to an internal PHP function which cannot determine default value for optional argument%s "%s".', $name, $callType, $callName, implode(', ', $names), \count($missingArguments) > 1 ? 's' : '', implode('", "', $missingArguments) ), $this->getTemplateLine(), $this->getSourceContext()); @@ -197,7 +204,7 @@ protected function getArguments($callable, $arguments) $missingArguments[] = $name; } } else { - throw new SyntaxError(sprintf('Value for argument "%s" is required for %s "%s".', $name, $callType, $callName), $this->getTemplateLine(), $this->getSourceContext()); + throw new SyntaxError(\sprintf('Value for argument "%s" is required for %s "%s".', $name, $callType, $callName), $this->getTemplateLine(), $this->getSourceContext()); } } @@ -228,7 +235,7 @@ protected function getArguments($callable, $arguments) } throw new SyntaxError( - sprintf( + \sprintf( 'Unknown argument%s "%s" for %s "%s(%s)".', \count($parameters) > 1 ? 's' : '', implode('", "', array_keys($parameters)), $callType, $callName, implode(', ', $names) ), @@ -247,7 +254,9 @@ protected function normalizeName(string $name): string private function getCallableParameters($callable, bool $isVariadic): array { - [$r, , $callableName] = $this->reflectCallable($callable); + $rc = $this->reflectCallable($callable); + $r = $rc->getReflector(); + $callableName = $rc->getName(); $parameters = $r->getParameters(); if ($this->hasNode('node')) { @@ -270,63 +279,26 @@ private function getCallableParameters($callable, bool $isVariadic): array $isPhpVariadic = false; if ($isVariadic) { $argument = end($parameters); - $isArray = $argument && $argument->hasType() && 'array' === $argument->getType()->getName(); + $isArray = $argument && $argument->hasType() && $argument->getType() instanceof \ReflectionNamedType && 'array' === $argument->getType()->getName(); if ($isArray && $argument->isDefaultValueAvailable() && [] === $argument->getDefaultValue()) { array_pop($parameters); } elseif ($argument && $argument->isVariadic()) { array_pop($parameters); $isPhpVariadic = true; } else { - throw new \LogicException(sprintf('The last parameter of "%s" for %s "%s" must be an array with default value, eg. "array $arg = []".', $callableName, $this->getAttribute('type'), $this->getAttribute('name'))); + throw new \LogicException(\sprintf('The last parameter of "%s" for %s "%s" must be an array with default value, eg. "array $arg = []".', $callableName, $this->getAttribute('type'), $this->getAttribute('name'))); } } return [$parameters, $isPhpVariadic]; } - private function reflectCallable($callable) + private function reflectCallable($callable): ReflectionCallable { - if (null !== $this->reflector) { - return $this->reflector; - } - - if (\is_string($callable) && false !== $pos = strpos($callable, '::')) { - $callable = [substr($callable, 0, $pos), substr($callable, 2 + $pos)]; - } - - if (\is_array($callable) && method_exists($callable[0], $callable[1])) { - $r = new \ReflectionMethod($callable[0], $callable[1]); - - return $this->reflector = [$r, $callable, $r->class.'::'.$r->name]; - } - - $checkVisibility = $callable instanceof \Closure; - try { - $closure = \Closure::fromCallable($callable); - } catch (\TypeError $e) { - throw new \LogicException(sprintf('Callback for %s "%s" is not callable in the current scope.', $this->getAttribute('type'), $this->getAttribute('name')), 0, $e); - } - $r = new \ReflectionFunction($closure); - - if (str_contains($r->name, '{closure')) { - return $this->reflector = [$r, $callable, 'Closure']; - } - - if ($object = $r->getClosureThis()) { - $callable = [$object, $r->name]; - $callableName = get_debug_type($object).'::'.$r->name; - } elseif (\PHP_VERSION_ID >= 80111 && $class = $r->getClosureCalledClass()) { - $callableName = $class->name.'::'.$r->name; - } elseif (\PHP_VERSION_ID < 80111 && $class = $r->getClosureScopeClass()) { - $callableName = (\is_array($callable) ? $callable[0] : $class->name).'::'.$r->name; - } else { - $callable = $callableName = $r->name; - } - - if ($checkVisibility && \is_array($callable) && method_exists(...$callable) && !(new \ReflectionMethod(...$callable))->isPublic()) { - $callable = $r->getClosure(); + if (!$this->reflector) { + $this->reflector = new ReflectionCallable($callable, $this->getAttribute('type'), $this->getAttribute('name')); } - return $this->reflector = [$r, $callable, $callableName]; + return $this->reflector; } } diff --git a/upload/system/storage/vendor/twig/twig/src/Node/Expression/ConstantExpression.php b/upload/system/storage/vendor/twig/twig/src/Node/Expression/ConstantExpression.php index 7ddbcc6fa..2a8909d54 100644 --- a/upload/system/storage/vendor/twig/twig/src/Node/Expression/ConstantExpression.php +++ b/upload/system/storage/vendor/twig/twig/src/Node/Expression/ConstantExpression.php @@ -14,6 +14,9 @@ use Twig\Compiler; +/** + * @final + */ class ConstantExpression extends AbstractExpression { public function __construct($value, int $lineno) diff --git a/upload/system/storage/vendor/twig/twig/src/Node/Expression/Filter/RawFilter.php b/upload/system/storage/vendor/twig/twig/src/Node/Expression/Filter/RawFilter.php new file mode 100644 index 000000000..584942306 --- /dev/null +++ b/upload/system/storage/vendor/twig/twig/src/Node/Expression/Filter/RawFilter.php @@ -0,0 +1,40 @@ + + */ +class RawFilter extends FilterExpression +{ + public function __construct(Node $node, ?ConstantExpression $filterName = null, ?Node $arguments = null, int $lineno = 0, ?string $tag = null) + { + if (null === $filterName) { + $filterName = new ConstantExpression('raw', $node->getTemplateLine()); + } + if (null === $arguments) { + $arguments = new Node(); + } + + parent::__construct($node, $filterName, $arguments, $lineno ?: $node->getTemplateLine(), $tag ?: $node->getNodeTag()); + } + + public function compile(Compiler $compiler): void + { + $compiler->subcompile($this->getNode('node')); + } +} diff --git a/upload/system/storage/vendor/twig/twig/src/Node/Expression/FilterExpression.php b/upload/system/storage/vendor/twig/twig/src/Node/Expression/FilterExpression.php index c803d5708..251870ae5 100644 --- a/upload/system/storage/vendor/twig/twig/src/Node/Expression/FilterExpression.php +++ b/upload/system/storage/vendor/twig/twig/src/Node/Expression/FilterExpression.php @@ -19,16 +19,25 @@ class FilterExpression extends CallExpression { public function __construct(Node $node, ConstantExpression $filterName, Node $arguments, int $lineno, ?string $tag = null) { - parent::__construct(['node' => $node, 'filter' => $filterName, 'arguments' => $arguments], [], $lineno, $tag); + parent::__construct(['node' => $node, 'filter' => $filterName, 'arguments' => $arguments], ['name' => $filterName->getAttribute('value'), 'type' => 'filter'], $lineno, $tag); } public function compile(Compiler $compiler): void { $name = $this->getNode('filter')->getAttribute('value'); + if ($name !== $this->getAttribute('name')) { + trigger_deprecation('twig/twig', '3.11', 'Changing the value of a "filter" node in a NodeVisitor class is not supported anymore.'); + $this->setAttribute('name', $name); + } + if ('raw' === $name) { + trigger_deprecation('twig/twig', '3.11', 'Creating the "raw" filter via "FilterExpression" is deprecated; use "RawFilter" instead.'); + + $compiler->subcompile($this->getNode('node')); + + return; + } $filter = $compiler->getEnvironment()->getFilter($name); - $this->setAttribute('name', $name); - $this->setAttribute('type', 'filter'); $this->setAttribute('needs_charset', $filter->needsCharset()); $this->setAttribute('needs_environment', $filter->needsEnvironment()); $this->setAttribute('needs_context', $filter->needsContext()); diff --git a/upload/system/storage/vendor/twig/twig/src/Node/Expression/FunctionExpression.php b/upload/system/storage/vendor/twig/twig/src/Node/Expression/FunctionExpression.php index d903a9e8f..ef99c401a 100644 --- a/upload/system/storage/vendor/twig/twig/src/Node/Expression/FunctionExpression.php +++ b/upload/system/storage/vendor/twig/twig/src/Node/Expression/FunctionExpression.php @@ -19,7 +19,7 @@ class FunctionExpression extends CallExpression { public function __construct(string $name, Node $arguments, int $lineno) { - parent::__construct(['arguments' => $arguments], ['name' => $name, 'is_defined_test' => false], $lineno); + parent::__construct(['arguments' => $arguments], ['name' => $name, 'type' => 'function', 'is_defined_test' => false], $lineno); } public function compile(Compiler $compiler) @@ -27,8 +27,6 @@ public function compile(Compiler $compiler) $name = $this->getAttribute('name'); $function = $compiler->getEnvironment()->getFunction($name); - $this->setAttribute('name', $name); - $this->setAttribute('type', 'function'); $this->setAttribute('needs_charset', $function->needsCharset()); $this->setAttribute('needs_environment', $function->needsEnvironment()); $this->setAttribute('needs_context', $function->needsContext()); diff --git a/upload/system/storage/vendor/twig/twig/src/Node/Expression/MethodCallExpression.php b/upload/system/storage/vendor/twig/twig/src/Node/Expression/MethodCallExpression.php index 6fa1c3f9e..01806f91d 100644 --- a/upload/system/storage/vendor/twig/twig/src/Node/Expression/MethodCallExpression.php +++ b/upload/system/storage/vendor/twig/twig/src/Node/Expression/MethodCallExpression.php @@ -46,7 +46,9 @@ public function compile(Compiler $compiler): void ->raw(', [') ; $first = true; - foreach ($this->getNode('arguments')->getKeyValuePairs() as $pair) { + /** @var ArrayExpression */ + $args = $this->getNode('arguments'); + foreach ($args->getKeyValuePairs() as $pair) { if (!$first) { $compiler->raw(', '); } diff --git a/upload/system/storage/vendor/twig/twig/src/Node/Expression/NameExpression.php b/upload/system/storage/vendor/twig/twig/src/Node/Expression/NameExpression.php index c3563f012..286aa5ae2 100644 --- a/upload/system/storage/vendor/twig/twig/src/Node/Expression/NameExpression.php +++ b/upload/system/storage/vendor/twig/twig/src/Node/Expression/NameExpression.php @@ -34,7 +34,7 @@ public function compile(Compiler $compiler): void $compiler->addDebugInfo($this); if ($this->getAttribute('is_defined_test')) { - if ($this->isSpecial()) { + if (isset($this->specialVars[$name])) { $compiler->repr(true); } elseif (\PHP_VERSION_ID >= 70400) { $compiler @@ -51,7 +51,7 @@ public function compile(Compiler $compiler): void ->raw(', $context))') ; } - } elseif ($this->isSpecial()) { + } elseif (isset($this->specialVars[$name])) { $compiler->raw($this->specialVars[$name]); } elseif ($this->getAttribute('always_defined')) { $compiler @@ -85,13 +85,23 @@ public function compile(Compiler $compiler): void } } + /** + * @deprecated since Twig 3.11 (to be removed in 4.0) + */ public function isSpecial() { + trigger_deprecation('twig/twig', '3.11', 'The "%s()" method is deprecated and will be removed in Twig 4.0.', __METHOD__); + return isset($this->specialVars[$this->getAttribute('name')]); } + /** + * @deprecated since Twig 3.11 (to be removed in 4.0) + */ public function isSimple() { + trigger_deprecation('twig/twig', '3.11', 'The "%s()" method is deprecated and will be removed in Twig 4.0.', __METHOD__); + return !$this->isSpecial() && !$this->getAttribute('is_defined_test'); } } diff --git a/upload/system/storage/vendor/twig/twig/src/Node/Expression/TestExpression.php b/upload/system/storage/vendor/twig/twig/src/Node/Expression/TestExpression.php index e518bd8f1..29c5a522c 100644 --- a/upload/system/storage/vendor/twig/twig/src/Node/Expression/TestExpression.php +++ b/upload/system/storage/vendor/twig/twig/src/Node/Expression/TestExpression.php @@ -23,16 +23,13 @@ public function __construct(Node $node, string $name, ?Node $arguments, int $lin $nodes['arguments'] = $arguments; } - parent::__construct($nodes, ['name' => $name], $lineno); + parent::__construct($nodes, ['name' => $name, 'type' => 'test'], $lineno); } public function compile(Compiler $compiler): void { - $name = $this->getAttribute('name'); - $test = $compiler->getEnvironment()->getTest($name); + $test = $compiler->getEnvironment()->getTest($this->getAttribute('name')); - $this->setAttribute('name', $name); - $this->setAttribute('type', 'test'); $this->setAttribute('arguments', $test->getArguments()); $this->setAttribute('callable', $test->getCallable()); $this->setAttribute('is_variadic', $test->isVariadic()); diff --git a/upload/system/storage/vendor/twig/twig/src/Node/IncludeNode.php b/upload/system/storage/vendor/twig/twig/src/Node/IncludeNode.php index f10779a80..7073fa4ac 100644 --- a/upload/system/storage/vendor/twig/twig/src/Node/IncludeNode.php +++ b/upload/system/storage/vendor/twig/twig/src/Node/IncludeNode.php @@ -42,10 +42,10 @@ public function compile(Compiler $compiler): void $template = $compiler->getVarName(); $compiler - ->write(sprintf("$%s = null;\n", $template)) + ->write(\sprintf("$%s = null;\n", $template)) ->write("try {\n") ->indent() - ->write(sprintf('$%s = ', $template)) + ->write(\sprintf('$%s = ', $template)) ; $this->addGetTemplate($compiler); @@ -58,9 +58,9 @@ public function compile(Compiler $compiler): void ->write("// ignore missing template\n") ->outdent() ->write("}\n") - ->write(sprintf("if ($%s) {\n", $template)) + ->write(\sprintf("if ($%s) {\n", $template)) ->indent() - ->write(sprintf('yield from $%s->unwrap()->yield(', $template)) + ->write(\sprintf('yield from $%s->unwrap()->yield(', $template)) ; $this->addTemplateArguments($compiler); diff --git a/upload/system/storage/vendor/twig/twig/src/Node/MacroNode.php b/upload/system/storage/vendor/twig/twig/src/Node/MacroNode.php index 78e1b6f76..a6048de9b 100644 --- a/upload/system/storage/vendor/twig/twig/src/Node/MacroNode.php +++ b/upload/system/storage/vendor/twig/twig/src/Node/MacroNode.php @@ -29,7 +29,7 @@ public function __construct(string $name, Node $body, Node $arguments, int $line { foreach ($arguments as $argumentName => $argument) { if (self::VARARGS_NAME === $argumentName) { - throw new SyntaxError(sprintf('The argument "%s" in macro "%s" cannot be defined because the variable "%s" is reserved for arbitrary arguments.', self::VARARGS_NAME, $name, self::VARARGS_NAME), $argument->getTemplateLine(), $argument->getSourceContext()); + throw new SyntaxError(\sprintf('The argument "%s" in macro "%s" cannot be defined because the variable "%s" is reserved for arbitrary arguments.', self::VARARGS_NAME, $name, self::VARARGS_NAME), $argument->getTemplateLine(), $argument->getSourceContext()); } } @@ -40,7 +40,7 @@ public function compile(Compiler $compiler): void { $compiler ->addDebugInfo($this) - ->write(sprintf('public function macro_%s(', $this->getAttribute('name'))) + ->write(\sprintf('public function macro_%s(', $this->getAttribute('name'))) ; $count = \count($this->getNode('arguments')); diff --git a/upload/system/storage/vendor/twig/twig/src/Node/ModuleNode.php b/upload/system/storage/vendor/twig/twig/src/Node/ModuleNode.php index df5d78d03..fb85cd895 100644 --- a/upload/system/storage/vendor/twig/twig/src/Node/ModuleNode.php +++ b/upload/system/storage/vendor/twig/twig/src/Node/ModuleNode.php @@ -191,14 +191,14 @@ protected function compileConstructor(Compiler $compiler) $compiler ->addDebugInfo($node) - ->write(sprintf('$_trait_%s = $this->loadTemplate(', $i)) + ->write(\sprintf('$_trait_%s = $this->loadTemplate(', $i)) ->subcompile($node) ->raw(', ') ->repr($node->getTemplateName()) ->raw(', ') ->repr($node->getTemplateLine()) ->raw(");\n") - ->write(sprintf("if (!\$_trait_%s->unwrap()->isTraitable()) {\n", $i)) + ->write(\sprintf("if (!\$_trait_%s->unwrap()->isTraitable()) {\n", $i)) ->indent() ->write("throw new RuntimeError('Template \"'.") ->subcompile($trait->getNode('template')) @@ -207,12 +207,12 @@ protected function compileConstructor(Compiler $compiler) ->raw(", \$this->source);\n") ->outdent() ->write("}\n") - ->write(sprintf("\$_trait_%s_blocks = \$_trait_%s->unwrap()->getBlocks();\n\n", $i, $i)) + ->write(\sprintf("\$_trait_%s_blocks = \$_trait_%s->unwrap()->getBlocks();\n\n", $i, $i)) ; foreach ($trait->getNode('targets') as $key => $value) { $compiler - ->write(sprintf('if (!isset($_trait_%s_blocks[', $i)) + ->write(\sprintf('if (!isset($_trait_%s_blocks[', $i)) ->string($key) ->raw("])) {\n") ->indent() @@ -226,11 +226,11 @@ protected function compileConstructor(Compiler $compiler) ->outdent() ->write("}\n\n") - ->write(sprintf('$_trait_%s_blocks[', $i)) + ->write(\sprintf('$_trait_%s_blocks[', $i)) ->subcompile($value) - ->raw(sprintf('] = $_trait_%s_blocks[', $i)) + ->raw(\sprintf('] = $_trait_%s_blocks[', $i)) ->string($key) - ->raw(sprintf(']; unset($_trait_%s_blocks[', $i)) + ->raw(\sprintf(']; unset($_trait_%s_blocks[', $i)) ->string($key) ->raw("]);\n\n") ; @@ -245,7 +245,7 @@ protected function compileConstructor(Compiler $compiler) for ($i = 0; $i < $countTraits; ++$i) { $compiler - ->write(sprintf('$_trait_%s_blocks'.($i == $countTraits - 1 ? '' : ',')."\n", $i)) + ->write(\sprintf('$_trait_%s_blocks'.($i == $countTraits - 1 ? '' : ',')."\n", $i)) ; } @@ -278,7 +278,7 @@ protected function compileConstructor(Compiler $compiler) foreach ($this->getNode('blocks') as $name => $node) { $compiler - ->write(sprintf("'%s' => [\$this, 'block_%s'],\n", $name, $name)) + ->write(\sprintf("'%s' => [\$this, 'block_%s'],\n", $name, $name)) ; } @@ -443,7 +443,7 @@ protected function compileDebugInfo(Compiler $compiler) ->write(" */\n") ->write("public function getDebugInfo()\n", "{\n") ->indent() - ->write(sprintf("return %s;\n", str_replace("\n", '', var_export(array_reverse($compiler->getDebugInfo(), true), true)))) + ->write(\sprintf("return %s;\n", str_replace("\n", '', var_export(array_reverse($compiler->getDebugInfo(), true), true)))) ->outdent() ->write("}\n\n") ; @@ -470,7 +470,7 @@ protected function compileLoadTemplate(Compiler $compiler, $node, $var) { if ($node instanceof ConstantExpression) { $compiler - ->write(sprintf('%s = $this->loadTemplate(', $var)) + ->write(\sprintf('%s = $this->loadTemplate(', $var)) ->subcompile($node) ->raw(', ') ->repr($node->getTemplateName()) diff --git a/upload/system/storage/vendor/twig/twig/src/Node/NameDeprecation.php b/upload/system/storage/vendor/twig/twig/src/Node/NameDeprecation.php new file mode 100644 index 000000000..63ab28576 --- /dev/null +++ b/upload/system/storage/vendor/twig/twig/src/Node/NameDeprecation.php @@ -0,0 +1,46 @@ + + */ +class NameDeprecation +{ + private $package; + private $version; + private $newName; + + public function __construct(string $package = '', string $version = '', string $newName = '') + { + $this->package = $package; + $this->version = $version; + $this->newName = $newName; + } + + public function getPackage(): string + { + return $this->package; + } + + public function getVersion(): string + { + return $this->version; + } + + public function getNewName(): string + { + return $this->newName; + } +} diff --git a/upload/system/storage/vendor/twig/twig/src/Node/Node.php b/upload/system/storage/vendor/twig/twig/src/Node/Node.php index 4ac94f1bc..5ef661f5e 100644 --- a/upload/system/storage/vendor/twig/twig/src/Node/Node.php +++ b/upload/system/storage/vendor/twig/twig/src/Node/Node.php @@ -30,6 +30,10 @@ class Node implements \Countable, \IteratorAggregate protected $tag; private $sourceContext; + /** @var array */ + private $nodeNameDeprecations = []; + /** @var array */ + private $attributeNameDeprecations = []; /** * @param array $nodes An array of named nodes @@ -41,7 +45,7 @@ public function __construct(array $nodes = [], array $attributes = [], int $line { foreach ($nodes as $name => $node) { if (!$node instanceof self) { - throw new \InvalidArgumentException(sprintf('Using "%s" for the value of node "%s" of "%s" is not supported. You must pass a \Twig\Node\Node instance.', \is_object($node) ? \get_class($node) : (null === $node ? 'null' : \gettype($node)), $name, static::class)); + throw new \InvalidArgumentException(\sprintf('Using "%s" for the value of node "%s" of "%s" is not supported. You must pass a \Twig\Node\Node instance.', \is_object($node) ? \get_class($node) : (null === $node ? 'null' : \gettype($node)), $name, static::class)); } } $this->nodes = $nodes; @@ -54,7 +58,7 @@ public function __toString() { $attributes = []; foreach ($this->attributes as $name => $value) { - $attributes[] = sprintf('%s: %s', $name, str_replace("\n", '', var_export($value, true))); + $attributes[] = \sprintf('%s: %s', $name, \is_callable($value) ? '\Closure' : str_replace("\n", '', var_export($value, true))); } $repr = [static::class.'('.implode(', ', $attributes)]; @@ -67,7 +71,7 @@ public function __toString() $noderepr[] = str_repeat(' ', $len).$line; } - $repr[] = sprintf(' %s: %s', $name, ltrim(implode("\n", $noderepr))); + $repr[] = \sprintf(' %s: %s', $name, ltrim(implode("\n", $noderepr))); } $repr[] = ')'; @@ -106,7 +110,17 @@ public function hasAttribute(string $name): bool public function getAttribute(string $name) { if (!\array_key_exists($name, $this->attributes)) { - throw new \LogicException(sprintf('Attribute "%s" does not exist for Node "%s".', $name, static::class)); + throw new \LogicException(\sprintf('Attribute "%s" does not exist for Node "%s".', $name, static::class)); + } + + $triggerDeprecation = \func_num_args() > 1 ? func_get_arg(1) : true; + if ($triggerDeprecation && isset($this->attributeNameDeprecations[$name])) { + $dep = $this->attributeNameDeprecations[$name]; + if ($dep->getNewName()) { + trigger_deprecation($dep->getPackage(), $dep->getVersion(), 'Getting attribute "%s" on a "%s" class is deprecated, get the "%s" attribute instead.', $name, static::class, $dep->getNewName()); + } else { + trigger_deprecation($dep->getPackage(), $dep->getVersion(), 'Getting attribute "%s" on a "%s" class is deprecated.', $name, static::class); + } } return $this->attributes[$name]; @@ -114,9 +128,24 @@ public function getAttribute(string $name) public function setAttribute(string $name, $value): void { + $triggerDeprecation = \func_num_args() > 2 ? func_get_arg(2) : true; + if ($triggerDeprecation && isset($this->attributeNameDeprecations[$name])) { + $dep = $this->attributeNameDeprecations[$name]; + if ($dep->getNewName()) { + trigger_deprecation($dep->getPackage(), $dep->getVersion(), 'Setting attribute "%s" on a "%s" class is deprecated, set the "%s" attribute instead.', $name, static::class, $dep->getNewName()); + } else { + trigger_deprecation($dep->getPackage(), $dep->getVersion(), 'Setting attribute "%s" on a "%s" class is deprecated.', $name, static::class); + } + } + $this->attributes[$name] = $value; } + public function deprecateAttribute(string $name, NameDeprecation $dep): void + { + $this->attributeNameDeprecations[$name] = $dep; + } + public function removeAttribute(string $name): void { unset($this->attributes[$name]); @@ -130,7 +159,17 @@ public function hasNode(string $name): bool public function getNode(string $name): self { if (!isset($this->nodes[$name])) { - throw new \LogicException(sprintf('Node "%s" does not exist for Node "%s".', $name, static::class)); + throw new \LogicException(\sprintf('Node "%s" does not exist for Node "%s".', $name, static::class)); + } + + $triggerDeprecation = \func_num_args() > 1 ? func_get_arg(1) : true; + if ($triggerDeprecation && isset($this->nodeNameDeprecations[$name])) { + $dep = $this->nodeNameDeprecations[$name]; + if ($dep->getNewName()) { + trigger_deprecation($dep->getPackage(), $dep->getVersion(), 'Getting node "%s" on a "%s" class is deprecated, get the "%s" node instead.', $name, static::class, $dep->getNewName()); + } else { + trigger_deprecation($dep->getPackage(), $dep->getVersion(), 'Getting node "%s" on a "%s" class is deprecated.', $name, static::class); + } } return $this->nodes[$name]; @@ -138,6 +177,16 @@ public function getNode(string $name): self public function setNode(string $name, self $node): void { + $triggerDeprecation = \func_num_args() > 2 ? func_get_arg(2) : true; + if ($triggerDeprecation && isset($this->nodeNameDeprecations[$name])) { + $dep = $this->nodeNameDeprecations[$name]; + if ($dep->getNewName()) { + trigger_deprecation($dep->getPackage(), $dep->getVersion(), 'Setting node "%s" on a "%s" class is deprecated, set the "%s" node instead.', $name, static::class, $dep->getNewName()); + } else { + trigger_deprecation($dep->getPackage(), $dep->getVersion(), 'Setting node "%s" on a "%s" class is deprecated.', $name, static::class); + } + } + if (null !== $this->sourceContext) { $node->setSourceContext($this->sourceContext); } @@ -149,6 +198,11 @@ public function removeNode(string $name): void unset($this->nodes[$name]); } + public function deprecateNode(string $name, NameDeprecation $dep): void + { + $this->nodeNameDeprecations[$name] = $dep; + } + /** * @return int */ diff --git a/upload/system/storage/vendor/twig/twig/src/Node/PrintNode.php b/upload/system/storage/vendor/twig/twig/src/Node/PrintNode.php index a6a89bd74..da442d852 100644 --- a/upload/system/storage/vendor/twig/twig/src/Node/PrintNode.php +++ b/upload/system/storage/vendor/twig/twig/src/Node/PrintNode.php @@ -31,11 +31,13 @@ public function __construct(AbstractExpression $expr, int $lineno, ?string $tag public function compile(Compiler $compiler): void { - $compiler->addDebugInfo($this); + /** @var AbstractExpression */ + $expr = $this->getNode('expr'); $compiler - ->write('yield ') - ->subcompile($this->getNode('expr')) + ->addDebugInfo($this) + ->write($expr->isGenerator() ? 'yield from ' : 'yield ') + ->subcompile($expr) ->raw(";\n") ; } diff --git a/upload/system/storage/vendor/twig/twig/src/Node/WithNode.php b/upload/system/storage/vendor/twig/twig/src/Node/WithNode.php index 9b8c57884..a7b7e70d9 100644 --- a/upload/system/storage/vendor/twig/twig/src/Node/WithNode.php +++ b/upload/system/storage/vendor/twig/twig/src/Node/WithNode.php @@ -38,35 +38,35 @@ public function compile(Compiler $compiler): void $parentContextName = $compiler->getVarName(); - $compiler->write(sprintf("\$%s = \$context;\n", $parentContextName)); + $compiler->write(\sprintf("\$%s = \$context;\n", $parentContextName)); if ($this->hasNode('variables')) { $node = $this->getNode('variables'); $varsName = $compiler->getVarName(); $compiler - ->write(sprintf('$%s = ', $varsName)) + ->write(\sprintf('$%s = ', $varsName)) ->subcompile($node) ->raw(";\n") - ->write(sprintf("if (!is_iterable(\$%s)) {\n", $varsName)) + ->write(\sprintf("if (!is_iterable(\$%s)) {\n", $varsName)) ->indent() - ->write("throw new RuntimeError('Variables passed to the \"with\" tag must be a hash.', ") + ->write("throw new RuntimeError('Variables passed to the \"with\" tag must be a mapping.', ") ->repr($node->getTemplateLine()) ->raw(", \$this->getSourceContext());\n") ->outdent() ->write("}\n") - ->write(sprintf("\$%s = CoreExtension::toArray(\$%s);\n", $varsName, $varsName)) + ->write(\sprintf("\$%s = CoreExtension::toArray(\$%s);\n", $varsName, $varsName)) ; if ($this->getAttribute('only')) { $compiler->write("\$context = [];\n"); } - $compiler->write(sprintf("\$context = \$this->env->mergeGlobals(array_merge(\$context, \$%s));\n", $varsName)); + $compiler->write(\sprintf("\$context = \$this->env->mergeGlobals(array_merge(\$context, \$%s));\n", $varsName)); } $compiler ->subcompile($this->getNode('body')) - ->write(sprintf("\$context = \$%s;\n", $parentContextName)) + ->write(\sprintf("\$context = \$%s;\n", $parentContextName)) ; } } diff --git a/upload/system/storage/vendor/twig/twig/src/NodeVisitor/OptimizerNodeVisitor.php b/upload/system/storage/vendor/twig/twig/src/NodeVisitor/OptimizerNodeVisitor.php index 6af056ac4..55f5d6eb9 100644 --- a/upload/system/storage/vendor/twig/twig/src/NodeVisitor/OptimizerNodeVisitor.php +++ b/upload/system/storage/vendor/twig/twig/src/NodeVisitor/OptimizerNodeVisitor.php @@ -15,7 +15,6 @@ use Twig\Node\BlockReferenceNode; use Twig\Node\Expression\BlockReferenceExpression; use Twig\Node\Expression\ConstantExpression; -use Twig\Node\Expression\FilterExpression; use Twig\Node\Expression\FunctionExpression; use Twig\Node\Expression\GetAttrExpression; use Twig\Node\Expression\NameExpression; @@ -55,8 +54,12 @@ final class OptimizerNodeVisitor implements NodeVisitorInterface */ public function __construct(int $optimizers = -1) { - if ($optimizers > (self::OPTIMIZE_FOR | self::OPTIMIZE_RAW_FILTER)) { - throw new \InvalidArgumentException(sprintf('Optimizer mode "%s" is not valid.', $optimizers)); + if ($optimizers > (self::OPTIMIZE_FOR | self::OPTIMIZE_RAW_FILTER | self::OPTIMIZE_TEXT_NODES)) { + throw new \InvalidArgumentException(\sprintf('Optimizer mode "%s" is not valid.', $optimizers)); + } + + if (-1 !== $optimizers && self::OPTIMIZE_RAW_FILTER === (self::OPTIMIZE_RAW_FILTER & $optimizers)) { + trigger_deprecation('twig/twig', '3.11', 'The "Twig\NodeVisitor\OptimizerNodeVisitor::OPTIMIZE_RAW_FILTER" option is deprecated and does nothing.'); } $this->optimizers = $optimizers; @@ -77,10 +80,6 @@ public function leaveNode(Node $node, Environment $env): ?Node $this->leaveOptimizeFor($node); } - if (self::OPTIMIZE_RAW_FILTER === (self::OPTIMIZE_RAW_FILTER & $this->optimizers)) { - $node = $this->optimizeRawFilter($node); - } - $node = $this->optimizePrintNode($node); if (self::OPTIMIZE_TEXT_NODES === (self::OPTIMIZE_TEXT_NODES & $this->optimizers)) { @@ -107,7 +106,7 @@ private function mergeTextNodeCalls(Node $node): Node return $node; } - if (Node::class === get_class($node)) { + if (Node::class === \get_class($node)) { return new TextNode($text, $node->getTemplateLine()); } @@ -153,18 +152,6 @@ private function optimizePrintNode(Node $node): Node return $node; } - /** - * Removes "raw" filters. - */ - private function optimizeRawFilter(Node $node): Node - { - if ($node instanceof FilterExpression && 'raw' == $node->getNode('filter')->getAttribute('value')) { - return $node->getNode('node'); - } - - return $node; - } - /** * Optimizes "for" tag by removing the "loop" variable creation whenever possible. */ diff --git a/upload/system/storage/vendor/twig/twig/src/NodeVisitor/SandboxNodeVisitor.php b/upload/system/storage/vendor/twig/twig/src/NodeVisitor/SandboxNodeVisitor.php index d1108394f..68020885e 100644 --- a/upload/system/storage/vendor/twig/twig/src/NodeVisitor/SandboxNodeVisitor.php +++ b/upload/system/storage/vendor/twig/twig/src/NodeVisitor/SandboxNodeVisitor.php @@ -119,7 +119,7 @@ public function leaveNode(Node $node, Environment $env): ?Node private function wrapNode(Node $node, string $name): void { $expr = $node->getNode($name); - if ($expr instanceof NameExpression || $expr instanceof GetAttrExpression) { + if (($expr instanceof NameExpression || $expr instanceof GetAttrExpression) && !$expr->isGenerator()) { $node->setNode($name, new CheckToStringNode($expr)); } } diff --git a/upload/system/storage/vendor/twig/twig/src/NodeVisitor/YieldNotReadyNodeVisitor.php b/upload/system/storage/vendor/twig/twig/src/NodeVisitor/YieldNotReadyNodeVisitor.php index 34c3ac18b..6470bdabc 100644 --- a/upload/system/storage/vendor/twig/twig/src/NodeVisitor/YieldNotReadyNodeVisitor.php +++ b/upload/system/storage/vendor/twig/twig/src/NodeVisitor/YieldNotReadyNodeVisitor.php @@ -39,7 +39,7 @@ public function enterNode(Node $node, Environment $env): Node if (!$this->yieldReadyNodes[$class] = (bool) (new \ReflectionClass($class))->getAttributes(YieldReady::class)) { if ($this->useYield) { - throw new \LogicException(sprintf('You cannot enable the "use_yield" option of Twig as node "%s" is not marked as ready for it; please make it ready and then flag it with the #[YieldReady] attribute.', $class)); + throw new \LogicException(\sprintf('You cannot enable the "use_yield" option of Twig as node "%s" is not marked as ready for it; please make it ready and then flag it with the #[YieldReady] attribute.', $class)); } trigger_deprecation('twig/twig', '3.9', 'Twig node "%s" is not marked as ready for using "yield" instead of "echo"; please make it ready and then flag it with the #[YieldReady] attribute.', $class); diff --git a/upload/system/storage/vendor/twig/twig/src/Parser.php b/upload/system/storage/vendor/twig/twig/src/Parser.php index adcaee316..7cfc2058c 100644 --- a/upload/system/storage/vendor/twig/twig/src/Parser.php +++ b/upload/system/storage/vendor/twig/twig/src/Parser.php @@ -25,6 +25,7 @@ use Twig\Node\PrintNode; use Twig\Node\TextNode; use Twig\TokenParser\TokenParserInterface; +use Twig\Util\ReflectionCallable; /** * @author Fabien Potencier @@ -52,7 +53,7 @@ public function __construct(Environment $env) public function getVarName(): string { - return sprintf('__internal_parse_%d', $this->varNameSalt++); + return \sprintf('__internal_parse_%d', $this->varNameSalt++); } public function parse(TokenStream $stream, $test = null, bool $dropNeedle = false): ModuleNode @@ -154,13 +155,14 @@ public function subparse($test, bool $dropNeedle = false): Node if (!$subparser = $this->env->getTokenParser($token->getValue())) { if (null !== $test) { - $e = new SyntaxError(sprintf('Unexpected "%s" tag', $token->getValue()), $token->getLine(), $this->stream->getSourceContext()); + $e = new SyntaxError(\sprintf('Unexpected "%s" tag', $token->getValue()), $token->getLine(), $this->stream->getSourceContext()); - if (\is_array($test) && isset($test[0]) && $test[0] instanceof TokenParserInterface) { - $e->appendMessage(sprintf(' (expecting closing tag for the "%s" tag defined near line %s).', $test[0]->getTag(), $lineno)); + $callable = (new ReflectionCallable($test))->getCallable(); + if (\is_array($callable) && $callable[0] instanceof TokenParserInterface) { + $e->appendMessage(\sprintf(' (expecting closing tag for the "%s" tag defined near line %s).', $callable[0]->getTag(), $lineno)); } } else { - $e = new SyntaxError(sprintf('Unknown "%s" tag.', $token->getValue()), $token->getLine(), $this->stream->getSourceContext()); + $e = new SyntaxError(\sprintf('Unknown "%s" tag.', $token->getValue()), $token->getLine(), $this->stream->getSourceContext()); $e->addSuggestions($token->getValue(), array_keys($this->env->getTokenParsers())); } diff --git a/upload/system/storage/vendor/twig/twig/src/Profiler/Dumper/BaseDumper.php b/upload/system/storage/vendor/twig/twig/src/Profiler/Dumper/BaseDumper.php index 4da43e475..267718c1f 100644 --- a/upload/system/storage/vendor/twig/twig/src/Profiler/Dumper/BaseDumper.php +++ b/upload/system/storage/vendor/twig/twig/src/Profiler/Dumper/BaseDumper.php @@ -50,7 +50,7 @@ private function dumpProfile(Profile $profile, $prefix = '', $sibling = false): if ($profile->getDuration() * 1000 < 1) { $str = $start."\n"; } else { - $str = sprintf("%s %s\n", $start, $this->formatTime($profile, $percent)); + $str = \sprintf("%s %s\n", $start, $this->formatTime($profile, $percent)); } $nCount = \count($profile->getProfiles()); diff --git a/upload/system/storage/vendor/twig/twig/src/Profiler/Dumper/BlackfireDumper.php b/upload/system/storage/vendor/twig/twig/src/Profiler/Dumper/BlackfireDumper.php index 03abe0fa0..bb3fbb52a 100644 --- a/upload/system/storage/vendor/twig/twig/src/Profiler/Dumper/BlackfireDumper.php +++ b/upload/system/storage/vendor/twig/twig/src/Profiler/Dumper/BlackfireDumper.php @@ -24,7 +24,7 @@ public function dump(Profile $profile): string $this->dumpProfile('main()', $profile, $data); $this->dumpChildren('main()', $profile, $data); - $start = sprintf('%f', microtime(true)); + $start = \sprintf('%f', microtime(true)); $str = <<isTemplate()) { $name = $p->getTemplate(); } else { - $name = sprintf('%s::%s(%s)', $p->getTemplate(), $p->getType(), $p->getName()); + $name = \sprintf('%s::%s(%s)', $p->getTemplate(), $p->getType(), $p->getName()); } - $this->dumpProfile(sprintf('%s==>%s', $parent, $name), $p, $data); + $this->dumpProfile(\sprintf('%s==>%s', $parent, $name), $p, $data); $this->dumpChildren($name, $p, $data); } } diff --git a/upload/system/storage/vendor/twig/twig/src/Profiler/Dumper/HtmlDumper.php b/upload/system/storage/vendor/twig/twig/src/Profiler/Dumper/HtmlDumper.php index 3c0daf1c8..cdab2de59 100644 --- a/upload/system/storage/vendor/twig/twig/src/Profiler/Dumper/HtmlDumper.php +++ b/upload/system/storage/vendor/twig/twig/src/Profiler/Dumper/HtmlDumper.php @@ -32,16 +32,16 @@ public function dump(Profile $profile): string protected function formatTemplate(Profile $profile, $prefix): string { - return sprintf('%s└ %s', $prefix, self::$colors['template'], $profile->getTemplate()); + return \sprintf('%s└ %s', $prefix, self::$colors['template'], $profile->getTemplate()); } protected function formatNonTemplate(Profile $profile, $prefix): string { - return sprintf('%s└ %s::%s(%s)', $prefix, $profile->getTemplate(), $profile->getType(), self::$colors[$profile->getType()] ?? 'auto', $profile->getName()); + return \sprintf('%s└ %s::%s(%s)', $prefix, $profile->getTemplate(), $profile->getType(), self::$colors[$profile->getType()] ?? 'auto', $profile->getName()); } protected function formatTime(Profile $profile, $percent): string { - return sprintf('%.2fms/%.0f%%', $percent > 20 ? self::$colors['big'] : 'auto', $profile->getDuration() * 1000, $percent); + return \sprintf('%.2fms/%.0f%%', $percent > 20 ? self::$colors['big'] : 'auto', $profile->getDuration() * 1000, $percent); } } diff --git a/upload/system/storage/vendor/twig/twig/src/Profiler/Dumper/TextDumper.php b/upload/system/storage/vendor/twig/twig/src/Profiler/Dumper/TextDumper.php index 31561c466..1c1f77e94 100644 --- a/upload/system/storage/vendor/twig/twig/src/Profiler/Dumper/TextDumper.php +++ b/upload/system/storage/vendor/twig/twig/src/Profiler/Dumper/TextDumper.php @@ -20,16 +20,16 @@ final class TextDumper extends BaseDumper { protected function formatTemplate(Profile $profile, $prefix): string { - return sprintf('%s└ %s', $prefix, $profile->getTemplate()); + return \sprintf('%s└ %s', $prefix, $profile->getTemplate()); } protected function formatNonTemplate(Profile $profile, $prefix): string { - return sprintf('%s└ %s::%s(%s)', $prefix, $profile->getTemplate(), $profile->getType(), $profile->getName()); + return \sprintf('%s└ %s::%s(%s)', $prefix, $profile->getTemplate(), $profile->getType(), $profile->getName()); } protected function formatTime(Profile $profile, $percent): string { - return sprintf('%.2fms/%.0f%%', $profile->getDuration() * 1000, $percent); + return \sprintf('%.2fms/%.0f%%', $profile->getDuration() * 1000, $percent); } } diff --git a/upload/system/storage/vendor/twig/twig/src/Profiler/Node/EnterProfileNode.php b/upload/system/storage/vendor/twig/twig/src/Profiler/Node/EnterProfileNode.php index 7b71f8b30..4d8e504d1 100644 --- a/upload/system/storage/vendor/twig/twig/src/Profiler/Node/EnterProfileNode.php +++ b/upload/system/storage/vendor/twig/twig/src/Profiler/Node/EnterProfileNode.php @@ -31,10 +31,10 @@ public function __construct(string $extensionName, string $type, string $name, s public function compile(Compiler $compiler): void { $compiler - ->write(sprintf('$%s = $this->extensions[', $this->getAttribute('var_name'))) + ->write(\sprintf('$%s = $this->extensions[', $this->getAttribute('var_name'))) ->repr($this->getAttribute('extension_name')) ->raw("];\n") - ->write(sprintf('$%s->enter($%s = new \Twig\Profiler\Profile($this->getTemplateName(), ', $this->getAttribute('var_name'), $this->getAttribute('var_name').'_prof')) + ->write(\sprintf('$%s->enter($%s = new \Twig\Profiler\Profile($this->getTemplateName(), ', $this->getAttribute('var_name'), $this->getAttribute('var_name').'_prof')) ->repr($this->getAttribute('type')) ->raw(', ') ->repr($this->getAttribute('name')) diff --git a/upload/system/storage/vendor/twig/twig/src/Profiler/Node/LeaveProfileNode.php b/upload/system/storage/vendor/twig/twig/src/Profiler/Node/LeaveProfileNode.php index 7e9ef9b64..bd9227e52 100644 --- a/upload/system/storage/vendor/twig/twig/src/Profiler/Node/LeaveProfileNode.php +++ b/upload/system/storage/vendor/twig/twig/src/Profiler/Node/LeaveProfileNode.php @@ -32,7 +32,7 @@ public function compile(Compiler $compiler): void { $compiler ->write("\n") - ->write(sprintf("\$%s->leave(\$%s);\n\n", $this->getAttribute('var_name'), $this->getAttribute('var_name').'_prof')) + ->write(\sprintf("\$%s->leave(\$%s);\n\n", $this->getAttribute('var_name'), $this->getAttribute('var_name').'_prof')) ; } } diff --git a/upload/system/storage/vendor/twig/twig/src/Profiler/NodeVisitor/ProfilerNodeVisitor.php b/upload/system/storage/vendor/twig/twig/src/Profiler/NodeVisitor/ProfilerNodeVisitor.php index 91abee807..4d2a58105 100644 --- a/upload/system/storage/vendor/twig/twig/src/Profiler/NodeVisitor/ProfilerNodeVisitor.php +++ b/upload/system/storage/vendor/twig/twig/src/Profiler/NodeVisitor/ProfilerNodeVisitor.php @@ -33,7 +33,7 @@ final class ProfilerNodeVisitor implements NodeVisitorInterface public function __construct(string $extensionName) { $this->extensionName = $extensionName; - $this->varName = sprintf('__internal_%s', hash(\PHP_VERSION_ID < 80100 ? 'sha256' : 'xxh128', $extensionName)); + $this->varName = \sprintf('__internal_%s', hash(\PHP_VERSION_ID < 80100 ? 'sha256' : 'xxh128', $extensionName)); } public function enterNode(Node $node, Environment $env): Node diff --git a/upload/system/storage/vendor/twig/twig/src/Runtime/EscaperRuntime.php b/upload/system/storage/vendor/twig/twig/src/Runtime/EscaperRuntime.php index eb5dfd06c..b1dac9640 100644 --- a/upload/system/storage/vendor/twig/twig/src/Runtime/EscaperRuntime.php +++ b/upload/system/storage/vendor/twig/twig/src/Runtime/EscaperRuntime.php @@ -17,6 +17,7 @@ final class EscaperRuntime implements RuntimeExtensionInterface { + /** @var array */ private $escapers = []; /** @internal */ @@ -35,8 +36,8 @@ public function __construct($charset = 'UTF-8') /** * Defines a new escaper to be used via the escape filter. * - * @param string $strategy The strategy name that should be used as a strategy in the escape call - * @param callable(string $string, string $charset) $callable A valid PHP callable + * @param string $strategy The strategy name that should be used as a strategy in the escape call + * @param callable(string $string, string $charset): string $callable A valid PHP callable */ public function setEscaper($strategy, callable $callable) { @@ -46,7 +47,7 @@ public function setEscaper($strategy, callable $callable) /** * Gets all defined escapers. * - * @return array An array of escapers + * @return array An array of escapers */ public function getEscapers() { @@ -199,7 +200,7 @@ public function escape($string, string $strategy = 'html', ?string $charset = nu $codepoint = mb_ord($char, 'UTF-8'); if (0x10000 > $codepoint) { - return sprintf('\u%04X', $codepoint); + return \sprintf('\u%04X', $codepoint); } // Split characters outside the BMP into surrogate pairs @@ -208,7 +209,7 @@ public function escape($string, string $strategy = 'html', ?string $charset = nu $high = 0xD800 | ($u >> 10); $low = 0xDC00 | ($u & 0x3FF); - return sprintf('\u%04X\u%04X', $high, $low); + return \sprintf('\u%04X\u%04X', $high, $low); }, $string); if ('UTF-8' !== $charset) { @@ -229,7 +230,7 @@ public function escape($string, string $strategy = 'html', ?string $charset = nu $string = preg_replace_callback('#[^a-zA-Z0-9]#Su', function ($matches) { $char = $matches[0]; - return sprintf('\\%X ', 1 === \strlen($char) ? \ord($char) : mb_ord($char, 'UTF-8')); + return \sprintf('\\%X ', 1 === \strlen($char) ? \ord($char) : mb_ord($char, 'UTF-8')); }, $string); if ('UTF-8' !== $charset) { @@ -287,14 +288,14 @@ public function escape($string, string $strategy = 'html', ?string $charset = nu return $entityMap[$ord]; } - return sprintf('&#x%02X;', $ord); + return \sprintf('&#x%02X;', $ord); } /* * Per OWASP recommendations, we'll use hex entities for any other * characters where a named entity does not exist. */ - return sprintf('&#x%04X;', mb_ord($chr, 'UTF-8')); + return \sprintf('&#x%04X;', mb_ord($chr, 'UTF-8')); }, $string); if ('UTF-8' !== $charset) { @@ -313,7 +314,7 @@ public function escape($string, string $strategy = 'html', ?string $charset = nu $validStrategies = implode('", "', array_merge(['html', 'js', 'url', 'css', 'html_attr'], array_keys($this->escapers))); - throw new RuntimeError(sprintf('Invalid escaping strategy "%s" (valid ones: "%s").', $strategy, $validStrategies)); + throw new RuntimeError(\sprintf('Invalid escaping strategy "%s" (valid ones: "%s").', $strategy, $validStrategies)); } } diff --git a/upload/system/storage/vendor/twig/twig/src/Sandbox/SecurityPolicy.php b/upload/system/storage/vendor/twig/twig/src/Sandbox/SecurityPolicy.php index a725aa4f1..417d38a8d 100644 --- a/upload/system/storage/vendor/twig/twig/src/Sandbox/SecurityPolicy.php +++ b/upload/system/storage/vendor/twig/twig/src/Sandbox/SecurityPolicy.php @@ -68,19 +68,19 @@ public function checkSecurity($tags, $filters, $functions): void { foreach ($tags as $tag) { if (!\in_array($tag, $this->allowedTags)) { - throw new SecurityNotAllowedTagError(sprintf('Tag "%s" is not allowed.', $tag), $tag); + throw new SecurityNotAllowedTagError(\sprintf('Tag "%s" is not allowed.', $tag), $tag); } } foreach ($filters as $filter) { if (!\in_array($filter, $this->allowedFilters)) { - throw new SecurityNotAllowedFilterError(sprintf('Filter "%s" is not allowed.', $filter), $filter); + throw new SecurityNotAllowedFilterError(\sprintf('Filter "%s" is not allowed.', $filter), $filter); } } foreach ($functions as $function) { if (!\in_array($function, $this->allowedFunctions)) { - throw new SecurityNotAllowedFunctionError(sprintf('Function "%s" is not allowed.', $function), $function); + throw new SecurityNotAllowedFunctionError(\sprintf('Function "%s" is not allowed.', $function), $function); } } } @@ -102,7 +102,7 @@ public function checkMethodAllowed($obj, $method): void if (!$allowed) { $class = \get_class($obj); - throw new SecurityNotAllowedMethodError(sprintf('Calling "%s" method on a "%s" object is not allowed.', $method, $class), $class, $method); + throw new SecurityNotAllowedMethodError(\sprintf('Calling "%s" method on a "%s" object is not allowed.', $method, $class), $class, $method); } } @@ -118,7 +118,7 @@ public function checkPropertyAllowed($obj, $property): void if (!$allowed) { $class = \get_class($obj); - throw new SecurityNotAllowedPropertyError(sprintf('Calling "%s" property on a "%s" object is not allowed.', $property, $class), $class, $property); + throw new SecurityNotAllowedPropertyError(\sprintf('Calling "%s" property on a "%s" object is not allowed.', $property, $class), $class, $property); } } } diff --git a/upload/system/storage/vendor/twig/twig/src/Template.php b/upload/system/storage/vendor/twig/twig/src/Template.php index e08837737..04c530cc9 100644 --- a/upload/system/storage/vendor/twig/twig/src/Template.php +++ b/upload/system/storage/vendor/twig/twig/src/Template.php @@ -382,7 +382,7 @@ public function yield(array $context, array $blocks = []): iterable throw $e; } catch (\Throwable $e) { - $e = new RuntimeError(sprintf('An exception has been thrown during the rendering of a template ("%s").', $e->getMessage()), -1, $this->getSourceContext(), $e); + $e = new RuntimeError(\sprintf('An exception has been thrown during the rendering of a template ("%s").', $e->getMessage()), -1, $this->getSourceContext(), $e); $e->guess(); throw $e; @@ -452,7 +452,7 @@ public function yieldBlock($name, array $context, array $blocks = [], $useBlocks throw $e; } catch (\Throwable $e) { - $e = new RuntimeError(sprintf('An exception has been thrown during the rendering of a template ("%s").', $e->getMessage()), -1, $template->getSourceContext(), $e); + $e = new RuntimeError(\sprintf('An exception has been thrown during the rendering of a template ("%s").', $e->getMessage()), -1, $template->getSourceContext(), $e); $e->guess(); throw $e; @@ -466,9 +466,9 @@ public function yieldBlock($name, array $context, array $blocks = [], $useBlocks } elseif ($parent = $this->getParent($context)) { yield from $parent->unwrap()->yieldBlock($name, $context, array_merge($this->blocks, $blocks), false, $templateContext ?? $this); } elseif (isset($blocks[$name])) { - throw new RuntimeError(sprintf('Block "%s" should not call parent() in "%s" as the block does not exist in the parent template "%s".', $name, $blocks[$name][0]->getTemplateName(), $this->getTemplateName()), -1, $blocks[$name][0]->getSourceContext()); + throw new RuntimeError(\sprintf('Block "%s" should not call parent() in "%s" as the block does not exist in the parent template "%s".', $name, $blocks[$name][0]->getTemplateName(), $this->getTemplateName()), -1, $blocks[$name][0]->getSourceContext()); } else { - throw new RuntimeError(sprintf('Block "%s" on template "%s" does not exist.', $name, $this->getTemplateName()), -1, ($templateContext ?? $this)->getSourceContext()); + throw new RuntimeError(\sprintf('Block "%s" on template "%s" does not exist.', $name, $this->getTemplateName()), -1, ($templateContext ?? $this)->getSourceContext()); } } @@ -491,7 +491,7 @@ public function yieldParentBlock($name, array $context, array $blocks = []) } elseif ($parent = $this->getParent($context)) { yield from $parent->unwrap()->yieldBlock($name, $context, $blocks, false); } else { - throw new RuntimeError(sprintf('The template has no parent and no traits defining the "%s" block.', $name), -1, $this->getSourceContext()); + throw new RuntimeError(\sprintf('The template has no parent and no traits defining the "%s" block.', $name), -1, $this->getSourceContext()); } } diff --git a/upload/system/storage/vendor/twig/twig/src/Test/IntegrationTestCase.php b/upload/system/storage/vendor/twig/twig/src/Test/IntegrationTestCase.php index d0731ce19..5519dd0a9 100644 --- a/upload/system/storage/vendor/twig/twig/src/Test/IntegrationTestCase.php +++ b/upload/system/storage/vendor/twig/twig/src/Test/IntegrationTestCase.php @@ -123,7 +123,7 @@ public function getTests($name, $legacyTests = false) $exception = false; preg_match_all('/--DATA--(.*?)(?:--CONFIG--(.*?))?--EXPECT--(.*?)(?=\-\-DATA\-\-|$)/s', $test, $outputs, \PREG_SET_ORDER); } else { - throw new \InvalidArgumentException(sprintf('Test "%s" is not valid.', str_replace($fixturesDir.'/', '', $file))); + throw new \InvalidArgumentException(\sprintf('Test "%s" is not valid.', str_replace($fixturesDir.'/', '', $file))); } $tests[] = [str_replace($fixturesDir.'/', '', $file), $message, $condition, $templates, $exception, $outputs, $deprecation]; @@ -185,11 +185,6 @@ protected function doIntegrationTest($file, $message, $condition, $templates, $e $twig->addFunction($function); } - // avoid using the same PHP class name for different cases - $p = new \ReflectionProperty($twig, 'templateClassPrefix'); - $p->setAccessible(true); - $p->setValue($twig, '__TwigTemplate_'.hash(\PHP_VERSION_ID < 80100 ? 'sha256' : 'xxh128', uniqid((string) mt_rand(), true), false).'_'); - $deprecations = []; try { $prevHandler = set_error_handler(function ($type, $msg, $file, $line, $context = []) use (&$deprecations, &$prevHandler) { @@ -206,14 +201,14 @@ protected function doIntegrationTest($file, $message, $condition, $templates, $e } catch (\Exception $e) { if (false !== $exception) { $message = $e->getMessage(); - $this->assertSame(trim($exception), trim(sprintf('%s: %s', \get_class($e), $message))); + $this->assertSame(trim($exception), trim(\sprintf('%s: %s', \get_class($e), $message))); $last = substr($message, \strlen($message) - 1); $this->assertTrue('.' === $last || '?' === $last, 'Exception message must end with a dot or a question mark.'); return; } - throw new Error(sprintf('%s: %s', \get_class($e), $e->getMessage()), -1, null, $e); + throw new Error(\sprintf('%s: %s', \get_class($e), $e->getMessage()), -1, null, $e); } finally { restore_error_handler(); } @@ -224,14 +219,14 @@ protected function doIntegrationTest($file, $message, $condition, $templates, $e $output = trim($template->render(eval($match[1].';')), "\n "); } catch (\Exception $e) { if (false !== $exception) { - $this->assertSame(trim($exception), trim(sprintf('%s: %s', \get_class($e), $e->getMessage()))); + $this->assertSame(trim($exception), trim(\sprintf('%s: %s', \get_class($e), $e->getMessage()))); return; } - $e = new Error(sprintf('%s: %s', \get_class($e), $e->getMessage()), -1, null, $e); + $e = new Error(\sprintf('%s: %s', \get_class($e), $e->getMessage()), -1, null, $e); - $output = trim(sprintf('%s: %s', \get_class($e), $e->getMessage())); + $output = trim(\sprintf('%s: %s', \get_class($e), $e->getMessage())); } if (false !== $exception) { diff --git a/upload/system/storage/vendor/twig/twig/src/Test/NodeTestCase.php b/upload/system/storage/vendor/twig/twig/src/Test/NodeTestCase.php index 30d6810f8..4046f08cd 100644 --- a/upload/system/storage/vendor/twig/twig/src/Test/NodeTestCase.php +++ b/upload/system/storage/vendor/twig/twig/src/Test/NodeTestCase.php @@ -53,14 +53,18 @@ protected function getCompiler(?Environment $environment = null) protected function getEnvironment() { - return $this->currentEnv = new Environment(new ArrayLoader([])); + if (!$this->currentEnv) { + $this->currentEnv = new Environment(new ArrayLoader()); + } + + return $this->currentEnv; } protected function getVariableGetter($name, $line = false) { $line = $line > 0 ? "// line $line\n" : ''; - return sprintf('%s($context["%s"] ?? null)', $line, $name); + return \sprintf('%s($context["%s"] ?? null)', $line, $name); } protected function getAttributeGetter() diff --git a/upload/system/storage/vendor/twig/twig/src/Token.php b/upload/system/storage/vendor/twig/twig/src/Token.php index 59279b8fe..5be39bdc7 100644 --- a/upload/system/storage/vendor/twig/twig/src/Token.php +++ b/upload/system/storage/vendor/twig/twig/src/Token.php @@ -46,7 +46,7 @@ public function __construct(int $type, $value, int $lineno) public function __toString() { - return sprintf('%s(%s)', self::typeToString($this->type, true), $this->value); + return \sprintf('%s(%s)', self::typeToString($this->type, true), $this->value); } /** @@ -138,7 +138,7 @@ public static function typeToString(int $type, bool $short = false): string $name = 'SPREAD_TYPE'; break; default: - throw new \LogicException(sprintf('Token of type "%s" does not exist.', $type)); + throw new \LogicException(\sprintf('Token of type "%s" does not exist.', $type)); } return $short ? $name : 'Twig\Token::'.$name; @@ -178,7 +178,7 @@ public static function typeToEnglish(int $type): string case self::SPREAD_TYPE: return 'spread operator'; default: - throw new \LogicException(sprintf('Token of type "%s" does not exist.', $type)); + throw new \LogicException(\sprintf('Token of type "%s" does not exist.', $type)); } } } diff --git a/upload/system/storage/vendor/twig/twig/src/TokenParser/BlockTokenParser.php b/upload/system/storage/vendor/twig/twig/src/TokenParser/BlockTokenParser.php index 5878131be..c654d31f9 100644 --- a/upload/system/storage/vendor/twig/twig/src/TokenParser/BlockTokenParser.php +++ b/upload/system/storage/vendor/twig/twig/src/TokenParser/BlockTokenParser.php @@ -37,7 +37,7 @@ public function parse(Token $token): Node $stream = $this->parser->getStream(); $name = $stream->expect(/* Token::NAME_TYPE */ 5)->getValue(); if ($this->parser->hasBlock($name)) { - throw new SyntaxError(sprintf("The block '%s' has already been defined line %d.", $name, $this->parser->getBlock($name)->getTemplateLine()), $stream->getCurrent()->getLine(), $stream->getSourceContext()); + throw new SyntaxError(\sprintf("The block '%s' has already been defined line %d.", $name, $this->parser->getBlock($name)->getTemplateLine()), $stream->getCurrent()->getLine(), $stream->getSourceContext()); } $this->parser->setBlock($name, $block = new BlockNode($name, new Node([]), $lineno)); $this->parser->pushLocalScope(); @@ -49,7 +49,7 @@ public function parse(Token $token): Node $value = $token->getValue(); if ($value != $name) { - throw new SyntaxError(sprintf('Expected endblock for block "%s" (but "%s" given).', $name, $value), $stream->getCurrent()->getLine(), $stream->getSourceContext()); + throw new SyntaxError(\sprintf('Expected endblock for block "%s" (but "%s" given).', $name, $value), $stream->getCurrent()->getLine(), $stream->getSourceContext()); } } } else { diff --git a/upload/system/storage/vendor/twig/twig/src/TokenParser/DeprecatedTokenParser.php b/upload/system/storage/vendor/twig/twig/src/TokenParser/DeprecatedTokenParser.php index 31416c79c..c17c4aadc 100644 --- a/upload/system/storage/vendor/twig/twig/src/TokenParser/DeprecatedTokenParser.php +++ b/upload/system/storage/vendor/twig/twig/src/TokenParser/DeprecatedTokenParser.php @@ -11,6 +11,7 @@ namespace Twig\TokenParser; +use Twig\Error\SyntaxError; use Twig\Node\DeprecatedNode; use Twig\Node\Node; use Twig\Token; @@ -21,6 +22,8 @@ * {% deprecated 'The "base.twig" template is deprecated, use "layout.twig" instead.' %} * {% extends 'layout.html.twig' %} * + * {% deprecated 'The "base.twig" template is deprecated, use "layout.twig" instead.' package="foo/bar" version="1.1" %} + * * @author Yonel Ceruto * * @internal @@ -29,11 +32,31 @@ final class DeprecatedTokenParser extends AbstractTokenParser { public function parse(Token $token): Node { - $expr = $this->parser->getExpressionParser()->parseExpression(); + $stream = $this->parser->getStream(); + $expressionParser = $this->parser->getExpressionParser(); + $expr = $expressionParser->parseExpression(); + $node = new DeprecatedNode($expr, $token->getLine(), $this->getTag()); + + while ($stream->test(Token::NAME_TYPE)) { + $k = $stream->getCurrent()->getValue(); + $stream->next(); + $stream->expect(Token::OPERATOR_TYPE, '='); + + switch ($k) { + case 'package': + $node->setNode('package', $expressionParser->parseExpression()); + break; + case 'version': + $node->setNode('version', $expressionParser->parseExpression()); + break; + default: + throw new SyntaxError(\sprintf('Unknown "%s" option.', $k), $stream->getCurrent()->getLine(), $stream->getSourceContext()); + } + } - $this->parser->getStream()->expect(Token::BLOCK_END_TYPE); + $stream->expect(Token::BLOCK_END_TYPE); - return new DeprecatedNode($expr, $token->getLine(), $this->getTag()); + return $node; } public function getTag(): string diff --git a/upload/system/storage/vendor/twig/twig/src/TokenParser/IfTokenParser.php b/upload/system/storage/vendor/twig/twig/src/TokenParser/IfTokenParser.php index c0fe6df0d..569ccfaf1 100644 --- a/upload/system/storage/vendor/twig/twig/src/TokenParser/IfTokenParser.php +++ b/upload/system/storage/vendor/twig/twig/src/TokenParser/IfTokenParser.php @@ -63,7 +63,7 @@ public function parse(Token $token): Node break; default: - throw new SyntaxError(sprintf('Unexpected end of template. Twig was looking for the following tags "else", "elseif", or "endif" to close the "if" block started at line %d).', $lineno), $stream->getCurrent()->getLine(), $stream->getSourceContext()); + throw new SyntaxError(\sprintf('Unexpected end of template. Twig was looking for the following tags "else", "elseif", or "endif" to close the "if" block started at line %d).', $lineno), $stream->getCurrent()->getLine(), $stream->getSourceContext()); } } diff --git a/upload/system/storage/vendor/twig/twig/src/TokenParser/MacroTokenParser.php b/upload/system/storage/vendor/twig/twig/src/TokenParser/MacroTokenParser.php index f584927e9..1f0e3e97f 100644 --- a/upload/system/storage/vendor/twig/twig/src/TokenParser/MacroTokenParser.php +++ b/upload/system/storage/vendor/twig/twig/src/TokenParser/MacroTokenParser.php @@ -43,7 +43,7 @@ public function parse(Token $token): Node $value = $token->getValue(); if ($value != $name) { - throw new SyntaxError(sprintf('Expected endmacro for macro "%s" (but "%s" given).', $name, $value), $stream->getCurrent()->getLine(), $stream->getSourceContext()); + throw new SyntaxError(\sprintf('Expected endmacro for macro "%s" (but "%s" given).', $name, $value), $stream->getCurrent()->getLine(), $stream->getSourceContext()); } } $this->parser->popLocalScope(); diff --git a/upload/system/storage/vendor/twig/twig/src/TokenStream.php b/upload/system/storage/vendor/twig/twig/src/TokenStream.php index 89e7e0f3f..9921f788d 100644 --- a/upload/system/storage/vendor/twig/twig/src/TokenStream.php +++ b/upload/system/storage/vendor/twig/twig/src/TokenStream.php @@ -71,11 +71,11 @@ public function expect($type, $value = null, ?string $message = null): Token $token = $this->tokens[$this->current]; if (!$token->test($type, $value)) { $line = $token->getLine(); - throw new SyntaxError(sprintf('%sUnexpected token "%s"%s ("%s" expected%s).', + throw new SyntaxError(\sprintf('%sUnexpected token "%s"%s ("%s" expected%s).', $message ? $message.'. ' : '', Token::typeToEnglish($token->getType()), - $token->getValue() ? sprintf(' of value "%s"', $token->getValue()) : '', - Token::typeToEnglish($type), $value ? sprintf(' with value "%s"', $value) : ''), + $token->getValue() ? \sprintf(' of value "%s"', $token->getValue()) : '', + Token::typeToEnglish($type), $value ? \sprintf(' with value "%s"', $value) : ''), $line, $this->source ); diff --git a/upload/system/storage/vendor/twig/twig/src/TwigFilter.php b/upload/system/storage/vendor/twig/twig/src/TwigFilter.php index c02469b91..2b80df939 100644 --- a/upload/system/storage/vendor/twig/twig/src/TwigFilter.php +++ b/upload/system/storage/vendor/twig/twig/src/TwigFilter.php @@ -46,6 +46,7 @@ public function __construct(string $name, $callable = null, array $options = []) 'preserves_safety' => null, 'node_class' => FilterExpression::class, 'deprecated' => false, + 'deprecating_package' => '', 'alternative' => null, ], $options); } @@ -128,6 +129,11 @@ public function isDeprecated(): bool return (bool) $this->options['deprecated']; } + public function getDeprecatingPackage(): string + { + return $this->options['deprecating_package']; + } + public function getDeprecatedVersion(): string { return \is_bool($this->options['deprecated']) ? '' : $this->options['deprecated']; diff --git a/upload/system/storage/vendor/twig/twig/src/TwigFunction.php b/upload/system/storage/vendor/twig/twig/src/TwigFunction.php index c15def633..bfee7eb87 100644 --- a/upload/system/storage/vendor/twig/twig/src/TwigFunction.php +++ b/upload/system/storage/vendor/twig/twig/src/TwigFunction.php @@ -44,6 +44,7 @@ public function __construct(string $name, $callable = null, array $options = []) 'is_safe_callback' => null, 'node_class' => FunctionExpression::class, 'deprecated' => false, + 'deprecating_package' => '', 'alternative' => null, ], $options); } @@ -116,6 +117,11 @@ public function isDeprecated(): bool return (bool) $this->options['deprecated']; } + public function getDeprecatingPackage(): string + { + return $this->options['deprecating_package']; + } + public function getDeprecatedVersion(): string { return \is_bool($this->options['deprecated']) ? '' : $this->options['deprecated']; diff --git a/upload/system/storage/vendor/twig/twig/src/TwigTest.php b/upload/system/storage/vendor/twig/twig/src/TwigTest.php index 3769ec162..0b43a2849 100644 --- a/upload/system/storage/vendor/twig/twig/src/TwigTest.php +++ b/upload/system/storage/vendor/twig/twig/src/TwigTest.php @@ -38,6 +38,7 @@ public function __construct(string $name, $callable = null, array $options = []) 'is_variadic' => false, 'node_class' => TestExpression::class, 'deprecated' => false, + 'deprecating_package' => '', 'alternative' => null, 'one_mandatory_argument' => false, ], $options); @@ -83,6 +84,11 @@ public function isDeprecated(): bool return (bool) $this->options['deprecated']; } + public function getDeprecatingPackage(): string + { + return $this->options['deprecating_package']; + } + public function getDeprecatedVersion(): string { return \is_bool($this->options['deprecated']) ? '' : $this->options['deprecated']; diff --git a/upload/system/storage/vendor/twig/twig/src/Util/DeprecationCollector.php b/upload/system/storage/vendor/twig/twig/src/Util/DeprecationCollector.php index 378b666bd..ad5310617 100644 --- a/upload/system/storage/vendor/twig/twig/src/Util/DeprecationCollector.php +++ b/upload/system/storage/vendor/twig/twig/src/Util/DeprecationCollector.php @@ -60,6 +60,8 @@ public function collect(\Traversable $iterator): array if (\E_USER_DEPRECATED === $type) { $deprecations[] = $msg; } + + return false; }); foreach ($iterator as $name => $contents) { diff --git a/upload/system/storage/vendor/twig/twig/src/Util/ReflectionCallable.php b/upload/system/storage/vendor/twig/twig/src/Util/ReflectionCallable.php new file mode 100644 index 000000000..54384e14b --- /dev/null +++ b/upload/system/storage/vendor/twig/twig/src/Util/ReflectionCallable.php @@ -0,0 +1,88 @@ + + * + * @internal + */ +final class ReflectionCallable +{ + private $reflector; + private $callable = null; + private $name; + + public function __construct($callable, string $debugType = 'unknown', string $debugName = 'unknown') + { + if (\is_string($callable) && false !== $pos = strpos($callable, '::')) { + $callable = [substr($callable, 0, $pos), substr($callable, 2 + $pos)]; + } + + if (\is_array($callable) && method_exists($callable[0], $callable[1])) { + $this->reflector = $r = new \ReflectionMethod($callable[0], $callable[1]); + $this->callable = $callable; + $this->name = $r->class.'::'.$r->name; + + return; + } + + $checkVisibility = $callable instanceof \Closure; + try { + $closure = \Closure::fromCallable($callable); + } catch (\TypeError $e) { + throw new \LogicException(\sprintf('Callback for %s "%s" is not callable in the current scope.', $debugType, $debugName), 0, $e); + } + $this->reflector = $r = new \ReflectionFunction($closure); + + if (str_contains($r->name, '{closure')) { + $this->callable = $callable; + $this->name = 'Closure'; + + return; + } + + if ($object = $r->getClosureThis()) { + $callable = [$object, $r->name]; + $this->name = get_debug_type($object).'::'.$r->name; + } elseif (\PHP_VERSION_ID >= 80111 && $class = $r->getClosureCalledClass()) { + $callable = [$class->name, $r->name]; + $this->name = $class->name.'::'.$r->name; + } elseif (\PHP_VERSION_ID < 80111 && $class = $r->getClosureScopeClass()) { + $callable = [\is_array($callable) ? $callable[0] : $class->name, $r->name]; + $this->name = (\is_array($callable) ? $callable[0] : $class->name).'::'.$r->name; + } else { + $callable = $this->name = $r->name; + } + + if ($checkVisibility && \is_array($callable) && method_exists(...$callable) && !(new \ReflectionMethod(...$callable))->isPublic()) { + $callable = $r->getClosure(); + } + + $this->callable = $callable; + } + + public function getReflector(): \ReflectionFunctionAbstract + { + return $this->reflector; + } + + public function getCallable() + { + return $this->callable; + } + + public function getName(): string + { + return $this->name; + } +}