From dfb5a4875a4e59d55646f870a7ddf04a6efbb082 Mon Sep 17 00:00:00 2001 From: Pierre Goiffon Date: Fri, 26 Jan 2024 09:55:51 +0100 Subject: [PATCH] =?UTF-8?q?N=C2=B05809=20Update=20Symfony=20artifacts=20fr?= =?UTF-8?q?om=206.4.0=20to=206.4.2=20symfony/console=20symfony/dotenv=20sy?= =?UTF-8?q?mfony/framework-bundle=20symfony/http-foundation=20symfony/http?= =?UTF-8?q?-kernel=20symfony/var-dumper=20symfony/web-profiler-bundle?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- composer.lock | 211 ++++++++-------- lib/composer/autoload_classmap.php | 4 + lib/composer/autoload_static.php | 4 + lib/composer/installed.json | 239 +++++++++--------- lib/composer/installed.php | 94 +++---- .../Adapter/CouchbaseCollectionAdapter.php | 6 +- lib/symfony/console/Output/StreamOutput.php | 19 +- lib/symfony/console/README.md | 13 +- .../dependency-injection/Attribute/Target.php | 6 +- .../Compiler/AutowirePass.php | 20 +- .../Compiler/ResolveBindingsPass.php | 13 +- .../dependency-injection/Dumper/PhpDumper.php | 1 + .../EnvVarProcessorInterface.php | 1 - lib/symfony/dotenv/Command/DebugCommand.php | 8 +- lib/symfony/dotenv/Dotenv.php | 6 +- lib/symfony/event-dispatcher/GenericEvent.php | 2 +- .../framework-bundle/Console/Application.php | 2 +- .../Controller/AbstractController.php | 2 +- .../FrameworkExtension.php | 49 +++- .../EventListener/ConsoleProfilerListener.php | 27 +- .../Resources/config/mailer_webhook.php | 14 + .../Resources/config/notifier_webhook.php | 4 + .../Resources/config/profiling.php | 3 +- .../Resources/config/schema/symfony-1.0.xsd | 1 + .../AnnotatedRouteControllerLoader.php | 2 +- lib/symfony/framework-bundle/composer.json | 2 +- .../http-foundation/RequestMatcher.php | 2 +- .../Controller/ArgumentResolver.php | 1 + .../BackedEnumValueResolver.php | 2 +- .../RequestPayloadValueResolver.php | 2 +- .../http-kernel/Debug/FileLinkFormatter.php | 2 +- ...RegisterControllerArgumentLocatorsPass.php | 8 +- .../EventListener/AbstractSessionListener.php | 26 +- .../EventListener/LocaleListener.php | 2 +- lib/symfony/http-kernel/Kernel.php | 6 +- lib/symfony/http-kernel/UriSigner.php | 2 +- .../routing/Loader/AnnotationClassLoader.php | 2 +- .../Loader/AnnotationDirectoryLoader.php | 2 +- .../routing/Loader/AnnotationFileLoader.php | 2 +- .../routing/Loader/AttributeClassLoader.php | 14 +- lib/symfony/routing/RouteCollection.php | 15 ++ lib/symfony/service-contracts/.gitignore | 3 - .../Attribute/SubscribedService.php | 20 +- lib/symfony/service-contracts/LICENSE | 2 +- lib/symfony/service-contracts/README.md | 2 +- .../service-contracts/ResetInterface.php | 3 + .../service-contracts/ServiceLocatorTrait.php | 27 +- .../ServiceProviderInterface.php | 11 +- .../ServiceSubscriberInterface.php | 15 +- .../ServiceSubscriberTrait.php | 89 +++---- lib/symfony/service-contracts/composer.json | 15 +- lib/symfony/var-dumper/Dumper/HtmlDumper.php | 2 +- lib/symfony/var-exporter/LazyGhostTrait.php | 5 +- lib/symfony/var-exporter/README.md | 10 +- .../views/Profiler/base_js.html.twig | 38 ++- .../Resources/views/Profiler/toolbar.css.twig | 4 + .../views/Profiler/toolbar_js.html.twig | 33 +-- .../views/Profiler/toolbar_redirect.html.twig | 4 +- .../Twig/WebProfilerExtension.php | 15 +- lib/twig/twig/.editorconfig | 18 -- lib/twig/twig/.gitattributes | 4 - lib/twig/twig/.github/workflows/ci.yml | 149 ----------- .../twig/.github/workflows/documentation.yml | 64 ----- lib/twig/twig/.gitignore | 6 - lib/twig/twig/.php-cs-fixer.dist.php | 20 -- lib/twig/twig/CHANGELOG | 45 ++++ lib/twig/twig/LICENSE | 2 +- lib/twig/twig/composer.json | 10 +- lib/twig/twig/src/Cache/FilesystemCache.php | 2 +- lib/twig/twig/src/Compiler.php | 11 +- lib/twig/twig/src/Environment.php | 18 +- lib/twig/twig/src/Error/Error.php | 8 +- lib/twig/twig/src/Error/SyntaxError.php | 2 +- lib/twig/twig/src/ExpressionParser.php | 32 ++- lib/twig/twig/src/Extension/CoreExtension.php | 145 +++++++---- .../twig/src/Extension/DebugExtension.php | 4 +- .../twig/src/Extension/EscaperExtension.php | 4 +- .../twig/src/Extension/ExtensionInterface.php | 8 + .../twig/src/Extension/GlobalsInterface.php | 3 + lib/twig/twig/src/ExtensionSet.php | 17 ++ .../src/FileExtensionEscapingStrategy.php | 2 +- lib/twig/twig/src/Lexer.php | 28 +- lib/twig/twig/src/Loader/FilesystemLoader.php | 4 +- .../src/Node/Expression/ArrayExpression.php | 64 ++++- .../Node/Expression/Binary/EndsWithBinary.php | 2 +- .../Node/Expression/Binary/HasEveryBinary.php | 33 +++ .../Node/Expression/Binary/HasSomeBinary.php | 33 +++ .../Node/Expression/Binary/MatchesBinary.php | 2 +- .../Expression/Binary/StartsWithBinary.php | 2 +- .../src/Node/Expression/CallExpression.php | 10 +- .../Node/Expression/ConditionalExpression.php | 27 +- lib/twig/twig/src/Node/IfNode.php | 5 +- lib/twig/twig/src/Node/ModuleNode.php | 9 + lib/twig/twig/src/Node/Node.php | 1 - lib/twig/twig/src/Node/WithNode.php | 2 +- .../src/NodeVisitor/EscaperNodeVisitor.php | 10 +- .../MacroAutoImportNodeVisitor.php | 8 +- .../src/NodeVisitor/OptimizerNodeVisitor.php | 32 +-- lib/twig/twig/src/Parser.php | 5 +- .../twig/src/Profiler/Dumper/HtmlDumper.php | 2 +- lib/twig/twig/src/Profiler/Profile.php | 2 +- lib/twig/twig/src/Sandbox/SecurityPolicy.php | 10 +- lib/twig/twig/src/Template.php | 4 +- lib/twig/twig/src/TemplateWrapper.php | 4 +- lib/twig/twig/src/Token.php | 12 +- .../twig/src/TokenParser/FromTokenParser.php | 4 +- .../twig/src/TokenParser/UseTokenParser.php | 4 +- lib/twig/twig/src/TwigFilter.php | 4 +- lib/twig/twig/src/TwigFunction.php | 4 +- lib/twig/twig/src/TwigTest.php | 4 +- 110 files changed, 1115 insertions(+), 929 deletions(-) delete mode 100644 lib/symfony/service-contracts/.gitignore delete mode 100644 lib/twig/twig/.editorconfig delete mode 100644 lib/twig/twig/.gitattributes delete mode 100644 lib/twig/twig/.github/workflows/ci.yml delete mode 100644 lib/twig/twig/.github/workflows/documentation.yml delete mode 100644 lib/twig/twig/.gitignore delete mode 100644 lib/twig/twig/.php-cs-fixer.dist.php create mode 100644 lib/twig/twig/src/Node/Expression/Binary/HasEveryBinary.php create mode 100644 lib/twig/twig/src/Node/Expression/Binary/HasSomeBinary.php diff --git a/composer.lock b/composer.lock index 5204cc9ed..f04e30ddc 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "44ec4a6bc173db43d68357900507ad8b", + "content-hash": "d8f21d10c2e9f2f9098698443baa8dd5", "packages": [ { "name": "apereo/phpcas", @@ -2054,16 +2054,16 @@ }, { "name": "symfony/cache", - "version": "v6.4.0", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "ac2d25f97b17eec6e19760b6b9962a4f7c44356a" + "reference": "14a75869bbb41cb35bc5d9d322473928c6f3f978" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/ac2d25f97b17eec6e19760b6b9962a4f7c44356a", - "reference": "ac2d25f97b17eec6e19760b6b9962a4f7c44356a", + "url": "https://api.github.com/repos/symfony/cache/zipball/14a75869bbb41cb35bc5d9d322473928c6f3f978", + "reference": "14a75869bbb41cb35bc5d9d322473928c6f3f978", "shasum": "" }, "require": { @@ -2130,7 +2130,7 @@ "psr6" ], "support": { - "source": "https://github.com/symfony/cache/tree/v6.4.0" + "source": "https://github.com/symfony/cache/tree/v6.4.2" }, "funding": [ { @@ -2146,7 +2146,7 @@ "type": "tidelift" } ], - "time": "2023-11-24T19:28:07+00:00" + "time": "2023-12-29T15:34:34+00:00" }, { "name": "symfony/cache-contracts", @@ -2301,16 +2301,16 @@ }, { "name": "symfony/console", - "version": "v6.4.0", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "cd9864b47c367450e14ab32f78fdbf98c44c26b6" + "reference": "0254811a143e6bc6c8deea08b589a7e68a37f625" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/cd9864b47c367450e14ab32f78fdbf98c44c26b6", - "reference": "cd9864b47c367450e14ab32f78fdbf98c44c26b6", + "url": "https://api.github.com/repos/symfony/console/zipball/0254811a143e6bc6c8deea08b589a7e68a37f625", + "reference": "0254811a143e6bc6c8deea08b589a7e68a37f625", "shasum": "" }, "require": { @@ -2375,7 +2375,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.4.0" + "source": "https://github.com/symfony/console/tree/v6.4.2" }, "funding": [ { @@ -2391,7 +2391,7 @@ "type": "tidelift" } ], - "time": "2023-11-20T16:41:16+00:00" + "time": "2023-12-10T16:15:48+00:00" }, { "name": "symfony/css-selector", @@ -2460,16 +2460,16 @@ }, { "name": "symfony/dependency-injection", - "version": "v6.4.0", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "5dc8ad5f2bbba7046f5947682bf7d868ce80d4e8" + "reference": "226ea431b1eda6f0d9f5a4b278757171960bb195" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/5dc8ad5f2bbba7046f5947682bf7d868ce80d4e8", - "reference": "5dc8ad5f2bbba7046f5947682bf7d868ce80d4e8", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/226ea431b1eda6f0d9f5a4b278757171960bb195", + "reference": "226ea431b1eda6f0d9f5a4b278757171960bb195", "shasum": "" }, "require": { @@ -2521,7 +2521,7 @@ "description": "Allows you to standardize and centralize the way objects are constructed in your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dependency-injection/tree/v6.4.0" + "source": "https://github.com/symfony/dependency-injection/tree/v6.4.2" }, "funding": [ { @@ -2537,7 +2537,7 @@ "type": "tidelift" } ], - "time": "2023-10-31T08:40:20+00:00" + "time": "2023-12-28T19:16:56+00:00" }, { "name": "symfony/deprecation-contracts", @@ -2608,16 +2608,16 @@ }, { "name": "symfony/dotenv", - "version": "v6.4.0", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/dotenv.git", - "reference": "d0d584a91422ddaa2c94317200d4c4e5b935555f" + "reference": "835f8d2d1022934ac038519de40b88158798c96f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dotenv/zipball/d0d584a91422ddaa2c94317200d4c4e5b935555f", - "reference": "d0d584a91422ddaa2c94317200d4c4e5b935555f", + "url": "https://api.github.com/repos/symfony/dotenv/zipball/835f8d2d1022934ac038519de40b88158798c96f", + "reference": "835f8d2d1022934ac038519de40b88158798c96f", "shasum": "" }, "require": { @@ -2662,7 +2662,7 @@ "environment" ], "support": { - "source": "https://github.com/symfony/dotenv/tree/v6.4.0" + "source": "https://github.com/symfony/dotenv/tree/v6.4.2" }, "funding": [ { @@ -2678,7 +2678,7 @@ "type": "tidelift" } ], - "time": "2023-10-26T18:19:48+00:00" + "time": "2023-12-28T19:16:56+00:00" }, { "name": "symfony/error-handler", @@ -2757,16 +2757,16 @@ }, { "name": "symfony/event-dispatcher", - "version": "v6.4.0", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "d76d2632cfc2206eecb5ad2b26cd5934082941b6" + "reference": "e95216850555cd55e71b857eb9d6c2674124603a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/d76d2632cfc2206eecb5ad2b26cd5934082941b6", - "reference": "d76d2632cfc2206eecb5ad2b26cd5934082941b6", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/e95216850555cd55e71b857eb9d6c2674124603a", + "reference": "e95216850555cd55e71b857eb9d6c2674124603a", "shasum": "" }, "require": { @@ -2817,7 +2817,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v6.4.0" + "source": "https://github.com/symfony/event-dispatcher/tree/v6.4.2" }, "funding": [ { @@ -2833,7 +2833,7 @@ "type": "tidelift" } ], - "time": "2023-07-27T06:52:43+00:00" + "time": "2023-12-27T22:16:42+00:00" }, { "name": "symfony/event-dispatcher-contracts", @@ -3040,16 +3040,16 @@ }, { "name": "symfony/framework-bundle", - "version": "v6.4.0", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/framework-bundle.git", - "reference": "981e016715b4a7f22f58c1d9fdf444311965d25e" + "reference": "c26a221e0462027d1f9d4a802ed63f8ab07a43d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/981e016715b4a7f22f58c1d9fdf444311965d25e", - "reference": "981e016715b4a7f22f58c1d9fdf444311965d25e", + "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/c26a221e0462027d1f9d4a802ed63f8ab07a43d0", + "reference": "c26a221e0462027d1f9d4a802ed63f8ab07a43d0", "shasum": "" }, "require": { @@ -3077,7 +3077,7 @@ "symfony/asset": "<5.4", "symfony/asset-mapper": "<6.4", "symfony/clock": "<6.3", - "symfony/console": "<5.4", + "symfony/console": "<5.4|>=7.0", "symfony/dom-crawler": "<6.4", "symfony/dotenv": "<5.4", "symfony/form": "<5.4", @@ -3168,7 +3168,7 @@ "description": "Provides a tight integration between Symfony components and the Symfony full-stack framework", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/framework-bundle/tree/v6.4.0" + "source": "https://github.com/symfony/framework-bundle/tree/v6.4.2" }, "funding": [ { @@ -3184,20 +3184,20 @@ "type": "tidelift" } ], - "time": "2023-11-25T19:10:27+00:00" + "time": "2023-12-29T15:34:34+00:00" }, { "name": "symfony/http-foundation", - "version": "v6.4.0", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "44a6d39a9cc11e154547d882d5aac1e014440771" + "reference": "172d807f9ef3fc3fbed8377cc57c20d389269271" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/44a6d39a9cc11e154547d882d5aac1e014440771", - "reference": "44a6d39a9cc11e154547d882d5aac1e014440771", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/172d807f9ef3fc3fbed8377cc57c20d389269271", + "reference": "172d807f9ef3fc3fbed8377cc57c20d389269271", "shasum": "" }, "require": { @@ -3245,7 +3245,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v6.4.0" + "source": "https://github.com/symfony/http-foundation/tree/v6.4.2" }, "funding": [ { @@ -3261,20 +3261,20 @@ "type": "tidelift" } ], - "time": "2023-11-20T16:41:16+00:00" + "time": "2023-12-27T22:16:42+00:00" }, { "name": "symfony/http-kernel", - "version": "v6.4.0", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "16a29c453966f29466ad34444ce97970a336f3c8" + "reference": "13e8387320b5942d0dc408440c888e2d526efef4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/16a29c453966f29466ad34444ce97970a336f3c8", - "reference": "16a29c453966f29466ad34444ce97970a336f3c8", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/13e8387320b5942d0dc408440c888e2d526efef4", + "reference": "13e8387320b5942d0dc408440c888e2d526efef4", "shasum": "" }, "require": { @@ -3358,7 +3358,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v6.4.0" + "source": "https://github.com/symfony/http-kernel/tree/v6.4.2" }, "funding": [ { @@ -3374,7 +3374,7 @@ "type": "tidelift" } ], - "time": "2023-11-29T10:40:15+00:00" + "time": "2023-12-30T15:31:44+00:00" }, { "name": "symfony/polyfill-ctype", @@ -4034,16 +4034,16 @@ }, { "name": "symfony/routing", - "version": "v6.4.0", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "ae014d60d7c8e80be5c3b644a286e91249a3e8f4" + "reference": "98eab13a07fddc85766f1756129c69f207ffbc21" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/ae014d60d7c8e80be5c3b644a286e91249a3e8f4", - "reference": "ae014d60d7c8e80be5c3b644a286e91249a3e8f4", + "url": "https://api.github.com/repos/symfony/routing/zipball/98eab13a07fddc85766f1756129c69f207ffbc21", + "reference": "98eab13a07fddc85766f1756129c69f207ffbc21", "shasum": "" }, "require": { @@ -4097,7 +4097,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v6.4.0" + "source": "https://github.com/symfony/routing/tree/v6.4.2" }, "funding": [ { @@ -4113,7 +4113,7 @@ "type": "tidelift" } ], - "time": "2023-11-29T08:04:54+00:00" + "time": "2023-12-29T15:34:34+00:00" }, { "name": "symfony/runtime", @@ -4196,33 +4196,29 @@ }, { "name": "symfony/service-contracts", - "version": "v2.5.2", + "version": "v3.4.1", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c" + "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/4b426aac47d6427cc1a1d0f7e2ac724627f5966c", - "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/fe07cbc8d837f60caf7018068e350cc5163681a0", + "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0", "shasum": "" }, "require": { - "php": ">=7.2.5", - "psr/container": "^1.1", - "symfony/deprecation-contracts": "^2.1|^3" + "php": ">=8.1", + "psr/container": "^1.1|^2.0" }, "conflict": { "ext-psr": "<1.1|>=2" }, - "suggest": { - "symfony/service-implementation": "" - }, "type": "library", "extra": { "branch-alias": { - "dev-main": "2.5-dev" + "dev-main": "3.4-dev" }, "thanks": { "name": "symfony/contracts", @@ -4232,7 +4228,10 @@ "autoload": { "psr-4": { "Symfony\\Contracts\\Service\\": "" - } + }, + "exclude-from-classmap": [ + "/Test/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -4259,7 +4258,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v2.5.2" + "source": "https://github.com/symfony/service-contracts/tree/v3.4.1" }, "funding": [ { @@ -4275,20 +4274,20 @@ "type": "tidelift" } ], - "time": "2022-05-30T19:17:29+00:00" + "time": "2023-12-26T14:02:43+00:00" }, { "name": "symfony/string", - "version": "v6.4.0", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "b45fcf399ea9c3af543a92edf7172ba21174d809" + "reference": "7cb80bc10bfcdf6b5492741c0b9357dac66940bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/b45fcf399ea9c3af543a92edf7172ba21174d809", - "reference": "b45fcf399ea9c3af543a92edf7172ba21174d809", + "url": "https://api.github.com/repos/symfony/string/zipball/7cb80bc10bfcdf6b5492741c0b9357dac66940bc", + "reference": "7cb80bc10bfcdf6b5492741c0b9357dac66940bc", "shasum": "" }, "require": { @@ -4345,7 +4344,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.4.0" + "source": "https://github.com/symfony/string/tree/v6.4.2" }, "funding": [ { @@ -4361,7 +4360,7 @@ "type": "tidelift" } ], - "time": "2023-11-28T20:41:49+00:00" + "time": "2023-12-10T16:15:48+00:00" }, { "name": "symfony/translation-contracts", @@ -4636,16 +4635,16 @@ }, { "name": "symfony/var-dumper", - "version": "v6.4.0", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "c40f7d17e91d8b407582ed51a2bbf83c52c367f6" + "reference": "68d6573ec98715ddcae5a0a85bee3c1c27a4c33f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/c40f7d17e91d8b407582ed51a2bbf83c52c367f6", - "reference": "c40f7d17e91d8b407582ed51a2bbf83c52c367f6", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/68d6573ec98715ddcae5a0a85bee3c1c27a4c33f", + "reference": "68d6573ec98715ddcae5a0a85bee3c1c27a4c33f", "shasum": "" }, "require": { @@ -4701,7 +4700,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v6.4.0" + "source": "https://github.com/symfony/var-dumper/tree/v6.4.2" }, "funding": [ { @@ -4717,20 +4716,20 @@ "type": "tidelift" } ], - "time": "2023-11-09T08:28:32+00:00" + "time": "2023-12-28T19:16:56+00:00" }, { "name": "symfony/var-exporter", - "version": "v6.4.0", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/var-exporter.git", - "reference": "d6081c0316f0f5921f2010d1766925005a82ea3b" + "reference": "5fe9a0021b8d35e67d914716ec8de50716a68e7e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/d6081c0316f0f5921f2010d1766925005a82ea3b", - "reference": "d6081c0316f0f5921f2010d1766925005a82ea3b", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/5fe9a0021b8d35e67d914716ec8de50716a68e7e", + "reference": "5fe9a0021b8d35e67d914716ec8de50716a68e7e", "shasum": "" }, "require": { @@ -4776,7 +4775,7 @@ "serialize" ], "support": { - "source": "https://github.com/symfony/var-exporter/tree/v6.4.0" + "source": "https://github.com/symfony/var-exporter/tree/v6.4.2" }, "funding": [ { @@ -4792,7 +4791,7 @@ "type": "tidelift" } ], - "time": "2023-11-28T20:41:49+00:00" + "time": "2023-12-27T08:18:35+00:00" }, { "name": "symfony/yaml", @@ -4928,33 +4927,29 @@ }, { "name": "twig/twig", - "version": "v3.4.3", + "version": "v3.8.0", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "c38fd6b0b7f370c198db91ffd02e23b517426b58" + "reference": "9d15f0ac07f44dc4217883ec6ae02fd555c6f71d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/c38fd6b0b7f370c198db91ffd02e23b517426b58", - "reference": "c38fd6b0b7f370c198db91ffd02e23b517426b58", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/9d15f0ac07f44dc4217883ec6ae02fd555c6f71d", + "reference": "9d15f0ac07f44dc4217883ec6ae02fd555c6f71d", "shasum": "" }, "require": { "php": ">=7.2.5", "symfony/polyfill-ctype": "^1.8", - "symfony/polyfill-mbstring": "^1.3" + "symfony/polyfill-mbstring": "^1.3", + "symfony/polyfill-php80": "^1.22" }, "require-dev": { - "psr/container": "^1.0", - "symfony/phpunit-bridge": "^4.4.9|^5.0.9|^6.0" + "psr/container": "^1.0|^2.0", + "symfony/phpunit-bridge": "^5.4.9|^6.3|^7.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, "autoload": { "psr-4": { "Twig\\": "src/" @@ -4988,7 +4983,7 @@ ], "support": { "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v3.4.3" + "source": "https://github.com/twigphp/Twig/tree/v3.8.0" }, "funding": [ { @@ -5000,7 +4995,7 @@ "type": "tidelift" } ], - "time": "2022-09-28T08:42:51+00:00" + "time": "2023-11-21T18:54:41+00:00" }, { "name": "webmozart/assert", @@ -5200,16 +5195,16 @@ }, { "name": "symfony/web-profiler-bundle", - "version": "v6.4.0", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/web-profiler-bundle.git", - "reference": "14752d3fb77c3c69b6cee7c03c06e2d6494a196b" + "reference": "38462d16856740ec0d1ba2cb902eebf09100dde2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/14752d3fb77c3c69b6cee7c03c06e2d6494a196b", - "reference": "14752d3fb77c3c69b6cee7c03c06e2d6494a196b", + "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/38462d16856740ec0d1ba2cb902eebf09100dde2", + "reference": "38462d16856740ec0d1ba2cb902eebf09100dde2", "shasum": "" }, "require": { @@ -5262,7 +5257,7 @@ "dev" ], "support": { - "source": "https://github.com/symfony/web-profiler-bundle/tree/v6.4.0" + "source": "https://github.com/symfony/web-profiler-bundle/tree/v6.4.2" }, "funding": [ { @@ -5278,7 +5273,7 @@ "type": "tidelift" } ], - "time": "2023-11-07T14:57:07+00:00" + "time": "2023-12-27T08:18:35+00:00" } ], "aliases": [], diff --git a/lib/composer/autoload_classmap.php b/lib/composer/autoload_classmap.php index 03e006e08..c394e3b37 100644 --- a/lib/composer/autoload_classmap.php +++ b/lib/composer/autoload_classmap.php @@ -2950,6 +2950,8 @@ return array( 'Twig\\Node\\Expression\\Binary\\FloorDivBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/FloorDivBinary.php', 'Twig\\Node\\Expression\\Binary\\GreaterBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/GreaterBinary.php', 'Twig\\Node\\Expression\\Binary\\GreaterEqualBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/GreaterEqualBinary.php', + 'Twig\\Node\\Expression\\Binary\\HasEveryBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/HasEveryBinary.php', + 'Twig\\Node\\Expression\\Binary\\HasSomeBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/HasSomeBinary.php', 'Twig\\Node\\Expression\\Binary\\InBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/InBinary.php', 'Twig\\Node\\Expression\\Binary\\LessBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/LessBinary.php', 'Twig\\Node\\Expression\\Binary\\LessEqualBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/LessEqualBinary.php', @@ -3030,6 +3032,8 @@ return array( 'Twig\\Source' => $vendorDir . '/twig/twig/src/Source.php', 'Twig\\Template' => $vendorDir . '/twig/twig/src/Template.php', 'Twig\\TemplateWrapper' => $vendorDir . '/twig/twig/src/TemplateWrapper.php', + 'Twig\\Test\\IntegrationTestCase' => $vendorDir . '/twig/twig/src/Test/IntegrationTestCase.php', + 'Twig\\Test\\NodeTestCase' => $vendorDir . '/twig/twig/src/Test/NodeTestCase.php', 'Twig\\Token' => $vendorDir . '/twig/twig/src/Token.php', 'Twig\\TokenParser\\AbstractTokenParser' => $vendorDir . '/twig/twig/src/TokenParser/AbstractTokenParser.php', 'Twig\\TokenParser\\ApplyTokenParser' => $vendorDir . '/twig/twig/src/TokenParser/ApplyTokenParser.php', diff --git a/lib/composer/autoload_static.php b/lib/composer/autoload_static.php index c5d8c98f3..fc0497d3f 100644 --- a/lib/composer/autoload_static.php +++ b/lib/composer/autoload_static.php @@ -3325,6 +3325,8 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'Twig\\Node\\Expression\\Binary\\FloorDivBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/FloorDivBinary.php', 'Twig\\Node\\Expression\\Binary\\GreaterBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/GreaterBinary.php', 'Twig\\Node\\Expression\\Binary\\GreaterEqualBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/GreaterEqualBinary.php', + 'Twig\\Node\\Expression\\Binary\\HasEveryBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/HasEveryBinary.php', + 'Twig\\Node\\Expression\\Binary\\HasSomeBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/HasSomeBinary.php', 'Twig\\Node\\Expression\\Binary\\InBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/InBinary.php', 'Twig\\Node\\Expression\\Binary\\LessBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/LessBinary.php', 'Twig\\Node\\Expression\\Binary\\LessEqualBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/LessEqualBinary.php', @@ -3405,6 +3407,8 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'Twig\\Source' => __DIR__ . '/..' . '/twig/twig/src/Source.php', 'Twig\\Template' => __DIR__ . '/..' . '/twig/twig/src/Template.php', 'Twig\\TemplateWrapper' => __DIR__ . '/..' . '/twig/twig/src/TemplateWrapper.php', + 'Twig\\Test\\IntegrationTestCase' => __DIR__ . '/..' . '/twig/twig/src/Test/IntegrationTestCase.php', + 'Twig\\Test\\NodeTestCase' => __DIR__ . '/..' . '/twig/twig/src/Test/NodeTestCase.php', 'Twig\\Token' => __DIR__ . '/..' . '/twig/twig/src/Token.php', 'Twig\\TokenParser\\AbstractTokenParser' => __DIR__ . '/..' . '/twig/twig/src/TokenParser/AbstractTokenParser.php', 'Twig\\TokenParser\\ApplyTokenParser' => __DIR__ . '/..' . '/twig/twig/src/TokenParser/ApplyTokenParser.php', diff --git a/lib/composer/installed.json b/lib/composer/installed.json index a8b851ca7..ec2489611 100644 --- a/lib/composer/installed.json +++ b/lib/composer/installed.json @@ -2141,17 +2141,17 @@ }, { "name": "symfony/cache", - "version": "v6.4.0", - "version_normalized": "6.4.0.0", + "version": "v6.4.2", + "version_normalized": "6.4.2.0", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "ac2d25f97b17eec6e19760b6b9962a4f7c44356a" + "reference": "14a75869bbb41cb35bc5d9d322473928c6f3f978" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/ac2d25f97b17eec6e19760b6b9962a4f7c44356a", - "reference": "ac2d25f97b17eec6e19760b6b9962a4f7c44356a", + "url": "https://api.github.com/repos/symfony/cache/zipball/14a75869bbb41cb35bc5d9d322473928c6f3f978", + "reference": "14a75869bbb41cb35bc5d9d322473928c6f3f978", "shasum": "" }, "require": { @@ -2185,7 +2185,7 @@ "symfony/messenger": "^5.4|^6.0|^7.0", "symfony/var-dumper": "^5.4|^6.0|^7.0" }, - "time": "2023-11-24T19:28:07+00:00", + "time": "2023-12-29T15:34:34+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -2220,7 +2220,7 @@ "psr6" ], "support": { - "source": "https://github.com/symfony/cache/tree/v6.4.0" + "source": "https://github.com/symfony/cache/tree/v6.4.2" }, "funding": [ { @@ -2397,17 +2397,17 @@ }, { "name": "symfony/console", - "version": "v6.4.0", - "version_normalized": "6.4.0.0", + "version": "v6.4.2", + "version_normalized": "6.4.2.0", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "cd9864b47c367450e14ab32f78fdbf98c44c26b6" + "reference": "0254811a143e6bc6c8deea08b589a7e68a37f625" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/cd9864b47c367450e14ab32f78fdbf98c44c26b6", - "reference": "cd9864b47c367450e14ab32f78fdbf98c44c26b6", + "url": "https://api.github.com/repos/symfony/console/zipball/0254811a143e6bc6c8deea08b589a7e68a37f625", + "reference": "0254811a143e6bc6c8deea08b589a7e68a37f625", "shasum": "" }, "require": { @@ -2440,7 +2440,7 @@ "symfony/stopwatch": "^5.4|^6.0|^7.0", "symfony/var-dumper": "^5.4|^6.0|^7.0" }, - "time": "2023-11-20T16:41:16+00:00", + "time": "2023-12-10T16:15:48+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -2474,7 +2474,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.4.0" + "source": "https://github.com/symfony/console/tree/v6.4.2" }, "funding": [ { @@ -2639,17 +2639,17 @@ }, { "name": "symfony/dependency-injection", - "version": "v6.4.0", - "version_normalized": "6.4.0.0", + "version": "v6.4.2", + "version_normalized": "6.4.2.0", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "5dc8ad5f2bbba7046f5947682bf7d868ce80d4e8" + "reference": "226ea431b1eda6f0d9f5a4b278757171960bb195" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/5dc8ad5f2bbba7046f5947682bf7d868ce80d4e8", - "reference": "5dc8ad5f2bbba7046f5947682bf7d868ce80d4e8", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/226ea431b1eda6f0d9f5a4b278757171960bb195", + "reference": "226ea431b1eda6f0d9f5a4b278757171960bb195", "shasum": "" }, "require": { @@ -2675,7 +2675,7 @@ "symfony/expression-language": "^5.4|^6.0|^7.0", "symfony/yaml": "^5.4|^6.0|^7.0" }, - "time": "2023-10-31T08:40:20+00:00", + "time": "2023-12-28T19:16:56+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -2703,7 +2703,7 @@ "description": "Allows you to standardize and centralize the way objects are constructed in your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dependency-injection/tree/v6.4.0" + "source": "https://github.com/symfony/dependency-injection/tree/v6.4.2" }, "funding": [ { @@ -2793,17 +2793,17 @@ }, { "name": "symfony/dotenv", - "version": "v6.4.0", - "version_normalized": "6.4.0.0", + "version": "v6.4.2", + "version_normalized": "6.4.2.0", "source": { "type": "git", "url": "https://github.com/symfony/dotenv.git", - "reference": "d0d584a91422ddaa2c94317200d4c4e5b935555f" + "reference": "835f8d2d1022934ac038519de40b88158798c96f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dotenv/zipball/d0d584a91422ddaa2c94317200d4c4e5b935555f", - "reference": "d0d584a91422ddaa2c94317200d4c4e5b935555f", + "url": "https://api.github.com/repos/symfony/dotenv/zipball/835f8d2d1022934ac038519de40b88158798c96f", + "reference": "835f8d2d1022934ac038519de40b88158798c96f", "shasum": "" }, "require": { @@ -2817,7 +2817,7 @@ "symfony/console": "^5.4|^6.0|^7.0", "symfony/process": "^5.4|^6.0|^7.0" }, - "time": "2023-10-26T18:19:48+00:00", + "time": "2023-12-28T19:16:56+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -2850,7 +2850,7 @@ "environment" ], "support": { - "source": "https://github.com/symfony/dotenv/tree/v6.4.0" + "source": "https://github.com/symfony/dotenv/tree/v6.4.2" }, "funding": [ { @@ -2948,17 +2948,17 @@ }, { "name": "symfony/event-dispatcher", - "version": "v6.4.0", - "version_normalized": "6.4.0.0", + "version": "v6.4.2", + "version_normalized": "6.4.2.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "d76d2632cfc2206eecb5ad2b26cd5934082941b6" + "reference": "e95216850555cd55e71b857eb9d6c2674124603a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/d76d2632cfc2206eecb5ad2b26cd5934082941b6", - "reference": "d76d2632cfc2206eecb5ad2b26cd5934082941b6", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/e95216850555cd55e71b857eb9d6c2674124603a", + "reference": "e95216850555cd55e71b857eb9d6c2674124603a", "shasum": "" }, "require": { @@ -2983,7 +2983,7 @@ "symfony/service-contracts": "^2.5|^3", "symfony/stopwatch": "^5.4|^6.0|^7.0" }, - "time": "2023-07-27T06:52:43+00:00", + "time": "2023-12-27T22:16:42+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -3011,7 +3011,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v6.4.0" + "source": "https://github.com/symfony/event-dispatcher/tree/v6.4.2" }, "funding": [ { @@ -3243,17 +3243,17 @@ }, { "name": "symfony/framework-bundle", - "version": "v6.4.0", - "version_normalized": "6.4.0.0", + "version": "v6.4.2", + "version_normalized": "6.4.2.0", "source": { "type": "git", "url": "https://github.com/symfony/framework-bundle.git", - "reference": "981e016715b4a7f22f58c1d9fdf444311965d25e" + "reference": "c26a221e0462027d1f9d4a802ed63f8ab07a43d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/981e016715b4a7f22f58c1d9fdf444311965d25e", - "reference": "981e016715b4a7f22f58c1d9fdf444311965d25e", + "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/c26a221e0462027d1f9d4a802ed63f8ab07a43d0", + "reference": "c26a221e0462027d1f9d4a802ed63f8ab07a43d0", "shasum": "" }, "require": { @@ -3281,7 +3281,7 @@ "symfony/asset": "<5.4", "symfony/asset-mapper": "<6.4", "symfony/clock": "<6.3", - "symfony/console": "<5.4", + "symfony/console": "<5.4|>=7.0", "symfony/dom-crawler": "<6.4", "symfony/dotenv": "<5.4", "symfony/form": "<5.4", @@ -3346,7 +3346,7 @@ "symfony/yaml": "^5.4|^6.0|^7.0", "twig/twig": "^2.10|^3.0" }, - "time": "2023-11-25T19:10:27+00:00", + "time": "2023-12-29T15:34:34+00:00", "type": "symfony-bundle", "installation-source": "dist", "autoload": { @@ -3374,7 +3374,7 @@ "description": "Provides a tight integration between Symfony components and the Symfony full-stack framework", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/framework-bundle/tree/v6.4.0" + "source": "https://github.com/symfony/framework-bundle/tree/v6.4.2" }, "funding": [ { @@ -3394,17 +3394,17 @@ }, { "name": "symfony/http-foundation", - "version": "v6.4.0", - "version_normalized": "6.4.0.0", + "version": "v6.4.2", + "version_normalized": "6.4.2.0", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "44a6d39a9cc11e154547d882d5aac1e014440771" + "reference": "172d807f9ef3fc3fbed8377cc57c20d389269271" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/44a6d39a9cc11e154547d882d5aac1e014440771", - "reference": "44a6d39a9cc11e154547d882d5aac1e014440771", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/172d807f9ef3fc3fbed8377cc57c20d389269271", + "reference": "172d807f9ef3fc3fbed8377cc57c20d389269271", "shasum": "" }, "require": { @@ -3426,7 +3426,7 @@ "symfony/mime": "^5.4|^6.0|^7.0", "symfony/rate-limiter": "^5.4|^6.0|^7.0" }, - "time": "2023-11-20T16:41:16+00:00", + "time": "2023-12-27T22:16:42+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -3454,7 +3454,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v6.4.0" + "source": "https://github.com/symfony/http-foundation/tree/v6.4.2" }, "funding": [ { @@ -3474,17 +3474,17 @@ }, { "name": "symfony/http-kernel", - "version": "v6.4.0", - "version_normalized": "6.4.0.0", + "version": "v6.4.2", + "version_normalized": "6.4.2.0", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "16a29c453966f29466ad34444ce97970a336f3c8" + "reference": "13e8387320b5942d0dc408440c888e2d526efef4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/16a29c453966f29466ad34444ce97970a336f3c8", - "reference": "16a29c453966f29466ad34444ce97970a336f3c8", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/13e8387320b5942d0dc408440c888e2d526efef4", + "reference": "13e8387320b5942d0dc408440c888e2d526efef4", "shasum": "" }, "require": { @@ -3542,7 +3542,7 @@ "symfony/var-exporter": "^6.2|^7.0", "twig/twig": "^2.13|^3.0.4" }, - "time": "2023-11-29T10:40:15+00:00", + "time": "2023-12-30T15:31:44+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -3570,7 +3570,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v6.4.0" + "source": "https://github.com/symfony/http-kernel/tree/v6.4.2" }, "funding": [ { @@ -4270,17 +4270,17 @@ }, { "name": "symfony/routing", - "version": "v6.4.0", - "version_normalized": "6.4.0.0", + "version": "v6.4.2", + "version_normalized": "6.4.2.0", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "ae014d60d7c8e80be5c3b644a286e91249a3e8f4" + "reference": "98eab13a07fddc85766f1756129c69f207ffbc21" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/ae014d60d7c8e80be5c3b644a286e91249a3e8f4", - "reference": "ae014d60d7c8e80be5c3b644a286e91249a3e8f4", + "url": "https://api.github.com/repos/symfony/routing/zipball/98eab13a07fddc85766f1756129c69f207ffbc21", + "reference": "98eab13a07fddc85766f1756129c69f207ffbc21", "shasum": "" }, "require": { @@ -4302,7 +4302,7 @@ "symfony/http-foundation": "^5.4|^6.0|^7.0", "symfony/yaml": "^5.4|^6.0|^7.0" }, - "time": "2023-11-29T08:04:54+00:00", + "time": "2023-12-29T15:34:34+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -4336,7 +4336,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v6.4.0" + "source": "https://github.com/symfony/routing/tree/v6.4.2" }, "funding": [ { @@ -4438,35 +4438,31 @@ }, { "name": "symfony/service-contracts", - "version": "v2.5.2", - "version_normalized": "2.5.2.0", + "version": "v3.4.1", + "version_normalized": "3.4.1.0", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c" + "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/4b426aac47d6427cc1a1d0f7e2ac724627f5966c", - "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/fe07cbc8d837f60caf7018068e350cc5163681a0", + "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0", "shasum": "" }, "require": { - "php": ">=7.2.5", - "psr/container": "^1.1", - "symfony/deprecation-contracts": "^2.1|^3" + "php": ">=8.1", + "psr/container": "^1.1|^2.0" }, "conflict": { "ext-psr": "<1.1|>=2" }, - "suggest": { - "symfony/service-implementation": "" - }, - "time": "2022-05-30T19:17:29+00:00", + "time": "2023-12-26T14:02:43+00:00", "type": "library", "extra": { "branch-alias": { - "dev-main": "2.5-dev" + "dev-main": "3.4-dev" }, "thanks": { "name": "symfony/contracts", @@ -4477,7 +4473,10 @@ "autoload": { "psr-4": { "Symfony\\Contracts\\Service\\": "" - } + }, + "exclude-from-classmap": [ + "/Test/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -4504,7 +4503,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v2.5.2" + "source": "https://github.com/symfony/service-contracts/tree/v3.4.1" }, "funding": [ { @@ -4589,17 +4588,17 @@ }, { "name": "symfony/string", - "version": "v6.4.0", - "version_normalized": "6.4.0.0", + "version": "v6.4.2", + "version_normalized": "6.4.2.0", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "b45fcf399ea9c3af543a92edf7172ba21174d809" + "reference": "7cb80bc10bfcdf6b5492741c0b9357dac66940bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/b45fcf399ea9c3af543a92edf7172ba21174d809", - "reference": "b45fcf399ea9c3af543a92edf7172ba21174d809", + "url": "https://api.github.com/repos/symfony/string/zipball/7cb80bc10bfcdf6b5492741c0b9357dac66940bc", + "reference": "7cb80bc10bfcdf6b5492741c0b9357dac66940bc", "shasum": "" }, "require": { @@ -4619,7 +4618,7 @@ "symfony/translation-contracts": "^2.5|^3.0", "symfony/var-exporter": "^5.4|^6.0|^7.0" }, - "time": "2023-11-28T20:41:49+00:00", + "time": "2023-12-10T16:15:48+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -4658,7 +4657,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.4.0" + "source": "https://github.com/symfony/string/tree/v6.4.2" }, "funding": [ { @@ -4958,17 +4957,17 @@ }, { "name": "symfony/var-dumper", - "version": "v6.4.0", - "version_normalized": "6.4.0.0", + "version": "v6.4.2", + "version_normalized": "6.4.2.0", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "c40f7d17e91d8b407582ed51a2bbf83c52c367f6" + "reference": "68d6573ec98715ddcae5a0a85bee3c1c27a4c33f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/c40f7d17e91d8b407582ed51a2bbf83c52c367f6", - "reference": "c40f7d17e91d8b407582ed51a2bbf83c52c367f6", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/68d6573ec98715ddcae5a0a85bee3c1c27a4c33f", + "reference": "68d6573ec98715ddcae5a0a85bee3c1c27a4c33f", "shasum": "" }, "require": { @@ -4988,7 +4987,7 @@ "symfony/uid": "^5.4|^6.0|^7.0", "twig/twig": "^2.13|^3.0.4" }, - "time": "2023-11-09T08:28:32+00:00", + "time": "2023-12-28T19:16:56+00:00", "bin": [ "Resources/bin/var-dump-server" ], @@ -5026,7 +5025,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v6.4.0" + "source": "https://github.com/symfony/var-dumper/tree/v6.4.2" }, "funding": [ { @@ -5046,17 +5045,17 @@ }, { "name": "symfony/var-exporter", - "version": "v6.4.0", - "version_normalized": "6.4.0.0", + "version": "v6.4.2", + "version_normalized": "6.4.2.0", "source": { "type": "git", "url": "https://github.com/symfony/var-exporter.git", - "reference": "d6081c0316f0f5921f2010d1766925005a82ea3b" + "reference": "5fe9a0021b8d35e67d914716ec8de50716a68e7e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/d6081c0316f0f5921f2010d1766925005a82ea3b", - "reference": "d6081c0316f0f5921f2010d1766925005a82ea3b", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/5fe9a0021b8d35e67d914716ec8de50716a68e7e", + "reference": "5fe9a0021b8d35e67d914716ec8de50716a68e7e", "shasum": "" }, "require": { @@ -5066,7 +5065,7 @@ "require-dev": { "symfony/var-dumper": "^5.4|^6.0|^7.0" }, - "time": "2023-11-28T20:41:49+00:00", + "time": "2023-12-27T08:18:35+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -5104,7 +5103,7 @@ "serialize" ], "support": { - "source": "https://github.com/symfony/var-exporter/tree/v6.4.0" + "source": "https://github.com/symfony/var-exporter/tree/v6.4.2" }, "funding": [ { @@ -5124,17 +5123,17 @@ }, { "name": "symfony/web-profiler-bundle", - "version": "v6.4.0", - "version_normalized": "6.4.0.0", + "version": "v6.4.2", + "version_normalized": "6.4.2.0", "source": { "type": "git", "url": "https://github.com/symfony/web-profiler-bundle.git", - "reference": "14752d3fb77c3c69b6cee7c03c06e2d6494a196b" + "reference": "38462d16856740ec0d1ba2cb902eebf09100dde2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/14752d3fb77c3c69b6cee7c03c06e2d6494a196b", - "reference": "14752d3fb77c3c69b6cee7c03c06e2d6494a196b", + "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/38462d16856740ec0d1ba2cb902eebf09100dde2", + "reference": "38462d16856740ec0d1ba2cb902eebf09100dde2", "shasum": "" }, "require": { @@ -5158,7 +5157,7 @@ "symfony/css-selector": "^5.4|^6.0|^7.0", "symfony/stopwatch": "^5.4|^6.0|^7.0" }, - "time": "2023-11-07T14:57:07+00:00", + "time": "2023-12-27T08:18:35+00:00", "type": "symfony-bundle", "installation-source": "dist", "autoload": { @@ -5189,7 +5188,7 @@ "dev" ], "support": { - "source": "https://github.com/symfony/web-profiler-bundle/tree/v6.4.0" + "source": "https://github.com/symfony/web-profiler-bundle/tree/v6.4.2" }, "funding": [ { @@ -5347,35 +5346,31 @@ }, { "name": "twig/twig", - "version": "v3.4.3", - "version_normalized": "3.4.3.0", + "version": "v3.8.0", + "version_normalized": "3.8.0.0", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "c38fd6b0b7f370c198db91ffd02e23b517426b58" + "reference": "9d15f0ac07f44dc4217883ec6ae02fd555c6f71d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/c38fd6b0b7f370c198db91ffd02e23b517426b58", - "reference": "c38fd6b0b7f370c198db91ffd02e23b517426b58", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/9d15f0ac07f44dc4217883ec6ae02fd555c6f71d", + "reference": "9d15f0ac07f44dc4217883ec6ae02fd555c6f71d", "shasum": "" }, "require": { "php": ">=7.2.5", "symfony/polyfill-ctype": "^1.8", - "symfony/polyfill-mbstring": "^1.3" + "symfony/polyfill-mbstring": "^1.3", + "symfony/polyfill-php80": "^1.22" }, "require-dev": { - "psr/container": "^1.0", - "symfony/phpunit-bridge": "^4.4.9|^5.0.9|^6.0" + "psr/container": "^1.0|^2.0", + "symfony/phpunit-bridge": "^5.4.9|^6.3|^7.0" }, - "time": "2022-09-28T08:42:51+00:00", + "time": "2023-11-21T18:54:41+00:00", "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, "installation-source": "dist", "autoload": { "psr-4": { @@ -5410,7 +5405,7 @@ ], "support": { "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v3.4.3" + "source": "https://github.com/twigphp/Twig/tree/v3.8.0" }, "funding": [ { diff --git a/lib/composer/installed.php b/lib/composer/installed.php index 0c789fb7e..7a72d010b 100644 --- a/lib/composer/installed.php +++ b/lib/composer/installed.php @@ -3,7 +3,7 @@ 'name' => 'combodo/itop', 'pretty_version' => 'dev-develop', 'version' => 'dev-develop', - 'reference' => '195d4137172d9169005b6b7f0569866480e6260f', + 'reference' => '30fabba7375459537e74897dc7dcdad61f73d10e', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -22,7 +22,7 @@ 'combodo/itop' => array( 'pretty_version' => 'dev-develop', 'version' => 'dev-develop', - 'reference' => '195d4137172d9169005b6b7f0569866480e6260f', + 'reference' => '30fabba7375459537e74897dc7dcdad61f73d10e', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -360,9 +360,9 @@ 'dev_requirement' => false, ), 'symfony/cache' => array( - 'pretty_version' => 'v6.4.0', - 'version' => '6.4.0.0', - 'reference' => 'ac2d25f97b17eec6e19760b6b9962a4f7c44356a', + 'pretty_version' => 'v6.4.2', + 'version' => '6.4.2.0', + 'reference' => '14a75869bbb41cb35bc5d9d322473928c6f3f978', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/cache', 'aliases' => array(), @@ -393,9 +393,9 @@ 'dev_requirement' => false, ), 'symfony/console' => array( - 'pretty_version' => 'v6.4.0', - 'version' => '6.4.0.0', - 'reference' => 'cd9864b47c367450e14ab32f78fdbf98c44c26b6', + 'pretty_version' => 'v6.4.2', + 'version' => '6.4.2.0', + 'reference' => '0254811a143e6bc6c8deea08b589a7e68a37f625', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/console', 'aliases' => array(), @@ -420,9 +420,9 @@ 'dev_requirement' => true, ), 'symfony/dependency-injection' => array( - 'pretty_version' => 'v6.4.0', - 'version' => '6.4.0.0', - 'reference' => '5dc8ad5f2bbba7046f5947682bf7d868ce80d4e8', + 'pretty_version' => 'v6.4.2', + 'version' => '6.4.2.0', + 'reference' => '226ea431b1eda6f0d9f5a4b278757171960bb195', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/dependency-injection', 'aliases' => array(), @@ -438,9 +438,9 @@ 'dev_requirement' => false, ), 'symfony/dotenv' => array( - 'pretty_version' => 'v6.4.0', - 'version' => '6.4.0.0', - 'reference' => 'd0d584a91422ddaa2c94317200d4c4e5b935555f', + 'pretty_version' => 'v6.4.2', + 'version' => '6.4.2.0', + 'reference' => '835f8d2d1022934ac038519de40b88158798c96f', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/dotenv', 'aliases' => array(), @@ -456,9 +456,9 @@ 'dev_requirement' => false, ), 'symfony/event-dispatcher' => array( - 'pretty_version' => 'v6.4.0', - 'version' => '6.4.0.0', - 'reference' => 'd76d2632cfc2206eecb5ad2b26cd5934082941b6', + 'pretty_version' => 'v6.4.2', + 'version' => '6.4.2.0', + 'reference' => 'e95216850555cd55e71b857eb9d6c2674124603a', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/event-dispatcher', 'aliases' => array(), @@ -498,27 +498,27 @@ 'dev_requirement' => false, ), 'symfony/framework-bundle' => array( - 'pretty_version' => 'v6.4.0', - 'version' => '6.4.0.0', - 'reference' => '981e016715b4a7f22f58c1d9fdf444311965d25e', + 'pretty_version' => 'v6.4.2', + 'version' => '6.4.2.0', + 'reference' => 'c26a221e0462027d1f9d4a802ed63f8ab07a43d0', 'type' => 'symfony-bundle', 'install_path' => __DIR__ . '/../symfony/framework-bundle', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/http-foundation' => array( - 'pretty_version' => 'v6.4.0', - 'version' => '6.4.0.0', - 'reference' => '44a6d39a9cc11e154547d882d5aac1e014440771', + 'pretty_version' => 'v6.4.2', + 'version' => '6.4.2.0', + 'reference' => '172d807f9ef3fc3fbed8377cc57c20d389269271', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/http-foundation', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/http-kernel' => array( - 'pretty_version' => 'v6.4.0', - 'version' => '6.4.0.0', - 'reference' => '16a29c453966f29466ad34444ce97970a336f3c8', + 'pretty_version' => 'v6.4.2', + 'version' => '6.4.2.0', + 'reference' => '13e8387320b5942d0dc408440c888e2d526efef4', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/http-kernel', 'aliases' => array(), @@ -597,9 +597,9 @@ 'dev_requirement' => false, ), 'symfony/routing' => array( - 'pretty_version' => 'v6.4.0', - 'version' => '6.4.0.0', - 'reference' => 'ae014d60d7c8e80be5c3b644a286e91249a3e8f4', + 'pretty_version' => 'v6.4.2', + 'version' => '6.4.2.0', + 'reference' => '98eab13a07fddc85766f1756129c69f207ffbc21', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/routing', 'aliases' => array(), @@ -615,9 +615,9 @@ 'dev_requirement' => false, ), 'symfony/service-contracts' => array( - 'pretty_version' => 'v2.5.2', - 'version' => '2.5.2.0', - 'reference' => '4b426aac47d6427cc1a1d0f7e2ac724627f5966c', + 'pretty_version' => 'v3.4.1', + 'version' => '3.4.1.0', + 'reference' => 'fe07cbc8d837f60caf7018068e350cc5163681a0', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/service-contracts', 'aliases' => array(), @@ -639,9 +639,9 @@ 'dev_requirement' => true, ), 'symfony/string' => array( - 'pretty_version' => 'v6.4.0', - 'version' => '6.4.0.0', - 'reference' => 'b45fcf399ea9c3af543a92edf7172ba21174d809', + 'pretty_version' => 'v6.4.2', + 'version' => '6.4.2.0', + 'reference' => '7cb80bc10bfcdf6b5492741c0b9357dac66940bc', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/string', 'aliases' => array(), @@ -675,27 +675,27 @@ 'dev_requirement' => false, ), 'symfony/var-dumper' => array( - 'pretty_version' => 'v6.4.0', - 'version' => '6.4.0.0', - 'reference' => 'c40f7d17e91d8b407582ed51a2bbf83c52c367f6', + 'pretty_version' => 'v6.4.2', + 'version' => '6.4.2.0', + 'reference' => '68d6573ec98715ddcae5a0a85bee3c1c27a4c33f', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/var-dumper', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/var-exporter' => array( - 'pretty_version' => 'v6.4.0', - 'version' => '6.4.0.0', - 'reference' => 'd6081c0316f0f5921f2010d1766925005a82ea3b', + 'pretty_version' => 'v6.4.2', + 'version' => '6.4.2.0', + 'reference' => '5fe9a0021b8d35e67d914716ec8de50716a68e7e', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/var-exporter', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/web-profiler-bundle' => array( - 'pretty_version' => 'v6.4.0', - 'version' => '6.4.0.0', - 'reference' => '14752d3fb77c3c69b6cee7c03c06e2d6494a196b', + 'pretty_version' => 'v6.4.2', + 'version' => '6.4.2.0', + 'reference' => '38462d16856740ec0d1ba2cb902eebf09100dde2', 'type' => 'symfony-bundle', 'install_path' => __DIR__ . '/../symfony/web-profiler-bundle', 'aliases' => array(), @@ -726,9 +726,9 @@ 'dev_requirement' => false, ), 'twig/twig' => array( - 'pretty_version' => 'v3.4.3', - 'version' => '3.4.3.0', - 'reference' => 'c38fd6b0b7f370c198db91ffd02e23b517426b58', + 'pretty_version' => 'v3.8.0', + 'version' => '3.8.0.0', + 'reference' => '9d15f0ac07f44dc4217883ec6ae02fd555c6f71d', 'type' => 'library', 'install_path' => __DIR__ . '/../twig/twig', 'aliases' => array(), diff --git a/lib/symfony/cache/Adapter/CouchbaseCollectionAdapter.php b/lib/symfony/cache/Adapter/CouchbaseCollectionAdapter.php index aaa8bbdae..b5bb603e3 100644 --- a/lib/symfony/cache/Adapter/CouchbaseCollectionAdapter.php +++ b/lib/symfony/cache/Adapter/CouchbaseCollectionAdapter.php @@ -35,7 +35,7 @@ class CouchbaseCollectionAdapter extends AbstractAdapter public function __construct(Collection $connection, string $namespace = '', int $defaultLifetime = 0, MarshallerInterface $marshaller = null) { if (!static::isSupported()) { - throw new CacheException('Couchbase >= 3.0.0 < 4.0.0 is required.'); + throw new CacheException('Couchbase >= 3.0.5 < 4.0.0 is required.'); } $this->maxIdLength = static::MAX_KEY_LENGTH; @@ -54,7 +54,7 @@ class CouchbaseCollectionAdapter extends AbstractAdapter } if (!static::isSupported()) { - throw new CacheException('Couchbase >= 3.0.0 < 4.0.0 is required.'); + throw new CacheException('Couchbase >= 3.0.5 < 4.0.0 is required.'); } set_error_handler(static fn ($type, $msg, $file, $line) => throw new \ErrorException($msg, 0, $type, $file, $line)); @@ -183,7 +183,7 @@ class CouchbaseCollectionAdapter extends AbstractAdapter } $upsertOptions = new UpsertOptions(); - $upsertOptions->expiry($lifetime); + $upsertOptions->expiry(\DateTimeImmutable::createFromFormat('U', time() + $lifetime)); $ko = []; foreach ($values as $key => $value) { diff --git a/lib/symfony/console/Output/StreamOutput.php b/lib/symfony/console/Output/StreamOutput.php index da5eefb6f..08005c292 100644 --- a/lib/symfony/console/Output/StreamOutput.php +++ b/lib/symfony/console/Output/StreamOutput.php @@ -97,18 +97,17 @@ class StreamOutput extends Output return false; } - if ('Hyper' === getenv('TERM_PROGRAM')) { + if (\DIRECTORY_SEPARATOR === '\\' + && \function_exists('sapi_windows_vt100_support') + && @sapi_windows_vt100_support($this->stream) + ) { return true; } - if (\DIRECTORY_SEPARATOR === '\\') { - return (\function_exists('sapi_windows_vt100_support') - && @sapi_windows_vt100_support($this->stream)) - || false !== getenv('ANSICON') - || 'ON' === getenv('ConEmuANSI') - || 'xterm' === getenv('TERM'); - } - - return stream_isatty($this->stream); + return 'Hyper' === getenv('TERM_PROGRAM') + || false !== getenv('ANSICON') + || 'ON' === getenv('ConEmuANSI') + || str_starts_with((string) getenv('TERM'), 'xterm') + || stream_isatty($this->stream); } } diff --git a/lib/symfony/console/README.md b/lib/symfony/console/README.md index 92f70e714..e9013182a 100644 --- a/lib/symfony/console/README.md +++ b/lib/symfony/console/README.md @@ -7,7 +7,14 @@ interfaces. Sponsor ------- -Help Symfony by [sponsoring][1] its development! +The Console component for Symfony 6.4 is [backed][1] by [Les-Tilleuls.coop][2]. + +Les-Tilleuls.coop is a team of 70+ Symfony experts who can help you design, develop and +fix your projects. They provide a wide range of professional services including development, +consulting, coaching, training and audits. They also are highly skilled in JS, Go and DevOps. +They are a worker cooperative! + +Help Symfony by [sponsoring][3] its development! Resources --------- @@ -24,4 +31,6 @@ Credits `Resources/bin/hiddeninput.exe` is a third party binary provided within this component. Find sources and license at https://github.com/Seldaek/hidden-input. -[1]: https://symfony.com/sponsor +[1]: https://symfony.com/backers +[2]: https://les-tilleuls.coop +[3]: https://symfony.com/sponsor diff --git a/lib/symfony/dependency-injection/Attribute/Target.php b/lib/symfony/dependency-injection/Attribute/Target.php index c3f22127b..6fbb3ad42 100644 --- a/lib/symfony/dependency-injection/Attribute/Target.php +++ b/lib/symfony/dependency-injection/Attribute/Target.php @@ -36,10 +36,12 @@ final class Target return lcfirst(str_replace(' ', '', ucwords(preg_replace('/[^a-zA-Z0-9\x7f-\xff]++/', ' ', $this->name)))); } - public static function parseName(\ReflectionParameter $parameter, self &$attribute = null): string + public static function parseName(\ReflectionParameter $parameter, self &$attribute = null, string &$parsedName = null): string { $attribute = null; if (!$target = $parameter->getAttributes(self::class)[0] ?? null) { + $parsedName = (new self($parameter->name))->getParsedName(); + return $parameter->name; } @@ -57,6 +59,6 @@ final class Target throw new InvalidArgumentException(sprintf('Invalid #[Target] name "%s" on parameter "$%s" of "%s()": the first character must be a letter.', $name, $parameter->name, $function)); } - return $parsedName; + return preg_match('/^[a-zA-Z0-9_\x7f-\xff]++$/', $name) ? $name : $parsedName; } } diff --git a/lib/symfony/dependency-injection/Compiler/AutowirePass.php b/lib/symfony/dependency-injection/Compiler/AutowirePass.php index ee3ba948b..9786ec4de 100644 --- a/lib/symfony/dependency-injection/Compiler/AutowirePass.php +++ b/lib/symfony/dependency-injection/Compiler/AutowirePass.php @@ -454,20 +454,30 @@ class AutowirePass extends AbstractRecursivePass $name = $target = (array_filter($reference->getAttributes(), static fn ($a) => $a instanceof Target)[0] ?? null)?->name; if (null !== $name ??= $reference->getName()) { + if ($this->container->has($alias = $type.' $'.$name) && !$this->container->findDefinition($alias)->isAbstract()) { + return new TypedReference($alias, $type, $reference->getInvalidBehavior()); + } + + if (null !== ($alias = $this->getCombinedAlias($type, $name)) && !$this->container->findDefinition($alias)->isAbstract()) { + return new TypedReference($alias, $type, $reference->getInvalidBehavior()); + } + $parsedName = (new Target($name))->getParsedName(); if ($this->container->has($alias = $type.' $'.$parsedName) && !$this->container->findDefinition($alias)->isAbstract()) { return new TypedReference($alias, $type, $reference->getInvalidBehavior()); } - if (null !== ($alias = $this->getCombinedAlias($type, $parsedName) ?? null) && !$this->container->findDefinition($alias)->isAbstract()) { + if (null !== ($alias = $this->getCombinedAlias($type, $parsedName)) && !$this->container->findDefinition($alias)->isAbstract()) { return new TypedReference($alias, $type, $reference->getInvalidBehavior()); } - if ($this->container->has($name) && !$this->container->findDefinition($name)->isAbstract()) { + if (($this->container->has($n = $name) && !$this->container->findDefinition($n)->isAbstract()) + || ($this->container->has($n = $parsedName) && !$this->container->findDefinition($n)->isAbstract()) + ) { foreach ($this->container->getAliases() as $id => $alias) { - if ($name === (string) $alias && str_starts_with($id, $type.' $')) { - return new TypedReference($name, $type, $reference->getInvalidBehavior()); + if ($n === (string) $alias && str_starts_with($id, $type.' $')) { + return new TypedReference($n, $type, $reference->getInvalidBehavior()); } } } @@ -481,7 +491,7 @@ class AutowirePass extends AbstractRecursivePass return new TypedReference($type, $type, $reference->getInvalidBehavior()); } - if (null !== ($alias = $this->getCombinedAlias($type) ?? null) && !$this->container->findDefinition($alias)->isAbstract()) { + if (null !== ($alias = $this->getCombinedAlias($type)) && !$this->container->findDefinition($alias)->isAbstract()) { return new TypedReference($alias, $type, $reference->getInvalidBehavior()); } diff --git a/lib/symfony/dependency-injection/Compiler/ResolveBindingsPass.php b/lib/symfony/dependency-injection/Compiler/ResolveBindingsPass.php index 68835d52a..2fa7db848 100644 --- a/lib/symfony/dependency-injection/Compiler/ResolveBindingsPass.php +++ b/lib/symfony/dependency-injection/Compiler/ResolveBindingsPass.php @@ -190,16 +190,19 @@ class ResolveBindingsPass extends AbstractRecursivePass $typeHint = ltrim(ProxyHelper::exportType($parameter) ?? '', '?'); - $name = Target::parseName($parameter); + $name = Target::parseName($parameter, parsedName: $parsedName); - if ($typeHint && \array_key_exists($k = preg_replace('/(^|[(|&])\\\\/', '\1', $typeHint).' $'.$name, $bindings)) { + if ($typeHint && ( + \array_key_exists($k = preg_replace('/(^|[(|&])\\\\/', '\1', $typeHint).' $'.$name, $bindings) + || \array_key_exists($k = preg_replace('/(^|[(|&])\\\\/', '\1', $typeHint).' $'.$parsedName, $bindings) + )) { $arguments[$key] = $this->getBindingValue($bindings[$k]); continue; } - if (\array_key_exists('$'.$name, $bindings)) { - $arguments[$key] = $this->getBindingValue($bindings['$'.$name]); + if (\array_key_exists($k = '$'.$name, $bindings) || \array_key_exists($k = '$'.$parsedName, $bindings)) { + $arguments[$key] = $this->getBindingValue($bindings[$k]); continue; } @@ -210,7 +213,7 @@ class ResolveBindingsPass extends AbstractRecursivePass continue; } - if (isset($bindingNames[$name]) || isset($bindingNames[$parameter->name])) { + if (isset($bindingNames[$name]) || isset($bindingNames[$parsedName]) || isset($bindingNames[$parameter->name])) { $bindingKey = array_search($binding, $bindings, true); $argumentType = substr($bindingKey, 0, strpos($bindingKey, ' ')); $this->errorMessages[] = sprintf('Did you forget to add the type "%s" to argument "$%s" of method "%s::%s()"?', $argumentType, $parameter->name, $reflectionMethod->class, $reflectionMethod->name); diff --git a/lib/symfony/dependency-injection/Dumper/PhpDumper.php b/lib/symfony/dependency-injection/Dumper/PhpDumper.php index ff11062b9..65985fd9c 100644 --- a/lib/symfony/dependency-injection/Dumper/PhpDumper.php +++ b/lib/symfony/dependency-injection/Dumper/PhpDumper.php @@ -258,6 +258,7 @@ class PhpDumper extends Dumper docStar} diff --git a/lib/symfony/dependency-injection/EnvVarProcessorInterface.php b/lib/symfony/dependency-injection/EnvVarProcessorInterface.php index fecd47407..3cda63934 100644 --- a/lib/symfony/dependency-injection/EnvVarProcessorInterface.php +++ b/lib/symfony/dependency-injection/EnvVarProcessorInterface.php @@ -23,7 +23,6 @@ interface EnvVarProcessorInterface /** * Returns the value of the given variable as managed by the current instance. * - * @param string $prefix The namespace of the variable * @param string $prefix The namespace of the variable; when the empty string is passed, null values should be kept as is * @param string $name The name of the variable within the namespace * @param \Closure(string): mixed $getEnv A closure that allows fetching more env vars diff --git a/lib/symfony/dotenv/Command/DebugCommand.php b/lib/symfony/dotenv/Command/DebugCommand.php index e60c83fae..0da80245e 100644 --- a/lib/symfony/dotenv/Command/DebugCommand.php +++ b/lib/symfony/dotenv/Command/DebugCommand.php @@ -151,7 +151,13 @@ EOT private function getAvailableVars(): array { - $vars = explode(',', $_SERVER['SYMFONY_DOTENV_VARS'] ?? ''); + $dotenvVars = $_SERVER['SYMFONY_DOTENV_VARS'] ?? ''; + + if ('' === $dotenvVars) { + return []; + } + + $vars = explode(',', $dotenvVars); sort($vars); return $vars; diff --git a/lib/symfony/dotenv/Dotenv.php b/lib/symfony/dotenv/Dotenv.php index 6e693ac28..9b905f31c 100644 --- a/lib/symfony/dotenv/Dotenv.php +++ b/lib/symfony/dotenv/Dotenv.php @@ -25,7 +25,7 @@ use Symfony\Component\Process\Process; */ final class Dotenv { - public const VARNAME_REGEX = '(?i:[A-Z][A-Z0-9_]*+)'; + public const VARNAME_REGEX = '(?i:_?[A-Z][A-Z0-9_]*+)'; public const STATE_VARNAME = 0; public const STATE_VALUE = 1; @@ -341,8 +341,8 @@ final class Dotenv ++$this->cursor; $value = str_replace(['\\"', '\r', '\n'], ['"', "\r", "\n"], $value); $resolvedValue = $value; - $resolvedValue = $this->resolveVariables($resolvedValue, $loadedVars); $resolvedValue = $this->resolveCommands($resolvedValue, $loadedVars); + $resolvedValue = $this->resolveVariables($resolvedValue, $loadedVars); $resolvedValue = str_replace('\\\\', '\\', $resolvedValue); $v .= $resolvedValue; } else { @@ -364,8 +364,8 @@ final class Dotenv } $value = rtrim($value); $resolvedValue = $value; - $resolvedValue = $this->resolveVariables($resolvedValue, $loadedVars); $resolvedValue = $this->resolveCommands($resolvedValue, $loadedVars); + $resolvedValue = $this->resolveVariables($resolvedValue, $loadedVars); $resolvedValue = str_replace('\\\\', '\\', $resolvedValue); if ($resolvedValue === $value && preg_match('/\s+/', $value)) { diff --git a/lib/symfony/event-dispatcher/GenericEvent.php b/lib/symfony/event-dispatcher/GenericEvent.php index 68a203063..0ccbbd810 100644 --- a/lib/symfony/event-dispatcher/GenericEvent.php +++ b/lib/symfony/event-dispatcher/GenericEvent.php @@ -29,7 +29,7 @@ class GenericEvent extends Event implements \ArrayAccess, \IteratorAggregate protected $arguments; /** - * Encapsulate an event with $subject and $args. + * Encapsulate an event with $subject and $arguments. * * @param mixed $subject The subject of the event, usually an object or a callable * @param array $arguments Arguments to store in the event diff --git a/lib/symfony/framework-bundle/Console/Application.php b/lib/symfony/framework-bundle/Console/Application.php index b8bae8fc2..38dd8405a 100644 --- a/lib/symfony/framework-bundle/Console/Application.php +++ b/lib/symfony/framework-bundle/Console/Application.php @@ -166,7 +166,7 @@ class Application extends BaseApplication public function getLongVersion(): string { - return parent::getLongVersion().sprintf(' (env: %s, debug: %s) #StandWithUkraine https://sf.to/ukraine', $this->kernel->getEnvironment(), $this->kernel->isDebug() ? 'true' : 'false'); + return parent::getLongVersion().sprintf(' (env: %s, debug: %s)', $this->kernel->getEnvironment(), $this->kernel->isDebug() ? 'true' : 'false'); } public function add(Command $command): ?Command diff --git a/lib/symfony/framework-bundle/Controller/AbstractController.php b/lib/symfony/framework-bundle/Controller/AbstractController.php index 9bcc34606..4ede883f7 100644 --- a/lib/symfony/framework-bundle/Controller/AbstractController.php +++ b/lib/symfony/framework-bundle/Controller/AbstractController.php @@ -111,7 +111,7 @@ abstract class AbstractController implements ServiceSubscriberInterface /** * Forwards the request to another controller. * - * @param string $controller The controller name (a string like Bundle\BlogBundle\Controller\PostController::indexAction) + * @param string $controller The controller name (a string like "App\Controller\PostController::index" or "App\Controller\PostController" if it is invokable) */ protected function forward(string $controller, array $path = [], array $query = []): Response { diff --git a/lib/symfony/framework-bundle/DependencyInjection/FrameworkExtension.php b/lib/symfony/framework-bundle/DependencyInjection/FrameworkExtension.php index 8a42bfb29..32026a84d 100644 --- a/lib/symfony/framework-bundle/DependencyInjection/FrameworkExtension.php +++ b/lib/symfony/framework-bundle/DependencyInjection/FrameworkExtension.php @@ -1938,7 +1938,7 @@ class FrameworkExtension extends Extension $container->removeDefinition('serializer.mapping.cache_class_metadata_factory'); } - if (!class_exists(Translator::class)) { + if (!$this->readConfigEnabled('translator', $container, $config)) { $container->removeDefinition('serializer.normalizer.translatable'); } @@ -1990,21 +1990,23 @@ class FrameworkExtension extends Extension $container->getDefinition('serializer.name_converter.metadata_aware')->setArgument(1, new Reference($config['name_converter'])); } + $defaultContext = $config['default_context'] ?? []; + + if ($defaultContext) { + $container->setParameter('serializer.default_context', $defaultContext); + } + if (isset($config['circular_reference_handler']) && $config['circular_reference_handler']) { $arguments = $container->getDefinition('serializer.normalizer.object')->getArguments(); - $context = ($arguments[6] ?? []) + ['circular_reference_handler' => new Reference($config['circular_reference_handler'])]; + $context = ($arguments[6] ?? $defaultContext) + ['circular_reference_handler' => new Reference($config['circular_reference_handler'])]; $container->getDefinition('serializer.normalizer.object')->setArgument(5, null); $container->getDefinition('serializer.normalizer.object')->setArgument(6, $context); } if ($config['max_depth_handler'] ?? false) { - $defaultContext = $container->getDefinition('serializer.normalizer.object')->getArgument(6); - $defaultContext += ['max_depth_handler' => new Reference($config['max_depth_handler'])]; - $container->getDefinition('serializer.normalizer.object')->replaceArgument(6, $defaultContext); - } - - if (isset($config['default_context']) && $config['default_context']) { - $container->setParameter('serializer.default_context', $config['default_context']); + $arguments = $container->getDefinition('serializer.normalizer.object')->getArguments(); + $context = ($arguments[6] ?? $defaultContext) + ['max_depth_handler' => new Reference($config['max_depth_handler'])]; + $container->getDefinition('serializer.normalizer.object')->setArgument(6, $context); } } @@ -2678,13 +2680,15 @@ class FrameworkExtension extends Extension if ($webhookEnabled) { $webhookRequestParsers = [ + MailerBridge\Brevo\Webhook\BrevoRequestParser::class => 'mailer.webhook.request_parser.brevo', MailerBridge\Mailgun\Webhook\MailgunRequestParser::class => 'mailer.webhook.request_parser.mailgun', + MailerBridge\Mailjet\Webhook\MailjetRequestParser::class => 'mailer.webhook.request_parser.mailjet', MailerBridge\Postmark\Webhook\PostmarkRequestParser::class => 'mailer.webhook.request_parser.postmark', MailerBridge\Sendgrid\Webhook\SendgridRequestParser::class => 'mailer.webhook.request_parser.sendgrid', ]; foreach ($webhookRequestParsers as $class => $service) { - $package = substr($service, \strlen('mailer.transport_factory.')); + $package = substr($service, \strlen('mailer.webhook.request_parser.')); if (!ContainerBuilder::willBeAvailable(sprintf('symfony/%s-mailer', 'gmail' === $package ? 'google' : $package), $class, ['symfony/framework-bundle', 'symfony/mailer'])) { $container->removeDefinition($service); @@ -2868,7 +2872,9 @@ class FrameworkExtension extends Extension if (ContainerBuilder::willBeAvailable('symfony/mercure-notifier', NotifierBridge\Mercure\MercureTransportFactory::class, $parentPackages) && ContainerBuilder::willBeAvailable('symfony/mercure-bundle', MercureBundle::class, $parentPackages) && \in_array(MercureBundle::class, $container->getParameter('kernel.bundles'), true)) { $container->getDefinition($classToServices[NotifierBridge\Mercure\MercureTransportFactory::class]) - ->replaceArgument('$registry', new Reference(HubRegistry::class)); + ->replaceArgument('$registry', new Reference(HubRegistry::class)) + ->replaceArgument('$client', new Reference('http_client', ContainerBuilder::NULL_ON_INVALID_REFERENCE)) + ->replaceArgument('$dispatcher', new Reference('event_dispatcher', ContainerBuilder::NULL_ON_INVALID_REFERENCE)); } elseif (ContainerBuilder::willBeAvailable('symfony/mercure-notifier', NotifierBridge\Mercure\MercureTransportFactory::class, $parentPackages)) { $container->removeDefinition($classToServices[NotifierBridge\Mercure\MercureTransportFactory::class]); } @@ -2876,13 +2882,17 @@ class FrameworkExtension extends Extension if (ContainerBuilder::willBeAvailable('symfony/fake-chat-notifier', NotifierBridge\FakeChat\FakeChatTransportFactory::class, ['symfony/framework-bundle', 'symfony/notifier', 'symfony/mailer'])) { $container->getDefinition($classToServices[NotifierBridge\FakeChat\FakeChatTransportFactory::class]) ->replaceArgument('$mailer', new Reference('mailer')) - ->replaceArgument('$logger', new Reference('logger')); + ->replaceArgument('$logger', new Reference('logger')) + ->replaceArgument('$client', new Reference('http_client', ContainerBuilder::NULL_ON_INVALID_REFERENCE)) + ->replaceArgument('$dispatcher', new Reference('event_dispatcher', ContainerBuilder::NULL_ON_INVALID_REFERENCE)); } if (ContainerBuilder::willBeAvailable('symfony/fake-sms-notifier', NotifierBridge\FakeSms\FakeSmsTransportFactory::class, ['symfony/framework-bundle', 'symfony/notifier', 'symfony/mailer'])) { $container->getDefinition($classToServices[NotifierBridge\FakeSms\FakeSmsTransportFactory::class]) ->replaceArgument('$mailer', new Reference('mailer')) - ->replaceArgument('$logger', new Reference('logger')); + ->replaceArgument('$logger', new Reference('logger')) + ->replaceArgument('$client', new Reference('http_client', ContainerBuilder::NULL_ON_INVALID_REFERENCE)) + ->replaceArgument('$dispatcher', new Reference('event_dispatcher', ContainerBuilder::NULL_ON_INVALID_REFERENCE)); } if (isset($config['admin_recipients'])) { @@ -2896,6 +2906,19 @@ class FrameworkExtension extends Extension if ($webhookEnabled) { $loader->load('notifier_webhook.php'); + + $webhookRequestParsers = [ + NotifierBridge\Twilio\Webhook\TwilioRequestParser::class => 'notifier.webhook.request_parser.twilio', + NotifierBridge\Vonage\Webhook\VonageRequestParser::class => 'notifier.webhook.request_parser.vonage', + ]; + + foreach ($webhookRequestParsers as $class => $service) { + $package = substr($service, \strlen('notifier.webhook.request_parser.')); + + if (!ContainerBuilder::willBeAvailable(sprintf('symfony/%s-notifier', $package), $class, ['symfony/framework-bundle', 'symfony/notifier'])) { + $container->removeDefinition($service); + } + } } } diff --git a/lib/symfony/framework-bundle/EventListener/ConsoleProfilerListener.php b/lib/symfony/framework-bundle/EventListener/ConsoleProfilerListener.php index d3fc38106..c2a71d0a7 100644 --- a/lib/symfony/framework-bundle/EventListener/ConsoleProfilerListener.php +++ b/lib/symfony/framework-bundle/EventListener/ConsoleProfilerListener.php @@ -42,7 +42,8 @@ final class ConsoleProfilerListener implements EventSubscriberInterface private readonly Profiler $profiler, private readonly RequestStack $requestStack, private readonly Stopwatch $stopwatch, - private readonly UrlGeneratorInterface $urlGenerator, + private readonly bool $cliMode, + private readonly ?UrlGeneratorInterface $urlGenerator = null, ) { $this->profiles = new \SplObjectStorage(); $this->parents = new \SplObjectStorage(); @@ -59,6 +60,10 @@ final class ConsoleProfilerListener implements EventSubscriberInterface public function initialize(ConsoleCommandEvent $event): void { + if (!$this->cliMode) { + return; + } + $input = $event->getInput(); if (!$input->hasOption('profile') || !$input->getOption('profile')) { $this->profiler->disable(); @@ -78,12 +83,16 @@ final class ConsoleProfilerListener implements EventSubscriberInterface public function catch(ConsoleErrorEvent $event): void { + if (!$this->cliMode) { + return; + } + $this->error = $event->getError(); } public function profile(ConsoleTerminateEvent $event): void { - if (!$this->profiler->isEnabled()) { + if (!$this->cliMode || !$this->profiler->isEnabled()) { return; } @@ -131,12 +140,14 @@ final class ConsoleProfilerListener implements EventSubscriberInterface $p = $this->profiles[$r]; $this->profiler->saveProfile($p); - $token = $p->getToken(); - $output?->writeln(sprintf( - 'See profile %s', - $this->urlGenerator->generate('_profiler', ['token' => $token], UrlGeneratorInterface::ABSOLUTE_URL), - $token - )); + if ($this->urlGenerator && $output) { + $token = $p->getToken(); + $output->writeln(sprintf( + 'See profile %s', + $this->urlGenerator->generate('_profiler', ['token' => $token], UrlGeneratorInterface::ABSOLUTE_URL), + $token + )); + } } $this->profiles = new \SplObjectStorage(); diff --git a/lib/symfony/framework-bundle/Resources/config/mailer_webhook.php b/lib/symfony/framework-bundle/Resources/config/mailer_webhook.php index 30ea50dad..bb487b36c 100644 --- a/lib/symfony/framework-bundle/Resources/config/mailer_webhook.php +++ b/lib/symfony/framework-bundle/Resources/config/mailer_webhook.php @@ -11,8 +11,12 @@ namespace Symfony\Component\DependencyInjection\Loader\Configurator; +use Symfony\Component\Mailer\Bridge\Brevo\RemoteEvent\BrevoPayloadConverter; +use Symfony\Component\Mailer\Bridge\Brevo\Webhook\BrevoRequestParser; use Symfony\Component\Mailer\Bridge\Mailgun\RemoteEvent\MailgunPayloadConverter; use Symfony\Component\Mailer\Bridge\Mailgun\Webhook\MailgunRequestParser; +use Symfony\Component\Mailer\Bridge\Mailjet\RemoteEvent\MailjetPayloadConverter; +use Symfony\Component\Mailer\Bridge\Mailjet\Webhook\MailjetRequestParser; use Symfony\Component\Mailer\Bridge\Postmark\RemoteEvent\PostmarkPayloadConverter; use Symfony\Component\Mailer\Bridge\Postmark\Webhook\PostmarkRequestParser; use Symfony\Component\Mailer\Bridge\Sendgrid\RemoteEvent\SendgridPayloadConverter; @@ -20,11 +24,21 @@ use Symfony\Component\Mailer\Bridge\Sendgrid\Webhook\SendgridRequestParser; return static function (ContainerConfigurator $container) { $container->services() + ->set('mailer.payload_converter.brevo', BrevoPayloadConverter::class) + ->set('mailer.webhook.request_parser.brevo', BrevoRequestParser::class) + ->args([service('mailer.payload_converter.brevo')]) + ->alias(BrevoRequestParser::class, 'mailer.webhook.request_parser.brevo') + ->set('mailer.payload_converter.mailgun', MailgunPayloadConverter::class) ->set('mailer.webhook.request_parser.mailgun', MailgunRequestParser::class) ->args([service('mailer.payload_converter.mailgun')]) ->alias(MailgunRequestParser::class, 'mailer.webhook.request_parser.mailgun') + ->set('mailer.payload_converter.mailjet', MailjetPayloadConverter::class) + ->set('mailer.webhook.request_parser.mailjet', MailjetRequestParser::class) + ->args([service('mailer.payload_converter.mailjet')]) + ->alias(MailjetRequestParser::class, 'mailer.webhook.request_parser.mailjet') + ->set('mailer.payload_converter.postmark', PostmarkPayloadConverter::class) ->set('mailer.webhook.request_parser.postmark', PostmarkRequestParser::class) ->args([service('mailer.payload_converter.postmark')]) diff --git a/lib/symfony/framework-bundle/Resources/config/notifier_webhook.php b/lib/symfony/framework-bundle/Resources/config/notifier_webhook.php index 87dfc6c6a..fc541fd99 100644 --- a/lib/symfony/framework-bundle/Resources/config/notifier_webhook.php +++ b/lib/symfony/framework-bundle/Resources/config/notifier_webhook.php @@ -12,10 +12,14 @@ namespace Symfony\Component\DependencyInjection\Loader\Configurator; use Symfony\Component\Notifier\Bridge\Twilio\Webhook\TwilioRequestParser; +use Symfony\Component\Notifier\Bridge\Vonage\Webhook\VonageRequestParser; return static function (ContainerConfigurator $container) { $container->services() ->set('notifier.webhook.request_parser.twilio', TwilioRequestParser::class) ->alias(TwilioRequestParser::class, 'notifier.webhook.request_parser.twilio') + + ->set('notifier.webhook.request_parser.vonage', VonageRequestParser::class) + ->alias(VonageRequestParser::class, 'notifier.webhook.request_parser.vonage') ; }; diff --git a/lib/symfony/framework-bundle/Resources/config/profiling.php b/lib/symfony/framework-bundle/Resources/config/profiling.php index ec764d837..eaef79597 100644 --- a/lib/symfony/framework-bundle/Resources/config/profiling.php +++ b/lib/symfony/framework-bundle/Resources/config/profiling.php @@ -43,7 +43,8 @@ return static function (ContainerConfigurator $container) { service('profiler'), service('.virtual_request_stack'), service('debug.stopwatch'), - service('router'), + param('kernel.runtime_mode.cli'), + service('router')->nullOnInvalid(), ]) ->tag('kernel.event_subscriber') diff --git a/lib/symfony/framework-bundle/Resources/config/schema/symfony-1.0.xsd b/lib/symfony/framework-bundle/Resources/config/schema/symfony-1.0.xsd index 6483732ef..ffa47c384 100644 --- a/lib/symfony/framework-bundle/Resources/config/schema/symfony-1.0.xsd +++ b/lib/symfony/framework-bundle/Resources/config/schema/symfony-1.0.xsd @@ -979,6 +979,7 @@ + diff --git a/lib/symfony/framework-bundle/Routing/AnnotatedRouteControllerLoader.php b/lib/symfony/framework-bundle/Routing/AnnotatedRouteControllerLoader.php index 9fb17d8d7..e9cf9b95c 100644 --- a/lib/symfony/framework-bundle/Routing/AnnotatedRouteControllerLoader.php +++ b/lib/symfony/framework-bundle/Routing/AnnotatedRouteControllerLoader.php @@ -19,7 +19,7 @@ if (false) { /** * @deprecated since Symfony 6.4, to be removed in 7.0, use {@link AttributeRouteControllerLoader} instead */ - class AnnotatedRouteControllerLoader + class AnnotatedRouteControllerLoader extends AttributeRouteControllerLoader { } } diff --git a/lib/symfony/framework-bundle/composer.json b/lib/symfony/framework-bundle/composer.json index e63a672e8..3aedebd74 100644 --- a/lib/symfony/framework-bundle/composer.json +++ b/lib/symfony/framework-bundle/composer.json @@ -82,7 +82,7 @@ "symfony/asset": "<5.4", "symfony/asset-mapper": "<6.4", "symfony/clock": "<6.3", - "symfony/console": "<5.4", + "symfony/console": "<5.4|>=7.0", "symfony/dotenv": "<5.4", "symfony/dom-crawler": "<6.4", "symfony/http-client": "<6.3", diff --git a/lib/symfony/http-foundation/RequestMatcher.php b/lib/symfony/http-foundation/RequestMatcher.php index 8c5f1d813..ac155fa30 100644 --- a/lib/symfony/http-foundation/RequestMatcher.php +++ b/lib/symfony/http-foundation/RequestMatcher.php @@ -88,7 +88,7 @@ class RequestMatcher implements RequestMatcherInterface } /** - * Adds a check for the the URL port. + * Adds a check for the URL port. * * @param int|null $port The port number to connect to * diff --git a/lib/symfony/http-kernel/Controller/ArgumentResolver.php b/lib/symfony/http-kernel/Controller/ArgumentResolver.php index 3b0f89509..6643cc58e 100644 --- a/lib/symfony/http-kernel/Controller/ArgumentResolver.php +++ b/lib/symfony/http-kernel/Controller/ArgumentResolver.php @@ -73,6 +73,7 @@ final class ArgumentResolver implements ArgumentResolverInterface $argumentValueResolvers = [ $this->namedResolvers->get($resolverName), + new RequestAttributeValueResolver(), new DefaultValueResolver(), ]; } diff --git a/lib/symfony/http-kernel/Controller/ArgumentResolver/BackedEnumValueResolver.php b/lib/symfony/http-kernel/Controller/ArgumentResolver/BackedEnumValueResolver.php index 4f0ca76d3..620e2de08 100644 --- a/lib/symfony/http-kernel/Controller/ArgumentResolver/BackedEnumValueResolver.php +++ b/lib/symfony/http-kernel/Controller/ArgumentResolver/BackedEnumValueResolver.php @@ -86,7 +86,7 @@ class BackedEnumValueResolver implements ArgumentValueResolverInterface, ValueRe try { return [$enumType::from($value)]; - } catch (\ValueError $e) { + } catch (\ValueError|\TypeError $e) { throw new NotFoundHttpException(sprintf('Could not resolve the "%s $%s" controller argument: ', $argument->getType(), $argument->getName()).$e->getMessage(), $e); } } diff --git a/lib/symfony/http-kernel/Controller/ArgumentResolver/RequestPayloadValueResolver.php b/lib/symfony/http-kernel/Controller/ArgumentResolver/RequestPayloadValueResolver.php index f7f603076..444be1b3f 100644 --- a/lib/symfony/http-kernel/Controller/ArgumentResolver/RequestPayloadValueResolver.php +++ b/lib/symfony/http-kernel/Controller/ArgumentResolver/RequestPayloadValueResolver.php @@ -119,7 +119,7 @@ class RequestPayloadValueResolver implements ValueResolverInterface, EventSubscr $payload = $e->getData(); } - if (null !== $payload) { + if (null !== $payload && !\count($violations)) { $violations->addAll($this->validator->validate($payload, null, $argument->validationGroups ?? null)); } diff --git a/lib/symfony/http-kernel/Debug/FileLinkFormatter.php b/lib/symfony/http-kernel/Debug/FileLinkFormatter.php index 23ced22fc..600a460fb 100644 --- a/lib/symfony/http-kernel/Debug/FileLinkFormatter.php +++ b/lib/symfony/http-kernel/Debug/FileLinkFormatter.php @@ -25,7 +25,7 @@ if (false) { /** * @deprecated since Symfony 6.4, use FileLinkFormatter from the ErrorHandler component instead */ - class FileLinkFormatter + class FileLinkFormatter extends ErrorHandlerFileLinkFormatter { } } diff --git a/lib/symfony/http-kernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php b/lib/symfony/http-kernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php index d43c6a3ae..f2cf2422b 100644 --- a/lib/symfony/http-kernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php +++ b/lib/symfony/http-kernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php @@ -128,6 +128,8 @@ class RegisterControllerArgumentLocatorsPass implements CompilerPassInterface $type = preg_replace('/(^|[(|&])\\\\/', '\1', $target = ltrim(ProxyHelper::exportType($p) ?? '', '?')); $invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE; $autowireAttributes = $autowire ? $emptyAutowireAttributes : []; + $parsedName = $p->name; + $k = null; if (isset($arguments[$r->name][$p->name])) { $target = $arguments[$r->name][$p->name]; @@ -138,7 +140,11 @@ class RegisterControllerArgumentLocatorsPass implements CompilerPassInterface } elseif ($p->allowsNull() && !$p->isOptional()) { $invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE; } - } elseif (isset($bindings[$bindingName = $type.' $'.$name = Target::parseName($p)]) || isset($bindings[$bindingName = '$'.$name]) || isset($bindings[$bindingName = $type])) { + } elseif (isset($bindings[$bindingName = $type.' $'.$name = Target::parseName($p, $k, $parsedName)]) + || isset($bindings[$bindingName = $type.' $'.$parsedName]) + || isset($bindings[$bindingName = '$'.$name]) + || isset($bindings[$bindingName = $type]) + ) { $binding = $bindings[$bindingName]; [$bindingValue, $bindingId, , $bindingType, $bindingFile] = $binding->getValues(); diff --git a/lib/symfony/http-kernel/EventListener/AbstractSessionListener.php b/lib/symfony/http-kernel/EventListener/AbstractSessionListener.php index 2eb7c473f..2f012ab52 100644 --- a/lib/symfony/http-kernel/EventListener/AbstractSessionListener.php +++ b/lib/symfony/http-kernel/EventListener/AbstractSessionListener.php @@ -35,14 +35,16 @@ use Symfony\Contracts\Service\ResetInterface; * * @author Johannes M. Schmitt * @author Tobias Schultze - * - * @internal */ abstract class AbstractSessionListener implements EventSubscriberInterface, ResetInterface { public const NO_AUTO_CACHE_CONTROL_HEADER = 'Symfony-Session-NoAutoCacheControl'; + /** + * @internal + */ protected ?ContainerInterface $container; + private bool $debug; /** @@ -50,6 +52,9 @@ abstract class AbstractSessionListener implements EventSubscriberInterface, Rese */ private array $sessionOptions; + /** + * @internal + */ public function __construct(ContainerInterface $container = null, bool $debug = false, array $sessionOptions = []) { $this->container = $container; @@ -57,6 +62,9 @@ abstract class AbstractSessionListener implements EventSubscriberInterface, Rese $this->sessionOptions = $sessionOptions; } + /** + * @internal + */ public function onKernelRequest(RequestEvent $event): void { if (!$event->isMainRequest()) { @@ -90,6 +98,9 @@ abstract class AbstractSessionListener implements EventSubscriberInterface, Rese } } + /** + * @internal + */ public function onKernelResponse(ResponseEvent $event): void { if (!$event->isMainRequest() || (!$this->container->has('initialized_session') && !$event->getRequest()->hasSession())) { @@ -218,6 +229,9 @@ abstract class AbstractSessionListener implements EventSubscriberInterface, Rese } } + /** + * @internal + */ public function onSessionUsage(): void { if (!$this->debug) { @@ -253,6 +267,9 @@ abstract class AbstractSessionListener implements EventSubscriberInterface, Rese throw new UnexpectedSessionUsageException('Session was used while the request was declared stateless.'); } + /** + * @internal + */ public static function getSubscribedEvents(): array { return [ @@ -262,6 +279,9 @@ abstract class AbstractSessionListener implements EventSubscriberInterface, Rese ]; } + /** + * @internal + */ public function reset(): void { if (\PHP_SESSION_ACTIVE === session_status()) { @@ -278,6 +298,8 @@ abstract class AbstractSessionListener implements EventSubscriberInterface, Rese /** * Gets the session object. + * + * @internal */ abstract protected function getSession(): ?SessionInterface; diff --git a/lib/symfony/http-kernel/EventListener/LocaleListener.php b/lib/symfony/http-kernel/EventListener/LocaleListener.php index 4516048be..65a3bfde4 100644 --- a/lib/symfony/http-kernel/EventListener/LocaleListener.php +++ b/lib/symfony/http-kernel/EventListener/LocaleListener.php @@ -69,7 +69,7 @@ class LocaleListener implements EventSubscriberInterface if ($locale = $request->attributes->get('_locale')) { $request->setLocale($locale); } elseif ($this->useAcceptLanguageHeader) { - if ($preferredLanguage = $request->getPreferredLanguage($this->enabledLocales)) { + if ($request->getLanguages() && $preferredLanguage = $request->getPreferredLanguage($this->enabledLocales)) { $request->setLocale($preferredLanguage); } $request->attributes->set('_vary_by_language', true); diff --git a/lib/symfony/http-kernel/Kernel.php b/lib/symfony/http-kernel/Kernel.php index 39170e833..6247db901 100644 --- a/lib/symfony/http-kernel/Kernel.php +++ b/lib/symfony/http-kernel/Kernel.php @@ -76,11 +76,11 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl */ private static array $freshCache = []; - public const VERSION = '6.4.0'; - public const VERSION_ID = 60400; + public const VERSION = '6.4.2'; + public const VERSION_ID = 60402; public const MAJOR_VERSION = 6; public const MINOR_VERSION = 4; - public const RELEASE_VERSION = 0; + public const RELEASE_VERSION = 2; public const EXTRA_VERSION = ''; public const END_OF_MAINTENANCE = '11/2026'; diff --git a/lib/symfony/http-kernel/UriSigner.php b/lib/symfony/http-kernel/UriSigner.php index 877d832e9..fb5383cde 100644 --- a/lib/symfony/http-kernel/UriSigner.php +++ b/lib/symfony/http-kernel/UriSigner.php @@ -21,7 +21,7 @@ if (false) { /** * @deprecated since Symfony 6.4, to be removed in 7.0, use {@link HttpFoundationUriSigner} instead */ - class UriSigner + class UriSigner extends HttpFoundationUriSigner { } } diff --git a/lib/symfony/routing/Loader/AnnotationClassLoader.php b/lib/symfony/routing/Loader/AnnotationClassLoader.php index fa04a0ca4..b2c52ce9e 100644 --- a/lib/symfony/routing/Loader/AnnotationClassLoader.php +++ b/lib/symfony/routing/Loader/AnnotationClassLoader.php @@ -19,7 +19,7 @@ if (false) { /** * @deprecated since Symfony 6.4, to be removed in 7.0, use {@link AttributeClassLoader} instead */ - class AnnotationClassLoader + abstract class AnnotationClassLoader extends AttributeClassLoader { } } diff --git a/lib/symfony/routing/Loader/AnnotationDirectoryLoader.php b/lib/symfony/routing/Loader/AnnotationDirectoryLoader.php index 80cec1f5d..169b1e60a 100644 --- a/lib/symfony/routing/Loader/AnnotationDirectoryLoader.php +++ b/lib/symfony/routing/Loader/AnnotationDirectoryLoader.php @@ -19,7 +19,7 @@ if (false) { /** * @deprecated since Symfony 6.4, to be removed in 7.0, use {@link AttributeDirectoryLoader} instead */ - class AnnotationDirectoryLoader + class AnnotationDirectoryLoader extends AttributeDirectoryLoader { } } diff --git a/lib/symfony/routing/Loader/AnnotationFileLoader.php b/lib/symfony/routing/Loader/AnnotationFileLoader.php index 296f312d6..60487bb27 100644 --- a/lib/symfony/routing/Loader/AnnotationFileLoader.php +++ b/lib/symfony/routing/Loader/AnnotationFileLoader.php @@ -19,7 +19,7 @@ if (false) { /** * @deprecated since Symfony 6.4, to be removed in 7.0, use {@link AttributeFileLoader} instead */ - class AnnotationFileLoader + class AnnotationFileLoader extends AttributeFileLoader { } } diff --git a/lib/symfony/routing/Loader/AttributeClassLoader.php b/lib/symfony/routing/Loader/AttributeClassLoader.php index cd12b8715..679b0c845 100644 --- a/lib/symfony/routing/Loader/AttributeClassLoader.php +++ b/lib/symfony/routing/Loader/AttributeClassLoader.php @@ -144,7 +144,9 @@ abstract class AttributeClassLoader implements LoaderInterface if (1 === $collection->count() - \count($routeNamesBefore)) { $newRouteName = current(array_diff(array_keys($collection->all()), $routeNamesBefore)); - $collection->addAlias(sprintf('%s::%s', $class->name, $method->name), $newRouteName); + if ($newRouteName !== $aliasName = sprintf('%s::%s', $class->name, $method->name)) { + $collection->addAlias($aliasName, $newRouteName); + } } } if (0 === $collection->count() && $class->hasMethod('__invoke')) { @@ -155,8 +157,14 @@ abstract class AttributeClassLoader implements LoaderInterface } } if ($fqcnAlias && 1 === $collection->count()) { - $collection->addAlias($class->name, $invokeRouteName = key($collection->all())); - $collection->addAlias(sprintf('%s::__invoke', $class->name), $invokeRouteName); + $invokeRouteName = key($collection->all()); + if ($invokeRouteName !== $class->name) { + $collection->addAlias($class->name, $invokeRouteName); + } + + if ($invokeRouteName !== $aliasName = sprintf('%s::__invoke', $class->name)) { + $collection->addAlias($aliasName, $invokeRouteName); + } } if ($this->hasDeprecatedAnnotations) { diff --git a/lib/symfony/routing/RouteCollection.php b/lib/symfony/routing/RouteCollection.php index 0175e3abf..0a04387ce 100644 --- a/lib/symfony/routing/RouteCollection.php +++ b/lib/symfony/routing/RouteCollection.php @@ -147,9 +147,24 @@ class RouteCollection implements \IteratorAggregate, \Countable */ public function remove(string|array $name) { + $routes = []; foreach ((array) $name as $n) { + if (isset($this->routes[$n])) { + $routes[] = $n; + } + unset($this->routes[$n], $this->priorities[$n], $this->aliases[$n]); } + + if (!$routes) { + return; + } + + foreach ($this->aliases as $k => $alias) { + if (\in_array($alias->getId(), $routes, true)) { + unset($this->aliases[$k]); + } + } } /** diff --git a/lib/symfony/service-contracts/.gitignore b/lib/symfony/service-contracts/.gitignore deleted file mode 100644 index c49a5d8df..000000000 --- a/lib/symfony/service-contracts/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -vendor/ -composer.lock -phpunit.xml diff --git a/lib/symfony/service-contracts/Attribute/SubscribedService.php b/lib/symfony/service-contracts/Attribute/SubscribedService.php index 10d1bc38e..d98e1dfdb 100644 --- a/lib/symfony/service-contracts/Attribute/SubscribedService.php +++ b/lib/symfony/service-contracts/Attribute/SubscribedService.php @@ -11,9 +11,14 @@ namespace Symfony\Contracts\Service\Attribute; +use Symfony\Contracts\Service\ServiceSubscriberInterface; use Symfony\Contracts\Service\ServiceSubscriberTrait; /** + * For use as the return value for {@see ServiceSubscriberInterface}. + * + * @example new SubscribedService('http_client', HttpClientInterface::class, false, new Target('githubApi')) + * * Use with {@see ServiceSubscriberTrait} to mark a method's return type * as a subscribed service. * @@ -22,12 +27,21 @@ use Symfony\Contracts\Service\ServiceSubscriberTrait; #[\Attribute(\Attribute::TARGET_METHOD)] final class SubscribedService { + /** @var object[] */ + public array $attributes; + /** - * @param string|null $key The key to use for the service - * If null, use "ClassName::methodName" + * @param string|null $key The key to use for the service + * @param class-string|null $type The service class + * @param bool $nullable Whether the service is optional + * @param object|object[] $attributes One or more dependency injection attributes to use */ public function __construct( - public ?string $key = null + public ?string $key = null, + public ?string $type = null, + public bool $nullable = false, + array|object $attributes = [], ) { + $this->attributes = \is_array($attributes) ? $attributes : [$attributes]; } } diff --git a/lib/symfony/service-contracts/LICENSE b/lib/symfony/service-contracts/LICENSE index 74cdc2dbf..7536caeae 100644 --- a/lib/symfony/service-contracts/LICENSE +++ b/lib/symfony/service-contracts/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2018-2022 Fabien Potencier +Copyright (c) 2018-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 diff --git a/lib/symfony/service-contracts/README.md b/lib/symfony/service-contracts/README.md index 41e054a10..42841a57d 100644 --- a/lib/symfony/service-contracts/README.md +++ b/lib/symfony/service-contracts/README.md @@ -3,7 +3,7 @@ Symfony Service Contracts A set of abstractions extracted out of the Symfony components. -Can be used to build on semantics that the Symfony components proved useful - and +Can be used to build on semantics that the Symfony components proved useful and that already have battle tested implementations. See https://github.com/symfony/contracts/blob/main/README.md for more information. diff --git a/lib/symfony/service-contracts/ResetInterface.php b/lib/symfony/service-contracts/ResetInterface.php index 1af1075ee..a4f389b01 100644 --- a/lib/symfony/service-contracts/ResetInterface.php +++ b/lib/symfony/service-contracts/ResetInterface.php @@ -26,5 +26,8 @@ namespace Symfony\Contracts\Service; */ interface ResetInterface { + /** + * @return void + */ public function reset(); } diff --git a/lib/symfony/service-contracts/ServiceLocatorTrait.php b/lib/symfony/service-contracts/ServiceLocatorTrait.php index 74dfa4362..b62ec3e53 100644 --- a/lib/symfony/service-contracts/ServiceLocatorTrait.php +++ b/lib/symfony/service-contracts/ServiceLocatorTrait.php @@ -26,34 +26,24 @@ class_exists(NotFoundExceptionInterface::class); */ trait ServiceLocatorTrait { - private $factories; - private $loading = []; - private $providedTypes; + private array $factories; + private array $loading = []; + private array $providedTypes; /** - * @param callable[] $factories + * @param array $factories */ public function __construct(array $factories) { $this->factories = $factories; } - /** - * {@inheritdoc} - * - * @return bool - */ - public function has(string $id) + public function has(string $id): bool { return isset($this->factories[$id]); } - /** - * {@inheritdoc} - * - * @return mixed - */ - public function get(string $id) + public function get(string $id): mixed { if (!isset($this->factories[$id])) { throw $this->createNotFoundException($id); @@ -75,12 +65,9 @@ trait ServiceLocatorTrait } } - /** - * {@inheritdoc} - */ public function getProvidedServices(): array { - if (null === $this->providedTypes) { + if (!isset($this->providedTypes)) { $this->providedTypes = []; foreach ($this->factories as $name => $factory) { diff --git a/lib/symfony/service-contracts/ServiceProviderInterface.php b/lib/symfony/service-contracts/ServiceProviderInterface.php index c60ad0bd4..2e71f00c6 100644 --- a/lib/symfony/service-contracts/ServiceProviderInterface.php +++ b/lib/symfony/service-contracts/ServiceProviderInterface.php @@ -18,9 +18,18 @@ use Psr\Container\ContainerInterface; * * @author Nicolas Grekas * @author Mateusz Sip + * + * @template-covariant T of mixed */ interface ServiceProviderInterface extends ContainerInterface { + /** + * @return T + */ + public function get(string $id): mixed; + + public function has(string $id): bool; + /** * Returns an associative array of service types keyed by the identifiers provided by the current container. * @@ -30,7 +39,7 @@ interface ServiceProviderInterface extends ContainerInterface * * ['foo' => '?'] means the container provides service name "foo" of unspecified type * * ['bar' => '?Bar\Baz'] means the container provides a service "bar" of type Bar\Baz|null * - * @return string[] The provided service types, keyed by service names + * @return array The provided service types, keyed by service names */ public function getProvidedServices(): array; } diff --git a/lib/symfony/service-contracts/ServiceSubscriberInterface.php b/lib/symfony/service-contracts/ServiceSubscriberInterface.php index 098ab908c..3da19169b 100644 --- a/lib/symfony/service-contracts/ServiceSubscriberInterface.php +++ b/lib/symfony/service-contracts/ServiceSubscriberInterface.php @@ -11,6 +11,8 @@ namespace Symfony\Contracts\Service; +use Symfony\Contracts\Service\Attribute\SubscribedService; + /** * A ServiceSubscriber exposes its dependencies via the static {@link getSubscribedServices} method. * @@ -29,7 +31,8 @@ namespace Symfony\Contracts\Service; interface ServiceSubscriberInterface { /** - * Returns an array of service types required by such instances, optionally keyed by the service names used internally. + * Returns an array of service types (or {@see SubscribedService} objects) required + * by such instances, optionally keyed by the service names used internally. * * For mandatory dependencies: * @@ -47,7 +50,13 @@ interface ServiceSubscriberInterface * * ['?Psr\Log\LoggerInterface'] is a shortcut for * * ['Psr\Log\LoggerInterface' => '?Psr\Log\LoggerInterface'] * - * @return string[] The required service types, optionally keyed by service names + * additionally, an array of {@see SubscribedService}'s can be returned: + * + * * [new SubscribedService('logger', Psr\Log\LoggerInterface::class)] + * * [new SubscribedService(type: Psr\Log\LoggerInterface::class, nullable: true)] + * * [new SubscribedService('http_client', HttpClientInterface::class, attributes: new Target('githubApi'))] + * + * @return string[]|SubscribedService[] The required service types, optionally keyed by service names */ - public static function getSubscribedServices(); + public static function getSubscribedServices(): array; } diff --git a/lib/symfony/service-contracts/ServiceSubscriberTrait.php b/lib/symfony/service-contracts/ServiceSubscriberTrait.php index 16e3eb2c1..f3b450cd6 100644 --- a/lib/symfony/service-contracts/ServiceSubscriberTrait.php +++ b/lib/symfony/service-contracts/ServiceSubscriberTrait.php @@ -12,6 +12,7 @@ namespace Symfony\Contracts\Service; use Psr\Container\ContainerInterface; +use Symfony\Contracts\Service\Attribute\Required; use Symfony\Contracts\Service\Attribute\SubscribedService; /** @@ -25,85 +26,53 @@ trait ServiceSubscriberTrait /** @var ContainerInterface */ protected $container; - /** - * {@inheritdoc} - */ public static function getSubscribedServices(): array { $services = method_exists(get_parent_class(self::class) ?: '', __FUNCTION__) ? parent::getSubscribedServices() : []; - $attributeOptIn = false; - if (\PHP_VERSION_ID >= 80000) { - foreach ((new \ReflectionClass(self::class))->getMethods() as $method) { - if (self::class !== $method->getDeclaringClass()->name) { - continue; - } - - if (!$attribute = $method->getAttributes(SubscribedService::class)[0] ?? null) { - continue; - } - - if ($method->isStatic() || $method->isAbstract() || $method->isGenerator() || $method->isInternal() || $method->getNumberOfRequiredParameters()) { - throw new \LogicException(sprintf('Cannot use "%s" on method "%s::%s()" (can only be used on non-static, non-abstract methods with no parameters).', SubscribedService::class, self::class, $method->name)); - } - - if (!$returnType = $method->getReturnType()) { - throw new \LogicException(sprintf('Cannot use "%s" on methods without a return type in "%s::%s()".', SubscribedService::class, $method->name, self::class)); - } - - $serviceId = $returnType instanceof \ReflectionNamedType ? $returnType->getName() : (string) $returnType; - - if ($returnType->allowsNull()) { - $serviceId = '?'.$serviceId; - } - - $services[$attribute->newInstance()->key ?? self::class.'::'.$method->name] = $serviceId; - $attributeOptIn = true; + foreach ((new \ReflectionClass(self::class))->getMethods() as $method) { + if (self::class !== $method->getDeclaringClass()->name) { + continue; } - } - if (!$attributeOptIn) { - foreach ((new \ReflectionClass(self::class))->getMethods() as $method) { - if ($method->isStatic() || $method->isAbstract() || $method->isGenerator() || $method->isInternal() || $method->getNumberOfRequiredParameters()) { - continue; - } + if (!$attribute = $method->getAttributes(SubscribedService::class)[0] ?? null) { + continue; + } - if (self::class !== $method->getDeclaringClass()->name) { - continue; - } + if ($method->isStatic() || $method->isAbstract() || $method->isGenerator() || $method->isInternal() || $method->getNumberOfRequiredParameters()) { + throw new \LogicException(sprintf('Cannot use "%s" on method "%s::%s()" (can only be used on non-static, non-abstract methods with no parameters).', SubscribedService::class, self::class, $method->name)); + } - if (!($returnType = $method->getReturnType()) instanceof \ReflectionNamedType) { - continue; - } + if (!$returnType = $method->getReturnType()) { + throw new \LogicException(sprintf('Cannot use "%s" on methods without a return type in "%s::%s()".', SubscribedService::class, $method->name, self::class)); + } - if ($returnType->isBuiltin()) { - continue; - } + /* @var SubscribedService $attribute */ + $attribute = $attribute->newInstance(); + $attribute->key ??= self::class.'::'.$method->name; + $attribute->type ??= $returnType instanceof \ReflectionNamedType ? $returnType->getName() : (string) $returnType; + $attribute->nullable = $returnType->allowsNull(); - if (\PHP_VERSION_ID >= 80000) { - trigger_deprecation('symfony/service-contracts', '2.5', 'Using "%s" in "%s" without using the "%s" attribute on any method is deprecated.', ServiceSubscriberTrait::class, self::class, SubscribedService::class); - } - - $services[self::class.'::'.$method->name] = '?'.($returnType instanceof \ReflectionNamedType ? $returnType->getName() : $returnType); + if ($attribute->attributes) { + $services[] = $attribute; + } else { + $services[$attribute->key] = ($attribute->nullable ? '?' : '').$attribute->type; } } return $services; } - /** - * @required - * - * @return ContainerInterface|null - */ - public function setContainer(ContainerInterface $container) + #[Required] + public function setContainer(ContainerInterface $container): ?ContainerInterface { - $this->container = $container; - + $ret = null; if (method_exists(get_parent_class(self::class) ?: '', __FUNCTION__)) { - return parent::setContainer($container); + $ret = parent::setContainer($container); } - return null; + $this->container = $container; + + return $ret; } } diff --git a/lib/symfony/service-contracts/composer.json b/lib/symfony/service-contracts/composer.json index f05863701..32bb8a316 100644 --- a/lib/symfony/service-contracts/composer.json +++ b/lib/symfony/service-contracts/composer.json @@ -16,23 +16,22 @@ } ], "require": { - "php": ">=7.2.5", - "psr/container": "^1.1", - "symfony/deprecation-contracts": "^2.1|^3" + "php": ">=8.1", + "psr/container": "^1.1|^2.0" }, "conflict": { "ext-psr": "<1.1|>=2" }, - "suggest": { - "symfony/service-implementation": "" - }, "autoload": { - "psr-4": { "Symfony\\Contracts\\Service\\": "" } + "psr-4": { "Symfony\\Contracts\\Service\\": "" }, + "exclude-from-classmap": [ + "/Test/" + ] }, "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-main": "2.5-dev" + "dev-main": "3.4-dev" }, "thanks": { "name": "symfony/contracts", diff --git a/lib/symfony/var-dumper/Dumper/HtmlDumper.php b/lib/symfony/var-dumper/Dumper/HtmlDumper.php index f93b220ef..f276bfdd2 100644 --- a/lib/symfony/var-dumper/Dumper/HtmlDumper.php +++ b/lib/symfony/var-dumper/Dumper/HtmlDumper.php @@ -664,7 +664,7 @@ pre.sf-dump:after { clear: both; } pre.sf-dump span { - display: inline; + display: inline-flex; } pre.sf-dump a { text-decoration: none; diff --git a/lib/symfony/var-exporter/LazyGhostTrait.php b/lib/symfony/var-exporter/LazyGhostTrait.php index a25fc21a8..26f7bc2cd 100644 --- a/lib/symfony/var-exporter/LazyGhostTrait.php +++ b/lib/symfony/var-exporter/LazyGhostTrait.php @@ -166,8 +166,9 @@ trait LazyGhostTrait if ($state && (null === $scope || isset($propertyScopes["\0$scope\0$name"]))) { if (LazyObjectState::STATUS_INITIALIZED_FULL === $state->status) { // Work around php/php-src#12695 - $property = $propertyScopes[null === $scope ? $name : "\0$scope\0$name"][3] - ?? (Hydrator::$propertyScopes[$this::class] = Hydrator::getPropertyScopes($this::class))[3]; + $property = null === $scope ? $name : "\0$scope\0$name"; + $property = $propertyScopes[$property][3] + ?? Hydrator::$propertyScopes[$this::class][$property][3] = new \ReflectionProperty($scope ?? $class, $name); } else { $property = null; } diff --git a/lib/symfony/var-exporter/README.md b/lib/symfony/var-exporter/README.md index 9f6e2550b..719527052 100644 --- a/lib/symfony/var-exporter/README.md +++ b/lib/symfony/var-exporter/README.md @@ -7,10 +7,10 @@ of objects: - `VarExporter::export()` allows exporting any serializable PHP data structure to plain PHP code. While doing so, it preserves all the semantics associated with the serialization mechanism of PHP (`__wakeup`, `__sleep`, `Serializable`, - `__serialize`, `__unserialize`.) + `__serialize`, `__unserialize`); - `Instantiator::instantiate()` creates an object and sets its properties without - calling its constructor nor any other methods. -- `Hydrator::hydrate()` can set the properties of an existing object. + calling its constructor nor any other methods; +- `Hydrator::hydrate()` can set the properties of an existing object; - `Lazy*Trait` can make a class behave as a lazy-loading ghost or virtual proxy. VarExporter::export() @@ -26,7 +26,7 @@ Unlike `var_export()`, this works on any serializable PHP value. It also provides a few improvements over `var_export()`/`serialize()`: * the output is PSR-2 compatible; - * the output can be re-indented without messing up with `\r` or `\n` in the data + * the output can be re-indented without messing up with `\r` or `\n` in the data; * missing classes throw a `ClassNotFoundException` instead of being unserialized to `PHP_Incomplete_Class` objects; * references involving `SplObjectStorage`, `ArrayObject` or `ArrayIterator` @@ -61,7 +61,7 @@ Hydrator::hydrate($object, [], [ ------------ The component provides two lazy-loading patterns: ghost objects and virtual -proxies (see https://martinfowler.com/eaaCatalog/lazyLoad.html for reference.) +proxies (see https://martinfowler.com/eaaCatalog/lazyLoad.html for reference). Ghost objects work only with concrete and non-internal classes. In the generic case, they are not compatible with using factories in their initializer. diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Profiler/base_js.html.twig b/lib/symfony/web-profiler-bundle/Resources/views/Profiler/base_js.html.twig index e501ebe58..8a669a5c6 100644 --- a/lib/symfony/web-profiler-bundle/Resources/views/Profiler/base_js.html.twig +++ b/lib/symfony/web-profiler-bundle/Resources/views/Profiler/base_js.html.twig @@ -13,6 +13,7 @@ constructor() { this.#createTabs(); this.#createToggles(); + this.#createCopyToClipboard(); this.#convertDateTimesToUserTimezone(); } @@ -161,18 +162,39 @@ }); }); - /* Prevents from disallowing clicks on "copy to clipboard" elements inside toggles */ - const copyToClipboardElements = toggle.querySelectorAll('span[data-clipboard-text]'); - copyToClipboardElements.forEach((copyToClipboardElement) => { - copyToClipboardElement.addEventListener('click', (e) => { - e.stopPropagation(); - }); - }); - toggle.setAttribute('data-processed', 'true'); }); } + #createCopyToClipboard() { + if (!navigator.clipboard) { + return; + } + + const copyToClipboardElements = document.querySelectorAll('[data-clipboard-text]'); + + copyToClipboardElements.forEach((copyToClipboardElement) => { + copyToClipboardElement.classList.remove('hidden'); + + copyToClipboardElement.addEventListener('click', (e) => { + /* Prevents from disallowing clicks on "copy to clipboard" elements inside toggles */ + e.stopPropagation(); + + navigator.clipboard.writeText(copyToClipboardElement.getAttribute('data-clipboard-text')); + + let oldContent = copyToClipboardElement.textContent; + + copyToClipboardElement.textContent = `✅ Copied!`; + copyToClipboardElement.disabled = true; + + setTimeout(() => { + copyToClipboardElement.textContent = oldContent; + copyToClipboardElement.disabled = false; + }, 7000); + }); + }); + } + #convertDateTimesToUserTimezone() { const userTimezoneName = Intl.DateTimeFormat().resolvedOptions().timeZone; diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Profiler/toolbar.css.twig b/lib/symfony/web-profiler-bundle/Resources/views/Profiler/toolbar.css.twig index 4bb9cb8d1..b61fa5e9f 100644 --- a/lib/symfony/web-profiler-bundle/Resources/views/Profiler/toolbar.css.twig +++ b/lib/symfony/web-profiler-bundle/Resources/views/Profiler/toolbar.css.twig @@ -47,6 +47,8 @@ } .sf-minitoolbar { + --sf-toolbar-gray-800: #262626; + background-color: var(--sf-toolbar-gray-800); border-top-left-radius: 4px; bottom: 0; @@ -66,6 +68,8 @@ } .sf-minitoolbar svg, .sf-minitoolbar img { + --sf-toolbar-gray-200: #e5e5e5; + color: var(--sf-toolbar-gray-200); max-height: 24px; max-width: 24px; diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Profiler/toolbar_js.html.twig b/lib/symfony/web-profiler-bundle/Resources/views/Profiler/toolbar_js.html.twig index 9d06ed835..47d004295 100644 --- a/lib/symfony/web-profiler-bundle/Resources/views/Profiler/toolbar_js.html.twig +++ b/lib/symfony/web-profiler-bundle/Resources/views/Profiler/toolbar_js.html.twig @@ -50,33 +50,6 @@ }; } - if (navigator.clipboard) { - document.addEventListener('readystatechange', () => { - if (document.readyState !== 'complete') { - return; - } - - document.querySelectorAll('[data-clipboard-text]').forEach(function (element) { - removeClass(element, 'hidden'); - element.addEventListener('click', function () { - navigator.clipboard.writeText(element.getAttribute('data-clipboard-text')); - - if (element.classList.contains("label")) { - let oldContent = element.textContent; - - element.textContent = "✅ Copied!"; - element.classList.add("status-success"); - - setTimeout(() => { - element.textContent = oldContent; - element.classList.remove("status-success"); - }, 7000); - } - }); - }); - }); - } - var request = function(url, onSuccess, onError, payload, options, tries) { var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP'); options = options || {}; @@ -577,7 +550,9 @@ /* Evaluate in global scope scripts embedded inside the toolbar */ var i, scripts = [].slice.call(el.querySelectorAll('script')); for (i = 0; i < scripts.length; ++i) { - eval.call({}, scripts[i].firstChild.nodeValue); + if (scripts[i].firstChild) { + eval.call({}, scripts[i].firstChild.nodeValue); + } } el.style.display = -1 !== xhr.responseText.indexOf('sf-toolbarreset') ? 'block' : 'none'; @@ -648,7 +623,7 @@ sfwdt.innerHTML = '\
\
\ - An error occurred while loading the web debug toolbar. Open the web profiler.\ + An error occurred while loading the web debug toolbar. Open the web profiler.\
\ '; sfwdt.setAttribute('class', 'sf-toolbar sf-error-toolbar'); diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Profiler/toolbar_redirect.html.twig b/lib/symfony/web-profiler-bundle/Resources/views/Profiler/toolbar_redirect.html.twig index 7963815a6..f29494226 100644 --- a/lib/symfony/web-profiler-bundle/Resources/views/Profiler/toolbar_redirect.html.twig +++ b/lib/symfony/web-profiler-bundle/Resources/views/Profiler/toolbar_redirect.html.twig @@ -39,10 +39,10 @@

Redirection Intercepted

- {% set absolute_url = host in location ? location : host ~ location %} + {% set absolute_url = absolute_url(location) %}

This request redirects to {{ absolute_url }}

-

Follow redirect

+

Follow redirect

The redirect was intercepted by the Symfony Web Debug toolbar to help debugging. diff --git a/lib/symfony/web-profiler-bundle/Twig/WebProfilerExtension.php b/lib/symfony/web-profiler-bundle/Twig/WebProfilerExtension.php index 60470b080..6df2a2472 100644 --- a/lib/symfony/web-profiler-bundle/Twig/WebProfilerExtension.php +++ b/lib/symfony/web-profiler-bundle/Twig/WebProfilerExtension.php @@ -14,6 +14,7 @@ namespace Symfony\Bundle\WebProfilerBundle\Twig; use Symfony\Component\VarDumper\Cloner\Data; use Symfony\Component\VarDumper\Dumper\HtmlDumper; use Twig\Environment; +use Twig\Extension\EscaperExtension; use Twig\Extension\ProfilerExtension; use Twig\Profiler\Profile; use Twig\TwigFunction; @@ -78,12 +79,12 @@ class WebProfilerExtension extends ProfilerExtension public function dumpLog(Environment $env, string $message, Data $context = null): string { - $message = twig_escape_filter($env, $message); + $message = self::escape($env, $message); $message = preg_replace('/"(.*?)"/', '"$1"', $message); $replacements = []; foreach ($context ?? [] as $k => $v) { - $k = '{'.twig_escape_filter($env, $k).'}'; + $k = '{'.self::escape($env, $k).'}'; if (str_contains($message, $k)) { $replacements[$k] = $v; } @@ -104,4 +105,14 @@ class WebProfilerExtension extends ProfilerExtension { return 'profiler'; } + + private static function escape(Environment $env, string $s): string + { + if (method_exists(EscaperExtension::class, 'escape')) { + return EscaperExtension::escape($env, $s); + } + + // to be removed when support for Twig 3 is dropped + return twig_escape_filter($env, $s); + } } diff --git a/lib/twig/twig/.editorconfig b/lib/twig/twig/.editorconfig deleted file mode 100644 index 270f1d1b7..000000000 --- a/lib/twig/twig/.editorconfig +++ /dev/null @@ -1,18 +0,0 @@ -; top-most EditorConfig file -root = true - -; Unix-style newlines -[*] -end_of_line = LF - -[*.php] -indent_style = space -indent_size = 4 - -[*.test] -indent_style = space -indent_size = 4 - -[*.rst] -indent_style = space -indent_size = 4 diff --git a/lib/twig/twig/.gitattributes b/lib/twig/twig/.gitattributes deleted file mode 100644 index 06bc36713..000000000 --- a/lib/twig/twig/.gitattributes +++ /dev/null @@ -1,4 +0,0 @@ -/doc/ export-ignore -/extra/ export-ignore -/tests/ export-ignore -/phpunit.xml.dist export-ignore diff --git a/lib/twig/twig/.github/workflows/ci.yml b/lib/twig/twig/.github/workflows/ci.yml deleted file mode 100644 index 50f23f9a4..000000000 --- a/lib/twig/twig/.github/workflows/ci.yml +++ /dev/null @@ -1,149 +0,0 @@ -name: "CI" - -on: - pull_request: - push: - branches: - - '3.x' - -env: - SYMFONY_PHPUNIT_DISABLE_RESULT_CACHE: 1 - -permissions: - contents: read - -jobs: - tests: - name: "PHP ${{ matrix.php-version }}" - - runs-on: 'ubuntu-latest' - - continue-on-error: ${{ matrix.experimental }} - - strategy: - matrix: - php-version: - - '7.2.5' - - '7.3' - - '7.4' - - '8.0' - - '8.1' - experimental: [false] - - steps: - - name: "Checkout code" - uses: actions/checkout@v2 - - - name: "Install PHP with extensions" - uses: shivammathur/setup-php@v2 - with: - coverage: "none" - php-version: ${{ matrix.php-version }} - ini-values: memory_limit=-1 - - - name: "Add PHPUnit matcher" - run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" - - - run: composer install - - - name: "Install PHPUnit" - run: vendor/bin/simple-phpunit install - - - name: "PHPUnit version" - run: vendor/bin/simple-phpunit --version - - - name: "Run tests" - run: vendor/bin/simple-phpunit - - extension-tests: - needs: - - 'tests' - - name: "${{ matrix.extension }} with PHP ${{ matrix.php-version }}" - - runs-on: 'ubuntu-latest' - - continue-on-error: true - - strategy: - matrix: - php-version: - - '7.2.5' - - '7.3' - - '7.4' - - '8.0' - - '8.1' - extension: - - 'extra/cache-extra' - - 'extra/cssinliner-extra' - - 'extra/html-extra' - - 'extra/inky-extra' - - 'extra/intl-extra' - - 'extra/markdown-extra' - - 'extra/string-extra' - - 'extra/twig-extra-bundle' - experimental: [false] - - steps: - - name: "Checkout code" - uses: actions/checkout@v2 - - - name: "Install PHP with extensions" - uses: shivammathur/setup-php@v2 - with: - coverage: "none" - php-version: ${{ matrix.php-version }} - ini-values: memory_limit=-1 - - - name: "Add PHPUnit matcher" - run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" - - - run: composer install - - - name: "Install PHPUnit" - run: vendor/bin/simple-phpunit install - - - name: "PHPUnit version" - run: vendor/bin/simple-phpunit --version - - - name: "Composer install" - working-directory: ${{ matrix.extension}} - run: composer install - - - name: "Run tests" - working-directory: ${{ matrix.extension}} - run: ../../vendor/bin/simple-phpunit - -# -# Drupal does not support Twig 3 now! -# -# integration-tests: -# needs: -# - 'tests' -# -# name: "Integration tests with PHP ${{ matrix.php-version }}" -# -# runs-on: 'ubuntu-20.04' -# -# continue-on-error: true -# -# strategy: -# matrix: -# php-version: -# - '7.3' -# -# steps: -# - name: "Checkout code" -# uses: actions/checkout@v2 -# -# - name: "Install PHP with extensions" -# uses: shivammathur/setup-php@2 -# with: -# coverage: "none" -# extensions: "gd, pdo_sqlite" -# php-version: ${{ matrix.php-version }} -# ini-values: memory_limit=-1 -# tools: composer:v2 -# -# - run: bash ./tests/drupal_test.sh -# shell: "bash" diff --git a/lib/twig/twig/.github/workflows/documentation.yml b/lib/twig/twig/.github/workflows/documentation.yml deleted file mode 100644 index ee83b5887..000000000 --- a/lib/twig/twig/.github/workflows/documentation.yml +++ /dev/null @@ -1,64 +0,0 @@ -name: "Documentation" - -on: - pull_request: - push: - branches: - - '2.x' - - '3.x' - -permissions: - contents: read - -jobs: - build: - name: "Build" - - runs-on: ubuntu-latest - - steps: - - name: "Checkout code" - uses: actions/checkout@v2 - - - name: "Set-up PHP" - uses: shivammathur/setup-php@v2 - with: - php-version: 8.1 - coverage: none - tools: "composer:v2" - - - name: Get composer cache directory - id: composercache - working-directory: doc/_build - run: echo "::set-output name=dir::$(composer config cache-files-dir)" - - - name: Cache dependencies - uses: actions/cache@v2 - with: - path: ${{ steps.composercache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} - restore-keys: ${{ runner.os }}-composer- - - - name: "Install dependencies" - working-directory: doc/_build - run: composer install --prefer-dist --no-progress - - - name: "Build the docs" - working-directory: doc/_build - run: php build.php --disable-cache - - doctor-rst: - name: "DOCtor-RST" - - runs-on: ubuntu-latest - - steps: - - name: "Checkout code" - uses: actions/checkout@v2 - - - name: "Run DOCtor-RST" - uses: docker://oskarstark/doctor-rst - with: - args: --short - env: - DOCS_DIR: 'doc/' diff --git a/lib/twig/twig/.gitignore b/lib/twig/twig/.gitignore deleted file mode 100644 index b197246ba..000000000 --- a/lib/twig/twig/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -/doc/_build/vendor -/doc/_build/output -/composer.lock -/phpunit.xml -/vendor -.phpunit.result.cache diff --git a/lib/twig/twig/.php-cs-fixer.dist.php b/lib/twig/twig/.php-cs-fixer.dist.php deleted file mode 100644 index b07ac7fca..000000000 --- a/lib/twig/twig/.php-cs-fixer.dist.php +++ /dev/null @@ -1,20 +0,0 @@ -setRules([ - '@Symfony' => true, - '@Symfony:risky' => true, - '@PHPUnit75Migration:risky' => true, - 'php_unit_dedicate_assert' => ['target' => '5.6'], - 'array_syntax' => ['syntax' => 'short'], - 'php_unit_fqcn_annotation' => true, - 'no_unreachable_default_argument_value' => false, - 'braces' => ['allow_single_line_closure' => true], - 'heredoc_to_nowdoc' => false, - 'ordered_imports' => true, - 'phpdoc_types_order' => ['null_adjustment' => 'always_last', 'sort_algorithm' => 'none'], - 'native_function_invocation' => ['include' => ['@compiler_optimized'], 'scope' => 'all'], - ]) - ->setRiskyAllowed(true) - ->setFinder((new PhpCsFixer\Finder())->in(__DIR__)) -; diff --git a/lib/twig/twig/CHANGELOG b/lib/twig/twig/CHANGELOG index 379387644..2b8341fd8 100644 --- a/lib/twig/twig/CHANGELOG +++ b/lib/twig/twig/CHANGELOG @@ -1,3 +1,48 @@ +# 3.8.0 (2023-11-21) + + * Catch errors thrown during template rendering + * Fix IntlExtension::formatDateTime use of date formatter prototype + * Fix premature loop exit in Security Policy lookup of allowed methods/properties + * Remove NumberFormatter::TYPE_CURRENCY (deprecated in PHP 8.3) + * Restore return type annotations + * Allow Symfony 7 packages to be installed + * Deprecate `twig_test_iterable` function. Use the native `is_iterable` instead. + +# 3.7.1 (2023-08-28) + + * Fix some phpdocs + +# 3.7.0 (2023-07-26) + + * Add support for the ...spread operator on arrays and hashes + +# 3.6.1 (2023-06-08) + + * Suppress some native return type deprecation messages + +# 3.6.0 (2023-05-03) + + * Allow psr/container 2.0 + * Add the new PHP 8.0 IntlDateFormatter::RELATIVE_* constants for date formatting + * Make the Lexer initialize itself lazily + +# 3.5.1 (2023-02-08) + + * Arrow functions passed to the "reduce" filter now accept the current key as a third argument + * Restores the leniency of the matches twig comparison + * Fix error messages in sandboxed mode for "has some" and "has every" + +# 3.5.0 (2022-12-27) + + * Make Twig\ExpressionParser non-internal + * Add "has some" and "has every" operators + * Add Compile::reset() + * Throw a better runtime error when the "matches" regexp is not valid + * Add "twig *_names" intl functions + * Fix optimizing closures callbacks + * Add a better exception when getting an undefined constant via `constant` + * Fix `if` nodes when outside of a block and with an empty body + # 3.4.3 (2022-09-28) * Fix a security issue on filesystem loader (possibility to load a template outside a configured directory) diff --git a/lib/twig/twig/LICENSE b/lib/twig/twig/LICENSE index 8711927f6..fd8234e51 100644 --- a/lib/twig/twig/LICENSE +++ b/lib/twig/twig/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2009-2022 by the Twig Team. +Copyright (c) 2009-present by the Twig Team. All rights reserved. diff --git a/lib/twig/twig/composer.json b/lib/twig/twig/composer.json index 33e46405c..1b1726fe8 100644 --- a/lib/twig/twig/composer.json +++ b/lib/twig/twig/composer.json @@ -25,12 +25,13 @@ ], "require": { "php": ">=7.2.5", + "symfony/polyfill-php80": "^1.22", "symfony/polyfill-mbstring": "^1.3", "symfony/polyfill-ctype": "^1.8" }, "require-dev": { - "symfony/phpunit-bridge": "^4.4.9|^5.0.9|^6.0", - "psr/container": "^1.0" + "symfony/phpunit-bridge": "^5.4.9|^6.3|^7.0", + "psr/container": "^1.0|^2.0" }, "autoload": { "psr-4" : { @@ -41,10 +42,5 @@ "psr-4" : { "Twig\\Tests\\" : "tests/" } - }, - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } } } diff --git a/lib/twig/twig/src/Cache/FilesystemCache.php b/lib/twig/twig/src/Cache/FilesystemCache.php index e075563ae..4024adbd7 100644 --- a/lib/twig/twig/src/Cache/FilesystemCache.php +++ b/lib/twig/twig/src/Cache/FilesystemCache.php @@ -63,7 +63,7 @@ class FilesystemCache implements CacheInterface if (self::FORCE_BYTECODE_INVALIDATION == ($this->options & self::FORCE_BYTECODE_INVALIDATION)) { // Compile cached file into bytecode cache - if (\function_exists('opcache_invalidate') && filter_var(ini_get('opcache.enable'), \FILTER_VALIDATE_BOOLEAN)) { + if (\function_exists('opcache_invalidate') && filter_var(\ini_get('opcache.enable'), \FILTER_VALIDATE_BOOLEAN)) { @opcache_invalidate($key, true); } elseif (\function_exists('apc_compile_file')) { apc_compile_file($key); diff --git a/lib/twig/twig/src/Compiler.php b/lib/twig/twig/src/Compiler.php index 95e1f183b..eb652c61a 100644 --- a/lib/twig/twig/src/Compiler.php +++ b/lib/twig/twig/src/Compiler.php @@ -46,7 +46,7 @@ class Compiler /** * @return $this */ - public function compile(Node $node, int $indentation = 0) + public function reset(int $indentation = 0) { $this->lastLine = null; $this->source = ''; @@ -57,6 +57,15 @@ class Compiler $this->indentation = $indentation; $this->varNameSalt = 0; + return $this; + } + + /** + * @return $this + */ + public function compile(Node $node, int $indentation = 0) + { + $this->reset($indentation); $node->compile($this); return $this; diff --git a/lib/twig/twig/src/Environment.php b/lib/twig/twig/src/Environment.php index 85aaab916..d7d51cdb1 100644 --- a/lib/twig/twig/src/Environment.php +++ b/lib/twig/twig/src/Environment.php @@ -25,6 +25,8 @@ use Twig\Extension\OptimizerExtension; use Twig\Loader\ArrayLoader; use Twig\Loader\ChainLoader; use Twig\Loader\LoaderInterface; +use Twig\Node\Expression\Binary\AbstractBinary; +use Twig\Node\Expression\Unary\AbstractUnary; use Twig\Node\ModuleNode; use Twig\Node\Node; use Twig\NodeVisitor\NodeVisitorInterface; @@ -38,11 +40,11 @@ use Twig\TokenParser\TokenParserInterface; */ class Environment { - public const VERSION = '3.4.3'; - public const VERSION_ID = 30403; + public const VERSION = '3.8.0'; + public const VERSION_ID = 30800; public const MAJOR_VERSION = 3; - public const MINOR_VERSION = 4; - public const RELEASE_VERSION = 3; + public const MINOR_VERSION = 8; + public const RELEASE_VERSION = 0; public const EXTRA_VERSION = ''; private $charset; @@ -53,6 +55,7 @@ class Environment private $lexer; private $parser; private $compiler; + /** @var array */ private $globals = []; private $resolvedGlobals; private $loadedTemplates; @@ -342,7 +345,6 @@ class Environment $this->cache->load($key); } - $source = null; if (!class_exists($cls, false)) { $source = $this->getLoader()->getSourceContext($name); $content = $this->compileSource($source); @@ -775,6 +777,8 @@ class Environment /** * @internal + * + * @return array */ public function getGlobals(): array { @@ -804,6 +808,8 @@ class Environment /** * @internal + * + * @return array}> */ public function getUnaryOperators(): array { @@ -812,6 +818,8 @@ class Environment /** * @internal + * + * @return array, associativity: ExpressionParser::OPERATOR_*}> */ public function getBinaryOperators(): array { diff --git a/lib/twig/twig/src/Error/Error.php b/lib/twig/twig/src/Error/Error.php index a68be65f2..bca1fa64c 100644 --- a/lib/twig/twig/src/Error/Error.php +++ b/lib/twig/twig/src/Error/Error.php @@ -53,7 +53,7 @@ class Error extends \Exception * @param int $lineno The template line where the error occurred * @param Source|null $source The source context where the error occurred */ - public function __construct(string $message, int $lineno = -1, Source $source = null, \Exception $previous = null) + public function __construct(string $message, int $lineno = -1, Source $source = null, \Throwable $previous = null) { parent::__construct('', 0, $previous); @@ -130,13 +130,13 @@ class Error extends \Exception } $dot = false; - if ('.' === substr($this->message, -1)) { + if (str_ends_with($this->message, '.')) { $this->message = substr($this->message, 0, -1); $dot = true; } $questionMark = false; - if ('?' === substr($this->message, -1)) { + if (str_ends_with($this->message, '?')) { $this->message = substr($this->message, 0, -1); $questionMark = true; } @@ -172,7 +172,7 @@ class Error extends \Exception foreach ($backtrace as $trace) { if (isset($trace['object']) && $trace['object'] instanceof Template) { $currentClass = \get_class($trace['object']); - $isEmbedContainer = null === $templateClass ? false : 0 === strpos($templateClass, $currentClass); + $isEmbedContainer = null === $templateClass ? false : str_starts_with($templateClass, $currentClass); if (null === $this->name || ($this->name == $trace['object']->getTemplateName() && !$isEmbedContainer)) { $template = $trace['object']; $templateClass = \get_class($trace['object']); diff --git a/lib/twig/twig/src/Error/SyntaxError.php b/lib/twig/twig/src/Error/SyntaxError.php index 726b3309e..77c437c68 100644 --- a/lib/twig/twig/src/Error/SyntaxError.php +++ b/lib/twig/twig/src/Error/SyntaxError.php @@ -30,7 +30,7 @@ class SyntaxError extends Error $alternatives = []; foreach ($items as $item) { $lev = levenshtein($name, $item); - if ($lev <= \strlen($name) / 3 || false !== strpos($item, $name)) { + if ($lev <= \strlen($name) / 3 || str_contains($item, $name)) { $alternatives[$item] = $lev; } } diff --git a/lib/twig/twig/src/ExpressionParser.php b/lib/twig/twig/src/ExpressionParser.php index 70b6eb05c..13e0f0876 100644 --- a/lib/twig/twig/src/ExpressionParser.php +++ b/lib/twig/twig/src/ExpressionParser.php @@ -17,6 +17,7 @@ use Twig\Node\Expression\AbstractExpression; use Twig\Node\Expression\ArrayExpression; use Twig\Node\Expression\ArrowFunctionExpression; use Twig\Node\Expression\AssignNameExpression; +use Twig\Node\Expression\Binary\AbstractBinary; use Twig\Node\Expression\Binary\ConcatBinary; use Twig\Node\Expression\BlockReferenceExpression; use Twig\Node\Expression\ConditionalExpression; @@ -26,6 +27,7 @@ use Twig\Node\Expression\MethodCallExpression; use Twig\Node\Expression\NameExpression; use Twig\Node\Expression\ParentExpression; use Twig\Node\Expression\TestExpression; +use Twig\Node\Expression\Unary\AbstractUnary; use Twig\Node\Expression\Unary\NegUnary; use Twig\Node\Expression\Unary\NotUnary; use Twig\Node\Expression\Unary\PosUnary; @@ -40,8 +42,6 @@ use Twig\Node\Node; * @see https://en.wikipedia.org/wiki/Operator-precedence_parser * * @author Fabien Potencier - * - * @internal */ class ExpressionParser { @@ -50,7 +50,9 @@ class ExpressionParser private $parser; private $env; + /** @var array}> */ private $unaryOperators; + /** @var array, associativity: self::OPERATOR_*}> */ private $binaryOperators; public function __construct(Parser $parser, Environment $env) @@ -80,7 +82,7 @@ class ExpressionParser } elseif (isset($op['callable'])) { $expr = $op['callable']($this->parser, $expr); } else { - $expr1 = $this->parseExpression(self::OPERATOR_LEFT === $op['associativity'] ? $op['precedence'] + 1 : $op['precedence']); + $expr1 = $this->parseExpression(self::OPERATOR_LEFT === $op['associativity'] ? $op['precedence'] + 1 : $op['precedence'], true); $class = $op['class']; $expr = new $class($expr, $expr1, $token->getLine()); } @@ -181,11 +183,14 @@ class ExpressionParser if (!$this->parser->getStream()->nextIf(/* Token::PUNCTUATION_TYPE */ 9, ':')) { $expr2 = $this->parseExpression(); if ($this->parser->getStream()->nextIf(/* Token::PUNCTUATION_TYPE */ 9, ':')) { + // Ternary operator (expr ? expr2 : expr3) $expr3 = $this->parseExpression(); } else { + // Ternary without else (expr ? expr2) $expr3 = new ConstantExpression('', $this->parser->getCurrentToken()->getLine()); } } else { + // Ternary without then (expr ?: expr3) $expr2 = $expr; $expr3 = $this->parseExpression(); } @@ -332,7 +337,14 @@ class ExpressionParser } $first = false; - $node->addElement($this->parseExpression()); + if ($stream->test(/* Token::SPREAD_TYPE */ 13)) { + $stream->next(); + $expr = $this->parseExpression(); + $expr->setAttribute('spread', true); + $node->addElement($expr); + } else { + $node->addElement($this->parseExpression()); + } } $stream->expect(/* Token::PUNCTUATION_TYPE */ 9, ']', 'An opened array is not properly closed'); @@ -357,6 +369,14 @@ class ExpressionParser } $first = false; + if ($stream->test(/* Token::SPREAD_TYPE */ 13)) { + $stream->next(); + $value = $this->parseExpression(); + $value->setAttribute('spread', true); + $node->addElement($value); + continue; + } + // a hash key can be: // // * a number -- 12 @@ -489,10 +509,6 @@ class ExpressionParser } if ($node instanceof NameExpression && null !== $this->parser->getImportedSymbol('template', $node->getAttribute('name'))) { - if (!$arg instanceof ConstantExpression) { - throw new SyntaxError(sprintf('Dynamic macro names are not supported (called on "%s").', $node->getAttribute('name')), $token->getLine(), $stream->getSourceContext()); - } - $name = $arg->getAttribute('value'); $node = new MethodCallExpression($node, 'macro_'.$name, $arguments, $lineno); diff --git a/lib/twig/twig/src/Extension/CoreExtension.php b/lib/twig/twig/src/Extension/CoreExtension.php index b77985859..36aa8f10a 100644 --- a/lib/twig/twig/src/Extension/CoreExtension.php +++ b/lib/twig/twig/src/Extension/CoreExtension.php @@ -23,6 +23,8 @@ use Twig\Node\Expression\Binary\EqualBinary; use Twig\Node\Expression\Binary\FloorDivBinary; use Twig\Node\Expression\Binary\GreaterBinary; use Twig\Node\Expression\Binary\GreaterEqualBinary; +use Twig\Node\Expression\Binary\HasEveryBinary; +use Twig\Node\Expression\Binary\HasSomeBinary; use Twig\Node\Expression\Binary\InBinary; use Twig\Node\Expression\Binary\LessBinary; use Twig\Node\Expression\Binary\LessEqualBinary; @@ -249,7 +251,7 @@ final class CoreExtension extends AbstractExtension new TwigTest('divisible by', null, ['node_class' => DivisiblebyTest::class, 'one_mandatory_argument' => true]), new TwigTest('constant', null, ['node_class' => ConstantTest::class]), new TwigTest('empty', 'twig_test_empty'), - new TwigTest('iterable', 'twig_test_iterable'), + new TwigTest('iterable', 'is_iterable'), ]; } @@ -284,6 +286,8 @@ final class CoreExtension extends AbstractExtension 'matches' => ['precedence' => 20, 'class' => MatchesBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT], 'starts with' => ['precedence' => 20, 'class' => StartsWithBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT], 'ends with' => ['precedence' => 20, 'class' => EndsWithBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT], + 'has some' => ['precedence' => 20, 'class' => HasSomeBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT], + 'has every' => ['precedence' => 20, 'class' => HasEveryBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT], '..' => ['precedence' => 25, 'class' => RangeBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT], '+' => ['precedence' => 30, 'class' => AddBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT], '-' => ['precedence' => 30, 'class' => SubBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT], @@ -339,9 +343,9 @@ function twig_cycle($values, $position) * @param \Traversable|array|int|float|string $values The values to pick a random item from * @param int|null $max Maximum value used when $values is an int * - * @throws RuntimeError when $values is an empty array (does not apply to an empty string which is returned as is) - * * @return mixed A random value from the given sequence + * + * @throws RuntimeError when $values is an empty array (does not apply to an empty string which is returned as is) */ function twig_random(Environment $env, $values = null, $max = null) { @@ -360,7 +364,6 @@ function twig_random(Environment $env, $values = null, $max = null) } } else { $min = $values; - $max = $max; } return mt_rand((int) $min, (int) $max); @@ -388,7 +391,7 @@ function twig_random(Environment $env, $values = null, $max = null) } } - if (!twig_test_iterable($values)) { + if (!is_iterable($values)) { return $values; } @@ -525,7 +528,7 @@ function twig_date_converter(Environment $env, $date = null, $timezone = null) */ function twig_replace_filter($str, $from) { - if (!twig_test_iterable($from)) { + 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))); } @@ -605,32 +608,34 @@ function twig_urlencode_filter($url) } /** - * Merges an array with another one. + * Merges any number of arrays or Traversable objects. * * {% set items = { 'apple': 'fruit', 'orange': 'fruit' } %} * - * {% set items = items|merge({ 'peugeot': 'car' }) %} + * {% set items = items|merge({ 'peugeot': 'car' }, { 'banana': 'fruit' }) %} * - * {# items now contains { 'apple': 'fruit', 'orange': 'fruit', 'peugeot': 'car' } #} + * {# items now contains { 'apple': 'fruit', 'orange': 'fruit', 'peugeot': 'car', 'banana': 'fruit' } #} * - * @param array|\Traversable $arr1 An array - * @param array|\Traversable $arr2 An array + * @param array|\Traversable ...$arrays Any number of arrays or Traversable objects to merge * * @return array The merged array */ -function twig_array_merge($arr1, $arr2) +function twig_array_merge(...$arrays) { - if (!twig_test_iterable($arr1)) { - throw new RuntimeError(sprintf('The merge filter only works with arrays or "Traversable", got "%s" as first argument.', \gettype($arr1))); + $result = []; + + 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)); + } + + $result = array_merge($result, twig_to_array($array)); } - if (!twig_test_iterable($arr2)) { - throw new RuntimeError(sprintf('The merge filter only works with arrays or "Traversable", got "%s" as second argument.', \gettype($arr2))); - } - - return array_merge(twig_to_array($arr1), twig_to_array($arr2)); + return $result; } + /** * Slices a variable. * @@ -650,7 +655,7 @@ function twig_slice(Environment $env, $item, $start, $length = null, $preserveKe if ($start >= 0 && $length >= 0 && $item instanceof \Iterator) { try { - return iterator_to_array(new \LimitIterator($item, $start, null === $length ? -1 : $length), $preserveKeys); + return iterator_to_array(new \LimitIterator($item, $start, $length ?? -1), $preserveKeys); } catch (\OutOfBoundsException $e) { return []; } @@ -663,7 +668,7 @@ function twig_slice(Environment $env, $item, $start, $length = null, $preserveKe return \array_slice($item, $start, $length, $preserveKeys); } - return (string) mb_substr((string) $item, $start, $length, $env->getCharset()); + return mb_substr((string) $item, $start, $length, $env->getCharset()); } /** @@ -716,7 +721,7 @@ function twig_last(Environment $env, $item) */ function twig_join_filter($value, $glue = '', $and = null) { - if (!twig_test_iterable($value)) { + if (!is_iterable($value)) { $value = (array) $value; } @@ -762,7 +767,7 @@ function twig_split_filter(Environment $env, $value, $delimiter, $limit = null) { $value = $value ?? ''; - if (\strlen($delimiter) > 0) { + if ('' !== $delimiter) { return null === $limit ? explode($delimiter, $value) : explode($delimiter, $value, $limit); } @@ -920,7 +925,7 @@ function twig_in_filter($value, $compare) if (\is_string($compare)) { if (\is_string($value) || \is_int($value) || \is_float($value)) { - return '' === $value || false !== strpos($compare, (string) $value); + return '' === $value || str_contains($compare, (string) $value); } return false; @@ -1015,6 +1020,23 @@ function twig_compare($a, $b) return $a <=> $b; } +/** + * @return int + * + * @throws RuntimeError When an invalid pattern is used + */ +function twig_matches(string $regexp, ?string $str) +{ + set_error_handler(function ($t, $m) use ($regexp) { + throw new RuntimeError(sprintf('Regexp "%s" passed to "matches" is not valid', $regexp).substr($m, 12)); + }); + try { + return preg_match($regexp, $str ?? ''); + } finally { + restore_error_handler(); + } +} + /** * Returns a trimmed string. * @@ -1097,7 +1119,7 @@ function twig_length_filter(Environment $env, $thing) return 0; } - if (is_scalar($thing)) { + if (\is_scalar($thing)) { return mb_strlen($thing, $env->getCharset()); } @@ -1207,7 +1229,7 @@ function twig_call_macro(Template $template, string $method, array $args, int $l */ function twig_ensure_traversable($seq) { - if ($seq instanceof \Traversable || \is_array($seq)) { + if (is_iterable($seq)) { return $seq; } @@ -1270,21 +1292,23 @@ function twig_test_empty($value) * @param mixed $value A variable * * @return bool true if the value is traversable + * + * @deprecated since Twig 3.8, to be removed in 4.0 (use the native "is_iterable" function instead) */ function twig_test_iterable($value) { - return $value instanceof \Traversable || \is_array($value); + return is_iterable($value); } /** * Renders a template. * - * @param array $context - * @param string|array $template The template to render or an array of templates to try consecutively - * @param array $variables The variables to pass to the template - * @param bool $withContext - * @param bool $ignoreMissing Whether to ignore missing templates or not - * @param bool $sandboxed Whether to sandbox the template or not + * @param array $context + * @param string|array|TemplateWrapper $template The template to render or an array of templates to try consecutively + * @param array $variables The variables to pass to the template + * @param bool $withContext + * @param bool $ignoreMissing Whether to ignore missing templates or not + * @param bool $sandboxed Whether to sandbox the template or not * * @return string The rendered template */ @@ -1366,6 +1390,10 @@ function twig_constant($constant, $object = null) $constant = \get_class($object).'::'.$constant; } + if (!\defined($constant)) { + throw new RuntimeError(sprintf('Constant "%s" is undefined.', $constant)); + } + return \constant($constant); } @@ -1401,7 +1429,7 @@ function twig_constant_is_defined($constant, $object = null) */ function twig_array_batch($items, $size, $fill = null, $preserveKeys = true) { - if (!twig_test_iterable($items)) { + 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))); } @@ -1543,13 +1571,13 @@ function twig_get_attribute(Environment $env, Source $source, $object, $item, ar $classCache[$method] = $method; $classCache[$lcName = $lcMethods[$i]] = $method; - if ('g' === $lcName[0] && 0 === strpos($lcName, 'get')) { + if ('g' === $lcName[0] && str_starts_with($lcName, 'get')) { $name = substr($method, 3); $lcName = substr($lcName, 3); - } elseif ('i' === $lcName[0] && 0 === strpos($lcName, 'is')) { + } elseif ('i' === $lcName[0] && str_starts_with($lcName, 'is')) { $name = substr($method, 2); $lcName = substr($lcName, 2); - } elseif ('h' === $lcName[0] && 0 === strpos($lcName, 'has')) { + } elseif ('h' === $lcName[0] && str_starts_with($lcName, 'has')) { $name = substr($method, 3); $lcName = substr($lcName, 3); if (\in_array('is'.$lcName, $lcMethods)) { @@ -1645,7 +1673,7 @@ function twig_array_column($array, $name, $index = null): array function twig_array_filter(Environment $env, $array, $arrow) { - if (!twig_test_iterable($array)) { + 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))); } @@ -1675,15 +1703,42 @@ function twig_array_reduce(Environment $env, $array, $arrow, $initial = null) { twig_check_arrow_in_sandbox($env, $arrow, 'reduce', 'filter'); - if (!\is_array($array)) { - if (!$array instanceof \Traversable) { - throw new RuntimeError(sprintf('The "reduce" filter only works with arrays or "Traversable", got "%s" as first argument.', \gettype($array))); - } - - $array = iterator_to_array($array); + 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))); } - return array_reduce($array, $arrow, $initial); + $accumulator = $initial; + foreach ($array as $key => $value) { + $accumulator = $arrow($accumulator, $value, $key); + } + + return $accumulator; +} + +function twig_array_some(Environment $env, $array, $arrow) +{ + twig_check_arrow_in_sandbox($env, $arrow, 'has some', 'operator'); + + foreach ($array as $k => $v) { + if ($arrow($v, $k)) { + return true; + } + } + + return false; +} + +function twig_array_every(Environment $env, $array, $arrow) +{ + twig_check_arrow_in_sandbox($env, $arrow, 'has every', 'operator'); + + foreach ($array as $k => $v) { + if (!$arrow($v, $k)) { + return false; + } + } + + return true; } function twig_check_arrow_in_sandbox(Environment $env, $arrow, $thing, $type) diff --git a/lib/twig/twig/src/Extension/DebugExtension.php b/lib/twig/twig/src/Extension/DebugExtension.php index bfb23d7bd..c0f10d5a3 100644 --- a/lib/twig/twig/src/Extension/DebugExtension.php +++ b/lib/twig/twig/src/Extension/DebugExtension.php @@ -19,10 +19,10 @@ final class DebugExtension extends AbstractExtension // dump is safe if var_dump is overridden by xdebug $isDumpOutputHtmlSafe = \extension_loaded('xdebug') // false means that it was not set (and the default is on) or it explicitly enabled - && (false === ini_get('xdebug.overload_var_dump') || ini_get('xdebug.overload_var_dump')) + && (false === \ini_get('xdebug.overload_var_dump') || \ini_get('xdebug.overload_var_dump')) // false means that it was not set (and the default is on) or it explicitly enabled // xdebug.overload_var_dump produces HTML only when html_errors is also enabled - && (false === ini_get('html_errors') || ini_get('html_errors')) + && (false === \ini_get('html_errors') || \ini_get('html_errors')) || 'cli' === \PHP_SAPI ; diff --git a/lib/twig/twig/src/Extension/EscaperExtension.php b/lib/twig/twig/src/Extension/EscaperExtension.php index 9d2251dc6..ef8879dbd 100644 --- a/lib/twig/twig/src/Extension/EscaperExtension.php +++ b/lib/twig/twig/src/Extension/EscaperExtension.php @@ -341,7 +341,7 @@ function twig_escape_filter(Environment $env, $string, $strategy = 'html', $char * The following replaces characters undefined in HTML with the * hex entity for the Unicode replacement character. */ - if (($ord <= 0x1f && "\t" != $chr && "\n" != $chr && "\r" != $chr) || ($ord >= 0x7f && $ord <= 0x9f)) { + if (($ord <= 0x1F && "\t" != $chr && "\n" != $chr && "\r" != $chr) || ($ord >= 0x7F && $ord <= 0x9F)) { return '�'; } @@ -388,7 +388,7 @@ function twig_escape_filter(Environment $env, $string, $strategy = 'html', $char default: $escapers = $env->getExtension(EscaperExtension::class)->getEscapers(); - if (array_key_exists($strategy, $escapers)) { + if (\array_key_exists($strategy, $escapers)) { return $escapers[$strategy]($env, $string, $charset); } diff --git a/lib/twig/twig/src/Extension/ExtensionInterface.php b/lib/twig/twig/src/Extension/ExtensionInterface.php index 75fa237e1..ab9c2c37c 100644 --- a/lib/twig/twig/src/Extension/ExtensionInterface.php +++ b/lib/twig/twig/src/Extension/ExtensionInterface.php @@ -11,6 +11,9 @@ namespace Twig\Extension; +use Twig\ExpressionParser; +use Twig\Node\Expression\Binary\AbstractBinary; +use Twig\Node\Expression\Unary\AbstractUnary; use Twig\NodeVisitor\NodeVisitorInterface; use Twig\TokenParser\TokenParserInterface; use Twig\TwigFilter; @@ -63,6 +66,11 @@ interface ExtensionInterface * Returns a list of operators to add to the existing list. * * @return array First array of unary operators, second array of binary operators + * + * @psalm-return array{ + * array}>, + * array, associativity: ExpressionParser::OPERATOR_*}> + * } */ public function getOperators(); } diff --git a/lib/twig/twig/src/Extension/GlobalsInterface.php b/lib/twig/twig/src/Extension/GlobalsInterface.php index ec0c68292..6f1dfe8a7 100644 --- a/lib/twig/twig/src/Extension/GlobalsInterface.php +++ b/lib/twig/twig/src/Extension/GlobalsInterface.php @@ -21,5 +21,8 @@ namespace Twig\Extension; */ interface GlobalsInterface { + /** + * @return array + */ public function getGlobals(): array; } diff --git a/lib/twig/twig/src/ExtensionSet.php b/lib/twig/twig/src/ExtensionSet.php index 36e5bbc59..d32200ceb 100644 --- a/lib/twig/twig/src/ExtensionSet.php +++ b/lib/twig/twig/src/ExtensionSet.php @@ -15,6 +15,8 @@ use Twig\Error\RuntimeError; use Twig\Extension\ExtensionInterface; use Twig\Extension\GlobalsInterface; use Twig\Extension\StagingExtension; +use Twig\Node\Expression\Binary\AbstractBinary; +use Twig\Node\Expression\Unary\AbstractUnary; use Twig\NodeVisitor\NodeVisitorInterface; use Twig\TokenParser\TokenParserInterface; @@ -31,11 +33,17 @@ final class ExtensionSet private $staging; private $parsers; private $visitors; + /** @var array */ private $filters; + /** @var array */ private $tests; + /** @var array */ private $functions; + /** @var array}> */ private $unaryOperators; + /** @var array, associativity: ExpressionParser::OPERATOR_*}> */ private $binaryOperators; + /** @var array */ private $globals; private $functionCallbacks = []; private $filterCallbacks = []; @@ -305,6 +313,9 @@ final class ExtensionSet $this->parserCallbacks[] = $callable; } + /** + * @return array + */ public function getGlobals(): array { if (null !== $this->globals) { @@ -379,6 +390,9 @@ final class ExtensionSet return null; } + /** + * @return array}> + */ public function getUnaryOperators(): array { if (!$this->initialized) { @@ -388,6 +402,9 @@ final class ExtensionSet return $this->unaryOperators; } + /** + * @return array, associativity: ExpressionParser::OPERATOR_*}> + */ public function getBinaryOperators(): array { if (!$this->initialized) { diff --git a/lib/twig/twig/src/FileExtensionEscapingStrategy.php b/lib/twig/twig/src/FileExtensionEscapingStrategy.php index 65198bbb6..812071bf9 100644 --- a/lib/twig/twig/src/FileExtensionEscapingStrategy.php +++ b/lib/twig/twig/src/FileExtensionEscapingStrategy.php @@ -37,7 +37,7 @@ class FileExtensionEscapingStrategy return 'html'; // return html for directories } - if ('.twig' === substr($name, -5)) { + if (str_ends_with($name, '.twig')) { $name = substr($name, 0, -5); } diff --git a/lib/twig/twig/src/Lexer.php b/lib/twig/twig/src/Lexer.php index 9ff028c87..b23080f58 100644 --- a/lib/twig/twig/src/Lexer.php +++ b/lib/twig/twig/src/Lexer.php @@ -19,6 +19,8 @@ use Twig\Error\SyntaxError; */ class Lexer { + private $isInitialized = false; + private $tokens; private $code; private $cursor; @@ -61,6 +63,15 @@ class Lexer 'whitespace_line_chars' => ' \t\0\x0B', 'interpolation' => ['#{', '}'], ], $options); + } + + private function initialize() + { + if ($this->isInitialized) { + return; + } + + $this->isInitialized = true; // when PHP 7.3 is the min version, we will be able to remove the '#' part in preg_quote as it's part of the default $this->regexes = [ @@ -153,6 +164,8 @@ class Lexer public function tokenize(Source $source): TokenStream { + $this->initialize(); + $this->source = $source; $this->code = str_replace(["\r\n", "\r"], "\n", $source->getCode()); $this->cursor = 0; @@ -302,8 +315,13 @@ class Lexer } } + // spread operator + if ('.' === $this->code[$this->cursor] && ($this->cursor + 2 < $this->end) && '.' === $this->code[$this->cursor + 1] && '.' === $this->code[$this->cursor + 2]) { + $this->pushToken(Token::SPREAD_TYPE, '...'); + $this->moveCursor('...'); + } // arrow function - if ('=' === $this->code[$this->cursor] && '>' === $this->code[$this->cursor + 1]) { + elseif ('=' === $this->code[$this->cursor] && '>' === $this->code[$this->cursor + 1]) { $this->pushToken(Token::ARROW_TYPE, '=>'); $this->moveCursor('=>'); } @@ -327,13 +345,13 @@ class Lexer $this->moveCursor($match[0]); } // punctuation - elseif (false !== strpos(self::PUNCTUATION, $this->code[$this->cursor])) { + elseif (str_contains(self::PUNCTUATION, $this->code[$this->cursor])) { // opening bracket - if (false !== strpos('([{', $this->code[$this->cursor])) { + if (str_contains('([{', $this->code[$this->cursor])) { $this->brackets[] = [$this->code[$this->cursor], $this->lineno]; } // closing bracket - elseif (false !== strpos(')]}', $this->code[$this->cursor])) { + 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); } @@ -404,7 +422,7 @@ class Lexer $this->pushToken(/* Token::INTERPOLATION_START_TYPE */ 10); $this->moveCursor($match[0]); $this->pushState(self::STATE_INTERPOLATION); - } elseif (preg_match(self::REGEX_DQ_STRING_PART, $this->code, $match, 0, $this->cursor) && \strlen($match[0]) > 0) { + } elseif (preg_match(self::REGEX_DQ_STRING_PART, $this->code, $match, 0, $this->cursor) && '' !== $match[0]) { $this->pushToken(/* Token::STRING_TYPE */ 7, stripcslashes($match[0])); $this->moveCursor($match[0]); } elseif (preg_match(self::REGEX_DQ_STRING_DELIM, $this->code, $match, 0, $this->cursor)) { diff --git a/lib/twig/twig/src/Loader/FilesystemLoader.php b/lib/twig/twig/src/Loader/FilesystemLoader.php index 62267a11c..1073a406a 100644 --- a/lib/twig/twig/src/Loader/FilesystemLoader.php +++ b/lib/twig/twig/src/Loader/FilesystemLoader.php @@ -36,7 +36,7 @@ class FilesystemLoader implements LoaderInterface */ public function __construct($paths = [], string $rootPath = null) { - $this->rootPath = (null === $rootPath ? getcwd() : $rootPath).\DIRECTORY_SEPARATOR; + $this->rootPath = ($rootPath ?? getcwd()).\DIRECTORY_SEPARATOR; if (null !== $rootPath && false !== ($realPath = realpath($rootPath))) { $this->rootPath = $realPath.\DIRECTORY_SEPARATOR; } @@ -250,7 +250,7 @@ class FilesystemLoader implements LoaderInterface private function validateName(string $name): void { - if (false !== strpos($name, "\0")) { + if (str_contains($name, "\0")) { throw new LoaderError('A template name cannot contain NUL bytes.'); } diff --git a/lib/twig/twig/src/Node/Expression/ArrayExpression.php b/lib/twig/twig/src/Node/Expression/ArrayExpression.php index 0e25fe46a..444283802 100644 --- a/lib/twig/twig/src/Node/Expression/ArrayExpression.php +++ b/lib/twig/twig/src/Node/Expression/ArrayExpression.php @@ -66,20 +66,70 @@ class ArrayExpression extends AbstractExpression public function compile(Compiler $compiler): void { + $keyValuePairs = $this->getKeyValuePairs(); + $needsArrayMergeSpread = \PHP_VERSION_ID < 80100 && $this->hasSpreadItem($keyValuePairs); + + if ($needsArrayMergeSpread) { + $compiler->raw('twig_array_merge('); + } $compiler->raw('['); $first = true; - foreach ($this->getKeyValuePairs() as $pair) { + $reopenAfterMergeSpread = false; + $nextIndex = 0; + foreach ($keyValuePairs as $pair) { + if ($reopenAfterMergeSpread) { + $compiler->raw(', ['); + $reopenAfterMergeSpread = false; + } + + if ($needsArrayMergeSpread && $pair['value']->hasAttribute('spread')) { + $compiler->raw('], ')->subcompile($pair['value']); + $first = true; + $reopenAfterMergeSpread = true; + continue; + } if (!$first) { $compiler->raw(', '); } $first = false; - $compiler - ->subcompile($pair['key']) - ->raw(' => ') - ->subcompile($pair['value']) - ; + if ($pair['value']->hasAttribute('spread') && !$needsArrayMergeSpread) { + $compiler->raw('...')->subcompile($pair['value']); + ++$nextIndex; + } else { + $key = $pair['key'] instanceof ConstantExpression ? $pair['key']->getAttribute('value') : null; + + if ($nextIndex !== $key) { + if (\is_int($key)) { + $nextIndex = $key + 1; + } + $compiler + ->subcompile($pair['key']) + ->raw(' => ') + ; + } else { + ++$nextIndex; + } + + $compiler->subcompile($pair['value']); + } } - $compiler->raw(']'); + if (!$reopenAfterMergeSpread) { + $compiler->raw(']'); + } + if ($needsArrayMergeSpread) { + $compiler->raw(')'); + } + } + + private function hasSpreadItem(array $pairs): bool + { + foreach ($pairs as $pair) { + if ($pair['value']->hasAttribute('spread')) { + return true; + } + } + + return false; } } diff --git a/lib/twig/twig/src/Node/Expression/Binary/EndsWithBinary.php b/lib/twig/twig/src/Node/Expression/Binary/EndsWithBinary.php index c3516b853..73fa20b1f 100644 --- a/lib/twig/twig/src/Node/Expression/Binary/EndsWithBinary.php +++ b/lib/twig/twig/src/Node/Expression/Binary/EndsWithBinary.php @@ -24,7 +24,7 @@ class EndsWithBinary extends AbstractBinary ->subcompile($this->getNode('left')) ->raw(sprintf(') && is_string($%s = ', $right)) ->subcompile($this->getNode('right')) - ->raw(sprintf(') && (\'\' === $%2$s || $%2$s === substr($%1$s, -strlen($%2$s))))', $left, $right)) + ->raw(sprintf(') && str_ends_with($%1$s, $%2$s))', $left, $right)) ; } diff --git a/lib/twig/twig/src/Node/Expression/Binary/HasEveryBinary.php b/lib/twig/twig/src/Node/Expression/Binary/HasEveryBinary.php new file mode 100644 index 000000000..adfabd44c --- /dev/null +++ b/lib/twig/twig/src/Node/Expression/Binary/HasEveryBinary.php @@ -0,0 +1,33 @@ +raw('twig_array_every($this->env, ') + ->subcompile($this->getNode('left')) + ->raw(', ') + ->subcompile($this->getNode('right')) + ->raw(')') + ; + } + + public function operator(Compiler $compiler): Compiler + { + return $compiler->raw(''); + } +} diff --git a/lib/twig/twig/src/Node/Expression/Binary/HasSomeBinary.php b/lib/twig/twig/src/Node/Expression/Binary/HasSomeBinary.php new file mode 100644 index 000000000..270da3692 --- /dev/null +++ b/lib/twig/twig/src/Node/Expression/Binary/HasSomeBinary.php @@ -0,0 +1,33 @@ +raw('twig_array_some($this->env, ') + ->subcompile($this->getNode('left')) + ->raw(', ') + ->subcompile($this->getNode('right')) + ->raw(')') + ; + } + + public function operator(Compiler $compiler): Compiler + { + return $compiler->raw(''); + } +} diff --git a/lib/twig/twig/src/Node/Expression/Binary/MatchesBinary.php b/lib/twig/twig/src/Node/Expression/Binary/MatchesBinary.php index bc97292cd..a8bce6f4e 100644 --- a/lib/twig/twig/src/Node/Expression/Binary/MatchesBinary.php +++ b/lib/twig/twig/src/Node/Expression/Binary/MatchesBinary.php @@ -18,7 +18,7 @@ class MatchesBinary extends AbstractBinary public function compile(Compiler $compiler): void { $compiler - ->raw('preg_match(') + ->raw('twig_matches(') ->subcompile($this->getNode('right')) ->raw(', ') ->subcompile($this->getNode('left')) diff --git a/lib/twig/twig/src/Node/Expression/Binary/StartsWithBinary.php b/lib/twig/twig/src/Node/Expression/Binary/StartsWithBinary.php index d0df1c4b6..22eff92a7 100644 --- a/lib/twig/twig/src/Node/Expression/Binary/StartsWithBinary.php +++ b/lib/twig/twig/src/Node/Expression/Binary/StartsWithBinary.php @@ -24,7 +24,7 @@ class StartsWithBinary extends AbstractBinary ->subcompile($this->getNode('left')) ->raw(sprintf(') && is_string($%s = ', $right)) ->subcompile($this->getNode('right')) - ->raw(sprintf(') && (\'\' === $%2$s || 0 === strpos($%1$s, $%2$s)))', $left, $right)) + ->raw(sprintf(') && str_starts_with($%1$s, $%2$s))', $left, $right)) ; } diff --git a/lib/twig/twig/src/Node/Expression/CallExpression.php b/lib/twig/twig/src/Node/Expression/CallExpression.php index 28881066b..3a2d7a4fc 100644 --- a/lib/twig/twig/src/Node/Expression/CallExpression.php +++ b/lib/twig/twig/src/Node/Expression/CallExpression.php @@ -24,7 +24,7 @@ abstract class CallExpression extends AbstractExpression { $callable = $this->getAttribute('callable'); - if (\is_string($callable) && false === strpos($callable, '::')) { + if (\is_string($callable) && !str_contains($callable, '::')) { $compiler->raw($callable); } else { [$r, $callable] = $this->reflectCallable($callable); @@ -297,14 +297,16 @@ abstract class CallExpression extends AbstractExpression } $r = new \ReflectionFunction($closure); - if (false !== strpos($r->name, '{closure}')) { + if (str_contains($r->name, '{closure}')) { return $this->reflector = [$r, $callable, 'Closure']; } if ($object = $r->getClosureThis()) { $callable = [$object, $r->name]; - $callableName = (\function_exists('get_debug_type') ? get_debug_type($object) : \get_class($object)).'::'.$r->name; - } elseif ($class = $r->getClosureScopeClass()) { + $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; diff --git a/lib/twig/twig/src/Node/Expression/ConditionalExpression.php b/lib/twig/twig/src/Node/Expression/ConditionalExpression.php index 2c7bd0a27..d7db99357 100644 --- a/lib/twig/twig/src/Node/Expression/ConditionalExpression.php +++ b/lib/twig/twig/src/Node/Expression/ConditionalExpression.php @@ -23,14 +23,23 @@ class ConditionalExpression extends AbstractExpression public function compile(Compiler $compiler): void { - $compiler - ->raw('((') - ->subcompile($this->getNode('expr1')) - ->raw(') ? (') - ->subcompile($this->getNode('expr2')) - ->raw(') : (') - ->subcompile($this->getNode('expr3')) - ->raw('))') - ; + // Ternary with no then uses Elvis operator + if ($this->getNode('expr1') === $this->getNode('expr2')) { + $compiler + ->raw('((') + ->subcompile($this->getNode('expr1')) + ->raw(') ?: (') + ->subcompile($this->getNode('expr3')) + ->raw('))'); + } else { + $compiler + ->raw('((') + ->subcompile($this->getNode('expr1')) + ->raw(') ? (') + ->subcompile($this->getNode('expr2')) + ->raw(') : (') + ->subcompile($this->getNode('expr3')) + ->raw('))'); + } } } diff --git a/lib/twig/twig/src/Node/IfNode.php b/lib/twig/twig/src/Node/IfNode.php index 5fa20082a..569ab7950 100644 --- a/lib/twig/twig/src/Node/IfNode.php +++ b/lib/twig/twig/src/Node/IfNode.php @@ -50,8 +50,11 @@ class IfNode extends Node ->subcompile($this->getNode('tests')->getNode($i)) ->raw(") {\n") ->indent() - ->subcompile($this->getNode('tests')->getNode($i + 1)) ; + // The node might not exists if the content is empty + if ($this->getNode('tests')->hasNode($i + 1)) { + $compiler->subcompile($this->getNode('tests')->getNode($i + 1)); + } } if ($this->hasNode('else')) { diff --git a/lib/twig/twig/src/Node/ModuleNode.php b/lib/twig/twig/src/Node/ModuleNode.php index e972b6ba5..9b485eeaf 100644 --- a/lib/twig/twig/src/Node/ModuleNode.php +++ b/lib/twig/twig/src/Node/ModuleNode.php @@ -355,6 +355,9 @@ final class ModuleNode extends Node protected function compileGetTemplateName(Compiler $compiler) { $compiler + ->write("/**\n") + ->write(" * @codeCoverageIgnore\n") + ->write(" */\n") ->write("public function getTemplateName()\n", "{\n") ->indent() ->write('return ') @@ -409,6 +412,9 @@ final class ModuleNode extends Node } $compiler + ->write("/**\n") + ->write(" * @codeCoverageIgnore\n") + ->write(" */\n") ->write("public function isTraitable()\n", "{\n") ->indent() ->write(sprintf("return %s;\n", $traitable ? 'true' : 'false')) @@ -420,6 +426,9 @@ final class ModuleNode extends Node protected function compileDebugInfo(Compiler $compiler) { $compiler + ->write("/**\n") + ->write(" * @codeCoverageIgnore\n") + ->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)))) diff --git a/lib/twig/twig/src/Node/Node.php b/lib/twig/twig/src/Node/Node.php index c0558b9af..30659ae0f 100644 --- a/lib/twig/twig/src/Node/Node.php +++ b/lib/twig/twig/src/Node/Node.php @@ -27,7 +27,6 @@ class Node implements \Countable, \IteratorAggregate protected $lineno; protected $tag; - private $name; private $sourceContext; /** diff --git a/lib/twig/twig/src/Node/WithNode.php b/lib/twig/twig/src/Node/WithNode.php index 56a334496..2ac9123d0 100644 --- a/lib/twig/twig/src/Node/WithNode.php +++ b/lib/twig/twig/src/Node/WithNode.php @@ -45,7 +45,7 @@ class WithNode extends Node ->write(sprintf('$%s = ', $varsName)) ->subcompile($node) ->raw(";\n") - ->write(sprintf("if (!twig_test_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.', ") ->repr($node->getTemplateLine()) diff --git a/lib/twig/twig/src/NodeVisitor/EscaperNodeVisitor.php b/lib/twig/twig/src/NodeVisitor/EscaperNodeVisitor.php index fe56ea307..c390d7cc7 100644 --- a/lib/twig/twig/src/NodeVisitor/EscaperNodeVisitor.php +++ b/lib/twig/twig/src/NodeVisitor/EscaperNodeVisitor.php @@ -57,7 +57,7 @@ final class EscaperNodeVisitor implements NodeVisitorInterface } elseif ($node instanceof AutoEscapeNode) { $this->statusStack[] = $node->getAttribute('value'); } elseif ($node instanceof BlockNode) { - $this->statusStack[] = isset($this->blocks[$node->getAttribute('name')]) ? $this->blocks[$node->getAttribute('name')] : $this->needEscaping($env); + $this->statusStack[] = $this->blocks[$node->getAttribute('name')] ?? $this->needEscaping(); } elseif ($node instanceof ImportNode) { $this->safeVars[] = $node->getNode('var')->getAttribute('name'); } @@ -73,7 +73,7 @@ final class EscaperNodeVisitor implements NodeVisitorInterface $this->blocks = []; } elseif ($node instanceof FilterExpression) { return $this->preEscapeFilterNode($node, $env); - } elseif ($node instanceof PrintNode && false !== $type = $this->needEscaping($env)) { + } elseif ($node instanceof PrintNode && false !== $type = $this->needEscaping()) { $expression = $node->getNode('expr'); if ($expression instanceof ConditionalExpression && $this->shouldUnwrapConditional($expression, $env, $type)) { return new DoNode($this->unwrapConditional($expression, $env, $type), $expression->getTemplateLine()); @@ -85,7 +85,7 @@ final class EscaperNodeVisitor implements NodeVisitorInterface if ($node instanceof AutoEscapeNode || $node instanceof BlockNode) { array_pop($this->statusStack); } elseif ($node instanceof BlockReferenceNode) { - $this->blocks[$node->getAttribute('name')] = $this->needEscaping($env); + $this->blocks[$node->getAttribute('name')] = $this->needEscaping(); } return $node; @@ -183,13 +183,13 @@ final class EscaperNodeVisitor implements NodeVisitorInterface return \in_array($type, $safe) || \in_array('all', $safe); } - private function needEscaping(Environment $env) + private function needEscaping() { if (\count($this->statusStack)) { return $this->statusStack[\count($this->statusStack) - 1]; } - return $this->defaultStrategy ? $this->defaultStrategy : false; + return $this->defaultStrategy ?: false; } private function getEscaperFilter(string $type, Node $node): FilterExpression diff --git a/lib/twig/twig/src/NodeVisitor/MacroAutoImportNodeVisitor.php b/lib/twig/twig/src/NodeVisitor/MacroAutoImportNodeVisitor.php index af477e653..d6a7781ba 100644 --- a/lib/twig/twig/src/NodeVisitor/MacroAutoImportNodeVisitor.php +++ b/lib/twig/twig/src/NodeVisitor/MacroAutoImportNodeVisitor.php @@ -50,10 +50,10 @@ final class MacroAutoImportNodeVisitor implements NodeVisitorInterface } } elseif ($this->inAModule) { if ( - $node instanceof GetAttrExpression && - $node->getNode('node') instanceof NameExpression && - '_self' === $node->getNode('node')->getAttribute('name') && - $node->getNode('attribute') instanceof ConstantExpression + $node instanceof GetAttrExpression + && $node->getNode('node') instanceof NameExpression + && '_self' === $node->getNode('node')->getAttribute('name') + && $node->getNode('attribute') instanceof ConstantExpression ) { $this->hasMacroCalls = true; diff --git a/lib/twig/twig/src/NodeVisitor/OptimizerNodeVisitor.php b/lib/twig/twig/src/NodeVisitor/OptimizerNodeVisitor.php index 7ac75e41a..6b39f0094 100644 --- a/lib/twig/twig/src/NodeVisitor/OptimizerNodeVisitor.php +++ b/lib/twig/twig/src/NodeVisitor/OptimizerNodeVisitor.php @@ -63,7 +63,7 @@ final class OptimizerNodeVisitor implements NodeVisitorInterface public function enterNode(Node $node, Environment $env): Node { if (self::OPTIMIZE_FOR === (self::OPTIMIZE_FOR & $this->optimizers)) { - $this->enterOptimizeFor($node, $env); + $this->enterOptimizeFor($node); } return $node; @@ -72,14 +72,14 @@ final class OptimizerNodeVisitor implements NodeVisitorInterface public function leaveNode(Node $node, Environment $env): ?Node { if (self::OPTIMIZE_FOR === (self::OPTIMIZE_FOR & $this->optimizers)) { - $this->leaveOptimizeFor($node, $env); + $this->leaveOptimizeFor($node); } if (self::OPTIMIZE_RAW_FILTER === (self::OPTIMIZE_RAW_FILTER & $this->optimizers)) { - $node = $this->optimizeRawFilter($node, $env); + $node = $this->optimizeRawFilter($node); } - $node = $this->optimizePrintNode($node, $env); + $node = $this->optimizePrintNode($node); return $node; } @@ -91,7 +91,7 @@ final class OptimizerNodeVisitor implements NodeVisitorInterface * * * "echo $this->render(Parent)Block()" with "$this->display(Parent)Block()" */ - private function optimizePrintNode(Node $node, Environment $env): Node + private function optimizePrintNode(Node $node): Node { if (!$node instanceof PrintNode) { return $node; @@ -99,8 +99,8 @@ final class OptimizerNodeVisitor implements NodeVisitorInterface $exprNode = $node->getNode('expr'); if ( - $exprNode instanceof BlockReferenceExpression || - $exprNode instanceof ParentExpression + $exprNode instanceof BlockReferenceExpression + || $exprNode instanceof ParentExpression ) { $exprNode->setAttribute('output', true); @@ -113,7 +113,7 @@ final class OptimizerNodeVisitor implements NodeVisitorInterface /** * Removes "raw" filters. */ - private function optimizeRawFilter(Node $node, Environment $env): Node + private function optimizeRawFilter(Node $node): Node { if ($node instanceof FilterExpression && 'raw' == $node->getNode('filter')->getAttribute('value')) { return $node->getNode('node'); @@ -125,7 +125,7 @@ final class OptimizerNodeVisitor implements NodeVisitorInterface /** * Optimizes "for" tag by removing the "loop" variable creation whenever possible. */ - private function enterOptimizeFor(Node $node, Environment $env): void + private function enterOptimizeFor(Node $node): void { if ($node instanceof ForNode) { // disable the loop variable by default @@ -166,7 +166,7 @@ final class OptimizerNodeVisitor implements NodeVisitorInterface && 'include' === $node->getAttribute('name') && (!$node->getNode('arguments')->hasNode('with_context') || false !== $node->getNode('arguments')->getNode('with_context')->getAttribute('value') - ) + ) ) { $this->addLoopToAll(); } @@ -175,12 +175,12 @@ final class OptimizerNodeVisitor implements NodeVisitorInterface elseif ($node instanceof GetAttrExpression && (!$node->getNode('attribute') instanceof ConstantExpression || 'parent' === $node->getNode('attribute')->getAttribute('value') - ) + ) && (true === $this->loops[0]->getAttribute('with_loop') - || ($node->getNode('node') instanceof NameExpression - && 'loop' === $node->getNode('node')->getAttribute('name') - ) - ) + || ($node->getNode('node') instanceof NameExpression + && 'loop' === $node->getNode('node')->getAttribute('name') + ) + ) ) { $this->addLoopToAll(); } @@ -189,7 +189,7 @@ final class OptimizerNodeVisitor implements NodeVisitorInterface /** * Optimizes "for" tag by removing the "loop" variable creation whenever possible. */ - private function leaveOptimizeFor(Node $node, Environment $env): void + private function leaveOptimizeFor(Node $node): void { if ($node instanceof ForNode) { array_shift($this->loops); diff --git a/lib/twig/twig/src/Parser.php b/lib/twig/twig/src/Parser.php index 4428208fe..4016a5f39 100644 --- a/lib/twig/twig/src/Parser.php +++ b/lib/twig/twig/src/Parser.php @@ -303,10 +303,9 @@ class Parser // check that the body does not contain non-empty output nodes if ( ($node instanceof TextNode && !ctype_space($node->getAttribute('data'))) - || - (!$node instanceof TextNode && !$node instanceof BlockReferenceNode && $node instanceof NodeOutputInterface) + || (!$node instanceof TextNode && !$node instanceof BlockReferenceNode && $node instanceof NodeOutputInterface) ) { - if (false !== strpos((string) $node, \chr(0xEF).\chr(0xBB).\chr(0xBF))) { + if (str_contains((string) $node, \chr(0xEF).\chr(0xBB).\chr(0xBF))) { $t = substr($node->getAttribute('data'), 3); if ('' === $t || ctype_space($t)) { // bypass empty nodes starting with a BOM diff --git a/lib/twig/twig/src/Profiler/Dumper/HtmlDumper.php b/lib/twig/twig/src/Profiler/Dumper/HtmlDumper.php index 1f2433b4d..3c0daf1c8 100644 --- a/lib/twig/twig/src/Profiler/Dumper/HtmlDumper.php +++ b/lib/twig/twig/src/Profiler/Dumper/HtmlDumper.php @@ -37,7 +37,7 @@ final class HtmlDumper extends BaseDumper protected function formatNonTemplate(Profile $profile, $prefix): string { - return sprintf('%s└ %s::%s(%s)', $prefix, $profile->getTemplate(), $profile->getType(), isset(self::$colors[$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 diff --git a/lib/twig/twig/src/Profiler/Profile.php b/lib/twig/twig/src/Profiler/Profile.php index 252ca9b0c..7979a23c6 100644 --- a/lib/twig/twig/src/Profiler/Profile.php +++ b/lib/twig/twig/src/Profiler/Profile.php @@ -32,7 +32,7 @@ final class Profile implements \IteratorAggregate, \Serializable { $this->template = $template; $this->type = $type; - $this->name = 0 === strpos($name, '__internal_') ? 'INTERNAL' : $name; + $this->name = str_starts_with($name, '__internal_') ? 'INTERNAL' : $name; $this->enter(); } diff --git a/lib/twig/twig/src/Sandbox/SecurityPolicy.php b/lib/twig/twig/src/Sandbox/SecurityPolicy.php index 2fc0d0131..a725aa4f1 100644 --- a/lib/twig/twig/src/Sandbox/SecurityPolicy.php +++ b/lib/twig/twig/src/Sandbox/SecurityPolicy.php @@ -94,9 +94,8 @@ final class SecurityPolicy implements SecurityPolicyInterface $allowed = false; $method = strtr($method, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'); foreach ($this->allowedMethods as $class => $methods) { - if ($obj instanceof $class) { - $allowed = \in_array($method, $methods); - + if ($obj instanceof $class && \in_array($method, $methods)) { + $allowed = true; break; } } @@ -111,9 +110,8 @@ final class SecurityPolicy implements SecurityPolicyInterface { $allowed = false; foreach ($this->allowedProperties as $class => $properties) { - if ($obj instanceof $class) { - $allowed = \in_array($property, \is_array($properties) ? $properties : [$properties]); - + if ($obj instanceof $class && \in_array($property, \is_array($properties) ? $properties : [$properties])) { + $allowed = true; break; } } diff --git a/lib/twig/twig/src/Template.php b/lib/twig/twig/src/Template.php index e04bd04a6..ffbaae1ea 100644 --- a/lib/twig/twig/src/Template.php +++ b/lib/twig/twig/src/Template.php @@ -181,7 +181,7 @@ abstract class Template } throw $e; - } catch (\Exception $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->guess(); @@ -404,7 +404,7 @@ abstract class Template } throw $e; - } catch (\Exception $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->guess(); diff --git a/lib/twig/twig/src/TemplateWrapper.php b/lib/twig/twig/src/TemplateWrapper.php index c9c6b07c6..1ecd82251 100644 --- a/lib/twig/twig/src/TemplateWrapper.php +++ b/lib/twig/twig/src/TemplateWrapper.php @@ -35,9 +35,7 @@ final class TemplateWrapper public function render(array $context = []): string { - // using func_get_args() allows to not expose the blocks argument - // as it should only be used by internal code - return $this->template->render($context, \func_get_args()[1] ?? []); + return $this->template->render($context); } public function display(array $context = []) diff --git a/lib/twig/twig/src/Token.php b/lib/twig/twig/src/Token.php index 53a6cafc3..59279b8fe 100644 --- a/lib/twig/twig/src/Token.php +++ b/lib/twig/twig/src/Token.php @@ -35,6 +35,7 @@ final class Token public const INTERPOLATION_START_TYPE = 10; public const INTERPOLATION_END_TYPE = 11; public const ARROW_TYPE = 12; + public const SPREAD_TYPE = 13; public function __construct(int $type, $value, int $lineno) { @@ -67,9 +68,9 @@ final class Token } return ($this->type === $type) && ( - null === $values || - (\is_array($values) && \in_array($this->value, $values)) || - $this->value == $values + null === $values + || (\is_array($values) && \in_array($this->value, $values)) + || $this->value == $values ); } @@ -133,6 +134,9 @@ final class Token case self::ARROW_TYPE: $name = 'ARROW_TYPE'; break; + case self::SPREAD_TYPE: + $name = 'SPREAD_TYPE'; + break; default: throw new \LogicException(sprintf('Token of type "%s" does not exist.', $type)); } @@ -171,6 +175,8 @@ final class Token return 'end of string interpolation'; case self::ARROW_TYPE: return 'arrow function'; + case self::SPREAD_TYPE: + return 'spread operator'; default: throw new \LogicException(sprintf('Token of type "%s" does not exist.', $type)); } diff --git a/lib/twig/twig/src/TokenParser/FromTokenParser.php b/lib/twig/twig/src/TokenParser/FromTokenParser.php index 35098c267..31b6cde41 100644 --- a/lib/twig/twig/src/TokenParser/FromTokenParser.php +++ b/lib/twig/twig/src/TokenParser/FromTokenParser.php @@ -32,7 +32,7 @@ final class FromTokenParser extends AbstractTokenParser $stream->expect(/* Token::NAME_TYPE */ 5, 'import'); $targets = []; - do { + while (true) { $name = $stream->expect(/* Token::NAME_TYPE */ 5)->getValue(); $alias = $name; @@ -45,7 +45,7 @@ final class FromTokenParser extends AbstractTokenParser if (!$stream->nextIf(/* Token::PUNCTUATION_TYPE */ 9, ',')) { break; } - } while (true); + } $stream->expect(/* Token::BLOCK_END_TYPE */ 3); diff --git a/lib/twig/twig/src/TokenParser/UseTokenParser.php b/lib/twig/twig/src/TokenParser/UseTokenParser.php index d0a2de41a..3cdbb98ad 100644 --- a/lib/twig/twig/src/TokenParser/UseTokenParser.php +++ b/lib/twig/twig/src/TokenParser/UseTokenParser.php @@ -43,7 +43,7 @@ final class UseTokenParser extends AbstractTokenParser $targets = []; if ($stream->nextIf('with')) { - do { + while (true) { $name = $stream->expect(/* Token::NAME_TYPE */ 5)->getValue(); $alias = $name; @@ -56,7 +56,7 @@ final class UseTokenParser extends AbstractTokenParser if (!$stream->nextIf(/* Token::PUNCTUATION_TYPE */ 9, ',')) { break; } - } while (true); + } } $stream->expect(/* Token::BLOCK_END_TYPE */ 3); diff --git a/lib/twig/twig/src/TwigFilter.php b/lib/twig/twig/src/TwigFilter.php index 94e5f9b01..8993026c8 100644 --- a/lib/twig/twig/src/TwigFilter.php +++ b/lib/twig/twig/src/TwigFilter.php @@ -29,7 +29,7 @@ final class TwigFilter private $arguments = []; /** - * @param callable|null $callable A callable implementing the filter. If null, you need to overwrite the "node_class" option to customize compilation. + * @param callable|array{class-string, string}|null $callable A callable implementing the filter. If null, you need to overwrite the "node_class" option to customize compilation. */ public function __construct(string $name, $callable = null, array $options = []) { @@ -57,7 +57,7 @@ final class TwigFilter /** * Returns the callable to execute for this filter. * - * @return callable|null + * @return callable|array{class-string, string}|null */ public function getCallable() { diff --git a/lib/twig/twig/src/TwigFunction.php b/lib/twig/twig/src/TwigFunction.php index 494d45b08..d910d1fd5 100644 --- a/lib/twig/twig/src/TwigFunction.php +++ b/lib/twig/twig/src/TwigFunction.php @@ -29,7 +29,7 @@ final class TwigFunction private $arguments = []; /** - * @param callable|null $callable A callable implementing the function. If null, you need to overwrite the "node_class" option to customize compilation. + * @param callable|array{class-string, string}|null $callable A callable implementing the function. If null, you need to overwrite the "node_class" option to customize compilation. */ public function __construct(string $name, $callable = null, array $options = []) { @@ -55,7 +55,7 @@ final class TwigFunction /** * Returns the callable to execute for this function. * - * @return callable|null + * @return callable|array{class-string, string}|null */ public function getCallable() { diff --git a/lib/twig/twig/src/TwigTest.php b/lib/twig/twig/src/TwigTest.php index 4c18632f5..3769ec162 100644 --- a/lib/twig/twig/src/TwigTest.php +++ b/lib/twig/twig/src/TwigTest.php @@ -28,7 +28,7 @@ final class TwigTest private $arguments = []; /** - * @param callable|null $callable A callable implementing the test. If null, you need to overwrite the "node_class" option to customize compilation. + * @param callable|array{class-string, string}|null $callable A callable implementing the test. If null, you need to overwrite the "node_class" option to customize compilation. */ public function __construct(string $name, $callable = null, array $options = []) { @@ -51,7 +51,7 @@ final class TwigTest /** * Returns the callable to execute for this test. * - * @return callable|null + * @return callable|array{class-string, string}|null */ public function getCallable() {